Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qpixeltool.h"
43
44#include <qapplication.h>
45#include <qdesktopwidget.h>
46#include <qapplication.h>
47#include <qclipboard.h>
48#include <qpainter.h>
49#include <qevent.h>
50#include <qfiledialog.h>
51#include <qsettings.h>
52#include <qmenu.h>
53#include <qactiongroup.h>
54
55#include <qdebug.h>
56
57QT_BEGIN_NAMESPACE
58
59QPixelTool::QPixelTool(QWidget *parent)
60 : QWidget(parent)
61{
62 setWindowTitle(QLatin1String("PixelTool"));
63 QSettings settings(QLatin1String("Trolltech"), QLatin1String("QPixelTool"));
64
65 m_freeze = false;
66
67 m_autoUpdate = settings.value(QLatin1String("autoUpdate"), 0).toBool();
68
69 m_gridSize = settings.value(QLatin1String("gridSize"), 1).toInt();
70 m_gridActive = settings.value(QLatin1String("gridActive"), 1).toInt();
71 m_displayGridSize = false;
72 m_displayGridSizeId = 0;
73
74 m_zoom = settings.value(QLatin1String("zoom"), 4).toInt();
75
76 m_displayZoom = false;
77 m_displayZoomId = 0;
78
79 m_preview_mode = false;
80
81 m_currentColor = 0;
82
83 m_mouseDown = false;
84
85 m_initialSize = settings.value(QLatin1String("initialSize"), QSize(250, 200)).toSize();
86
87 move(settings.value(QLatin1String("position")).toPoint());
88
89 setMouseTracking(true);
90 setAttribute(Qt::WA_NoBackground);
91 m_updateId = startTimer(30);
92}
93
94QPixelTool::~QPixelTool()
95{
96 QSettings settings(QLatin1String("Trolltech"), QLatin1String("QPixelTool"));
97 settings.setValue(QLatin1String("autoUpdate"), int(m_autoUpdate));
98 settings.setValue(QLatin1String("gridSize"), m_gridSize);
99 settings.setValue(QLatin1String("gridActive"), m_gridActive);
100 settings.setValue(QLatin1String("zoom"), m_zoom);
101 settings.setValue(QLatin1String("initialSize"), size());
102 settings.setValue(QLatin1String("position"), pos());
103}
104
105void QPixelTool::setPreviewImage(const QImage &image)
106{
107 m_preview_mode = true;
108 m_preview_image = image;
109 m_freeze = true;
110}
111
112void QPixelTool::timerEvent(QTimerEvent *event)
113{
114 if (event->timerId() == m_updateId && !m_freeze) {
115 grabScreen();
116 } else if (event->timerId() == m_displayZoomId) {
117 killTimer(m_displayZoomId);
118 setZoomVisible(false);
119 } else if (event->timerId() == m_displayGridSizeId) {
120 killTimer(m_displayGridSizeId);
121 m_displayGridSize = false;
122 }
123}
124
125void render_string(QPainter *p, int w, int h, const QString &text, int flags)
126{
127 p->setBrush(QColor(255, 255, 255, 191));
128 p->setPen(Qt::black);
129 QRect bounds;
130 p->drawText(0, 0, w, h, Qt::TextDontPrint | flags, text, &bounds);
131
132 if (bounds.x() == 0) bounds.adjust(0, 0, 10, 0);
133 else bounds.adjust(-10, 0, 0, 0);
134
135 if (bounds.y() == 0) bounds.adjust(0, 0, 0, 10);
136 else bounds.adjust(0, -10, 0, 0);
137
138 p->drawRect(bounds);
139 p->drawText(bounds, flags, text);
140}
141
142void QPixelTool::paintEvent(QPaintEvent *)
143{
144 QPainter p(this);
145
146 if (m_preview_mode) {
147 QPixmap pixmap(40, 40);
148 QPainter pt(&pixmap);
149 pt.fillRect(0, 0, 20, 20, Qt::white);
150 pt.fillRect(20, 20, 20, 20, Qt::white);
151 pt.fillRect(20, 0, 20, 20, Qt::lightGray);
152 pt.fillRect(0, 20, 20, 20, Qt::lightGray);
153 pt.end();
154 p.fillRect(0, 0, width(), height(), pixmap);
155 }
156
157 int w = width();
158 int h = height();
159
160 p.save();
161 p.scale(m_zoom, m_zoom);
162 p.drawPixmap(0, 0, m_buffer);
163 p.scale(1/m_zoom, 1/m_zoom);
164 p.restore();
165
166 // Draw the grid on top.
167 if (m_gridActive) {
168 p.setPen(m_gridActive == 1 ? Qt::black : Qt::white);
169 int incr = m_gridSize * m_zoom;
170 for (int x=0; x<w; x+=incr)
171 p.drawLine(x, 0, x, h);
172 for (int y=0; y<h; y+=incr)
173 p.drawLine(0, y, w, y);
174 }
175
176 QFont f(QLatin1String("courier"));
177 f.setBold(true);
178 p.setFont(f);
179
180 if (m_displayZoom) {
181 render_string(&p, w, h,
182 QString::fromLatin1("Zoom: x%1").arg(m_zoom),
183 Qt::AlignTop | Qt::AlignRight);
184 }
185
186 if (m_displayGridSize) {
187 render_string(&p, w, h,
188 QString::fromLatin1("Grid size: %1").arg(m_gridSize),
189 Qt::AlignBottom | Qt::AlignLeft);
190 }
191
192 if (m_freeze) {
193 QString str;
194 str.sprintf("%8X (%3d,%3d,%3d,%3d)",
195 m_currentColor,
196 (0xff000000 & m_currentColor) >> 24,
197 (0x00ff0000 & m_currentColor) >> 16,
198 (0x0000ff00 & m_currentColor) >> 8,
199 (0x000000ff & m_currentColor));
200 render_string(&p, w, h,
201 str,
202 Qt::AlignBottom | Qt::AlignRight);
203 }
204
205 if (m_mouseDown && m_dragStart != m_dragCurrent) {
206 int x1 = (m_dragStart.x() / m_zoom) * m_zoom;
207 int y1 = (m_dragStart.y() / m_zoom) * m_zoom;
208 int x2 = (m_dragCurrent.x() / m_zoom) * m_zoom;
209 int y2 = (m_dragCurrent.y() / m_zoom) * m_zoom;
210 QRect r = QRect(x1, y1, x2 - x1, y2 - y1).normalized();
211 p.setBrush(Qt::NoBrush);
212 p.setPen(QPen(Qt::red, 3, Qt::SolidLine));
213 p.drawRect(r);
214 p.setPen(QPen(Qt::black, 1, Qt::SolidLine));
215 p.drawRect(r);
216
217 QString str;
218 str.sprintf("Rect: x=%d, y=%d, w=%d, h=%d",
219 r.x() / m_zoom,
220 r.y() / m_zoom,
221 r.width() / m_zoom,
222 r.height() / m_zoom);
223 render_string(&p, w, h, str, Qt::AlignBottom | Qt::AlignLeft);
224 }
225
226
227}
228
229void QPixelTool::keyPressEvent(QKeyEvent *e)
230{
231 switch (e->key()) {
232 case Qt::Key_Space:
233 toggleFreeze();
234 break;
235 case Qt::Key_Plus:
236 setZoom(m_zoom + 1);
237 break;
238 case Qt::Key_Minus:
239 setZoom(m_zoom - 1);
240 break;
241 case Qt::Key_PageUp:
242 setGridSize(m_gridSize + 1);
243 break;
244 case Qt::Key_PageDown:
245 setGridSize(m_gridSize - 1);
246 break;
247 case Qt::Key_G:
248 toggleGrid();
249 break;
250 case Qt::Key_A:
251 m_autoUpdate = !m_autoUpdate;
252 break;
253 case Qt::Key_C:
254 if (e->modifiers() & Qt::ControlModifier)
255 copyToClipboard();
256 break;
257 case Qt::Key_S:
258 if (e->modifiers() & Qt::ControlModifier) {
259 releaseKeyboard();
260 saveToFile();
261 }
262 break;
263 case Qt::Key_Control:
264 grabKeyboard();
265 break;
266 }
267}
268
269void QPixelTool::keyReleaseEvent(QKeyEvent *e)
270{
271 switch(e->key()) {
272 case Qt::Key_Control:
273 releaseKeyboard();
274 break;
275 default:
276 break;
277 }
278}
279
280void QPixelTool::resizeEvent(QResizeEvent *)
281{
282 grabScreen();
283}
284
285void QPixelTool::mouseMoveEvent(QMouseEvent *e)
286{
287 if (m_mouseDown)
288 m_dragCurrent = e->pos();
289
290 int x = e->x() / m_zoom;
291 int y = e->y() / m_zoom;
292
293 QImage im = m_buffer.toImage().convertToFormat(QImage::Format_ARGB32);
294 if (x < im.width() && y < im.height() && x >= 0 && y >= 0) {
295 m_currentColor = im.pixel(x, y);
296 update();
297 }
298}
299
300void QPixelTool::mousePressEvent(QMouseEvent *e)
301{
302 if (!m_freeze)
303 return;
304 m_mouseDown = true;
305 m_dragStart = e->pos();
306}
307
308void QPixelTool::mouseReleaseEvent(QMouseEvent *)
309{
310 m_mouseDown = false;
311}
312
313void QPixelTool::contextMenuEvent(QContextMenuEvent *e)
314{
315 bool tmpFreeze = m_freeze;
316 m_freeze = true;
317
318 QMenu menu;
319
320 QAction title(QLatin1String("Qt Pixel Zooming Tool"), &menu);
321 title.setEnabled(false);
322
323 // Grid color options...
324 QActionGroup gridGroup(this);
325 QAction whiteGrid(QLatin1String("White grid"), &gridGroup);
326 whiteGrid.setCheckable(true);
327 whiteGrid.setChecked(m_gridActive == 2);
328 whiteGrid.setShortcut(QKeySequence(Qt::Key_G));
329 QAction blackGrid(QLatin1String("Black grid"), &gridGroup);
330 blackGrid.setCheckable(true);
331 blackGrid.setChecked(m_gridActive == 1);
332 blackGrid.setShortcut(QKeySequence(Qt::Key_G));
333 QAction noGrid(QLatin1String("No grid"), &gridGroup);
334 noGrid.setCheckable(true);
335 noGrid.setChecked(m_gridActive == 0);
336 noGrid.setShortcut(QKeySequence(Qt::Key_G));
337
338 // Grid size options
339 QAction incrGrid(QLatin1String("Increase grid size"), &menu);
340 incrGrid.setShortcut(QKeySequence(Qt::Key_PageUp));
341 connect(&incrGrid, SIGNAL(triggered()), this, SLOT(increaseGridSize()));
342 QAction decrGrid(QLatin1String("Decrease grid size"), &menu);
343 decrGrid.setShortcut(QKeySequence(Qt::Key_PageDown));
344 connect(&decrGrid, SIGNAL(triggered()), this, SLOT(decreaseGridSize()));
345
346 // Zoom options
347 QAction incrZoom(QLatin1String("Zoom in"), &menu);
348 incrZoom.setShortcut(QKeySequence(Qt::Key_Plus));
349 connect(&incrZoom, SIGNAL(triggered()), this, SLOT(increaseZoom()));
350 QAction decrZoom(QLatin1String("Zoom out"), &menu);
351 decrZoom.setShortcut(QKeySequence(Qt::Key_Minus));
352 connect(&decrZoom, SIGNAL(triggered()), this, SLOT(decreaseZoom()));
353
354 // Freeze / Autoupdate
355 QAction freeze(QLatin1String("Frozen"), &menu);
356 freeze.setCheckable(true);
357 freeze.setChecked(tmpFreeze);
358 freeze.setShortcut(QKeySequence(Qt::Key_Space));
359 QAction autoUpdate(QLatin1String("Continuous update"), &menu);
360 autoUpdate.setCheckable(true);
361 autoUpdate.setChecked(m_autoUpdate);
362 autoUpdate.setShortcut(QKeySequence(Qt::Key_A));
363
364 // Copy to clipboard / save
365 QAction save(QLatin1String("Save as image"), &menu);
366 save.setShortcut(QKeySequence(QLatin1String("Ctrl+S")));
367 connect(&save, SIGNAL(triggered()), this, SLOT(saveToFile()));
368 QAction copy(QLatin1String("Copy to clipboard"), &menu);
369 copy.setShortcut(QKeySequence(QLatin1String("Ctrl+C")));
370 connect(&copy, SIGNAL(triggered()), this, SLOT(copyToClipboard()));
371
372 menu.addAction(&title);
373 menu.addSeparator();
374 menu.addAction(&whiteGrid);
375 menu.addAction(&blackGrid);
376 menu.addAction(&noGrid);
377 menu.addSeparator();
378 menu.addAction(&incrGrid);
379 menu.addAction(&decrGrid);
380 menu.addSeparator();
381 menu.addAction(&incrZoom);
382 menu.addAction(&decrZoom);
383 menu.addSeparator();
384 menu.addAction(&freeze);
385 menu.addAction(&autoUpdate);
386 menu.addSeparator();
387 menu.addAction(&save);
388 menu.addAction(&copy);
389
390 menu.exec(mapToGlobal(e->pos()));
391
392 // Read out grid settings
393 if (noGrid.isChecked()) m_gridActive = 0;
394 else if (blackGrid.isChecked()) m_gridActive = 1;
395 else m_gridActive = 2;
396
397 m_autoUpdate = autoUpdate.isChecked();
398 tmpFreeze = freeze.isChecked();
399
400
401 m_freeze = tmpFreeze;
402}
403
404QSize QPixelTool::sizeHint() const
405{
406 return m_initialSize;
407}
408
409void QPixelTool::grabScreen()
410{
411 if (m_preview_mode) {
412 int w = qMin(width() / m_zoom + 1, m_preview_image.width());
413 int h = qMin(height() / m_zoom + 1, m_preview_image.height());
414 m_buffer = QPixmap::fromImage(m_preview_image).copy(0, 0, w, h);
415 update();
416 return;
417 }
418
419 QPoint mousePos = QCursor::pos();
420 if (mousePos == m_lastMousePos && !m_autoUpdate)
421 return;
422
423 int w = int(width() / float(m_zoom));
424 int h = int(height() / float(m_zoom));
425
426 if (width() % m_zoom > 0)
427 ++w;
428 if (height() % m_zoom > 0)
429 ++h;
430
431 int x = mousePos.x() - w/2;
432 int y = mousePos.y() - h/2;
433
434 m_buffer = QPixmap::grabWindow(qApp->desktop()->winId(), x, y, w, h);
435
436 QRegion geom(x, y, w, h);
437 QRect screenRect;
438 for (int i=0; i<qApp->desktop()->numScreens(); ++i)
439 screenRect |= qApp->desktop()->screenGeometry(i);
440 geom -= screenRect;
441 QVector<QRect> rects = geom.rects();
442 if (rects.size() > 0) {
443 QPainter p(&m_buffer);
444 p.translate(-x, -y);
445 p.setPen(Qt::NoPen);
446 p.setBrush(palette().color(QPalette::Dark));
447 p.drawRects(rects);
448 }
449
450 update();
451
452 m_lastMousePos = mousePos;
453}
454
455void QPixelTool::startZoomVisibleTimer()
456{
457 if (m_displayZoomId > 0) {
458 killTimer(m_displayZoomId);
459 }
460 m_displayZoomId = startTimer(5000);
461 setZoomVisible(true);
462}
463
464void QPixelTool::startGridSizeVisibleTimer()
465{
466 if (m_gridActive) {
467 if (m_displayGridSizeId > 0)
468 killTimer(m_displayGridSizeId);
469 m_displayGridSizeId = startTimer(5000);
470 m_displayGridSize = true;
471 update();
472 }
473}
474
475void QPixelTool::setZoomVisible(bool visible)
476{
477 m_displayZoom = visible;
478 update();
479}
480
481void QPixelTool::toggleFreeze()
482{
483 m_freeze = !m_freeze;
484 if (!m_freeze)
485 m_dragStart = m_dragCurrent = QPoint();
486}
487
488void QPixelTool::setZoom(int zoom)
489{
490 if (zoom > 0) {
491 QPoint pos = m_lastMousePos;
492 m_lastMousePos = QPoint();
493 m_zoom = zoom;
494 grabScreen();
495 m_lastMousePos = pos;
496 m_dragStart = m_dragCurrent = QPoint();
497 startZoomVisibleTimer();
498 }
499}
500
501void QPixelTool::toggleGrid()
502{
503 if (++m_gridActive > 2)
504 m_gridActive = 0;
505 update();
506}
507
508void QPixelTool::setGridSize(int gridSize)
509{
510 if (m_gridActive && gridSize > 0) {
511 m_gridSize = gridSize;
512 startGridSizeVisibleTimer();
513 update();
514 }
515}
516
517void QPixelTool::copyToClipboard()
518{
519 QClipboard *cb = QApplication::clipboard();
520 cb->setPixmap(m_buffer);
521}
522
523void QPixelTool::saveToFile()
524{
525 bool oldFreeze = m_freeze;
526 m_freeze = true;
527 QString name = QFileDialog::getSaveFileName(this, QLatin1String("Save as image"), QString(), QLatin1String("*.png"));
528 if (!name.isEmpty()) {
529 if (!name.endsWith(QLatin1String(".png")))
530 name.append(QLatin1String(".png"));
531 m_buffer.save(name, "PNG");
532 }
533 m_freeze = oldFreeze;
534}
535
536QT_END_NAMESPACE
537

Warning: That file was not part of the compilation database. It may have many parsing errors.