📄 temporuler.cpp
字号:
} return ; }}voidTempoRuler::mouseMoveEvent(QMouseEvent *e){ bool shiftPressed = ((e->state() & Qt::ShiftButton) != 0); if (m_dragVert) { if (shiftPressed != m_dragFine) { m_dragFine = shiftPressed; m_dragStartY = e->y(); // reset the start tempi to whatever we last updated them // to as we switch into or out of fine mode int tcn = m_composition->getTempoChangeNumberAt(m_dragStartTime); std::pair<timeT, tempoT> tc = m_composition->getTempoChange(tcn); std::pair<bool, tempoT> tr = m_composition->getTempoRamping(tcn, true); m_dragStartTempo = tc.second; m_dragStartTarget = tr.first ? tr.second : -1; } int diff = m_dragStartY - e->y(); // +ve for upwards drag tempoT newTempo = m_dragStartTempo; tempoT newTarget = m_dragStartTarget; if (diff != 0) { float qpm = m_composition->getTempoQpm(newTempo); if (m_dragTarget && newTarget > 0) { qpm = m_composition->getTempoQpm(newTarget); } float qdiff = (m_dragFine ? diff * 0.05 : diff * 0.5); qpm += qdiff; if (qpm < 1) qpm = 1; if (m_dragTarget) { newTarget = m_composition->getTempoForQpm(qpm); } else { newTempo = m_composition->getTempoForQpm(qpm); if (newTarget >= 0) { qpm = m_composition->getTempoQpm(newTarget); qpm += qdiff; if (qpm < 1) qpm = 1; newTarget = m_composition->getTempoForQpm(qpm); } } } showTextFloat(newTempo, newTarget, m_dragStartTime); m_composition->addTempoAtTime(m_dragStartTime, newTempo, newTarget); update(); } else if (m_dragHoriz) { int x = e->x(); SnapGrid grid(m_rulerScale); if (shiftPressed) { grid.setSnapTime(SnapGrid::NoSnap); } else { grid.setSnapTime(SnapGrid::SnapToUnit); } timeT newTime = grid.snapX(x - m_currentXOffset - m_xorigin, SnapGrid::SnapEither); int tcn = m_composition->getTempoChangeNumberAt(m_dragPreviousTime); int ncn = m_composition->getTempoChangeNumberAt(newTime); if (ncn > tcn || ncn < tcn - 1) return ; if (ncn >= 0 && ncn == tcn - 1) { std::pair<timeT, tempoT> nc = m_composition->getTempoChange(ncn); if (nc.first == newTime) return ; } // std::cerr << " -> " << newTime << std::endl; m_composition->removeTempoChange(tcn); m_composition->addTempoAtTime(newTime, m_dragStartTempo, m_dragStartTarget); showTextFloat(m_dragStartTempo, m_dragStartTarget, newTime, true); m_dragPreviousTime = newTime; update(); } else { int x = e->x() + 1; timeT t = m_rulerScale->getTimeForX(x - m_currentXOffset - m_xorigin); int tcn = m_composition->getTempoChangeNumberAt(t); if (tcn < 0 || tcn >= m_composition->getTempoChangeCount()) return ; std::pair<timeT, tempoT> tc = m_composition->getTempoChange(tcn); std::pair<bool, tempoT> tr = m_composition->getTempoRamping(tcn, true); int bar, beat, fraction, remainder; m_composition->getMusicalTimeForAbsoluteTime(tc.first, bar, beat, fraction, remainder); RG_DEBUG << "Tempo change: tempo " << m_composition->getTempoQpm(tc.second) << " at " << bar << ":" << beat << ":" << fraction << ":" << remainder << endl; m_illuminate = tcn; m_illuminatePoint = false; m_illuminateTarget = false; //!!! m_refreshLinesOnly = true; //!!! merge this test with the one in mousePressEvent as //isCloseToStart or equiv, and likewise for close to end int px = m_rulerScale->getXForTime(tc.first) + m_currentXOffset + m_xorigin; if (x >= px && x < px + 5) { m_illuminatePoint = true; } else { timeT nt = m_composition->getEndMarker(); if (tcn < m_composition->getTempoChangeCount() - 1) { nt = m_composition->getTempoChange(tcn + 1).first; } int nx = m_rulerScale->getXForTime(nt) + m_currentXOffset + m_xorigin; if (x > px + 5 && x > nx - 5) { m_illuminateTarget = true; } // std::cerr << "nt = " << nt << ", nx = " << nx << ", x = " << x << ", m_illuminateTarget = " << m_illuminateTarget << std::endl; } showTextFloat(tc.second, tr.first ? tr.second : -1, tc.first, m_illuminatePoint); update(); }}voidTempoRuler::wheelEvent(QWheelEvent *e){}voidTempoRuler::enterEvent(QEvent *){ setMouseTracking(true);}voidTempoRuler::leaveEvent(QEvent *){ if (!m_dragVert && !m_dragHoriz) { setMouseTracking(false); m_illuminate = -1; m_illuminatePoint = false; //!!! m_refreshLinesOnly = true; m_textFloat->hide(); update(); }}voidTempoRuler::showTextFloat(tempoT tempo, tempoT target, timeT time, bool showTime){ float qpm = m_composition->getTempoQpm(tempo); int qi = int(qpm + 0.0001); int q0 = int(qpm * 10 + 0.0001) % 10; int q00 = int(qpm * 100 + 0.0001) % 10; bool haveSet = false; QString tempoText, timeText; if (time >= 0) { if (showTime) { int bar, beat, fraction, remainder; m_composition->getMusicalTimeForAbsoluteTime (time, bar, beat, fraction, remainder); RealTime rt = m_composition->getElapsedRealTime(time); // blargh -- duplicated with TempoView::makeTimeString timeText = QString("%1%2%3-%4%5-%6%7-%8%9") .arg(bar / 100) .arg((bar % 100) / 10) .arg(bar % 10) .arg(beat / 10) .arg(beat % 10) .arg(fraction / 10) .arg(fraction % 10) .arg(remainder / 10) .arg(remainder % 10); timeText = QString("%1\n%2") .arg(timeText) // .arg(rt.toString().c_str()); .arg(rt.toText(true).c_str()); } TimeSignature sig = m_composition->getTimeSignatureAt(time); if (sig.getBeatDuration() != Note(Note::Crotchet).getDuration()) { float bpm = (qpm * Note(Note::Crotchet).getDuration()) / sig.getBeatDuration(); int bi = int(bpm + 0.0001); int b0 = int(bpm * 10 + 0.0001) % 10; int b00 = int(bpm * 100 + 0.0001) % 10; tempoText = i18n("%1.%2%3 (%4.%5%6 bpm)") .arg(qi).arg(q0).arg(q00) .arg(bi).arg(b0).arg(b00); haveSet = true; } } if (!haveSet) { tempoText = i18n("%1.%2%3 bpm").arg(qi).arg(q0).arg(q00); } if (target > 0 && target != tempo) { float tq = m_composition->getTempoQpm(target); int tqi = int(tq + 0.0001); int tq0 = int(tq * 10 + 0.0001) % 10; int tq00 = int(tq * 100 + 0.0001) % 10; tempoText = i18n("%1 - %2.%3%4").arg(tempoText).arg(tqi).arg(tq0).arg(tq00); } if (showTime && time >= 0) { m_textFloat->setText(QString("%1\n%2").arg(timeText).arg(tempoText)); } else { m_textFloat->setText(tempoText); } QPoint cp = mapFromGlobal(QPoint(QCursor::pos())); // std::cerr << "cp = " << cp.x() << "," << cp.y() << ", tempo = " << qpm << std::endl; QPoint mp = cp + pos(); QWidget *parent = parentWidget(); while (parent->parentWidget() && !parent->isTopLevel() && !parent->isDialog()) { mp += parent->pos(); parent = parent->parentWidget(); } int yoff = cp.y() + m_textFloat->height() + 3; mp = QPoint(mp.x() + 10, mp.y() > yoff ? mp.y() - yoff : 0); m_textFloat->move(mp); m_textFloat->show();}QSizeTempoRuler::sizeHint() const{ double width = m_rulerScale->getBarPosition(m_rulerScale->getLastVisibleBar()) + m_rulerScale->getBarWidth(m_rulerScale->getLastVisibleBar()) + m_xorigin; QSize res(std::max(int(width), m_width), m_height); return res;}QSizeTempoRuler::minimumSizeHint() const{ double firstBarWidth = m_rulerScale->getBarWidth(0) + m_xorigin; QSize res = QSize(int(firstBarWidth), m_height); return res;}intTempoRuler::getYForTempo(tempoT tempo){ int drawh = height() - 4; int y = drawh / 2; tempoT minTempo = m_composition->getMinTempo(); tempoT maxTempo = m_composition->getMaxTempo(); if (maxTempo > minTempo) { y = drawh - int((double(tempo - minTempo) / double(maxTempo - minTempo)) * drawh + 0.5); } return y;}tempoTTempoRuler::getTempoForY(int y){ int drawh = height() - 4; tempoT minTempo = m_composition->getMinTempo(); tempoT maxTempo = m_composition->getMaxTempo(); tempoT tempo = minTempo; if (maxTempo > minTempo) { tempo = (maxTempo - minTempo) * (double(drawh - y) / double(drawh)) + minTempo + 0.5; } return tempo;}voidTempoRuler::paintEvent(QPaintEvent* e){ QRect clipRect = e->rect(); if (m_buffer.width() < width() || m_buffer.height() < height()) { m_buffer = QPixmap(width(), height()); } m_buffer.fill(GUIPalette::getColour (GUIPalette::TextRulerBackground)); QPainter paint(&m_buffer); paint.setPen(GUIPalette::getColour (GUIPalette::TextRulerForeground)); paint.setClipRegion(e->region()); paint.setClipRect(clipRect); if (m_xorigin > 0) { paint.fillRect(0, 0, m_xorigin, height(), paletteBackgroundColor()); } timeT from = m_rulerScale->getTimeForX (clipRect.x() - m_currentXOffset - 100 - m_xorigin); timeT to = m_rulerScale->getTimeForX (clipRect.x() + clipRect.width() - m_currentXOffset + 100 - m_xorigin); QRect boundsForHeight = m_fontMetrics.boundingRect("019"); int fontHeight = boundsForHeight.height(); int textY = fontHeight + 2; double prevEndX = -1000.0; double prevTempo = 0.0; long prevBpm = 0; typedef std::map<timeT, int> TimePoints; int tempoChangeHere = 1; int timeSigChangeHere = 2; TimePoints timePoints;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -