annotate view/Overview.cpp @ 378:22b72f0f6a4e

* More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui.
author Chris Cannam
date Fri, 14 Mar 2008 17:14:21 +0000
parents ac954fc0ec6f
children 2ed4e572d0d4
rev   line source
Chris@173 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@173 2
Chris@173 3 /*
Chris@173 4 Sonic Visualiser
Chris@173 5 An audio file viewer and annotation editor.
Chris@173 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@173 8
Chris@173 9 This program is free software; you can redistribute it and/or
Chris@173 10 modify it under the terms of the GNU General Public License as
Chris@173 11 published by the Free Software Foundation; either version 2 of the
Chris@173 12 License, or (at your option) any later version. See the file
Chris@173 13 COPYING included with this distribution for more information.
Chris@173 14 */
Chris@173 15
Chris@173 16 #include "Overview.h"
Chris@173 17 #include "layer/Layer.h"
Chris@173 18 #include "data/model/Model.h"
Chris@173 19 #include "base/ZoomConstraint.h"
Chris@173 20
Chris@173 21 #include <QPaintEvent>
Chris@173 22 #include <QPainter>
Chris@173 23 #include <iostream>
Chris@173 24
Chris@173 25 using std::cerr;
Chris@173 26 using std::endl;
Chris@173 27
Chris@173 28 Overview::Overview(QWidget *w) :
Chris@173 29 View(w, false),
Chris@173 30 m_clickedInRange(false)
Chris@173 31 {
Chris@173 32 setObjectName(tr("Overview"));
Chris@173 33 m_followPan = false;
Chris@173 34 m_followZoom = false;
Chris@211 35 setPlaybackFollow(PlaybackIgnore);
Chris@274 36 m_modelTestTime.start();
Chris@173 37 }
Chris@173 38
Chris@173 39 void
Chris@173 40 Overview::modelChanged(size_t startFrame, size_t endFrame)
Chris@173 41 {
Chris@253 42 bool zoomChanged = false;
Chris@253 43
Chris@253 44 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
Chris@253 45 int zoomLevel = frameCount / width();
Chris@253 46 if (zoomLevel < 1) zoomLevel = 1;
Chris@253 47 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
Chris@253 48 ZoomConstraint::RoundUp);
Chris@253 49 if (zoomLevel != m_zoomLevel) {
Chris@253 50 zoomChanged = true;
Chris@253 51 }
Chris@253 52
Chris@253 53 if (!zoomChanged) {
Chris@274 54 if (m_modelTestTime.elapsed() < 1000) {
Chris@274 55 for (LayerList::const_iterator i = m_layers.begin();
Chris@274 56 i != m_layers.end(); ++i) {
Chris@274 57 if ((*i)->getModel() &&
Chris@274 58 !(*i)->getModel()->isOK() ||
Chris@274 59 !(*i)->getModel()->isReady()) {
Chris@274 60 return;
Chris@274 61 }
Chris@253 62 }
Chris@274 63 } else {
Chris@274 64 m_modelTestTime.restart();
Chris@253 65 }
Chris@253 66 }
Chris@253 67
Chris@173 68 View::modelChanged(startFrame, endFrame);
Chris@173 69 }
Chris@173 70
Chris@173 71 void
Chris@173 72 Overview::modelReplaced()
Chris@173 73 {
Chris@339 74 m_playPointerFrame = getAlignedPlaybackFrame();
Chris@173 75 View::modelReplaced();
Chris@173 76 }
Chris@173 77
Chris@173 78 void
Chris@211 79 Overview::registerView(View *view)
Chris@173 80 {
Chris@211 81 m_views.insert(view);
Chris@173 82 update();
Chris@173 83 }
Chris@173 84
Chris@173 85 void
Chris@211 86 Overview::unregisterView(View *view)
Chris@173 87 {
Chris@211 88 m_views.erase(view);
Chris@173 89 update();
Chris@173 90 }
Chris@173 91
Chris@173 92 void
Chris@248 93 Overview::globalCentreFrameChanged(unsigned long)
Chris@173 94 {
Chris@211 95 update();
Chris@211 96 }
Chris@173 97
Chris@211 98 void
Chris@248 99 Overview::viewCentreFrameChanged(View *v, unsigned long)
Chris@211 100 {
Chris@211 101 if (m_views.find(v) != m_views.end()) {
Chris@173 102 update();
Chris@173 103 }
Chris@211 104 }
Chris@173 105
Chris@173 106 void
Chris@248 107 Overview::viewZoomLevelChanged(View *v, unsigned long, bool)
Chris@173 108 {
Chris@222 109 if (v == this) return;
Chris@211 110 if (m_views.find(v) != m_views.end()) {
Chris@173 111 update();
Chris@173 112 }
Chris@173 113 }
Chris@173 114
Chris@173 115 void
Chris@173 116 Overview::viewManagerPlaybackFrameChanged(unsigned long f)
Chris@173 117 {
Chris@173 118 bool changed = false;
Chris@173 119
Chris@339 120 f = getAlignedPlaybackFrame();
Chris@339 121
Chris@173 122 if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true;
Chris@173 123 m_playPointerFrame = f;
Chris@173 124
Chris@173 125 if (changed) update();
Chris@173 126 }
Chris@173 127
Chris@173 128 void
Chris@173 129 Overview::paintEvent(QPaintEvent *e)
Chris@173 130 {
Chris@173 131 // Recalculate zoom in case the size of the widget has changed.
Chris@173 132
Chris@214 133 // std::cerr << "Overview::paintEvent: width is " << width() << ", centre frame " << m_centreFrame << std::endl;
Chris@214 134
Chris@173 135 size_t startFrame = getModelsStartFrame();
Chris@173 136 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
Chris@173 137 int zoomLevel = frameCount / width();
Chris@173 138 if (zoomLevel < 1) zoomLevel = 1;
Chris@173 139 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
Chris@173 140 ZoomConstraint::RoundUp);
Chris@173 141 if (zoomLevel != m_zoomLevel) {
Chris@173 142 m_zoomLevel = zoomLevel;
Chris@222 143 emit zoomLevelChanged(m_zoomLevel, m_followZoom);
Chris@173 144 }
Chris@253 145
Chris@173 146 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
Chris@173 147 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
Chris@173 148 centreFrame = (startFrame + getModelsEndFrame())/2;
Chris@173 149 }
Chris@173 150 if (centreFrame != m_centreFrame) {
Chris@214 151 // std::cerr << "Overview::paintEvent: Centre frame changed from "
Chris@214 152 // << m_centreFrame << " to " << centreFrame << " and thus start frame from " << getStartFrame();
Chris@173 153 m_centreFrame = centreFrame;
Chris@214 154 // std::cerr << " to " << getStartFrame() << std::endl;
Chris@211 155 emit centreFrameChanged(m_centreFrame, false, PlaybackIgnore);
Chris@173 156 }
Chris@173 157
Chris@173 158 View::paintEvent(e);
Chris@173 159
Chris@173 160 QPainter paint;
Chris@173 161 paint.begin(this);
Chris@173 162
Chris@173 163 QRect r(rect());
Chris@173 164
Chris@173 165 if (e) {
Chris@173 166 r = e->rect();
Chris@173 167 paint.setClipRect(r);
Chris@173 168 }
Chris@173 169
Chris@287 170 paint.setPen(getForeground());
Chris@173 171
Chris@173 172 int y = 0;
Chris@173 173
Chris@173 174 int prevx0 = -10;
Chris@173 175 int prevx1 = -10;
Chris@173 176
Chris@211 177 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
Chris@173 178 if (!*i) continue;
Chris@173 179
Chris@173 180 View *w = (View *)*i;
Chris@173 181
Chris@173 182 long f0 = w->getFrameForX(0);
Chris@173 183 long f1 = w->getFrameForX(w->width());
Chris@173 184
Chris@339 185 if (f0 >= 0) {
Chris@339 186 size_t rf0 = w->alignToReference(f0);
Chris@339 187 f0 = alignFromReference(rf0);
Chris@339 188 }
Chris@339 189 if (f1 >= 0) {
Chris@339 190 size_t rf1 = w->alignToReference(f1);
Chris@339 191 f1 = alignFromReference(rf1);
Chris@339 192 }
Chris@339 193
Chris@173 194 int x0 = getXForFrame(f0);
Chris@173 195 int x1 = getXForFrame(f1);
Chris@173 196
Chris@173 197 if (x0 != prevx0 || x1 != prevx1) {
Chris@173 198 y += height() / 10 + 1;
Chris@173 199 prevx0 = x0;
Chris@173 200 prevx1 = x1;
Chris@173 201 }
Chris@173 202
Chris@173 203 if (x1 <= x0) x1 = x0 + 1;
Chris@173 204
Chris@173 205 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
Chris@173 206 }
Chris@173 207
Chris@173 208 paint.end();
Chris@173 209 }
Chris@173 210
Chris@173 211 void
Chris@173 212 Overview::mousePressEvent(QMouseEvent *e)
Chris@173 213 {
Chris@173 214 m_clickPos = e->pos();
Chris@339 215 long clickFrame = getFrameForX(m_clickPos.x());
Chris@339 216 if (clickFrame > 0) m_dragCentreFrame = clickFrame;
Chris@339 217 else m_dragCentreFrame = 0;
Chris@339 218 m_clickedInRange = true;
Chris@339 219
Chris@211 220 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
Chris@339 221 if (*i && (*i)->getAligningModel() == getAligningModel()) {
Chris@339 222 m_dragCentreFrame = (*i)->getCentreFrame();
Chris@339 223 break;
Chris@339 224 }
Chris@173 225 }
Chris@173 226 }
Chris@173 227
Chris@173 228 void
Chris@173 229 Overview::mouseReleaseEvent(QMouseEvent *e)
Chris@173 230 {
Chris@173 231 if (m_clickedInRange) {
Chris@173 232 mouseMoveEvent(e);
Chris@173 233 }
Chris@173 234 m_clickedInRange = false;
Chris@173 235 }
Chris@173 236
Chris@173 237 void
Chris@173 238 Overview::mouseMoveEvent(QMouseEvent *e)
Chris@173 239 {
Chris@173 240 if (!m_clickedInRange) return;
Chris@173 241
Chris@173 242 long xoff = int(e->x()) - int(m_clickPos.x());
Chris@173 243 long frameOff = xoff * m_zoomLevel;
Chris@173 244
Chris@173 245 size_t newCentreFrame = m_dragCentreFrame;
Chris@173 246 if (frameOff > 0) {
Chris@173 247 newCentreFrame += frameOff;
Chris@173 248 } else if (newCentreFrame >= size_t(-frameOff)) {
Chris@173 249 newCentreFrame += frameOff;
Chris@173 250 } else {
Chris@173 251 newCentreFrame = 0;
Chris@173 252 }
Chris@173 253
Chris@173 254 if (newCentreFrame >= getModelsEndFrame()) {
Chris@173 255 newCentreFrame = getModelsEndFrame();
Chris@173 256 if (newCentreFrame > 0) --newCentreFrame;
Chris@173 257 }
Chris@173 258
Chris@173 259 if (std::max(m_centreFrame, newCentreFrame) -
Chris@173 260 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
Chris@339 261 size_t rf = alignToReference(newCentreFrame);
Chris@339 262 emit centreFrameChanged(rf, true, PlaybackScrollContinuous);
Chris@173 263 }
Chris@173 264 }
Chris@173 265
Chris@189 266 void
Chris@189 267 Overview::mouseDoubleClickEvent(QMouseEvent *e)
Chris@189 268 {
Chris@189 269 long frame = getFrameForX(e->x());
Chris@339 270 size_t rf = 0;
Chris@339 271 if (frame > 0) rf = alignToReference(frame);
Chris@339 272 emit centreFrameChanged(rf, true, PlaybackScrollContinuous);
Chris@189 273 }
Chris@173 274
Chris@189 275 void
Chris@189 276 Overview::enterEvent(QEvent *)
Chris@189 277 {
Chris@189 278 emit contextHelpChanged(tr("Click and drag to navigate; double-click to jump"));
Chris@189 279 }
Chris@189 280
Chris@189 281 void
Chris@189 282 Overview::leaveEvent(QEvent *)
Chris@189 283 {
Chris@189 284 emit contextHelpChanged("");
Chris@189 285 }
Chris@189 286
Chris@189 287