lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam and QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "Overview.h" lbajardsilogic@0: #include "layer/Layer.h" lbajardsilogic@0: #include "data/model/Model.h" lbajardsilogic@0: #include "base/ZoomConstraint.h" lbajardsilogic@0: #include "system/System.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: using std::cerr; lbajardsilogic@0: using std::endl; lbajardsilogic@0: lbajardsilogic@0: Overview::Overview(QWidget *w) : lbajardsilogic@0: View(w, false), lbajardsilogic@0: m_clickedInRange(false) lbajardsilogic@0: { lbajardsilogic@0: setObjectName(tr("Overview")); lbajardsilogic@0: m_followPan = false; lbajardsilogic@0: m_followZoom = false; lbajardsilogic@0: setPlaybackFollow(PlaybackIgnore); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::modelChanged(size_t startFrame, size_t endFrame) lbajardsilogic@0: { lbajardsilogic@0: View::modelChanged(startFrame, endFrame); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::modelReplaced() lbajardsilogic@0: { lbajardsilogic@0: View::modelReplaced(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::registerView(View *view) lbajardsilogic@0: { lbajardsilogic@0: m_views.insert(view); lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::unregisterView(View *view) lbajardsilogic@0: { lbajardsilogic@0: m_views.erase(view); lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::globalCentreFrameChanged(unsigned long) lbajardsilogic@0: { lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::viewCentreFrameChanged(View *v, unsigned long) lbajardsilogic@0: { lbajardsilogic@0: if (m_views.find(v) != m_views.end()) { lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::viewZoomLevelChanged(View *v, unsigned long, bool) lbajardsilogic@0: { lbajardsilogic@0: if (v == this) return; lbajardsilogic@0: if (m_views.find(v) != m_views.end()) { lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::viewManagerPlaybackFrameChanged(unsigned long f) lbajardsilogic@0: { lbajardsilogic@0: bool changed = false; lbajardsilogic@0: lbajardsilogic@0: if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true; lbajardsilogic@0: m_playPointerFrame = f; lbajardsilogic@0: lbajardsilogic@0: if (changed) update(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::paintEvent(QPaintEvent *e) lbajardsilogic@0: { lbajardsilogic@0: // Recalculate zoom in case the size of the widget has changed. lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "Overview::paintEvent: width is " << width() << ", centre frame " << m_centreFrame << std::endl; lbajardsilogic@0: lbajardsilogic@0: size_t startFrame = getModelsStartFrame(); lbajardsilogic@0: size_t frameCount = getModelsEndFrame() - getModelsStartFrame(); lbajardsilogic@0: int zoomLevel = frameCount / width(); lbajardsilogic@0: if (zoomLevel < 1) zoomLevel = 1; lbajardsilogic@0: zoomLevel = getZoomConstraintBlockSize(zoomLevel, lbajardsilogic@0: ZoomConstraint::RoundUp); lbajardsilogic@0: if (zoomLevel != m_zoomLevel) { lbajardsilogic@0: m_zoomLevel = zoomLevel; lbajardsilogic@0: emit zoomLevelChanged(m_zoomLevel, m_followZoom); lbajardsilogic@0: } lbajardsilogic@0: size_t centreFrame = startFrame + m_zoomLevel * (width() / 2); lbajardsilogic@0: if (centreFrame > (startFrame + getModelsEndFrame())/2) { lbajardsilogic@0: centreFrame = (startFrame + getModelsEndFrame())/2; lbajardsilogic@0: } lbajardsilogic@0: if (centreFrame != m_centreFrame) { lbajardsilogic@0: // std::cerr << "Overview::paintEvent: Centre frame changed from " lbajardsilogic@0: // << m_centreFrame << " to " << centreFrame << " and thus start frame from " << getStartFrame(); lbajardsilogic@0: m_centreFrame = centreFrame; lbajardsilogic@0: // std::cerr << " to " << getStartFrame() << std::endl; lbajardsilogic@0: emit centreFrameChanged(m_centreFrame, false, PlaybackIgnore); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: View::paintEvent(e); lbajardsilogic@0: lbajardsilogic@0: QPainter paint; lbajardsilogic@0: paint.begin(this); lbajardsilogic@0: lbajardsilogic@0: QRect r(rect()); lbajardsilogic@0: lbajardsilogic@0: if (e) { lbajardsilogic@0: r = e->rect(); lbajardsilogic@0: paint.setClipRect(r); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: paint.setPen(Qt::black); lbajardsilogic@0: lbajardsilogic@0: int y = 0; lbajardsilogic@0: lbajardsilogic@0: int prevx0 = -10; lbajardsilogic@0: int prevx1 = -10; lbajardsilogic@0: lbajardsilogic@0: for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) { lbajardsilogic@0: if (!*i) continue; lbajardsilogic@0: lbajardsilogic@0: View *w = (View *)*i; lbajardsilogic@0: lbajardsilogic@0: long f0 = w->getFrameForX(0); lbajardsilogic@0: long f1 = w->getFrameForX(w->width()); lbajardsilogic@0: lbajardsilogic@0: int x0 = getXForFrame(f0); lbajardsilogic@0: int x1 = getXForFrame(f1); lbajardsilogic@0: lbajardsilogic@0: if (x0 != prevx0 || x1 != prevx1) { lbajardsilogic@0: y += height() / 10 + 1; lbajardsilogic@0: prevx0 = x0; lbajardsilogic@0: prevx1 = x1; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (x1 <= x0) x1 = x0 + 1; lbajardsilogic@0: lbajardsilogic@0: paint.drawRect(x0, y, x1 - x0, height() - 2 * y); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: paint.end(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::mousePressEvent(QMouseEvent *e) lbajardsilogic@0: { lbajardsilogic@0: m_clickPos = e->pos(); lbajardsilogic@0: for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) { lbajardsilogic@0: if (*i) { lbajardsilogic@0: m_clickedInRange = true; lbajardsilogic@0: m_dragCentreFrame = ((View *)*i)->getCentreFrame(); lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::mouseReleaseEvent(QMouseEvent *e) lbajardsilogic@0: { lbajardsilogic@0: if (m_clickedInRange) { lbajardsilogic@0: mouseMoveEvent(e); lbajardsilogic@0: } lbajardsilogic@0: m_clickedInRange = false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::mouseMoveEvent(QMouseEvent *e) lbajardsilogic@0: { lbajardsilogic@0: if (!m_clickedInRange) return; lbajardsilogic@0: lbajardsilogic@0: long xoff = int(e->x()) - int(m_clickPos.x()); lbajardsilogic@0: long frameOff = xoff * m_zoomLevel; lbajardsilogic@0: lbajardsilogic@0: size_t newCentreFrame = m_dragCentreFrame; lbajardsilogic@0: if (frameOff > 0) { lbajardsilogic@0: newCentreFrame += frameOff; lbajardsilogic@0: } else if (newCentreFrame >= size_t(-frameOff)) { lbajardsilogic@0: newCentreFrame += frameOff; lbajardsilogic@0: } else { lbajardsilogic@0: newCentreFrame = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (newCentreFrame >= getModelsEndFrame()) { lbajardsilogic@0: newCentreFrame = getModelsEndFrame(); lbajardsilogic@0: if (newCentreFrame > 0) --newCentreFrame; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@191: if (MAX(m_centreFrame, newCentreFrame) - lbajardsilogic@191: MIN(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) { lbajardsilogic@0: emit centreFrameChanged(newCentreFrame, true, PlaybackScrollContinuous); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::mouseDoubleClickEvent(QMouseEvent *e) lbajardsilogic@0: { lbajardsilogic@0: long frame = getFrameForX(e->x()); lbajardsilogic@0: emit centreFrameChanged(frame, true, PlaybackScrollContinuous); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::enterEvent(QEvent *) lbajardsilogic@0: { lbajardsilogic@0: emit contextHelpChanged(tr("Click and drag to navigate; double-click to jump")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Overview::leaveEvent(QEvent *) lbajardsilogic@0: { lbajardsilogic@0: emit contextHelpChanged(""); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: