annotate panner.cpp @ 200:8c8c04bdf0fa

* Separate out the hg test action into two tests, one for plain hg and one with the extension (so can report separately)
author Chris Cannam
date Tue, 04 Jan 2011 12:42:28 +0000
parents a6d336837ebe
children 8fd71f570884
rev   line source
Chris@57 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@45 2
cannam@45 3 /*
Chris@57 4 EasyMercurial
Chris@57 5
Chris@57 6 Based on HgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@57 8 Copyright (c) 2010 Chris Cannam
Chris@57 9 Copyright (c) 2010 Queen Mary, University of London
Chris@57 10
cannam@45 11 This program is free software; you can redistribute it and/or
cannam@45 12 modify it under the terms of the GNU General Public License as
cannam@45 13 published by the Free Software Foundation; either version 2 of the
cannam@45 14 License, or (at your option) any later version. See the file
cannam@45 15 COPYING included with this distribution for more information.
cannam@45 16 */
cannam@45 17
cannam@45 18 #include "panner.h"
cannam@45 19 #include "panned.h"
Chris@113 20 #include "debug.h"
cannam@45 21
cannam@45 22 #include <QPolygon>
cannam@45 23 #include <QMouseEvent>
cannam@45 24 #include <QColor>
cannam@45 25
cannam@45 26 #include <iostream>
cannam@45 27
cannam@45 28 class PannerScene : public QGraphicsScene
cannam@45 29 {
cannam@45 30 public:
cannam@45 31 friend class Panner;
cannam@45 32 };
cannam@45 33
cannam@45 34 Panner::Panner() :
cannam@45 35 m_clicked(false)
cannam@45 36 {
cannam@45 37 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
cannam@45 38 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
Chris@48 39 setOptimizationFlags(QGraphicsView::DontSavePainterState |
Chris@48 40 QGraphicsView::IndirectPainting);
cannam@45 41 setMouseTracking(true);
cannam@45 42 setInteractive(false);
cannam@45 43 }
cannam@45 44
cannam@45 45 void
Chris@113 46 Panner::fit(QRectF r)
Chris@113 47 {
Chris@113 48 Qt::AspectRatioMode m = Qt::IgnoreAspectRatio;
Chris@113 49 if (height() > width()) {
Chris@113 50 // Our panner is vertical; if the source is not tall,
Chris@113 51 // don't stretch it to fit in the height, it'd look weird
Chris@113 52 if (r.height() < height() * 2) {
Chris@113 53 m = Qt::KeepAspectRatio;
Chris@113 54 }
Chris@113 55 } else {
Chris@113 56 // Similarly, but horizontal
Chris@113 57 if (r.width() < width() * 2) {
Chris@113 58 m = Qt::KeepAspectRatio;
Chris@113 59 }
Chris@113 60 }
Chris@113 61 DEBUG << "Panner: fit mode " << m << endl;
Chris@113 62 fitInView(r, m);
Chris@113 63 }
Chris@113 64
Chris@113 65 void
cannam@45 66 Panner::setScene(QGraphicsScene *s)
cannam@45 67 {
cannam@45 68 if (scene()) {
Chris@133 69 disconnect(scene(), SIGNAL(changed(const QList<QRectF> &)),
Chris@132 70 this, SLOT(slotSceneChanged(const QList<QRectF> &)));
cannam@45 71 disconnect(scene(), SIGNAL(sceneRectChanged(const QRectF &)),
cannam@45 72 this, SLOT(slotSceneRectChanged(const QRectF &)));
cannam@45 73 }
cannam@45 74 QGraphicsView::setScene(s);
Chris@136 75 m_cache = QPixmap();
Chris@113 76 if (scene()) {
Chris@113 77 QRectF r = sceneRect();
Chris@113 78 DEBUG << "scene rect: " << r << ", my rect " << rect() << endl;
Chris@113 79 fit(r);
Chris@136 80 connect(scene(), SIGNAL(changed(const QList<QRectF> &)),
Chris@136 81 this, SLOT(slotSceneChanged(const QList<QRectF> &)));
Chris@136 82 connect(scene(), SIGNAL(sceneRectChanged(const QRectF &)),
Chris@136 83 this, SLOT(slotSceneRectChanged(const QRectF &)));
Chris@113 84 }
cannam@45 85 }
cannam@45 86
cannam@45 87 void
cannam@45 88 Panner::connectToPanned(Panned *p)
cannam@45 89 {
cannam@45 90 connect(p, SIGNAL(pannedRectChanged(QRectF)),
cannam@45 91 this, SLOT(slotSetPannedRect(QRectF)));
cannam@45 92
cannam@45 93 connect(this, SIGNAL(pannedRectChanged(QRectF)),
cannam@45 94 p, SLOT(slotSetPannedRect(QRectF)));
Chris@53 95
Chris@53 96 connect(this, SIGNAL(zoomIn()),
Chris@53 97 p, SLOT(zoomIn()));
Chris@53 98
Chris@53 99 connect(this, SIGNAL(zoomOut()),
Chris@53 100 p, SLOT(zoomOut()));
cannam@45 101 }
cannam@45 102
cannam@45 103 void
cannam@45 104 Panner::slotSetPannedRect(QRectF rect)
cannam@45 105 {
cannam@45 106 m_pannedRect = rect;
cannam@45 107 viewport()->update();
cannam@45 108 }
cannam@45 109
cannam@45 110 void
cannam@45 111 Panner::resizeEvent(QResizeEvent *)
cannam@45 112 {
Chris@113 113 if (scene()) fit(sceneRect());
cannam@45 114 m_cache = QPixmap();
cannam@45 115 }
cannam@45 116
cannam@45 117 void
cannam@45 118 Panner::slotSceneRectChanged(const QRectF &newRect)
cannam@45 119 {
cannam@45 120 if (!scene()) return; // spurious
Chris@113 121 fit(newRect);
cannam@45 122 m_cache = QPixmap();
cannam@45 123 viewport()->update();
cannam@45 124 }
cannam@45 125
cannam@45 126 void
Chris@132 127 Panner::slotSceneChanged(const QList<QRectF> &)
Chris@132 128 {
Chris@132 129 if (!scene()) return; // spurious
Chris@132 130 m_cache = QPixmap();
Chris@132 131 viewport()->update();
Chris@132 132 }
Chris@132 133
Chris@132 134 void
cannam@45 135 Panner::paintEvent(QPaintEvent *e)
cannam@45 136 {
cannam@45 137 QPaintEvent *e2 = new QPaintEvent(e->region().boundingRect());
cannam@45 138 QGraphicsView::paintEvent(e2);
cannam@45 139
cannam@45 140 QPainter paint;
cannam@45 141 paint.begin(viewport());
cannam@45 142 paint.setClipRegion(e->region());
cannam@45 143
cannam@45 144 QPainterPath path;
cannam@45 145 path.addRect(rect());
cannam@45 146 path.addPolygon(mapFromScene(m_pannedRect));
cannam@45 147
cannam@45 148 QColor c(QColor::fromHsv(211, 194, 238));
cannam@45 149 c.setAlpha(80);
cannam@45 150 paint.setPen(Qt::NoPen);
cannam@45 151 paint.setBrush(c);
cannam@45 152 paint.drawPath(path);
cannam@45 153
cannam@45 154 paint.setBrush(Qt::NoBrush);
cannam@45 155 paint.setPen(QPen(QColor::fromHsv(211, 194, 238), 0));
cannam@45 156 paint.drawConvexPolygon(mapFromScene(m_pannedRect));
cannam@45 157
cannam@45 158 paint.end();
cannam@45 159
cannam@45 160 emit pannerChanged(m_pannedRect);
cannam@45 161 }
cannam@45 162
cannam@45 163 void
cannam@45 164 Panner::updateScene(const QList<QRectF> &rects)
cannam@45 165 {
cannam@45 166 if (!m_cache.isNull()) m_cache = QPixmap();
cannam@45 167 QGraphicsView::updateScene(rects);
cannam@45 168 }
cannam@45 169
cannam@45 170 void
cannam@45 171 Panner::drawItems(QPainter *painter, int numItems,
cannam@45 172 QGraphicsItem *items[],
cannam@45 173 const QStyleOptionGraphicsItem options[])
cannam@45 174 {
cannam@45 175 if (m_cache.size() != viewport()->size()) {
cannam@45 176
Chris@131 177 DEBUG << "Panner: cache size " << m_cache.size() << " != viewport size " << viewport()->size() << ": recreating cache" << endl;
Chris@48 178
cannam@45 179 QGraphicsScene *s = scene();
cannam@45 180 if (!s) return;
cannam@45 181 PannerScene *ps = static_cast<PannerScene *>(s);
cannam@45 182
cannam@45 183 m_cache = QPixmap(viewport()->size());
cannam@45 184 m_cache.fill(Qt::transparent);
cannam@45 185 QPainter cachePainter;
cannam@45 186 cachePainter.begin(&m_cache);
cannam@45 187 cachePainter.setTransform(viewportTransform());
cannam@45 188 ps->drawItems(&cachePainter, numItems, items, options);
cannam@45 189 cachePainter.end();
cannam@45 190 }
cannam@45 191
cannam@45 192 painter->save();
cannam@45 193 painter->setTransform(QTransform());
cannam@45 194 painter->drawPixmap(0, 0, m_cache);
cannam@45 195 painter->restore();
cannam@45 196 }
cannam@45 197
cannam@45 198 void
cannam@45 199 Panner::mousePressEvent(QMouseEvent *e)
cannam@45 200 {
cannam@45 201 if (e->button() != Qt::LeftButton) {
cannam@45 202 QGraphicsView::mouseDoubleClickEvent(e);
cannam@45 203 return;
cannam@45 204 }
cannam@45 205 m_clicked = true;
cannam@45 206 m_clickedRect = m_pannedRect;
cannam@45 207 m_clickedPoint = e->pos();
cannam@45 208 }
cannam@45 209
cannam@45 210 void
cannam@45 211 Panner::mouseDoubleClickEvent(QMouseEvent *e)
cannam@45 212 {
cannam@45 213 if (e->button() != Qt::LeftButton) {
cannam@45 214 QGraphicsView::mouseDoubleClickEvent(e);
cannam@45 215 return;
cannam@45 216 }
cannam@45 217
cannam@45 218 moveTo(e->pos());
cannam@45 219 }
cannam@45 220
cannam@45 221 void
cannam@45 222 Panner::mouseMoveEvent(QMouseEvent *e)
cannam@45 223 {
cannam@45 224 if (!m_clicked) return;
cannam@45 225 QPointF cp = mapToScene(m_clickedPoint);
cannam@45 226 QPointF mp = mapToScene(e->pos());
cannam@45 227 QPointF delta = mp - cp;
cannam@45 228 QRectF nr = m_clickedRect;
cannam@45 229 nr.translate(delta);
Chris@173 230 m_pannedRect = nr;
cannam@45 231 emit pannedRectChanged(m_pannedRect);
cannam@45 232 viewport()->update();
cannam@45 233 }
cannam@45 234
cannam@45 235 void
cannam@45 236 Panner::mouseReleaseEvent(QMouseEvent *e)
cannam@45 237 {
cannam@45 238 if (e->button() != Qt::LeftButton) {
cannam@45 239 QGraphicsView::mouseDoubleClickEvent(e);
cannam@45 240 return;
cannam@45 241 }
cannam@45 242
cannam@45 243 if (m_clicked) {
cannam@45 244 mouseMoveEvent(e);
cannam@45 245 }
cannam@45 246
cannam@45 247 m_clicked = false;
cannam@45 248 viewport()->update();
cannam@45 249 }
cannam@45 250
cannam@45 251 void
cannam@45 252 Panner::wheelEvent(QWheelEvent *e)
cannam@45 253 {
Chris@53 254 int d = e->delta();
Chris@53 255 if (d > 0) {
Chris@53 256 while (d > 0) {
Chris@53 257 emit zoomOut();
Chris@53 258 d -= 120;
Chris@53 259 }
cannam@45 260 } else {
Chris@53 261 while (d < 0) {
Chris@53 262 emit zoomIn();
Chris@53 263 d += 120;
Chris@53 264 }
cannam@45 265 }
cannam@45 266 }
cannam@45 267
cannam@45 268 void
cannam@45 269 Panner::moveTo(QPoint p)
cannam@45 270 {
cannam@45 271 QPointF sp = mapToScene(p);
cannam@45 272 QRectF nr = m_pannedRect;
cannam@45 273 double d = sp.x() - nr.center().x();
cannam@45 274 nr.translate(d, 0);
cannam@45 275 slotSetPannedRect(nr);
cannam@45 276 emit pannedRectChanged(m_pannedRect);
cannam@45 277 viewport()->update();
cannam@45 278 }
cannam@45 279