timeT MatrixPercussionInsertionCommand::getEffectiveStartTime(Segment &segment, timeT time, Event &event) { timeT startTime = time; int pitch = 0; if (event.has(PITCH)) { pitch = event.get<Int>(PITCH); } Segment::iterator i = segment.findTime(time); while (i != segment.begin()) { --i; if ((*i)->has(PITCH) && (*i)->get <Int>(PITCH) == pitch) { if ((*i)->getAbsoluteTime() < time && (*i)->isa(Note::EventType)) { if ((*i)->getAbsoluteTime() + (*i)->getDuration() > time) { startTime = (*i)->getAbsoluteTime(); } else { break; } } } } return startTime; }
void SegmentLinker::refreshSegment(Segment *seg) { timeT startTime = seg->getStartTime(); eraseNonIgnored(seg,seg->begin(),seg->end()); //find another segment Segment *sourceSeg = 0; Segment *tempClone = 0; LinkedSegmentParamsList::iterator itr; for (itr = m_linkedSegmentParamsList.begin(); itr!= m_linkedSegmentParamsList.end(); ++itr) { LinkedSegmentParams &linkedSegParams = *itr; Segment *other = linkedSegParams.m_linkedSegment; if (other != seg) { sourceSeg = other; break; } } if (!sourceSeg) { //make a temporary clone tempClone = createLinkedSegment(seg); sourceSeg = tempClone; } timeT sourceSegStartTime = sourceSeg->getStartTime(); Segment::const_iterator segitr; for(segitr=sourceSeg->begin(); segitr!=sourceSeg->end(); ++segitr) { const Event *refEvent = *segitr; timeT refEventTime = refEvent->getAbsoluteTime() - sourceSegStartTime; timeT freshEventTime = refEventTime+startTime; insertMappedEvent(seg,refEvent,freshEventTime, seg->getLinkTransposeParams().m_semitones, seg->getLinkTransposeParams().m_steps); } if (tempClone) { delete tempClone; } }
Segment * Clipboard::newSegment(const EventSelection *copyFrom) { // create with clone function so as to inherit track, instrument etc // but clone as a segment only, even if it's actually a linked segment Segment *s = copyFrom->getSegment().clone(false); s->erase(s->begin(), s->end()); const EventSelection::eventcontainer &events(copyFrom->getSegmentEvents()); for (EventSelection::eventcontainer::const_iterator i = events.begin(); i != events.end(); ++i) { s->insert(new Event(**i)); } m_segments.insert(s); m_partial = true; return s; }
void Clipboard::newSegment(const Segment *copyFrom, timeT from, timeT to, bool expandRepeats) { // create with copy ctor so as to inherit track, instrument etc Segment *s = copyFrom->clone(false); // If the segment is within the time range if (from <= s->getStartTime() && to >= s->getEndMarkerTime()) { // Insert the whole thing. m_segments.insert(s); // don't change m_partial as we are inserting a complete segment return; } // Only a portion of the source segment will be used. const timeT segStart = copyFrom->getStartTime(); const timeT segEndMarker = copyFrom->getEndMarkerTime(); timeT segDuration = segEndMarker - segStart; // We can't copy starting prior to the start of the segment. if (from < segStart) from = segStart; int firstRepeat = 0; int lastRepeat = 0; if (!copyFrom->isRepeating() || segDuration <= 0) { expandRepeats = false; } if (expandRepeats) { firstRepeat = (from - segStart) / segDuration; to = std::min(to, copyFrom->getRepeatEndTime()); lastRepeat = (to - segStart) / segDuration; } s->setRepeating(false); if (s->getType() == Segment::Audio) { Composition *c = copyFrom->getComposition(); for (int repeat = firstRepeat; repeat <= lastRepeat; ++repeat) { timeT wrappedFrom = segStart; timeT wrappedTo = segEndMarker; if (!expandRepeats) { wrappedFrom = from; wrappedTo = to; } else { if (repeat == firstRepeat) { wrappedFrom = segStart + (from - segStart) % segDuration; } if (repeat == lastRepeat) { wrappedTo = segStart + (to - segStart) % segDuration; } } if (wrappedFrom > segStart) { if (c) { s->setAudioStartTime (s->getAudioStartTime() + c->getRealTimeDifference(segStart + repeat * segDuration, from)); } s->setStartTime(from); } else { s->setStartTime(segStart + repeat * segDuration); } if (wrappedTo < segEndMarker) { s->setEndMarkerTime(to); if (c) { s->setAudioEndTime (s->getAudioStartTime() + c->getRealTimeDifference(segStart + repeat * segDuration, to)); } } else { s->setEndMarkerTime(segStart + (repeat + 1) * segDuration); } m_segments.insert(s); if (repeat < lastRepeat) { s = copyFrom->clone(false); s->setRepeating(false); } } m_partial = true; return; } // We have a normal (MIDI) segment. s->erase(s->begin(), s->end()); for (int repeat = firstRepeat; repeat <= lastRepeat; ++repeat) { Segment::const_iterator ifrom = copyFrom->begin(); Segment::const_iterator ito = copyFrom->end(); if (!expandRepeats) { ifrom = copyFrom->findTime(from); ito = copyFrom->findTime(to); } else { if (repeat == firstRepeat) { ifrom = copyFrom->findTime (segStart + (from - segStart) % segDuration); } if (repeat == lastRepeat) { ito = copyFrom->findTime (segStart + (to - segStart) % segDuration); } } // For each event in the time range and before the end marker. for (Segment::const_iterator i = ifrom; i != ito && copyFrom->isBeforeEndMarker(i); ++i) { Event *e = (*i)->copyMoving(repeat * segDuration); s->insert(e); } } if (expandRepeats) s->setEndMarkerTime(to); // Make sure the end of the segment doesn't go past the end of the range. // Need to use the end marker time from the original segment, not s, // because its value may depend on the composition it's in. if (segEndMarker > to) s->setEndMarkerTime(to); // Fix the beginning. timeT firstEventTime = s->getStartTime(); // if the beginning was chopped off and the first event isn't at the start if (from > segStart && firstEventTime > from) { // Expand the beginning to the left so that it starts at the expected // time (from). s->fillWithRests(from, firstEventTime); } // Fix zero-length segments. // if s is zero length if (s->getStartTime() == s->getEndMarkerTime()) { // Figure out what start and end time would look right. timeT finalStartTime = ((segStart > from) ? segStart : from); timeT finalEndTime = ((segEndMarker < to) ? segEndMarker : to); // Fill it up so it appears. s->fillWithRests(finalStartTime, finalEndTime); } m_segments.insert(s); m_partial = true; }
Segment * SegmentJoinCommand::makeSegment(SegmentVec oldSegments) { // We can proceed even if composition is NULL, just normalize // rests will do less. Composition *composition = oldSegments[0]->getComposition(); // Find the leftmost segment's index and the rightmost segment's // index. timeT t0 = oldSegments[0]->getStartTime(); timeT t1 = oldSegments[0]->getEndMarkerTime(); size_t leftmostIndex = 0; size_t rightmostIndex = 0; for (size_t i = 1; i < oldSegments.size(); ++i) { timeT startTime = oldSegments[i]->getStartTime(); if (startTime < t0) { t0 = startTime; leftmostIndex = i; } timeT endMarkerTime = oldSegments[i]->getEndMarkerTime(); if (endMarkerTime > t1) { t1 = endMarkerTime; rightmostIndex = i; } } // Always begin with the leftmost segment to keep in the new segment // any clef or key change found at the start of this segment. Segment *newSegment = oldSegments[leftmostIndex]->clone(false); // drop any events beyond the end marker newSegment->setEndTime(newSegment->getEndMarkerTime()); // that duplicated the leftmost segment; now do the rest // we normalize rests in any overlapping areas timeT overlapStart = 0, overlapEnd = 0; bool haveOverlap = false; for (size_t i = 0; i < oldSegments.size(); ++i) { // Don't add twice the first old segment if (i == leftmostIndex) continue; Segment *s = oldSegments[i]; timeT start = s->getStartTime(), end = s->getEndMarkerTime(); timeT os = 0, oe = 0; bool haveOverlapHere = false; if (start < newSegment->getEndMarkerTime() && end > newSegment->getStartTime()) { haveOverlapHere = true; os = std::max(start, newSegment->getStartTime()); oe = std::min(end, newSegment->getEndMarkerTime()); RG_DEBUG << "overlap here, os = " << os << ", oe = " << oe; } if (haveOverlapHere) { if (haveOverlap) { overlapStart = std::min(overlapStart, os); overlapEnd = std::max(overlapEnd, oe); } else { overlapStart = os; overlapEnd = oe; haveOverlap = true; } } if (start > newSegment->getEndMarkerTime()) { newSegment->setEndMarkerTime(start); } for (Segment::iterator si = s->begin(); ; ++si) { // If we're in the rightmost segment if (i == rightmostIndex) { // Copy all of the events to the end if (si == s->end()) break; } else { // Just copy up to the End Marker of this segment. if (!s->isBeforeEndMarker(si)) break; } // weed out duplicate clefs and keys if ((*si)->isa(Clef::EventType)) { try { Clef newClef(**si); if (newSegment->getClefAtTime ((*si)->getAbsoluteTime() + 1) == newClef) { continue; } } catch (...) { } } if ((*si)->isa(Key::EventType)) { try { Key newKey(**si); if (newSegment->getKeyAtTime ((*si)->getAbsoluteTime() + 1) == newKey) { continue; } } catch (...) { } } newSegment->insert(new Event(**si)); } if (end > newSegment->getEndMarkerTime()) { newSegment->setEndMarkerTime(end); } } if (haveOverlap) { /// normalizeRests doesn't require Composition, but is less /// than ideal without it; newSegment->setComposition(composition); newSegment->normalizeRests(overlapStart, overlapEnd); newSegment->setComposition(0); } return newSegment; }
void MatrixMover::handleLeftButtonPress(const MatrixMouseEvent *e) { MATRIX_DEBUG << "MatrixMover::handleLeftButtonPress() : snapped time = " << e->snappedLeftTime << ", el = " << e->element << endl; if (!e->element) return; // Check the scene's current segment (apparently not necessarily the same // segment referred to by the scene's current view segment) for this event; // return if not found, indicating that this event is from some other, // non-active segment. // // I think notation just makes whatever segment active when you click an // event outside the active segment, and I think that's what this code // attempted to do too. I couldn't get that to work at all. This is better // than being able to click on non-active elements to create new events by // accident, and will probably fly. Especially since the multi-segment // matrix is new, and we're defining the terms of how it works. Segment *segment = m_scene->getCurrentSegment(); if (!segment) return; bool found = false; for (Segment::iterator i = segment->begin(); i != segment->end(); ++i) { if ((*i) == e->element->event()) found = true; } if (!found) { MATRIX_DEBUG << "Clicked element not owned by active segment. Returning..." << endl; return; } m_currentViewSegment = e->viewSegment; m_currentElement = e->element; m_clickSnappedLeftTime = e->snappedLeftTime; m_quickCopy = (e->modifiers & Qt::ControlModifier); if (!m_duplicateElements.empty()) { for (size_t i = 0; i < m_duplicateElements.size(); ++i) { delete m_duplicateElements[i]->event(); delete m_duplicateElements[i]; } m_duplicateElements.clear(); } // Add this element and allow movement // EventSelection* selection = m_scene->getSelection(); Event *event = m_currentElement->event(); if (selection) { EventSelection *newSelection; if ((e->modifiers & Qt::ShiftModifier) || selection->contains(event)) { newSelection = new EventSelection(*selection); } else { newSelection = new EventSelection(m_currentViewSegment->getSegment()); } // if the selection already contains the event, remove it from the // selection if shift is pressed if (selection->contains(event)) { if (e->modifiers & Qt::ShiftModifier) { newSelection->removeEvent(event); } } else { newSelection->addEvent(event); } m_scene->setSelection(newSelection, true); selection = newSelection; } else { m_scene->setSingleSelectedEvent(m_currentViewSegment, m_currentElement, true); } long velocity = m_widget->getCurrentVelocity(); event->get<Int>(BaseProperties::VELOCITY, velocity); long pitchOffset = m_currentViewSegment->getSegment().getTranspose(); long pitch = 60; event->get<Int>(BaseProperties::PITCH, pitch); // We used to m_scene->playNote() here, but the new concert pitch matrix was // playing chords the first time I clicked a note. Investigation with // KMidiMon revealed two notes firing nearly simultaneously, and with // segments of 0 transpose, they were simply identical to each other. One // of them came from here, and this was the one sounding at the wrong pitch // in transposed segments. I've simply removed it with no apparent ill side // effects, and a problem solved super cheap. m_lastPlayedPitch = pitch; if (m_quickCopy && selection) { for (EventSelection::eventcontainer::iterator i = selection->getSegmentEvents().begin(); i != selection->getSegmentEvents().end(); ++i) { MatrixElement *duplicate = new MatrixElement (m_scene, new Event(**i), m_widget->isDrumMode(), pitchOffset); m_duplicateElements.push_back(duplicate); } } }
/// Initialize ExpandFigurationCommand /// @author Tom Breton (Tehom) void ExpandFigurationCommand::initialise(SegmentSelection selection) { FigurationVector figs; int figSourceID = -1; bool gotFigSource = false; RG_DEBUG << "Initializing ExpandFigurationCommand" << endl; // Update, because if we need new IDs they mustn't duplicate old // IDs, so we must be up to date on what IDs are there. SegmentFigData::SegmentFigDataMap segMap = SegmentFigData::getInvolvedSegments(true, this); for (SegmentSelection::iterator i = selection.begin(); i != selection.end(); ++i) { SegmentFigData& segmentData = SegmentFigData::findOrAdd(segMap, *i); // If it's used here, it's not uninvolved, so unless it's a // figuration, it's a chord source. if (segmentData.isa(SegmentFigData::Uninvolved)) { segmentData.convertType(SegmentFigData::ChordSource); } segmentData.addTagIfNeeded(*i, this); if (gotFigSource || !segmentData.isa(SegmentFigData::FigurationSource)) { continue; } figSourceID = segmentData.getID(); figs = FigurationSourceMap::getFigurations(*i); if (!figs.empty()) { gotFigSource = true; } } // If we didn't find a real figuration, there's nothing to do. if (!gotFigSource) { return; } SourcedFiguration sourcedfigs(figSourceID, figs); // Expand figuration in each segment in selection except the // figuration segment itself. for (SegmentSelection::iterator i = selection.begin(); i != selection.end(); ++i) { Segment *s = (*i); SegmentFigData::SegmentFigDataMap::iterator it = segMap.find(*i); Q_ASSERT_X(it != segMap.end(), "ExpandFigurationCommand::initialise", "didn't find the segment"); SegmentFigData& segmentData = it->second; if (!segmentData.isa(SegmentFigData::ChordSource)) { continue; } // Make a target segment Segment *target = s->clone(false); // Temporarily attach it to composition so that expand can // work. m_composition->weakAddSegment(target); target->clear(); target->fillWithRests(s->getEndTime()); SegmentFigData::addTag(target, this, SegmentID::Target); m_newSegments.insert(target); /** Add notes to target segment **/ for (Segment::iterator e = s->begin(); e != s->end(); ++e) { // Non-notes they don't imply there's a chord here. // We add them to target segment in case they are // clefs or key changes. if ((*e)->isa(SegmentID::EventType)) { continue; } if (!(*e)->isa(Note::EventType)) { target->insert(new Event(**e)); } } // rawStartTime is the apparent start time before we take bars // into account. We step it along the composition, finding // valid places to expand. Specifically, on bar lines not // already part of an expansion. timeT rawStartTime = s->getStartTime(); while (1) { timeT figurationStartTime = rawStartTimeToExact(rawStartTime); if (rawStartTime >= s->getEndTime()) { break; } timeT timePastFiguration = SegmentFigData::expand(sourcedfigs, ChordSegment(s, segmentData.getID()), target, figurationStartTime); // If we didn't expand, ensure we don't try endlessly at // the same place. if (timePastFiguration == figurationStartTime) { ++timePastFiguration; } rawStartTime = timePastFiguration; } // Detach from composition, because SegmentInsertCommand does // the actual placing m_composition->weakDetachSegment(target); Command *c = new SegmentInsertCommand(m_composition, target, s->getTrack()); addCommand(c); } }
DocumentMetaConfigurationPage::DocumentMetaConfigurationPage(RosegardenDocument *doc, QWidget *parent) : TabbedConfigurationPage(doc, parent) { m_headersPage = new HeadersConfigurationPage(this, doc); addTab(m_headersPage, tr("Headers")); Composition &comp = doc->getComposition(); std::set <TrackId> usedTracks; int audioSegments = 0, internalSegments = 0; for (Composition::iterator ci = comp.begin(); ci != comp.end(); ++ci) { usedTracks.insert((*ci)->getTrack()); if ((*ci)->getType() == Segment::Audio) ++audioSegments; else ++internalSegments; } QFrame *frame = new QFrame(m_tabWidget); frame->setContentsMargins(10, 10, 10, 10); QGridLayout *layout = new QGridLayout(frame); layout->setSpacing(5); layout->addWidget(new QLabel(tr("Filename:"), frame), 0, 0); layout->addWidget(new QLabel(doc->getTitle(), frame), 0, 1); layout->addWidget(new QLabel(tr("Formal duration (to end marker):"), frame), 1, 0); timeT d = comp.getEndMarker(); RealTime rtd = comp.getElapsedRealTime(d); layout->addWidget(new QLabel(durationToString(comp, 0, d, rtd), frame), 1, 1); layout->addWidget(new QLabel(tr("Playing duration:"), frame), 2, 0); d = comp.getDuration(); rtd = comp.getElapsedRealTime(d); layout->addWidget(new QLabel(durationToString(comp, 0, d, rtd), frame), 2, 1); layout->addWidget(new QLabel(tr("Tracks:"), frame), 3, 0); layout->addWidget(new QLabel(tr("%1 used, %2 total") .arg(usedTracks.size()) .arg(comp.getNbTracks()), frame), 3, 1); layout->addWidget(new QLabel(tr("Segments:"), frame), 4, 0); layout->addWidget(new QLabel(tr("%1 MIDI, %2 audio, %3 total") .arg(internalSegments) .arg(audioSegments) .arg(internalSegments + audioSegments), frame), 4, 1); layout->setRowStretch(5, 2); addTab(frame, tr("Statistics")); frame = new QFrame(m_tabWidget); frame->setContentsMargins(10, 10, 10, 10); layout = new QGridLayout(frame); layout->setSpacing(5); QTableWidget *table = new QTableWidget(1, 11, frame); // , "Segment Table" table->setObjectName("StyledTable"); table->setAlternatingRowColors(true); //table->setSelectionMode(QTableWidget::NoSelection); table->setSelectionBehavior( QAbstractItemView::SelectRows ); table->setSelectionMode( QAbstractItemView::SingleSelection ); table->setSortingEnabled(true); table->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr("Type"))); // p1=column table->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr("Track"))); table->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr("Label"))); table->setHorizontalHeaderItem( 3, new QTableWidgetItem( tr("Time"))); table->setHorizontalHeaderItem( 4, new QTableWidgetItem( tr("Duration"))); table->setHorizontalHeaderItem( 5, new QTableWidgetItem( tr("Events"))); table->setHorizontalHeaderItem( 6, new QTableWidgetItem( tr("Polyphony"))); table->setHorizontalHeaderItem( 7, new QTableWidgetItem( tr("Repeat"))); table->setHorizontalHeaderItem( 8, new QTableWidgetItem( tr("Quantize"))); table->setHorizontalHeaderItem( 9, new QTableWidgetItem( tr("Transpose"))); table->setHorizontalHeaderItem( 10, new QTableWidgetItem( tr("Delay"))); //table->setNumRows(audioSegments + internalSegments); table->setRowCount(audioSegments + internalSegments); table->setColumnWidth(0, 50); table->setColumnWidth(1, 50); table->setColumnWidth(2, 150); table->setColumnWidth(3, 80); table->setColumnWidth(4, 80); table->setColumnWidth(5, 80); table->setColumnWidth(6, 80); table->setColumnWidth(7, 80); table->setColumnWidth(8, 80); table->setColumnWidth(9, 80); table->setColumnWidth(10, 80); int i = 0; for (Composition::iterator ci = comp.begin(); ci != comp.end(); ++ci) { Segment *s = *ci; table->setItem(i, 0, new SegmentDataItem (table, s->getType() == Segment::Audio ? tr("Audio") : tr("MIDI"))); table->setItem(i, 1, new SegmentDataItem (table, QString("%1").arg(s->getTrack() + 1))); QPixmap colourPixmap(16, 16); Colour colour = comp.getSegmentColourMap().getColourByIndex(s->getColourIndex()); colourPixmap.fill(GUIPalette::convertColour(colour)); table->setItem(i, 2, new QTableWidgetItem( colourPixmap, strtoqstr(s->getLabel())) ); // new QTableWidgetItem(table, QTableWidgetItem::Never, // strtoqstr(s->getLabel()), // colourPixmap)); table->setItem(i, 3, new SegmentDataItem (table, QString("%1").arg(s->getStartTime()))); table->setItem(i, 4, new SegmentDataItem (table, QString("%1").arg(s->getEndMarkerTime() - s->getStartTime()))); std::set<long> notesOn; std::multimap<timeT, long> noteOffs; int events = 0, notes = 0, poly = 0, maxPoly = 0; for (Segment::iterator si = s->begin(); s->isBeforeEndMarker(si); ++si) { ++events; if ((*si)->isa(Note::EventType)) { ++notes; timeT startTime = (*si)->getAbsoluteTime(); timeT endTime = startTime + (*si)->getDuration(); if (endTime == startTime) continue; while (!noteOffs.empty() && (startTime >= noteOffs.begin()->first)) { notesOn.erase(noteOffs.begin()->second); noteOffs.erase(noteOffs.begin()); } long pitch = 0; (*si)->get<Int>(BaseProperties::PITCH, pitch); notesOn.insert(pitch); noteOffs.insert(std::multimap<timeT, long>::value_type(endTime, pitch)); poly = notesOn.size(); if (poly > maxPoly) maxPoly = poly; } } table->setItem(i, 5, new SegmentDataItem (table, QString("%1").arg(events))); table->setItem(i, 6, new SegmentDataItem (table, QString("%1").arg(maxPoly))); table->setItem(i, 7, new SegmentDataItem (table, s->isRepeating() ? tr("Yes") : tr("No"))); timeT discard; if (s->getQuantizer() && s->hasQuantization()) { timeT unit = s->getQuantizer()->getUnit(); table->setItem(i, 8, new SegmentDataItem (table, NotationStrings::makeNoteMenuLabel (unit, true, discard, false))); } else { table->setItem(i, 8, new SegmentDataItem (table, tr("Off"))); } table->setItem(i, 9, new SegmentDataItem (table, QString("%1").arg(s->getTranspose()))); if (s->getDelay() != 0) { if (s->getRealTimeDelay() != RealTime::zeroTime) { table->setItem(i, 10, new SegmentDataItem (table, QString("%1 + %2 ms") .arg(NotationStrings::makeNoteMenuLabel (s->getDelay(), true, discard, false)) .arg(s->getRealTimeDelay().sec * 1000 + s->getRealTimeDelay().msec()))); } else { table->setItem(i, 10, new SegmentDataItem (table, NotationStrings::makeNoteMenuLabel (s->getDelay(), true, discard, false))); } } else if (s->getRealTimeDelay() != RealTime::zeroTime) { table->setItem(i, 10, new SegmentDataItem (table, QString("%2 ms") .arg(s->getRealTimeDelay().sec * 1000 + s->getRealTimeDelay().msec()))); } else { table->setItem(i, 10, new SegmentDataItem (table, tr("None"))); } ++i; } layout->addWidget(table, 0, 0); addTab(frame, tr("Segment Summary")); }
void AddLayerCommand::execute() { if (!m_segment) return; Segment *layer = new Segment(); layer->setTrack(m_segment->getTrack()); layer->setStartTime(m_segment->getStartTime()); m_composition.addSegment(layer); layer->setEndTime(m_segment->getEndTime()); std::string label = m_segment->getLabel(); label += tr(" - layer").toStdString(); layer->setLabel(label); layer->setHighestPlayable(m_segment->getHighestPlayable()); layer->setLowestPlayable(m_segment->getLowestPlayable()); layer->setTranspose(m_segment->getTranspose()); // fill the segment with rests, so we can make them invisible layer->fillWithRests(m_segment->getStartTime(), m_segment->getEndTime()); for (Segment::iterator i = m_segment->begin(); i != m_segment->end(); ++i) { // copy over any clefs or key signatures, as these are needed to // maintain compatibility between segments if ((*i)->isa(Clef::EventType) || (*i)->isa(Key::EventType)) { layer->insert(new Event(**i)); } } // set everything in the layer segment invisible for (Segment::iterator i = layer->begin(); i != layer->end(); ++i) { (*i)->set<Bool>(BaseProperties::INVISIBLE, true); // raise the heights of alternate voice rests to get them out of the // middle of the staff, where they may be easier to deal with if ((*i)->isa(Note::EventRestType)) (*i)->setMaybe<Int>(BaseProperties::DISPLACED_Y, -1000); } // get the total number of colors in the map int maxColors = m_composition.getSegmentColourMap().size(); // get the color index for the segment used as the template for the new // empty one we're creating int index = m_segment->getColourIndex(); // with the default color map (the only one I care about anymore) a // difference of +5 guarantees enough contrast to make the segment changer // widget, raw note ruler, and track headers show enough contrast to be // useful as an indication that this segment is not the same as the one it // is patterned after index += 5; // if we went past the end of the color map, just roll back to 0, because // this will happen so infrequently in use it's not worth a lot of fancy // handling, and anyway 0 will be a contrast from what's sitting on the end // of the standard color map, so it will still be functional if (index > maxColors) index = 0; layer->setColourIndex(index); // now what other gotchas are there? // now m_segment goes from being the input template to what we'll return if // asked m_segment = layer; m_detached = false; }