svgui
1.9
|
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 //#define DEBUG_OVERVIEW 1 00026 00027 00028 Overview::Overview(QWidget *w) : 00029 View(w, false), 00030 m_clickedInRange(false), 00031 m_dragCentreFrame(0) 00032 { 00033 setObjectName(tr("Overview")); 00034 m_followPan = false; 00035 m_followZoom = false; 00036 setPlaybackFollow(PlaybackIgnore); 00037 m_modelTestTime.start(); 00038 } 00039 00040 void 00041 Overview::modelChangedWithin(int startFrame, int endFrame) 00042 { 00043 bool zoomChanged = false; 00044 00045 int frameCount = getModelsEndFrame() - getModelsStartFrame(); 00046 int zoomLevel = frameCount / width(); 00047 if (zoomLevel < 1) zoomLevel = 1; 00048 zoomLevel = getZoomConstraintBlockSize(zoomLevel, 00049 ZoomConstraint::RoundUp); 00050 if (zoomLevel != m_zoomLevel) { 00051 zoomChanged = true; 00052 } 00053 00054 if (!zoomChanged) { 00055 if (m_modelTestTime.elapsed() < 1000) { 00056 for (LayerList::const_iterator i = m_layerStack.begin(); 00057 i != m_layerStack.end(); ++i) { 00058 if ((*i)->getModel() && 00059 (!(*i)->getModel()->isOK() || 00060 !(*i)->getModel()->isReady())) { 00061 return; 00062 } 00063 } 00064 } else { 00065 m_modelTestTime.restart(); 00066 } 00067 } 00068 00069 View::modelChangedWithin(startFrame, endFrame); 00070 } 00071 00072 void 00073 Overview::modelReplaced() 00074 { 00075 m_playPointerFrame = getAlignedPlaybackFrame(); 00076 View::modelReplaced(); 00077 } 00078 00079 void 00080 Overview::registerView(View *view) 00081 { 00082 m_views.insert(view); 00083 update(); 00084 } 00085 00086 void 00087 Overview::unregisterView(View *view) 00088 { 00089 m_views.erase(view); 00090 update(); 00091 } 00092 00093 void 00094 Overview::globalCentreFrameChanged(int 00095 #ifdef DEBUG_OVERVIEW 00096 f 00097 #endif 00098 ) 00099 { 00100 #ifdef DEBUG_OVERVIEW 00101 cerr << "Overview::globalCentreFrameChanged: " << f << endl; 00102 #endif 00103 update(); 00104 } 00105 00106 void 00107 Overview::viewCentreFrameChanged(View *v, int 00108 #ifdef DEBUG_OVERVIEW 00109 f 00110 #endif 00111 ) 00112 { 00113 #ifdef DEBUG_OVERVIEW 00114 cerr << "Overview[" << this << "]::viewCentreFrameChanged(" << v << "): " << f << endl; 00115 #endif 00116 if (m_views.find(v) != m_views.end()) { 00117 update(); 00118 } 00119 } 00120 00121 void 00122 Overview::viewZoomLevelChanged(View *v, int, bool) 00123 { 00124 if (v == this) return; 00125 if (m_views.find(v) != m_views.end()) { 00126 update(); 00127 } 00128 } 00129 00130 void 00131 Overview::viewManagerPlaybackFrameChanged(int f) 00132 { 00133 #ifdef DEBUG_OVERVIEW 00134 cerr << "Overview[" << this << "]::viewManagerPlaybackFrameChanged(" << f << "): " << f << endl; 00135 #endif 00136 00137 bool changed = false; 00138 00139 f = getAlignedPlaybackFrame(); 00140 00141 if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true; 00142 m_playPointerFrame = f; 00143 00144 if (changed) update(); 00145 } 00146 00147 void 00148 Overview::paintEvent(QPaintEvent *e) 00149 { 00150 // Recalculate zoom in case the size of the widget has changed. 00151 00152 #ifdef DEBUG_OVERVIEW 00153 cerr << "Overview::paintEvent: width is " << width() << ", centre frame " << m_centreFrame << endl; 00154 #endif 00155 00156 int startFrame = getModelsStartFrame(); 00157 int frameCount = getModelsEndFrame() - getModelsStartFrame(); 00158 int zoomLevel = frameCount / width(); 00159 if (zoomLevel < 1) zoomLevel = 1; 00160 zoomLevel = getZoomConstraintBlockSize(zoomLevel, 00161 ZoomConstraint::RoundUp); 00162 if (zoomLevel != m_zoomLevel) { 00163 m_zoomLevel = zoomLevel; 00164 emit zoomLevelChanged(m_zoomLevel, m_followZoom); 00165 } 00166 00167 int centreFrame = startFrame + m_zoomLevel * (width() / 2); 00168 if (centreFrame > (startFrame + getModelsEndFrame())/2) { 00169 centreFrame = (startFrame + getModelsEndFrame())/2; 00170 } 00171 if (centreFrame != m_centreFrame) { 00172 #ifdef DEBUG_OVERVIEW 00173 cerr << "Overview::paintEvent: Centre frame changed from " 00174 << m_centreFrame << " to " << centreFrame << " and thus start frame from " << getStartFrame(); 00175 #endif 00176 m_centreFrame = centreFrame; 00177 #ifdef DEBUG_OVERVIEW 00178 cerr << " to " << getStartFrame() << endl; 00179 #endif 00180 emit centreFrameChanged(m_centreFrame, false, PlaybackIgnore); 00181 } 00182 00183 View::paintEvent(e); 00184 00185 QPainter paint; 00186 paint.begin(this); 00187 00188 QRect r(rect()); 00189 00190 if (e) { 00191 r = e->rect(); 00192 paint.setClipRect(r); 00193 } 00194 00195 paint.setPen(getForeground()); 00196 00197 int y = 0; 00198 00199 int prevx0 = -10; 00200 int prevx1 = -10; 00201 00202 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) { 00203 if (!*i) continue; 00204 00205 View *w = (View *)*i; 00206 00207 int f0 = w->getFrameForX(0); 00208 int f1 = w->getFrameForX(w->width()); 00209 00210 if (f0 >= 0) { 00211 int rf0 = w->alignToReference(f0); 00212 f0 = alignFromReference(rf0); 00213 } 00214 if (f1 >= 0) { 00215 int rf1 = w->alignToReference(f1); 00216 f1 = alignFromReference(rf1); 00217 } 00218 00219 int x0 = getXForFrame(f0); 00220 int x1 = getXForFrame(f1); 00221 00222 if (x0 != prevx0 || x1 != prevx1) { 00223 y += height() / 10 + 1; 00224 prevx0 = x0; 00225 prevx1 = x1; 00226 } 00227 00228 if (x1 <= x0) x1 = x0 + 1; 00229 00230 paint.drawRect(x0, y, x1 - x0, height() - 2 * y); 00231 } 00232 00233 paint.end(); 00234 } 00235 00236 void 00237 Overview::mousePressEvent(QMouseEvent *e) 00238 { 00239 m_clickPos = e->pos(); 00240 int clickFrame = getFrameForX(m_clickPos.x()); 00241 if (clickFrame > 0) m_dragCentreFrame = clickFrame; 00242 else m_dragCentreFrame = 0; 00243 m_clickedInRange = true; 00244 00245 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) { 00246 if (*i && (*i)->getAligningModel() == getAligningModel()) { 00247 m_dragCentreFrame = (*i)->getCentreFrame(); 00248 break; 00249 } 00250 } 00251 } 00252 00253 void 00254 Overview::mouseReleaseEvent(QMouseEvent *e) 00255 { 00256 if (m_clickedInRange) { 00257 mouseMoveEvent(e); 00258 } 00259 m_clickedInRange = false; 00260 } 00261 00262 void 00263 Overview::mouseMoveEvent(QMouseEvent *e) 00264 { 00265 if (!m_clickedInRange) return; 00266 00267 int xoff = int(e->x()) - int(m_clickPos.x()); 00268 int frameOff = xoff * m_zoomLevel; 00269 00270 int newCentreFrame = m_dragCentreFrame; 00271 if (frameOff > 0) { 00272 newCentreFrame += frameOff; 00273 } else if (newCentreFrame >= int(-frameOff)) { 00274 newCentreFrame += frameOff; 00275 } else { 00276 newCentreFrame = 0; 00277 } 00278 00279 if (newCentreFrame >= getModelsEndFrame()) { 00280 newCentreFrame = getModelsEndFrame(); 00281 if (newCentreFrame > 0) --newCentreFrame; 00282 } 00283 00284 if (std::max(m_centreFrame, newCentreFrame) - 00285 std::min(m_centreFrame, newCentreFrame) > int(m_zoomLevel)) { 00286 int rf = alignToReference(newCentreFrame); 00287 #ifdef DEBUG_OVERVIEW 00288 cerr << "Overview::mouseMoveEvent: x " << e->x() << " and click x " << m_clickPos.x() << " -> frame " << newCentreFrame << " -> rf " << rf << endl; 00289 #endif 00290 if (m_followPlay == PlaybackScrollContinuous || 00291 m_followPlay == PlaybackScrollPageWithCentre) { 00292 emit centreFrameChanged(rf, true, PlaybackScrollContinuous); 00293 } else { 00294 emit centreFrameChanged(rf, true, PlaybackIgnore); 00295 } 00296 } 00297 } 00298 00299 void 00300 Overview::mouseDoubleClickEvent(QMouseEvent *e) 00301 { 00302 int frame = getFrameForX(e->x()); 00303 int rf = 0; 00304 if (frame > 0) rf = alignToReference(frame); 00305 #ifdef DEBUG_OVERVIEW 00306 cerr << "Overview::mouseDoubleClickEvent: frame " << frame << " -> rf " << rf << endl; 00307 #endif 00308 m_clickedInRange = false; // we're not starting a drag with the second click 00309 emit centreFrameChanged(rf, true, PlaybackScrollContinuous); 00310 } 00311 00312 void 00313 Overview::enterEvent(QEvent *) 00314 { 00315 emit contextHelpChanged(tr("Click and drag to navigate; double-click to jump")); 00316 } 00317 00318 void 00319 Overview::leaveEvent(QEvent *) 00320 { 00321 emit contextHelpChanged(""); 00322 } 00323 00324