Esempio n. 1
0
SegmentSplitCommand::SegmentVec
SegmentSplitCommand::
getNewSegments(Segment *segment, timeT splitTime, bool keepLabel)
{
    Segment * newSegmentA = segment->clone(false);
    Segment * newSegmentB = new Segment();

    newSegmentB->setTrack(segment->getTrack());
    newSegmentB->setStartTime(splitTime);

    // !!! Set Composition?
    
    Event *clefEvent = 0;
    Event *keyEvent = 0;

    // Copy the last occurrence of clef and key
    // from the left hand side of the split (nb. timesig events
    // don't appear in segments, only in composition)
    //
    Segment::iterator it = segment->findTime(splitTime);

    while (it != segment->begin()) {

        --it;

        if (!clefEvent && (*it)->isa(Clef::EventType)) {
            clefEvent = new Event(**it, splitTime);
        }

        if (!keyEvent && (*it)->isa(Key::EventType)) {
            keyEvent = new Event(**it, splitTime);
        }

        if (clefEvent && keyEvent)
            break;
    }

    // Insert relevant meta info if we've found some
    //
    if (clefEvent)
        newSegmentB->insert(clefEvent);

    if (keyEvent)
        newSegmentB->insert(keyEvent);

    // Copy through the Events
    //
    it = segment->findTime(splitTime);

    if (it != segment->end() && (*it)->getAbsoluteTime() > splitTime) {
        newSegmentB->fillWithRests((*it)->getAbsoluteTime());
    }

    while (it != segment->end()) {
        newSegmentB->insert(new Event(**it));
        ++it;
    }
    newSegmentB->setEndTime(segment->getEndTime());
    newSegmentB->setEndMarkerTime(segment->getEndMarkerTime());

    // Set labels
    //
    std::string label = segment->getLabel();
    newSegmentA->setLabel(label);
    newSegmentB->setLabel(label);
    if (!keepLabel) {
        newSegmentA->setLabel(appendLabel(label, qstrtostr(tr("(split)"))));
        newSegmentB->setLabel(appendLabel(label, qstrtostr(tr("(split)"))));
    }

    newSegmentB->setColourIndex(segment->getColourIndex());
    newSegmentB->setTranspose(segment->getTranspose());
    newSegmentB->setDelay(segment->getDelay());

    // Resize left hand Segment
    //
    std::vector<Event *> toErase, toInsert;
    for (Segment::iterator i = newSegmentA->findTime(splitTime);
         i != newSegmentA->end(); ++i) {
        if ((*i)->getAbsoluteTime() >= splitTime) break;
        if ((*i)->getAbsoluteTime() + (*i)->getDuration() > splitTime) {
            Event *e = new Event(**i, (*i)->getAbsoluteTime(),
                                 splitTime - (*i)->getAbsoluteTime());
            toErase.push_back(*i);
            toInsert.push_back(e);
        }
    }

    for (size_t i = 0; i < toErase.size(); ++i) {
        newSegmentA->eraseSingle(toErase[i]);
        delete toErase[i];
    }
    for (size_t i = 0; i < toInsert.size(); ++i) {
        newSegmentA->insert(toInsert[i]);
    }

    newSegmentA->setEndTime(splitTime);
    newSegmentA->setEndMarkerTime(splitTime);
    SegmentVec segmentVec;
    segmentVec.reserve(2);
    segmentVec.push_back(newSegmentA);
    segmentVec.push_back(newSegmentB);
    return segmentVec;
}
Esempio n. 2
0
Segment *
SegmentGroupInsertRangeCommand::
splitRejoin(Segment *segment)
{

    /*
      Initially we have:

      ---|---------
       SSSSSSS
    */

    SegmentVec segmentsAC =
        SegmentSplitCommand::getNewSegments(segment, m_splitTime, true);
    Segment *segmentA = segmentsAC[0];
    Segment *segmentC = segmentsAC[1];


    /*
      Now we have two segments:

      ---|---------
      AAA CCC

    */

    // Move segment C as if inserting the range into composition.
    // This moves its end marker too, etc.
    segmentC->setStartTime(segmentC->getStartTime() + getRangeDuration());

    /*
      Now all of their times are as they will be after
      InsertRangeCommand has executed.

      ---|RANGE|---
      AAA       CCC

    */

    // Join A and C.
    SegmentVec toBeJoined;
    toBeJoined.reserve(2);
    toBeJoined.push_back(segmentA);
    toBeJoined.push_back(segmentC);

    Segment * segmentFinal =
        SegmentJoinCommand::makeSegment(toBeJoined);

    // A and C themselves will never be seen.
    delete segmentA;
    delete segmentC;

    /*
      Now we have one segment in its the final version.  It starts
      before the range and therefore won't be moved by
      OpenOrCloseRangeCommand.

      ---|RANGE|---
      FFFFFFFFFFFF

    */

    return segmentFinal;
}