//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2017 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "musescore.h"
#include "scoreview.h"
#include "texttools.h"
#include "libmscore/chordrest.h"
#include "libmscore/harmony.h"
#include "libmscore/score.h"
#include "libmscore/segment.h"
#include "libmscore/measure.h"
namespace Ms {
//---------------------------------------------------------
// harmonyTab
//---------------------------------------------------------
void ScoreView::harmonyTab(bool back)
{
Harmony* harmony = toHarmony(editData.element);
if (!harmony->parent() || harmony->parent()->type() != ElementType::SEGMENT){
qDebug("harmonyTab: no segment parent");
return;
}
int track = harmony->track();
Segment* segment = static_cast<Segment*>(harmony->parent());
if (!segment) {
qDebug("harmonyTicksTab: no segment");
return;
}
// moving to next/prev measure
Measure* measure = segment->measure();
if (measure) {
if (back)
measure = measure->prevMeasure();
else
measure = measure->nextMeasure();
}
if (!measure) {
qDebug("harmonyTab: no prev/next measure");
return;
}
segment = measure->findSegment(SegmentType::ChordRest, measure->tick());
if (!segment) {
qDebug("harmonyTab: no ChordRest segment as measure");
return;
}
changeState(ViewState::NORMAL);
_score->startCmd();
// search for next chord name
harmony = 0;
foreach(Element* e, segment->annotations()) {
if (e->isHarmony() && e->track() == track) {
Harmony* h = toHarmony(e);
harmony = h;
break;
}
}
if (!harmony) {
harmony = new Harmony(_score);
harmony->setTrack(track);
harmony->setParent(segment);
_score->undoAddElement(harmony);
}
_score->select(harmony, SelectType::SINGLE, 0);
startEdit(harmony, Grip::NO_GRIP);
// mscore->changeState(mscoreState());
adjustCanvasPosition(harmony, false);
//TODO-edit toHarmony(editData.element)->moveCursorToEnd();
_score->update();
}
//---------------------------------------------------------
// harmonyBeatsTab
// manages [;:], moving forward or back to the next beat
// and Space/Shift-Space, to stop at next note, rest, harmony or beat.
//---------------------------------------------------------
void ScoreView::harmonyBeatsTab(bool noterest, bool back)
{
Harmony* harmony = toHarmony(editData.element);
int track = harmony->track();
Segment* segment = toSegment(harmony->parent());
if (!segment) {
qDebug("harmonyBeatsTab: no segment");
return;
}
Measure* measure = segment->measure();
int tick = segment->tick();
if (back && tick == measure->tick()) {
// previous bar, if any
measure = measure->prevMeasure();
if (!measure) {
qDebug("harmonyBeatsTab: no previous measure");
return;
}
}
Fraction f = measure->len();
int ticksPerBeat = f.ticks() / ((f.numerator()>3 && (f.numerator()%3)==0 && f.denominator()>4) ? f.numerator()/3 : f.numerator());
int tickInBar = tick - measure->tick();
int newTick = measure->tick() + ((tickInBar + (back?-1:ticksPerBeat)) / ticksPerBeat) * ticksPerBeat;
// look for next/prev beat, note, rest or chord
for (;;) {
segment = back ? segment->prev1(SegmentType::ChordRest) : segment->next1(SegmentType::ChordRest);
if (!segment || (back ? (segment->tick() < newTick) : (segment->tick() > newTick))) {
// no segment or moved past the beat - create new segment
if (!back && newTick >= measure->tick() + f.ticks()) {
// next bar, if any
measure = measure->nextMeasure();
if (!measure) {
qDebug("harmonyBeatsTab: no next measure");
return;
}
}
segment = new Segment(measure, SegmentType::ChordRest, newTick - measure->tick());
if (!segment) {
qDebug("harmonyBeatsTab: no prev segment");
return;
}
_score->undoAddElement(segment);
break;
}
if (segment->tick() == newTick)
break;
if (noterest) {
int minTrack = (track / VOICES ) * VOICES;
int maxTrack = minTrack + (VOICES-1);
if (segment->findAnnotationOrElement(ElementType::HARMONY, minTrack, maxTrack))
break;
}
}
changeState(ViewState::NORMAL);
_score->startCmd();
// search for next chord name
harmony = 0;
foreach (Element* e, segment->annotations()) {
if (e->isHarmony() && e->track() == track) {
Harmony* h = toHarmony(e);
harmony = h;
break;
}
}
if (!harmony) {
harmony = new Harmony(_score);
harmony->setTrack(track);
harmony->setParent(segment);
_score->undoAddElement(harmony);
}
_score->select(harmony, SelectType::SINGLE, 0);
startEdit(harmony, Grip::NO_GRIP);
mscore->changeState(mscoreState());
adjustCanvasPosition(harmony, false);
//TODO-edit toHarmony(editData.element)->moveCursorToEnd();
_score->update();
}
//---------------------------------------------------------
// harmonyTicksTab
// manages [Ctrl] [1]-[9], moving forward the given number of ticks
//---------------------------------------------------------
void ScoreView::harmonyTicksTab(int ticks)
{
Harmony* harmony = static_cast<Harmony*>(editData.element);
int track = harmony->track();
Segment* segment = static_cast<Segment*>(harmony->parent());
if (!segment) {
qDebug("harmonyTicksTab: no segment");
return;
}
Measure* measure = segment->measure();
int newTick = segment->tick() + ticks;
// find the measure containing the target tick
while (newTick >= measure->tick() + measure->ticks()) {
measure = measure->nextMeasure();
if (!measure) {
qDebug("harmonyTicksTab: no next measure");
return;
}
}
// look for a segment at this tick; if none, create one
while (segment && segment->tick() < newTick)
segment = segment->next1(SegmentType::ChordRest);
if (!segment || segment->tick() > newTick) { // no ChordRest segment at this tick
segment = new Segment(measure, SegmentType::ChordRest, newTick - measure->tick());
if (!segment) {
qDebug("harmonyTicksTab: no next segment");
return;
}
_score->undoAddElement(segment);
}
changeState(ViewState::NORMAL);
_score->startCmd();
// search for next chord name
harmony = 0;
foreach(Element* e, segment->annotations()) {
if (e->type() == ElementType::HARMONY && e->track() == track) {
Harmony* h = static_cast<Harmony*>(e);
harmony = h;
break;
}
}
if (!harmony) {
harmony = new Harmony(_score);
harmony->setTrack(track);
harmony->setParent(segment);
_score->undoAddElement(harmony);
}
_score->select(harmony, SelectType::SINGLE, 0);
startEdit(harmony, Grip::NO_GRIP);
mscore->changeState(mscoreState());
adjustCanvasPosition(harmony, false);
//TODO-edit ((Harmony*)editData.element)->moveCursorToEnd();
_score->update();
}
//---------------------------------------------------------
// harmonyEndEdit
//---------------------------------------------------------
void ScoreView::harmonyEndEdit()
{
Harmony* harmony = static_cast<Harmony*>(editData.element);
if (harmony->empty())
_score->undoRemoveElement(harmony);
}
}
↑ V668 There is no sense in testing the 'segment' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error.
↑ V668 There is no sense in testing the 'segment' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error.