examples/threads/mandelbrot/mandelbrotwidget.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/threads/mandelbrot/mandelbrotwidget.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include <math.h>
+
+#include "mandelbrotwidget.h"
+
+//! [0]
+const double DefaultCenterX = -0.637011f;
+const double DefaultCenterY = -0.0395159f;
+const double DefaultScale = 0.00403897f;
+
+const double ZoomInFactor = 0.8f;
+const double ZoomOutFactor = 1 / ZoomInFactor;
+const int ScrollStep = 20;
+//! [0]
+
+//! [1]
+MandelbrotWidget::MandelbrotWidget(QWidget *parent)
+    : QWidget(parent)
+{
+    centerX = DefaultCenterX;
+    centerY = DefaultCenterY;
+    pixmapScale = DefaultScale;
+    curScale = DefaultScale;
+
+    qRegisterMetaType<QImage>("QImage");
+    connect(&thread, SIGNAL(renderedImage(const QImage &, double)),
+            this, SLOT(updatePixmap(const QImage &, double)));
+
+    setWindowTitle(tr("Mandelbrot"));
+#ifndef QT_NO_CURSOR
+    setCursor(Qt::CrossCursor);
+#endif
+    resize(550, 400);
+}
+//! [1]
+
+//! [2]
+void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)
+{
+    QPainter painter(this);
+    painter.fillRect(rect(), Qt::black);
+
+    if (pixmap.isNull()) {
+        painter.setPen(Qt::white);
+        painter.drawText(rect(), Qt::AlignCenter,
+                         tr("Rendering initial image, please wait..."));
+//! [2] //! [3]
+        return;
+//! [3] //! [4]
+    }
+//! [4]
+
+//! [5]
+    if (curScale == pixmapScale) {
+//! [5] //! [6]
+        painter.drawPixmap(pixmapOffset, pixmap);
+//! [6] //! [7]
+    } else {
+//! [7] //! [8]
+        double scaleFactor = pixmapScale / curScale;
+        int newWidth = int(pixmap.width() * scaleFactor);
+        int newHeight = int(pixmap.height() * scaleFactor);
+        int newX = pixmapOffset.x() + (pixmap.width() - newWidth) / 2;
+        int newY = pixmapOffset.y() + (pixmap.height() - newHeight) / 2;
+
+        painter.save();
+        painter.translate(newX, newY);
+        painter.scale(scaleFactor, scaleFactor);
+        QRectF exposed = painter.matrix().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
+        painter.drawPixmap(exposed, pixmap, exposed);
+        painter.restore();
+    }
+//! [8] //! [9]
+
+    QString text = tr("Use mouse wheel or the '+' and '-' keys to zoom. "
+                      "Press and hold left mouse button to scroll.");
+    QFontMetrics metrics = painter.fontMetrics();
+    int textWidth = metrics.width(text);
+
+    painter.setPen(Qt::NoPen);
+    painter.setBrush(QColor(0, 0, 0, 127));
+    painter.drawRect((width() - textWidth) / 2 - 5, 0, textWidth + 10,
+                     metrics.lineSpacing() + 5);
+    painter.setPen(Qt::white);
+    painter.drawText((width() - textWidth) / 2,
+                     metrics.leading() + metrics.ascent(), text);
+}
+//! [9]
+
+//! [10]
+void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */)
+{
+    thread.render(centerX, centerY, curScale, size());
+}
+//! [10]
+
+//! [11]
+void MandelbrotWidget::keyPressEvent(QKeyEvent *event)
+{
+    switch (event->key()) {
+    case Qt::Key_Plus:
+        zoom(ZoomInFactor);
+        break;
+    case Qt::Key_Minus:
+        zoom(ZoomOutFactor);
+        break;
+    case Qt::Key_Left:
+        scroll(-ScrollStep, 0);
+        break;
+    case Qt::Key_Right:
+        scroll(+ScrollStep, 0);
+        break;
+    case Qt::Key_Down:
+        scroll(0, -ScrollStep);
+        break;
+    case Qt::Key_Up:
+        scroll(0, +ScrollStep);
+        break;
+    default:
+        QWidget::keyPressEvent(event);
+    }
+}
+//! [11]
+
+//! [12]
+void MandelbrotWidget::wheelEvent(QWheelEvent *event)
+{
+    int numDegrees = event->delta() / 8;
+    double numSteps = numDegrees / 15.0f;
+    zoom(pow(ZoomInFactor, numSteps));
+}
+//! [12]
+
+//! [13]
+void MandelbrotWidget::mousePressEvent(QMouseEvent *event)
+{
+    if (event->button() == Qt::LeftButton)
+        lastDragPos = event->pos();
+}
+//! [13]
+
+//! [14]
+void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event)
+{
+    if (event->buttons() & Qt::LeftButton) {
+        pixmapOffset += event->pos() - lastDragPos;
+        lastDragPos = event->pos();
+        update();
+    }
+}
+//! [14]
+
+//! [15]
+void MandelbrotWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+    if (event->button() == Qt::LeftButton) {
+        pixmapOffset += event->pos() - lastDragPos;
+        lastDragPos = QPoint();
+
+        int deltaX = (width() - pixmap.width()) / 2 - pixmapOffset.x();
+        int deltaY = (height() - pixmap.height()) / 2 - pixmapOffset.y();
+        scroll(deltaX, deltaY);
+    }
+}
+//! [15]
+
+//! [16]
+void MandelbrotWidget::updatePixmap(const QImage &image, double scaleFactor)
+{
+    if (!lastDragPos.isNull())
+        return;
+
+    pixmap = QPixmap::fromImage(image);
+    pixmapOffset = QPoint();
+    lastDragPos = QPoint();
+    pixmapScale = scaleFactor;
+    update();
+}
+//! [16]
+
+//! [17]
+void MandelbrotWidget::zoom(double zoomFactor)
+{
+    curScale *= zoomFactor;
+    update();
+    thread.render(centerX, centerY, curScale, size());
+}
+//! [17]
+
+//! [18]
+void MandelbrotWidget::scroll(int deltaX, int deltaY)
+{
+    centerX += deltaX * curScale;
+    centerY += deltaY * curScale;
+    update();
+    thread.render(centerX, centerY, curScale, size());
+}
+//! [18]