annotate widgets/Panner.cpp @ 77:fd348f36c0d3

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