Mercurial > hg > easyhg
diff src/panner.cpp @ 370:b9c153e00e84
Move source files to src/
author | Chris Cannam |
---|---|
date | Thu, 24 Mar 2011 10:27:51 +0000 |
parents | panner.cpp@be483734bde5 |
children | 496f2042155a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/panner.cpp Thu Mar 24 10:27:51 2011 +0000 @@ -0,0 +1,285 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + EasyMercurial + + Based on HgExplorer by Jari Korhonen + Copyright (c) 2010 Jari Korhonen + Copyright (c) 2011 Chris Cannam + Copyright (c) 2011 Queen Mary, University of London + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "panner.h" +#include "panned.h" +#include "debug.h" + +#include <QPolygon> +#include <QMouseEvent> +#include <QColor> + +#include <iostream> + +class PannerScene : public QGraphicsScene +{ +public: + friend class Panner; +}; + +Panner::Panner() : + m_clicked(false) +{ + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setOptimizationFlags(QGraphicsView::DontSavePainterState | + QGraphicsView::IndirectPainting); + setMouseTracking(true); + setInteractive(false); +} + +void +Panner::fit(QRectF r) +{ + Qt::AspectRatioMode m = Qt::IgnoreAspectRatio; + if (height() > width()) { + // Our panner is vertical; if the source is not tall, + // don't stretch it to fit in the height, it'd look weird + if (r.height() < height() * 2) { + m = Qt::KeepAspectRatio; + } + } else { + // Similarly, but horizontal + if (r.width() < width() * 2) { + m = Qt::KeepAspectRatio; + } + } + DEBUG << "Panner: fit mode " << m << endl; + fitInView(r, m); +} + +void +Panner::setScene(QGraphicsScene *s) +{ + if (scene()) { + disconnect(scene(), SIGNAL(changed(const QList<QRectF> &)), + this, SLOT(slotSceneChanged(const QList<QRectF> &))); + disconnect(scene(), SIGNAL(sceneRectChanged(const QRectF &)), + this, SLOT(slotSceneRectChanged(const QRectF &))); + } + QGraphicsView::setScene(s); + m_cache = QPixmap(); + if (scene()) { + QRectF r = sceneRect(); + DEBUG << "scene rect: " << r << ", my rect " << rect() << endl; + fit(r); + connect(scene(), SIGNAL(changed(const QList<QRectF> &)), + this, SLOT(slotSceneChanged(const QList<QRectF> &))); + connect(scene(), SIGNAL(sceneRectChanged(const QRectF &)), + this, SLOT(slotSceneRectChanged(const QRectF &))); + } +} + +void +Panner::connectToPanned(Panned *p) +{ + connect(p, SIGNAL(pannedRectChanged(QRectF)), + this, SLOT(slotSetPannedRect(QRectF))); + + connect(this, SIGNAL(pannedRectChanged(QRectF)), + p, SLOT(slotSetPannedRect(QRectF))); + + connect(this, SIGNAL(zoomIn()), + p, SLOT(zoomIn())); + + connect(this, SIGNAL(zoomOut()), + p, SLOT(zoomOut())); +} + +void +Panner::slotSetPannedRect(QRectF rect) +{ + m_pannedRect = rect; + viewport()->update(); +} + +void +Panner::resizeEvent(QResizeEvent *) +{ + DEBUG << "Panner::resizeEvent" << endl; + if (scene()) fit(sceneRect()); + m_cache = QPixmap(); +} + +void +Panner::slotSceneRectChanged(const QRectF &newRect) +{ + DEBUG << "Panner::slotSceneRectChanged" << endl; + if (!scene()) return; // spurious + fit(newRect); + m_cache = QPixmap(); + viewport()->update(); +} + +void +Panner::slotSceneChanged(const QList<QRectF> &) +{ + DEBUG << "Panner::slotSceneChanged" << endl; + if (!scene()) return; // spurious + m_cache = QPixmap(); + viewport()->update(); +} + +void +Panner::paintEvent(QPaintEvent *e) +{ + QPaintEvent *e2 = new QPaintEvent(e->region().boundingRect()); + QGraphicsView::paintEvent(e2); + + QPainter paint; + paint.begin(viewport()); + paint.setClipRegion(e->region()); + + QPainterPath path; + path.addRect(rect()); + path.addPolygon(mapFromScene(m_pannedRect)); + + QColor c(QColor::fromHsv(211, 194, 238)); + c.setAlpha(80); + paint.setPen(Qt::NoPen); + paint.setBrush(c); + paint.drawPath(path); + + paint.setBrush(Qt::NoBrush); + paint.setPen(QPen(QColor::fromHsv(211, 194, 238), 0)); + paint.drawConvexPolygon(mapFromScene(m_pannedRect)); + + paint.end(); + + emit pannerChanged(m_pannedRect); +} + +void +Panner::updateScene(const QList<QRectF> &rects) +{ + DEBUG << "Panner::updateScene" << endl; +// if (!m_cache.isNull()) m_cache = QPixmap(); + QGraphicsView::updateScene(rects); +} + +void +Panner::drawItems(QPainter *painter, int numItems, + QGraphicsItem *items[], + const QStyleOptionGraphicsItem options[]) +{ + if (m_cache.size() != viewport()->size()) { + + DEBUG << "Panner: cache size " << m_cache.size() << " != viewport size " << viewport()->size() << ": recreating cache" << endl; + + QGraphicsScene *s = scene(); + if (!s) return; + PannerScene *ps = static_cast<PannerScene *>(s); + + m_cache = QPixmap(viewport()->size()); + m_cache.fill(Qt::transparent); + QPainter cachePainter; + cachePainter.begin(&m_cache); + cachePainter.setTransform(viewportTransform()); + ps->drawItems(&cachePainter, numItems, items, options); + cachePainter.end(); + + DEBUG << "done" << endl; + } + + painter->save(); + painter->setTransform(QTransform()); + painter->drawPixmap(0, 0, m_cache); + painter->restore(); +} + +void +Panner::mousePressEvent(QMouseEvent *e) +{ + if (e->button() != Qt::LeftButton) { + QGraphicsView::mouseDoubleClickEvent(e); + return; + } + m_clicked = true; + m_clickedRect = m_pannedRect; + m_clickedPoint = e->pos(); +} + +void +Panner::mouseDoubleClickEvent(QMouseEvent *e) +{ + if (e->button() != Qt::LeftButton) { + QGraphicsView::mouseDoubleClickEvent(e); + return; + } + + moveTo(e->pos()); +} + +void +Panner::mouseMoveEvent(QMouseEvent *e) +{ + if (!m_clicked) return; + QPointF cp = mapToScene(m_clickedPoint); + QPointF mp = mapToScene(e->pos()); + QPointF delta = mp - cp; + QRectF nr = m_clickedRect; + nr.translate(delta); + m_pannedRect = nr; + emit pannedRectChanged(m_pannedRect); + viewport()->update(); +} + +void +Panner::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->button() != Qt::LeftButton) { + QGraphicsView::mouseDoubleClickEvent(e); + return; + } + + if (m_clicked) { + mouseMoveEvent(e); + } + + m_clicked = false; + viewport()->update(); +} + +void +Panner::wheelEvent(QWheelEvent *e) +{ + int d = e->delta(); + if (d > 0) { + while (d > 0) { + emit zoomOut(); + d -= 120; + } + } else { + while (d < 0) { + emit zoomIn(); + d += 120; + } + } +} + +void +Panner::moveTo(QPoint p) +{ + QPointF sp = mapToScene(p); + QRectF nr = m_pannedRect; + double d = sp.x() - nr.center().x(); + nr.translate(d, 0); + slotSetPannedRect(nr); + emit pannedRectChanged(m_pannedRect); + viewport()->update(); +} +