Overview.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "Overview.h"
00017 #include "layer/Layer.h"
00018 #include "data/model/Model.h"
00019 #include "base/ZoomConstraint.h"
00020 
00021 #include <QPaintEvent>
00022 #include <QPainter>
00023 #include <iostream>
00024 
00025 using std::cerr;
00026 using std::endl;
00027 
00028 Overview::Overview(QWidget *w) :
00029     View(w, false),
00030     m_clickedInRange(false)
00031 {
00032     setObjectName(tr("Overview"));
00033     m_followPan = false;
00034     m_followZoom = false;
00035     setPlaybackFollow(PlaybackIgnore);
00036     m_modelTestTime.start();
00037 }
00038 
00039 void
00040 Overview::modelChanged(size_t startFrame, size_t endFrame)
00041 {
00042     bool zoomChanged = false;
00043 
00044     size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
00045     int zoomLevel = frameCount / width();
00046     if (zoomLevel < 1) zoomLevel = 1;
00047     zoomLevel = getZoomConstraintBlockSize(zoomLevel,
00048                                            ZoomConstraint::RoundUp);
00049     if (zoomLevel != m_zoomLevel) {
00050         zoomChanged = true;
00051     }
00052 
00053     if (!zoomChanged) {
00054         if (m_modelTestTime.elapsed() < 1000) {
00055             for (LayerList::const_iterator i = m_layers.begin();
00056                  i != m_layers.end(); ++i) {
00057                 if ((*i)->getModel() &&
00058                     !(*i)->getModel()->isOK() ||
00059                     !(*i)->getModel()->isReady()) {
00060                     return;
00061                 }
00062             }
00063         } else {
00064             m_modelTestTime.restart();
00065         }
00066     }
00067 
00068     View::modelChanged(startFrame, endFrame);
00069 }
00070 
00071 void
00072 Overview::modelReplaced()
00073 {
00074     m_playPointerFrame = getAlignedPlaybackFrame();
00075     View::modelReplaced();
00076 }
00077 
00078 void
00079 Overview::registerView(View *view)
00080 {
00081     m_views.insert(view);
00082     update(); 
00083 }
00084 
00085 void
00086 Overview::unregisterView(View *view)
00087 {
00088     m_views.erase(view);
00089     update();
00090 }
00091 
00092 void
00093 Overview::globalCentreFrameChanged(unsigned long)
00094 {
00095     update();
00096 }
00097 
00098 void
00099 Overview::viewCentreFrameChanged(View *v, unsigned long)
00100 {
00101     if (m_views.find(v) != m_views.end()) {
00102         update();
00103     }
00104 }    
00105 
00106 void
00107 Overview::viewZoomLevelChanged(View *v, unsigned long, bool)
00108 {
00109     if (v == this) return;
00110     if (m_views.find(v) != m_views.end()) {
00111         update();
00112     }
00113 }
00114 
00115 void
00116 Overview::viewManagerPlaybackFrameChanged(unsigned long f)
00117 {
00118     bool changed = false;
00119 
00120     f = getAlignedPlaybackFrame();
00121 
00122     if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true;
00123     m_playPointerFrame = f;
00124 
00125     if (changed) update();
00126 }
00127 
00128 void
00129 Overview::paintEvent(QPaintEvent *e)
00130 {
00131     // Recalculate zoom in case the size of the widget has changed.
00132 
00133 //    std::cerr << "Overview::paintEvent: width is " << width() << ", centre frame " << m_centreFrame << std::endl;
00134 
00135     size_t startFrame = getModelsStartFrame();
00136     size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
00137     int zoomLevel = frameCount / width();
00138     if (zoomLevel < 1) zoomLevel = 1;
00139     zoomLevel = getZoomConstraintBlockSize(zoomLevel,
00140                                            ZoomConstraint::RoundUp);
00141     if (zoomLevel != m_zoomLevel) {
00142         m_zoomLevel = zoomLevel;
00143         emit zoomLevelChanged(m_zoomLevel, m_followZoom);
00144     }
00145 
00146     size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
00147     if (centreFrame > (startFrame + getModelsEndFrame())/2) {
00148         centreFrame = (startFrame + getModelsEndFrame())/2;
00149     }
00150     if (centreFrame != m_centreFrame) {
00151 //        std::cerr << "Overview::paintEvent: Centre frame changed from "
00152 //                  << m_centreFrame << " to " << centreFrame << " and thus start frame from " << getStartFrame();
00153         m_centreFrame = centreFrame;
00154 //        std::cerr << " to " << getStartFrame() << std::endl;
00155         emit centreFrameChanged(m_centreFrame, false, PlaybackIgnore);
00156     }
00157 
00158     View::paintEvent(e);
00159 
00160     QPainter paint;
00161     paint.begin(this);
00162 
00163     QRect r(rect());
00164 
00165     if (e) {
00166         r = e->rect();
00167         paint.setClipRect(r);
00168     }
00169 
00170     paint.setPen(getForeground());
00171 
00172     int y = 0;
00173 
00174     int prevx0 = -10;
00175     int prevx1 = -10;
00176 
00177     for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
00178         if (!*i) continue;
00179 
00180         View *w = (View *)*i;
00181 
00182         long f0 = w->getFrameForX(0);
00183         long f1 = w->getFrameForX(w->width());
00184 
00185         if (f0 >= 0) {
00186             size_t rf0 = w->alignToReference(f0);
00187             f0 = alignFromReference(rf0);
00188         }
00189         if (f1 >= 0) {
00190             size_t rf1 = w->alignToReference(f1);
00191             f1 = alignFromReference(rf1);
00192         }
00193 
00194         int x0 = getXForFrame(f0);
00195         int x1 = getXForFrame(f1);
00196 
00197         if (x0 != prevx0 || x1 != prevx1) {
00198             y += height() / 10 + 1;
00199             prevx0 = x0;
00200             prevx1 = x1;
00201         }
00202 
00203         if (x1 <= x0) x1 = x0 + 1;
00204         
00205         paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
00206     }
00207 
00208     paint.end();
00209 }
00210 
00211 void
00212 Overview::mousePressEvent(QMouseEvent *e)
00213 {
00214     m_clickPos = e->pos();
00215     long clickFrame = getFrameForX(m_clickPos.x());
00216     if (clickFrame > 0) m_dragCentreFrame = clickFrame;
00217     else m_dragCentreFrame = 0;
00218     m_clickedInRange = true;
00219 
00220     for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
00221         if (*i && (*i)->getAligningModel() == getAligningModel()) {
00222             m_dragCentreFrame = (*i)->getCentreFrame();
00223             break;
00224         }
00225     }
00226 }
00227 
00228 void
00229 Overview::mouseReleaseEvent(QMouseEvent *e)
00230 {
00231     if (m_clickedInRange) {
00232         mouseMoveEvent(e);
00233     }
00234     m_clickedInRange = false;
00235 }
00236 
00237 void
00238 Overview::mouseMoveEvent(QMouseEvent *e)
00239 {
00240     if (!m_clickedInRange) return;
00241 
00242     long xoff = int(e->x()) - int(m_clickPos.x());
00243     long frameOff = xoff * m_zoomLevel;
00244     
00245     size_t newCentreFrame = m_dragCentreFrame;
00246     if (frameOff > 0) {
00247         newCentreFrame += frameOff;
00248     } else if (newCentreFrame >= size_t(-frameOff)) {
00249         newCentreFrame += frameOff;
00250     } else {
00251         newCentreFrame = 0;
00252     }
00253 
00254     if (newCentreFrame >= getModelsEndFrame()) {
00255         newCentreFrame = getModelsEndFrame();
00256         if (newCentreFrame > 0) --newCentreFrame;
00257     }
00258     
00259     if (std::max(m_centreFrame, newCentreFrame) -
00260         std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
00261         size_t rf = alignToReference(newCentreFrame);
00262         emit centreFrameChanged(rf, true, PlaybackScrollContinuous);
00263     }
00264 }
00265 
00266 void
00267 Overview::mouseDoubleClickEvent(QMouseEvent *e)
00268 {
00269     long frame = getFrameForX(e->x());
00270     size_t rf = 0;
00271     if (frame > 0) rf = alignToReference(frame);
00272     emit centreFrameChanged(rf, true, PlaybackScrollContinuous);
00273 }
00274 
00275 void
00276 Overview::enterEvent(QEvent *)
00277 {
00278     emit contextHelpChanged(tr("Click and drag to navigate; double-click to jump"));
00279 }
00280 
00281 void
00282 Overview::leaveEvent(QEvent *)
00283 {
00284     emit contextHelpChanged("");
00285 }
00286 
00287 

Generated on Wed Feb 20 15:45:27 2008 for SonicVisualiser by  doxygen 1.5.1