void TrackEditor::deleteSelectedSegments() { SegmentSelection segments = m_compositionView->getSelectedSegments(); if (segments.empty()) return; // Clear the selection before erasing the Segments // the selection points to // m_compositionView->getModel()->clearSelected(); MacroCommand *macro = new MacroCommand(tr("Delete Segments")); // For each selected segment for (SegmentSelection::iterator it = segments.begin(); it != segments.end(); ++it) { macro->addCommand(new SegmentEraseCommand(*it, &m_doc->getAudioFileManager())); } addCommandToHistory(macro); }
void TrackEditor::turnLinkedSegmentsToRealCopies() { RG_DEBUG << "turnLinkedSegmentsToRealCopies()"; SegmentSelection segments = m_compositionView->getSelectedSegments(); if (segments.empty()) return; QString text = tr("Turn %n Linked Segment(s) into Real Copies", "", segments.size()); MacroCommand *macro = new MacroCommand(text); // For each selected segment for (SegmentSelection::iterator it = segments.begin(); it != segments.end(); ++it) { if ((*it)->isLinked()) { macro->addCommand(new SegmentLinkToCopyCommand(*it)); } } addCommandToHistory(macro); }
/// Construct ExpandFigurationCommand /// @author Tom Breton (Tehom) ExpandFigurationCommand::ExpandFigurationCommand(SegmentSelection selection) : MacroCommand(getGlobalName()), m_executed(false) { m_composition = (*selection.begin())->getComposition(); m_newSegments.clear(); initialise(selection); }
SegmentColourCommand::SegmentColourCommand( SegmentSelection &segments, const unsigned int index): NamedCommand(tr("Change Segment Color")), m_newColourIndex(index) { for (SegmentSelection::iterator i = segments.begin(); i != segments.end(); ++i) m_segments.push_back(*i); }
SegmentLabelCommand::SegmentLabelCommand( SegmentSelection &segments, const QString &label): NamedCommand(tr("Label Segments")), m_newLabel(label) { for (SegmentSelection::iterator i = segments.begin(); i != segments.end(); ++i) m_segments.push_back(*i); }
CutCommand::CutCommand(SegmentSelection &selection, Clipboard *clipboard) : MacroCommand(getGlobalName()) { addCommand(new CopyCommand(selection, clipboard)); for (SegmentSelection::iterator i = selection.begin(); i != selection.end(); ++i) { addCommand(new SegmentEraseCommand(*i)); } }
SegmentTransposeCommand::SegmentTransposeCommand(SegmentSelection selection, bool changeKey, int steps, int semitones, bool transposeSegmentBack) : MacroCommand(tr("Change segment transposition")) { //SegmentSelection selection(m_view->getSelection()); for (SegmentSelection::iterator i = selection.begin(); i != selection.end(); ++i) { Segment &segment = **i; processSegment(segment, changeKey, steps, semitones, transposeSegmentBack); } }
SegmentJoinCommand::SegmentJoinCommand(SegmentSelection &segments) : NamedCommand(getGlobalName()), m_newSegment(0), m_detached(false) // true if the old segments are detached, not the new { for (SegmentSelection::iterator i = segments.begin(); i != segments.end(); ++i) { m_oldSegments.push_back(*i); } Q_ASSERT_X(!m_oldSegments.empty(), "SegmentJoinCommand::SegmentJoinCommand()", "No segments to join"); }
CopyCommand::CopyCommand(SegmentSelection &selection, Clipboard *clipboard) : NamedCommand(getGlobalName()), m_targetClipboard(clipboard) { m_sourceClipboard = new Clipboard; m_savedClipboard = 0; for (SegmentSelection::iterator i = selection.begin(); i != selection.end(); ++i) { std::string label = (*i)->getLabel(); m_sourceClipboard->newSegment(*i)->setLabel( appendLabel(label, qstrtostr(tr("(copied)")))); } }
int SegmentSelector::mouseMoveEvent(QMouseEvent *e) { // No need to propagate. e->accept(); QPoint pos = m_canvas->viewportToContents(e->pos()); m_lastMousePos = pos; // If no buttons are pressed, update the context help and bail. // Note: Mouse tracking must be on for this to work. See // QWidget::setMouseTracking(). if (e->buttons() == Qt::NoButton) { setContextHelpFor(pos, e->modifiers()); return RosegardenScrollView::NoFollow; } // If another tool has taken over, delegate. if (m_dispatchTool) return m_dispatchTool->mouseMoveEvent(e); // We only handle the left button. The middle button is handled by // the dispatch tool (segment pencil) or ignored. if (e->buttons() != Qt::LeftButton) return RosegardenScrollView::NoFollow; // If we aren't moving anything, rubber band. if (!getChangingSegment()) { m_canvas->drawSelectionRectPos2(pos); m_canvas->getModel()->selectionHasChanged(); return RosegardenScrollView::FollowHorizontal | RosegardenScrollView::FollowVertical; } // Moving // If the segment that was clicked on isn't selected, bail. if (!m_canvas->getModel()->isSelected(getChangingSegment()->getSegment())) return RosegardenScrollView::NoFollow; const int dx = pos.x() - m_clickPoint.x(); const int dy = pos.y() - m_clickPoint.y(); const int inertiaDistance = 8; // If we've not already exceeded the inertia distance, and we // still haven't, bail. if (!m_passedInertiaEdge && abs(dx) < inertiaDistance && abs(dy) < inertiaDistance) { return RosegardenScrollView::NoFollow; } m_passedInertiaEdge = true; m_canvas->viewport()->setCursor(Qt::SizeAllCursor); #if 0 // ??? Moving to mouseReleaseEvent(). if (m_segmentCopyMode && !m_segmentQuickCopyDone) { // Make copies of the original Segment(s). These copies will // take the place of the originals as the user drags the // the originals to a new location. MacroCommand *macroCommand = 0; if (m_segmentCopyingAsLink) { macroCommand = new MacroCommand( SegmentQuickLinkCommand::getGlobalName()); } else { macroCommand = new MacroCommand( SegmentQuickCopyCommand::getGlobalName()); } SegmentSelection selectedItems = m_canvas->getSelectedSegments(); // for each selected segment for (SegmentSelection::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) { Segment *segment = *it; Command *command = 0; if (m_segmentCopyingAsLink) { command = new SegmentQuickLinkCommand(segment); } else { // if it's a link, copy as link if (segment->isTrulyLinked()) command = new SegmentQuickLinkCommand(segment); else // copy as a non-link segment command = new SegmentQuickCopyCommand(segment); } macroCommand->addCommand(command); } CommandHistory::getInstance()->addCommand(macroCommand); m_canvas->update(); // Make sure we don't do it again. m_segmentQuickCopyDone = true; } #endif setSnapTime(e, SnapGrid::SnapToBeat); // start move on selected items only once if (!m_selectionMoveStarted) { m_selectionMoveStarted = true; m_canvas->getModel()->startChangeSelection( m_segmentCopyMode ? CompositionModelImpl::ChangeCopy : CompositionModelImpl::ChangeMove); // The call to startChangeSelection() generates a new changing segment. // Get it. ChangingSegmentPtr newChangingSegment = m_canvas->getModel()->findChangingSegment( getChangingSegment()->getSegment()); if (newChangingSegment) { // Toss the local "changing" segment since it isn't going to // be moving at all. Swap it for the same changing segment in // CompositionModelImpl. That one *will* be moving and can be // used to drive the guides. setChangingSegment(newChangingSegment); } } // Display help for the Shift key. setContextHelpFor(pos, e->modifiers()); Composition &comp = m_doc->getComposition(); const int startDragTrackPos = m_canvas->grid().getYBin(m_clickPoint.y()); const int currentTrackPos = m_canvas->grid().getYBin(pos.y()); const int trackDiff = currentTrackPos - startDragTrackPos; CompositionModelImpl::ChangingSegmentSet &changingSegments = m_canvas->getModel()->getChangingSegments(); // For each changing segment for (CompositionModelImpl::ChangingSegmentSet::iterator it = changingSegments.begin(); it != changingSegments.end(); ++it) { ChangingSegmentPtr changingSegment = *it; const timeT newStartTime = m_canvas->grid().snapX( changingSegment->savedRect().x() + dx); const int newX = lround( m_canvas->grid().getRulerScale()->getXForTime(newStartTime)); int newTrackPos = m_canvas->grid().getYBin( changingSegment->savedRect().y()) + trackDiff; // Limit to [0, comp.getNbTracks()-1]. if (newTrackPos < 0) newTrackPos = 0; if (newTrackPos > static_cast<int>(comp.getNbTracks()) - 1) newTrackPos = comp.getNbTracks() - 1; const int newY = m_canvas->grid().getYBinCoordinate(newTrackPos); changingSegment->moveTo(newX, newY); m_changeMade = true; } if (m_changeMade) { // Make sure the segments are redrawn. // Note: The update() call below doesn't cause the segments to be // redrawn. It just updates from the cache. m_canvas->slotUpdateAll(); } // Guides const int guideX = getChangingSegment()->rect().x(); const int guideY = getChangingSegment()->rect().y(); m_canvas->drawGuides(guideX, guideY); // Text Float const timeT guideTime = m_canvas->grid().snapX(guideX); RealTime time = comp.getElapsedRealTime(guideTime); QString msecs; msecs.sprintf("%03d", time.msec()); int bar; int beat; int fraction; int remainder; comp.getMusicalTimeForAbsoluteTime(guideTime, bar, beat, fraction, remainder); QString posString = QString("%1.%2s (%3, %4, %5)"). arg(time.sec).arg(msecs).arg(bar + 1).arg(beat).arg(fraction); m_canvas->drawTextFloat(guideX + 10, guideY - 30, posString); m_canvas->update(); return RosegardenScrollView::FollowHorizontal | RosegardenScrollView::FollowVertical; }
void SegmentSelector::mouseReleaseEvent(QMouseEvent *e) { // We only care about the left and middle mouse buttons. if (e->button() != Qt::LeftButton && e->button() != Qt::MidButton) return; // No need to propagate. e->accept(); QPoint pos = m_canvas->viewportToContents(e->pos()); // If another tool (SegmentPencil or SegmentResizer) has taken // over, delegate. if (m_dispatchTool) { m_dispatchTool->mouseReleaseEvent(e); m_dispatchTool->stow(); // Forget about the tool. // Note that this is not a memory leak. There is only one instance // of each tool stored in BaseToolBox::m_tools. m_dispatchTool = 0; // Back to this tool. ready(); return; } // We only handle the left button. The middle button is handled by // the dispatch tool (segment pencil) or ignored. if (e->button() != Qt::LeftButton) return; // The left button has been released. m_canvas->hideGuides(); m_canvas->hideTextFloat(); // If rubber band mode if (!getChangingSegment()) { m_canvas->hideSelectionRect(); m_canvas->getModel()->finalizeSelectionRect(); m_canvas->getModel()->selectionHasChanged(); return; } m_canvas->viewport()->setCursor(Qt::ArrowCursor); if (m_canvas->getModel()->isSelected(getChangingSegment()->getSegment())) { if (m_changeMade) { MacroCommand *macroCommand = 0; CompositionModelImpl::ChangingSegmentSet &changingSegments = m_canvas->getModel()->getChangingSegments(); if (m_segmentCopyMode) { if (m_segmentCopyingAsLink) { macroCommand = new MacroCommand( tr("Copy %n Segment(s) as link(s)", "", changingSegments.size())); } else { macroCommand = new MacroCommand( tr("Copy %n Segment(s)", "", changingSegments.size())); } } else { macroCommand = new MacroCommand( tr("Move %n Segment(s)", "", changingSegments.size())); } if (m_segmentCopyMode) { // Make copies of the original Segment(s). These copies will // take the place of the originals. SegmentSelection selectedItems = m_canvas->getSelectedSegments(); // for each selected segment for (SegmentSelection::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) { Segment *segment = *it; Command *command = 0; if (m_segmentCopyingAsLink) { command = new SegmentQuickLinkCommand(segment); } else { // if it's a link, copy as link if (segment->isTrulyLinked()) command = new SegmentQuickLinkCommand(segment); else // copy as a non-link segment command = new SegmentQuickCopyCommand(segment); } macroCommand->addCommand(command); } } const int startDragTrackPos = m_canvas->grid().getYBin(m_clickPoint.y()); const int currentTrackPos = m_canvas->grid().getYBin(pos.y()); const int trackDiff = currentTrackPos - startDragTrackPos; Composition &comp = m_doc->getComposition(); SegmentReconfigureCommand *segmentReconfigureCommand = new SegmentReconfigureCommand("", &comp); // For each changing segment, add the segment to the // SegmentReconfigureCommand. for (CompositionModelImpl::ChangingSegmentSet::iterator it = changingSegments.begin(); it != changingSegments.end(); ++it) { ChangingSegmentPtr changingSegment = *it; Segment *segment = changingSegment->getSegment(); TrackId origTrackId = segment->getTrack(); int newTrackPos = comp.getTrackPositionById(origTrackId) + trackDiff; // Limit to [0, comp.getNbTracks()-1] if (newTrackPos < 0) newTrackPos = 0; if (newTrackPos > static_cast<int>(comp.getNbTracks()) - 1) newTrackPos = comp.getNbTracks() - 1; Track *newTrack = comp.getTrackByPosition(newTrackPos); int newTrackId = origTrackId; if (newTrack) newTrackId = newTrack->getId(); timeT startTime = changingSegment->getStartTime(m_canvas->grid()); // endTime = startTime + segment duration // We absolutely don't want to snap the end time to // the grid. We want it to remain exactly the same as // it was, but relative to the new start time. timeT endTime = startTime + segment->getEndMarkerTime(false) - segment->getStartTime(); segmentReconfigureCommand->addSegment( segment, startTime, endTime, newTrackId); } macroCommand->addCommand(segmentReconfigureCommand); CommandHistory::getInstance()->addCommand(macroCommand); m_canvas->update(); } m_canvas->getModel()->endChange(); m_canvas->slotUpdateAll(); } // Get ready for the next button press. m_segmentQuickCopyDone = false; m_changeMade = false; m_selectionMoveStarted = false; setChangingSegment(ChangingSegmentPtr()); setContextHelpFor(pos); }
/// 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); } }