annotate src/panned.cpp @ 571:012ba1b83328

Show cancel button with progress bar only when running an operation that it makes sense to cancel (we don't really want people cancelling e.g. initial folder scan because it would leave things in an inconsistent state)
author Chris Cannam
date Thu, 01 Mar 2012 22:53:54 +0000
parents 533519ebc0cb
children ae67ea0af696
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
cannam@45 5
Chris@57 6 Based on HgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@560 8 Copyright (c) 2012 Chris Cannam
Chris@560 9 Copyright (c) 2012 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 "panned.h"
Chris@131 19 #include "debug.h"
cannam@45 20
cannam@45 21 #include <QScrollBar>
Chris@53 22 #include <QWheelEvent>
Chris@168 23 #include <QTimer>
Chris@168 24
Chris@168 25 #include <cmath>
cannam@45 26
cannam@45 27 #include <iostream>
cannam@45 28
Chris@168 29 Panned::Panned() :
Chris@168 30 m_dragging(false)
cannam@45 31 {
Chris@168 32 m_dragTimer = new QTimer(this);
Chris@168 33 m_dragTimerMs = 50;
Chris@168 34 connect(m_dragTimer, SIGNAL(timeout()), this, SLOT(dragTimerTimeout()));
Chris@56 35 setRenderHints(QPainter::Antialiasing |
Chris@56 36 QPainter::TextAntialiasing);
cannam@45 37 }
cannam@45 38
cannam@45 39 void
cannam@45 40 Panned::resizeEvent(QResizeEvent *ev)
cannam@45 41 {
Chris@131 42 DEBUG << "Panned::resizeEvent()" << endl;
Chris@131 43
Chris@60 44 QPointF nearpt = mapToScene(0, 0);
Chris@60 45 QPointF farpt = mapToScene(width(), height());
Chris@60 46 QSizeF sz(farpt.x()-nearpt.x(), farpt.y()-nearpt.y());
Chris@60 47 QRectF pr(nearpt, sz);
cannam@45 48
Chris@132 49 QGraphicsView::resizeEvent(ev);
Chris@132 50
cannam@45 51 if (pr != m_pannedRect) {
Chris@132 52 DEBUG << "Panned: setting panned rect to " << pr << endl;
cannam@45 53 m_pannedRect = pr;
Chris@133 54 centerOn(pr.center());
Chris@133 55 emit pannedRectChanged(pr);
Chris@133 56 }
Chris@133 57 }
Chris@133 58
Chris@133 59 void
Chris@133 60 Panned::setScene(QGraphicsScene *s)
Chris@133 61 {
Chris@133 62 if (!scene()) {
Chris@133 63 QGraphicsView::setScene(s);
Chris@133 64 return;
Chris@133 65 }
Chris@133 66
Chris@133 67 QPointF nearpt = mapToScene(0, 0);
Chris@133 68 QPointF farpt = mapToScene(width(), height());
Chris@133 69 QSizeF sz(farpt.x()-nearpt.x(), farpt.y()-nearpt.y());
Chris@133 70 QRectF pr(nearpt, sz);
Chris@133 71
Chris@133 72 QGraphicsView::setScene(s);
Chris@133 73
Chris@133 74 DEBUG << "Panned::setScene: pr = " << pr << ", sceneRect = " << sceneRect() << endl;
Chris@133 75
Chris@133 76 if (scene() && sceneRect().intersects(pr)) {
Chris@133 77 DEBUG << "Panned::setScene: restoring old rect " << pr << endl;
Chris@133 78 m_pannedRect = pr;
Chris@133 79 centerOn(pr.center());
cannam@45 80 emit pannedRectChanged(pr);
cannam@45 81 }
cannam@45 82 }
cannam@45 83
cannam@45 84 void
cannam@45 85 Panned::paintEvent(QPaintEvent *e)
cannam@45 86 {
cannam@45 87 QGraphicsView::paintEvent(e);
cannam@45 88 }
cannam@45 89
cannam@45 90 void
cannam@45 91 Panned::drawForeground(QPainter *paint, const QRectF &)
cannam@45 92 {
Chris@60 93 QPointF nearpt = mapToScene(0, 0);
Chris@60 94 QPointF farpt = mapToScene(width(), height());
Chris@60 95 QSizeF sz(farpt.x()-nearpt.x(), farpt.y()-nearpt.y());
Chris@60 96 QRectF pr(nearpt, sz);
cannam@45 97
cannam@45 98 if (pr != m_pannedRect) {
Chris@133 99 DEBUG << "Panned::drawForeground: visible rect " << pr << " differs from panned rect " << m_pannedRect << ", updating panned rect" <<endl;
cannam@45 100 if (pr.x() != m_pannedRect.x()) emit pannedContentsScrolled();
cannam@45 101 m_pannedRect = pr;
cannam@45 102 emit pannedRectChanged(pr);
cannam@45 103 }
cannam@45 104 }
cannam@45 105
cannam@45 106 void
Chris@53 107 Panned::zoomIn()
Chris@53 108 {
Chris@53 109 QMatrix m = matrix();
Chris@53 110 m.scale(1.0 / 1.1, 1.0 / 1.1);
Chris@53 111 setMatrix(m);
Chris@53 112 }
Chris@53 113
Chris@53 114 void
Chris@53 115 Panned::zoomOut()
Chris@53 116 {
Chris@53 117 QMatrix m = matrix();
Chris@53 118 m.scale(1.1, 1.1);
Chris@53 119 setMatrix(m);
Chris@53 120 }
Chris@53 121
Chris@53 122 void
cannam@45 123 Panned::slotSetPannedRect(QRectF pr)
cannam@45 124 {
cannam@45 125 centerOn(pr.center());
cannam@45 126 // setSceneRect(pr);
cannam@45 127 // m_pannedRect = pr;
cannam@45 128 }
cannam@45 129
cannam@45 130 void
cannam@45 131 Panned::wheelEvent(QWheelEvent *ev)
cannam@45 132 {
Chris@53 133 if (ev->modifiers() & Qt::ControlModifier) {
Chris@53 134 int d = ev->delta();
Chris@53 135 if (d > 0) {
Chris@53 136 while (d > 0) {
Chris@53 137 zoomOut();
Chris@53 138 d -= 120;
Chris@53 139 }
Chris@53 140 } else {
Chris@53 141 while (d < 0) {
Chris@53 142 zoomIn();
Chris@53 143 d += 120;
Chris@53 144 }
Chris@53 145 }
Chris@53 146 } else {
Chris@53 147 emit wheelEventReceived(ev);
Chris@53 148 QGraphicsView::wheelEvent(ev);
Chris@53 149 }
cannam@45 150 }
cannam@45 151
cannam@45 152 void
cannam@45 153 Panned::slotEmulateWheelEvent(QWheelEvent *ev)
cannam@45 154 {
cannam@45 155 QGraphicsView::wheelEvent(ev);
cannam@45 156 }
cannam@45 157
cannam@45 158 void
Chris@168 159 Panned::mousePressEvent(QMouseEvent *ev)
Chris@168 160 {
Chris@168 161 if (dragMode() != QGraphicsView::ScrollHandDrag ||
Chris@168 162 ev->button() != Qt::LeftButton) {
Chris@168 163 QGraphicsView::mousePressEvent(ev);
Chris@168 164 return;
Chris@168 165 }
Chris@168 166
Chris@168 167 DEBUG << "Panned::mousePressEvent: have left button in drag mode" << endl;
Chris@168 168
Chris@168 169 setDragMode(QGraphicsView::NoDrag);
Chris@168 170 QGraphicsView::mousePressEvent(ev);
Chris@168 171 setDragMode(QGraphicsView::ScrollHandDrag);
Chris@168 172
Chris@168 173 if (!ev->isAccepted()) {
Chris@168 174 ev->accept();
Chris@168 175 m_dragging = true;
Chris@168 176 m_lastDragPos = ev->pos();
Chris@403 177 m_lastDragStart = ev->pos();
Chris@168 178 m_lastOrigin = QPoint(horizontalScrollBar()->value(),
Chris@168 179 verticalScrollBar()->value());
Chris@168 180 m_velocity = QPointF(0, 0);
Chris@168 181 m_dragTimer->start(m_dragTimerMs);
Chris@403 182 m_dragDirection = UnknownDrag;
Chris@403 183 }
Chris@403 184 }
Chris@403 185
Chris@403 186 void
Chris@403 187 Panned::updateDragDirection(QPoint pos)
Chris@403 188 {
Chris@403 189 if (m_dragDirection == FreeDrag) {
Chris@403 190 return;
Chris@168 191 }
Chris@168 192
Chris@403 193 QPoint overall = pos - m_lastDragStart;
Chris@403 194
Chris@403 195 int smallThreshold = 10;
Chris@403 196 int largeThreshold = 30;
Chris@403 197 int dx = qAbs(overall.x());
Chris@403 198 int dy = qAbs(overall.y());
Chris@403 199
Chris@403 200 switch (m_dragDirection) {
Chris@403 201
Chris@403 202 case UnknownDrag:
Chris@403 203 if (dx > smallThreshold) {
Chris@403 204 if (dy > smallThreshold) {
Chris@403 205 m_dragDirection = FreeDrag;
Chris@403 206 } else {
Chris@403 207 m_dragDirection = HorizontalDrag;
Chris@403 208 }
Chris@403 209 } else if (dy > smallThreshold) {
Chris@403 210 m_dragDirection = VerticalDrag;
Chris@403 211 }
Chris@403 212 break;
Chris@403 213
Chris@403 214 case HorizontalDrag:
Chris@403 215 if (dy > largeThreshold) {
Chris@403 216 m_dragDirection = FreeDrag;
Chris@403 217 }
Chris@403 218 break;
Chris@403 219
Chris@403 220 case VerticalDrag:
Chris@403 221 if (dx > largeThreshold) {
Chris@403 222 m_dragDirection = FreeDrag;
Chris@403 223 }
Chris@403 224 break;
Chris@403 225 };
Chris@168 226 }
Chris@168 227
Chris@168 228 void
Chris@168 229 Panned::mouseMoveEvent(QMouseEvent *ev)
Chris@168 230 {
Chris@168 231 if (!m_dragging) {
Chris@168 232 QGraphicsView::mouseMoveEvent(ev);
Chris@168 233 return;
Chris@168 234 }
Chris@168 235 DEBUG << "Panned::mouseMoveEvent: dragging" << endl;
Chris@168 236 ev->accept();
Chris@403 237 updateDragDirection(ev->pos());
Chris@168 238 QScrollBar *hBar = horizontalScrollBar();
Chris@168 239 QScrollBar *vBar = verticalScrollBar();
Chris@168 240 QPoint delta = ev->pos() - m_lastDragPos;
Chris@403 241 if (m_dragDirection != VerticalDrag) {
Chris@403 242 hBar->setValue(hBar->value() +
Chris@403 243 (isRightToLeft() ? delta.x() : -delta.x()));
Chris@403 244 }
Chris@403 245 if (m_dragDirection != HorizontalDrag) {
Chris@403 246 vBar->setValue(vBar->value() - delta.y());
Chris@403 247 }
Chris@168 248 m_lastDragPos = ev->pos();
Chris@168 249 }
Chris@168 250
Chris@168 251 void
Chris@168 252 Panned::mouseReleaseEvent(QMouseEvent *ev)
Chris@168 253 {
Chris@168 254 if (!m_dragging) {
Chris@168 255 QGraphicsView::mouseReleaseEvent(ev);
Chris@168 256 return;
Chris@168 257 }
Chris@168 258 DEBUG << "Panned::mouseReleaseEvent: dragging" << endl;
Chris@168 259 ev->accept();
Chris@168 260 m_dragging = false;
Chris@168 261 }
Chris@168 262
Chris@168 263 void
Chris@168 264 Panned::dragTimerTimeout()
Chris@168 265 {
Chris@168 266 QPoint origin = QPoint(horizontalScrollBar()->value(),
Chris@168 267 verticalScrollBar()->value());
Chris@168 268 if (m_dragging) {
Chris@168 269 m_velocity = QPointF
Chris@168 270 (float(origin.x() - m_lastOrigin.x()) / m_dragTimerMs,
Chris@168 271 float(origin.y() - m_lastOrigin.y()) / m_dragTimerMs);
Chris@168 272 m_lastOrigin = origin;
Chris@168 273 DEBUG << "Panned::dragTimerTimeout: velocity = " << m_velocity << endl;
Chris@168 274 } else {
Chris@168 275 if (origin == m_lastOrigin) {
Chris@168 276 m_dragTimer->stop();
Chris@168 277 }
Chris@168 278 float x = m_velocity.x(), y = m_velocity.y();
Chris@168 279 if (fabsf(x) > 1.0/m_dragTimerMs) x = x * 0.9f;
Chris@168 280 else x = 0.f;
Chris@168 281 if (fabsf(y) > 1.0/m_dragTimerMs) y = y * 0.9f;
Chris@168 282 else y = 0.f;
Chris@168 283 m_velocity = QPointF(x, y);
Chris@168 284 DEBUG << "Panned::dragTimerTimeout: velocity adjusted to " << m_velocity << endl;
Chris@168 285 m_lastOrigin = origin;
Chris@168 286 //!!! need to store origin in floats
Chris@403 287 if (m_dragDirection != VerticalDrag) {
Chris@403 288 horizontalScrollBar()->setValue(m_lastOrigin.x() +
Chris@403 289 m_velocity.x() * m_dragTimerMs);
Chris@403 290 }
Chris@403 291 if (m_dragDirection != HorizontalDrag) {
Chris@403 292 verticalScrollBar()->setValue(m_lastOrigin.y() +
Chris@403 293 m_velocity.y() * m_dragTimerMs);
Chris@403 294 }
Chris@168 295 }
Chris@168 296 }
Chris@168 297
Chris@168 298 void
cannam@45 299 Panned::leaveEvent(QEvent *)
cannam@45 300 {
cannam@45 301 emit mouseLeaves();
cannam@45 302 }