|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 #ifndef WIDGETS_H |
|
42 #define WIDGETS_H |
|
43 |
|
44 #include "paintcommands.h" |
|
45 |
|
46 #include <QWidget> |
|
47 #include <QSettings> |
|
48 #include <QFileInfo> |
|
49 #include <QPainter> |
|
50 #include <QPaintEvent> |
|
51 #include <QListWidgetItem> |
|
52 #include <QTextEdit> |
|
53 #include <QHBoxLayout> |
|
54 #include <QSplitter> |
|
55 #include <QPushButton> |
|
56 #include <QFileDialog> |
|
57 #include <QTextStream> |
|
58 #include <QPaintEngine> |
|
59 #include <QSignalMapper> |
|
60 #include <QAction> |
|
61 |
|
62 |
|
63 #include <private/qwindowsurface_p.h> |
|
64 |
|
65 #include <qmath.h> |
|
66 |
|
67 const int CP_RADIUS = 10; |
|
68 |
|
69 class StupidWorkaround : public QObject |
|
70 { |
|
71 Q_OBJECT |
|
72 public: |
|
73 StupidWorkaround(QWidget *widget, int *value) |
|
74 : QObject(widget), w(widget), mode(value) |
|
75 { |
|
76 } |
|
77 |
|
78 public slots: |
|
79 void setViewMode(int m) { |
|
80 *mode = m; |
|
81 w->update(); |
|
82 } |
|
83 |
|
84 private: |
|
85 QWidget *w; |
|
86 int *mode; |
|
87 }; |
|
88 |
|
89 template <class T> |
|
90 class OnScreenWidget : public T |
|
91 { |
|
92 public: |
|
93 |
|
94 enum ViewMode { |
|
95 RenderView, |
|
96 BaselineView, |
|
97 DifferenceView |
|
98 }; |
|
99 |
|
100 OnScreenWidget(const QString &file, QWidget *parent = 0) |
|
101 : T(parent), |
|
102 m_filename(file), |
|
103 m_view_mode(RenderView) |
|
104 { |
|
105 QSettings settings("Trolltech", "lance"); |
|
106 for (int i=0; i<10; ++i) { |
|
107 QPointF suggestion(100 + i * 40, 100 + 100 * qSin(i * 3.1415 / 10.0)); |
|
108 m_controlPoints << settings.value("cp" + QString::number(i), suggestion).toPointF(); |
|
109 } |
|
110 |
|
111 m_currentPoint = -1; |
|
112 m_showControlPoints = false; |
|
113 m_deviceType = WidgetType; |
|
114 m_checkersBackground = true; |
|
115 m_verboseMode = false; |
|
116 |
|
117 m_baseline_name = QString(m_filename).replace(".qps", "_qps") + ".png"; |
|
118 if (QFileInfo(m_baseline_name).exists()) { |
|
119 m_baseline = QPixmap(m_baseline_name); |
|
120 } |
|
121 |
|
122 if (m_baseline.isNull()) { |
|
123 T::setWindowTitle("Rendering: '" + file + "'. No baseline available"); |
|
124 } else { |
|
125 T::setWindowTitle("Rendering: '" + file + "'. Shortcuts: 1=render, 2=baseline, 3=difference"); |
|
126 |
|
127 StupidWorkaround *workaround = new StupidWorkaround(this, &m_view_mode); |
|
128 |
|
129 QSignalMapper *mapper = new QSignalMapper(this); |
|
130 T::connect(mapper, SIGNAL(mapped(int)), workaround, SLOT(setViewMode(int))); |
|
131 T::connect(mapper, SIGNAL(mapped(QString)), this, SLOT(setWindowTitle(QString))); |
|
132 |
|
133 QAction *renderViewAction = new QAction("Render View", this); |
|
134 renderViewAction->setShortcut(Qt::Key_1); |
|
135 T::connect(renderViewAction, SIGNAL(triggered()), mapper, SLOT(map())); |
|
136 mapper->setMapping(renderViewAction, RenderView); |
|
137 mapper->setMapping(renderViewAction, "Render View: " + file); |
|
138 T::addAction(renderViewAction); |
|
139 |
|
140 QAction *baselineAction = new QAction("Baseline", this); |
|
141 baselineAction->setShortcut(Qt::Key_2); |
|
142 T::connect(baselineAction, SIGNAL(triggered()), mapper, SLOT(map())); |
|
143 mapper->setMapping(baselineAction, BaselineView); |
|
144 mapper->setMapping(baselineAction, "Baseline View: " + file); |
|
145 T::addAction(baselineAction); |
|
146 |
|
147 QAction *differenceAction = new QAction("Differenfe View", this); |
|
148 differenceAction->setShortcut(Qt::Key_3); |
|
149 T::connect(differenceAction, SIGNAL(triggered()), mapper, SLOT(map())); |
|
150 mapper->setMapping(differenceAction, DifferenceView); |
|
151 mapper->setMapping(differenceAction, "Difference View" + file); |
|
152 T::addAction(differenceAction); |
|
153 |
|
154 } |
|
155 |
|
156 } |
|
157 |
|
158 ~OnScreenWidget() |
|
159 { |
|
160 QSettings settings("Trolltech", "lance"); |
|
161 for (int i=0; i<10; ++i) { |
|
162 settings.setValue("cp" + QString::number(i), m_controlPoints.at(i)); |
|
163 } |
|
164 settings.sync(); |
|
165 } |
|
166 |
|
167 void setVerboseMode(bool v) { m_verboseMode = v; } |
|
168 void setCheckersBackground(bool b) { m_checkersBackground = b; } |
|
169 void setType(DeviceType t) { m_deviceType = t; } |
|
170 |
|
171 void resizeEvent(QResizeEvent *e) { |
|
172 m_image = QImage(); |
|
173 T::resizeEvent(e); |
|
174 } |
|
175 |
|
176 void paintEvent(QPaintEvent *) { |
|
177 switch (m_view_mode) { |
|
178 case RenderView: paintRenderView(); break; |
|
179 case BaselineView: paintBaselineView(); break; |
|
180 case DifferenceView: paintDifferenceView(); break; |
|
181 } |
|
182 } |
|
183 |
|
184 void paintRenderView() |
|
185 { |
|
186 QPainter pt; |
|
187 QPaintDevice *dev = this; |
|
188 if (m_deviceType == ImageWidgetType) { |
|
189 if (m_image.size() != T::size()) |
|
190 m_image = QImage(T::size(), QImage::Format_ARGB32_Premultiplied); |
|
191 m_image.fill(0); |
|
192 dev = &m_image; |
|
193 } |
|
194 |
|
195 pt.begin(dev); |
|
196 |
|
197 PaintCommands paintCommands(m_commands, 800, 800); |
|
198 paintCommands.setVerboseMode(m_verboseMode); |
|
199 paintCommands.setCheckersBackground(m_checkersBackground); |
|
200 paintCommands.setType(m_deviceType); |
|
201 paintCommands.setPainter(&pt); |
|
202 paintCommands.setControlPoints(m_controlPoints); |
|
203 paintCommands.setFilePath(QFileInfo(m_filename).absolutePath()); |
|
204 #ifdef DO_QWS_DEBUGGING |
|
205 qt_show_painter_debug_output = true; |
|
206 #endif |
|
207 pt.save(); |
|
208 paintCommands.runCommands(); |
|
209 pt.restore(); |
|
210 #ifdef DO_QWS_DEBUGGING |
|
211 qt_show_painter_debug_output = false; |
|
212 #endif |
|
213 |
|
214 pt.end(); |
|
215 |
|
216 if (m_deviceType == ImageWidgetType) { |
|
217 QPainter(this).drawImage(0, 0, m_image); |
|
218 } |
|
219 |
|
220 if (m_currentPoint >= 0 || m_showControlPoints) { |
|
221 pt.begin(this); |
|
222 pt.setRenderHint(QPainter::Antialiasing); |
|
223 pt.setFont(this->font()); |
|
224 pt.resetMatrix(); |
|
225 pt.setPen(QColor(127, 127, 127, 191)); |
|
226 pt.setBrush(QColor(191, 191, 255, 63)); |
|
227 for (int i=0; i<m_controlPoints.size(); ++i) { |
|
228 if (m_showControlPoints || m_currentPoint == i) { |
|
229 QPointF cp = m_controlPoints.at(i); |
|
230 QRectF rect(cp.x() - CP_RADIUS, cp.y() - CP_RADIUS, |
|
231 CP_RADIUS * 2, CP_RADIUS * 2); |
|
232 pt.drawEllipse(rect); |
|
233 pt.drawText(rect, Qt::AlignCenter, QString::number(i)); |
|
234 } |
|
235 } |
|
236 } |
|
237 |
|
238 if (m_render_view.isNull()) { |
|
239 m_render_view = T::window()->windowSurface()->grabWidget(this); |
|
240 m_render_view.save("renderView.png"); |
|
241 } |
|
242 } |
|
243 |
|
244 void paintBaselineView() { |
|
245 QPainter p(this); |
|
246 |
|
247 if (m_baseline.isNull()) { |
|
248 p.drawText(T::rect(), Qt::AlignCenter, |
|
249 "No baseline found\n" |
|
250 "file '" + m_baseline_name + "' does not exist..."); |
|
251 return; |
|
252 } |
|
253 |
|
254 p.drawPixmap(0, 0, m_baseline); |
|
255 |
|
256 p.setPen(QColor::fromRgb(0, 0, 0, 0.1)); |
|
257 p.setFont(QFont("Arial", 128)); |
|
258 p.rotate(45); |
|
259 p.drawText(100, 0, "BASELINE"); |
|
260 } |
|
261 |
|
262 QPixmap generateDifference() |
|
263 { |
|
264 QImage img(T::size(), QImage::Format_RGB32); |
|
265 img.fill(0); |
|
266 |
|
267 QPainter p(&img); |
|
268 p.drawPixmap(0, 0, m_render_view); |
|
269 |
|
270 p.setCompositionMode(QPainter::RasterOp_SourceXorDestination); |
|
271 p.drawPixmap(0, 0, m_baseline); |
|
272 |
|
273 p.end(); |
|
274 |
|
275 return QPixmap::fromImage(img); |
|
276 } |
|
277 |
|
278 void paintDifferenceView() { |
|
279 QPainter p(this); |
|
280 if (m_baseline.isNull()) { |
|
281 p.drawText(T::rect(), Qt::AlignCenter, |
|
282 "No baseline found\n" |
|
283 "file '" + m_baseline_name + "' does not exist..."); |
|
284 return; |
|
285 } |
|
286 |
|
287 p.fillRect(T::rect(), Qt::black); |
|
288 p.drawPixmap(0, 0, generateDifference()); |
|
289 } |
|
290 |
|
291 |
|
292 void mouseMoveEvent(QMouseEvent *e) |
|
293 { |
|
294 if (m_currentPoint == -1) |
|
295 return; |
|
296 if (T::rect().contains(e->pos())) |
|
297 m_controlPoints[m_currentPoint] = e->pos(); |
|
298 T::update(); |
|
299 } |
|
300 |
|
301 void mousePressEvent(QMouseEvent *e) |
|
302 { |
|
303 if (e->button() == Qt::RightButton) { |
|
304 m_showControlPoints = true; |
|
305 } |
|
306 |
|
307 if (e->button() == Qt::LeftButton) { |
|
308 for (int i=0; i<m_controlPoints.size(); ++i) { |
|
309 if (QLineF(m_controlPoints.at(i), e->pos()).length() < CP_RADIUS) { |
|
310 m_currentPoint = i; |
|
311 break; |
|
312 } |
|
313 } |
|
314 } |
|
315 T::update(); |
|
316 } |
|
317 |
|
318 void mouseReleaseEvent(QMouseEvent *e) |
|
319 { |
|
320 if (e->button() == Qt::LeftButton) |
|
321 m_currentPoint = -1; |
|
322 if (e->button() == Qt::RightButton) |
|
323 m_showControlPoints = false; |
|
324 T::update(); |
|
325 } |
|
326 |
|
327 QSize sizeHint() const { return QSize(800, 800); } |
|
328 |
|
329 QVector<QPointF> m_controlPoints; |
|
330 int m_currentPoint; |
|
331 bool m_showControlPoints; |
|
332 |
|
333 QStringList m_commands; |
|
334 QString m_filename; |
|
335 QString m_baseline_name; |
|
336 |
|
337 bool m_verboseMode; |
|
338 bool m_checkersBackground; |
|
339 DeviceType m_deviceType; |
|
340 |
|
341 int m_view_mode; |
|
342 |
|
343 QImage m_image; |
|
344 |
|
345 QPixmap m_baseline; |
|
346 QPixmap m_render_view; |
|
347 }; |
|
348 |
|
349 #endif |