annotate widgets/Panner.cpp @ 4:ce747045a023

* Invalidate cache when model replaced
author Chris Cannam
date Thu, 12 Jan 2006 13:43:15 +0000
parents 2a4f26e85b4c
children 37b110168acf
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@0 5 Chris Cannam, Queen Mary University of London, 2005
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #include "Panner.h"
Chris@0 11 #include "base/Layer.h"
Chris@0 12 #include "base/Model.h"
Chris@0 13 #include "base/ZoomConstraint.h"
Chris@0 14
Chris@0 15 #include <QPaintEvent>
Chris@0 16 #include <QPainter>
Chris@0 17 #include <iostream>
Chris@0 18
Chris@0 19 using std::cerr;
Chris@0 20 using std::endl;
Chris@0 21
Chris@0 22 Panner::Panner(QWidget *w) :
Chris@0 23 View(w, false),
Chris@0 24 m_clickedInRange(false)
Chris@0 25 {
Chris@0 26 setObjectName(tr("Panner"));
Chris@0 27 m_followPan = false;
Chris@0 28 m_followZoom = false;
Chris@0 29 }
Chris@0 30
Chris@0 31 void
Chris@0 32 Panner::modelChanged(size_t startFrame, size_t endFrame)
Chris@0 33 {
Chris@0 34 View::modelChanged(startFrame, endFrame);
Chris@0 35 }
Chris@0 36
Chris@0 37 void
Chris@0 38 Panner::modelReplaced()
Chris@0 39 {
Chris@0 40 View::modelReplaced();
Chris@0 41 }
Chris@0 42
Chris@0 43 void
Chris@0 44 Panner::registerView(View *widget)
Chris@0 45 {
Chris@0 46 m_widgets[widget] = WidgetRec(0, -1);
Chris@0 47 update();
Chris@0 48 }
Chris@0 49
Chris@0 50 void
Chris@0 51 Panner::unregisterView(View *widget)
Chris@0 52 {
Chris@0 53 m_widgets.erase(widget);
Chris@0 54 update();
Chris@0 55 }
Chris@0 56
Chris@0 57 void
Chris@0 58 Panner::viewManagerCentreFrameChanged(void *p, unsigned long f, bool)
Chris@0 59 {
Chris@0 60 // std::cerr << "Panner[" << this << "]::viewManagerCentreFrameChanged("
Chris@0 61 // << p << ", " << f << ")" << std::endl;
Chris@0 62
Chris@0 63 if (p == this) return;
Chris@0 64 if (m_widgets.find(p) != m_widgets.end()) {
Chris@0 65 m_widgets[p].first = f;
Chris@0 66 update();
Chris@0 67 }
Chris@0 68 }
Chris@0 69
Chris@0 70 void
Chris@0 71 Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool)
Chris@0 72 {
Chris@0 73 if (p == this) return;
Chris@0 74 if (m_widgets.find(p) != m_widgets.end()) {
Chris@0 75 m_widgets[p].second = z;
Chris@0 76 update();
Chris@0 77 }
Chris@0 78 }
Chris@0 79
Chris@0 80 void
Chris@0 81 Panner::viewManagerPlaybackFrameChanged(unsigned long f)
Chris@0 82 {
Chris@0 83 bool changed = false;
Chris@0 84
Chris@0 85 if (m_playPointerFrame / m_zoomLevel != f / m_zoomLevel) changed = true;
Chris@0 86 m_playPointerFrame = f;
Chris@0 87
Chris@0 88 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
Chris@0 89 unsigned long of = i->second.first;
Chris@0 90 i->second.first = f;
Chris@0 91 if (of / m_zoomLevel != f / m_zoomLevel) changed = true;
Chris@0 92 }
Chris@0 93
Chris@0 94 if (changed) update();
Chris@0 95 }
Chris@0 96
Chris@0 97 void
Chris@0 98 Panner::paintEvent(QPaintEvent *e)
Chris@0 99 {
Chris@0 100 /*!!!
Chris@0 101 // Force View to recalculate zoom in case the size of the
Chris@0 102 // widget has changed. (We need a better name/mechanism for this)
Chris@0 103 m_newModel = true;
Chris@0 104 */
Chris@0 105
Chris@0 106 // Recalculate zoom in case the size of the widget has changed.
Chris@0 107
Chris@0 108 size_t startFrame = getModelsStartFrame();
Chris@0 109 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
Chris@0 110 int zoomLevel = frameCount / width();
Chris@0 111 if (zoomLevel < 1) zoomLevel = 1;
Chris@0 112 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
Chris@0 113 ZoomConstraint::RoundUp);
Chris@0 114 if (zoomLevel != m_zoomLevel) {
Chris@0 115 m_zoomLevel = zoomLevel;
Chris@0 116 emit zoomLevelChanged(this, m_zoomLevel, m_followZoom);
Chris@0 117 }
Chris@0 118 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
Chris@0 119 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
Chris@0 120 centreFrame = (startFrame + getModelsEndFrame())/2;
Chris@0 121 }
Chris@0 122 if (centreFrame != m_centreFrame) {
Chris@0 123 m_centreFrame = centreFrame;
Chris@0 124 emit centreFrameChanged(this, m_centreFrame, false);
Chris@0 125 }
Chris@0 126
Chris@0 127 View::paintEvent(e);
Chris@0 128
Chris@0 129 QPainter paint;
Chris@0 130 paint.begin(this);
Chris@0 131
Chris@0 132 QRect r(rect());
Chris@0 133
Chris@0 134 if (e) {
Chris@0 135 r = e->rect();
Chris@0 136 paint.setClipRect(r);
Chris@0 137 }
Chris@0 138
Chris@0 139 paint.setPen(Qt::black);
Chris@0 140
Chris@0 141 int y = 0;
Chris@0 142 long prevCentre = 0;
Chris@0 143 long prevZoom = -1;
Chris@0 144
Chris@0 145 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
Chris@0 146 if (!i->first) continue;
Chris@0 147
Chris@0 148 View *w = (View *)i->first;
Chris@0 149 if (i->second.second < 0) i->second.second = w->getZoomLevel();
Chris@0 150 if (i->second.second < 0) continue;
Chris@0 151
Chris@0 152 long c = (long)i->second.first;
Chris@0 153 long z = (long)i->second.second;
Chris@0 154
Chris@0 155 long f0 = c - (w->width() / 2) * z;
Chris@0 156 long f1 = c + (w->width() / 2) * z;
Chris@0 157
Chris@0 158 int x0 = (f0 - long(getCentreFrame())) / getZoomLevel() + width()/2;
Chris@0 159 int x1 = (f1 - long(getCentreFrame())) / getZoomLevel() + width()/2 - 1;
Chris@0 160
Chris@0 161 if (c != prevCentre || z != prevZoom) {
Chris@0 162 y += height() / 10 + 1;
Chris@0 163 prevCentre = c;
Chris@0 164 prevZoom = z;
Chris@0 165 }
Chris@0 166
Chris@0 167 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
Chris@0 168 }
Chris@0 169
Chris@0 170 paint.end();
Chris@0 171 }
Chris@0 172
Chris@0 173 void
Chris@0 174 Panner::mousePressEvent(QMouseEvent *e)
Chris@0 175 {
Chris@0 176 m_clickPos = e->pos();
Chris@0 177 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
Chris@0 178 if (i->first && i->second.second >= 0) {
Chris@0 179 m_clickedInRange = true;
Chris@0 180 m_dragCentreFrame = i->second.first;
Chris@0 181 }
Chris@0 182 }
Chris@0 183 }
Chris@0 184
Chris@0 185 void
Chris@0 186 Panner::mouseReleaseEvent(QMouseEvent *e)
Chris@0 187 {
Chris@0 188 if (m_clickedInRange) {
Chris@0 189 mouseMoveEvent(e);
Chris@0 190 }
Chris@0 191 m_clickedInRange = false;
Chris@0 192 }
Chris@0 193
Chris@0 194 void
Chris@0 195 Panner::mouseMoveEvent(QMouseEvent *e)
Chris@0 196 {
Chris@0 197 if (!m_clickedInRange) return;
Chris@0 198
Chris@0 199 /*!!!
Chris@0 200 long newFrame = getStartFrame() + e->x() * m_zoomLevel;
Chris@0 201
Chris@0 202 if (newFrame < 0) newFrame = 0;
Chris@0 203 if (newFrame >= getModelsEndFrame()) {
Chris@0 204 newFrame = getModelsEndFrame();
Chris@0 205 if (newFrame > 0) --newFrame;
Chris@0 206 }
Chris@0 207 emit centreFrameChanged(this, newFrame, true);
Chris@0 208 */
Chris@0 209
Chris@0 210 long xoff = int(e->x()) - int(m_clickPos.x());
Chris@0 211 long frameOff = xoff * m_zoomLevel;
Chris@0 212
Chris@0 213 size_t newCentreFrame = m_dragCentreFrame;
Chris@0 214 if (frameOff > 0) {
Chris@0 215 newCentreFrame += frameOff;
Chris@0 216 } else if (newCentreFrame >= size_t(-frameOff)) {
Chris@0 217 newCentreFrame += frameOff;
Chris@0 218 } else {
Chris@0 219 newCentreFrame = 0;
Chris@0 220 }
Chris@0 221
Chris@0 222 if (newCentreFrame >= getModelsEndFrame()) {
Chris@0 223 newCentreFrame = getModelsEndFrame();
Chris@0 224 if (newCentreFrame > 0) --newCentreFrame;
Chris@0 225 }
Chris@0 226
Chris@0 227 if (std::max(m_centreFrame, newCentreFrame) -
Chris@0 228 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
Chris@0 229 emit centreFrameChanged(this, newCentreFrame, true);
Chris@0 230 }
Chris@0 231 }
Chris@0 232
Chris@0 233 #ifdef INCLUDE_MOCFILES
Chris@0 234 #include "Panner.moc.cpp"
Chris@0 235 #endif
Chris@0 236