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; }
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")); } } } } }
bool MatrixSelector::getSelection(EventSelection *&selection) { if (!m_selectionRect || !m_selectionRect->isVisible()) return 0; Segment& originalSegment = m_currentViewSegment->getSegment(); selection = new EventSelection(originalSegment); // get the selections // QList<QGraphicsItem *> l = m_selectionRect->collidingItems (Qt::IntersectsItemShape); // This is a nasty optimisation, just to avoid re-creating the // selection if the items we span are unchanged. It's not very // effective, either, because the colliding items returned // includes things like the horizontal and vertical background // lines -- and so it changes often: every time we cross a line. // More thought needed. // It might be better to use the event properties (i.e. time and // pitch) to calculate this "from first principles" rather than // doing it graphically. That might also be helpful to avoid us // dragging off the logical edges of the scene. // (Come to think of it, though, that would be troublesome just // because of the requirement to use all events that have any part // inside the selection. Quickly finding all events that start // within a time range is trivial, finding all events that // intersect one is more of a pain.) if (l == m_previousCollisions) return false; m_previousCollisions = l; if (!l.empty()) { for (int i = 0; i < l.size(); ++i) { QGraphicsItem *item = l[i]; MatrixElement *element = MatrixElement::getMatrixElement(item); if (element) { //!!! NB. In principle, this element might not come //!!! from the right segment (in practice we only have //!!! one segment, but that may change) selection->addEvent(element->event()); } } } if (selection->getAddedEvents() == 0) { delete selection; selection = 0; } return true; }
void MatrixViewSegment::updateElements(timeT from, timeT to) { if (!m_viewElementList) return; ViewElementList::iterator i = m_viewElementList->findTime(from); ViewElementList::iterator j = m_viewElementList->findTime(to); while (i != m_viewElementList->end()) { MatrixElement *e = static_cast<MatrixElement *>(*i); e->reconfigure(); if (i == j) break; ++i; } }
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); }
void MatrixSelector::handleMouseDoubleClick(const MatrixMouseEvent *e) { // Don't use m_clickedElement here, as it's reset to 0 on mouse // release, which occurs before our dialog completes (and we need // to know the element after that) MatrixElement *element = e->element; MatrixViewSegment *vs = e->viewSegment; if (!vs) return; if (element) { if (element->event()->isa(Note::EventType) && element->event()->has(BaseProperties::TRIGGER_SEGMENT_ID)) { int id = element->event()->get<Int>(BaseProperties::TRIGGER_SEGMENT_ID); emit editTriggerSegment(id); return; } if (e->modifiers & Qt::ShiftModifier) { // advanced edit EventEditDialog dialog(m_widget, *element->event(), true); if (dialog.exec() == QDialog::Accepted && dialog.isModified()) { EventEditCommand *command = new EventEditCommand (vs->getSegment(), element->event(), dialog.getEvent()); CommandHistory::getInstance()->addCommand(command); } } else { SimpleEventEditDialog dialog (m_widget, m_scene->getDocument(), *element->event(), false); if (dialog.exec() == QDialog::Accepted && dialog.isModified()) { EventEditCommand *command = new EventEditCommand (vs->getSegment(), element->event(), dialog.getEvent()); CommandHistory::getInstance()->addCommand(command); } } } /* #988167: Matrix:Multiclick select methods don't work in matrix editor Postponing this, as it falls foul of world-matrix transformation etiquette and other such niceties else { QRect rect = staff->getBarExtents(ev->x(), ev->y()); m_selectionRect->setX(rect.x() + 2); m_selectionRect->setY(rect.y()); m_selectionRect->setSize(rect.width() - 4, rect.height()); m_selectionRect->show(); m_updateRect = false; m_justSelectedBar = true; QTimer::singleShot(QApplication::doubleClickInterval(), this, SLOT(slotClickTimeout())); } */ }