annotate view/Overview.cpp @ 317:e251c3599ea8

* Make RemoteFile far more pervasive, and use it for local files as well so that we can handle both transparently. Make it shallow copy with reference counting, so it can be used by value without having to worry about the cache file lifetime. Use RemoteFile for MainWindow file-open functions, etc
author Chris Cannam
date Thu, 18 Oct 2007 15:31:20 +0000
parents cd2492c5fe45
children ac954fc0ec6f
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@173 74 View::modelReplaced();
Chris@173 75 }
Chris@173 76
Chris@173 77 void
Chris@211 78 Overview::registerView(View *view)
Chris@173 79 {
Chris@211 80 m_views.insert(view);
Chris@173 81 update();
Chris@173 82 }
Chris@173 83
Chris@173 84 void
Chris@211 85 Overview::unregisterView(View *view)
Chris@173 86 {
Chris@211 87 m_views.erase(view);
Chris@173 88 update();
Chris@173 89 }
Chris@173 90
Chris@173 91 void
Chris@248 92 Overview::globalCentreFrameChanged(unsigned long)
Chris@173 93 {
Chris@211 94 update();
Chris@211 95 }
Chris@173 96
Chris@211 97 void
Chris@248 98 Overview::viewCentreFrameChanged(View *v, unsigned long)
Chris@211 99 {
Chris@211 100 if (m_views.find(v) != m_views.end()) {
Chris@173 101 update();
Chris@173 102 }
Chris@211 103 }
Chris@173 104
Chris@173 105 void
Chris@248 106 Overview::viewZoomLevelChanged(View *v, unsigned long, bool)
Chris@173 107 {
Chris@222 108 if (v == this) return;
Chris@211 109 if (m_views.find(v) != m_views.end()) {
Chris@173 110 update();
Chris@173 111 }
Chris@173 112 }
Chris@173 113
Chris@173 114 void
Chris@173 115 Overview::viewManagerPlaybackFrameChanged(unsigned long f)
Chris@173 116 {
Chris@173 117 bool changed = false;
Chris@173 118
Chris@173 119 if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true;
Chris@173 120 m_playPointerFrame = f;
Chris@173 121
Chris@173 122 if (changed) update();
Chris@173 123 }
Chris@173 124
Chris@173 125 void
Chris@173 126 Overview::paintEvent(QPaintEvent *e)
Chris@173 127 {
Chris@173 128 // Recalculate zoom in case the size of the widget has changed.
Chris@173 129
Chris@214 130 // std::cerr << "Overview::paintEvent: width is " << width() << ", centre frame " << m_centreFrame << std::endl;
Chris@214 131
Chris@173 132 size_t startFrame = getModelsStartFrame();
Chris@173 133 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
Chris@173 134 int zoomLevel = frameCount / width();
Chris@173 135 if (zoomLevel < 1) zoomLevel = 1;
Chris@173 136 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
Chris@173 137 ZoomConstraint::RoundUp);
Chris@173 138 if (zoomLevel != m_zoomLevel) {
Chris@173 139 m_zoomLevel = zoomLevel;
Chris@222 140 emit zoomLevelChanged(m_zoomLevel, m_followZoom);
Chris@173 141 }
Chris@253 142
Chris@173 143 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
Chris@173 144 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
Chris@173 145 centreFrame = (startFrame + getModelsEndFrame())/2;
Chris@173 146 }
Chris@173 147 if (centreFrame != m_centreFrame) {
Chris@214 148 // std::cerr << "Overview::paintEvent: Centre frame changed from "
Chris@214 149 // << m_centreFrame << " to " << centreFrame << " and thus start frame from " << getStartFrame();
Chris@173 150 m_centreFrame = centreFrame;
Chris@214 151 // std::cerr << " to " << getStartFrame() << std::endl;
Chris@211 152 emit centreFrameChanged(m_centreFrame, false, PlaybackIgnore);
Chris@173 153 }
Chris@173 154
Chris@173 155 View::paintEvent(e);
Chris@173 156
Chris@173 157 QPainter paint;
Chris@173 158 paint.begin(this);
Chris@173 159
Chris@173 160 QRect r(rect());
Chris@173 161
Chris@173 162 if (e) {
Chris@173 163 r = e->rect();
Chris@173 164 paint.setClipRect(r);
Chris@173 165 }
Chris@173 166
Chris@287 167 paint.setPen(getForeground());
Chris@173 168
Chris@173 169 int y = 0;
Chris@173 170
Chris@173 171 int prevx0 = -10;
Chris@173 172 int prevx1 = -10;
Chris@173 173
Chris@211 174 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
Chris@173 175 if (!*i) continue;
Chris@173 176
Chris@173 177 View *w = (View *)*i;
Chris@173 178
Chris@173 179 long f0 = w->getFrameForX(0);
Chris@173 180 long f1 = w->getFrameForX(w->width());
Chris@173 181
Chris@173 182 int x0 = getXForFrame(f0);
Chris@173 183 int x1 = getXForFrame(f1);
Chris@173 184
Chris@173 185 if (x0 != prevx0 || x1 != prevx1) {
Chris@173 186 y += height() / 10 + 1;
Chris@173 187 prevx0 = x0;
Chris@173 188 prevx1 = x1;
Chris@173 189 }
Chris@173 190
Chris@173 191 if (x1 <= x0) x1 = x0 + 1;
Chris@173 192
Chris@173 193 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
Chris@173 194 }
Chris@173 195
Chris@173 196 paint.end();
Chris@173 197 }
Chris@173 198
Chris@173 199 void
Chris@173 200 Overview::mousePressEvent(QMouseEvent *e)
Chris@173 201 {
Chris@173 202 m_clickPos = e->pos();
Chris@211 203 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
Chris@173 204 if (*i) {
Chris@173 205 m_clickedInRange = true;
Chris@173 206 m_dragCentreFrame = ((View *)*i)->getCentreFrame();
Chris@173 207 break;
Chris@173 208 }
Chris@173 209 }
Chris@173 210 }
Chris@173 211
Chris@173 212 void
Chris@173 213 Overview::mouseReleaseEvent(QMouseEvent *e)
Chris@173 214 {
Chris@173 215 if (m_clickedInRange) {
Chris@173 216 mouseMoveEvent(e);
Chris@173 217 }
Chris@173 218 m_clickedInRange = false;
Chris@173 219 }
Chris@173 220
Chris@173 221 void
Chris@173 222 Overview::mouseMoveEvent(QMouseEvent *e)
Chris@173 223 {
Chris@173 224 if (!m_clickedInRange) return;
Chris@173 225
Chris@173 226 long xoff = int(e->x()) - int(m_clickPos.x());
Chris@173 227 long frameOff = xoff * m_zoomLevel;
Chris@173 228
Chris@173 229 size_t newCentreFrame = m_dragCentreFrame;
Chris@173 230 if (frameOff > 0) {
Chris@173 231 newCentreFrame += frameOff;
Chris@173 232 } else if (newCentreFrame >= size_t(-frameOff)) {
Chris@173 233 newCentreFrame += frameOff;
Chris@173 234 } else {
Chris@173 235 newCentreFrame = 0;
Chris@173 236 }
Chris@173 237
Chris@173 238 if (newCentreFrame >= getModelsEndFrame()) {
Chris@173 239 newCentreFrame = getModelsEndFrame();
Chris@173 240 if (newCentreFrame > 0) --newCentreFrame;
Chris@173 241 }
Chris@173 242
Chris@173 243 if (std::max(m_centreFrame, newCentreFrame) -
Chris@173 244 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
Chris@213 245 emit centreFrameChanged(newCentreFrame, true, PlaybackScrollContinuous);
Chris@173 246 }
Chris@173 247 }
Chris@173 248
Chris@189 249 void
Chris@189 250 Overview::mouseDoubleClickEvent(QMouseEvent *e)
Chris@189 251 {
Chris@189 252 long frame = getFrameForX(e->x());
Chris@213 253 emit centreFrameChanged(frame, true, PlaybackScrollContinuous);
Chris@189 254 }
Chris@173 255
Chris@189 256 void
Chris@189 257 Overview::enterEvent(QEvent *)
Chris@189 258 {
Chris@189 259 emit contextHelpChanged(tr("Click and drag to navigate; double-click to jump"));
Chris@189 260 }
Chris@189 261
Chris@189 262 void
Chris@189 263 Overview::leaveEvent(QEvent *)
Chris@189 264 {
Chris@189 265 emit contextHelpChanged("");
Chris@189 266 }
Chris@189 267
Chris@189 268