annotate view/Overview.cpp @ 294:919740b20cc9

* Better abbreviation modes for layer names in pane (and input model combo of plugin parameter dialog) * Avoid crash when loading SV file containing model derived from nonexistent model (shouldn't happen of course, but see bug #1771769) * Remember last-used input model in plugin parameter dialog * Don't override a layer colour loaded from a session file with the generated default colour when attaching it to a view
author Chris Cannam
date Fri, 10 Aug 2007 16:36:50 +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