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