MacroCommand *SummaryTaskGeneralPanel::buildCommand() { MacroCommand *cmd = new MacroCommand(kundo2_i18n("Modify task")); bool modified = false; if (!namefield->isHidden() && m_task.name() != namefield->text()) { cmd->addCommand(new NodeModifyNameCmd(m_task, namefield->text())); modified = true; } if (!leaderfield->isHidden() && m_task.leader() != leaderfield->text()) { cmd->addCommand(new NodeModifyLeaderCmd(m_task, leaderfield->text())); modified = true; } /* if (!descriptionfield->isHidden() && m_task.description() != descriptionfield->text()) { cmd->addCommand(new NodeModifyDescriptionCmd(m_task, descriptionfield->text())); modified = true; }*/ MacroCommand *m = m_description->buildCommand(); if ( m ) { cmd->addCommand( m ); modified = true; } if (!modified) { delete cmd; return 0; } return cmd; }
void TrackEditor::deleteTracks(std::vector<TrackId> tracks) { MacroCommand *macro = new MacroCommand(tr("Delete Tracks")); Composition &comp = m_doc->getComposition(); const SegmentMultiSet &segments = comp.getSegments(); // Delete the segments. // for each track we are deleting for (size_t i = 0; i < tracks.size(); ++i) { const TrackId trackId = tracks[i]; // for each segment in the composition for (SegmentMultiSet::const_iterator segmentIter = segments.begin(); segmentIter != segments.end(); ++segmentIter) { Segment *segment = *segmentIter; // if this segment is in the track if (segment->getTrack() == trackId) { macro->addCommand(new SegmentEraseCommand( segment, &m_doc->getAudioFileManager())); } } } // Delete the tracks. macro->addCommand(new DeleteTracksCommand(&comp, tracks)); addCommandToHistory(macro); }
MacroCommand *TaskCostPanel::buildCommand() { MacroCommand *cmd = new MacroCommand(i18nc("(qtundo-format)", "Modify Task Cost")); bool modified = false; if ((m_oldrunning == 0 && runningAccount->currentIndex() != 0) || (m_oldrunning && m_oldrunning->name() != runningAccount->currentText())) { cmd->addCommand(new NodeModifyRunningAccountCmd(m_task, m_oldrunning, m_accounts.findAccount(runningAccount->currentText()))); modified = true; } if ((m_oldstartup == 0 && startupAccount->currentIndex() != 0) || (m_oldstartup && m_oldstartup->name() != startupAccount->currentText())) { cmd->addCommand(new NodeModifyStartupAccountCmd(m_task, m_oldstartup, m_accounts.findAccount(startupAccount->currentText()))); modified = true; } if ((m_oldshutdown == 0 && shutdownAccount->currentIndex() != 0) || (m_oldshutdown && m_oldshutdown->name() != shutdownAccount->currentText())) { cmd->addCommand(new NodeModifyShutdownAccountCmd(m_task, m_oldshutdown, m_accounts.findAccount(shutdownAccount->currentText()))); modified = true; } double money = m_locale->readMoney(startupCost->text()); if (money != m_task.startupCost()) { cmd->addCommand(new NodeModifyStartupCostCmd(m_task, money)); modified = true; } money = m_locale->readMoney(shutdownCost->text()); if (money != m_task.shutdownCost()) { cmd->addCommand(new NodeModifyShutdownCostCmd(m_task, money)); modified = true; } if (!modified) { delete cmd; return 0; } return cmd; }
MacroCommand *LocaleConfigMoney::buildCommand() { MacroCommand *m = new MacroCommand(); if ( m_locale->currencySymbolExplicit() != m_edMonCurSym->text() ) { m->addCommand( new ModifyCurrencySymolCmd( m_locale, m_edMonCurSym->text() ) ); } if (m_locale->monetaryDecimalPlaces() != m_inMonFraDig->value()) { m->addCommand( new ModifyCurrencyFractionalDigitsCmd( m_locale, m_inMonFraDig->value() ) ); } debugPlan<<"buildCommand:"<<m->isEmpty(); if ( m->isEmpty() ) { delete m; return 0; } return m; }
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); }
MacroCommand *MainProjectDialog::buildCommand() { MacroCommand *m = 0; KUndo2MagicString c = kundo2_i18n("Modify main project"); MacroCommand *cmd = panel->buildCommand(); if (cmd) { if (!m) m = new MacroCommand(c); m->addCommand(cmd); } return m; }
KUndo2Command *LocaleConfigMoneyDialog::buildCommand( Project &project ) { MacroCommand *m = new ModifyProjectLocaleCmd( project, kundo2_i18n( "Modify currency settings" ) ); MacroCommand *cmd = m_panel->buildCommand(); if (cmd) { m->addCommand(cmd); } if ( m->isEmpty() ) { delete m; return 0; } return m; }
MacroCommand *SummaryTaskDialog::buildCommand() { MacroCommand *m = new MacroCommand(kundo2_i18n("Modify Summary Task")); bool modified = false; MacroCommand *cmd = m_generalTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } if (!modified) { delete m; return 0; } return m; }
MacroCommand *StandardWorktimeDialog::buildCommand() { //kDebug(planDbg()); KUndo2MagicString n = kundo2_i18n("Modify Estimate Conversions"); MacroCommand *cmd = 0; if (m_original->year() != dia->inYear()) { if (cmd == 0) cmd = new MacroCommand(n); cmd->addCommand(new ModifyStandardWorktimeYearCmd(m_original, m_original->year(), dia->inYear())); } if (m_original->month() != dia->inMonth()) { if (cmd == 0) cmd = new MacroCommand(n); cmd->addCommand(new ModifyStandardWorktimeMonthCmd(m_original, m_original->month(), dia->inMonth())); } if (m_original->week() != dia->inWeek()) { if (cmd == 0) cmd = new MacroCommand(n); cmd->addCommand(new ModifyStandardWorktimeWeekCmd(m_original, m_original->week(), dia->inWeek())); } if (m_original->day() != dia->inDay()) { if (cmd == 0) cmd = new MacroCommand(n); cmd->addCommand(new ModifyStandardWorktimeDayCmd(m_original, m_original->day(), dia->inDay())); } return cmd; }
MacroCommand *TaskProgressDialog::buildCommand() { MacroCommand *m = new MacroCommand(kundo2_i18n("Modify Task Progress")); bool modified = false; MacroCommand *cmd = m_panel->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } if (!modified) { delete m; return 0; } return m; }
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(); }
MacroCommand *TaskDescriptionPanel::buildCommand() { QString s = i18n("Modify task description"); if ( m_node.type() == Node::Type_Milestone ) { s = i18n("Modify milestone description"); } else if ( m_node.type() == Node::Type_Summarytask ) { s = i18n("Modify summary task description"); } else if ( m_node.type() == Node::Type_Project ) { s = i18n("Modify project description"); } MacroCommand *cmd = new MacroCommand(s); bool modified = false; if ( m_node.description() != descriptionfield->textOrHtml() ) { cmd->addCommand(new NodeModifyDescriptionCmd(m_node, descriptionfield->textOrHtml())); modified = true; } if (!modified) { delete cmd; return 0; } return cmd; }
void ControllerEventsRuler::addControlLine(float x1, float y1, float x2, float y2, bool eraseExistingControllers) { std::cout << "ControllerEventsRuler::addControlLine()"; clearSelectedItems(); // get a timeT for one end point of our line timeT originTime = m_rulerScale->getTimeForX(x1); // get a timeT for the other end point of our line timeT destinationTime = m_rulerScale->getTimeForX(x2); // get a value for one end point of our line long originValue = yToValue(y1); // get a value for the other end point long destinationValue = yToValue(y2); if (originTime == destinationTime || originValue == destinationValue) return; // If the "anchor point" was to the right of the newly clicked destination // point, we're drawing a line from right to left. We simply swap origin // for destination and calculate all lines as drawn from left to right, for // convenience and sanity. if (originTime > destinationTime) { timeT swapTime = originTime; originTime = destinationTime; destinationTime = swapTime; long swapValue = originValue; originValue = destinationValue; destinationValue = swapValue; } // save a list of existing events that occur within the span of the new line // for later deletion, if desired std::vector<Event*> eventsToClear; if (eraseExistingControllers) { for (Segment::iterator si = m_segment->begin(); si != m_segment->end(); ++si) { timeT t = (*si)->getNotationAbsoluteTime(); if (t >= originTime && t <= destinationTime) { eventsToClear.push_back(*si); } } } // rise and run long rise = destinationValue - originValue; timeT run = destinationTime - originTime; std::cout << "Drawing a line from origin time: " << originTime << " to " << destinationTime << " rising from: " << originValue << " to " << destinationValue << " with a rise of: " << rise << " and run of: " << run << std::endl; // avoid divide by 0 potential, rise is always at least 1 if (rise == 0) rise = 1; // are we rising or falling? bool rising = (rise > 0); // always calculate step on a positive value for rise, and make sure it's at // least 1 float step = run / (float)(rising ? rise : rise * -1); // Trying this with pitch bend with a rise approaching the maximum over a // span of around four bars generated over 15,000 pitch bend events! That's // super duper fine resolution, but it's too much for anything to handle. // Let's try to do some sensible thinning without getting too complicated... // bool isPitchBend = (m_controller->getType() == Rosegarden::PitchBend::EventType); int thinningHackCounter = 1; long intermediateValue = originValue; long controllerNumber = 0; if (m_controller) { controllerNumber = m_controller->getControllerValue(); } else { std::cout << "No controller number set. Time to panic! Line drawing aborted." << std::endl; return; } MacroCommand *macro = new MacroCommand(tr("Insert Line of Controllers")); bool failsafe = false; // if we're clearing existing events, add that to the macro command for (std::vector<Event*>::iterator ei = eventsToClear.begin(); ei != eventsToClear.end(); ++ei) { // if the event was a controller or pitch bend, and it is on this ruler, // add it to the list if (((*ei)->isa(Controller::EventType) || (*ei)->isa(PitchBend::EventType)) && isOnThisRuler(*ei)) { bool collapseRests = true; macro->addCommand(new EraseEventCommand(*m_segment, *ei, collapseRests)); } } if (macro->haveCommands()) { CommandHistory::getInstance()->addCommand(macro); macro = new MacroCommand(tr("Insert Line of Controllers")); } for (float i = originTime; i <= destinationTime; i += step) { if (failsafe) continue; if (rising) intermediateValue++; else intermediateValue--; if (rising && intermediateValue > destinationValue) failsafe = true; else if (!rising && intermediateValue < destinationValue) failsafe = true; // std::cout << "creating event at time: " << i << " of value: " << intermediateValue << std::endl; // continue; Event *controllerEvent = new Event(m_controller->getType(), (timeT) i); if (m_controller->getType() == Rosegarden::Controller::EventType) { controllerEvent->set<Rosegarden::Int>(Rosegarden::Controller::VALUE, intermediateValue); controllerEvent->set<Rosegarden::Int>(Rosegarden::Controller::NUMBER, controllerNumber); } else if (m_controller->getType() == Rosegarden::PitchBend::EventType) { // always set the first and last events, then only set every 25th, // 50th, and 75th event for pitch bend if (thinningHackCounter++ > 100) thinningHackCounter = 1; if (thinningHackCounter != 25 && thinningHackCounter != 50 && thinningHackCounter != 75 && i != originTime && i != destinationTime) continue; std::cout << "intermediate value: " << intermediateValue << std::endl; // Convert to PitchBend MSB/LSB int lsb = intermediateValue & 0x7f; int msb = (intermediateValue >> 7) & 0x7f; controllerEvent->set<Rosegarden::Int>(Rosegarden::PitchBend::MSB, msb); controllerEvent->set<Rosegarden::Int>(Rosegarden::PitchBend::LSB, lsb); } if (failsafe) std::cout << "intermediate value: " << intermediateValue << " exceeded target: " << destinationValue << std::endl; macro->addCommand(new EventInsertionCommand (*m_segment, controllerEvent)); } m_moddingSegment = true; CommandHistory::getInstance()->addCommand(macro); m_moddingSegment = false; // How else to re-initialize and bring things into view? I'm missing // something, but this works... init(); }
MacroCommand *AddRelationDialog::buildCommand() { MacroCommand *c = new MacroCommand( kundo2_i18n("Add task dependency") ); c->addCommand( new AddRelationCmd(m_project, m_relation ) ); m_deleterelation = false; // don't delete return c; }
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)); } }
MacroCommand *AddRelationDialog::buildCommand() { MacroCommand *c = new MacroCommand( i18n("Add Relation") ); c->addCommand( new AddRelationCmd(m_project, m_relation ) ); return c; }
MacroCommand *RequestResourcesPanel::buildCommand() { Task *t = m_view->task(); if ( t == 0 ) { return 0; } MacroCommand *cmd = new MacroCommand( i18nc( "(qtundo-format)", "Modify resource allocations" ) ); /*Project *p = */m_view->project(); const QMap<const Resource*, ResourceRequest*> &rmap = m_view->resourceCache(); // First remove all that should be removed for( QMap<const Resource*, ResourceRequest*>::const_iterator rit = rmap.constBegin(); rit != rmap.constEnd(); ++rit ) { if ( rit.value()->units() == 0 ) { ResourceRequest *rr = t->requests().find( rit.key() ); if ( rr ) { cmd->addCommand( new RemoveResourceRequestCmd( rr->parent(), rr ) ); } } } QMap<const ResourceGroup*, ResourceGroupRequest*> groups; // Add/modify const QMap<const ResourceGroup*, ResourceGroupRequest*> &gmap = m_view->groupCache(); for( QMap<const ResourceGroup*, ResourceGroupRequest*>::const_iterator git = gmap.constBegin(); git != gmap.constEnd(); ++git ) { ResourceGroupRequest *gr = t->requests().find( git.key() ); if ( gr == 0 ) { if ( git.value()->units() > 0 ) { gr = new ResourceGroupRequest( const_cast<ResourceGroup*>( git.key() ), git.value()->units() ); cmd->addCommand( new AddResourceGroupRequestCmd( *t, gr ) ); groups[ git.key() ] = gr; } // else nothing } else { cmd->addCommand( new ModifyResourceGroupRequestUnitsCmd( gr, gr->units(), git.value()->units() ) ); } } for( QMap<const Resource*, ResourceRequest*>::const_iterator rit = rmap.constBegin(); rit != rmap.constEnd(); ++rit ) { Resource *resource = const_cast<Resource*>( rit.key() ); ResourceGroup *group = resource->parentGroup(); if ( rit.value()->units() > 0 ) { ResourceRequest *rr = t->requests().find( resource ); if ( rr == 0 ) { ResourceGroupRequest *gr = t->requests().find( group ); if ( gr == 0 ) { if ( groups.contains( group ) ) { gr = groups[ group ]; } else { gr = new ResourceGroupRequest( group, 0 ); groups[ group ] = gr; cmd->addCommand( new AddResourceGroupRequestCmd( *t, gr ) ); } } ResourceRequest *rr = new ResourceRequest( resource, rit.value()->units() ); rr->setRequiredResources( rit.value()->requiredResources() ); cmd->addCommand( new AddResourceRequestCmd( gr, rr ) ); } else { if ( rit.value()->units() != rr->units() ) { cmd->addCommand( new ModifyResourceRequestUnitsCmd( rr, rr->units(), rit.value()->units() ) ); } if ( rit.value()->requiredResources() != rr->requiredResources() ) { cmd->addCommand( new ModifyResourceRequestRequiredCmd( rr, rit.value()->requiredResources() ) ); } } } } if ( cmd->isEmpty() ) { delete cmd; return 0; } return cmd; }
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(); }
void ControlRuler::updateSegment() { // Bring the segment up to date with the ControlRuler's items // A number of different actions take place here: // 1) m_eventSelection is empty // 2) m_eventSelection has events // a) Events in the selection have been modified in value only // b) Events in the selection have moved in time // // Either run through the ruler's EventSelection, updating from each item // or, if there isn't one, go through m_selectedItems timeT start,end; // bool segmentModified = false; QString commandLabel = "Adjust control/property"; MacroCommand *macro = new MacroCommand(commandLabel); // Find the extent of the selected items float xmin=FLT_MAX,xmax=-1.0; // EventSelection::addEvent adds timeT(1) to its extentt for zero duration events so need to mimic this here timeT durationAdd = 0; for (ControlItemList::iterator it = m_selectedItems.begin(); it != m_selectedItems.end(); ++it) { if ((*it)->xStart() < xmin) xmin = (*it)->xStart(); if ((*it)->xEnd() > xmax) { xmax = (*it)->xEnd(); if ((*it)->xEnd() == (*it)->xStart()) durationAdd = 1; else durationAdd = 0; } } start = getRulerScale()->getTimeForX(xmin); end = getRulerScale()->getTimeForX(xmax)+durationAdd; if (m_eventSelection->getAddedEvents() == 0) { // We do not have a valid set of selected events to update if (m_selectedItems.size() == 0) { // There are no selected items, nothing to update return; } // Events will be added by the controlItem->updateSegment methods commandLabel = "Add control"; macro->setName(commandLabel); // segmentModified = true; } else { // Check for movement in time here and delete events if necessary if (start != m_eventSelection->getStartTime() || end != m_eventSelection->getEndTime()) { commandLabel = "Move control"; macro->setName(commandLabel); // Get the limits of the change for undo start = std::min(start,m_eventSelection->getStartTime()); end = std::max(end,m_eventSelection->getEndTime()); // segmentModified = true; } } // Add change command to macro // ControlChangeCommand calls each selected items updateSegment method // Note that updateSegment deletes and renews the event whether it has moved or not macro->addCommand(new ControlChangeCommand(m_selectedItems, *m_segment, start, end)); CommandHistory::getInstance()->addCommand(macro); updateSelection(); }
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(); }
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); }