Chris@127
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@127
|
2
|
Chris@127
|
3 /*
|
Chris@127
|
4 Sonic Visualiser
|
Chris@127
|
5 An audio file viewer and annotation editor.
|
Chris@127
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@127
|
7 This file copyright 2006 Chris Cannam.
|
Chris@127
|
8
|
Chris@127
|
9 This program is free software; you can redistribute it and/or
|
Chris@127
|
10 modify it under the terms of the GNU General Public License as
|
Chris@127
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@127
|
12 License, or (at your option) any later version. See the file
|
Chris@127
|
13 COPYING included with this distribution for more information.
|
Chris@127
|
14 */
|
Chris@127
|
15
|
Chris@127
|
16 #include "Panner.h"
|
Chris@127
|
17 #include "base/Layer.h"
|
Chris@127
|
18 #include "base/Model.h"
|
Chris@127
|
19 #include "base/ZoomConstraint.h"
|
Chris@127
|
20
|
Chris@127
|
21 #include <QPaintEvent>
|
Chris@127
|
22 #include <QPainter>
|
Chris@127
|
23 #include <iostream>
|
Chris@127
|
24
|
Chris@127
|
25 using std::cerr;
|
Chris@127
|
26 using std::endl;
|
Chris@127
|
27
|
Chris@127
|
28 Panner::Panner(QWidget *w) :
|
Chris@127
|
29 View(w, false),
|
Chris@127
|
30 m_clickedInRange(false)
|
Chris@127
|
31 {
|
Chris@127
|
32 setObjectName(tr("Panner"));
|
Chris@127
|
33 m_followPan = false;
|
Chris@127
|
34 m_followZoom = false;
|
Chris@127
|
35 }
|
Chris@127
|
36
|
Chris@127
|
37 void
|
Chris@127
|
38 Panner::modelChanged(size_t startFrame, size_t endFrame)
|
Chris@127
|
39 {
|
Chris@127
|
40 View::modelChanged(startFrame, endFrame);
|
Chris@127
|
41 }
|
Chris@127
|
42
|
Chris@127
|
43 void
|
Chris@127
|
44 Panner::modelReplaced()
|
Chris@127
|
45 {
|
Chris@127
|
46 View::modelReplaced();
|
Chris@127
|
47 }
|
Chris@127
|
48
|
Chris@127
|
49 void
|
Chris@127
|
50 Panner::registerView(View *widget)
|
Chris@127
|
51 {
|
Chris@127
|
52 m_widgets.insert(widget);
|
Chris@127
|
53 update();
|
Chris@127
|
54 }
|
Chris@127
|
55
|
Chris@127
|
56 void
|
Chris@127
|
57 Panner::unregisterView(View *widget)
|
Chris@127
|
58 {
|
Chris@127
|
59 m_widgets.erase(widget);
|
Chris@127
|
60 update();
|
Chris@127
|
61 }
|
Chris@127
|
62
|
Chris@127
|
63 void
|
Chris@127
|
64 Panner::viewManagerCentreFrameChanged(void *p, unsigned long f, bool)
|
Chris@127
|
65 {
|
Chris@127
|
66 // std::cerr << "Panner[" << this << "]::viewManagerCentreFrameChanged("
|
Chris@127
|
67 // << p << ", " << f << ")" << std::endl;
|
Chris@127
|
68
|
Chris@127
|
69 if (p == this) return;
|
Chris@127
|
70 if (m_widgets.find(p) != m_widgets.end()) {
|
Chris@127
|
71 update();
|
Chris@127
|
72 }
|
Chris@127
|
73 }
|
Chris@127
|
74
|
Chris@127
|
75 void
|
Chris@127
|
76 Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool)
|
Chris@127
|
77 {
|
Chris@127
|
78 if (p == this) return;
|
Chris@127
|
79 if (m_widgets.find(p) != m_widgets.end()) {
|
Chris@127
|
80 update();
|
Chris@127
|
81 }
|
Chris@127
|
82 }
|
Chris@127
|
83
|
Chris@127
|
84 void
|
Chris@127
|
85 Panner::viewManagerPlaybackFrameChanged(unsigned long f)
|
Chris@127
|
86 {
|
Chris@127
|
87 bool changed = false;
|
Chris@127
|
88
|
Chris@127
|
89 if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true;
|
Chris@127
|
90 m_playPointerFrame = f;
|
Chris@127
|
91
|
Chris@127
|
92 if (changed) update();
|
Chris@127
|
93 }
|
Chris@127
|
94
|
Chris@127
|
95 void
|
Chris@127
|
96 Panner::paintEvent(QPaintEvent *e)
|
Chris@127
|
97 {
|
Chris@127
|
98 // Recalculate zoom in case the size of the widget has changed.
|
Chris@127
|
99
|
Chris@127
|
100 size_t startFrame = getModelsStartFrame();
|
Chris@127
|
101 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
|
Chris@127
|
102 int zoomLevel = frameCount / width();
|
Chris@127
|
103 if (zoomLevel < 1) zoomLevel = 1;
|
Chris@127
|
104 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
|
Chris@127
|
105 ZoomConstraint::RoundUp);
|
Chris@127
|
106 if (zoomLevel != m_zoomLevel) {
|
Chris@127
|
107 m_zoomLevel = zoomLevel;
|
Chris@127
|
108 emit zoomLevelChanged(this, m_zoomLevel, m_followZoom);
|
Chris@127
|
109 }
|
Chris@127
|
110 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
|
Chris@127
|
111 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
|
Chris@127
|
112 centreFrame = (startFrame + getModelsEndFrame())/2;
|
Chris@127
|
113 }
|
Chris@127
|
114 if (centreFrame != m_centreFrame) {
|
Chris@127
|
115 m_centreFrame = centreFrame;
|
Chris@127
|
116 emit centreFrameChanged(this, m_centreFrame, false);
|
Chris@127
|
117 }
|
Chris@127
|
118
|
Chris@127
|
119 View::paintEvent(e);
|
Chris@127
|
120
|
Chris@127
|
121 QPainter paint;
|
Chris@127
|
122 paint.begin(this);
|
Chris@127
|
123
|
Chris@127
|
124 QRect r(rect());
|
Chris@127
|
125
|
Chris@127
|
126 if (e) {
|
Chris@127
|
127 r = e->rect();
|
Chris@127
|
128 paint.setClipRect(r);
|
Chris@127
|
129 }
|
Chris@127
|
130
|
Chris@127
|
131 paint.setPen(Qt::black);
|
Chris@127
|
132
|
Chris@127
|
133 int y = 0;
|
Chris@127
|
134
|
Chris@127
|
135 int prevx0 = -10;
|
Chris@127
|
136 int prevx1 = -10;
|
Chris@127
|
137
|
Chris@127
|
138 for (WidgetSet::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@127
|
139 if (!*i) continue;
|
Chris@127
|
140
|
Chris@127
|
141 View *w = (View *)*i;
|
Chris@127
|
142
|
Chris@127
|
143 long f0 = w->getFrameForX(0);
|
Chris@127
|
144 long f1 = w->getFrameForX(w->width());
|
Chris@127
|
145
|
Chris@127
|
146 int x0 = getXForFrame(f0);
|
Chris@127
|
147 int x1 = getXForFrame(f1);
|
Chris@127
|
148
|
Chris@127
|
149 if (x0 != prevx0 || x1 != prevx1) {
|
Chris@127
|
150 y += height() / 10 + 1;
|
Chris@127
|
151 prevx0 = x0;
|
Chris@127
|
152 prevx1 = x1;
|
Chris@127
|
153 }
|
Chris@127
|
154
|
Chris@127
|
155 if (x1 <= x0) x1 = x0 + 1;
|
Chris@127
|
156
|
Chris@127
|
157 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
|
Chris@127
|
158 }
|
Chris@127
|
159
|
Chris@127
|
160 paint.end();
|
Chris@127
|
161 }
|
Chris@127
|
162
|
Chris@127
|
163 void
|
Chris@127
|
164 Panner::mousePressEvent(QMouseEvent *e)
|
Chris@127
|
165 {
|
Chris@127
|
166 m_clickPos = e->pos();
|
Chris@127
|
167 for (WidgetSet::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@127
|
168 if (*i) {
|
Chris@127
|
169 m_clickedInRange = true;
|
Chris@127
|
170 m_dragCentreFrame = ((View *)*i)->getCentreFrame();
|
Chris@127
|
171 break;
|
Chris@127
|
172 }
|
Chris@127
|
173 }
|
Chris@127
|
174 }
|
Chris@127
|
175
|
Chris@127
|
176 void
|
Chris@127
|
177 Panner::mouseReleaseEvent(QMouseEvent *e)
|
Chris@127
|
178 {
|
Chris@127
|
179 if (m_clickedInRange) {
|
Chris@127
|
180 mouseMoveEvent(e);
|
Chris@127
|
181 }
|
Chris@127
|
182 m_clickedInRange = false;
|
Chris@127
|
183 }
|
Chris@127
|
184
|
Chris@127
|
185 void
|
Chris@127
|
186 Panner::mouseMoveEvent(QMouseEvent *e)
|
Chris@127
|
187 {
|
Chris@127
|
188 if (!m_clickedInRange) return;
|
Chris@127
|
189
|
Chris@127
|
190 long xoff = int(e->x()) - int(m_clickPos.x());
|
Chris@127
|
191 long frameOff = xoff * m_zoomLevel;
|
Chris@127
|
192
|
Chris@127
|
193 size_t newCentreFrame = m_dragCentreFrame;
|
Chris@127
|
194 if (frameOff > 0) {
|
Chris@127
|
195 newCentreFrame += frameOff;
|
Chris@127
|
196 } else if (newCentreFrame >= size_t(-frameOff)) {
|
Chris@127
|
197 newCentreFrame += frameOff;
|
Chris@127
|
198 } else {
|
Chris@127
|
199 newCentreFrame = 0;
|
Chris@127
|
200 }
|
Chris@127
|
201
|
Chris@127
|
202 if (newCentreFrame >= getModelsEndFrame()) {
|
Chris@127
|
203 newCentreFrame = getModelsEndFrame();
|
Chris@127
|
204 if (newCentreFrame > 0) --newCentreFrame;
|
Chris@127
|
205 }
|
Chris@127
|
206
|
Chris@127
|
207 if (std::max(m_centreFrame, newCentreFrame) -
|
Chris@127
|
208 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
|
Chris@127
|
209 emit centreFrameChanged(this, newCentreFrame, true);
|
Chris@127
|
210 }
|
Chris@127
|
211 }
|
Chris@127
|
212
|
Chris@127
|
213 #ifdef INCLUDE_MOCFILES
|
Chris@127
|
214 #include "Panner.moc.cpp"
|
Chris@127
|
215 #endif
|
Chris@127
|
216
|