source: branches/vendor/trolltech/qt/current/tools/pixeltool/qpixeltool.cpp @ 2

Last change on this file since 2 was 2, checked in by Dmitry A. Kuminov, 12 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 15.1 KB
RevLine 
[2]1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file.  Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file.  Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at qt-sales@nokia.com.
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(QLatin1String("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(QLatin1String("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("Continous 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
Note: See TracBrowser for help on using the repository browser.