EventSelection * SymbolInsertionCommand::getSubsequentSelection() { EventSelection *selection = new EventSelection(getSegment()); selection->addEvent(getLastInsertedEvent()); return selection; }
// Select exactly the beat-defining events, including any extra notes // this command inserted. // @author Tom Breton (Tehom) EventSelection * SelectAddEvenNotesCommand::getSubsequentSelection() { RG_DEBUG << "SelectAddEvenNotesCommand::getSubsequentSelection" << endl; EventSelection *selection = new EventSelection(getSegment()); RG_DEBUG << (int)m_beatEventVector.size() << "elements in m_beatEventVector" << endl; // Add the beat events we found to the selection for (BeatEventVector::iterator i = m_beatEventVector.begin(); i != m_beatEventVector.end(); ++i) { BeatEvent &beatEvent = *i; // Skip ties selection->addEvent(beatEvent.m_event, false); } // Also add any events that we made. RG_DEBUG << (int)m_eventsAdded.size() << "elements in redoEvents" << endl; for (EventVector::const_iterator i = m_eventsAdded.begin(); i != m_eventsAdded.end(); ++i) { Event *e = *i; // Skip ties selection->addEvent(e, false); } return selection; }
MatrixResizer::FollowMode MatrixResizer::handleMouseMove(const MatrixMouseEvent *e) { if (!e) return NoFollow; setBasicContextHelp(); if (!m_currentElement || !m_currentViewSegment) return NoFollow; if (getSnapGrid()->getSnapSetting() != SnapGrid::NoSnap) { setContextHelp(tr("Hold Shift to avoid snapping to beat grid")); } else { clearContextHelp(); } // snap in the closest direction timeT snapTime = e->snappedLeftTime; if (e->snappedRightTime - e->time < e->time - e->snappedLeftTime) { snapTime = e->snappedRightTime; } timeT newDuration = snapTime - m_currentElement->getViewAbsoluteTime(); timeT durationDiff = newDuration - m_currentElement->getViewDuration(); EventSelection* selection = m_scene->getSelection(); if (!selection || selection->getAddedEvents() == 0) return NoFollow; EventSelection::eventcontainer::iterator it = selection->getSegmentEvents().begin(); for (; it != selection->getSegmentEvents().end(); ++it) { MatrixElement *element = 0; ViewElementList::iterator vi = m_currentViewSegment->findEvent(*it); if (vi != m_currentViewSegment->getViewElementList()->end()) { element = static_cast<MatrixElement *>(*vi); } if (!element) continue; timeT t = element->getViewAbsoluteTime(); timeT d = element->getViewDuration(); d = d + durationDiff; if (d < 0) { t = t + d; d = -d; } else if (d == 0) { d = getSnapGrid()->getSnapTime(t); } element->reconfigure(t, d); // m_currentStaff->positionElement(element); // } } // m_mParentView->canvas()->update(); return FollowHorizontal; }
CollapseRestsCommand::CollapseRestsCommand (EventSelection &selection) : BasicCommand(getGlobalName(), selection.getSegment(), selection.getStartTime(), selection.getEndTime()) { // nothing else }
/*!!! void MatrixResizer::slotMatrixScrolled(int newX, int newY) { QPoint newP1(newX, newY), oldP1(m_parentView->getCanvasView()->contentsX(), m_parentView->getCanvasView()->contentsY()); QPoint p(newX, newY); if (newP1.x() > oldP1.x()) { p.setX(newX + m_parentView->getCanvasView()->visibleWidth()); } p = m_mParentView->inverseMapPoint(p); int newTime = getSnapGrid()->snapX(p.x()); handleMouseMove(newTime, 0, 0); } */ void MatrixResizer::setBasicContextHelp() { EventSelection *selection = m_scene->getSelection(); if (selection && selection->getAddedEvents() > 1) { setContextHelp(tr("Click and drag to resize selected notes")); } else { setContextHelp(tr("Click and drag to resize a note")); } }
CutAndCloseCommand::CutAndCloseCommand(EventSelection &selection, Clipboard *clipboard) : MacroCommand(getGlobalName()) { addCommand(new CutCommand(selection, clipboard)); addCommand(new CloseCommand(&selection.getSegment(), selection.getEndTime(), selection.getStartTime())); }
void MatrixSelector::setContextHelpFor(const MatrixMouseEvent *e, bool ctrlPressed) { QSettings settings; settings.beginGroup( GeneralOptionsConfigGroup ); if (! qStrToBool( settings.value("toolcontexthelp", "true" ) ) ) { settings.endGroup(); return; } settings.endGroup(); MatrixElement *element = e->element; if (!element) { setContextHelp (tr("Click and drag to select; middle-click and drag to draw new note")); } else { // same logic as in handleLeftButtonPress float x = element->getLayoutX(); float width = element->getWidth(); float resizeStart = int(double(width) * 0.85) + x; // max size of 10 if ((x + width) - resizeStart > 10) resizeStart = x + width - 10; EventSelection *s = m_scene->getSelection(); if (e->sceneX > resizeStart) { if (s && s->getAddedEvents() > 1) { setContextHelp(tr("Click and drag to resize selected notes")); } else { setContextHelp(tr("Click and drag to resize note")); } } else { if (s && s->getAddedEvents() > 1) { if (!ctrlPressed) { setContextHelp(tr("Click and drag to move selected notes; hold Ctrl as well to copy")); } else { setContextHelp(tr("Click and drag to copy selected notes")); } } else { if (!ctrlPressed) { setContextHelp(tr("Click and drag to move note; hold Ctrl as well to copy")); } else { setContextHelp(tr("Click and drag to copy note")); } } } } }
BasicSelectionCommand::BasicSelectionCommand(const QString &name, EventSelection &selection, bool bruteForceRedo) : BasicCommand(name, selection.getSegment(), selection.getStartTime(), selection.getEndTime(), bruteForceRedo) { // nothing }
EventUnquantizeCommand::EventUnquantizeCommand( EventSelection &selection, Quantizer *quantizer) : BasicCommand(tr("Unquantize Events"), selection.getSegment(), selection.getStartTime(), selection.getEndTime(), true), // bruteForceRedo m_quantizer(quantizer), m_selection(&selection) { // nothing else }
void PitchBendSequenceDialog::accept() { /* The user has finished the dialog, other than aborting. */ // We don't enable "OK" if the interval isn't sensible, so // something's badly wrong if this test fails. Q_ASSERT_X(m_startTime < m_endTime, "accept", "got a zero or negative time interval"); /* Save current settings. They'll be the defaults next time. */ saveSettings(); // TRANSLATORS: The arg value will be either a controller name or // Pitchbend, so the resulting text is like "Pitchbend Sequence", // "Expression Sequence", etc. QString controllerName(m_control.getName().data()); QString commandName(tr("%1 Sequence").arg(controllerName)); MacroCommand *macro = new MacroCommand(commandName); if (getReplaceMode() != OnlyAdd) { // Selection initially contains no event, and we add all the // relevant ones. EventSelection *selection = new EventSelection(*m_segment); for (Segment::const_iterator i = m_segment->findTime(m_startTime); i != m_segment->findTime(m_endTime); ++i) { Event *e = *i; if (m_control.matches(e)) { selection->addEvent(e, false); } } // EraseCommand takes ownership of "selection". macro->addCommand(new EraseCommand(*selection)); } if (getReplaceMode() != OnlyErase) { if ((getRampMode() == Linear) && (getStepSizeCalculation() == StepSizeByCount)) { addLinearCountedEvents(macro); } else { addStepwiseEvents(macro); } } CommandHistory::getInstance()->addCommand(macro); QDialog::accept(); }
void MatrixMover::setBasicContextHelp(bool ctrlPressed) { EventSelection *selection = m_scene->getSelection(); if (!selection || selection->getAddedEvents() < 2) { if (!ctrlPressed) { setContextHelp(tr("Click and drag to move a note; hold Ctrl as well to copy it")); } else { setContextHelp(tr("Click and drag to copy a note")); } } else { if (!ctrlPressed) { setContextHelp(tr("Click and drag to move selected notes; hold Ctrl as well to copy")); } else { setContextHelp(tr("Click and drag to copy selected notes")); } } }
CopyCommand::CopyCommand(EventSelection &selection, Clipboard *clipboard) : NamedCommand(getGlobalName()), m_targetClipboard(clipboard) { m_sourceClipboard = new Clipboard; m_savedClipboard = 0; std::string label = selection.getSegment().getLabel(); m_sourceClipboard->newSegment(&selection)->setLabel( appendLabel(label, qstrtostr(tr("(excerpt)")))); }
void MatrixSelector::setViewCurrentSelection(bool always) { if (always) m_previousCollisions.clear(); EventSelection* selection = 0; bool changed = getSelection(selection); if (!changed) { delete selection; return; } if (m_selectionToMerge && selection && m_selectionToMerge->getSegment() == selection->getSegment()) { selection->addFromSelection(m_selectionToMerge); m_scene->setSelection(selection, true); } else if (!m_selectionToMerge) { m_scene->setSelection(selection, true); } }
void MatrixResizer::handleLeftButtonPress(const MatrixMouseEvent *e) { MATRIX_DEBUG << "MatrixResizer::handleLeftButtonPress() : el = " << e->element << endl; if (!e->element) return; m_currentViewSegment = e->viewSegment; m_currentElement = e->element; // 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()); } newSelection->addEvent(event); m_scene->setSelection(newSelection, true); // m_mParentView->canvas()->update(); } else { m_scene->setSingleSelectedEvent(m_currentViewSegment, m_currentElement, true); // m_mParentView->canvas()->update(); } }
AddIndicationCommand::AddIndicationCommand(std::string indicationType, EventSelection &selection) : BasicCommand(getGlobalName(indicationType), selection.getSegment(), std::min(selection.getStartTime(), selection.getNotationStartTime()), std::max(selection.getEndTime(), selection.getNotationEndTime())), m_indicationType(indicationType), m_indicationStart(selection.getNotationStartTime()), m_indicationDuration(selection.getTotalNotationDuration()), m_lastInsertedEvent(0) { if (!canExecute()) { throw CommandFailed //!!! need to use text from trunk/src/gui/editors/notation/NotationView.cpp (but this requires an informal human-readable version of the indication name) (qstrtostr(tr("Can't add identical overlapping indications"))); } }
void MatrixMover::handleMouseRelease(const MatrixMouseEvent *e) { if (!e) return; MATRIX_DEBUG << "MatrixMover::handleMouseRelease() - newPitch = " << e->pitch << endl; if (!m_currentElement || !m_currentViewSegment) return; timeT newTime = m_currentElement->getViewAbsoluteTime() + (e->snappedLeftTime - m_clickSnappedLeftTime); int newPitch = e->pitch; if (newPitch > 127) newPitch = 127; if (newPitch < 0) newPitch = 0; // get a basic pitch difference calculation comparing the current element's // pitch to the pitch the mouse was released at (see note in // handleMouseMove) using BaseProperties::PITCH; timeT diffTime = newTime - m_currentElement->getViewAbsoluteTime(); int diffPitch = 0; if (m_currentElement->event()->has(PITCH)) { diffPitch = newPitch - m_currentElement->event()->get<Int>(PITCH); } EventSelection* selection = m_scene->getSelection(); // factor in transpose to adjust the height calculation long pitchOffset = selection->getSegment().getTranspose(); diffPitch += (pitchOffset * -1); if ((diffTime == 0 && diffPitch == 0) || selection->getAddedEvents() == 0) { for (size_t i = 0; i < m_duplicateElements.size(); ++i) { delete m_duplicateElements[i]->event(); delete m_duplicateElements[i]; } m_duplicateElements.clear(); m_currentElement = 0; return; } if (newPitch != m_lastPlayedPitch) { long velocity = m_widget->getCurrentVelocity(); m_currentElement->event()->get<Int>(BaseProperties::VELOCITY, velocity); m_scene->playNote(m_currentViewSegment->getSegment(), newPitch + (pitchOffset * -1), velocity); m_lastPlayedPitch = newPitch; } QString commandLabel; if (m_quickCopy) { if (selection->getAddedEvents() < 2) { commandLabel = tr("Copy and Move Event"); } else { commandLabel = tr("Copy and Move Events"); } } else { if (selection->getAddedEvents() < 2) { commandLabel = tr("Move Event"); } else { commandLabel = tr("Move Events"); } } MacroCommand *macro = new MacroCommand(commandLabel); EventSelection::eventcontainer::iterator it = selection->getSegmentEvents().begin(); Segment &segment = m_currentViewSegment->getSegment(); EventSelection *newSelection = new EventSelection(segment); timeT normalizeStart = selection->getStartTime(); timeT normalizeEnd = selection->getEndTime(); if (m_quickCopy) { for (size_t i = 0; i < m_duplicateElements.size(); ++i) { timeT time = m_duplicateElements[i]->getViewAbsoluteTime(); timeT endTime = time + m_duplicateElements[i]->getViewDuration(); if (time < normalizeStart) normalizeStart = time; if (endTime > normalizeEnd) normalizeEnd = endTime; macro->addCommand(new MatrixInsertionCommand (segment, time, endTime, m_duplicateElements[i]->event())); delete m_duplicateElements[i]->event(); delete m_duplicateElements[i]; } m_duplicateElements.clear(); m_quickCopy = false; } for (; it != selection->getSegmentEvents().end(); ++it) { timeT newTime = (*it)->getAbsoluteTime() + diffTime; int newPitch = 60; if ((*it)->has(PITCH)) { newPitch = (*it)->get<Int>(PITCH) + diffPitch; } Event *newEvent = 0; if (newTime < segment.getStartTime()) { newTime = segment.getStartTime(); } if (newTime + (*it)->getDuration() >= segment.getEndMarkerTime()) { timeT limit = getSnapGrid()->snapTime (segment.getEndMarkerTime() - 1, SnapGrid::SnapLeft); if (newTime > limit) newTime = limit; timeT newDuration = std::min ((*it)->getDuration(), segment.getEndMarkerTime() - newTime); newEvent = new Event(**it, newTime, newDuration); } else { newEvent = new Event(**it, newTime); } newEvent->set<Int>(BaseProperties::PITCH, newPitch); macro->addCommand(new MatrixModifyCommand(segment, (*it), newEvent, true, false)); newSelection->addEvent(newEvent); } normalizeStart = std::min(normalizeStart, newSelection->getStartTime()); normalizeEnd = std::max(normalizeEnd, newSelection->getEndTime()); macro->addCommand(new NormalizeRestsCommand(segment, normalizeStart, normalizeEnd)); m_scene->setSelection(0, false); CommandHistory::getInstance()->addCommand(macro); m_scene->setSelection(newSelection, false); // m_mParentView->canvas()->update(); m_currentElement = 0; setBasicContextHelp(); }
void SegmentTransposeCommand::processSegment(Segment &segment, bool changeKey, int steps, int semitones, bool transposeSegmentBack) { MacroCommand * macroCommand = this; // TODO delete it somewhere. EventSelection * wholeSegment = new EventSelection(segment, segment.getStartTime(), segment.getEndMarkerTime()); macroCommand->addCommand(new TransposeCommand (semitones, steps, *wholeSegment)); // Key insertion can do transposition, but a C4 to D becomes a D4, while // a C4 to G becomes a G3. Because we let the user specify an explicit number // of octaves to move the notes up/down, we add the keys without transposing // and handle the transposition seperately: if (changeKey) { Rosegarden::Key initialKey = segment.getKeyAtTime(segment.getStartTime()); Rosegarden::Key newInitialKey = initialKey.transpose(semitones, steps); EventSelection::eventcontainer::iterator i; //std::list<KeyInsertionCommand*> commands; for (i = wholeSegment->getSegmentEvents().begin(); i != wholeSegment->getSegmentEvents().end(); ++i) { // transpose key if ((*i)->isa(Rosegarden::Key::EventType)) { Rosegarden::Key trKey = (Rosegarden::Key (**i)).transpose(semitones, steps); //commands.push_front macroCommand->addCommand (new KeyInsertionCommand (segment, (*i)->getAbsoluteTime(), trKey, false, false, false, true)); } } std::list<KeyInsertionCommand*>::iterator ci; //for (ci=commands.begin(); ci!=commands.end(); ci++) //{ // commandHistory->addCommand(*ci); //} KeyInsertionCommand *firstKeyCommand = new KeyInsertionCommand (segment, segment.getStartTime(), newInitialKey, false, false, false, true); //commandHistory->addCommand(firstKeyCommand); macroCommand->addCommand(firstKeyCommand); } if (transposeSegmentBack) { // Transpose segment in opposite direction int newTranspose = segment.getTranspose() - semitones; macroCommand->addCommand(new SegmentChangeTransposeCommand(newTranspose, &segment)); } }
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); } } }
void MatrixResizer::handleMouseRelease(const MatrixMouseEvent *e) { if (!e || !m_currentElement || !m_currentViewSegment) return; // snap in the closest direction timeT snapTime = e->snappedLeftTime; if (e->snappedRightTime - e->time < e->time - e->snappedLeftTime) { snapTime = e->snappedRightTime; } timeT newDuration = snapTime - m_currentElement->getViewAbsoluteTime(); timeT durationDiff = newDuration - m_currentElement->getViewDuration(); EventSelection *selection = m_scene->getSelection(); if (!selection || selection->getAddedEvents() == 0) return; QString commandLabel = tr("Resize Event"); if (selection->getAddedEvents() > 1) commandLabel = tr("Resize Events"); MacroCommand *macro = new MacroCommand(commandLabel); EventSelection::eventcontainer::iterator it = selection->getSegmentEvents().begin(); Segment &segment = m_currentViewSegment->getSegment(); EventSelection *newSelection = new EventSelection(segment); timeT normalizeStart = selection->getStartTime(); timeT normalizeEnd = selection->getEndTime(); for (; it != selection->getSegmentEvents().end(); ++it) { timeT t = (*it)->getAbsoluteTime(); timeT d = (*it)->getDuration(); MATRIX_DEBUG << "MatrixResizer::handleMouseRelease - " << "Time = " << t << ", Duration = " << d << endl; d = d + durationDiff; if (d < 0) { t = t + d; d = -d; } else if (d == 0) { d = getSnapGrid()->getSnapTime(t); } if (t + d > segment.getEndMarkerTime()) { d = segment.getEndMarkerTime() - t; if (d <= 0) { d = segment.getEndMarkerTime(); t = d - getSnapGrid()->getSnapTime(t); } } Event *newEvent = new Event(**it, t, d); macro->addCommand(new MatrixModifyCommand(segment, *it, newEvent, false, false)); newSelection->addEvent(newEvent); } normalizeStart = std::min(normalizeStart, newSelection->getStartTime()); normalizeEnd = std::max(normalizeEnd, newSelection->getEndTime()); macro->addCommand(new NormalizeRestsCommand(segment, normalizeStart, normalizeEnd)); m_scene->setSelection(0, false); CommandHistory::getInstance()->addCommand(macro); m_scene->setSelection(newSelection, false); // m_mParentView->update(); m_currentElement = 0; setBasicContextHelp(); }
MatrixTool::FollowMode MatrixMover::handleMouseMove(const MatrixMouseEvent *e) { if (!e) return NoFollow; MATRIX_DEBUG << "MatrixMover::handleMouseMove() snapped time = " << e->snappedLeftTime << endl; setBasicContextHelp(e->modifiers & Qt::ControlModifier); if (!m_currentElement || !m_currentViewSegment) return NoFollow; if (getSnapGrid()->getSnapSetting() != SnapGrid::NoSnap) { setContextHelp(tr("Hold Shift to avoid snapping to beat grid")); } else { clearContextHelp(); } timeT newTime = m_currentElement->getViewAbsoluteTime() + (e->snappedLeftTime - m_clickSnappedLeftTime); int newPitch = e->pitch; emit hoveredOverNoteChanged(newPitch, true, newTime); // get a basic pitch difference calculation comparing the current element's // pitch to the clicked pitch (this does not take the transpose factor into // account, so in a -9 segment, the initial result winds up being 9 // semitones too low) using BaseProperties::PITCH; int diffPitch = 0; if (m_currentElement->event()->has(PITCH)) { diffPitch = newPitch - m_currentElement->event()->get<Int>(PITCH); } EventSelection* selection = m_scene->getSelection(); // factor in transpose to adjust the height calculation long pitchOffset = selection->getSegment().getTranspose(); diffPitch += (pitchOffset * -1); for (EventSelection::eventcontainer::iterator it = selection->getSegmentEvents().begin(); it != selection->getSegmentEvents().end(); ++it) { MatrixElement *element = 0; ViewElementList::iterator vi = m_currentViewSegment->findEvent(*it); if (vi != m_currentViewSegment->getViewElementList()->end()) { element = static_cast<MatrixElement *>(*vi); } if (!element) continue; timeT diffTime = element->getViewAbsoluteTime() - m_currentElement->getViewAbsoluteTime(); int epitch = 0; if (element->event()->has(PITCH)) { epitch = element->event()->get<Int>(PITCH); } element->reconfigure(newTime + diffTime, element->getViewDuration(), epitch + diffPitch); element->setSelected(true); } if (newPitch != m_lastPlayedPitch) { long velocity = m_widget->getCurrentVelocity(); m_currentElement->event()->get<Int>(BaseProperties::VELOCITY, velocity); m_scene->playNote(m_currentViewSegment->getSegment(), newPitch + (pitchOffset * -1), velocity); m_lastPlayedPitch = newPitch; } return FollowMode(FollowHorizontal | FollowVertical); }