2012-05-30 17:12:30 +02:00
|
|
|
//=============================================================================
|
2013-04-02 20:46:07 +02:00
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
2012-05-30 17:12:30 +02:00
|
|
|
//
|
2013-04-02 20:46:07 +02:00
|
|
|
// Copyright (C) 2012 Werner Schweer
|
2012-05-30 17:12:30 +02:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
2013-04-02 20:46:07 +02:00
|
|
|
// 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
|
2012-05-30 17:12:30 +02:00
|
|
|
//=============================================================================
|
|
|
|
|
2012-06-05 17:15:46 +02:00
|
|
|
#include "libmscore/score.h"
|
2012-05-30 17:12:30 +02:00
|
|
|
#include "libmscore/chordrest.h"
|
|
|
|
#include "libmscore/chord.h"
|
|
|
|
#include "libmscore/rest.h"
|
|
|
|
#include "libmscore/note.h"
|
|
|
|
#include "libmscore/stafftext.h"
|
|
|
|
#include "libmscore/measure.h"
|
|
|
|
#include "libmscore/repeatlist.h"
|
|
|
|
#include "libmscore/page.h"
|
|
|
|
#include "libmscore/system.h"
|
|
|
|
#include "libmscore/segment.h"
|
2013-10-05 21:09:01 +02:00
|
|
|
#include "libmscore/timesig.h"
|
2012-05-30 17:12:30 +02:00
|
|
|
#include "cursor.h"
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-05-30 17:12:30 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Cursor
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Cursor::Cursor(Score* s)
|
2012-05-30 20:54:26 +02:00
|
|
|
: QObject(0)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2013-07-10 10:33:05 +02:00
|
|
|
_track = 0;
|
|
|
|
_segment = 0;
|
|
|
|
setScore(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cursor::setScore(Score* s)
|
|
|
|
{
|
|
|
|
_score = s;
|
|
|
|
if (_score) {
|
|
|
|
_score->inputState().setTrack(_track);
|
|
|
|
_score->inputState().setSegment(_segment);
|
|
|
|
}
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// rewind
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Cursor::rewind(int type)
|
|
|
|
{
|
|
|
|
if (type == 0) {
|
2012-06-08 19:06:52 +02:00
|
|
|
_segment = 0;
|
2012-05-30 17:12:30 +02:00
|
|
|
Measure* m = _score->firstMeasure();
|
|
|
|
if (m) {
|
2012-08-03 15:54:02 +02:00
|
|
|
_segment = m->first(Segment::SegChordRest);
|
2012-07-18 17:34:34 +02:00
|
|
|
firstChordRestInTrack();
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type == 1) {
|
|
|
|
_segment = _score->selection().startSegment();
|
2012-05-30 20:54:26 +02:00
|
|
|
_track = _score->selection().staffStart() * VOICES;
|
2012-07-18 17:34:34 +02:00
|
|
|
firstChordRestInTrack();
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
else if (type == 2) {
|
|
|
|
_segment = _score->selection().endSegment();
|
2012-07-18 17:34:34 +02:00
|
|
|
_track = (_score->selection().staffEnd() * VOICES) - 1; // be sure _track exists
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
2012-06-08 19:06:52 +02:00
|
|
|
_score->inputState().setTrack(_track);
|
|
|
|
_score->inputState().setSegment(_segment);
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// next
|
|
|
|
// go to next segment
|
|
|
|
// return false if end of score is reached
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Cursor::next()
|
|
|
|
{
|
|
|
|
if (!_segment)
|
|
|
|
return false;
|
2013-06-12 14:23:57 +02:00
|
|
|
_segment = _segment->next1(Segment::SegChordRest);
|
2012-07-18 17:34:34 +02:00
|
|
|
firstChordRestInTrack();
|
2012-06-08 19:06:52 +02:00
|
|
|
_score->inputState().setTrack(_track);
|
|
|
|
_score->inputState().setSegment(_segment);
|
2012-05-30 20:54:26 +02:00
|
|
|
return _segment != 0;
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// nextMeasure
|
|
|
|
// go to first segment of next measure
|
|
|
|
// return false if end of score is reached
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Cursor::nextMeasure()
|
|
|
|
{
|
2012-05-30 20:54:26 +02:00
|
|
|
if (_segment == 0)
|
|
|
|
return false;
|
|
|
|
Measure* m = _segment->measure()->nextMeasure();
|
2012-05-30 17:12:30 +02:00
|
|
|
if (m == 0) {
|
2012-05-30 20:54:26 +02:00
|
|
|
_segment = 0;
|
2012-05-30 17:12:30 +02:00
|
|
|
return false;
|
|
|
|
}
|
2013-06-12 14:23:57 +02:00
|
|
|
_segment = m->first(Segment::SegChordRest);
|
2012-07-18 17:34:34 +02:00
|
|
|
// while (seg && seg->element(_track) == 0)
|
2013-06-12 14:23:57 +02:00
|
|
|
// seg = seg->next1(SegChordRest);
|
2012-07-18 17:34:34 +02:00
|
|
|
firstChordRestInTrack();
|
2012-05-30 20:54:26 +02:00
|
|
|
return _segment != 0;
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-05-30 20:54:26 +02:00
|
|
|
// add
|
2012-05-30 17:12:30 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
void Cursor::add(Element* s)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-05-30 20:54:26 +02:00
|
|
|
if (!_segment)
|
2012-05-30 17:12:30 +02:00
|
|
|
return;
|
2012-05-30 20:54:26 +02:00
|
|
|
s->setTrack(_track);
|
2012-06-07 09:24:05 +02:00
|
|
|
s->setParent(_segment);
|
2013-10-05 21:09:01 +02:00
|
|
|
if (s->isChordRest())
|
2012-06-07 09:24:05 +02:00
|
|
|
s->score()->undoAddCR(static_cast<ChordRest*>(s), _segment->measure(), _segment->tick());
|
2013-10-05 21:09:01 +02:00
|
|
|
else if (s->type() == Element::KEYSIG) {
|
|
|
|
Segment* ns = _segment->measure()->undoGetSegment(Segment::SegKeySig, _segment->tick());
|
|
|
|
s->setParent(ns);
|
|
|
|
_score->undoAddElement(s);
|
|
|
|
}
|
|
|
|
else if (s->type() == Element::TIMESIG) {
|
|
|
|
Measure* m = _segment->measure();
|
|
|
|
int tick = m->tick();
|
|
|
|
_score->cmdAddTimeSig(m, _track, static_cast<TimeSig*>(s), false);
|
|
|
|
m = _score->tick2measure(tick);
|
|
|
|
_segment = m->first(Segment::SegChordRest);
|
|
|
|
firstChordRestInTrack();
|
|
|
|
}
|
2013-10-05 23:13:33 +02:00
|
|
|
else if (s->type() == Element::LAYOUT_BREAK) {
|
|
|
|
Measure* m = _segment->measure();
|
|
|
|
s->setParent(m);
|
|
|
|
_score->undoAddElement(s);
|
|
|
|
}
|
2013-10-05 21:09:01 +02:00
|
|
|
else {
|
|
|
|
_score->undoAddElement(s);
|
2012-06-07 09:24:05 +02:00
|
|
|
}
|
2012-05-30 17:12:30 +02:00
|
|
|
s->score()->setLayoutAll(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-06-08 19:06:52 +02:00
|
|
|
// addNote
|
2012-05-30 17:12:30 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-06-28 10:03:19 +02:00
|
|
|
Note* Cursor::addNote(int pitch)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-06-28 10:03:19 +02:00
|
|
|
return _score->addPitch(pitch, false);
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-06-08 19:06:52 +02:00
|
|
|
// setDuration
|
2012-05-30 17:12:30 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-06-08 19:06:52 +02:00
|
|
|
void Cursor::setDuration(int z, int n)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-06-08 19:06:52 +02:00
|
|
|
TDuration d(Fraction(z, n));
|
|
|
|
if (!d.isValid())
|
|
|
|
d = TDuration(TDuration::V_QUARTER);
|
|
|
|
_score->inputState().setDuration(d);
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-06-08 19:06:52 +02:00
|
|
|
// tick
|
2012-05-30 17:12:30 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-06-08 19:06:52 +02:00
|
|
|
int Cursor::tick()
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-06-08 19:06:52 +02:00
|
|
|
return (_segment) ? _segment->tick() : 0;
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
2012-09-13 16:10:13 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// time
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
double Cursor::time()
|
|
|
|
{
|
|
|
|
return _score->utick2utime(tick()) * 1000;
|
|
|
|
}
|
|
|
|
|
2012-07-13 11:26:08 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// element
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
Element* Cursor::element() const
|
|
|
|
{
|
|
|
|
return _segment ? _segment->element(_track) : 0;
|
|
|
|
}
|
|
|
|
|
2012-07-13 11:26:08 +02:00
|
|
|
//---------------------------------------------------------
|
2013-08-21 19:53:24 +02:00
|
|
|
// measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure* Cursor::measure() const
|
|
|
|
{
|
|
|
|
return _segment ? _segment->measure() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-07-13 11:26:08 +02:00
|
|
|
// setTrack
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
void Cursor::setTrack(int v)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-05-30 20:54:26 +02:00
|
|
|
_track = v;
|
|
|
|
int tracks = _score->nstaves() * VOICES;
|
|
|
|
if (_track < 0)
|
|
|
|
_track = 0;
|
|
|
|
else if (_track >= tracks)
|
|
|
|
_track = tracks - 1;
|
2012-06-08 19:06:52 +02:00
|
|
|
_score->inputState().setTrack(_track);
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
2012-07-13 11:26:08 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setStaffIdx
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
void Cursor::setStaffIdx(int v)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-05-30 20:54:26 +02:00
|
|
|
_track = v * VOICES + _track % VOICES;
|
|
|
|
int tracks = _score->nstaves() * VOICES;
|
|
|
|
if (_track < 0)
|
|
|
|
_track = 0;
|
|
|
|
else if (_track >= tracks)
|
|
|
|
_track = tracks - 1;
|
2012-06-08 19:06:52 +02:00
|
|
|
_score->inputState().setTrack(_track);
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
2012-05-30 20:54:26 +02:00
|
|
|
|
2012-07-13 11:26:08 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setVoice
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
void Cursor::setVoice(int v)
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-05-30 20:54:26 +02:00
|
|
|
_track = (_track / VOICES) * VOICES + v;
|
|
|
|
int tracks = _score->nstaves() * VOICES;
|
|
|
|
if (_track < 0)
|
|
|
|
_track = 0;
|
|
|
|
else if (_track >= tracks)
|
|
|
|
_track = tracks - 1;
|
2012-06-08 19:06:52 +02:00
|
|
|
_score->inputState().setTrack(_track);
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
2012-07-13 11:26:08 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// staffIdx
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
int Cursor::staffIdx() const
|
|
|
|
{
|
|
|
|
return _track / VOICES;
|
|
|
|
}
|
|
|
|
|
2012-07-13 11:26:08 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// voice
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-05-30 20:54:26 +02:00
|
|
|
int Cursor::voice() const
|
2012-05-30 17:12:30 +02:00
|
|
|
{
|
2012-05-30 20:54:26 +02:00
|
|
|
return _track % VOICES;
|
2012-05-30 17:12:30 +02:00
|
|
|
}
|
|
|
|
|
2012-07-18 17:34:34 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// nextInTrack
|
|
|
|
// go to first segment at or after _segment which has notes / rests in _track
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
inline void Cursor::firstChordRestInTrack()
|
|
|
|
{
|
2012-07-26 16:07:23 +02:00
|
|
|
while (_segment && _segment->element(_track) == 0)
|
2013-06-12 14:23:57 +02:00
|
|
|
_segment = _segment->next1(Segment::SegChordRest);
|
2012-07-18 17:34:34 +02:00
|
|
|
}
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|