cannam@45: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@45: cannam@45: /* cannam@45: Rosegarden cannam@45: A MIDI and audio sequencer and musical notation editor. cannam@45: Copyright 2000-2010 the Rosegarden development team. cannam@45: cannam@45: Other copyrights also apply to some parts of this work. Please cannam@45: see the AUTHORS file and individual file headers for details. cannam@45: cannam@45: This program is free software; you can redistribute it and/or cannam@45: modify it under the terms of the GNU General Public License as cannam@45: published by the Free Software Foundation; either version 2 of the cannam@45: License, or (at your option) any later version. See the file cannam@45: COPYING included with this distribution for more information. cannam@45: */ cannam@45: cannam@45: #include "panner.h" cannam@45: #include "panned.h" cannam@45: cannam@45: #include cannam@45: #include cannam@45: #include cannam@45: cannam@45: #include cannam@45: cannam@45: class PannerScene : public QGraphicsScene cannam@45: { cannam@45: public: cannam@45: friend class Panner; cannam@45: }; cannam@45: cannam@45: Panner::Panner() : cannam@45: m_clicked(false) cannam@45: { cannam@45: setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); cannam@45: setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); cannam@45: setOptimizationFlags(QGraphicsView::DontSavePainterState); cannam@45: setMouseTracking(true); cannam@45: setInteractive(false); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::setScene(QGraphicsScene *s) cannam@45: { cannam@45: if (scene()) { cannam@45: disconnect(scene(), SIGNAL(sceneRectChanged(const QRectF &)), cannam@45: this, SLOT(slotSceneRectChanged(const QRectF &))); cannam@45: } cannam@45: QGraphicsView::setScene(s); cannam@45: if (scene()) fitInView(sceneRect(), Qt::IgnoreAspectRatio); cannam@45: m_cache = QPixmap(); cannam@45: connect(scene(), SIGNAL(sceneRectChanged(const QRectF &)), cannam@45: this, SLOT(slotSceneRectChanged(const QRectF &))); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::connectToPanned(Panned *p) cannam@45: { cannam@45: connect(p, SIGNAL(pannedRectChanged(QRectF)), cannam@45: this, SLOT(slotSetPannedRect(QRectF))); cannam@45: cannam@45: connect(this, SIGNAL(pannedRectChanged(QRectF)), cannam@45: p, SLOT(slotSetPannedRect(QRectF))); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::slotSetPannedRect(QRectF rect) cannam@45: { cannam@45: m_pannedRect = rect; cannam@45: viewport()->update(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::resizeEvent(QResizeEvent *) cannam@45: { cannam@45: if (scene()) fitInView(sceneRect(), Qt::IgnoreAspectRatio); cannam@45: m_cache = QPixmap(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::slotSceneRectChanged(const QRectF &newRect) cannam@45: { cannam@45: if (!scene()) return; // spurious cannam@45: fitInView(newRect, Qt::IgnoreAspectRatio); cannam@45: m_cache = QPixmap(); cannam@45: viewport()->update(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::paintEvent(QPaintEvent *e) cannam@45: { cannam@45: QPaintEvent *e2 = new QPaintEvent(e->region().boundingRect()); cannam@45: QGraphicsView::paintEvent(e2); cannam@45: cannam@45: QPainter paint; cannam@45: paint.begin(viewport()); cannam@45: paint.setClipRegion(e->region()); cannam@45: cannam@45: QPainterPath path; cannam@45: path.addRect(rect()); cannam@45: path.addPolygon(mapFromScene(m_pannedRect)); cannam@45: cannam@45: QColor c(QColor::fromHsv(211, 194, 238)); cannam@45: c.setAlpha(80); cannam@45: paint.setPen(Qt::NoPen); cannam@45: paint.setBrush(c); cannam@45: paint.drawPath(path); cannam@45: cannam@45: paint.setBrush(Qt::NoBrush); cannam@45: paint.setPen(QPen(QColor::fromHsv(211, 194, 238), 0)); cannam@45: paint.drawConvexPolygon(mapFromScene(m_pannedRect)); cannam@45: cannam@45: paint.end(); cannam@45: cannam@45: emit pannerChanged(m_pannedRect); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::updateScene(const QList &rects) cannam@45: { cannam@45: if (!m_cache.isNull()) m_cache = QPixmap(); cannam@45: QGraphicsView::updateScene(rects); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::drawItems(QPainter *painter, int numItems, cannam@45: QGraphicsItem *items[], cannam@45: const QStyleOptionGraphicsItem options[]) cannam@45: { cannam@45: if (m_cache.size() != viewport()->size()) { cannam@45: cannam@45: QGraphicsScene *s = scene(); cannam@45: if (!s) return; cannam@45: PannerScene *ps = static_cast(s); cannam@45: cannam@45: m_cache = QPixmap(viewport()->size()); cannam@45: m_cache.fill(Qt::transparent); cannam@45: QPainter cachePainter; cannam@45: cachePainter.begin(&m_cache); cannam@45: cachePainter.setTransform(viewportTransform()); cannam@45: ps->drawItems(&cachePainter, numItems, items, options); cannam@45: cachePainter.end(); cannam@45: } cannam@45: cannam@45: painter->save(); cannam@45: painter->setTransform(QTransform()); cannam@45: painter->drawPixmap(0, 0, m_cache); cannam@45: painter->restore(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::mousePressEvent(QMouseEvent *e) cannam@45: { cannam@45: if (e->button() != Qt::LeftButton) { cannam@45: QGraphicsView::mouseDoubleClickEvent(e); cannam@45: return; cannam@45: } cannam@45: m_clicked = true; cannam@45: m_clickedRect = m_pannedRect; cannam@45: m_clickedPoint = e->pos(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::mouseDoubleClickEvent(QMouseEvent *e) cannam@45: { cannam@45: if (e->button() != Qt::LeftButton) { cannam@45: QGraphicsView::mouseDoubleClickEvent(e); cannam@45: return; cannam@45: } cannam@45: cannam@45: moveTo(e->pos()); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::mouseMoveEvent(QMouseEvent *e) cannam@45: { cannam@45: if (!m_clicked) return; cannam@45: QPointF cp = mapToScene(m_clickedPoint); cannam@45: QPointF mp = mapToScene(e->pos()); cannam@45: QPointF delta = mp - cp; cannam@45: QRectF nr = m_clickedRect; cannam@45: nr.translate(delta); cannam@45: slotSetPannedRect(nr); cannam@45: emit pannedRectChanged(m_pannedRect); cannam@45: viewport()->update(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::mouseReleaseEvent(QMouseEvent *e) cannam@45: { cannam@45: if (e->button() != Qt::LeftButton) { cannam@45: QGraphicsView::mouseDoubleClickEvent(e); cannam@45: return; cannam@45: } cannam@45: cannam@45: if (m_clicked) { cannam@45: mouseMoveEvent(e); cannam@45: } cannam@45: cannam@45: m_clicked = false; cannam@45: viewport()->update(); cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::wheelEvent(QWheelEvent *e) cannam@45: { cannam@45: if (e->delta() > 0) { cannam@45: emit zoomOut(); cannam@45: } else { cannam@45: emit zoomIn(); cannam@45: } cannam@45: } cannam@45: cannam@45: void cannam@45: Panner::moveTo(QPoint p) cannam@45: { cannam@45: QPointF sp = mapToScene(p); cannam@45: QRectF nr = m_pannedRect; cannam@45: double d = sp.x() - nr.center().x(); cannam@45: nr.translate(d, 0); cannam@45: slotSetPannedRect(nr); cannam@45: emit pannedRectChanged(m_pannedRect); cannam@45: viewport()->update(); cannam@45: } cannam@45: