annotate widgets/Panner.cpp @ 11:2d5005f2b3d9

* Rework handling of layer properties in file I/O -- we now get the individual layers to load and save them rather than doing it via generic property lists in the base class, so as to ensure we read and write meaningful values rather than generic int values requiring conversion.
author Chris Cannam
date Thu, 19 Jan 2006 12:54:38 +0000
parents 37b110168acf
children 38fe0ea9e46e
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@5 5 Chris Cannam, Queen Mary University of London, 2005-2006
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