2012-05-26 14:26:10 +02:00
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2011 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
/**
\ file
Implementation of class Score ( partial ) .
*/
# include <assert.h>
# include "score.h"
# include "key.h"
# include "sig.h"
# include "clef.h"
# include "tempo.h"
# include "measure.h"
# include "page.h"
# include "undo.h"
# include "system.h"
# include "select.h"
# include "segment.h"
# include "xml.h"
# include "text.h"
# include "note.h"
# include "chord.h"
# include "rest.h"
# include "slur.h"
# include "staff.h"
# include "part.h"
# include "style.h"
# include "tuplet.h"
# include "lyrics.h"
# include "pitchspelling.h"
# include "line.h"
# include "volta.h"
# include "repeat.h"
# include "ottava.h"
# include "barline.h"
# include "box.h"
# include "utils.h"
# include "excerpt.h"
# include "stafftext.h"
# include "repeatlist.h"
# include "keysig.h"
# include "beam.h"
# include "stafftype.h"
# include "tempotext.h"
# include "articulation.h"
# include "revisions.h"
# include "tiemap.h"
# include "layoutbreak.h"
# include "harmony.h"
# include "mscore.h"
2012-07-06 17:42:20 +02:00
# ifdef OMR
2012-05-26 14:26:10 +02:00
# include "omr/omr.h"
2012-07-06 17:42:20 +02:00
# endif
2012-05-26 14:26:10 +02:00
# include "bracket.h"
# include "audio.h"
2012-06-07 09:24:05 +02:00
# include "instrtemplate.h"
2012-06-28 10:03:19 +02:00
# include "cursor.h"
2013-11-11 16:53:03 +01:00
# include "sym.h"
2014-11-15 16:29:48 +01:00
# include "rehearsalmark.h"
2015-01-29 22:37:39 +01:00
# include "breath.h"
2015-03-05 16:46:37 +01:00
# include "instrchange.h"
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2016-03-10 10:41:31 +01:00
MasterScore * gscore ; ///< system score, used for palettes etc.
2012-05-26 14:26:10 +02:00
bool scriptDebug = false ;
bool noSeq = false ;
bool noMidi = false ;
bool midiInputTrace = false ;
bool midiOutputTrace = false ;
bool showRubberBand = true ;
//---------------------------------------------------------
// MeasureBaseList
//---------------------------------------------------------
MeasureBaseList : : MeasureBaseList ( )
{
_first = 0 ;
_last = 0 ;
_size = 0 ;
} ;
//---------------------------------------------------------
// push_back
//---------------------------------------------------------
void MeasureBaseList : : push_back ( MeasureBase * e )
{
+ + _size ;
if ( _last ) {
_last - > setNext ( e ) ;
e - > setPrev ( _last ) ;
e - > setNext ( 0 ) ;
}
else {
_first = e ;
e - > setPrev ( 0 ) ;
e - > setNext ( 0 ) ;
}
_last = e ;
}
//---------------------------------------------------------
// push_front
//---------------------------------------------------------
void MeasureBaseList : : push_front ( MeasureBase * e )
{
+ + _size ;
if ( _first ) {
_first - > setPrev ( e ) ;
e - > setNext ( _first ) ;
e - > setPrev ( 0 ) ;
}
else {
_last = e ;
e - > setPrev ( 0 ) ;
e - > setNext ( 0 ) ;
}
_first = e ;
}
//---------------------------------------------------------
// add
// insert e before e->next()
//---------------------------------------------------------
void MeasureBaseList : : add ( MeasureBase * e )
{
MeasureBase * el = e - > next ( ) ;
if ( el = = 0 ) {
push_back ( e ) ;
return ;
}
if ( el = = _first ) {
push_front ( e ) ;
return ;
}
+ + _size ;
e - > setPrev ( el - > prev ( ) ) ;
el - > prev ( ) - > setNext ( e ) ;
el - > setPrev ( e ) ;
}
//---------------------------------------------------------
2015-06-13 17:57:57 +02:00
// remove
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
void MeasureBaseList : : remove ( MeasureBase * el )
{
- - _size ;
if ( el - > prev ( ) )
el - > prev ( ) - > setNext ( el - > next ( ) ) ;
else
_first = el - > next ( ) ;
if ( el - > next ( ) )
el - > next ( ) - > setPrev ( el - > prev ( ) ) ;
else
_last = el - > prev ( ) ;
}
//---------------------------------------------------------
// insert
//---------------------------------------------------------
void MeasureBaseList : : insert ( MeasureBase * fm , MeasureBase * lm )
{
+ + _size ;
for ( MeasureBase * m = fm ; m ! = lm ; m = m - > next ( ) )
+ + _size ;
MeasureBase * pm = fm - > prev ( ) ;
if ( pm )
pm - > setNext ( fm ) ;
else
_first = fm ;
MeasureBase * nm = lm - > next ( ) ;
if ( nm )
nm - > setPrev ( lm ) ;
else
_last = lm ;
}
//---------------------------------------------------------
// remove
//---------------------------------------------------------
void MeasureBaseList : : remove ( MeasureBase * fm , MeasureBase * lm )
{
- - _size ;
for ( MeasureBase * m = fm ; m ! = lm ; m = m - > next ( ) )
- - _size ;
MeasureBase * pm = fm - > prev ( ) ;
MeasureBase * nm = lm - > next ( ) ;
if ( pm )
pm - > setNext ( nm ) ;
else
_first = nm ;
if ( nm )
nm - > setPrev ( pm ) ;
else
_last = pm ;
}
//---------------------------------------------------------
// change
//---------------------------------------------------------
void MeasureBaseList : : change ( MeasureBase * ob , MeasureBase * nb )
{
nb - > setPrev ( ob - > prev ( ) ) ;
nb - > setNext ( ob - > next ( ) ) ;
if ( ob - > prev ( ) )
ob - > prev ( ) - > setNext ( nb ) ;
if ( ob - > next ( ) )
ob - > next ( ) - > setPrev ( nb ) ;
if ( ob = = _last )
_last = nb ;
if ( ob = = _first )
_first = nb ;
2014-06-24 18:36:02 +02:00
if ( nb - > type ( ) = = Element : : Type : : HBOX | | nb - > type ( ) = = Element : : Type : : VBOX
| | nb - > type ( ) = = Element : : Type : : TBOX | | nb - > type ( ) = = Element : : Type : : FBOX )
2012-05-26 14:26:10 +02:00
nb - > setSystem ( ob - > system ( ) ) ;
2015-02-17 20:22:24 +01:00
foreach ( Element * e , nb - > el ( ) )
2012-05-26 14:26:10 +02:00
e - > setParent ( nb ) ;
}
2016-03-11 12:18:46 +01:00
#if 0
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// init
//---------------------------------------------------------
void Score : : init ( )
{
Layer l ;
l . name = " default " ;
l . tags = 1 ;
_layer . append ( l ) ;
_layerTags [ 0 ] = " default " ;
2013-11-06 15:58:05 +01:00
_scoreFont = ScoreFont : : fontFactory ( " emmentaler " ) ;
2013-10-18 12:21:01 +02:00
_pos [ int ( POS : : CURRENT ) ] = 0 ;
_pos [ int ( POS : : LEFT ) ] = 0 ;
_pos [ int ( POS : : RIGHT ) ] = 0 ;
_fileDivision = MScore : : division ;
2012-05-26 14:26:10 +02:00
}
2016-03-11 12:18:46 +01:00
# endif
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// Score
//---------------------------------------------------------
2012-05-28 19:34:13 +02:00
Score : : Score ( )
2015-10-01 15:03:32 +02:00
: QObject ( 0 ) , ScoreElement ( this ) , _is ( this ) , _selection ( this ) , _selectionFilter ( this )
2012-05-28 19:34:13 +02:00
{
2016-03-10 10:41:31 +01:00
_masterScore = 0 ;
2016-03-11 12:18:46 +01:00
// init();
Layer l ;
l . name = " default " ;
l . tags = 1 ;
_layer . append ( l ) ;
_layerTags [ 0 ] = " default " ;
_scoreFont = ScoreFont : : fontFactory ( " emmentaler " ) ;
_pos [ int ( POS : : CURRENT ) ] = 0 ;
_pos [ int ( POS : : LEFT ) ] = 0 ;
_pos [ int ( POS : : RIGHT ) ] = 0 ;
_fileDivision = MScore : : division ;
2012-05-28 19:34:13 +02:00
_style = * ( MScore : : defaultStyle ( ) ) ;
2014-07-10 14:13:37 +02:00
accInfo = tr ( " No selection " ) ;
2012-05-28 19:34:13 +02:00
}
2016-03-10 10:41:31 +01:00
Score : : Score ( MasterScore * parent )
: Score { }
2012-05-26 14:26:10 +02:00
{
2016-03-10 10:41:31 +01:00
_masterScore = parent ;
2014-02-19 21:33:44 +01:00
if ( MScore : : defaultStyleForParts ( ) )
_style = * MScore : : defaultStyleForParts ( ) ;
2014-02-19 03:26:31 +01:00
else {
2014-02-19 21:33:44 +01:00
// inherit most style settings from parent
_style = * parent - > style ( ) ;
2015-08-30 22:15:39 +02:00
2014-02-19 21:33:44 +01:00
// but borrow defaultStyle page layout settings
2014-02-19 03:26:31 +01:00
const PageFormat * pf = MScore : : defaultStyle ( ) - > pageFormat ( ) ;
_style . setPageFormat ( * pf ) ;
2016-03-02 13:20:19 +01:00
_style . set ( StyleIdx : : spatium , MScore : : defaultStyle ( ) - > value ( StyleIdx : : spatium ) ) ;
2014-04-10 15:10:28 +02:00
2015-08-30 22:15:39 +02:00
// and force some style settings that just make sense for parts
2014-05-26 15:31:36 +02:00
_style . set ( StyleIdx : : concertPitch , false ) ;
2015-08-30 22:15:39 +02:00
_style . set ( StyleIdx : : createMultiMeasureRests , true ) ;
_style . set ( StyleIdx : : dividerLeft , false ) ;
_style . set ( StyleIdx : : dividerRight , false ) ;
2014-02-19 03:26:31 +01:00
}
2013-04-02 20:46:07 +02:00
_synthesizerState = parent - > _synthesizerState ;
2012-05-26 14:26:10 +02:00
}
2016-03-10 10:41:31 +01:00
Score : : Score ( MasterScore * parent , const MStyle * s )
: Score { parent }
2014-04-17 22:41:11 +02:00
{
2016-03-10 10:41:31 +01:00
_style = * s ;
2014-04-17 22:41:11 +02:00
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// ~Score
//---------------------------------------------------------
Score : : ~ Score ( )
{
foreach ( MuseScoreView * v , viewer )
v - > removeScore ( ) ;
2013-10-05 14:03:34 +02:00
// deselectAll();
2012-05-26 14:26:10 +02:00
for ( MeasureBase * m = _measures . first ( ) ; m ; ) {
MeasureBase * nm = m - > next ( ) ;
delete m ;
m = nm ;
}
2016-02-04 11:27:47 +01:00
qDeleteAll ( _parts ) ;
qDeleteAll ( _staves ) ;
qDeleteAll ( _systems ) ;
qDeleteAll ( _pages ) ;
2016-03-30 22:33:04 +02:00
_masterScore = 0 ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// elementAdjustReadPos
//---------------------------------------------------------
static void elementAdjustReadPos ( void * , Element * e )
{
if ( e - > isMovable ( ) )
e - > adjustReadPos ( ) ;
}
//---------------------------------------------------------
// addMeasure
//---------------------------------------------------------
void Score : : addMeasure ( MeasureBase * m , MeasureBase * pos )
{
m - > setNext ( pos ) ;
_measures . add ( m ) ;
}
//---------------------------------------------------------
// fixTicks
// update:
// - measure ticks
// - tempo map
// - time signature map
//---------------------------------------------------------
/**
This is needed after
2013-05-14 16:43:21 +02:00
- inserting or removing a measure
2012-05-26 14:26:10 +02:00
- changing the sigmap
- after inserting / deleting time ( changes the sigmap )
*/
void Score : : fixTicks ( )
{
2013-09-19 15:08:54 +02:00
int tick = 0 ;
2012-05-26 14:26:10 +02:00
Measure * fm = firstMeasure ( ) ;
if ( fm = = 0 )
return ;
2014-05-03 11:33:47 +02:00
for ( Staff * staff : _staves )
staff - > clearTimeSig ( ) ;
2014-11-27 13:04:03 +01:00
2012-05-26 14:26:10 +02:00
Fraction sig ( fm - > len ( ) ) ;
2016-07-09 14:22:06 +02:00
Fraction nomSig ( fm - > timesig ( ) ) ;
2014-11-27 13:04:03 +01:00
2016-03-10 10:41:31 +01:00
if ( isMaster ( ) ) {
2012-05-26 14:26:10 +02:00
tempomap ( ) - > clear ( ) ;
2016-03-10 10:41:31 +01:00
sigmap ( ) - > clear ( ) ;
sigmap ( ) - > add ( 0 , SigEvent ( fm - > len ( ) , fm - > timesig ( ) , 0 ) ) ;
2012-05-26 14:26:10 +02:00
}
for ( MeasureBase * mb = first ( ) ; mb ; mb = mb - > next ( ) ) {
2014-06-24 18:36:02 +02:00
if ( mb - > type ( ) ! = Element : : Type : : MEASURE ) {
2012-05-26 14:26:10 +02:00
mb - > setTick ( tick ) ;
continue ;
}
2016-06-03 10:17:06 +02:00
Measure * m = toMeasure ( mb ) ;
2012-05-26 14:26:10 +02:00
int mtick = m - > tick ( ) ;
int diff = tick - mtick ;
int measureTicks = m - > ticks ( ) ;
m - > moveTicks ( diff ) ;
2013-09-28 12:05:48 +02:00
if ( m - > mmRest ( ) )
m - > mmRest ( ) - > moveTicks ( diff ) ;
2012-05-26 14:26:10 +02:00
2016-01-04 14:48:58 +01:00
//
// implement section break rest
//
if ( m - > sectionBreak ( ) & & m - > pause ( ) ! = 0.0 )
setPause ( m - > tick ( ) + m - > ticks ( ) , m - > pause ( ) ) ;
//
// implement fermata as a tempo change
//
for ( Segment * s = m - > first ( ) ; s ; s = s - > next ( ) ) {
if ( s - > segmentType ( ) = = Segment : : Type : : Breath ) {
qreal length = 0.0 ;
int tick = s - > tick ( ) ;
// find longest pause
for ( int i = 0 , n = ntracks ( ) ; i < n ; + + i ) {
Element * e = s - > element ( i ) ;
if ( e & & e - > type ( ) = = Element : : Type : : BREATH ) {
2016-06-03 10:17:06 +02:00
Breath * b = toBreath ( e ) ;
2016-01-04 14:48:58 +01:00
length = qMax ( length , b - > pause ( ) ) ;
2015-01-29 22:37:39 +01:00
}
}
2016-01-04 14:48:58 +01:00
if ( length ! = 0.0 )
setPause ( tick , length ) ;
}
else if ( s - > segmentType ( ) = = Segment : : Type : : TimeSig ) {
for ( int staffIdx = 0 ; staffIdx < _staves . size ( ) ; + + staffIdx ) {
2016-06-03 10:17:06 +02:00
TimeSig * ts = toTimeSig ( s - > element ( staffIdx * VOICES ) ) ;
2016-01-04 14:48:58 +01:00
if ( ts )
staff ( staffIdx ) - > addTimeSig ( ts ) ;
2012-05-26 14:26:10 +02:00
}
2016-01-04 14:48:58 +01:00
}
2016-06-24 11:58:22 +02:00
// TODO: all done in doLayout, getNextMeasure, collectSystem... Do we keep?
2016-03-10 10:41:31 +01:00
else if ( isMaster ( ) & & ( s - > segmentType ( ) = = Segment : : Type : : ChordRest ) ) {
2016-05-09 14:58:47 +02:00
for ( Element * e : s - > annotations ( ) ) {
2016-01-04 14:48:58 +01:00
if ( e - > type ( ) = = Element : : Type : : TEMPO_TEXT ) {
2016-05-09 14:58:47 +02:00
TempoText * tt = toTempoText ( e ) ;
if ( tt - > isRelative ( ) )
tt - > updateRelative ( ) ;
2016-01-04 14:48:58 +01:00
setTempo ( tt - > segment ( ) , tt - > tempo ( ) ) ;
2012-12-06 12:46:05 +01:00
}
2016-01-04 14:48:58 +01:00
}
qreal stretch = 0.0 ;
2016-02-09 13:51:19 +01:00
for ( unsigned i = 0 ; i < s - > elist ( ) . size ( ) ; + + i ) {
2016-01-04 14:48:58 +01:00
Element * e = s - > elist ( ) . at ( i ) ;
if ( ! e )
continue ;
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( e ) ;
2016-01-04 14:48:58 +01:00
int nn = cr - > articulations ( ) . size ( ) ;
for ( int ii = 0 ; ii < nn ; + + ii )
stretch = qMax ( cr - > articulations ( ) . at ( ii ) - > timeStretch ( ) , stretch ) ;
if ( stretch ! = 0.0 & & stretch ! = 1.0 ) {
qreal otempo = tempomap ( ) - > tempo ( cr - > tick ( ) ) ;
qreal ntempo = otempo / stretch ;
setTempo ( cr - > tick ( ) , ntempo ) ;
int etick = cr - > tick ( ) + cr - > actualTicks ( ) - 1 ;
auto e = tempomap ( ) - > find ( etick ) ;
if ( e = = tempomap ( ) - > end ( ) )
setTempo ( etick , otempo ) ;
break ;
2012-05-26 14:26:10 +02:00
}
}
}
2016-01-04 14:48:58 +01:00
}
2012-05-26 14:26:10 +02:00
// update time signature map
2015-06-13 10:55:15 +02:00
// create event if measure len and time signature are different
// even if they are equivalent 4/4 vs 2/2
2016-07-09 14:22:06 +02:00
// also check if nominal time signature has changed
2016-01-04 14:48:58 +01:00
2016-07-09 14:22:06 +02:00
if ( isMaster ( ) & & ( ! sig . identical ( m - > len ( ) ) | | ! nomSig . identical ( m - > timesig ( ) ) ) ) {
2012-05-26 14:26:10 +02:00
sig = m - > len ( ) ;
2016-07-09 14:22:06 +02:00
nomSig = m - > timesig ( ) ;
sigmap ( ) - > add ( tick , SigEvent ( sig , nomSig , m - > no ( ) ) ) ;
2012-05-26 14:26:10 +02:00
}
2014-11-27 13:04:03 +01:00
2012-05-26 14:26:10 +02:00
tick + = measureTicks ;
}
2016-06-24 11:58:22 +02:00
// Now done in getNextMeasure(), do we keep?
2012-05-26 14:26:10 +02:00
if ( tempomap ( ) - > empty ( ) )
tempomap ( ) - > setTempo ( 0 , 2.0 ) ;
}
2012-11-08 12:59:30 +01:00
//---------------------------------------------------------
// validSegment
//---------------------------------------------------------
static bool validSegment ( Segment * s , int startTrack , int endTrack )
{
for ( int track = startTrack ; track < endTrack ; + + track ) {
if ( s - > element ( track ) )
return true ;
}
return false ;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// pos2measure
//---------------------------------------------------------
/**
Return measure for canvas relative position \ a p .
*/
MeasureBase * Score : : pos2measure ( const QPointF & p , int * rst , int * pitch ,
Segment * * seg , QPointF * offset ) const
{
Measure * m = searchMeasure ( p ) ;
if ( m = = 0 )
return 0 ;
System * s = m - > system ( ) ;
qreal y = p . y ( ) - s - > canvasPos ( ) . y ( ) ;
int i ;
for ( i = 0 ; i < nstaves ( ) ; ) {
2013-08-29 18:42:01 +02:00
SysStaff * stff = s - > staff ( i ) ;
if ( ! stff - > show ( ) | | ! staff ( i ) - > show ( ) ) {
2012-05-26 14:26:10 +02:00
+ + i ;
continue ;
}
int ni = i ;
for ( ; ; ) {
+ + ni ;
2013-08-29 18:42:01 +02:00
if ( ni = = nstaves ( ) | | ( s - > staff ( ni ) - > show ( ) & & staff ( ni ) - > show ( ) ) )
2012-05-26 14:26:10 +02:00
break ;
}
qreal sy2 ;
if ( ni ! = nstaves ( ) ) {
SysStaff * nstaff = s - > staff ( ni ) ;
2013-08-29 18:42:01 +02:00
qreal s1y2 = stff - > bbox ( ) . y ( ) + stff - > bbox ( ) . height ( ) ;
2012-05-26 14:26:10 +02:00
sy2 = s1y2 + ( nstaff - > bbox ( ) . y ( ) - s1y2 ) / 2 ;
}
else
sy2 = s - > page ( ) - > height ( ) - s - > pos ( ) . y ( ) ; // s->height();
if ( y > sy2 ) {
i = ni ;
continue ;
}
break ;
}
// search for segment + offset
QPointF pppp = p - m - > canvasPos ( ) ;
2012-11-08 12:59:30 +01:00
int strack = i * VOICES ;
2015-08-30 13:03:39 +02:00
if ( ! staff ( i ) )
2015-12-11 14:30:54 +01:00
return 0 ;
2012-11-08 12:59:30 +01:00
int etrack = staff ( i ) - > part ( ) - > nstaves ( ) * VOICES + strack ;
2012-05-26 14:26:10 +02:00
SysStaff * sstaff = m - > system ( ) - > staff ( i ) ;
2014-06-25 11:46:10 +02:00
Segment : : Type st = Segment : : Type : : ChordRest ;
2012-11-08 12:59:30 +01:00
for ( Segment * segment = m - > first ( st ) ; segment ; segment = segment - > next ( st ) ) {
if ( ! validSegment ( segment , strack , etrack ) )
2012-05-26 14:26:10 +02:00
continue ;
2012-11-08 12:59:30 +01:00
Segment * ns = segment - > next ( st ) ;
for ( ; ns ; ns = ns - > next ( st ) ) {
if ( validSegment ( ns , strack , etrack ) )
2012-05-26 14:26:10 +02:00
break ;
}
if ( ! ns | | ( pppp . x ( ) < ( segment - > x ( ) + ( ns - > x ( ) - segment - > x ( ) ) / 2.0 ) ) ) {
* rst = i ;
if ( pitch ) {
Staff * s = _staves [ i ] ;
2013-09-05 16:37:49 +02:00
ClefType clef = s - > clef ( segment - > tick ( ) ) ;
2012-05-26 14:26:10 +02:00
* pitch = y2pitch ( pppp . y ( ) - sstaff - > bbox ( ) . y ( ) , clef , s - > spatium ( ) ) ;
}
if ( offset )
* offset = pppp - QPointF ( segment - > x ( ) , sstaff - > bbox ( ) . y ( ) ) ;
if ( seg )
* seg = segment ;
return m ;
}
}
return 0 ;
}
2016-07-19 20:19:23 +02:00
//---------------------------------------------------------
// dragPosition
// on input:
// p - canvas relative drag position
// rst - current staff index
// seg - current segment
// on output:
// rst - new staff index for drag position
// seg - new segment for drag position
//---------------------------------------------------------
void Score : : dragPosition ( const QPointF & p , int * rst , Segment * * seg ) const
{
Measure * m = searchMeasure ( p ) ;
if ( m = = 0 )
return ;
System * s = m - > system ( ) ;
qreal y = p . y ( ) - s - > canvasPos ( ) . y ( ) ;
int i ;
for ( i = 0 ; i < nstaves ( ) ; ) {
SysStaff * stff = s - > staff ( i ) ;
if ( ! stff - > show ( ) | | ! staff ( i ) - > show ( ) ) {
+ + i ;
continue ;
}
int ni = i ;
for ( ; ; ) {
+ + ni ;
if ( ni = = nstaves ( ) | | ( s - > staff ( ni ) - > show ( ) & & staff ( ni ) - > show ( ) ) )
break ;
}
qreal sy2 ;
if ( ni ! = nstaves ( ) ) {
SysStaff * nstaff = s - > staff ( ni ) ;
qreal s1y2 = stff - > bbox ( ) . y ( ) + stff - > bbox ( ) . height ( ) ;
if ( i = = * rst )
sy2 = s1y2 + ( nstaff - > bbox ( ) . y ( ) - s1y2 ) ;
else if ( ni = = * rst )
sy2 = s1y2 ;
else
sy2 = s1y2 + ( nstaff - > bbox ( ) . y ( ) - s1y2 ) * .5 ;
}
else
sy2 = s - > page ( ) - > height ( ) - s - > pos ( ) . y ( ) ;
if ( y > sy2 ) {
i = ni ;
continue ;
}
break ;
}
// search for segment + offset
QPointF pppp = p - m - > canvasPos ( ) ;
int strack = i * VOICES ;
if ( ! staff ( i ) )
return ;
int etrack = staff ( i ) - > part ( ) - > nstaves ( ) * VOICES + strack ;
Segment : : Type st = Segment : : Type : : ChordRest ;
for ( Segment * segment = m - > first ( st ) ; segment ; segment = segment - > next ( st ) ) {
if ( ! validSegment ( segment , strack , etrack ) )
continue ;
Segment * ns = segment - > next ( st ) ;
for ( ; ns ; ns = ns - > next ( st ) ) {
if ( validSegment ( ns , strack , etrack ) )
break ;
}
if ( ! ns ) {
* rst = i ;
* seg = segment ;
return ;
}
if ( * seg = = segment ) {
if ( pppp . x ( ) < ( segment - > x ( ) + ( ns - > x ( ) - segment - > x ( ) ) ) ) {
* rst = i ;
* seg = segment ;
return ;
}
}
else if ( * seg = = ns ) {
if ( pppp . x ( ) < = segment - > x ( ) ) {
* rst = i ;
* seg = segment ;
return ;
}
}
else {
if ( pppp . x ( ) < ( segment - > x ( ) + ( ns - > x ( ) - segment - > x ( ) ) / 2.0 ) ) {
* rst = i ;
* seg = segment ;
return ;
}
}
}
return ;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// staffIdx
//
/// Return index for the first staff of \a part.
//---------------------------------------------------------
int Score : : staffIdx ( const Part * part ) const
{
int idx = 0 ;
foreach ( Part * p , _parts ) {
if ( p = = part )
break ;
idx + = p - > nstaves ( ) ;
}
return idx ;
}
//---------------------------------------------------------
// setShowInvisible
//---------------------------------------------------------
void Score : : setShowInvisible ( bool v )
{
_showInvisible = v ;
2014-05-07 12:10:28 +02:00
rebuildBspTree ( ) ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2016-03-18 09:29:16 +01:00
update ( ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// setShowUnprintable
//---------------------------------------------------------
void Score : : setShowUnprintable ( bool v )
{
_showUnprintable = v ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2016-03-18 09:29:16 +01:00
update ( ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// setShowFrames
//---------------------------------------------------------
void Score : : setShowFrames ( bool v )
{
_showFrames = v ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2016-03-18 09:29:16 +01:00
update ( ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// setShowPageborders
//---------------------------------------------------------
void Score : : setShowPageborders ( bool v )
{
_showPageborders = v ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2016-03-18 09:29:16 +01:00
update ( ) ;
2012-05-26 14:26:10 +02:00
}
2016-08-06 11:36:51 +02:00
//---------------------------------------------------------
// setMarkIrregularMeasures
//---------------------------------------------------------
void Score : : setMarkIrregularMeasures ( bool v )
{
_markIrregularMeasures = v ;
setUpdateAll ( ) ;
update ( ) ;
}
2014-02-25 14:14:59 +01:00
//---------------------------------------------------------
// dirty
//---------------------------------------------------------
bool Score : : dirty ( ) const
{
2016-03-10 10:41:31 +01:00
return ! undoStack ( ) - > isClean ( ) ;
2014-02-25 14:14:59 +01:00
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// spell
//---------------------------------------------------------
void Score : : spell ( )
{
for ( int i = 0 ; i < nstaves ( ) ; + + i ) {
2016-02-06 22:03:43 +01:00
std : : vector < Note * > notes ;
2012-05-26 14:26:10 +02:00
for ( Segment * s = firstSegment ( ) ; s ; s = s - > next1 ( ) ) {
int strack = i * VOICES ;
int etrack = strack + VOICES ;
for ( int track = strack ; track < etrack ; + + track ) {
Element * e = s - > element ( track ) ;
2014-06-24 18:36:02 +02:00
if ( e & & e - > type ( ) = = Element : : Type : : CHORD )
2016-02-06 22:03:43 +01:00
notes . insert ( notes . end ( ) ,
2016-06-03 10:17:06 +02:00
toChord ( e ) - > notes ( ) . begin ( ) ,
toChord ( e ) - > notes ( ) . end ( ) ) ;
2012-05-26 14:26:10 +02:00
}
}
spellNotelist ( notes ) ;
}
}
void Score : : spell ( int startStaff , int endStaff , Segment * startSegment , Segment * endSegment )
{
for ( int i = startStaff ; i < endStaff ; + + i ) {
2016-02-06 22:03:43 +01:00
std : : vector < Note * > notes ;
2012-05-26 14:26:10 +02:00
for ( Segment * s = startSegment ; s & & s ! = endSegment ; s = s - > next ( ) ) {
int strack = i * VOICES ;
int etrack = strack + VOICES ;
for ( int track = strack ; track < etrack ; + + track ) {
Element * e = s - > element ( track ) ;
2014-06-24 18:36:02 +02:00
if ( e & & e - > type ( ) = = Element : : Type : : CHORD )
2016-02-06 22:03:43 +01:00
notes . insert ( notes . end ( ) ,
2016-06-03 10:17:06 +02:00
toChord ( e ) - > notes ( ) . begin ( ) ,
toChord ( e ) - > notes ( ) . end ( ) ) ;
2012-05-26 14:26:10 +02:00
}
}
spellNotelist ( notes ) ;
}
}
//---------------------------------------------------------
// prevNote
//---------------------------------------------------------
Note * prevNote ( Note * n )
{
Chord * chord = n - > chord ( ) ;
Segment * seg = chord - > segment ( ) ;
2016-02-06 22:03:43 +01:00
const std : : vector < Note * > nl = chord - > notes ( ) ;
auto i = std : : find ( nl . begin ( ) , nl . end ( ) , n ) ;
2016-02-09 13:51:19 +01:00
if ( i ! = nl . begin ( ) )
2016-02-06 22:03:43 +01:00
return * ( i - 1 ) ;
2012-05-26 14:26:10 +02:00
int staff = n - > staffIdx ( ) ;
int startTrack = staff * VOICES + n - > voice ( ) - 1 ;
int endTrack = 0 ;
while ( seg ) {
2014-06-25 11:46:10 +02:00
if ( seg - > segmentType ( ) = = Segment : : Type : : ChordRest ) {
2012-05-26 14:26:10 +02:00
for ( int track = startTrack ; track > = endTrack ; - - track ) {
Element * e = seg - > element ( track ) ;
2014-06-24 18:36:02 +02:00
if ( e & & e - > type ( ) = = Element : : Type : : CHORD )
2016-06-03 10:17:06 +02:00
return toChord ( e ) - > upNote ( ) ;
2012-05-26 14:26:10 +02:00
}
}
seg = seg - > prev1 ( ) ;
startTrack = staff * VOICES + VOICES - 1 ;
}
return n ;
}
//---------------------------------------------------------
// nextNote
//---------------------------------------------------------
2016-02-09 09:20:54 +01:00
static Note * nextNote ( Note * n )
2012-05-26 14:26:10 +02:00
{
Chord * chord = n - > chord ( ) ;
2016-02-06 22:03:43 +01:00
const std : : vector < Note * > nl = chord - > notes ( ) ;
auto i = std : : find ( nl . begin ( ) , nl . end ( ) , n ) ;
if ( i ! = nl . end ( ) ) {
+ + i ;
if ( i ! = nl . end ( ) )
return * i ;
}
2012-05-26 14:26:10 +02:00
Segment * seg = chord - > segment ( ) ;
int staff = n - > staffIdx ( ) ;
int startTrack = staff * VOICES + n - > voice ( ) + 1 ;
int endTrack = staff * VOICES + VOICES ;
while ( seg ) {
2014-06-25 11:46:10 +02:00
if ( seg - > segmentType ( ) = = Segment : : Type : : ChordRest ) {
2012-05-26 14:26:10 +02:00
for ( int track = startTrack ; track < endTrack ; + + track ) {
Element * e = seg - > element ( track ) ;
2014-06-24 18:36:02 +02:00
if ( e & & e - > type ( ) = = Element : : Type : : CHORD ) {
2012-05-26 14:26:10 +02:00
return ( ( Chord * ) e ) - > downNote ( ) ;
}
}
}
seg = seg - > next1 ( ) ;
startTrack = staff * VOICES ;
}
return n ;
}
//---------------------------------------------------------
// spell
//---------------------------------------------------------
void Score : : spell ( Note * note )
{
2016-02-06 22:03:43 +01:00
std : : vector < Note * > notes ;
2012-05-26 14:26:10 +02:00
2016-02-06 22:03:43 +01:00
notes . push_back ( note ) ;
2012-05-26 14:26:10 +02:00
Note * nn = nextNote ( note ) ;
2016-02-06 22:03:43 +01:00
notes . push_back ( nn ) ;
2012-05-26 14:26:10 +02:00
nn = nextNote ( nn ) ;
2016-02-06 22:03:43 +01:00
notes . push_back ( nn ) ;
2012-05-26 14:26:10 +02:00
nn = nextNote ( nn ) ;
2016-02-06 22:03:43 +01:00
notes . push_back ( nn ) ;
2012-05-26 14:26:10 +02:00
nn = prevNote ( note ) ;
2016-02-06 22:03:43 +01:00
notes . insert ( notes . begin ( ) , nn ) ;
2012-05-26 14:26:10 +02:00
nn = prevNote ( nn ) ;
2016-02-06 22:03:43 +01:00
notes . insert ( notes . begin ( ) , nn ) ;
2012-05-26 14:26:10 +02:00
nn = prevNote ( nn ) ;
2016-02-06 22:03:43 +01:00
notes . insert ( notes . begin ( ) , nn ) ;
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
int opt = Ms : : computeWindow ( notes , 0 , 7 ) ;
note - > setTpc ( Ms : : tpc ( 3 , note - > pitch ( ) , opt ) ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// appendPart
//---------------------------------------------------------
void Score : : appendPart ( Part * p )
{
_parts . append ( p ) ;
}
//---------------------------------------------------------
// searchPage
// p is in canvas coordinates
//---------------------------------------------------------
Page * Score : : searchPage ( const QPointF & p ) const
{
2015-12-11 14:30:54 +01:00
for ( Page * page : pages ( ) ) {
2012-05-26 14:26:10 +02:00
if ( page - > bbox ( ) . translated ( page - > pos ( ) ) . contains ( p ) )
return page ;
}
return 0 ;
}
//---------------------------------------------------------
// searchSystem
// return list of systems as there may be more than
// one system in a row
// p is in canvas coordinates
//---------------------------------------------------------
QList < System * > Score : : searchSystem ( const QPointF & pos ) const
{
QList < System * > systems ;
Page * page = searchPage ( pos ) ;
if ( page = = 0 )
return systems ;
qreal y = pos . y ( ) - page - > pos ( ) . y ( ) ; // transform to page relative
2016-01-04 14:48:58 +01:00
const QList < System * > * sl = & page - > systems ( ) ;
2012-05-26 14:26:10 +02:00
qreal y2 ;
int n = sl - > size ( ) ;
for ( int i = 0 ; i < n ; + + i ) {
System * s = sl - > at ( i ) ;
System * ns = 0 ; // next system row
int ii = i + 1 ;
for ( ; ii < n ; + + ii ) {
ns = sl - > at ( ii ) ;
if ( ns - > y ( ) ! = s - > y ( ) )
break ;
}
if ( ( ii = = n ) | | ( ns = = 0 ) )
y2 = page - > height ( ) ;
2015-07-04 11:24:23 +02:00
else {
2012-05-26 14:26:10 +02:00
qreal sy2 = s - > y ( ) + s - > bbox ( ) . height ( ) ;
y2 = sy2 + ( ns - > y ( ) - sy2 ) * .5 ;
}
if ( y < y2 ) {
systems . append ( s ) ;
for ( int ii = i + 1 ; ii < n ; + + ii ) {
if ( sl - > at ( ii ) - > y ( ) ! = s - > y ( ) )
break ;
systems . append ( sl - > at ( ii ) ) ;
}
return systems ;
}
}
return systems ;
}
//---------------------------------------------------------
// searchMeasure
// p is in canvas coordinates
//---------------------------------------------------------
Measure * Score : : searchMeasure ( const QPointF & p ) const
{
QList < System * > systems = searchSystem ( p ) ;
2016-02-06 22:03:43 +01:00
if ( systems . empty ( ) )
2012-05-26 14:26:10 +02:00
return 0 ;
foreach ( System * system , systems ) {
qreal x = p . x ( ) - system - > canvasPos ( ) . x ( ) ;
foreach ( MeasureBase * mb , system - > measures ( ) ) {
2014-06-24 18:36:02 +02:00
if ( mb - > type ( ) ! = Element : : Type : : MEASURE )
2012-05-26 14:26:10 +02:00
continue ;
if ( x < ( mb - > x ( ) + mb - > bbox ( ) . width ( ) ) )
2016-06-03 10:17:06 +02:00
return toMeasure ( mb ) ;
2012-05-26 14:26:10 +02:00
}
}
return 0 ;
}
//---------------------------------------------------------
// getNextValidInputSegment
2014-06-25 11:46:10 +02:00
// - s is of type Segment::Type::ChordRest
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
static Segment * getNextValidInputSegment ( Segment * s , int track , int voice )
{
if ( s = = 0 )
return 0 ;
2014-06-25 11:46:10 +02:00
Q_ASSERT ( s - > segmentType ( ) = = Segment : : Type : : ChordRest ) ;
2012-05-26 14:26:10 +02:00
// Segment* s1 = s;
ChordRest * cr1 ;
2014-06-25 11:46:10 +02:00
for ( Segment * s1 = s ; s1 ; s1 = s1 - > prev ( Segment : : Type : : ChordRest ) ) {
2016-06-03 10:17:06 +02:00
cr1 = toChordRest ( s1 - > element ( track + voice ) ) ;
2012-05-26 14:26:10 +02:00
if ( cr1 )
break ;
}
int nextTick = ( cr1 = = 0 ) ? s - > measure ( ) - > tick ( ) : cr1 - > tick ( ) + cr1 - > actualTicks ( ) ;
2014-06-25 11:46:10 +02:00
static const Segment : : Type st { Segment : : Type : : ChordRest } ;
2012-05-26 14:26:10 +02:00
while ( s ) {
if ( s - > element ( track + voice ) )
break ;
if ( voice & & s - > tick ( ) = = nextTick )
return s ;
#if 0
int v ;
for ( v = 0 ; v < VOICES ; + + v ) {
if ( s - > element ( track + v ) )
break ;
}
if ( ( v ! = VOICES ) & & voice ) {
int ntick ;
bool skipChord = false ;
bool ns = false ;
for ( Segment * s1 = s - > measure ( ) - > first ( st ) ; s1 ; s1 = s1 - > next ( st ) ) {
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( s1 - > element ( track + voice ) ) ;
2012-05-26 14:26:10 +02:00
if ( cr ) {
if ( ns )
return s1 ;
ntick = s1 - > tick ( ) + cr - > actualTicks ( ) ;
skipChord = true ;
}
if ( s1 = = s )
ns = true ;
if ( skipChord ) {
if ( s - > tick ( ) > = ntick )
skipChord = false ;
}
if ( ! skipChord & & ns )
return s1 ;
}
if ( ! skipChord )
return s ;
}
# endif
s = s - > next ( st ) ;
}
return s ;
}
//---------------------------------------------------------
// getPosition
// return true if valid position found
//---------------------------------------------------------
bool Score : : getPosition ( Position * pos , const QPointF & p , int voice ) const
{
2012-08-07 12:44:19 +02:00
Measure * measure = searchMeasure ( p ) ;
if ( measure = = 0 )
2012-05-26 14:26:10 +02:00
return false ;
2012-08-29 18:42:28 +02:00
pos - > fret = FRET_NONE ;
2012-05-26 14:26:10 +02:00
//
// search staff
//
pos - > staffIdx = 0 ;
SysStaff * sstaff = 0 ;
2012-08-07 12:44:19 +02:00
System * system = measure - > system ( ) ;
2012-05-26 14:26:10 +02:00
qreal y = p . y ( ) - system - > pagePos ( ) . y ( ) ;
for ( ; pos - > staffIdx < nstaves ( ) ; + + pos - > staffIdx ) {
2014-07-31 14:12:34 +02:00
Staff * st = staff ( pos - > staffIdx ) ;
if ( st - > invisible ( ) | | ! st - > part ( ) - > show ( ) )
continue ;
2012-05-26 14:26:10 +02:00
qreal sy2 ;
SysStaff * ss = system - > staff ( pos - > staffIdx ) ;
2014-07-31 14:12:34 +02:00
SysStaff * nstaff = 0 ;
// find next visible staff
for ( int i = pos - > staffIdx + 1 ; i < nstaves ( ) ; + + i ) {
Staff * st = staff ( i ) ;
if ( st - > invisible ( ) | | ! st - > part ( ) - > show ( ) )
continue ;
nstaff = system - > staff ( i ) ;
break ;
}
if ( nstaff ) {
2016-02-16 07:44:03 +01:00
qreal s1y2 = ss - > bbox ( ) . bottom ( ) ;
sy2 = system - > page ( ) - > canvasPos ( ) . y ( ) + s1y2 + ( nstaff - > bbox ( ) . y ( ) - s1y2 ) * .5 ;
2012-05-26 14:26:10 +02:00
}
else
2016-02-16 07:44:03 +01:00
sy2 = system - > page ( ) - > canvasPos ( ) . y ( ) + system - > page ( ) - > height ( ) - system - > pagePos ( ) . y ( ) ; // system->height();
2012-05-26 14:26:10 +02:00
if ( y < sy2 ) {
sstaff = ss ;
break ;
}
}
if ( sstaff = = 0 )
return false ;
//
// search segment
//
2012-08-07 12:44:19 +02:00
QPointF pppp ( p - measure - > canvasPos ( ) ) ;
2012-05-26 14:26:10 +02:00
qreal x = pppp . x ( ) ;
Segment * segment = 0 ;
pos - > segment = 0 ;
// int track = pos->staffIdx * VOICES + voice;
int track = pos - > staffIdx * VOICES ;
2014-06-25 11:46:10 +02:00
for ( segment = measure - > first ( Segment : : Type : : ChordRest ) ; segment ; ) {
2012-05-26 14:26:10 +02:00
segment = getNextValidInputSegment ( segment , track , voice ) ;
if ( segment = = 0 )
break ;
2014-06-25 11:46:10 +02:00
Segment * ns = getNextValidInputSegment ( segment - > next ( Segment : : Type : : ChordRest ) , track , voice ) ;
2012-05-26 14:26:10 +02:00
qreal x1 = segment - > x ( ) ;
qreal x2 ;
qreal d ;
if ( ns ) {
x2 = ns - > x ( ) ;
d = x2 - x1 ;
}
else {
2012-08-07 12:44:19 +02:00
x2 = measure - > bbox ( ) . width ( ) ;
2012-05-26 14:26:10 +02:00
d = ( x2 - x1 ) * 2.0 ;
x = x1 ;
pos - > segment = segment ;
break ;
}
if ( x < ( x1 + d * .5 ) ) {
x = x1 ;
pos - > segment = segment ;
break ;
}
segment = ns ;
}
if ( segment = = 0 )
return false ;
//
// TODO: restrict to reasonable values (pitch 0-127)
//
Staff * s = staff ( pos - > staffIdx ) ;
2012-09-07 16:43:29 +02:00
qreal mag = s - > mag ( ) ;
// in TABs, step from one string to another; in other staves, step on and between lines
qreal lineDist = s - > staffType ( ) - > lineDistance ( ) . val ( ) * ( s - > isTabStaff ( ) ? 1 : .5 ) * mag * spatium ( ) ;
2012-05-26 14:26:10 +02:00
pos - > line = lrint ( ( pppp . y ( ) - sstaff - > bbox ( ) . y ( ) ) / lineDist ) ;
2012-08-16 11:09:36 +02:00
if ( s - > isTabStaff ( ) ) {
2012-05-26 14:26:10 +02:00
if ( pos - > line < - 1 | | pos - > line > s - > lines ( ) + 1 )
return false ;
if ( pos - > line < 0 )
pos - > line = 0 ;
else if ( pos - > line > = s - > lines ( ) )
pos - > line = s - > lines ( ) - 1 ;
}
else {
2012-08-07 16:05:37 +02:00
int minLine = absStep ( 0 ) ;
2012-08-07 12:44:19 +02:00
ClefType clef = s - > clef ( pos - > segment - > tick ( ) ) ;
2012-08-07 16:05:37 +02:00
minLine = relStep ( minLine , clef ) ;
int maxLine = absStep ( 127 ) ;
maxLine = relStep ( maxLine , clef ) ;
2012-05-26 14:26:10 +02:00
if ( pos - > line > minLine | | pos - > line < maxLine )
return false ;
}
y = sstaff - > y ( ) + pos - > line * lineDist ;
2012-08-07 12:44:19 +02:00
pos - > pos = QPointF ( x , y ) + measure - > canvasPos ( ) ;
2012-05-26 14:26:10 +02:00
return true ;
}
//---------------------------------------------------------
// checkHasMeasures
//---------------------------------------------------------
bool Score : : checkHasMeasures ( ) const
{
Page * page = pages ( ) . front ( ) ;
2016-01-04 14:48:58 +01:00
const QList < System * > * sl = & page - > systems ( ) ;
2012-05-26 14:26:10 +02:00
if ( sl = = 0 | | sl - > empty ( ) | | sl - > front ( ) - > measures ( ) . empty ( ) ) {
2013-07-25 17:22:49 +02:00
qDebug ( " first create measure, then repeat operation " ) ;
2012-05-26 14:26:10 +02:00
return false ;
}
return true ;
}
//---------------------------------------------------------
// moveBracket
// columns are counted from right to left
//---------------------------------------------------------
void Score : : moveBracket ( int staffIdx , int srcCol , int dstCol )
{
2016-02-04 11:27:47 +01:00
for ( System * system : systems ( ) )
system - > moveBracket ( staffIdx , srcCol , dstCol ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// spatiumHasChanged
//---------------------------------------------------------
static void spatiumHasChanged ( void * data , Element * e )
{
qreal * val = ( qreal * ) data ;
e - > spatiumChanged ( val [ 0 ] , val [ 1 ] ) ;
}
//---------------------------------------------------------
// spatiumChanged
//---------------------------------------------------------
void Score : : spatiumChanged ( qreal oldValue , qreal newValue )
{
qreal data [ 2 ] ;
data [ 0 ] = oldValue ;
data [ 1 ] = newValue ;
scanElements ( data , spatiumHasChanged , true ) ;
foreach ( Staff * staff , _staves )
staff - > spatiumChanged ( oldValue , newValue ) ;
2015-11-16 14:24:47 +01:00
_noteHeadWidth = _scoreFont - > width ( SymId : : noteheadBlack , newValue / SPATIUM20 ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// getCreateMeasure
// - return Measure for tick
// - create new Measure(s) if there is no measure for
// this tick
//---------------------------------------------------------
Measure * Score : : getCreateMeasure ( int tick )
{
Measure * last = lastMeasure ( ) ;
if ( last = = 0 | | ( ( last - > tick ( ) + last - > ticks ( ) ) < = tick ) ) {
int lastTick = last ? ( last - > tick ( ) + last - > ticks ( ) ) : 0 ;
while ( tick > = lastTick ) {
Measure * m = new Measure ( this ) ;
2016-03-10 10:41:31 +01:00
Fraction ts = sigmap ( ) - > timesig ( lastTick ) . timesig ( ) ;
2013-07-25 17:22:49 +02:00
// qDebug("getCreateMeasure %d %d/%d", tick, ts.numerator(), ts.denominator());
2012-05-26 14:26:10 +02:00
m - > setTick ( lastTick ) ;
m - > setTimesig ( ts ) ;
m - > setLen ( ts ) ;
2014-07-03 15:02:36 +02:00
measures ( ) - > add ( static_cast < MeasureBase * > ( m ) ) ;
2012-05-26 14:26:10 +02:00
lastTick + = ts . ticks ( ) ;
}
}
return tick2measure ( tick ) ;
}
//---------------------------------------------------------
// addElement
//---------------------------------------------------------
/**
Add \ a element to its parent .
Several elements ( clef , keysig , timesig ) need special handling , as they may cause
changes throughout the score .
*/
void Score : : addElement ( Element * element )
{
2016-02-04 11:27:47 +01:00
Element * parent = element - > parent ( ) ;
2016-06-14 10:32:34 +02:00
element - > triggerLayout ( ) ;
2016-02-04 11:27:47 +01:00
2016-03-24 12:39:18 +01:00
// qDebug("Score(%p) Element(%p)(%s) parent %p(%s)",
2016-03-02 13:20:19 +01:00
// this, element, element->name(), parent, parent ? parent->name() : "");
2016-02-04 11:27:47 +01:00
2014-06-24 18:36:02 +02:00
Element : : Type et = element - > type ( ) ;
2016-06-14 10:32:34 +02:00
if ( et = = Element : : Type : : MEASURE
2014-06-24 18:36:02 +02:00
| | ( et = = Element : : Type : : HBOX & & element - > parent ( ) - > type ( ) ! = Element : : Type : : VBOX )
| | et = = Element : : Type : : VBOX
| | et = = Element : : Type : : TBOX
| | et = = Element : : Type : : FBOX
2012-05-26 14:26:10 +02:00
) {
2014-07-03 15:02:36 +02:00
measures ( ) - > add ( static_cast < MeasureBase * > ( element ) ) ;
2012-05-26 14:26:10 +02:00
return ;
}
2016-02-04 11:27:47 +01:00
if ( parent )
parent - > add ( element ) ;
2012-05-26 14:26:10 +02:00
2016-04-18 11:22:03 +02:00
switch ( et ) {
2014-07-03 15:02:36 +02:00
case Element : : Type : : BEAM :
{
2016-06-03 10:17:06 +02:00
Beam * b = toBeam ( element ) ;
2014-07-03 15:02:36 +02:00
int n = b - > elements ( ) . size ( ) ;
for ( int i = 0 ; i < n ; + + i )
b - > elements ( ) . at ( i ) - > setBeam ( b ) ;
}
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : SLUR :
2014-05-30 10:16:38 +02:00
addLayoutFlags ( LayoutFlag : : PLAY_EVENTS ) ;
2013-06-20 18:48:28 +02:00
// fall through
2014-06-24 18:36:02 +02:00
case Element : : Type : : VOLTA :
case Element : : Type : : TRILL :
case Element : : Type : : PEDAL :
case Element : : Type : : TEXTLINE :
case Element : : Type : : HAIRPIN :
2012-05-26 14:26:10 +02:00
{
Spanner * spanner = static_cast < Spanner * > ( element ) ;
2014-06-24 18:36:02 +02:00
if ( et = = Element : : Type : : TEXTLINE & & spanner - > anchor ( ) = = Spanner : : Anchor : : NOTE )
2013-07-04 13:40:25 +02:00
break ;
2014-07-09 18:05:58 +02:00
addSpanner ( spanner ) ;
for ( SpannerSegment * ss : spanner - > spannerSegments ( ) ) {
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 : : OTTAVA :
2012-05-26 14:26:10 +02:00
{
2016-06-03 10:17:06 +02:00
Ottava * o = toOttava ( element ) ;
2014-07-03 15:02:36 +02:00
addSpanner ( o ) ;
2012-05-26 14:26:10 +02:00
foreach ( SpannerSegment * ss , o - > spannerSegments ( ) ) {
if ( ss - > system ( ) )
ss - > system ( ) - > add ( ss ) ;
}
2016-03-18 09:29:16 +01:00
cmdState ( ) . layoutFlags | = LayoutFlag : : FIX_PITCH_VELO ;
2014-07-15 12:49:51 +02:00
o - > staff ( ) - > updateOttava ( ) ;
2012-05-26 14:26:10 +02:00
_playlistDirty = true ;
}
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : DYNAMIC :
2016-03-18 09:29:16 +01:00
cmdState ( ) . layoutFlags | = LayoutFlag : : FIX_PITCH_VELO ;
2012-05-26 14:26:10 +02:00
_playlistDirty = true ;
break ;
2013-07-05 11:23:52 +02:00
2014-06-24 18:36:02 +02:00
case Element : : Type : : TEMPO_TEXT :
2012-05-26 14:26:10 +02:00
{
2016-05-18 12:24:22 +02:00
TempoText * tt = toTempoText ( element ) ;
if ( tt - > isRelative ( ) )
tt - > updateRelative ( ) ;
2012-05-26 14:26:10 +02:00
setTempo ( tt - > segment ( ) , tt - > tempo ( ) ) ;
}
break ;
2013-07-05 11:23:52 +02:00
2015-03-05 16:46:37 +01:00
case Element : : Type : : INSTRUMENT_CHANGE : {
2016-06-03 10:17:06 +02:00
InstrumentChange * ic = toInstrumentChange ( element ) ;
2015-09-21 02:13:22 +02:00
int tickStart = ic - > segment ( ) - > tick ( ) ;
auto i = ic - > part ( ) - > instruments ( ) - > upper_bound ( tickStart ) ;
int tickEnd ;
if ( i = = ic - > part ( ) - > instruments ( ) - > end ( ) )
tickEnd = - 1 ;
else
tickEnd = i - > first ;
Interval oldV = ic - > part ( ) - > instrument ( tickStart ) - > transpose ( ) ;
ic - > part ( ) - > setInstrument ( ic - > instrument ( ) , tickStart ) ;
transpositionChanged ( ic - > part ( ) , oldV , tickStart , tickEnd ) ;
2016-03-11 12:18:46 +01:00
masterScore ( ) - > rebuildMidiMapping ( ) ;
2016-03-18 09:29:16 +01:00
cmdState ( ) . _instrumentsChanged = true ;
2015-03-05 16:46:37 +01:00
}
2012-05-26 14:26:10 +02:00
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : CHORD :
2015-01-30 17:03:51 +01:00
setPlaylistDirty ( ) ;
2015-01-29 10:19:25 +01:00
// create playlist does not work here bc. tremolos may not be complete
2016-06-03 10:17:06 +02:00
// createPlayEvents(toChord(element));
2012-11-21 15:57:35 +01:00
break ;
2015-02-17 20:22:24 +01:00
case Element : : Type : : NOTE :
2014-06-24 18:36:02 +02:00
case Element : : Type : : TREMOLO :
case Element : : Type : : ARTICULATION :
case Element : : Type : : ARPEGGIO :
2013-01-03 16:56:56 +01:00
{
2016-02-04 11:27:47 +01:00
Element * cr = parent ;
2016-04-18 11:22:03 +02:00
if ( cr - > isChord ( ) )
createPlayEvents ( toChord ( cr ) ) ;
2012-12-08 17:24:20 +01:00
}
2016-06-03 10:17:06 +02:00
break ;
2016-04-18 11:22:03 +02:00
2012-05-26 14:26:10 +02:00
default :
break ;
}
2016-06-03 10:17:06 +02:00
setLayout ( element - > tick ( ) ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// removeElement
/// Remove \a element from its parent.
/// Several elements (clef, keysig, timesig) need special handling, as they may cause
/// changes throughout the score.
//---------------------------------------------------------
void Score : : removeElement ( Element * element )
{
Element * parent = element - > parent ( ) ;
2016-06-14 10:32:34 +02:00
setLayout ( element - > tick ( ) ) ;
2012-05-26 14:26:10 +02:00
2016-03-24 12:39:18 +01:00
// qDebug("Score(%p) Element(%p)(%s) parent %p(%s)",
2016-03-02 13:20:19 +01:00
// this, element, element->name(), parent, parent ? parent->name() : "");
2014-05-21 20:08:37 +02:00
2012-05-26 14:26:10 +02:00
// special for MEASURE, HBOX, VBOX
// their parent is not static
2014-06-24 18:36:02 +02:00
Element : : Type et = element - > type ( ) ;
2013-06-05 15:47:34 +02:00
2016-06-14 10:32:34 +02:00
if ( et = = Element : : Type : : MEASURE
2016-02-09 13:51:19 +01:00
| | ( et = = Element : : Type : : HBOX & & ! parent - > isVBox ( ) )
2014-06-24 18:36:02 +02:00
| | et = = Element : : Type : : VBOX
| | et = = Element : : Type : : TBOX
| | et = = Element : : Type : : FBOX
2012-05-26 14:26:10 +02:00
) {
2014-07-03 15:02:36 +02:00
measures ( ) - > remove ( static_cast < MeasureBase * > ( element ) ) ;
2012-05-26 14:26:10 +02:00
return ;
}
2014-06-24 18:36:02 +02:00
if ( et = = Element : : Type : : BEAM ) // beam parent does not survive layout
2012-05-26 14:26:10 +02:00
element - > setParent ( 0 ) ;
if ( parent )
parent - > remove ( element ) ;
2016-02-09 13:51:19 +01:00
switch ( et ) {
2014-07-03 15:02:36 +02:00
case Element : : Type : : BEAM :
2016-06-03 10:17:06 +02:00
for ( ChordRest * cr : toBeam ( element ) - > elements ( ) )
2014-07-03 15:02:36 +02:00
cr - > setBeam ( 0 ) ;
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : SLUR :
2014-05-30 10:16:38 +02:00
addLayoutFlags ( LayoutFlag : : PLAY_EVENTS ) ;
2013-06-20 18:48:28 +02:00
// fall through
2012-05-26 14:26:10 +02:00
2014-06-24 18:36:02 +02:00
case Element : : Type : : VOLTA :
case Element : : Type : : TRILL :
case Element : : Type : : PEDAL :
case Element : : Type : : TEXTLINE :
case Element : : Type : : HAIRPIN :
2012-05-26 14:26:10 +02:00
{
Spanner * spanner = static_cast < Spanner * > ( element ) ;
2014-07-09 18:05:58 +02:00
if ( et = = Element : : Type : : TEXTLINE & & spanner - > anchor ( ) = = Spanner : : Anchor : : NOTE )
break ;
2014-07-03 15:02:36 +02:00
removeSpanner ( spanner ) ;
for ( SpannerSegment * ss : spanner - > spannerSegments ( ) ) {
2012-05-26 14:26:10 +02:00
if ( ss - > system ( ) )
ss - > system ( ) - > remove ( ss ) ;
}
}
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : OTTAVA :
2012-05-26 14:26:10 +02:00
{
2016-06-03 10:17:06 +02:00
Ottava * o = toOttava ( element ) ;
2014-07-03 15:02:36 +02:00
removeSpanner ( o ) ;
2012-05-26 14:26:10 +02:00
foreach ( SpannerSegment * ss , o - > spannerSegments ( ) ) {
if ( ss - > system ( ) )
ss - > system ( ) - > remove ( ss ) ;
}
2014-07-15 12:49:51 +02:00
o - > staff ( ) - > updateOttava ( ) ;
2016-03-18 09:29:16 +01:00
cmdState ( ) . layoutFlags | = LayoutFlag : : FIX_PITCH_VELO ;
2012-05-26 14:26:10 +02:00
_playlistDirty = true ;
}
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : DYNAMIC :
2016-03-18 09:29:16 +01:00
cmdState ( ) . layoutFlags | = LayoutFlag : : FIX_PITCH_VELO ;
2012-05-26 14:26:10 +02:00
_playlistDirty = true ;
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : CHORD :
case Element : : Type : : REST :
2012-05-26 14:26:10 +02:00
{
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( element ) ;
2012-05-26 14:26:10 +02:00
if ( cr - > beam ( ) )
cr - > beam ( ) - > remove ( cr ) ;
2016-08-17 12:52:35 +02:00
for ( Lyrics * lyr : cr - > lyrics ( ) )
2016-08-24 14:49:34 +02:00
lyr - > removeFromScore ( ) ;
2014-05-21 20:08:37 +02:00
// TODO: check for tuplet?
2012-05-26 14:26:10 +02:00
}
break ;
2014-06-24 18:36:02 +02:00
case Element : : Type : : TEMPO_TEXT :
2012-05-26 14:26:10 +02:00
{
2016-06-03 10:17:06 +02:00
TempoText * tt = toTempoText ( element ) ;
2012-05-26 14:26:10 +02:00
int tick = tt - > segment ( ) - > tick ( ) ;
tempomap ( ) - > delTempo ( tick ) ;
}
break ;
2015-03-05 16:46:37 +01:00
case Element : : Type : : INSTRUMENT_CHANGE : {
2016-06-03 10:17:06 +02:00
InstrumentChange * ic = toInstrumentChange ( element ) ;
2015-09-21 02:13:22 +02:00
int tickStart = ic - > segment ( ) - > tick ( ) ;
auto i = ic - > part ( ) - > instruments ( ) - > upper_bound ( tickStart ) ;
int tickEnd ;
if ( i = = ic - > part ( ) - > instruments ( ) - > end ( ) )
tickEnd = - 1 ;
else
tickEnd = i - > first ;
Interval oldV = ic - > part ( ) - > instrument ( tickStart ) - > transpose ( ) ;
ic - > part ( ) - > removeInstrument ( tickStart ) ;
transpositionChanged ( ic - > part ( ) , oldV , tickStart , tickEnd ) ;
2016-03-11 12:18:46 +01:00
masterScore ( ) - > rebuildMidiMapping ( ) ;
2016-03-18 09:29:16 +01:00
cmdState ( ) . _instrumentsChanged = true ;
2015-03-05 16:46:37 +01:00
}
2012-05-26 14:26:10 +02:00
break ;
2012-11-20 20:51:18 +01:00
2014-06-24 18:36:02 +02:00
case Element : : Type : : TREMOLO :
case Element : : Type : : ARTICULATION :
case Element : : Type : : ARPEGGIO :
2013-01-29 18:11:51 +01:00
{
Element * cr = element - > parent ( ) ;
2016-04-18 11:22:03 +02:00
if ( cr - > isChord ( ) )
createPlayEvents ( toChord ( cr ) ) ;
2013-01-29 18:11:51 +01:00
}
2016-06-03 10:17:06 +02:00
break ;
2012-11-20 20:51:18 +01:00
2012-05-26 14:26:10 +02:00
default :
break ;
}
}
//---------------------------------------------------------
// firstMeasure
//---------------------------------------------------------
Measure * Score : : firstMeasure ( ) const
{
MeasureBase * mb = _measures . first ( ) ;
2014-06-24 18:36:02 +02:00
while ( mb & & mb - > type ( ) ! = Element : : Type : : MEASURE )
2012-05-26 14:26:10 +02:00
mb = mb - > next ( ) ;
2013-09-19 15:08:54 +02:00
2016-06-03 10:17:06 +02:00
return toMeasure ( mb ) ;
2013-09-19 15:08:54 +02:00
}
//---------------------------------------------------------
// firstMeasureMM
//---------------------------------------------------------
Measure * Score : : firstMeasureMM ( ) const
{
2016-03-02 13:20:19 +01:00
Measure * m = firstMeasure ( ) ;
2014-05-26 15:31:36 +02:00
if ( m & & styleB ( StyleIdx : : createMultiMeasureRests ) & & m - > hasMMRest ( ) )
2013-09-20 12:59:31 +02:00
return m - > mmRest ( ) ;
return m ;
2012-05-26 14:26:10 +02:00
}
2013-09-19 15:08:54 +02:00
//---------------------------------------------------------
// firstMM
//---------------------------------------------------------
MeasureBase * Score : : firstMM ( ) const
{
MeasureBase * m = _measures . first ( ) ;
if ( m
2014-06-24 18:36:02 +02:00
& & m - > type ( ) = = Element : : Type : : MEASURE
2014-05-26 15:31:36 +02:00
& & styleB ( StyleIdx : : createMultiMeasureRests )
2016-06-03 10:17:06 +02:00
& & toMeasure ( m ) - > hasMMRest ( ) ) {
return toMeasure ( m ) - > mmRest ( ) ;
2013-09-19 15:08:54 +02:00
}
return m ;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// measure
//---------------------------------------------------------
MeasureBase * Score : : measure ( int idx ) const
{
MeasureBase * mb = _measures . first ( ) ;
for ( int i = 0 ; i < idx ; + + i ) {
mb = mb - > next ( ) ;
if ( mb = = 0 )
return 0 ;
}
return mb ;
}
//---------------------------------------------------------
// lastMeasure
//---------------------------------------------------------
Measure * Score : : lastMeasure ( ) const
{
MeasureBase * mb = _measures . last ( ) ;
2014-06-24 18:36:02 +02:00
while ( mb & & mb - > type ( ) ! = Element : : Type : : MEASURE )
2012-05-26 14:26:10 +02:00
mb = mb - > prev ( ) ;
2016-06-03 10:17:06 +02:00
return toMeasure ( mb ) ;
2012-05-26 14:26:10 +02:00
}
2013-10-06 16:43:43 +02:00
//---------------------------------------------------------
// lastMeasureMM
//---------------------------------------------------------
Measure * Score : : lastMeasureMM ( ) const
{
2014-08-17 12:41:44 +02:00
Measure * m = lastMeasure ( ) ;
2015-01-28 04:56:28 +01:00
if ( m & & styleB ( StyleIdx : : createMultiMeasureRests ) ) {
2016-06-03 10:17:06 +02:00
Measure * m1 = const_cast < Measure * > ( toMeasure ( m - > mmRest1 ( ) ) ) ;
2015-01-28 04:56:28 +01:00
if ( m1 )
return m1 ;
}
2014-08-17 12:41:44 +02:00
return m ;
2013-10-06 16:43:43 +02:00
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// firstSegment
//---------------------------------------------------------
2014-06-25 11:46:10 +02:00
Segment * Score : : firstSegment ( Segment : : Type segType ) const
2012-05-26 14:26:10 +02:00
{
2014-12-15 13:31:59 +01:00
Segment * seg ;
2012-05-26 14:26:10 +02:00
Measure * m = firstMeasure ( ) ;
2014-12-15 13:31:59 +01:00
if ( ! m )
seg = 0 ;
else {
seg = m - > first ( ) ;
if ( seg & & ! ( seg - > segmentType ( ) & segType ) )
seg = seg - > next1 ( segType ) ;
}
2014-07-06 01:56:30 +02:00
# ifdef SCRIPT_INTERFACE
// if called from QML/JS, tell QML engine not to garbage collect this object
if ( seg )
QQmlEngine : : setObjectOwnership ( seg , QQmlEngine : : CppOwnership ) ;
# endif
2014-07-06 02:14:58 +02:00
return seg ;
2012-05-26 14:26:10 +02:00
}
2016-01-12 22:59:38 +01:00
//---------------------------------------------------------
// firstSegment Q_INVOKABLE wrapper
//---------------------------------------------------------
Segment * Score : : firstSegment ( int segType ) const
{
return firstSegment ( static_cast < Segment : : Type > ( segType ) ) ;
}
2013-10-02 10:26:09 +02:00
//---------------------------------------------------------
// firstSegmentMM
//---------------------------------------------------------
2014-06-25 11:46:10 +02:00
Segment * Score : : firstSegmentMM ( Segment : : Type segType ) const
2013-10-02 10:26:09 +02:00
{
Measure * m = firstMeasureMM ( ) ;
return m ? m - > first ( segType ) : 0 ;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// lastSegment
//---------------------------------------------------------
Segment * Score : : lastSegment ( ) const
{
Measure * m = lastMeasure ( ) ;
return m ? m - > last ( ) : 0 ;
}
//---------------------------------------------------------
// utick2utime
//---------------------------------------------------------
qreal Score : : utick2utime ( int tick ) const
{
return repeatList ( ) - > utick2utime ( tick ) ;
}
//---------------------------------------------------------
// utime2utick
//---------------------------------------------------------
int Score : : utime2utick ( qreal utime ) const
{
return repeatList ( ) - > utime2utick ( utime ) ;
}
//---------------------------------------------------------
// inputPos
//---------------------------------------------------------
int Score : : inputPos ( ) const
{
return _is . tick ( ) ;
}
//---------------------------------------------------------
// scanElements
// scan all elements
//---------------------------------------------------------
void Score : : scanElements ( void * data , void ( * func ) ( void * , Element * ) , bool all )
{
2014-12-30 00:59:01 +01:00
for ( MeasureBase * mb = first ( ) ; mb ; mb = mb - > next ( ) ) {
mb - > scanElements ( data , func , all ) ;
if ( mb - > type ( ) = = Element : : Type : : MEASURE ) {
2016-06-03 10:17:06 +02:00
Measure * m = toMeasure ( mb ) ;
2014-12-30 00:59:01 +01:00
Measure * mmr = m - > mmRest ( ) ;
if ( mmr )
mmr - > scanElements ( data , func , all ) ;
}
}
2016-04-20 10:45:51 +02:00
for ( Page * page : pages ( ) ) {
for ( System * s : page - > systems ( ) )
s - > scanElements ( data , func , all ) ;
func ( data , page ) ;
}
2012-05-26 14:26:10 +02:00
}
2014-12-04 14:40:26 +01:00
//---------------------------------------------------------
// scanElementsInRange
//---------------------------------------------------------
2014-07-15 12:55:33 +02:00
void Score : : scanElementsInRange ( void * data , void ( * func ) ( void * , Element * ) , bool all )
{
Segment * startSeg = _selection . startSegment ( ) ;
2014-12-30 00:59:01 +01:00
for ( Segment * s = startSeg ; s & & s ! = _selection . endSegment ( ) ; s = s - > next1 ( ) ) {
s - > scanElements ( data , func , all ) ;
Measure * m = s - > measure ( ) ;
if ( m & & s = = m - > first ( ) ) {
Measure * mmr = m - > mmRest ( ) ;
if ( mmr )
mmr - > scanElements ( data , func , all ) ;
}
2014-07-15 12:55:33 +02:00
}
2015-05-18 10:46:10 +02:00
for ( Element * e : _selection . elements ( ) ) {
if ( e - > isSpanner ( ) ) {
Spanner * spanner = static_cast < Spanner * > ( e ) ;
for ( SpannerSegment * ss : spanner - > spannerSegments ( ) ) {
ss - > scanElements ( data , func , all ) ;
}
}
}
2014-07-15 12:55:33 +02:00
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// setSelection
//---------------------------------------------------------
void Score : : setSelection ( const Selection & s )
{
deselectAll ( ) ;
_selection = s ;
2013-04-17 10:31:21 +02:00
2012-05-26 14:26:10 +02:00
foreach ( Element * e , _selection . elements ( ) )
e - > setSelected ( true ) ;
}
//---------------------------------------------------------
// getText
//---------------------------------------------------------
2014-07-03 11:22:42 +02:00
Text * Score : : getText ( TextStyleType subtype )
2012-05-26 14:26:10 +02:00
{
2012-11-27 13:19:24 +01:00
MeasureBase * m = first ( ) ;
2014-06-24 18:36:02 +02:00
if ( m & & m - > type ( ) = = Element : : Type : : VBOX ) {
2015-02-17 20:22:24 +01:00
foreach ( Element * e , m - > el ( ) ) {
2016-06-03 10:17:06 +02:00
if ( e - > type ( ) = = Element : : Type : : TEXT & & toText ( e ) - > textStyleType ( ) = = subtype )
return toText ( e ) ;
2012-05-26 14:26:10 +02:00
}
}
return 0 ;
}
2013-07-19 10:39:32 +02:00
//---------------------------------------------------------
// metaTag
//---------------------------------------------------------
2014-05-22 19:49:51 +02:00
QString Score : : metaTag ( const QString & s ) const
2013-07-19 10:39:32 +02:00
{
2013-07-19 18:03:35 +02:00
if ( _metaTags . contains ( s ) )
return _metaTags . value ( s ) ;
2016-03-10 10:41:31 +01:00
return _masterScore - > _metaTags . value ( s ) ;
2013-07-19 10:39:32 +02:00
}
//---------------------------------------------------------
// setMetaTag
//---------------------------------------------------------
2014-05-22 19:49:51 +02:00
void Score : : setMetaTag ( const QString & tag , const QString & val )
2013-07-19 10:39:32 +02:00
{
2013-07-19 18:03:35 +02:00
_metaTags . insert ( tag , val ) ;
2013-07-19 10:39:32 +02:00
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// addExcerpt
//---------------------------------------------------------
2016-03-11 12:18:46 +01:00
void MasterScore : : addExcerpt ( Score * score )
2012-05-26 14:26:10 +02:00
{
2014-11-27 17:22:18 +01:00
Excerpt * ex = new Excerpt ( this ) ;
ex - > setPartScore ( score ) ;
2012-05-26 14:26:10 +02:00
excerpts ( ) . append ( ex ) ;
2016-03-18 09:29:16 +01:00
ex - > setTitle ( score - > fileInfo ( ) - > completeBaseName ( ) ) ;
2016-02-19 13:47:21 +01:00
for ( Staff * s : score - > staves ( ) ) {
2012-05-26 14:26:10 +02:00
LinkedStaves * ls = s - > linkedStaves ( ) ;
if ( ls = = 0 )
continue ;
2016-03-11 12:18:46 +01:00
for ( Staff * ps : ls - > staves ( ) ) {
2012-05-26 14:26:10 +02:00
if ( ps - > score ( ) = = this ) {
ex - > parts ( ) . append ( ps - > part ( ) ) ;
break ;
}
}
}
setExcerptsChanged ( true ) ;
}
//---------------------------------------------------------
// removeExcerpt
//---------------------------------------------------------
2016-04-18 12:20:42 +02:00
void MasterScore : : removeExcerpt ( Score * score )
2012-05-26 14:26:10 +02:00
{
2016-02-19 13:47:21 +01:00
for ( Excerpt * ex : excerpts ( ) ) {
2014-11-27 14:50:02 +01:00
if ( ex - > partScore ( ) = = score ) {
2012-05-26 14:26:10 +02:00
if ( excerpts ( ) . removeOne ( ex ) ) {
2016-04-18 12:20:42 +02:00
setExcerptsChanged ( true ) ;
2012-05-26 14:26:10 +02:00
delete ex ;
return ;
}
else
2013-07-25 17:22:49 +02:00
qDebug ( " removeExcerpt:: ex not found " ) ;
2012-05-26 14:26:10 +02:00
}
}
2013-07-25 17:22:49 +02:00
qDebug ( " Score::removeExcerpt: excerpt not found " ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// clone
//---------------------------------------------------------
2016-03-10 10:41:31 +01:00
MasterScore * MasterScore : : clone ( )
2012-05-26 14:26:10 +02:00
{
QBuffer buffer ;
buffer . open ( QIODevice : : WriteOnly ) ;
Xml xml ( & buffer ) ;
xml . header ( ) ;
xml . stag ( " museScore version= \" " MSC_VERSION " \" " ) ;
write ( xml , false ) ;
xml . etag ( ) ;
buffer . close ( ) ;
2013-01-11 18:10:18 +01:00
XmlReader r ( buffer . buffer ( ) ) ;
2016-03-10 10:41:31 +01:00
MasterScore * score = new MasterScore ( style ( ) ) ;
2013-01-11 18:10:18 +01:00
score - > read1 ( r , true ) ;
2012-05-26 14:26:10 +02:00
2016-02-10 13:40:34 +01:00
score - > addLayoutFlags ( LayoutFlag : : FIX_PITCH_VELO ) ;
2012-05-26 14:26:10 +02:00
score - > doLayout ( ) ;
score - > scanElements ( 0 , elementAdjustReadPos ) ; //??
return score ;
}
//---------------------------------------------------------
2013-04-02 20:46:07 +02:00
// setSynthesizerState
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2013-04-02 20:46:07 +02:00
void Score : : setSynthesizerState ( const SynthesizerState & s )
2012-05-26 14:26:10 +02:00
{
2013-04-02 20:46:07 +02:00
// TODO: make undoable
_synthesizerState = s ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// removeAudio
//---------------------------------------------------------
void Score : : removeAudio ( )
{
delete _audio ;
_audio = 0 ;
}
//---------------------------------------------------------
// appendScore
//---------------------------------------------------------
2016-04-12 00:18:41 +02:00
bool Score : : appendScore ( Score * score , bool addPageBreak , bool addSectionBreak )
2012-05-26 14:26:10 +02:00
{
2016-04-11 08:29:26 +02:00
if ( parts ( ) . size ( ) < score - > parts ( ) . size ( ) | | staves ( ) . size ( ) < score - > staves ( ) . size ( ) ) {
qDebug ( " Score to append has %d parts and %d staves, but this score only has %d parts and %d staves. " , score - > parts ( ) . size ( ) , score - > staves ( ) . size ( ) , parts ( ) . size ( ) , staves ( ) . size ( ) ) ;
2014-11-28 14:49:46 +01:00
return false ;
2016-04-11 08:29:26 +02:00
}
2012-05-26 14:26:10 +02:00
2016-04-11 08:29:26 +02:00
if ( ! last ( ) ) {
qDebug ( " This score doesn't have any MeasureBase objects. " ) ;
2014-12-16 13:30:36 +01:00
return false ;
2016-04-11 08:29:26 +02:00
}
TieMap tieMap ;
int tickOfAppend = last ( ) - > endTick ( ) ;
2014-11-28 14:49:46 +01:00
2016-04-12 00:18:41 +02:00
// apply Page/Section Breaks if desired
if ( addPageBreak ) {
2016-04-11 08:29:26 +02:00
if ( ! last ( ) - > pageBreak ( ) ) {
last ( ) - > undoSetBreak ( false , LayoutBreak : : Type : : LINE ) ; // remove line break if exists
last ( ) - > undoSetBreak ( true , LayoutBreak : : Type : : PAGE ) ; // apply page break
2016-04-12 00:18:41 +02:00
}
2014-11-28 14:49:46 +01:00
}
2016-04-11 08:29:26 +02:00
else if ( ! last ( ) - > lineBreak ( ) & & ! last ( ) - > pageBreak ( ) )
last ( ) - > undoSetBreak ( true , LayoutBreak : : Type : : LINE ) ;
if ( addSectionBreak & & ! last ( ) - > sectionBreak ( ) )
last ( ) - > undoSetBreak ( true , LayoutBreak : : Type : : SECTION ) ;
2014-11-28 14:49:46 +01:00
2014-12-23 00:18:59 +01:00
// match concert pitch states
if ( styleB ( StyleIdx : : concertPitch ) ! = score - > styleB ( StyleIdx : : concertPitch ) )
score - > cmdConcertPitchChanged ( styleB ( StyleIdx : : concertPitch ) , true ) ;
2015-09-18 09:03:55 +02:00
// convert any "generated" initial clefs into real "non-generated" clefs if clef type changes
if ( score - > firstMeasure ( ) ) {
Segment * initialClefSegment = score - > firstMeasure ( ) - > findSegment ( Segment : : Type : : Clef , 0 ) ; // find clefs at first tick of first measure
if ( initialClefSegment ) {
for ( int staffIdx = 0 ; staffIdx < score - > nstaves ( ) ; + + staffIdx ) {
int track = staffIdx * VOICES ;
Staff * staff = score - > staff ( staffIdx ) ;
2016-06-03 10:17:06 +02:00
Clef * initialClef = toClef ( initialClefSegment - > element ( track ) ) ;
2015-09-18 09:03:55 +02:00
// if the first clef of score to append is generated and
// if the first clef of score to append is of different type than clef at final tick of first score
2016-04-11 08:29:26 +02:00
if ( initialClef & & initialClef - > generated ( ) & & initialClef - > clefType ( ) ! = this - > staff ( staffIdx ) - > clef ( tickOfAppend ) ) {
2015-09-18 09:03:55 +02:00
// then convert that generated clef into a real non-generated clef so that its different type will be copied to joined score
score - > undoChangeClef ( staff , initialClefSegment , initialClef - > clefType ( ) ) ;
}
}
}
}
2014-11-28 14:49:46 +01:00
// clone the measures
2012-05-26 14:26:10 +02:00
MeasureBaseList * ml = & score - > _measures ;
for ( MeasureBase * mb = ml - > first ( ) ; mb ; mb = mb - > next ( ) ) {
MeasureBase * nmb ;
2014-06-24 18:36:02 +02:00
if ( mb - > type ( ) = = Element : : Type : : MEASURE )
2016-06-03 10:17:06 +02:00
nmb = toMeasure ( mb ) - > cloneMeasure ( this , & tieMap ) ;
2012-05-26 14:26:10 +02:00
else
nmb = mb - > clone ( ) ;
nmb - > setNext ( 0 ) ;
nmb - > setPrev ( 0 ) ;
nmb - > setScore ( this ) ;
_measures . add ( nmb ) ;
}
fixTicks ( ) ;
2015-09-21 08:07:56 +02:00
Measure * firstAppendedMeasure = tick2measure ( tickOfAppend ) ;
2014-11-28 14:49:46 +01:00
2015-07-04 11:24:23 +02:00
// if the appended score has less staves,
// make sure the measures have full measure rest
2015-09-21 08:07:56 +02:00
for ( Measure * m = firstAppendedMeasure ; m ; m = m - > nextMeasure ( ) ) {
2015-07-04 11:24:23 +02:00
for ( int staffIdx = 0 ; staffIdx < nstaves ( ) ; + + staffIdx ) {
Fraction f ;
for ( Segment * s = m - > first ( Segment : : Type : : ChordRest ) ; s ; s = s - > next ( Segment : : Type : : ChordRest ) ) {
for ( int v = 0 ; v < VOICES ; + + v ) {
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( s - > element ( staffIdx * VOICES + v ) ) ;
2015-07-04 11:24:23 +02:00
if ( cr = = 0 )
continue ;
f + = cr - > actualFraction ( ) ;
}
}
if ( f . isZero ( ) )
addRest ( m - > tick ( ) , staffIdx * VOICES , TDuration ( TDuration : : DurationType : : V_MEASURE ) , 0 ) ;
}
}
2014-12-23 00:18:59 +01:00
// adjust key signatures
2015-09-21 08:07:56 +02:00
if ( firstAppendedMeasure ) {
Segment * seg = firstAppendedMeasure - > getSegment ( Segment : : Type : : KeySig , tickOfAppend ) ;
for ( Staff * st : score - > staves ( ) ) {
int staffIdx = score - > staffIdx ( st ) ;
Staff * joinedStaff = staff ( staffIdx ) ;
// special case for initial "C" key signature - these have no explicit element
if ( ! seg - > element ( staffIdx * VOICES ) ) {
// no need to create new initial "C" key sig
// if staff already ends in that key
if ( joinedStaff - > key ( tickOfAppend - 1 ) = = Key : : C )
continue ;
Key key = Key : : C ;
KeySig * ks = new KeySig ( this ) ;
ks - > setTrack ( staffIdx * VOICES ) ;
ks - > setKey ( key ) ;
ks - > setParent ( seg ) ;
addElement ( ks ) ;
}
// other key signatures (initial other than "C", non-initial)
for ( auto k : * ( st - > keyList ( ) ) ) {
int tick = k . first ;
KeySigEvent key = k . second ;
joinedStaff - > setKey ( tick + tickOfAppend , key ) ;
}
2014-11-28 14:49:46 +01:00
}
}
// clone the spanners
for ( auto sp : score - > spanner ( ) ) {
Spanner * spanner = sp . second ;
Spanner * ns = static_cast < Spanner * > ( spanner - > clone ( ) ) ;
ns - > setScore ( this ) ;
ns - > setParent ( 0 ) ;
2015-09-21 08:07:56 +02:00
ns - > setTick ( spanner - > tick ( ) + tickOfAppend ) ;
ns - > setTick2 ( spanner - > tick2 ( ) + tickOfAppend ) ;
2014-11-28 14:49:46 +01:00
if ( ns - > type ( ) = = Element : : Type : : SLUR ) {
// set start/end element for slur
ns - > setStartElement ( 0 ) ;
ns - > setEndElement ( 0 ) ;
Measure * sm = tick2measure ( ns - > tick ( ) ) ;
if ( sm )
ns - > setStartElement ( sm - > findChordRest ( ns - > tick ( ) , ns - > track ( ) ) ) ;
Measure * em = tick2measure ( ns - > tick2 ( ) ) ;
if ( em )
ns - > setEndElement ( em - > findChordRest ( ns - > tick2 ( ) , ns - > track2 ( ) ) ) ;
if ( ! ns - > startElement ( ) )
qDebug ( " clone Slur: no start element " ) ;
if ( ! ns - > endElement ( ) )
qDebug ( " clone Slur: no end element " ) ;
}
addElement ( ns ) ;
}
2016-03-02 13:20:19 +01:00
setLayoutAll ( ) ;
2012-05-26 14:26:10 +02:00
return true ;
}
//---------------------------------------------------------
// splitStaff
//---------------------------------------------------------
void Score : : splitStaff ( int staffIdx , int splitPoint )
{
2016-04-11 15:28:32 +02:00
// qDebug("split staff %d point %d", staffIdx, splitPoint);
2012-05-26 14:26:10 +02:00
//
// create second staff
//
Staff * s = staff ( staffIdx ) ;
Part * p = s - > part ( ) ;
2014-08-16 13:32:08 +02:00
Staff * ns = new Staff ( this ) ;
ns - > setPart ( p ) ;
2015-01-26 23:37:10 +01:00
// convert staffIdx from score-relative to part-relative
int staffIdxPart = staffIdx - p - > staff ( 0 ) - > idx ( ) ;
undoInsertStaff ( ns , staffIdxPart + 1 , false ) ;
2012-05-26 14:26:10 +02:00
Clef * clef = new Clef ( this ) ;
2013-09-05 16:37:49 +02:00
clef - > setClefType ( ClefType : : F ) ;
2012-05-26 14:26:10 +02:00
clef - > setTrack ( ( staffIdx + 1 ) * VOICES ) ;
2014-06-25 11:46:10 +02:00
Segment * seg = firstMeasure ( ) - > getSegment ( Segment : : Type : : Clef , 0 ) ;
2012-05-26 14:26:10 +02:00
clef - > setParent ( seg ) ;
undoAddElement ( clef ) ;
2016-01-04 14:48:58 +01:00
clef - > layout ( ) ;
2012-05-26 14:26:10 +02:00
2014-12-08 18:02:17 +01:00
undoChangeKeySig ( ns , 0 , s - > keySigEvent ( 0 ) ) ;
2012-05-26 14:26:10 +02:00
2016-03-11 12:18:46 +01:00
masterScore ( ) - > rebuildMidiMapping ( ) ;
2016-03-18 09:29:16 +01:00
cmdState ( ) . _instrumentsChanged = true ;
2012-05-26 14:26:10 +02:00
doLayout ( ) ;
//
// move notes
//
2014-05-27 10:34:08 +02:00
select ( 0 , SelectType : : SINGLE , 0 ) ;
2012-05-26 14:26:10 +02:00
int strack = staffIdx * VOICES ;
int dtrack = ( staffIdx + 1 ) * VOICES ;
2014-06-25 11:46:10 +02:00
for ( Segment * s = firstSegment ( Segment : : Type : : ChordRest ) ; s ; s = s - > next1 ( Segment : : Type : : ChordRest ) ) {
2012-05-26 14:26:10 +02:00
for ( int voice = 0 ; voice < VOICES ; + + voice ) {
2016-06-03 10:49:40 +02:00
Element * e = s - > element ( strack + voice ) ;
if ( ! ( e & & e - > isChord ( ) ) )
2012-05-26 14:26:10 +02:00
continue ;
2016-06-03 10:49:40 +02:00
Chord * c = toChord ( e ) ;
2012-05-26 14:26:10 +02:00
QList < Note * > removeNotes ;
foreach ( Note * note , c - > notes ( ) ) {
if ( note - > pitch ( ) > = splitPoint )
continue ;
2016-06-03 10:17:06 +02:00
Chord * chord = toChord ( s - > element ( dtrack + voice ) ) ;
2014-06-24 18:36:02 +02:00
Q_ASSERT ( ! chord | | ( chord - > type ( ) = = Element : : Type : : CHORD ) ) ;
2012-05-26 14:26:10 +02:00
if ( chord = = 0 ) {
chord = new Chord ( * c ) ;
2014-08-16 16:10:47 +02:00
qDeleteAll ( chord - > notes ( ) ) ;
2012-05-26 14:26:10 +02:00
chord - > notes ( ) . clear ( ) ;
chord - > setTrack ( dtrack + voice ) ;
undoAddElement ( chord ) ;
}
Note * nnote = new Note ( * note ) ;
nnote - > setTrack ( dtrack + voice ) ;
chord - > add ( nnote ) ;
2013-03-21 16:27:10 +01:00
nnote - > updateLine ( ) ;
2012-05-26 14:26:10 +02:00
removeNotes . append ( note ) ;
}
2014-04-09 16:09:21 +02:00
c - > sortNotes ( ) ;
2015-04-10 11:51:15 +02:00
for ( Note * note : removeNotes ) {
2012-05-26 14:26:10 +02:00
undoRemoveElement ( note ) ;
2015-04-10 11:51:15 +02:00
Chord * chord = note - > chord ( ) ;
2016-02-06 22:03:43 +01:00
if ( chord - > notes ( ) . empty ( ) ) {
2015-04-10 11:51:15 +02:00
for ( auto sp : spanner ( ) ) {
Slur * slur = static_cast < Slur * > ( sp . second ) ;
if ( slur - > type ( ) ! = Element : : Type : : SLUR )
continue ;
if ( slur - > startCR ( ) = = chord ) {
slur - > undoChangeProperty ( P_ID : : TRACK , slur - > track ( ) + VOICES ) ;
2015-04-13 21:03:29 +02:00
for ( ScoreElement * ee : slur - > linkList ( ) ) {
Slur * lslur = static_cast < Slur * > ( ee ) ;
lslur - > setStartElement ( 0 ) ;
}
2015-04-10 11:51:15 +02:00
}
if ( slur - > endCR ( ) = = chord ) {
slur - > undoChangeProperty ( P_ID : : SPANNER_TRACK2 , slur - > track2 ( ) + VOICES ) ;
2015-04-13 21:03:29 +02:00
for ( ScoreElement * ee : slur - > linkList ( ) ) {
Slur * lslur = static_cast < Slur * > ( ee ) ;
lslur - > setEndElement ( 0 ) ;
}
2015-04-10 11:51:15 +02:00
}
}
2016-01-13 20:13:08 +01:00
undoRemoveElement ( chord ) ;
2015-04-10 11:51:15 +02:00
}
2012-05-26 14:26:10 +02:00
}
}
}
//
// make sure that the timeline for dtrack
// has no gaps
//
int ctick = 0 ;
for ( Measure * m = firstMeasure ( ) ; m ; m = m - > nextMeasure ( ) ) {
2014-06-25 11:46:10 +02:00
for ( Segment * s = m - > first ( Segment : : Type : : ChordRest ) ; s ; s = s - > next1 ( Segment : : Type : : ChordRest ) ) {
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( s - > element ( dtrack ) ) ;
2012-05-26 14:26:10 +02:00
if ( cr = = 0 )
continue ;
int rest = s - > tick ( ) - ctick ;
if ( rest ) {
// insert Rest
Segment * s = tick2segment ( ctick ) ;
if ( s = = 0 ) {
2013-07-25 17:22:49 +02:00
qDebug ( " no segment at %d " , ctick ) ;
2012-05-26 14:26:10 +02:00
continue ;
}
setRest ( ctick , dtrack , Fraction : : fromTicks ( rest ) , false , 0 ) ;
}
ctick = s - > tick ( ) + cr - > actualTicks ( ) ;
}
int rest = m - > tick ( ) + m - > ticks ( ) - ctick ;
if ( rest ) {
setRest ( ctick , dtrack , Fraction : : fromTicks ( rest ) , false , 0 ) ;
ctick + = rest ;
}
}
//
// same for strack
//
ctick = 0 ;
for ( Measure * m = firstMeasure ( ) ; m ; m = m - > nextMeasure ( ) ) {
2014-06-25 11:46:10 +02:00
for ( Segment * s = m - > first ( Segment : : Type : : ChordRest ) ; s ; s = s - > next1 ( Segment : : Type : : ChordRest ) ) {
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( s - > element ( strack ) ) ;
2012-05-26 14:26:10 +02:00
if ( cr = = 0 )
continue ;
int rest = s - > tick ( ) - ctick ;
if ( rest ) {
// insert Rest
Segment * s = tick2segment ( ctick ) ;
if ( s = = 0 ) {
2013-07-25 17:22:49 +02:00
qDebug ( " no segment at %d " , ctick ) ;
2012-05-26 14:26:10 +02:00
continue ;
}
setRest ( ctick , strack , Fraction : : fromTicks ( rest ) , false , 0 ) ;
}
ctick = s - > tick ( ) + cr - > actualTicks ( ) ;
}
int rest = m - > tick ( ) + m - > ticks ( ) - ctick ;
if ( rest ) {
setRest ( ctick , strack , Fraction : : fromTicks ( rest ) , false , 0 ) ;
ctick + = rest ;
}
}
}
//---------------------------------------------------------
// cmdRemovePart
//---------------------------------------------------------
void Score : : cmdRemovePart ( Part * part )
{
int sidx = staffIdx ( part ) ;
int n = part - > nstaves ( ) ;
2014-08-16 14:18:06 +02:00
2012-05-26 14:26:10 +02:00
for ( int i = 0 ; i < n ; + + i )
cmdRemoveStaff ( sidx ) ;
2013-09-20 12:59:31 +02:00
2012-05-26 14:26:10 +02:00
undoRemovePart ( part , sidx ) ;
}
//---------------------------------------------------------
// insertPart
//---------------------------------------------------------
void Score : : insertPart ( Part * part , int idx )
{
int staff = 0 ;
for ( QList < Part * > : : iterator i = _parts . begin ( ) ; i ! = _parts . end ( ) ; + + i ) {
if ( staff > = idx ) {
_parts . insert ( i , part ) ;
return ;
}
staff + = ( * i ) - > nstaves ( ) ;
}
_parts . push_back ( part ) ;
}
//---------------------------------------------------------
// removePart
//---------------------------------------------------------
void Score : : removePart ( Part * part )
{
_parts . removeAt ( _parts . indexOf ( part ) ) ;
}
//---------------------------------------------------------
// insertStaff
//---------------------------------------------------------
2014-08-11 15:25:55 +02:00
void Score : : insertStaff ( Staff * staff , int ridx )
2012-05-26 14:26:10 +02:00
{
2014-08-11 15:25:55 +02:00
staff - > part ( ) - > insertStaff ( staff , ridx ) ;
2014-08-16 13:32:08 +02:00
2014-08-16 14:18:06 +02:00
int idx = staffIdx ( staff - > part ( ) ) + ridx ;
_staves . insert ( idx , staff ) ;
2014-08-16 13:32:08 +02:00
2013-10-11 13:58:18 +02:00
for ( auto i = staff - > score ( ) - > spanner ( ) . cbegin ( ) ; i ! = staff - > score ( ) - > spanner ( ) . cend ( ) ; + + i ) {
Spanner * s = i - > second ;
2014-12-20 20:56:40 +01:00
if ( s - > systemFlag ( ) )
continue ;
2013-10-11 13:58:18 +02:00
if ( s - > staffIdx ( ) > = idx ) {
int t = s - > track ( ) + VOICES ;
s - > setTrack ( t < ntracks ( ) ? t : ntracks ( ) - 1 ) ;
if ( s - > track2 ( ) ! = - 1 ) {
t = s - > track2 ( ) + VOICES ;
s - > setTrack2 ( t < ntracks ( ) ? t : s - > track ( ) ) ;
}
}
}
2012-05-26 14:26:10 +02:00
}
2014-08-16 14:18:06 +02:00
//---------------------------------------------------------
// removeStaff
//---------------------------------------------------------
void Score : : removeStaff ( Staff * staff )
{
int idx = staffIdx ( staff ) ;
for ( auto i = staff - > score ( ) - > spanner ( ) . cbegin ( ) ; i ! = staff - > score ( ) - > spanner ( ) . cend ( ) ; + + i ) {
Spanner * s = i - > second ;
if ( s - > staffIdx ( ) > idx ) {
int t = s - > track ( ) - VOICES ;
s - > setTrack ( t > = 0 ? t : 0 ) ;
if ( s - > track2 ( ) ! = - 1 ) {
t = s - > track2 ( ) - VOICES ;
s - > setTrack2 ( t > = 0 ? t : s - > track ( ) ) ;
}
}
}
_staves . removeAll ( staff ) ;
staff - > part ( ) - > removeStaff ( staff ) ;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// adjustBracketsDel
//---------------------------------------------------------
void Score : : adjustBracketsDel ( int sidx , int eidx )
{
for ( int staffIdx = 0 ; staffIdx < _staves . size ( ) ; + + staffIdx ) {
Staff * staff = _staves [ staffIdx ] ;
for ( int i = 0 ; i < staff - > bracketLevels ( ) ; + + i ) {
int span = staff - > bracketSpan ( i ) ;
if ( ( span = = 0 ) | | ( ( staffIdx + span ) < sidx ) | | ( staffIdx > eidx ) )
continue ;
if ( ( sidx > = staffIdx ) & & ( eidx < = ( staffIdx + span ) ) )
undoChangeBracketSpan ( staff , i , span - ( eidx - sidx ) ) ;
}
2016-01-04 14:48:58 +01:00
#if 0 // TODO
2016-02-09 13:51:19 +01:00
int span = staff - > barLineSpan ( ) ;
2012-10-14 00:35:11 +02:00
if ( ( sidx > = staffIdx ) & & ( eidx < = ( staffIdx + span ) ) ) {
2012-11-05 10:12:57 +01:00
int newSpan = span - ( eidx - sidx ) + 1 ;
2012-10-14 00:35:11 +02:00
int lastSpannedStaffIdx = staffIdx + newSpan - 1 ;
2012-11-05 10:12:57 +01:00
undoChangeBarLineSpan ( staff , newSpan , 0 , ( _staves [ lastSpannedStaffIdx ] - > lines ( ) - 1 ) * 2 ) ;
2012-10-14 00:35:11 +02:00
}
2016-01-04 14:48:58 +01:00
# endif
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
// adjustBracketsIns
//---------------------------------------------------------
void Score : : adjustBracketsIns ( int sidx , int eidx )
{
for ( int staffIdx = 0 ; staffIdx < _staves . size ( ) ; + + staffIdx ) {
Staff * staff = _staves [ staffIdx ] ;
int bl = staff - > bracketLevels ( ) ;
for ( int i = 0 ; i < bl ; + + i ) {
int span = staff - > bracketSpan ( i ) ;
if ( ( span = = 0 ) | | ( ( staffIdx + span ) < sidx ) | | ( staffIdx > eidx ) )
continue ;
if ( ( sidx > = staffIdx ) & & ( eidx < ( staffIdx + span ) ) )
undoChangeBracketSpan ( staff , i , span + ( eidx - sidx ) ) ;
}
2016-02-09 13:51:19 +01:00
#if 0 // TODO
2012-05-26 14:26:10 +02:00
int span = staff - > barLineSpan ( ) ;
2014-08-16 17:54:10 +02:00
if ( ( sidx > = staffIdx ) & & ( eidx < ( staffIdx + span ) ) ) {
int idx = staffIdx + span - 1 ;
if ( idx > = _staves . size ( ) )
idx = _staves . size ( ) - 1 ;
undoChangeBarLineSpan ( staff , span , 0 , ( _staves [ idx ] - > lines ( ) - 1 ) * 2 ) ;
}
2016-01-04 14:48:58 +01:00
# endif
2012-05-26 14:26:10 +02:00
}
}
2013-09-11 16:13:43 +02:00
//---------------------------------------------------------
// adjustKeySigs
//---------------------------------------------------------
void Score : : adjustKeySigs ( int sidx , int eidx , KeyList km )
{
for ( int staffIdx = sidx ; staffIdx < eidx ; + + staffIdx ) {
Staff * staff = _staves [ staffIdx ] ;
2014-06-05 11:37:21 +02:00
if ( staff - > isDrumStaff ( ) )
continue ;
for ( auto i = km . begin ( ) ; i ! = km . end ( ) ; + + i ) {
int tick = i - > first ;
Measure * measure = tick2measure ( tick ) ;
2014-11-10 11:42:00 +01:00
if ( ! measure )
continue ;
2014-12-08 18:02:17 +01:00
KeySigEvent oKey = i - > second ;
KeySigEvent nKey = oKey ;
2015-09-21 02:13:22 +02:00
int diff = - staff - > part ( ) - > instrument ( tick ) - > transpose ( ) . chromatic ;
2015-06-05 01:53:47 +02:00
if ( diff ! = 0 & & ! styleB ( StyleIdx : : concertPitch ) & & ! oKey . custom ( ) & & ! oKey . isAtonal ( ) )
2014-12-08 18:02:17 +01:00
nKey . setKey ( transposeKey ( nKey . key ( ) , diff ) ) ;
2014-06-05 11:37:21 +02:00
staff - > setKey ( tick , nKey ) ;
KeySig * keysig = new KeySig ( this ) ;
keysig - > setTrack ( staffIdx * VOICES ) ;
2014-12-08 18:02:17 +01:00
keysig - > setKeySigEvent ( nKey ) ;
2014-06-05 11:37:21 +02:00
Segment * s = measure - > getSegment ( keysig , tick ) ;
s - > add ( keysig ) ;
2013-09-11 16:13:43 +02:00
}
}
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// cmdRemoveStaff
//---------------------------------------------------------
void Score : : cmdRemoveStaff ( int staffIdx )
{
Staff * s = staff ( staffIdx ) ;
2013-09-16 21:57:54 +02:00
adjustBracketsDel ( staffIdx , staffIdx + 1 ) ;
2013-09-19 18:24:58 +02:00
QList < Spanner * > sl ;
for ( auto i = _spanner . cbegin ( ) ; i ! = _spanner . cend ( ) ; + + i ) {
Spanner * s = i - > second ;
2014-12-20 20:56:40 +01:00
if ( s - > staffIdx ( ) = = staffIdx & & ( staffIdx ! = 0 | | ! s - > systemFlag ( ) ) )
2013-09-19 18:24:58 +02:00
sl . append ( s ) ;
}
2014-08-07 11:33:05 +02:00
for ( auto i : sl ) {
i - > undoUnlink ( ) ;
undo ( new RemoveElement ( i ) ) ;
}
2013-09-19 18:24:58 +02:00
2014-08-11 15:25:55 +02:00
undoRemoveStaff ( s ) ;
2013-09-16 21:57:54 +02:00
2016-02-19 13:47:21 +01:00
// remove linked staff and measures in linked staves in excerpts
// unlink staff in the same score
2013-09-19 18:24:58 +02:00
if ( s - > linkedStaves ( ) ) {
2016-03-21 18:39:29 +01:00
Staff * sameScoreLinkedStaff = nullptr ;
auto staves = s - > linkedStaves ( ) - > staves ( ) ;
for ( Staff * staff : staves ) {
2016-02-19 13:47:21 +01:00
if ( staff = = s )
continue ;
2015-07-04 11:24:23 +02:00
Score * lscore = staff - > score ( ) ;
if ( lscore ! = this ) {
2016-01-19 18:37:52 +01:00
lscore - > undoRemoveStaff ( staff ) ;
2016-03-21 18:39:29 +01:00
s - > score ( ) - > undo ( new UnlinkStaff ( s , staff ) ) ;
2014-08-25 19:30:56 +02:00
if ( staff - > part ( ) - > nstaves ( ) = = 0 ) {
int pIndex = lscore - > staffIdx ( staff - > part ( ) ) ;
2016-01-19 18:37:52 +01:00
lscore - > undoRemovePart ( staff - > part ( ) , pIndex ) ;
2014-08-25 19:30:56 +02:00
}
2013-09-17 13:11:23 +02:00
}
2016-02-19 13:47:21 +01:00
else // linked staff in the same score
2016-03-21 18:39:29 +01:00
sameScoreLinkedStaff = staff ;
2013-09-16 21:57:54 +02:00
}
2016-03-21 18:39:29 +01:00
if ( sameScoreLinkedStaff )
s - > score ( ) - > undo ( new UnlinkStaff ( sameScoreLinkedStaff , s ) ) ; // once should be enough
2013-09-16 21:57:54 +02:00
}
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// sortStaves
//---------------------------------------------------------
void Score : : sortStaves ( QList < int > & dst )
{
2016-02-04 11:27:47 +01:00
systems ( ) . clear ( ) ; //??
2012-05-26 14:26:10 +02:00
_parts . clear ( ) ;
Part * curPart = 0 ;
QList < Staff * > dl ;
2013-09-20 12:59:31 +02:00
foreach ( int idx , dst ) {
2012-05-26 14:26:10 +02:00
Staff * staff = _staves [ idx ] ;
if ( staff - > part ( ) ! = curPart ) {
curPart = staff - > part ( ) ;
curPart - > staves ( ) - > clear ( ) ;
_parts . push_back ( curPart ) ;
}
curPart - > staves ( ) - > push_back ( staff ) ;
dl . push_back ( staff ) ;
}
_staves = dl ;
2013-09-20 12:59:31 +02:00
for ( Measure * m = firstMeasure ( ) ; m ; m = m - > nextMeasure ( ) ) {
2012-05-26 14:26:10 +02:00
m - > sortStaves ( dst ) ;
2013-09-20 12:59:31 +02:00
if ( m - > hasMMRest ( ) )
m - > mmRest ( ) - > sortStaves ( dst ) ;
2012-05-26 14:26:10 +02:00
}
2013-10-11 10:46:48 +02:00
for ( auto i : _spanner . map ( ) ) {
Spanner * sp = i . second ;
2014-12-20 20:56:40 +01:00
if ( sp - > systemFlag ( ) )
continue ;
2013-10-11 10:46:48 +02:00
int voice = sp - > voice ( ) ;
int staffIdx = sp - > staffIdx ( ) ;
int idx = dst . indexOf ( staffIdx ) ;
if ( idx > = 0 ) {
sp - > setTrack ( idx * VOICES + voice ) ;
if ( sp - > track2 ( ) ! = - 1 )
sp - > setTrack2 ( idx * VOICES + ( sp - > track2 ( ) % VOICES ) ) ; // at least keep the voice...
}
}
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// cmdConcertPitchChanged
//---------------------------------------------------------
2014-04-09 14:13:22 +02:00
void Score : : cmdConcertPitchChanged ( bool flag , bool /*useDoubleSharpsFlats*/ )
2012-05-26 14:26:10 +02:00
{
2016-07-04 09:27:43 +02:00
undo ( new ChangeStyleVal ( this , StyleIdx : : concertPitch , flag ) ) ; // change style flag
2012-05-26 14:26:10 +02:00
2014-04-02 18:11:56 +02:00
for ( Staff * staff : _staves ) {
2014-05-27 13:30:23 +02:00
if ( staff - > staffType ( ) - > group ( ) = = StaffGroup : : PERCUSSION )
2012-05-26 14:26:10 +02:00
continue ;
2015-09-21 02:13:22 +02:00
// if this staff has no transposition, and no instrument changes, we can skip it
2015-03-13 11:16:43 +01:00
Interval interval = staff - > part ( ) - > instrument ( ) - > transpose ( ) ;
2015-09-21 02:13:22 +02:00
if ( interval . isZero ( ) & & staff - > part ( ) - > instruments ( ) - > size ( ) = = 1 )
2012-05-26 14:26:10 +02:00
continue ;
if ( ! flag )
interval . flip ( ) ;
2014-04-02 18:11:56 +02:00
2014-04-09 09:40:25 +02:00
int staffIdx = staff - > idx ( ) ;
2014-04-02 18:11:56 +02:00
int startTrack = staffIdx * VOICES ;
int endTrack = startTrack + VOICES ;
2015-09-21 02:13:22 +02:00
transposeKeys ( staffIdx , staffIdx + 1 , 0 , lastSegment ( ) - > tick ( ) , interval , true , ! flag ) ;
2014-04-02 18:11:56 +02:00
2014-06-25 11:46:10 +02:00
for ( Segment * segment = firstSegment ( Segment : : Type : : ChordRest ) ; segment ; segment = segment - > next1 ( Segment : : Type : : ChordRest ) ) {
2015-09-21 02:13:22 +02:00
interval = staff - > part ( ) - > instrument ( segment - > tick ( ) ) - > transpose ( ) ;
if ( ! flag )
interval . flip ( ) ;
2014-04-02 18:11:56 +02:00
for ( Element * e : segment - > annotations ( ) ) {
2016-07-04 09:27:43 +02:00
if ( ! e - > isHarmony ( ) | | ( e - > track ( ) < startTrack ) | | ( e - > track ( ) > = endTrack ) )
2014-04-02 18:11:56 +02:00
continue ;
2016-06-03 10:17:06 +02:00
Harmony * h = toHarmony ( e ) ;
2014-12-20 00:27:06 +01:00
int rootTpc = transposeTpc ( h - > rootTpc ( ) , interval , true ) ;
int baseTpc = transposeTpc ( h - > baseTpc ( ) , interval , true ) ;
2015-04-08 05:28:28 +02:00
for ( ScoreElement * e : h - > linkList ( ) ) {
// don't transpose all links
// just ones resulting from mmrests
Harmony * he = static_cast < Harmony * > ( e ) ;
if ( he - > staff ( ) = = h - > staff ( ) )
undoTransposeHarmony ( he , rootTpc , baseTpc ) ;
}
2014-04-02 18:11:56 +02:00
}
2012-05-26 14:26:10 +02:00
}
}
}
//---------------------------------------------------------
// addAudioTrack
//---------------------------------------------------------
void Score : : addAudioTrack ( )
{
// TODO
}
//---------------------------------------------------------
// padToggle
//---------------------------------------------------------
2014-05-30 10:16:58 +02:00
void Score : : padToggle ( Pad n )
2012-05-26 14:26:10 +02:00
{
2016-08-08 17:45:53 +02:00
int oldDots = _is . duration ( ) . dots ( ) ;
2012-05-26 14:26:10 +02:00
switch ( n ) {
2014-05-30 10:16:58 +02:00
case Pad : : NOTE00 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_LONG ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE0 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_BREVE ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE1 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_WHOLE ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE2 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_HALF ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE4 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_QUARTER ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE8 :
2014-08-15 18:32:48 +02:00
_is . setDuration ( TDuration : : DurationType : : V_EIGHTH ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE16 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_16TH ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE32 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_32ND ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE64 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_64TH ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : NOTE128 :
2014-05-21 15:43:19 +02:00
_is . setDuration ( TDuration : : DurationType : : V_128TH ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : REST :
2013-10-24 12:09:00 +02:00
_is . setRest ( ! _is . rest ( ) ) ;
2012-05-26 14:26:10 +02:00
break ;
2014-05-30 10:16:58 +02:00
case Pad : : DOT :
2015-03-12 16:08:01 +01:00
if ( ( _is . duration ( ) . dots ( ) = = 1 ) | | ( _is . duration ( ) = = TDuration : : DurationType : : V_128TH ) )
2012-05-26 14:26:10 +02:00
_is . setDots ( 0 ) ;
else
_is . setDots ( 1 ) ;
break ;
2014-05-30 10:16:58 +02:00
case Pad : : DOTDOT :
2016-05-31 19:48:28 +02:00
if ( ( _is . duration ( ) . dots ( ) = = 2 )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_64TH )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_128TH ) )
2012-05-26 14:26:10 +02:00
_is . setDots ( 0 ) ;
else
_is . setDots ( 2 ) ;
break ;
2016-05-31 19:48:28 +02:00
case Pad : : DOT3 :
if ( ( _is . duration ( ) . dots ( ) = = 3 )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_32ND )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_64TH )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_128TH ) )
_is . setDots ( 0 ) ;
else
_is . setDots ( 3 ) ;
break ;
case Pad : : DOT4 :
if ( ( _is . duration ( ) . dots ( ) = = 4 )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_16TH )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_32ND )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_64TH )
| | ( _is . duration ( ) = = TDuration : : DurationType : : V_128TH ) )
_is . setDots ( 0 ) ;
else
_is . setDots ( 4 ) ;
break ;
2012-05-26 14:26:10 +02:00
}
2014-05-30 10:16:58 +02:00
if ( n > = Pad : : NOTE00 & & n < = Pad : : NOTE128 ) {
2012-05-26 14:26:10 +02:00
_is . setDots ( 0 ) ;
//
// if in "note enter" mode, reset
// rest flag
//
2016-08-08 17:45:53 +02:00
if ( noteEntryMode ( ) ) {
if ( usingNoteEntryMethod ( NoteEntryMethod : : RHYTHM ) ) {
switch ( oldDots ) {
case 1 :
padToggle ( Pad : : DOT ) ;
break ;
case 2 :
padToggle ( Pad : : DOTDOT ) ;
break ;
}
NoteVal nval ;
if ( _is . rest ( ) ) {
// Enter a rest
nval = NoteVal ( ) ;
}
else {
// Enter a note on the middle staff line
Staff * s = staff ( _is . track ( ) / VOICES ) ;
int tick = _is . tick ( ) ;
ClefType clef = s - > clef ( tick ) ;
Key key = s - > key ( tick ) ;
nval = NoteVal ( line2pitch ( 4 , clef , key ) ) ;
}
setNoteRest ( _is . segment ( ) , _is . track ( ) , nval , _is . duration ( ) . fraction ( ) ) ;
_is . moveToNextInputPos ( ) ;
}
else
_is . setRest ( false ) ;
}
2012-05-26 14:26:10 +02:00
}
2016-05-31 19:48:28 +02:00
if ( noteEntryMode ( ) | | ! selection ( ) . isSingle ( ) )
2012-05-26 14:26:10 +02:00
return ;
//do not allow to add a dot on a full measure rest
Element * e = selection ( ) . element ( ) ;
2016-08-03 17:29:52 +02:00
if ( e & & e - > isRest ( ) ) {
2016-06-03 10:17:06 +02:00
Rest * r = toRest ( e ) ;
2016-08-03 17:29:52 +02:00
if ( r - > isFullMeasureRest ( ) )
2012-05-26 14:26:10 +02:00
_is . setDots ( 0 ) ;
}
2016-07-29 15:06:36 +02:00
// on measure rest, select the first actual rest
2014-11-22 13:05:23 +01:00
ChordRest * cr = selection ( ) . cr ( ) ;
2016-07-29 15:06:36 +02:00
if ( cr & & cr - > isRest ( ) & & cr - > measure ( ) - > isMMRest ( ) ) {
Measure * m = cr - > measure ( ) - > mmRestFirst ( ) ;
if ( m )
cr = m - > findChordRest ( 0 , 0 ) ;
}
2014-11-22 13:05:23 +01:00
if ( ! cr )
2012-05-26 14:26:10 +02:00
return ;
2016-08-03 17:29:52 +02:00
if ( cr - > isChord ( ) & & ( toChord ( cr ) - > isGrace ( ) ) ) {
2012-05-26 14:26:10 +02:00
//
// handle appoggiatura and acciaccatura
//
2014-11-29 08:27:07 +01:00
undoChangeChordRestLen ( cr , _is . duration ( ) ) ;
2012-05-26 14:26:10 +02:00
}
else
changeCRlen ( cr , _is . duration ( ) ) ;
}
//---------------------------------------------------------
// deselect
//---------------------------------------------------------
void Score : : deselect ( Element * el )
{
2016-03-18 09:29:16 +01:00
addRefresh ( el - > abbox ( ) ) ;
2012-05-26 14:26:10 +02:00
_selection . remove ( el ) ;
2015-06-27 14:18:35 +02:00
setSelectionChanged ( true ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// select
// staffIdx is valid, if element is of type MEASURE
//---------------------------------------------------------
void Score : : select ( Element * e , SelectType type , int staffIdx )
{
2014-06-24 18:36:02 +02:00
if ( e & & ( e - > type ( ) = = Element : : Type : : NOTE | | e - > type ( ) = = Element : : Type : : REST ) ) {
2012-05-26 14:26:10 +02:00
Element * ee = e ;
2014-06-24 18:36:02 +02:00
if ( ee - > type ( ) = = Element : : Type : : NOTE )
2012-05-26 14:26:10 +02:00
ee = ee - > parent ( ) ;
2016-06-03 10:17:06 +02:00
int tick = toChordRest ( ee ) - > segment ( ) - > tick ( ) ;
2014-11-17 16:44:05 +01:00
if ( playPos ( ) ! = tick )
setPlayPos ( tick ) ;
2012-05-26 14:26:10 +02:00
}
if ( MScore : : debugMode )
2015-10-27 11:30:09 +01:00
qDebug ( " select element <%s> type %d(state %d) staff %d " ,
e ? e - > name ( ) : " " , int ( type ) , int ( selection ( ) . state ( ) ) , e ? e - > staffIdx ( ) : - 1 ) ;
2012-05-26 14:26:10 +02:00
2014-05-24 22:24:48 +02:00
switch ( type ) {
case SelectType : : SINGLE : return selectSingle ( e , staffIdx ) ;
case SelectType : : ADD : return selectAdd ( e ) ;
case SelectType : : RANGE : return selectRange ( e , staffIdx ) ;
}
}
2012-05-26 14:26:10 +02:00
2014-05-24 22:24:48 +02:00
//---------------------------------------------------------
// selectSingle
// staffIdx is valid, if element is of type MEASURE
//---------------------------------------------------------
void Score : : selectSingle ( Element * e , int staffIdx )
{
SelState selState = _selection . state ( ) ;
deselectAll ( ) ;
if ( e = = 0 ) {
selState = SelState : : NONE ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2014-05-24 22:24:48 +02:00
}
else {
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) = = Element : : Type : : MEASURE ) {
2014-05-24 22:24:48 +02:00
select ( e , SelectType : : RANGE , staffIdx ) ;
return ;
2012-05-26 14:26:10 +02:00
}
2016-03-18 09:29:16 +01:00
addRefresh ( e - > abbox ( ) ) ;
2014-05-24 22:24:48 +02:00
_selection . add ( e ) ;
_is . setTrack ( e - > track ( ) ) ;
selState = SelState : : LIST ;
2014-07-10 14:13:37 +02:00
if ( e - > type ( ) = = Element : : Type : : NOTE ) {
2014-05-24 22:24:48 +02:00
e = e - > parent ( ) ;
2014-07-10 14:13:37 +02:00
}
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) = = Element : : Type : : REST | | e - > type ( ) = = Element : : Type : : CHORD ) {
2014-05-24 22:24:48 +02:00
_is . setLastSegment ( _is . segment ( ) ) ;
2016-06-03 10:17:06 +02:00
_is . setSegment ( toChordRest ( e ) - > segment ( ) ) ;
2012-05-26 14:26:10 +02:00
}
}
2014-05-24 22:24:48 +02:00
_selection . setActiveSegment ( 0 ) ;
_selection . setActiveTrack ( 0 ) ;
_selection . setState ( selState ) ;
}
//---------------------------------------------------------
// selectAdd
//---------------------------------------------------------
void Score : : selectAdd ( Element * e )
{
SelState selState = _selection . state ( ) ;
if ( _selection . isRange ( ) ) {
select ( 0 , SelectType : : SINGLE , 0 ) ;
return ;
}
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) = = Element : : Type : : MEASURE ) {
2016-06-03 10:17:06 +02:00
Measure * m = toMeasure ( e ) ;
2014-05-24 22:24:48 +02:00
int tick = m - > tick ( ) ;
if ( _selection . isNone ( ) ) {
2014-05-31 19:30:17 +02:00
_selection . setRange ( m - > tick2segment ( tick ) ,
m = = lastMeasure ( ) ? 0 : m - > last ( ) ,
0 ,
nstaves ( ) ) ;
2012-05-26 14:26:10 +02:00
}
else {
2014-05-24 22:24:48 +02:00
select ( 0 , SelectType : : SINGLE , 0 ) ;
return ;
2012-05-26 14:26:10 +02:00
}
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2014-05-24 22:24:48 +02:00
selState = SelState : : RANGE ;
_selection . updateSelectedElements ( ) ;
2012-05-26 14:26:10 +02:00
}
2014-05-24 22:24:48 +02:00
else { // None or List
2016-03-18 09:29:16 +01:00
addRefresh ( e - > abbox ( ) ) ;
2014-05-24 22:24:48 +02:00
if ( _selection . elements ( ) . contains ( e ) )
_selection . remove ( e ) ;
else {
2015-07-04 11:24:23 +02:00
_selection . add ( e ) ;
selState = SelState : : LIST ;
}
2014-05-24 22:24:48 +02:00
}
_selection . setState ( selState ) ;
}
2014-05-24 12:53:50 +02:00
2014-05-24 22:24:48 +02:00
//---------------------------------------------------------
// selectRange
// staffIdx is valid, if element is of type MEASURE
//---------------------------------------------------------
void Score : : selectRange ( Element * e , int staffIdx )
{
int activeTrack = e - > track ( ) ;
2015-11-06 22:43:10 +01:00
// current selection is range extending to end of score?
bool endRangeSelected = selection ( ) . isRange ( ) & & selection ( ) . endSegment ( ) = = nullptr ;
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) = = Element : : Type : : MEASURE ) {
2016-06-03 10:17:06 +02:00
Measure * m = toMeasure ( e ) ;
2014-05-24 22:24:48 +02:00
int tick = m - > tick ( ) ;
int etick = tick + m - > ticks ( ) ;
activeTrack = staffIdx * VOICES ;
if ( _selection . isNone ( )
2015-07-04 11:24:23 +02:00
| | ( _selection . isList ( ) & & ! _selection . isSingle ( ) ) ) {
2014-05-24 12:53:50 +02:00
if ( _selection . isList ( ) )
2014-05-24 20:28:01 +02:00
deselectAll ( ) ;
2014-05-24 22:24:48 +02:00
_selection . setRange ( m - > tick2segment ( tick ) ,
m = = lastMeasure ( ) ? 0 : m - > last ( ) ,
staffIdx ,
staffIdx + 1 ) ;
}
else if ( _selection . isRange ( ) ) {
2014-05-31 22:23:23 +02:00
_selection . extendRangeSelection ( m - > tick2segment ( tick ) ,
m = = lastMeasure ( ) ? 0 : m - > last ( ) ,
staffIdx ,
tick ,
etick ) ;
2014-05-24 22:24:48 +02:00
}
else if ( _selection . isSingle ( ) ) {
2014-06-30 13:05:28 +02:00
Element * oe = selection ( ) . element ( ) ;
if ( oe - > type ( ) = = Element : : Element : : Type : : NOTE | | oe - > isChordRest ( ) ) {
if ( oe - > type ( ) = = Element : : Element : : Type : : NOTE )
oe = oe - > parent ( ) ;
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( oe ) ;
2014-06-30 13:05:28 +02:00
int oetick = cr - > segment ( ) - > tick ( ) ;
2015-05-30 15:00:02 +02:00
Segment * startSegment = cr - > segment ( ) ;
Segment * endSegment = m - > last ( ) ;
2014-06-30 13:05:28 +02:00
if ( tick < oetick ) {
2015-05-30 15:00:02 +02:00
startSegment = m - > tick2segment ( tick ) ;
2015-05-30 18:27:14 +02:00
if ( etick < = oetick )
2015-05-30 15:00:02 +02:00
endSegment = cr - > nextSegmentAfterCR ( Segment : : Type : : ChordRest
2014-08-10 02:09:04 +02:00
| Segment : : Type : : EndBarLine
2015-05-30 15:00:02 +02:00
| Segment : : Type : : Clef ) ;
2014-08-11 15:25:55 +02:00
2014-06-30 13:05:28 +02:00
}
2015-05-30 15:00:02 +02:00
int staffStart = staffIdx ;
int endStaff = staffIdx + 1 ;
if ( staffStart > cr - > staffIdx ( ) )
staffStart = cr - > staffIdx ( ) ;
else if ( cr - > staffIdx ( ) > = endStaff )
endStaff = cr - > staffIdx ( ) + 1 ;
_selection . setRange ( startSegment , endSegment , staffStart , endStaff ) ;
2012-05-26 14:26:10 +02:00
}
2014-06-30 13:05:28 +02:00
else {
deselectAll ( ) ;
_selection . setRange ( m - > tick2segment ( tick ) ,
m = = lastMeasure ( ) ? 0 : m - > last ( ) ,
staffIdx ,
staffIdx + 1 ) ;
2012-05-26 14:26:10 +02:00
}
2014-05-24 22:24:48 +02:00
}
else {
2015-10-27 11:30:09 +01:00
qDebug ( " SELECT_RANGE: measure: sel state %d " , int ( _selection . state ( ) ) ) ;
2014-05-24 22:24:48 +02:00
return ;
2012-05-26 14:26:10 +02:00
}
2014-05-24 22:24:48 +02:00
}
2014-06-24 18:36:02 +02:00
else if ( e - > type ( ) = = Element : : Type : : NOTE | | e - > isChordRest ( ) ) {
if ( e - > type ( ) = = Element : : Type : : NOTE )
2014-05-24 22:24:48 +02:00
e = e - > parent ( ) ;
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( e ) ;
2012-05-26 14:26:10 +02:00
2014-05-31 21:14:25 +02:00
if ( _selection . isNone ( )
| | ( _selection . isList ( ) & & ! _selection . isSingle ( ) ) ) {
if ( _selection . isList ( ) )
deselectAll ( ) ;
2014-05-31 19:30:17 +02:00
_selection . setRange ( cr - > segment ( ) ,
2014-06-30 11:26:58 +02:00
cr - > nextSegmentAfterCR ( Segment : : Type : : ChordRest
| Segment : : Type : : EndBarLine
| Segment : : Type : : Clef ) ,
2014-05-31 19:30:17 +02:00
e - > staffIdx ( ) ,
2014-06-18 10:17:00 +02:00
e - > staffIdx ( ) + 1 ) ;
2014-05-24 22:24:48 +02:00
activeTrack = cr - > track ( ) ;
}
else if ( _selection . isSingle ( ) ) {
Element * oe = _selection . element ( ) ;
2014-06-24 18:36:02 +02:00
if ( oe & & ( oe - > type ( ) = = Element : : Type : : NOTE | | oe - > type ( ) = = Element : : Type : : REST ) ) {
if ( oe - > type ( ) = = Element : : Type : : NOTE )
2014-05-24 22:24:48 +02:00
oe = oe - > parent ( ) ;
2016-06-03 10:17:06 +02:00
ChordRest * ocr = toChordRest ( oe ) ;
2014-05-31 21:14:25 +02:00
2015-06-14 20:14:31 +02:00
Segment * endSeg = tick2segmentMM ( ocr - > segment ( ) - > tick ( ) + ocr - > actualTicks ( ) ) ;
2014-05-31 21:14:25 +02:00
if ( ! endSeg )
endSeg = ocr - > segment ( ) - > next ( ) ;
2014-05-31 19:30:17 +02:00
_selection . setRange ( ocr - > segment ( ) ,
2014-05-31 21:14:25 +02:00
endSeg ,
2014-05-31 19:30:17 +02:00
oe - > staffIdx ( ) ,
2014-06-18 10:17:00 +02:00
oe - > staffIdx ( ) + 1 ) ;
2014-05-31 21:14:25 +02:00
_selection . extendRangeSelection ( cr ) ;
2012-05-26 14:26:10 +02:00
}
else {
2014-05-24 22:24:48 +02:00
select ( e , SelectType : : SINGLE , 0 ) ;
2014-05-24 20:28:01 +02:00
return ;
2012-05-26 14:26:10 +02:00
}
2014-05-24 22:24:48 +02:00
}
else if ( _selection . isRange ( ) ) {
2014-05-31 21:14:25 +02:00
_selection . extendRangeSelection ( cr ) ;
2012-05-26 14:26:10 +02:00
}
else {
2015-10-27 11:30:09 +01:00
qDebug ( " sel state %d " , int ( _selection . state ( ) ) ) ;
2012-05-26 14:26:10 +02:00
return ;
}
2015-11-06 22:43:10 +01:00
if ( ! endRangeSelected & & ! _selection . endSegment ( ) )
2014-05-24 22:24:48 +02:00
_selection . setEndSegment ( cr - > segment ( ) - > nextCR ( ) ) ;
if ( ! _selection . startSegment ( ) )
_selection . setStartSegment ( cr - > segment ( ) ) ;
}
else {
select ( e , SelectType : : SINGLE , staffIdx ) ;
return ;
}
2012-05-26 14:26:10 +02:00
2014-05-24 22:24:48 +02:00
_selection . setActiveTrack ( activeTrack ) ;
2012-05-26 14:26:10 +02:00
2015-02-09 18:21:37 +01:00
// doing this in note entry mode can clear selection
if ( _selection . startSegment ( ) & & ! noteEntryMode ( ) )
2014-11-15 23:12:09 +01:00
setPlayPos ( _selection . startSegment ( ) - > tick ( ) ) ;
2014-05-24 22:24:48 +02:00
_selection . updateSelectedElements ( ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
2014-07-15 00:28:31 +02:00
// collectMatch
//---------------------------------------------------------
void Score : : collectMatch ( void * data , Element * e )
{
ElementPattern * p = static_cast < ElementPattern * > ( data ) ;
if ( p - > type ! = int ( e - > type ( ) ) )
return ;
2014-09-23 18:07:32 +02:00
if ( p - > subtypeValid ) {
// HACK: grace note is different from normal note
2016-05-03 01:21:42 +02:00
// TODO: this disables the ability to distinguish noteheads in subtype
2014-09-23 18:07:32 +02:00
if ( p - > type = = int ( Element : : Type : : NOTE ) ) {
2016-06-03 10:17:06 +02:00
if ( p - > subtype ! = toNote ( e ) - > chord ( ) - > isGrace ( ) )
2014-09-23 18:07:32 +02:00
return ;
}
else {
if ( p - > subtype ! = e - > subtype ( ) )
return ;
}
}
2014-07-16 15:36:20 +02:00
if ( ( p - > staffStart ! = - 1 )
2015-07-04 11:24:23 +02:00
& & ( ( p - > staffStart > e - > staffIdx ( ) ) | | ( p - > staffEnd < = e - > staffIdx ( ) ) ) )
2014-07-15 00:28:31 +02:00
return ;
2016-04-20 10:45:51 +02:00
if ( e - > isChord ( ) | | e - > isRest ( ) | | e - > isNote ( ) | | e - > isLyrics ( ) | | e - > isBeam ( ) | | e - > isStem ( ) | | e - > isSlurSegment ( ) ) {
2014-07-15 00:28:31 +02:00
if ( p - > voice ! = - 1 & & p - > voice ! = e - > voice ( ) )
return ;
}
if ( p - > system ) {
Element * ee = e ;
do {
if ( ee - > type ( ) = = Element : : Type : : SYSTEM ) {
if ( p - > system ! = ee )
return ;
break ;
}
ee = ee - > parent ( ) ;
} while ( ee ) ;
}
p - > el . append ( e ) ;
}
2014-08-15 17:20:20 +02:00
//---------------------------------------------------------
// selectSimilar
//---------------------------------------------------------
2014-07-15 00:28:31 +02:00
void Score : : selectSimilar ( Element * e , bool sameStaff )
{
Element : : Type type = e - > type ( ) ;
2014-08-15 17:20:20 +02:00
Score * score = e - > score ( ) ;
2014-07-15 00:28:31 +02:00
ElementPattern pattern ;
2014-09-23 18:07:32 +02:00
pattern . type = int ( type ) ;
if ( type = = Element : : Type : : NOTE ) {
2016-06-03 10:17:06 +02:00
pattern . subtype = toNote ( e ) - > chord ( ) - > isGrace ( ) ;
2014-09-23 18:07:32 +02:00
pattern . subtypeValid = true ;
}
2014-10-08 04:21:02 +02:00
else if ( type = = Element : : Type : : SLUR_SEGMENT ) {
2016-06-03 10:17:06 +02:00
pattern . subtype = static_cast < int > ( toSlurSegment ( e ) - > spanner ( ) - > type ( ) ) ;
2014-10-08 04:21:02 +02:00
pattern . subtypeValid = true ;
}
2014-09-23 18:07:32 +02:00
else {
pattern . subtype = 0 ;
pattern . subtypeValid = false ;
}
2014-07-16 15:36:20 +02:00
pattern . staffStart = sameStaff ? e - > staffIdx ( ) : - 1 ;
pattern . staffEnd = sameStaff ? e - > staffIdx ( ) + 1 : - 1 ;
2014-07-15 00:28:31 +02:00
pattern . voice = - 1 ;
pattern . system = 0 ;
score - > scanElements ( & pattern , collectMatch ) ;
score - > select ( 0 , SelectType : : SINGLE , 0 ) ;
2016-04-20 10:45:51 +02:00
for ( Element * e : pattern . el )
2014-07-15 00:28:31 +02:00
score - > select ( e , SelectType : : ADD , 0 ) ;
}
2014-08-15 17:20:20 +02:00
//---------------------------------------------------------
// selectSimilarInRange
//---------------------------------------------------------
2014-07-15 00:28:31 +02:00
void Score : : selectSimilarInRange ( Element * e )
{
Element : : Type type = e - > type ( ) ;
ElementPattern pattern ;
Score * score = e - > score ( ) ;
pattern . type = int ( type ) ;
pattern . subtype = 0 ;
2014-07-16 15:36:20 +02:00
pattern . staffStart = selection ( ) . staffStart ( ) ;
pattern . staffEnd = selection ( ) . staffEnd ( ) ;
2014-07-15 00:28:31 +02:00
pattern . voice = - 1 ;
pattern . system = 0 ;
pattern . subtypeValid = false ;
score - > scanElementsInRange ( & pattern , collectMatch ) ;
score - > select ( 0 , SelectType : : SINGLE , 0 ) ;
2015-07-04 11:24:23 +02:00
for ( Element * e : pattern . el ) {
score - > select ( e , SelectType : : ADD , 0 ) ;
2014-07-15 00:28:31 +02:00
}
}
2014-08-15 17:20:20 +02:00
2014-07-15 00:28:31 +02:00
//---------------------------------------------------------
2012-05-26 14:26:10 +02:00
// lassoSelect
//---------------------------------------------------------
void Score : : lassoSelect ( const QRectF & bbox )
{
2014-05-27 10:34:08 +02:00
select ( 0 , SelectType : : SINGLE , 0 ) ;
2012-05-26 14:26:10 +02:00
QRectF fr ( bbox . normalized ( ) ) ;
foreach ( Page * page , _pages ) {
QRectF pr ( page - > bbox ( ) ) ;
QRectF frr ( fr . translated ( - page - > pos ( ) ) ) ;
if ( pr . right ( ) < frr . left ( ) )
continue ;
if ( pr . left ( ) > frr . right ( ) )
break ;
2013-04-29 15:31:22 +02:00
QList < Element * > el = page - > items ( frr ) ;
2012-05-26 14:26:10 +02:00
for ( int i = 0 ; i < el . size ( ) ; + + i ) {
2013-04-29 15:31:22 +02:00
Element * e = el . at ( i ) ;
2012-05-26 14:26:10 +02:00
if ( frr . contains ( e - > abbox ( ) ) ) {
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) ! = Element : : Type : : MEASURE & & e - > selectable ( ) )
2014-05-27 10:34:08 +02:00
select ( e , SelectType : : ADD , 0 ) ;
2012-05-26 14:26:10 +02:00
}
}
}
}
//---------------------------------------------------------
// lassoSelectEnd
//---------------------------------------------------------
void Score : : lassoSelectEnd ( )
{
int noteRestCount = 0 ;
Segment * startSegment = 0 ;
Segment * endSegment = 0 ;
int startStaff = 0x7fffffff ;
int endStaff = 0 ;
2014-12-18 20:41:15 +01:00
const ChordRest * endCR = 0 ;
2012-05-26 14:26:10 +02:00
2016-02-06 22:03:43 +01:00
if ( _selection . elements ( ) . empty ( ) ) {
2014-05-26 13:21:04 +02:00
_selection . setState ( SelState : : NONE ) ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2012-05-26 14:26:10 +02:00
return ;
}
2014-05-26 13:21:04 +02:00
_selection . setState ( SelState : : LIST ) ;
2012-05-26 14:26:10 +02:00
foreach ( const Element * e , _selection . elements ( ) ) {
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) ! = Element : : Type : : NOTE & & e - > type ( ) ! = Element : : Type : : REST )
2012-05-26 14:26:10 +02:00
continue ;
+ + noteRestCount ;
2014-06-24 18:36:02 +02:00
if ( e - > type ( ) = = Element : : Type : : NOTE )
2012-05-26 14:26:10 +02:00
e = e - > parent ( ) ;
Segment * seg = static_cast < const ChordRest * > ( e ) - > segment ( ) ;
2012-08-09 12:12:43 +02:00
if ( ( startSegment = = 0 ) | | ( * seg < * startSegment ) )
2012-05-26 14:26:10 +02:00
startSegment = seg ;
2012-08-09 12:12:43 +02:00
if ( ( endSegment = = 0 ) | | ( * seg > * endSegment ) ) {
2012-05-26 14:26:10 +02:00
endSegment = seg ;
2014-05-31 17:22:45 +02:00
endCR = static_cast < const ChordRest * > ( e ) ;
2012-05-26 14:26:10 +02:00
}
int idx = e - > staffIdx ( ) ;
if ( idx < startStaff )
startStaff = idx ;
if ( idx > endStaff )
endStaff = idx ;
}
if ( noteRestCount > 0 ) {
2014-05-31 17:22:45 +02:00
endSegment = endCR - > nextSegmentAfterCR ( Segment : : Type : : ChordRest
2015-07-04 11:24:23 +02:00
| Segment : : Type : : EndBarLine
| Segment : : Type : : Clef ) ;
2012-05-26 14:26:10 +02:00
_selection . setRange ( startSegment , endSegment , startStaff , endStaff + 1 ) ;
2014-05-24 12:53:50 +02:00
if ( ! _selection . isRange ( ) )
2014-05-26 13:21:04 +02:00
_selection . setState ( SelState : : RANGE ) ;
2015-07-04 11:24:23 +02:00
_selection . updateSelectedElements ( ) ;
2012-05-26 14:26:10 +02:00
}
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// addLyrics
//---------------------------------------------------------
void Score : : addLyrics ( int tick , int staffIdx , const QString & txt )
{
if ( txt . trimmed ( ) . isEmpty ( ) )
return ;
Measure * measure = tick2measure ( tick ) ;
2014-06-25 11:46:10 +02:00
Segment * seg = measure - > findSegment ( Segment : : Type : : ChordRest , tick ) ;
2012-05-26 14:26:10 +02:00
if ( seg = = 0 ) {
2013-07-25 17:22:49 +02:00
qDebug ( " no segment found for lyrics<%s> at tick %d " ,
2012-05-26 14:26:10 +02:00
qPrintable ( txt ) , tick ) ;
return ;
}
2015-06-05 11:19:51 +02:00
bool lyricsAdded = false ;
for ( int voice = 0 ; voice < VOICES ; + + voice ) {
int track = staffIdx * VOICES + voice ;
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( seg - > element ( track ) ) ;
2015-06-05 11:19:51 +02:00
if ( cr ) {
Lyrics * l = new Lyrics ( this ) ;
l - > setXmlText ( txt ) ;
l - > setTrack ( track ) ;
cr - > add ( l ) ;
lyricsAdded = true ;
break ;
}
2012-05-26 14:26:10 +02:00
}
2015-06-05 11:19:51 +02:00
if ( ! lyricsAdded ) {
2013-07-25 17:22:49 +02:00
qDebug ( " no chord/rest for lyrics<%s> at tick %d, staff %d " ,
2015-07-04 11:24:23 +02:00
qPrintable ( txt ) , tick , staffIdx ) ;
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
// setTempo
// convenience function to access TempoMap
//---------------------------------------------------------
void Score : : setTempo ( Segment * segment , qreal tempo )
{
setTempo ( segment - > tick ( ) , tempo ) ;
}
void Score : : setTempo ( int tick , qreal tempo )
{
tempomap ( ) - > setTempo ( tick , tempo ) ;
_playlistDirty = true ;
}
//---------------------------------------------------------
// removeTempo
//---------------------------------------------------------
void Score : : removeTempo ( int tick )
{
tempomap ( ) - > delTempo ( tick ) ;
_playlistDirty = true ;
}
//---------------------------------------------------------
// setPause
//---------------------------------------------------------
void Score : : setPause ( int tick , qreal seconds )
{
tempomap ( ) - > setPause ( tick , seconds ) ;
_playlistDirty = true ;
}
//---------------------------------------------------------
// tempo
//---------------------------------------------------------
qreal Score : : tempo ( int tick ) const
{
return tempomap ( ) - > tempo ( tick ) ;
}
//---------------------------------------------------------
// loWidth
//---------------------------------------------------------
qreal Score : : loWidth ( ) const
{
2015-11-16 14:24:47 +01:00
return pageFormat ( ) - > size ( ) . width ( ) * DPI ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// loHeight
//---------------------------------------------------------
qreal Score : : loHeight ( ) const
{
2015-11-16 14:24:47 +01:00
return pageFormat ( ) - > size ( ) . height ( ) * DPI ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// cmdSelectAll
//---------------------------------------------------------
void Score : : cmdSelectAll ( )
{
2013-10-06 16:43:43 +02:00
if ( _measures . size ( ) = = 0 )
return ;
2014-08-20 19:18:27 +02:00
deselectAll ( ) ;
2014-11-11 06:16:30 +01:00
Measure * first = firstMeasureMM ( ) ;
if ( ! first )
return ;
Measure * last = lastMeasureMM ( ) ;
selectRange ( first , 0 ) ;
selectRange ( last , nstaves ( ) - 1 ) ;
2016-03-02 13:20:19 +01:00
setUpdateAll ( ) ;
2016-04-18 18:11:51 +02:00
update ( ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// cmdSelectSection
//---------------------------------------------------------
void Score : : cmdSelectSection ( )
{
Segment * s = _selection . startSegment ( ) ;
if ( s = = 0 )
return ;
MeasureBase * sm = s - > measure ( ) ;
MeasureBase * em = sm ;
while ( sm - > prev ( ) ) {
if ( sm - > prev ( ) - > sectionBreak ( ) )
break ;
sm = sm - > prev ( ) ;
}
while ( em - > next ( ) ) {
if ( em - > sectionBreak ( ) )
break ;
em = em - > next ( ) ;
}
2014-06-24 18:36:02 +02:00
while ( sm & & sm - > type ( ) ! = Element : : Type : : MEASURE )
2012-05-26 14:26:10 +02:00
sm = sm - > next ( ) ;
2014-06-24 18:36:02 +02:00
while ( em & & em - > type ( ) ! = Element : : Type : : MEASURE )
2012-05-26 14:26:10 +02:00
em = em - > next ( ) ;
if ( sm = = 0 | | em = = 0 )
return ;
2016-06-03 10:17:06 +02:00
_selection . setRange ( toMeasure ( sm ) - > first ( ) , toMeasure ( em ) - > last ( ) , 0 , nstaves ( ) ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// undo
//---------------------------------------------------------
void Score : : undo ( UndoCommand * cmd ) const
{
2016-03-10 10:41:31 +01:00
undoStack ( ) - > push ( cmd ) ;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// linkId
//---------------------------------------------------------
int Score : : linkId ( )
{
2016-03-10 10:41:31 +01:00
return ( masterScore ( ) - > _linkId ) + + ;
2012-05-26 14:26:10 +02:00
}
2012-09-22 19:40:45 +02:00
// val is a used link id
2012-05-26 14:26:10 +02:00
void Score : : linkId ( int val )
{
2016-03-10 10:41:31 +01:00
Score * s = masterScore ( ) ;
2012-09-22 19:40:45 +02:00
if ( val > = s - > _linkId )
s - > _linkId = val + 1 ; // update unused link id
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// scoreList
// return a list of scores containing the root score
// and all part scores (if there are any)
//---------------------------------------------------------
QList < Score * > Score : : scoreList ( )
{
QList < Score * > scores ;
2016-03-10 10:41:31 +01:00
Score * root = masterScore ( ) ;
2012-05-26 14:26:10 +02:00
scores . append ( root ) ;
2014-11-27 14:50:02 +01:00
for ( const Excerpt * ex : root - > excerpts ( ) ) {
if ( ex - > partScore ( ) )
scores . append ( ex - > partScore ( ) ) ;
}
2012-05-26 14:26:10 +02:00
return scores ;
}
//---------------------------------------------------------
// switchLayer
//---------------------------------------------------------
bool Score : : switchLayer ( const QString & s )
{
int layerIdx = 0 ;
2014-05-31 12:03:21 +02:00
for ( const Layer & l : layer ( ) ) {
2012-05-26 14:26:10 +02:00
if ( s = = l . name ) {
setCurrentLayer ( layerIdx ) ;
return true ;
}
+ + layerIdx ;
}
return false ;
}
2012-06-07 09:24:05 +02:00
//---------------------------------------------------------
// appendPart
//---------------------------------------------------------
void Score : : appendPart ( const QString & name )
{
static InstrumentTemplate defaultInstrument ;
InstrumentTemplate * t ;
t = searchTemplate ( name ) ;
2012-06-08 19:06:52 +02:00
if ( t = = 0 ) {
qDebug ( " appendPart: <%s> not found " , qPrintable ( name ) ) ;
2012-06-07 09:24:05 +02:00
t = & defaultInstrument ;
2012-06-08 19:06:52 +02:00
}
2012-06-07 09:24:05 +02:00
2016-02-06 22:03:43 +01:00
if ( t - > channel . empty ( ) ) {
2012-06-07 09:24:05 +02:00
Channel a ;
a . chorus = 0 ;
a . reverb = 0 ;
a . name = " normal " ;
a . bank = 0 ;
a . volume = 100 ;
2014-12-11 11:35:10 +01:00
a . pan = 64 ; // actually 63.5 for center
2012-06-07 09:24:05 +02:00
t - > channel . append ( a ) ;
}
Part * part = new Part ( this ) ;
part - > initFromInstrTemplate ( t ) ;
int n = nstaves ( ) ;
2012-07-26 14:35:13 +02:00
for ( int i = 0 ; i < t - > nstaves ( ) ; + + i ) {
2014-08-16 13:32:08 +02:00
Staff * staff = new Staff ( this ) ;
staff - > setPart ( part ) ;
2012-06-07 09:24:05 +02:00
staff - > setLines ( t - > staffLines [ i ] ) ;
staff - > setSmall ( t - > smallStaff [ i ] ) ;
if ( i = = 0 ) {
staff - > setBracket ( 0 , t - > bracket [ 0 ] ) ;
2012-07-26 14:35:13 +02:00
staff - > setBracketSpan ( 0 , t - > nstaves ( ) ) ;
2012-06-07 09:24:05 +02:00
}
2015-04-28 22:12:32 +02:00
undoInsertStaff ( staff , i ) ;
2012-06-07 09:24:05 +02:00
}
part - > staves ( ) - > front ( ) - > setBarLineSpan ( part - > nstaves ( ) ) ;
2014-08-16 14:18:06 +02:00
undoInsertPart ( part , n ) ;
2012-06-07 09:24:05 +02:00
fixTicks ( ) ;
2016-03-11 12:18:46 +01:00
masterScore ( ) - > rebuildMidiMapping ( ) ;
2012-06-07 09:24:05 +02:00
}
//---------------------------------------------------------
// appendMeasures
//---------------------------------------------------------
void Score : : appendMeasures ( int n )
{
for ( int i = 0 ; i < n ; + + i )
2014-06-24 18:36:02 +02:00
insertMeasure ( Element : : Type : : MEASURE , 0 , false ) ;
2012-06-07 09:24:05 +02:00
}
2015-04-27 12:59:30 +02:00
# ifdef SCRIPT_INTERFACE
2012-06-07 09:24:05 +02:00
//---------------------------------------------------------
// addText
//---------------------------------------------------------
void Score : : addText ( const QString & type , const QString & txt )
{
MeasureBase * measure = first ( ) ;
2014-06-24 18:36:02 +02:00
if ( measure = = 0 | | measure - > type ( ) ! = Element : : Type : : VBOX ) {
insertMeasure ( Element : : Type : : VBOX , measure ) ;
2012-06-07 09:24:05 +02:00
measure = first ( ) ;
}
Text * text = new Text ( this ) ;
if ( type = = " title " )
2014-05-30 10:13:29 +02:00
text - > setTextStyleType ( TextStyleType : : TITLE ) ;
2012-06-07 09:24:05 +02:00
else if ( type = = " subtitle " )
2014-05-30 10:13:29 +02:00
text - > setTextStyleType ( TextStyleType : : SUBTITLE ) ;
2012-06-07 09:24:05 +02:00
text - > setParent ( measure ) ;
2015-04-27 12:59:30 +02:00
text - > setXmlText ( txt ) ;
2012-06-07 09:24:05 +02:00
undoAddElement ( text ) ;
}
2012-05-26 14:26:10 +02:00
2012-06-28 10:03:19 +02:00
//---------------------------------------------------------
// newCursor
//---------------------------------------------------------
Cursor * Score : : newCursor ( )
{
return new Cursor ( this ) ;
}
2015-04-27 12:59:30 +02:00
# endif
2012-06-28 10:03:19 +02:00
2013-06-20 13:57:15 +02:00
//---------------------------------------------------------
// addSpanner
//---------------------------------------------------------
void Score : : addSpanner ( Spanner * s )
{
2013-07-05 11:23:52 +02:00
_spanner . addSpanner ( s ) ;
2013-06-20 13:57:15 +02:00
}
//---------------------------------------------------------
// removeSpanner
//---------------------------------------------------------
void Score : : removeSpanner ( Spanner * s )
{
2013-07-05 11:23:52 +02:00
_spanner . removeSpanner ( s ) ;
2013-06-20 13:57:15 +02:00
}
2013-06-10 11:03:34 +02:00
//---------------------------------------------------------
// isSpannerStartEnd
// does is spanner start or end at tick position tick
// for track ?
//---------------------------------------------------------
bool Score : : isSpannerStartEnd ( int tick , int track ) const
{
2013-07-05 11:23:52 +02:00
for ( auto i : _spanner . map ( ) ) {
2013-06-20 13:57:15 +02:00
if ( i . second - > track ( ) ! = track )
2013-06-10 11:03:34 +02:00
continue ;
2013-06-20 13:57:15 +02:00
if ( i . second - > tick ( ) = = tick | | i . second - > tick2 ( ) = = tick )
2013-06-10 11:03:34 +02:00
return true ;
}
return false ;
}
2013-12-29 17:33:45 +01:00
void Score : : insertTime ( int tick , int len )
{
2015-02-17 09:36:42 +01:00
for ( Staff * staff : staves ( ) )
staff - > insertTime ( tick , len ) ;
2015-03-13 12:39:38 +01:00
for ( Part * part : parts ( ) )
part - > insertTime ( tick , len ) ;
2013-06-19 16:25:29 +02:00
}
2012-06-28 10:03:19 +02:00
Lyrics multi-system melisma and dashes
Implements melisma and dash lines for lyrics spanning several systems.
The melisma and dash line is based on the `SLine` class and its segments on the `LineSegment` class. Both the whole line and its segments are not selectable, marked as generated and not saved in the score file, which is not changed in any way.
For very wide dash segments, several dashes are drawn; the distance between the dashes is not configurable.
Lyrics layout code in `Measure` class and in `layout.cpp` file has been commented out as the lyrics line layout is all contained in the lyrics.cpp file
The line is registered with the `Score` (to have its layout delayed until all elements are positioned) with a mechanism similar to other `Spanner`'s, but in a different container (`_unmanagedSpanner`), as the owning `Lyrics` should decide when create, register, unregister and delete its line.
The line segments are registered with the `System` they belong to (to have them drawn), in the same way as other `Spanner`'s.
There is code for using the dash metrics of the lyrics font, but it is turned off via a conditional directive, as there does not seem to be a reliable way to determine the dash metrics; conventional values (determined by trials and errors and based on my taste!) are used when the conditional directive is off.
2015-01-11 10:11:44 +01:00
//---------------------------------------------------------
// addUnmanagedSpanner
//---------------------------------------------------------
void Score : : addUnmanagedSpanner ( Spanner * s )
{
_unmanagedSpanner . insert ( s ) ;
}
//---------------------------------------------------------
// removeSpanner
//---------------------------------------------------------
void Score : : removeUnmanagedSpanner ( Spanner * s )
{
_unmanagedSpanner . erase ( s ) ;
}
2013-08-22 18:29:25 +02:00
//---------------------------------------------------------
2013-10-18 12:21:01 +02:00
// setPos
2013-08-22 18:29:25 +02:00
//---------------------------------------------------------
2013-10-18 12:21:01 +02:00
void Score : : setPos ( POS pos , int tick )
2013-08-22 18:29:25 +02:00
{
2013-10-18 12:21:01 +02:00
if ( tick < 0 )
2013-08-22 18:29:25 +02:00
tick = 0 ;
2014-11-13 08:42:16 +01:00
if ( tick ! = _pos [ int ( pos ) ] )
2013-10-18 12:21:01 +02:00
_pos [ int ( pos ) ] = tick ;
2014-11-13 08:42:16 +01:00
// even though tick position might not have changed, layout might have
2014-11-17 16:44:05 +01:00
// so we should update cursor here
// however, we must be careful not to call setPos() again while handling posChanged, or recursion results
2014-11-13 08:42:16 +01:00
emit posChanged ( pos , unsigned ( tick ) ) ;
2013-08-22 18:29:25 +02:00
}
2013-09-19 15:08:54 +02:00
2014-05-22 16:18:35 +02:00
//---------------------------------------------------------
// uniqueStaves
//---------------------------------------------------------
QList < int > Score : : uniqueStaves ( ) const
{
QList < int > sl ;
for ( int staffIdx = 0 ; staffIdx < nstaves ( ) ; + + staffIdx ) {
Staff * s = staff ( staffIdx ) ;
if ( s - > linkedStaves ( ) ) {
bool alreadyInList = false ;
for ( int idx : sl ) {
if ( s - > linkedStaves ( ) - > staves ( ) . contains ( staff ( idx ) ) ) {
alreadyInList = true ;
break ;
}
}
if ( alreadyInList )
continue ;
}
sl . append ( staffIdx ) ;
}
return sl ;
}
2014-05-29 12:13:49 +02:00
//---------------------------------------------------------
// findCR
// find chord/rest <= tick in track
//---------------------------------------------------------
ChordRest * Score : : findCR ( int tick , int track ) const
{
Measure * m = tick2measureMM ( tick ) ;
2014-07-27 16:48:05 +02:00
if ( ! m ) {
qDebug ( " findCR: no measure for tick %d " , tick ) ;
2014-07-27 16:11:59 +02:00
return nullptr ;
2014-07-27 16:48:05 +02:00
}
2014-05-29 12:13:49 +02:00
// attach to first rest all spanner when mmRest
if ( m - > isMMRest ( ) )
tick = m - > tick ( ) ;
2014-06-25 11:46:10 +02:00
Segment * s = m - > first ( Segment : : Type : : ChordRest ) ;
for ( Segment * ns = s ; ; ns = ns - > next ( Segment : : Type : : ChordRest ) ) {
2014-05-29 12:13:49 +02:00
if ( ns = = 0 | | ns - > tick ( ) > tick )
break ;
2016-05-17 22:14:29 +02:00
Element * el = ns - > element ( track ) ;
if ( el & & el - > isRest ( ) & & toRest ( el ) - > isGap ( ) )
continue ;
else if ( el )
2014-05-29 12:13:49 +02:00
s = ns ;
}
2016-05-17 22:14:29 +02:00
Element * el = s - > element ( track ) ;
if ( el & & el - > isRest ( ) & & toRest ( el ) - > isGap ( ) )
s = 0 ;
2014-05-29 12:13:49 +02:00
if ( s )
2016-06-03 10:17:06 +02:00
return toChordRest ( s - > element ( track ) ) ;
2014-05-29 12:13:49 +02:00
return nullptr ;
}
2014-08-18 11:33:17 +02:00
//---------------------------------------------------------
// findCRinStaff
2015-08-12 20:07:29 +02:00
// find last chord/rest on staff that ends before tick
2014-08-18 11:33:17 +02:00
//---------------------------------------------------------
2015-08-12 20:07:29 +02:00
ChordRest * Score : : findCRinStaff ( int tick , int staffIdx ) const
2014-08-18 11:33:17 +02:00
{
2015-08-12 20:07:29 +02:00
int ptick = tick - 1 ;
Measure * m = tick2measureMM ( ptick ) ;
2014-08-18 11:33:17 +02:00
if ( ! m ) {
2015-08-12 20:07:29 +02:00
qDebug ( " findCRinStaff: no measure for tick %d " , ptick ) ;
2014-08-18 11:33:17 +02:00
return nullptr ;
}
// attach to first rest all spanner when mmRest
if ( m - > isMMRest ( ) )
2015-08-12 20:07:29 +02:00
ptick = m - > tick ( ) ;
2014-08-18 11:33:17 +02:00
Segment * s = m - > first ( Segment : : Type : : ChordRest ) ;
2015-08-12 20:07:29 +02:00
int strack = staffIdx * VOICES ;
2014-08-18 11:33:17 +02:00
int etrack = strack + VOICES ;
int actualTrack = strack ;
2015-08-12 20:07:29 +02:00
int lastTick = - 1 ;
2014-08-18 11:33:17 +02:00
for ( Segment * ns = s ; ; ns = ns - > next ( Segment : : Type : : ChordRest ) ) {
2015-08-12 20:07:29 +02:00
if ( ns = = 0 | | ns - > tick ( ) > ptick )
2014-08-18 11:33:17 +02:00
break ;
2015-08-12 20:07:29 +02:00
// found a segment; now find longest cr on this staff that does not overlap tick
2014-08-18 11:33:17 +02:00
for ( int t = strack ; t < etrack ; + + t ) {
2016-06-03 10:17:06 +02:00
ChordRest * cr = toChordRest ( ns - > element ( t ) ) ;
2015-08-12 20:07:29 +02:00
if ( cr ) {
int endTick = cr - > tick ( ) + cr - > actualTicks ( ) ;
2015-08-15 16:26:04 +02:00
// allow fudge factor for tuplets
// TODO: replace with fraction-based calculation
int fudge = cr - > tuplet ( ) ? 5 : 0 ;
if ( endTick + fudge > = lastTick & & endTick - fudge < = tick ) {
2015-08-12 20:07:29 +02:00
s = ns ;
actualTrack = t ;
lastTick = endTick ;
}
2014-08-18 11:33:17 +02:00
}
}
}
if ( s )
2016-06-03 10:17:06 +02:00
return toChordRest ( s - > element ( actualTrack ) ) ;
2014-08-18 11:33:17 +02:00
return nullptr ;
}
2014-08-16 17:01:41 +02:00
//---------------------------------------------------------
// setSoloMute
// called once at opening file, adds soloMute marks
//---------------------------------------------------------
2016-03-11 12:18:46 +01:00
void MasterScore : : setSoloMute ( )
2014-08-16 17:01:41 +02:00
{
for ( int i = 0 ; i < _midiMapping . size ( ) ; i + + ) {
Channel * b = _midiMapping [ i ] . articulation ;
if ( b - > solo ) {
b - > soloMute = false ;
for ( int j = 0 ; j < _midiMapping . size ( ) ; j + + ) {
Channel * a = _midiMapping [ j ] . articulation ;
2015-07-15 18:04:33 +02:00
bool sameMidiMapping = _midiMapping [ i ] . port = = _midiMapping [ j ] . port & & _midiMapping [ i ] . channel = = _midiMapping [ j ] . channel ;
a - > soloMute = ( i ! = j & & ! a - > solo & & ! sameMidiMapping ) ;
a - > solo = ( i = = j | | a - > solo | | sameMidiMapping ) ;
2014-08-16 17:01:41 +02:00
}
}
}
}
2014-11-01 10:52:35 +01:00
//---------------------------------------------------------
// setImportedFilePath
//---------------------------------------------------------
void Score : : setImportedFilePath ( const QString & filePath )
{
_importedFilePath = filePath ;
}
2014-11-14 21:00:36 +01:00
//---------------------------------------------------------
// title
//---------------------------------------------------------
QString Score : : title ( )
{
2014-12-28 18:20:12 +01:00
QString fn ;
2014-11-14 21:00:36 +01:00
Text * t = getText ( TextStyleType : : TITLE ) ;
if ( t )
2015-04-27 12:59:30 +02:00
fn = QTextDocumentFragment : : fromHtml ( t - > xmlText ( ) ) . toPlainText ( ) . replace ( " & " , " & " ) . replace ( " > " , " > " ) . replace ( " < " , " < " ) . replace ( " " " , " \" " ) ;
2014-12-28 18:20:12 +01:00
if ( fn . isEmpty ( ) )
fn = metaTag ( " workTitle " ) ;
if ( fn . isEmpty ( ) )
2016-03-10 10:41:31 +01:00
fn = masterScore ( ) - > fileInfo ( ) - > completeBaseName ( ) ;
2014-12-28 18:20:12 +01:00
2014-11-14 21:00:36 +01:00
if ( fn . isEmpty ( ) )
fn = " Untitled " ;
2014-12-28 18:20:12 +01:00
2014-11-14 21:00:36 +01:00
return fn . simplified ( ) ;
}
2014-12-28 18:20:12 +01:00
//---------------------------------------------------------
// subtitle
//---------------------------------------------------------
QString Score : : subtitle ( )
{
QString fn ;
Text * t = getText ( TextStyleType : : SUBTITLE ) ;
if ( t )
2015-04-27 12:59:30 +02:00
fn = QTextDocumentFragment : : fromHtml ( t - > xmlText ( ) ) . toPlainText ( ) . replace ( " & " , " & " ) . replace ( " > " , " > " ) . replace ( " < " , " < " ) . replace ( " " " , " \" " ) ;
2014-12-28 18:20:12 +01:00
return fn . simplified ( ) ;
}
//---------------------------------------------------------
// composer
//---------------------------------------------------------
QString Score : : composer ( )
{
QString fn ;
Text * t = getText ( TextStyleType : : COMPOSER ) ;
if ( t )
2015-04-27 12:59:30 +02:00
fn = QTextDocumentFragment : : fromHtml ( t - > xmlText ( ) ) . toPlainText ( ) . replace ( " & " , " & " ) . replace ( " > " , " > " ) . replace ( " < " , " < " ) . replace ( " " " , " \" " ) ;
2014-12-28 18:20:12 +01:00
if ( fn . isEmpty ( ) )
fn = metaTag ( " composer " ) ;
return fn . simplified ( ) ;
}
//---------------------------------------------------------
// poet
//---------------------------------------------------------
QString Score : : poet ( )
{
QString fn ;
Text * t = getText ( TextStyleType : : POET ) ;
if ( t )
2015-04-27 12:59:30 +02:00
fn = QTextDocumentFragment : : fromHtml ( t - > xmlText ( ) ) . toPlainText ( ) . replace ( " & " , " & " ) . replace ( " > " , " > " ) . replace ( " < " , " < " ) . replace ( " " " , " \" " ) ;
2014-12-28 18:20:12 +01:00
if ( fn . isEmpty ( ) )
fn = metaTag ( " lyricist " ) ;
if ( fn . isEmpty ( ) )
fn = " " ;
return fn . simplified ( ) ;
}
//---------------------------------------------------------
// nmeasure
//---------------------------------------------------------
int Score : : nmeasures ( )
{
int n = 0 ;
for ( Measure * m = firstMeasure ( ) ; m ; m = m - > nextMeasure ( ) )
n + + ;
return n ;
}
//---------------------------------------------------------
// hasLyrics
//---------------------------------------------------------
bool Score : : hasLyrics ( )
{
Segment : : Type st = Segment : : Type : : ChordRest ;
for ( Segment * seg = firstMeasure ( ) - > first ( st ) ; seg ; seg = seg - > next1 ( st ) ) {
2015-07-04 11:24:23 +02:00
for ( int i = 0 ; i < ntracks ( ) ; + + i ) {
2016-08-17 12:52:35 +02:00
ChordRest * cr = toChordRest ( seg - > element ( i ) ) ;
2016-08-24 14:49:34 +02:00
if ( cr & & ! cr - > lyrics ( ) . empty ( ) )
2014-12-28 18:20:12 +01:00
return true ;
}
}
return false ;
}
//---------------------------------------------------------
// hasHarmonies
//---------------------------------------------------------
bool Score : : hasHarmonies ( )
{
Segment : : Type st = Segment : : Type : : ChordRest ;
for ( Segment * seg = firstMeasure ( ) - > first ( st ) ; seg ; seg = seg - > next1 ( st ) ) {
for ( Element * e : seg - > annotations ( ) ) {
2015-07-02 18:07:21 +02:00
if ( e - > type ( ) = = Element : : Type : : HARMONY )
return true ;
2014-12-28 18:20:12 +01:00
}
}
return false ;
}
2015-07-02 18:07:21 +02:00
//---------------------------------------------------------
// lyricCount
//---------------------------------------------------------
int Score : : lyricCount ( )
{
int count = 0 ;
Segment : : Type st = Segment : : Type : : ChordRest ;
for ( Segment * seg = firstMeasure ( ) - > first ( st ) ; seg ; seg = seg - > next1 ( st ) ) {
2015-07-04 11:24:23 +02:00
for ( int i = 0 ; i < ntracks ( ) ; + + i ) {
2016-08-17 12:52:35 +02:00
ChordRest * cr = toChordRest ( seg - > element ( i ) ) ;
if ( cr )
count + = cr - > lyrics ( ) . size ( ) ;
2015-07-02 18:07:21 +02:00
}
}
return count ;
}
//---------------------------------------------------------
// harmonyCount
//---------------------------------------------------------
int Score : : harmonyCount ( )
{
int count = 0 ;
Segment : : Type st = Segment : : Type : : ChordRest ;
for ( Segment * seg = firstMeasure ( ) - > first ( st ) ; seg ; seg = seg - > next1 ( st ) ) {
for ( Element * e : seg - > annotations ( ) ) {
if ( e - > type ( ) = = Element : : Type : : HARMONY )
count + + ;
}
}
return count ;
}
2016-08-17 12:52:35 +02:00
//---------------------------------------------------------
// extractLyrics
//---------------------------------------------------------
2015-07-02 18:07:21 +02:00
QString Score : : extractLyrics ( )
{
QString result ;
updateRepeatList ( true ) ;
setPlaylistDirty ( ) ;
Segment : : Type st = Segment : : Type : : ChordRest ;
for ( int track = 0 ; track < ntracks ( ) ; track + = VOICES ) {
bool found = false ;
2016-08-24 14:49:34 +02:00
unsigned maxLyrics = 1 ;
2015-07-02 18:07:21 +02:00
for ( Measure * m = firstMeasure ( ) ; m ; m = m - > nextMeasure ( ) ) {
m - > setPlaybackCount ( 0 ) ;
}
// follow the repeat segments
for ( const RepeatSegment * rs : * repeatList ( ) ) {
int startTick = rs - > tick ;
int endTick = startTick + rs - > len ;
for ( Measure * m = tick2measure ( startTick ) ; m ; m = m - > nextMeasure ( ) ) {
int playCount = m - > playbackCount ( ) ;
for ( Segment * seg = m - > first ( st ) ; seg ; seg = seg - > next ( st ) ) {
// consider voice 1 only
2016-08-17 12:52:35 +02:00
ChordRest * cr = toChordRest ( seg - > element ( track ) ) ;
if ( ! cr | | cr - > lyrics ( ) . empty ( ) )
2015-07-02 18:07:21 +02:00
continue ;
2016-08-17 12:52:35 +02:00
if ( cr - > lyrics ( ) . size ( ) > maxLyrics )
maxLyrics = cr - > lyrics ( ) . size ( ) ;
2016-08-25 09:49:19 +02:00
if ( playCount > = int ( cr - > lyrics ( ) . size ( ) ) )
2015-07-02 18:07:21 +02:00
continue ;
2016-08-24 14:49:34 +02:00
Lyrics * l = cr - > lyrics ( playCount , Element : : Placement : : BELOW ) ; // TODO: ABOVE
2015-07-02 18:07:21 +02:00
if ( ! l )
continue ;
found = true ;
QString lyric = l - > plainText ( ) . trimmed ( ) ;
if ( l - > syllabic ( ) = = Lyrics : : Syllabic : : SINGLE | | l - > syllabic ( ) = = Lyrics : : Syllabic : : END )
result + = lyric + " " ;
else if ( l - > syllabic ( ) = = Lyrics : : Syllabic : : BEGIN | | l - > syllabic ( ) = = Lyrics : : Syllabic : : MIDDLE )
result + = lyric ;
}
m - > setPlaybackCount ( m - > playbackCount ( ) + 1 ) ;
if ( m - > tick ( ) + m - > ticks ( ) > = endTick )
break ;
}
}
// consider remaning lyrics
2016-08-25 09:49:19 +02:00
for ( unsigned lyricsNumber = 0 ; lyricsNumber < maxLyrics ; lyricsNumber + + ) {
2015-07-02 18:07:21 +02:00
for ( Measure * m = firstMeasure ( ) ; m ; m = m - > nextMeasure ( ) ) {
2016-08-25 09:49:19 +02:00
unsigned playCount = m - > playbackCount ( ) ;
2015-07-02 18:07:21 +02:00
if ( lyricsNumber > = playCount ) {
for ( Segment * seg = m - > first ( st ) ; seg ; seg = seg - > next ( st ) ) {
// consider voice 1 only
2016-08-17 12:52:35 +02:00
ChordRest * cr = toChordRest ( seg - > element ( track ) ) ;
if ( ! cr | | cr - > lyrics ( ) . empty ( ) )
2015-07-02 18:07:21 +02:00
continue ;
2016-08-17 12:52:35 +02:00
if ( cr - > lyrics ( ) . size ( ) > maxLyrics )
maxLyrics = cr - > lyrics ( ) . size ( ) ;
if ( lyricsNumber > = cr - > lyrics ( ) . size ( ) )
2015-07-02 18:07:21 +02:00
continue ;
2016-08-24 14:49:34 +02:00
Lyrics * l = cr - > lyrics ( lyricsNumber , Element : : Placement : : BELOW ) ; // TODO
2015-07-02 18:07:21 +02:00
if ( ! l )
continue ;
found = true ;
QString lyric = l - > plainText ( ) . trimmed ( ) ;
if ( l - > syllabic ( ) = = Lyrics : : Syllabic : : SINGLE | | l - > syllabic ( ) = = Lyrics : : Syllabic : : END )
result + = lyric + " " ;
else if ( l - > syllabic ( ) = = Lyrics : : Syllabic : : BEGIN | | l - > syllabic ( ) = = Lyrics : : Syllabic : : MIDDLE )
result + = lyric ;
}
}
}
}
if ( found )
result + = " \n \n " ;
}
return result . trimmed ( ) ;
}
2014-12-28 18:20:12 +01:00
//---------------------------------------------------------
// keysig
//---------------------------------------------------------
int Score : : keysig ( )
{
Key result = Key : : C ;
for ( int staffIdx = 0 ; staffIdx < nstaves ( ) ; + + staffIdx ) {
Staff * st = staff ( staffIdx ) ;
Key key = st - > key ( 0 ) ;
2015-06-05 01:53:47 +02:00
if ( st - > staffType ( ) - > group ( ) = = StaffGroup : : PERCUSSION | | st - > keySigEvent ( 0 ) . custom ( ) | | st - > keySigEvent ( 0 ) . isAtonal ( ) ) // ignore percussion and custom / atonal key
2014-12-28 18:20:12 +01:00
continue ;
result = key ;
2015-03-13 11:16:43 +01:00
int diff = st - > part ( ) - > instrument ( ) - > transpose ( ) . chromatic ;
2014-12-28 18:20:12 +01:00
if ( ! styleB ( StyleIdx : : concertPitch ) & & diff )
result = transposeKey ( key , diff ) ;
break ;
}
return int ( result ) ;
}
//---------------------------------------------------------
// duration
//---------------------------------------------------------
int Score : : duration ( )
{
updateRepeatList ( true ) ;
RepeatSegment * rs = repeatList ( ) - > last ( ) ;
return lrint ( utick2utime ( rs - > utick + rs - > len ) ) ;
}
2014-11-15 16:29:48 +01:00
//---------------------------------------------------------
2014-12-09 08:45:30 +01:00
// createRehearsalMarkText
2014-11-15 16:29:48 +01:00
//---------------------------------------------------------
2014-12-09 08:45:30 +01:00
QString Score : : createRehearsalMarkText ( RehearsalMark * current ) const
2014-11-15 16:29:48 +01:00
{
2014-12-09 08:45:30 +01:00
int tick = current - > segment ( ) - > tick ( ) ;
2014-11-15 16:29:48 +01:00
RehearsalMark * before = 0 ;
RehearsalMark * after = 0 ;
for ( Segment * s = firstSegment ( ) ; s ; s = s - > next1 ( ) ) {
for ( Element * e : s - > annotations ( ) ) {
if ( e & & e - > type ( ) = = Element : : Type : : REHEARSAL_MARK ) {
if ( s - > tick ( ) < tick )
2016-06-03 10:17:06 +02:00
before = toRehearsalMark ( e ) ;
2014-11-15 16:29:48 +01:00
else if ( s - > tick ( ) > tick ) {
2016-06-03 10:17:06 +02:00
after = toRehearsalMark ( e ) ;
2014-11-15 16:29:48 +01:00
break ;
}
}
}
if ( after )
break ;
}
QString s = " A " ;
2015-04-27 12:59:30 +02:00
QString s1 = before ? before - > xmlText ( ) : " " ;
QString s2 = after ? after - > xmlText ( ) : " " ;
2014-11-15 16:29:48 +01:00
if ( s1 . isEmpty ( ) )
return s ;
2015-06-08 17:58:07 +02:00
s = nextRehearsalMarkText ( before , current ) ; // try to sequence
if ( s = = current - > xmlText ( ) ) {
// no sequence detected (or current happens to be correct)
return s ;
}
else if ( s = = s2 ) {
// next in sequence already present
if ( s1 [ 0 ] . isLetter ( ) ) {
if ( s1 . size ( ) = = 2 )
s = s1 [ 0 ] + QChar : : fromLatin1 ( s1 [ 1 ] . toLatin1 ( ) + 1 ) ; // BB, BC, CC
else
s = s1 + QChar : : fromLatin1 ( ' 1 ' ) ; // B, B1, C
}
else {
s = s1 + QChar : : fromLatin1 ( ' A ' ) ; // 2, 2A, 3
}
2014-11-15 16:29:48 +01:00
}
return s ;
}
2014-12-09 08:45:30 +01:00
//---------------------------------------------------------
// nextRehearsalMarkText
// finds next rehearsal in sequence established by previous
// Alphabetic sequences:
// A, B, ..., Y, Z, AA, BB, ..., YY, ZZ
// a, b, ..., y, z, aa, bb, ..., yy, zz
// Numeric sequences:
// 1, 2, 3, ...
// If number of previous rehearsal mark matches measure number, assume use of measure numbers throughout
//---------------------------------------------------------
QString Score : : nextRehearsalMarkText ( RehearsalMark * previous , RehearsalMark * current ) const
{
2015-04-27 12:59:30 +02:00
QString previousText = previous - > xmlText ( ) ;
QString fallback = current ? current - > xmlText ( ) : previousText + " ' " ;
2014-12-09 08:45:30 +01:00
if ( previousText . length ( ) = = 1 & & previousText [ 0 ] . isLetter ( ) ) {
// single letter sequence
if ( previousText = = " Z " )
return " AA " ;
else if ( previousText = = " z " )
return " aa " ;
else
return QChar : : fromLatin1 ( previousText [ 0 ] . toLatin1 ( ) + 1 ) ;
}
else if ( previousText . length ( ) = = 2 & & previousText [ 0 ] . isLetter ( ) & & previousText [ 1 ] . isLetter ( ) ) {
// double letter sequence
if ( previousText [ 0 ] = = previousText [ 1 ] ) {
// repeated letter sequence
if ( previousText . toUpper ( ) ! = " ZZ " ) {
QString c = QChar : : fromLatin1 ( previousText [ 0 ] . toLatin1 ( ) + 1 ) ;
return c + c ;
}
else {
return fallback ;
}
}
else {
return fallback ;
}
}
else {
// try to interpret as number
bool ok ;
int n = previousText . toInt ( & ok ) ;
if ( ! ok ) {
return fallback ;
}
else if ( current & & n = = previous - > segment ( ) - > measure ( ) - > no ( ) + 1 ) {
// use measure number
n = current - > segment ( ) - > measure ( ) - > no ( ) + 1 ;
return QString ( " %1 " ) . arg ( n ) ;
}
else {
// use number sequence
n = previousText . toInt ( ) + 1 ;
return QString ( " %1 " ) . arg ( n ) ;
}
}
}
2015-02-13 06:57:37 +01:00
//---------------------------------------------------------
// changeVoice
// moves selected notes into specified voice if possible
//---------------------------------------------------------
void Score : : changeVoice ( int voice )
{
startCmd ( ) ;
QList < Element * > el ;
2015-06-27 20:51:04 +02:00
QList < Element * > oel = selection ( ) . elements ( ) ; // make copy
for ( Element * e : oel ) {
2015-02-13 06:57:37 +01:00
if ( e - > type ( ) = = Element : : Type : : NOTE ) {
2016-06-03 10:17:06 +02:00
Note * note = toNote ( e ) ;
2015-02-13 06:57:37 +01:00
Chord * chord = note - > chord ( ) ;
// TODO - handle ties; for now we skip tied notes
if ( note - > tieFor ( ) | | note - > tieBack ( ) )
continue ;
2015-05-06 00:35:47 +02:00
// move grace notes with main chord only
if ( chord - > isGrace ( ) )
continue ;
2015-02-13 06:57:37 +01:00
if ( chord - > voice ( ) ! = voice ) {
Segment * s = chord - > segment ( ) ;
Measure * m = s - > measure ( ) ;
int notes = chord - > notes ( ) . size ( ) ;
int dstTrack = chord - > staffIdx ( ) * VOICES + voice ;
2016-06-03 10:17:06 +02:00
ChordRest * dstCR = toChordRest ( s - > element ( dstTrack ) ) ;
2015-02-13 06:57:37 +01:00
Chord * dstChord = nullptr ;
// set up destination chord
if ( dstCR & & dstCR - > type ( ) = = Element : : Type : : CHORD & & dstCR - > globalDuration ( ) = = chord - > globalDuration ( ) ) {
// existing chord in destination with correct duration;
// can simply move note in
2016-06-03 10:17:06 +02:00
dstChord = toChord ( dstCR ) ;
2015-02-13 06:57:37 +01:00
}
else if ( dstCR & & dstCR - > type ( ) = = Element : : Type : : REST & & dstCR - > globalDuration ( ) = = chord - > globalDuration ( ) ) {
// existing rest in destination with correct duration;
// replace with chord, then move note in
// this case allows for tuplets, unlike the more general case below
dstChord = new Chord ( this ) ;
dstChord - > setTrack ( dstTrack ) ;
dstChord - > setDurationType ( chord - > durationType ( ) ) ;
dstChord - > setDuration ( chord - > duration ( ) ) ;
dstChord - > setTuplet ( dstCR - > tuplet ( ) ) ;
dstChord - > setParent ( s ) ;
undoRemoveElement ( dstCR ) ;
}
else if ( ! chord - > tuplet ( ) ) {
// rests or gap in destination
// insert new chord if the rests / gap are long enough
// then move note in
ChordRest * pcr = nullptr ;
ChordRest * ncr = nullptr ;
for ( Segment * s2 = m - > first ( Segment : : Type : : ChordRest ) ; s2 ; s2 = s2 - > next ( ) ) {
2015-06-27 20:51:04 +02:00
if ( s2 - > segmentType ( ) ! = Segment : : Type : : ChordRest )
continue ;
2016-06-03 10:17:06 +02:00
ChordRest * cr2 = toChordRest ( s2 - > element ( dstTrack ) ) ;
2015-02-13 06:57:37 +01:00
if ( ! cr2 | | cr2 - > type ( ) = = Element : : Type : : REST )
continue ;
if ( s2 - > tick ( ) < s - > tick ( ) ) {
pcr = cr2 ;
continue ;
}
else if ( s2 - > tick ( ) > = s - > tick ( ) ) {
ncr = cr2 ;
break ;
}
}
int gapStart = pcr ? pcr - > tick ( ) + pcr - > actualTicks ( ) : m - > tick ( ) ;
int gapEnd = ncr ? ncr - > tick ( ) : m - > tick ( ) + m - > ticks ( ) ;
if ( gapStart < = s - > tick ( ) & & gapEnd > = s - > tick ( ) + chord - > actualTicks ( ) ) {
// big enough gap found
dstChord = new Chord ( this ) ;
dstChord - > setTrack ( dstTrack ) ;
dstChord - > setDurationType ( chord - > durationType ( ) ) ;
dstChord - > setDuration ( chord - > duration ( ) ) ;
dstChord - > setParent ( s ) ;
// makeGapVoice will not back-fill an empty voice
if ( voice & & ! dstCR )
expandVoice ( s , /*m->first(Segment::Type::ChordRest,*/ dstTrack ) ;
makeGapVoice ( s , dstTrack , chord - > actualFraction ( ) , s - > tick ( ) ) ;
}
}
// move note to destination chord
if ( dstChord ) {
// create & add new note
Note * newNote = new Note ( * note ) ;
newNote - > setSelected ( false ) ;
newNote - > setParent ( dstChord ) ;
undoAddElement ( newNote ) ;
el . append ( newNote ) ;
// add new chord if one was created
if ( dstChord ! = dstCR )
undoAddCR ( dstChord , m , s - > tick ( ) ) ;
// remove original note
if ( notes > 1 ) {
undoRemoveElement ( note ) ;
}
else if ( notes = = 1 ) {
// create rest to leave behind
Rest * r = new Rest ( this ) ;
r - > setTrack ( chord - > track ( ) ) ;
r - > setDurationType ( chord - > durationType ( ) ) ;
r - > setDuration ( chord - > duration ( ) ) ;
r - > setTuplet ( chord - > tuplet ( ) ) ;
r - > setParent ( s ) ;
2015-05-06 00:35:47 +02:00
// if there were grace notes, move them
for ( Chord * gc : chord - > graceNotes ( ) ) {
Chord * ngc = new Chord ( * gc ) ;
undoRemoveElement ( gc ) ;
ngc - > setParent ( dstChord ) ;
ngc - > setTrack ( dstChord - > track ( ) ) ;
undoAddElement ( ngc ) ;
}
2015-02-13 06:57:37 +01:00
// remove chord, replace with rest
undoRemoveElement ( chord ) ;
undoAddCR ( r , m , s - > tick ( ) ) ;
}
}
}
}
}
2016-02-06 22:03:43 +01:00
if ( ! el . empty ( ) )
2015-02-13 06:57:37 +01:00
selection ( ) . clear ( ) ;
2015-06-27 20:51:04 +02:00
for ( Element * e : el )
2015-02-13 06:57:37 +01:00
select ( e , SelectType : : ADD , - 1 ) ;
2016-03-02 13:20:19 +01:00
setLayoutAll ( ) ;
2015-02-13 06:57:37 +01:00
endCmd ( ) ;
}
2015-02-20 22:30:10 +01:00
//---------------------------------------------------------
// cropPage - crop a single page score to the content
/// margins will be applied on the 4 sides
//---------------------------------------------------------
void Score : : cropPage ( qreal margins )
{
if ( npages ( ) = = 1 ) {
Page * page = pages ( ) [ 0 ] ;
if ( page ) {
QRectF ttbox = page - > tbbox ( ) ;
PageFormat * curFormat = pageFormat ( ) ;
PageFormat f ;
f . copy ( * curFormat ) ;
qreal margin = margins / INCH ;
2015-11-16 14:24:47 +01:00
f . setSize ( QSizeF ( ( ttbox . width ( ) / DPI ) + 2 * margin , ( ttbox . height ( ) / DPI ) + 2 * margin ) ) ;
2015-02-20 22:30:10 +01:00
2015-11-16 14:24:47 +01:00
qreal offset = curFormat - > oddLeftMargin ( ) - ttbox . x ( ) / DPI ;
2015-02-20 22:30:10 +01:00
if ( offset < 0 )
offset = 0.0 ;
f . setOddLeftMargin ( margin + offset ) ;
f . setEvenLeftMargin ( margin + offset ) ;
f . setOddBottomMargin ( margin ) ;
f . setOddTopMargin ( margin ) ;
f . setEvenBottomMargin ( margin ) ;
f . setEvenTopMargin ( margin ) ;
undoChangePageFormat ( & f , spatium ( ) , pageNumberOffset ( ) ) ;
}
}
}
2015-10-01 15:03:32 +02:00
//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
QVariant Score : : getProperty ( P_ID id ) const
{
switch ( id ) {
default :
qDebug ( " Score::getProperty: unhandled id " ) ;
return QVariant ( ) ;
}
}
//---------------------------------------------------------
// setProperty
//---------------------------------------------------------
2016-05-19 12:20:42 +02:00
bool Score : : setProperty ( P_ID id , const QVariant & /*v*/ )
2015-10-01 15:03:32 +02:00
{
switch ( id ) {
default :
qDebug ( " Score::setProperty: unhandled id " ) ;
break ;
}
2016-05-18 15:43:47 +02:00
setLayoutAll ( ) ;
2015-10-01 15:03:32 +02:00
return true ;
}
//---------------------------------------------------------
// propertyDefault
//---------------------------------------------------------
QVariant Score : : propertyDefault ( P_ID id ) const
{
switch ( id ) {
default :
return QVariant ( ) ;
}
}
2016-03-02 13:20:19 +01:00
//---------------------------------------------------------
// setStyle
//---------------------------------------------------------
void Score : : setStyle ( const MStyle & s )
{
if ( style ( ) - > value ( StyleIdx : : spatium ) ! = s . value ( StyleIdx : : spatium ) )
spatiumChanged ( style ( ) - > value ( StyleIdx : : spatium ) . toDouble ( ) , s . value ( StyleIdx : : spatium ) . toDouble ( ) ) ;
_style = s ;
}
2016-03-10 10:41:31 +01:00
//---------------------------------------------------------
// MasterScore
//---------------------------------------------------------
MasterScore : : MasterScore ( )
: Score ( )
{
_tempomap = new TempoMap ;
_sigmap = new TimeSigMap ( ) ;
_undo = new UndoStack ( ) ;
_repeatList = new RepeatList ( this ) ;
_revisions = new Revisions ;
setMasterScore ( this ) ;
2016-06-03 10:17:06 +02:00
// _undoRedo = false;
2016-03-10 10:41:31 +01:00
_omr = 0 ;
_showOmr = false ;
# if defined(Q_OS_WIN)
metaTags ( ) . insert ( " platform " , " Microsoft Windows " ) ;
# elif defined(Q_OS_MAC)
metaTags ( ) . insert ( " platform " , " Apple Macintosh " ) ;
# elif defined(Q_OS_LINUX)
metaTags ( ) . insert ( " platform " , " Linux " ) ;
# else
metaTags ( ) . insert ( " platform " , " Unknown " ) ;
# endif
metaTags ( ) . insert ( " movementNumber " , " " ) ;
metaTags ( ) . insert ( " movementTitle " , " " ) ;
metaTags ( ) . insert ( " workNumber " , " " ) ;
metaTags ( ) . insert ( " workTitle " , " " ) ;
metaTags ( ) . insert ( " arranger " , " " ) ;
metaTags ( ) . insert ( " composer " , " " ) ;
metaTags ( ) . insert ( " lyricist " , " " ) ;
metaTags ( ) . insert ( " poet " , " " ) ;
metaTags ( ) . insert ( " translator " , " " ) ;
metaTags ( ) . insert ( " source " , " " ) ;
metaTags ( ) . insert ( " copyright " , " " ) ;
metaTags ( ) . insert ( " creationDate " , QDate : : currentDate ( ) . toString ( Qt : : ISODate ) ) ;
}
MasterScore : : MasterScore ( const MStyle * s )
: MasterScore { }
{
setStyle ( * s ) ;
}
MasterScore : : ~ MasterScore ( )
{
delete _revisions ;
delete _repeatList ;
delete _undo ;
delete _sigmap ;
delete _tempomap ;
qDeleteAll ( _excerpts ) ;
}
//---------------------------------------------------------
// isSavable
//---------------------------------------------------------
bool MasterScore : : isSavable ( ) const
{
// TODO: check if file can be created if it does not exist
2016-03-11 12:18:46 +01:00
return fileInfo ( ) - > isWritable ( ) | | ! fileInfo ( ) - > exists ( ) ;
2016-03-10 10:41:31 +01:00
}
//---------------------------------------------------------
// setTempomap
//---------------------------------------------------------
void MasterScore : : setTempomap ( TempoMap * tm )
{
delete _tempomap ;
_tempomap = tm ;
}
//---------------------------------------------------------
// setName
//---------------------------------------------------------
2016-03-11 12:18:46 +01:00
void Score : : setName ( const QString & ss )
2016-03-10 10:41:31 +01:00
{
QString s ( ss ) ;
s . replace ( ' / ' , ' _ ' ) ; // for sanity
if ( ! ( s . endsWith ( " .mscz " ) | | s . endsWith ( " .mscx " ) ) )
s + = " .mscz " ;
info . setFile ( s ) ;
}
//---------------------------------------------------------
// removeOmr
//---------------------------------------------------------
void MasterScore : : removeOmr ( )
{
_showOmr = false ;
# ifdef OMR
delete _omr ;
# endif
_omr = 0 ;
}
2016-03-18 09:29:16 +01:00
//---------------------------------------------------------
// addRefresh
//---------------------------------------------------------
void Score : : addRefresh ( const QRectF & r )
{
_updateState . refresh | = r ;
cmdState ( ) . setUpdateMode ( UpdateMode : : Update ) ;
}
2013-05-13 18:49:17 +02:00
}