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@173
|
36 }
|
Chris@173
|
37
|
Chris@173
|
38 void
|
Chris@173
|
39 Overview::modelChanged(size_t startFrame, size_t endFrame)
|
Chris@173
|
40 {
|
Chris@253
|
41 bool zoomChanged = false;
|
Chris@253
|
42
|
Chris@253
|
43 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
|
Chris@253
|
44 int zoomLevel = frameCount / width();
|
Chris@253
|
45 if (zoomLevel < 1) zoomLevel = 1;
|
Chris@253
|
46 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
|
Chris@253
|
47 ZoomConstraint::RoundUp);
|
Chris@253
|
48 if (zoomLevel != m_zoomLevel) {
|
Chris@253
|
49 zoomChanged = true;
|
Chris@253
|
50 }
|
Chris@253
|
51
|
Chris@253
|
52 if (!zoomChanged) {
|
Chris@253
|
53 for (LayerList::const_iterator i = m_layers.begin();
|
Chris@253
|
54 i != m_layers.end(); ++i) {
|
Chris@253
|
55 if ((*i)->getModel() &&
|
Chris@253
|
56 !(*i)->getModel()->isOK() ||
|
Chris@253
|
57 !(*i)->getModel()->isReady()) {
|
Chris@253
|
58 return;
|
Chris@253
|
59 }
|
Chris@253
|
60 }
|
Chris@253
|
61 }
|
Chris@253
|
62
|
Chris@173
|
63 View::modelChanged(startFrame, endFrame);
|
Chris@173
|
64 }
|
Chris@173
|
65
|
Chris@173
|
66 void
|
Chris@173
|
67 Overview::modelReplaced()
|
Chris@173
|
68 {
|
Chris@173
|
69 View::modelReplaced();
|
Chris@173
|
70 }
|
Chris@173
|
71
|
Chris@173
|
72 void
|
Chris@211
|
73 Overview::registerView(View *view)
|
Chris@173
|
74 {
|
Chris@211
|
75 m_views.insert(view);
|
Chris@173
|
76 update();
|
Chris@173
|
77 }
|
Chris@173
|
78
|
Chris@173
|
79 void
|
Chris@211
|
80 Overview::unregisterView(View *view)
|
Chris@173
|
81 {
|
Chris@211
|
82 m_views.erase(view);
|
Chris@173
|
83 update();
|
Chris@173
|
84 }
|
Chris@173
|
85
|
Chris@173
|
86 void
|
Chris@248
|
87 Overview::globalCentreFrameChanged(unsigned long)
|
Chris@173
|
88 {
|
Chris@211
|
89 update();
|
Chris@211
|
90 }
|
Chris@173
|
91
|
Chris@211
|
92 void
|
Chris@248
|
93 Overview::viewCentreFrameChanged(View *v, unsigned long)
|
Chris@211
|
94 {
|
Chris@211
|
95 if (m_views.find(v) != m_views.end()) {
|
Chris@173
|
96 update();
|
Chris@173
|
97 }
|
Chris@211
|
98 }
|
Chris@173
|
99
|
Chris@173
|
100 void
|
Chris@248
|
101 Overview::viewZoomLevelChanged(View *v, unsigned long, bool)
|
Chris@173
|
102 {
|
Chris@222
|
103 if (v == this) return;
|
Chris@211
|
104 if (m_views.find(v) != m_views.end()) {
|
Chris@173
|
105 update();
|
Chris@173
|
106 }
|
Chris@173
|
107 }
|
Chris@173
|
108
|
Chris@173
|
109 void
|
Chris@173
|
110 Overview::viewManagerPlaybackFrameChanged(unsigned long f)
|
Chris@173
|
111 {
|
Chris@173
|
112 bool changed = false;
|
Chris@173
|
113
|
Chris@173
|
114 if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true;
|
Chris@173
|
115 m_playPointerFrame = f;
|
Chris@173
|
116
|
Chris@173
|
117 if (changed) update();
|
Chris@173
|
118 }
|
Chris@173
|
119
|
Chris@173
|
120 void
|
Chris@173
|
121 Overview::paintEvent(QPaintEvent *e)
|
Chris@173
|
122 {
|
Chris@173
|
123 // Recalculate zoom in case the size of the widget has changed.
|
Chris@173
|
124
|
Chris@214
|
125 // std::cerr << "Overview::paintEvent: width is " << width() << ", centre frame " << m_centreFrame << std::endl;
|
Chris@214
|
126
|
Chris@173
|
127 size_t startFrame = getModelsStartFrame();
|
Chris@173
|
128 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
|
Chris@173
|
129 int zoomLevel = frameCount / width();
|
Chris@173
|
130 if (zoomLevel < 1) zoomLevel = 1;
|
Chris@173
|
131 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
|
Chris@173
|
132 ZoomConstraint::RoundUp);
|
Chris@173
|
133 if (zoomLevel != m_zoomLevel) {
|
Chris@173
|
134 m_zoomLevel = zoomLevel;
|
Chris@222
|
135 emit zoomLevelChanged(m_zoomLevel, m_followZoom);
|
Chris@173
|
136 }
|
Chris@253
|
137
|
Chris@173
|
138 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
|
Chris@173
|
139 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
|
Chris@173
|
140 centreFrame = (startFrame + getModelsEndFrame())/2;
|
Chris@173
|
141 }
|
Chris@173
|
142 if (centreFrame != m_centreFrame) {
|
Chris@214
|
143 // std::cerr << "Overview::paintEvent: Centre frame changed from "
|
Chris@214
|
144 // << m_centreFrame << " to " << centreFrame << " and thus start frame from " << getStartFrame();
|
Chris@173
|
145 m_centreFrame = centreFrame;
|
Chris@214
|
146 // std::cerr << " to " << getStartFrame() << std::endl;
|
Chris@211
|
147 emit centreFrameChanged(m_centreFrame, false, PlaybackIgnore);
|
Chris@173
|
148 }
|
Chris@173
|
149
|
Chris@173
|
150 View::paintEvent(e);
|
Chris@173
|
151
|
Chris@173
|
152 QPainter paint;
|
Chris@173
|
153 paint.begin(this);
|
Chris@173
|
154
|
Chris@173
|
155 QRect r(rect());
|
Chris@173
|
156
|
Chris@173
|
157 if (e) {
|
Chris@173
|
158 r = e->rect();
|
Chris@173
|
159 paint.setClipRect(r);
|
Chris@173
|
160 }
|
Chris@173
|
161
|
Chris@173
|
162 paint.setPen(Qt::black);
|
Chris@173
|
163
|
Chris@173
|
164 int y = 0;
|
Chris@173
|
165
|
Chris@173
|
166 int prevx0 = -10;
|
Chris@173
|
167 int prevx1 = -10;
|
Chris@173
|
168
|
Chris@211
|
169 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
|
Chris@173
|
170 if (!*i) continue;
|
Chris@173
|
171
|
Chris@173
|
172 View *w = (View *)*i;
|
Chris@173
|
173
|
Chris@173
|
174 long f0 = w->getFrameForX(0);
|
Chris@173
|
175 long f1 = w->getFrameForX(w->width());
|
Chris@173
|
176
|
Chris@173
|
177 int x0 = getXForFrame(f0);
|
Chris@173
|
178 int x1 = getXForFrame(f1);
|
Chris@173
|
179
|
Chris@173
|
180 if (x0 != prevx0 || x1 != prevx1) {
|
Chris@173
|
181 y += height() / 10 + 1;
|
Chris@173
|
182 prevx0 = x0;
|
Chris@173
|
183 prevx1 = x1;
|
Chris@173
|
184 }
|
Chris@173
|
185
|
Chris@173
|
186 if (x1 <= x0) x1 = x0 + 1;
|
Chris@173
|
187
|
Chris@173
|
188 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
|
Chris@173
|
189 }
|
Chris@173
|
190
|
Chris@173
|
191 paint.end();
|
Chris@173
|
192 }
|
Chris@173
|
193
|
Chris@173
|
194 void
|
Chris@173
|
195 Overview::mousePressEvent(QMouseEvent *e)
|
Chris@173
|
196 {
|
Chris@173
|
197 m_clickPos = e->pos();
|
Chris@211
|
198 for (ViewSet::iterator i = m_views.begin(); i != m_views.end(); ++i) {
|
Chris@173
|
199 if (*i) {
|
Chris@173
|
200 m_clickedInRange = true;
|
Chris@173
|
201 m_dragCentreFrame = ((View *)*i)->getCentreFrame();
|
Chris@173
|
202 break;
|
Chris@173
|
203 }
|
Chris@173
|
204 }
|
Chris@173
|
205 }
|
Chris@173
|
206
|
Chris@173
|
207 void
|
Chris@173
|
208 Overview::mouseReleaseEvent(QMouseEvent *e)
|
Chris@173
|
209 {
|
Chris@173
|
210 if (m_clickedInRange) {
|
Chris@173
|
211 mouseMoveEvent(e);
|
Chris@173
|
212 }
|
Chris@173
|
213 m_clickedInRange = false;
|
Chris@173
|
214 }
|
Chris@173
|
215
|
Chris@173
|
216 void
|
Chris@173
|
217 Overview::mouseMoveEvent(QMouseEvent *e)
|
Chris@173
|
218 {
|
Chris@173
|
219 if (!m_clickedInRange) return;
|
Chris@173
|
220
|
Chris@173
|
221 long xoff = int(e->x()) - int(m_clickPos.x());
|
Chris@173
|
222 long frameOff = xoff * m_zoomLevel;
|
Chris@173
|
223
|
Chris@173
|
224 size_t newCentreFrame = m_dragCentreFrame;
|
Chris@173
|
225 if (frameOff > 0) {
|
Chris@173
|
226 newCentreFrame += frameOff;
|
Chris@173
|
227 } else if (newCentreFrame >= size_t(-frameOff)) {
|
Chris@173
|
228 newCentreFrame += frameOff;
|
Chris@173
|
229 } else {
|
Chris@173
|
230 newCentreFrame = 0;
|
Chris@173
|
231 }
|
Chris@173
|
232
|
Chris@173
|
233 if (newCentreFrame >= getModelsEndFrame()) {
|
Chris@173
|
234 newCentreFrame = getModelsEndFrame();
|
Chris@173
|
235 if (newCentreFrame > 0) --newCentreFrame;
|
Chris@173
|
236 }
|
Chris@173
|
237
|
Chris@173
|
238 if (std::max(m_centreFrame, newCentreFrame) -
|
Chris@173
|
239 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
|
Chris@213
|
240 emit centreFrameChanged(newCentreFrame, true, PlaybackScrollContinuous);
|
Chris@173
|
241 }
|
Chris@173
|
242 }
|
Chris@173
|
243
|
Chris@189
|
244 void
|
Chris@189
|
245 Overview::mouseDoubleClickEvent(QMouseEvent *e)
|
Chris@189
|
246 {
|
Chris@189
|
247 long frame = getFrameForX(e->x());
|
Chris@213
|
248 emit centreFrameChanged(frame, true, PlaybackScrollContinuous);
|
Chris@189
|
249 }
|
Chris@173
|
250
|
Chris@189
|
251 void
|
Chris@189
|
252 Overview::enterEvent(QEvent *)
|
Chris@189
|
253 {
|
Chris@189
|
254 emit contextHelpChanged(tr("Click and drag to navigate; double-click to jump"));
|
Chris@189
|
255 }
|
Chris@189
|
256
|
Chris@189
|
257 void
|
Chris@189
|
258 Overview::leaveEvent(QEvent *)
|
Chris@189
|
259 {
|
Chris@189
|
260 emit contextHelpChanged("");
|
Chris@189
|
261 }
|
Chris@189
|
262
|
Chris@189
|
263
|