diff options
author | Qt by Nokia <qt-info@nokia.com> | 2011-04-27 12:05:43 +0200 |
---|---|---|
committer | axis <qt-info@nokia.com> | 2011-04-27 12:05:43 +0200 |
commit | 38be0d13830efd2d98281c645c3a60afe05ffece (patch) | |
tree | 6ea73f3ec77f7d153333779883e8120f82820abe /demos |
Diffstat (limited to 'demos')
386 files changed, 32744 insertions, 0 deletions
diff --git a/demos/README b/demos/README new file mode 100644 index 0000000000..b1619908e2 --- /dev/null +++ b/demos/README @@ -0,0 +1,39 @@ +These demonstrations are intended to highlight Qt's capabilities in different +application areas, and provide examples that are more advanced than those in +the examples directory. + +Beginners to Qt may wish to try out the Qt tutorial and some of the examples +before examining the demonstrations in detail. + + +The example launcher can be used to explore the different categories +available. It provides an overview of each example, lets you view the +documentation in Qt Assistant, and is able to launch examples. + + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/demos/affine/affine.pro b/demos/affine/affine.pro new file mode 100644 index 0000000000..4f869987b9 --- /dev/null +++ b/demos/affine/affine.pro @@ -0,0 +1,25 @@ +SOURCES += main.cpp xform.cpp +HEADERS += xform.h + +contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +SHARED_FOLDER = ../shared + +include($$SHARED_FOLDER/shared.pri) + +RESOURCES += affine.qrc + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/affine +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.html *.jpg +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/affine +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + +wince*: { + DEPLOYMENT_PLUGIN += qjpeg +} diff --git a/demos/affine/affine.qrc b/demos/affine/affine.qrc new file mode 100644 index 0000000000..d8a7ae40cb --- /dev/null +++ b/demos/affine/affine.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/affine"> + <file>xform.cpp</file> + <file>xform.html</file> + <file>bg1.jpg</file> +</qresource> +</RCC> diff --git a/demos/affine/bg1.jpg b/demos/affine/bg1.jpg Binary files differnew file mode 100644 index 0000000000..dfc7cee6ad --- /dev/null +++ b/demos/affine/bg1.jpg diff --git a/demos/affine/main.cpp b/demos/affine/main.cpp new file mode 100644 index 0000000000..92b7fab81d --- /dev/null +++ b/demos/affine/main.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "xform.h" + +#include <QApplication> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(affine); + + QApplication app(argc, argv); + + XFormWidget xformWidget(0); + QStyle *arthurStyle = new ArthurStyle(); + xformWidget.setStyle(arthurStyle); + + QList<QWidget *> widgets = xformWidget.findChildren<QWidget *>(); + foreach (QWidget *w, widgets) { + w->setStyle(arthurStyle); + w->setAttribute(Qt::WA_AcceptTouchEvents); + } + + xformWidget.show(); + + return app.exec(); +} diff --git a/demos/affine/xform.cpp b/demos/affine/xform.cpp new file mode 100644 index 0000000000..724b640664 --- /dev/null +++ b/demos/affine/xform.cpp @@ -0,0 +1,902 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "xform.h" +#include "hoverpoints.h" + +#include <QLayout> +#include <QPainter> +#include <QPainterPath> + +const int alpha = 155; + +XFormView::XFormView(QWidget *parent) + : ArthurFrame(parent) +{ + setAttribute(Qt::WA_MouseTracking); + m_type = VectorType; + m_rotation = 0.0; + m_scale = 1.0; + m_shear = 0.0; + + m_pixmap = QPixmap(":res/affine/bg1.jpg"); + pts = new HoverPoints(this, HoverPoints::CircleShape); + pts->setConnectionType(HoverPoints::LineConnection); + pts->setEditable(false); + pts->setPointSize(QSize(15, 15)); + pts->setShapeBrush(QBrush(QColor(151, 0, 0, alpha))); + pts->setShapePen(QPen(QColor(255, 100, 50, alpha))); + pts->setConnectionPen(QPen(QColor(151, 0, 0, 50))); + pts->setBoundingRect(QRectF(0, 0, 500, 500)); + ctrlPoints << QPointF(250, 250) << QPointF(350, 250); + pts->setPoints(ctrlPoints); + connect(pts, SIGNAL(pointsChanged(QPolygonF)), + this, SLOT(updateCtrlPoints(QPolygonF))); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +XFormView::XFormType XFormView::type() const +{ + return m_type; +} + +QPixmap XFormView::pixmap() const +{ + return m_pixmap; +} + +QString XFormView::text() const +{ + return m_text; +} + +void XFormView::setText(const QString &t) +{ + m_text = t; + update(); +} + +void XFormView::setPixmap(const QPixmap &p) +{ + m_pixmap = p; + update(); +} + +void XFormView::setType(XFormType t) +{ + m_type = t; + update(); +} + +void XFormView::mousePressEvent(QMouseEvent *) +{ + setDescriptionEnabled(false); +} + +void XFormView::resizeEvent(QResizeEvent *e) +{ + pts->setBoundingRect(rect()); + ArthurFrame::resizeEvent(e); +} + +void XFormView::paint(QPainter *p) +{ + p->save(); + p->setRenderHint(QPainter::Antialiasing); + p->setRenderHint(QPainter::SmoothPixmapTransform); + switch (m_type) { + case VectorType: + drawVectorType(p); + break; + case PixmapType: + drawPixmapType(p); + break; + case TextType: + drawTextType(p); + break; + } + p->restore(); +} + +void XFormView::updateCtrlPoints(const QPolygonF &points) +{ + QPointF trans = points.at(0) - ctrlPoints.at(0); + + if (qAbs(points.at(0).x() - points.at(1).x()) < 10 + && qAbs(points.at(0).y() - points.at(1).y()) < 10) + pts->setPoints(ctrlPoints); + if (!trans.isNull()) { + ctrlPoints[0] = points.at(0); + ctrlPoints[1] += trans; + pts->setPoints(ctrlPoints); + } + ctrlPoints = points; + + QLineF line(ctrlPoints.at(0), ctrlPoints.at(1)); + m_rotation = line.angle(QLineF(0, 0, 1, 0)); + if (line.dy() < 0) + m_rotation = 360 - m_rotation; + + if (trans.isNull()) + emit rotationChanged(int(m_rotation*10)); +} + +void XFormView::setVectorType() +{ + m_type = VectorType; + update(); +} + +void XFormView::setPixmapType() +{ + m_type = PixmapType; + update(); +} + +void XFormView::setTextType() +{ + m_type = TextType; + update(); +} + +void XFormView::setAnimation(bool animate) +{ + timer.stop(); + if (animate) + timer.start(25, this); +} + +void XFormView::changeRotation(int r) +{ + setRotation(qreal(r) / 10); +} + +void XFormView::changeScale(int s) +{ + setScale(qreal(s) / 1000); +} + +void XFormView::changeShear(int s) +{ + setShear(qreal(s) / 1000); +} + +void XFormView::setShear(qreal s) +{ + m_shear = s; + update(); +} + +void XFormView::setScale(qreal s) +{ + m_scale = s; + update(); +} + +void XFormView::setRotation(qreal r) +{ + qreal old_rot = m_rotation; + m_rotation = r; + + QPointF center(pts->points().at(0)); + QMatrix m; + m.translate(center.x(), center.y()); + m.rotate(m_rotation - old_rot); + m.translate(-center.x(), -center.y()); + pts->setPoints(pts->points() * m); + + update(); +} + +void XFormView::timerEvent(QTimerEvent *e) +{ + if (e->timerId() == timer.timerId()) { + QPointF center(pts->points().at(0)); + QMatrix m; + m.translate(center.x(), center.y()); + m.rotate(0.2); + m.translate(-center.x(), -center.y()); + pts->setPoints(pts->points() * m); + + setUpdatesEnabled(false); + static qreal scale_inc = 0.003; + static qreal shear_inc = -0.001; + emit scaleChanged(int((m_scale + scale_inc) * 1000)); + emit shearChanged(int((m_shear + shear_inc) * 1000)); + if (m_scale >= 4.0 || m_scale <= 0.1) + scale_inc = -scale_inc; + if (m_shear >= 1.0 || m_shear <= -1.0) + shear_inc = -shear_inc; + setUpdatesEnabled(true); + + pts->firePointChange(); + } +} + +void XFormView::wheelEvent(QWheelEvent *e) +{ + m_scale += e->delta() / qreal(600); + m_scale = qMax(qreal(0.1), qMin(qreal(4), m_scale)); + emit scaleChanged(int(m_scale*1000)); +} + +void XFormView::reset() +{ + emit rotationChanged(0); + emit scaleChanged(1000); + emit shearChanged(0); + ctrlPoints = QPolygonF(); + ctrlPoints << QPointF(250, 250) << QPointF(350, 250); + pts->setPoints(ctrlPoints); + pts->firePointChange(); +} + +void XFormView::drawPixmapType(QPainter *painter) +{ + QPointF center(m_pixmap.width() / qreal(2), m_pixmap.height() / qreal(2)); + painter->translate(ctrlPoints.at(0) - center); + + painter->translate(center); + painter->rotate(m_rotation); + painter->scale(m_scale, m_scale); + painter->shear(0, m_shear); + painter->translate(-center); + + painter->drawPixmap(QPointF(0, 0), m_pixmap); + painter->setPen(QPen(QColor(255, 0, 0, alpha), 0.25, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(QRectF(0, 0, m_pixmap.width(), m_pixmap.height()).adjusted(-2, -2, 2, 2)); +} + +void XFormView::drawTextType(QPainter *painter) +{ + QPainterPath path; + QFont f("times new roman,utopia"); + f.setStyleStrategy(QFont::ForceOutline); + f.setPointSize(72); + f.setStyleHint(QFont::Times); + path.addText(0, 0, f, m_text); + + QFontMetrics fm(f); + QRectF br(fm.boundingRect(m_text)); + QPointF center(br.center()); + painter->translate(ctrlPoints.at(0) - center); + + painter->translate(center); + painter->rotate(m_rotation); + painter->scale(m_scale, m_scale); + painter->shear(0, m_shear); + painter->translate(-center); + + painter->fillPath(path, Qt::black); + + painter->setPen(QPen(QColor(255, 0, 0, alpha), 0.25, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(br.adjusted(-1, -1, 1, 1)); +} + +void XFormView::drawVectorType(QPainter *painter) +{ + QPainterPath path; + painter->translate(ctrlPoints.at(0) - QPointF(250,250)); + + painter->scale(0.77, 0.77); + painter->translate(98.9154 + 30 , -217.691 - 20); + + QRect br(-55, 275, 500, 590); + QPoint center = br.center(); + painter->translate(center.x(), center.y()); + painter->rotate(m_rotation); + painter->scale(m_scale, m_scale); + painter->shear(0, m_shear); + painter->translate(-center.x(), -center.y()); + + painter->setPen(Qt::NoPen); + path.moveTo(120, 470); + path.lineTo(60+245, 470); + path.lineTo(60+245, 470+350); + path.lineTo(60, 470+350); + path.lineTo(60, 470+80); + + painter->setBrush(Qt::white); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor( 193, 193, 191, 255)); + path.moveTo(329.336, 727.552); + path.cubicTo(QPointF(315.224, 726.328), QPointF(304.136, 715.816), QPointF(303.128, 694.936)); + path.cubicTo(QPointF(306.368, 639.496), QPointF(309.608, 582.112), QPointF(271.232, 545.104)); + path.cubicTo(QPointF(265.256, 499.024), QPointF(244.016, 482.104), QPointF(234.008, 452.512)); + path.lineTo(218.24, 441.208); + path.lineTo(237.104, 411.688); + path.lineTo(245.168, 411.904); + path.lineTo(323.936, 571.168); + path.lineTo(340.424, 651.448); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(136.232, 439.696); + path.cubicTo(QPointF(133.856, 455.248), QPointF(132.56, 470.512), QPointF(134.792, 485.272)); + path.cubicTo(QPointF(118.376, 507.592), QPointF(105.92, 530.128), QPointF(104.48, 553.312)); + path.cubicTo(QPointF(92.024, 586.504), QPointF(62.432, 614.584), QPointF(67.544, 680.104)); + path.cubicTo(QPointF(84.176, 697.456), QPointF(107.432, 713.584), QPointF(127.376, 730.36)); + path.cubicTo(QPointF(152.432, 751.312), QPointF(137.528, 778.96), QPointF(102.248, 772.408)); + path.cubicTo(QPointF(94.4, 763.768), QPointF(76.616, 709.624), QPointF(42.92, 676.288)); + path.lineTo(49.544, 632.584); + path.lineTo(81.368, 547.408); + path.lineTo(120.968, 484.048); + path.lineTo(125.36, 456.688); + path.lineTo(119.816, 386.776); + path.lineTo(124.424, 361.216); + path.lineTo(136.232, 439.696); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(115.64, 341.416); + path.cubicTo(QPointF(116.576, 336.376), QPointF(117.8, 331.624), QPointF(119.312, 327.16)); + path.lineTo(121.688, 342.784); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(120.968, 500.464); + path.cubicTo(QPointF(108.368, 523.792), QPointF(103.976, 546.256), QPointF(132.92, 550.216)); + path.cubicTo(QPointF(117.008, 553.888), QPointF(97.208, 568.648), QPointF(77.192, 593.488)); + path.lineTo(77.624, 543.016); + path.lineTo(101.456, 503.272); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(-33.256, 818.488); + path.cubicTo(QPointF(10.52, 838.144), QPointF(41.408, 837.064), QPointF(69.272, 850.96)); + path.cubicTo(QPointF(91.304, 862.552), QPointF(113.552, 861.184), QPointF(126.944, 847.144)); + path.cubicTo(QPointF(138.32, 832.456), QPointF(146.744, 831.736), QPointF(163.52, 830.224)); + path.cubicTo(QPointF(190.952, 828.568), QPointF(217.736, 828.28), QPointF(241.928, 830.8)); + path.lineTo(269.576, 833.032); + path.cubicTo(QPointF(269.072, 864.064), QPointF(328.04, 867.88), QPointF(345.392, 844.336)); + path.cubicTo(QPointF(366.344, 819.424), QPointF(395.144, 808.264), QPointF(419.84, 790.192)); + path.lineTo(289.304, 725.536); + path.cubicTo(QPointF(255.824, 806.464), QPointF(131.048, 827.632), QPointF(113.768, 763.264)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(286.424, 711.568); + path.cubicTo(QPointF(273.824, 711.496), QPointF(260.936, 715.6), QPointF(261.944, 732.16)); + path.lineTo(266.192, 776.44); + path.lineTo(304.424, 756.64); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(0, 0, 0, 255)); + path.moveTo(-37.36, 821.224); + path.cubicTo(QPointF(7.136, 840.88), QPointF(38.6, 839.728), QPointF(66.968, 853.696)); + path.cubicTo(QPointF(89.36, 865.216), QPointF(111.968, 863.92), QPointF(125.648, 849.808)); + path.cubicTo(QPointF(137.24, 835.192), QPointF(145.808, 834.472), QPointF(162.872, 832.96)); + path.cubicTo(QPointF(190.736, 831.232), QPointF(218.024, 831.016), QPointF(242.648, 833.464)); + path.lineTo(270.728, 835.768); + path.cubicTo(QPointF(270.224, 866.8), QPointF(330.272, 870.544), QPointF(347.912, 847)); + path.cubicTo(QPointF(369.224, 822.088), QPointF(398.528, 811), QPointF(423.656, 792.856)); + path.lineTo(290.816, 728.272); + path.cubicTo(QPointF(256.76, 809.128), QPointF(129.824, 830.296), QPointF(112.256, 766)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(183, 114, 0, 255)); + path.moveTo(382.328, 691.984); + path.cubicTo(QPointF(403.64, 698.968), QPointF(389.888, 720.28), QPointF(400.76, 732.52)); + path.cubicTo(QPointF(405.44, 742.888), QPointF(415.304, 752.032), QPointF(431.792, 760.528)); + path.cubicTo(QPointF(459.368, 774.424), QPointF(426.248, 799.336), QPointF(392.768, 812.08)); + path.cubicTo(QPointF(351.944, 825.616), QPointF(344.024, 862.912), QPointF(299.312, 851.896)); + path.cubicTo(QPointF(283.112, 846.496), QPointF(278.36, 831.808), QPointF(278.864, 809.128)); + path.cubicTo(QPointF(284.264, 762.76), QPointF(277.784, 730.432), QPointF(278.792, 698.824)); + path.cubicTo(QPointF(278.72, 686.152), QPointF(283.544, 684.64), QPointF(307.232, 687.952)); + path.cubicTo(QPointF(310.04, 726.328), QPointF(352.376, 727.336), QPointF(382.328, 691.984)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(242, 183, 0, 255)); + path.moveTo(339.632, 826.624); + path.cubicTo(QPointF(371.6, 814.312), QPointF(403.856, 798.112), QPointF(429.848, 782.128)); + path.cubicTo(QPointF(437.84, 777.448), QPointF(438.92, 765.928), QPointF(427.688, 762.328)); + path.cubicTo(QPointF(403.352, 748.504), QPointF(390.104, 731.224), QPointF(392.912, 708.76)); + path.cubicTo(QPointF(393.344, 700.912), QPointF(383.696, 692.56), QPointF(381.104, 700.048)); + path.cubicTo(QPointF(359.864, 771.472), QPointF(291.32, 767.656), QPointF(300.752, 696.952)); + path.cubicTo(QPointF(301.256, 694.864), QPointF(301.76, 692.776), QPointF(302.264, 690.76)); + path.cubicTo(QPointF(289.952, 688.24), QPointF(285.2, 690.976), QPointF(285.776, 700.408)); + path.lineTo(295.28, 806.608); + path.cubicTo(QPointF(297.656, 830.8), QPointF(317.312, 836.128), QPointF(339.632, 826.624)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(0, 0, 0, 255)); + path.moveTo(354.464, 537.544); + path.cubicTo(QPointF(379.16, 569.8), QPointF(404.432, 651.088), QPointF(384.416, 691.552)); + path.cubicTo(QPointF(360.944, 737.776), QPointF(307.808, 743.248), QPointF(305.504, 695.8)); + path.cubicTo(QPointF(308.816, 639.64), QPointF(311.984, 581.536), QPointF(273.68, 544.096)); + path.cubicTo(QPointF(267.704, 497.368), QPointF(246.392, 480.232), QPointF(236.384, 450.28)); + path.lineTo(203.12, 426.088); + path.lineTo(133.568, 435.088); + path.cubicTo(QPointF(130.76, 452.152), QPointF(129.104, 468.784), QPointF(131.552, 484.912)); + path.cubicTo(QPointF(115.064, 507.376), QPointF(102.608, 530.056), QPointF(101.168, 553.312)); + path.cubicTo(QPointF(88.712, 586.648), QPointF(59.12, 614.944), QPointF(64.232, 680.752)); + path.cubicTo(QPointF(80.864, 698.248), QPointF(104.12, 714.448), QPointF(124.064, 731.296)); + path.cubicTo(QPointF(149.12, 752.392), QPointF(135.512, 776.296), QPointF(100.232, 769.672)); + path.cubicTo(QPointF(78.848, 746.056), QPointF(56.744, 722.872), QPointF(35.288, 699.328)); + path.cubicTo(QPointF(12.392, 683.056), QPointF(3.896, 662.176), QPointF(27.368, 630.496)); + path.cubicTo(QPointF(43.424, 609.04), QPointF(47.96, 562.456), QPointF(62, 543.664)); + path.cubicTo(QPointF(74.312, 525.16), QPointF(92.24, 508.6), QPointF(105.272, 490.096)); + path.cubicTo(QPointF(112.184, 477.928), QPointF(114.344, 468.568), QPointF(113.264, 454.456)); + path.lineTo(110.312, 369.136); + path.cubicTo(QPointF(108.368, 307.216), QPointF(142.424, 274.24), QPointF(189.8, 275.248)); + path.cubicTo(QPointF(243.512, 275.752), QPointF(287.576, 312.472), QPointF(288.152, 378.28)); + path.cubicTo(QPointF(292.688, 410.32), QPointF(283.256, 428.68), QPointF(308.672, 474.472)); + path.cubicTo(QPointF(334.52, 522.712), QPointF(338.552, 520.12), QPointF(354.464, 537.544)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(261.296, 503.632); + path.lineTo(263.528, 512.2); + path.cubicTo(QPointF(257.696, 501.688), QPointF(250.712, 483.616), QPointF(241.928, 475.696)); + path.cubicTo(QPointF(239.264, 473.536), QPointF(235.808, 473.608), QPointF(233.72, 475.624)); + path.cubicTo(QPointF(222.056, 486.928), QPointF(193.112, 510.112), QPointF(169.928, 507.088)); + path.cubicTo(QPointF(152.072, 505.288), QPointF(134.648, 493.264), QPointF(130.832, 480.232)); + path.cubicTo(QPointF(128.816, 470.872), QPointF(129.752, 463.168), QPointF(130.976, 455.32)); + path.lineTo(240.704, 453.52); + path.cubicTo(QPointF(238.472, 463.168), QPointF(253.088, 487), QPointF(261.296, 503.632)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(143.144, 363.232); + path.cubicTo(QPointF(154.088, 363.232), QPointF(163.88, 376.84), QPointF(163.808, 395.632)); + path.cubicTo(QPointF(163.736, 408.232), QPointF(155.528, 411.472), QPointF(149.336, 417.016)); + path.cubicTo(QPointF(146.6, 419.536), QPointF(145.952, 433.144), QPointF(142.568, 433.144)); + path.cubicTo(QPointF(131.696, 433.144), QPointF(123.488, 413.776), QPointF(123.488, 395.632)); + path.cubicTo(QPointF(123.488, 377.56), QPointF(132.272, 363.232), QPointF(143.144, 363.232)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(255, 255, 255, 255)); + path.moveTo(144.368, 375.04); + path.cubicTo(QPointF(154.088, 375.04), QPointF(160.856, 379.936), QPointF(161.648, 391.312)); + path.cubicTo(QPointF(162.224, 399.16), QPointF(160.136, 411.76), QPointF(154.664, 414.424)); + path.cubicTo(QPointF(152.144, 415.648), QPointF(143.432, 426.664), QPointF(140.408, 426.52)); + path.cubicTo(QPointF(128.096, 425.944), QPointF(125, 402.112), QPointF(125.936, 390.736)); + path.cubicTo(QPointF(126.8, 379.36), QPointF(134.72, 375.04), QPointF(144.368, 375.04)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(0, 0, 0, 255)); + path.moveTo(141.848, 382.672); + path.cubicTo(QPointF(148.544, 382.096), QPointF(154.736, 389.728), QPointF(155.6, 399.664)); + path.cubicTo(QPointF(156.464, 409.6), QPointF(151.64, 418.24), QPointF(144.944, 418.816)); + path.cubicTo(QPointF(138.248, 419.392), QPointF(132.056, 411.76), QPointF(131.192, 401.752)); + path.cubicTo(QPointF(130.328, 391.816), QPointF(135.152, 383.248), QPointF(141.848, 382.672)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(151.064, 397.288); + path.cubicTo(QPointF(151.424, 399.088), QPointF(149.408, 400.024), QPointF(148.832, 398.224)); + path.cubicTo(QPointF(148.256, 395.992), QPointF(146.888, 393.328), QPointF(145.088, 391.168)); + path.cubicTo(QPointF(143.936, 389.872), QPointF(145.088, 388.432), QPointF(146.528, 389.44)); + path.cubicTo(QPointF(149.048, 391.528), QPointF(150.488, 394.12), QPointF(151.064, 397.288)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(216.944, 360.712); + path.cubicTo(QPointF(232.712, 360.712), QPointF(245.6, 377.416), QPointF(245.6, 397.792)); + path.cubicTo(QPointF(245.6, 418.24), QPointF(232.712, 434.872), QPointF(216.944, 434.872)); + path.cubicTo(QPointF(201.176, 434.872), QPointF(188.432, 418.24), QPointF(188.432, 397.792)); + path.cubicTo(QPointF(188.432, 377.416), QPointF(201.176, 360.712), QPointF(216.944, 360.712)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(255, 255, 255, 255)); + path.moveTo(224.792, 374.968); + path.cubicTo(QPointF(235.664, 378.856), QPointF(241.928, 387.424), QPointF(242.72, 396.568)); + path.cubicTo(QPointF(243.656, 407.08), QPointF(239.408, 418.96), QPointF(230.264, 425.944)); + path.cubicTo(QPointF(227.672, 427.888), QPointF(197.72, 416.08), QPointF(195.992, 411.616)); + path.cubicTo(QPointF(193.4, 405.208), QPointF(191.816, 392.896), QPointF(193.76, 385.624)); + path.cubicTo(QPointF(194.552, 382.744), QPointF(197.216, 378.568), QPointF(201.176, 376.336)); + path.cubicTo(QPointF(207.44, 372.808), QPointF(216.656, 372.088), QPointF(224.792, 374.968)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(0, 0, 0, 255)); + path.moveTo(216.872, 380.944); + path.cubicTo(QPointF(225.584, 380.944), QPointF(232.712, 389.296), QPointF(232.712, 399.448)); + path.cubicTo(QPointF(232.712, 409.672), QPointF(225.584, 418.024), QPointF(216.872, 418.024)); + path.cubicTo(QPointF(208.16, 418.024), QPointF(201.032, 409.672), QPointF(201.032, 399.448)); + path.cubicTo(QPointF(201.032, 389.296), QPointF(208.16, 380.944), QPointF(216.872, 380.944)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(227.096, 392.392); + path.cubicTo(QPointF(228.104, 394.048), QPointF(226.448, 395.776), QPointF(225.224, 394.12)); + path.cubicTo(QPointF(223.784, 392.104), QPointF(221.408, 389.944), QPointF(218.888, 388.432)); + path.cubicTo(QPointF(217.232, 387.568), QPointF(217.808, 385.624), QPointF(219.68, 386.2)); + path.cubicTo(QPointF(222.92, 387.28), QPointF(225.368, 389.368), QPointF(227.096, 392.392)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(183, 114, 0, 255)); + path.moveTo(164.96, 404.488); + path.cubicTo(QPointF(172.376, 402.328), QPointF(184.112, 403.048), QPointF(192.248, 404.632)); + path.cubicTo(QPointF(200.384, 406.792), QPointF(222.056, 418.24), QPointF(245.024, 430.696)); + path.cubicTo(QPointF(247.976, 432.208), QPointF(248.84, 437.104), QPointF(245.024, 438.688)); + path.cubicTo(QPointF(239.12, 439.12), QPointF(249.272, 453.664), QPointF(238.904, 458.848)); + path.cubicTo(QPointF(223.352, 462.88), QPointF(198.44, 485.992), QPointF(186.128, 487.864)); + path.cubicTo(QPointF(179.288, 489.376), QPointF(172.232, 489.592), QPointF(164.6, 487.864)); + path.cubicTo(QPointF(140.552, 482.968), QPointF(134.216, 455.608), QPointF(122.912, 450.064)); + path.cubicTo(QPointF(119.816, 446.824), QPointF(121.4, 441.208), QPointF(122.408, 440.056)); + path.cubicTo(QPointF(123.632, 434.224), QPointF(149.696, 406.216), QPointF(164.96, 404.488)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(242, 183, 0, 255)); + path.moveTo(185.408, 405.856); + path.cubicTo(QPointF(198.44, 407.296), QPointF(226.088, 423.928), QPointF(239.408, 430.624)); + path.cubicTo(QPointF(242.72, 432.424), QPointF(242.504, 437.824), QPointF(239.552, 438.688)); + path.cubicTo(QPointF(236.384, 440.488), QPointF(235.448, 438.256), QPointF(232.928, 437.896)); + path.cubicTo(QPointF(228.896, 435.736), QPointF(222.272, 440.92), QPointF(217.016, 444.88)); + path.cubicTo(QPointF(186.704, 467.776), QPointF(180.656, 465.256), QPointF(156.176, 462.664)); + path.cubicTo(QPointF(147.68, 460.576), QPointF(142.136, 457.984), QPointF(139.688, 455.968)); + path.cubicTo(QPointF(141.488, 445.888), QPointF(160.496, 407.656), QPointF(166.76, 406.792)); + path.cubicTo(QPointF(168.344, 404.704), QPointF(179.936, 404.632), QPointF(185.408, 405.856)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(183, 114, 0, 255)); + path.moveTo(190.664, 412.048); + path.lineTo(193.76, 413.416); + path.cubicTo(QPointF(196.064, 414.712), QPointF(193.256, 418.168), QPointF(190.736, 417.088)); + path.lineTo(186.2, 415.504); + path.cubicTo(QPointF(183.536, 413.272), QPointF(186.704, 410.104), QPointF(190.664, 412.048)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(268.568, 452.368); + path.cubicTo(QPointF(273.032, 454.384), QPointF(279.224, 457.192), QPointF(282.536, 460.144)); + path.cubicTo(QPointF(285.488, 464.104), QPointF(286.784, 468.064), QPointF(286.424, 472.024)); + path.cubicTo(QPointF(285.776, 474.544), QPointF(284.12, 476.344), QPointF(281.24, 477.424)); + path.cubicTo(QPointF(277.856, 478.216), QPointF(273.68, 477.424), QPointF(271.376, 474.112)); + path.cubicTo(QPointF(269.864, 471.448), QPointF(265.256, 462.16), QPointF(263.96, 460.576)); + path.cubicTo(QPointF(262.232, 457.12), QPointF(261.944, 454.456), QPointF(262.88, 452.368)); + path.cubicTo(QPointF(264.032, 451.288), QPointF(266.048, 451), QPointF(268.568, 452.368)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(255, 255, 255, 255)); + path.moveTo(273.752, 461.584); + path.cubicTo(QPointF(275.48, 462.376), QPointF(277.928, 463.456), QPointF(279.224, 464.68)); + path.cubicTo(QPointF(280.376, 466.264), QPointF(280.88, 467.776), QPointF(280.736, 469.36)); + path.cubicTo(QPointF(280.52, 470.296), QPointF(279.8, 471.016), QPointF(278.72, 471.448)); + path.cubicTo(QPointF(277.352, 471.808), QPointF(275.768, 471.448), QPointF(274.832, 470.152)); + path.cubicTo(QPointF(274.256, 469.144), QPointF(272.456, 465.472), QPointF(271.952, 464.824)); + path.cubicTo(QPointF(271.232, 463.456), QPointF(271.088, 462.448), QPointF(271.448, 461.584)); + path.cubicTo(QPointF(271.952, 461.152), QPointF(272.744, 461.08), QPointF(273.752, 461.584)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(238.616, 358.552); + path.cubicTo(QPointF(239.048, 359.2), QPointF(238.976, 359.776), QPointF(238.4, 360.28)); + path.cubicTo(QPointF(237.896, 360.784), QPointF(237.176, 360.712), QPointF(236.24, 360.208)); + path.lineTo(231.632, 356.248); + path.cubicTo(QPointF(231.056, 355.744), QPointF(230.912, 354.952), QPointF(231.272, 354.088)); + path.cubicTo(QPointF(232.28, 353.44), QPointF(233.144, 353.44), QPointF(233.936, 354.088)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(235.592, 305.992); + path.cubicTo(QPointF(239.624, 308.224), QPointF(240.848, 313.912), QPointF(238.184, 318.592)); + path.cubicTo(QPointF(235.592, 323.2), QPointF(230.12, 325.144), QPointF(226.016, 322.84)); + path.cubicTo(QPointF(221.984, 320.536), QPointF(220.76, 314.92), QPointF(223.424, 310.24)); + path.cubicTo(QPointF(226.016, 305.56), QPointF(231.488, 303.688), QPointF(235.592, 305.992)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(374.912, 680.536); + path.cubicTo(QPointF(378.296, 683.128), QPointF(373.256, 687.376), QPointF(371.024, 686.296)); + path.cubicTo(QPointF(369.152, 685.648), QPointF(367.784, 683.488), QPointF(366.92, 682.408)); + path.cubicTo(QPointF(366.128, 681.184), QPointF(366.2, 679.168), QPointF(366.92, 678.448)); + path.cubicTo(QPointF(367.712, 677.44), QPointF(369.728, 677.656), QPointF(371.024, 678.52)); + path.cubicTo(QPointF(372.32, 679.168), QPointF(373.616, 679.888), QPointF(374.912, 680.536)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(297.44, 551.512); + path.cubicTo(QPointF(338.984, 572.896), QPointF(350, 611.56), QPointF(332.072, 664.192)); + path.cubicTo(QPointF(330.992, 666.64), QPointF(334.16, 668.368), QPointF(335.24, 666.064)); + path.cubicTo(QPointF(354.824, 610.336), QPointF(341.432, 571.312), QPointF(299.024, 548.56)); + path.cubicTo(QPointF(296.864, 547.552), QPointF(295.28, 550.432), QPointF(297.44, 551.512)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(72.008, 569.512); + path.cubicTo(QPointF(38.312, 627.256), QPointF(38.096, 662.68), QPointF(62.504, 681.328)); + path.cubicTo(QPointF(63.728, 682.264), QPointF(64.448, 680.032), QPointF(63.296, 679.168)); + path.cubicTo(QPointF(36.296, 655.48), QPointF(48.896, 615.52), QPointF(74.168, 570.88)); + path.cubicTo(QPointF(74.888, 569.584), QPointF(72.512, 568.432), QPointF(72.008, 569.512)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(289.376, 586.864); + path.cubicTo(QPointF(289.232, 589.168), QPointF(288.368, 589.528), QPointF(286.424, 587.368)); + path.cubicTo(QPointF(279.8, 575.848), QPointF(235.088, 551.44), QPointF(213.344, 548.704)); + path.cubicTo(QPointF(209.24, 547.264), QPointF(209.456, 545.392), QPointF(213.488, 544.816)); + path.cubicTo(QPointF(229.184, 544.816), QPointF(241.28, 537.904), QPointF(254.96, 537.904)); + path.cubicTo(QPointF(258.704, 538.048), QPointF(262.304, 539.488), QPointF(264.392, 541.648)); + path.cubicTo(QPointF(269.504, 544.96), QPointF(288.08, 570.592), QPointF(289.376, 586.864)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(180.152, 546.832); + path.cubicTo(QPointF(180.872, 550.792), QPointF(163.808, 545.68), QPointF(164.744, 556.696)); + path.cubicTo(QPointF(165.032, 559.72), QPointF(160.496, 561.376), QPointF(160.64, 556.696)); + path.cubicTo(QPointF(160.64, 548.272), QPointF(161.072, 548.416), QPointF(152.72, 546.832)); + path.cubicTo(QPointF(151.208, 546.76), QPointF(151.352, 544.528), QPointF(152.72, 544.816)); + path.lineTo(152.72, 544.816); + path.cubicTo(QPointF(158.696, 546.472), QPointF(166.76, 542.872), QPointF(166.4, 538.84)); + path.cubicTo(QPointF(166.256, 537.472), QPointF(168.56, 537.688), QPointF(168.488, 538.84)); + path.cubicTo(QPointF(167.984, 545.248), QPointF(181.664, 542.152), QPointF(180.152, 546.832)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(193, 193, 191, 255)); + path.moveTo(151.568, 705.376); + path.cubicTo(QPointF(151.64, 708.328), QPointF(148.76, 707.68), QPointF(148.544, 705.592)); + path.cubicTo(QPointF(140.192, 680.536), QPointF(143.72, 618.832), QPointF(151.856, 598.96)); + path.cubicTo(QPointF(152.432, 596.08), QPointF(156.248, 596.944), QPointF(155.744, 598.96)); + path.cubicTo(QPointF(147.104, 635.464), QPointF(147.248, 673.048), QPointF(151.568, 705.376)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(183, 114, 0, 255)); + path.moveTo(51.704, 684.424); + path.cubicTo(QPointF(75.68, 707.824), QPointF(91.376, 743.248), QPointF(114.632, 775.288)); + path.cubicTo(QPointF(148.472, 816.04), QPointF(121.472, 858.304), QPointF(66.464, 845.56)); + path.cubicTo(QPointF(38.888, 835.192), QPointF(-0.784, 836.344), QPointF(-32.68, 825.832)); + path.cubicTo(QPointF(-55.072, 820.36), QPointF(-55.864, 809.272), QPointF(-44.416, 787.6)); + path.cubicTo(QPointF(-40.384, 773.776), QPointF(-40.024, 751.312), QPointF(-43.768, 732.592)); + path.cubicTo(QPointF(-45.784, 718.408), QPointF(-39.232, 710.488), QPointF(-24.112, 708.832)); + path.lineTo(-24.112, 708.832); + path.cubicTo(QPointF(-11.296, 708.688), QPointF(6.56, 713.872), QPointF(16.28, 686.44)); + path.cubicTo(QPointF(23.552, 673.336), QPointF(40.976, 672.976), QPointF(51.704, 684.424)); + path.closeSubpath(); + painter->drawPath(path); + path = QPainterPath(); + + painter->setBrush(QColor(242, 183, 0, 255)); + path.moveTo(24.632, 699.04); + path.cubicTo(QPointF(23.84, 680.968), QPointF(39.32, 677.296), QPointF(49.688, 688.312)); + path.cubicTo(QPointF(68.192, 710.992), QPointF(85.112, 736.048), QPointF(100.376, 764.992)); + path.cubicTo(QPointF(124.712, 804.16), QPointF(104.624, 842.68), QPointF(67.904, 828.064)); + path.cubicTo(QPointF(49.688, 817.84), QPointF(6.128, 813.304), QPointF(-17.344, 809.128)); + path.cubicTo(QPointF(-33.04, 807.832), QPointF(-35.128, 797.608), QPointF(-29.152, 791.848)); + path.cubicTo(QPointF(-20.944, 782.416), QPointF(-20.08, 759.808), QPointF(-27.856, 740.512)); + path.cubicTo(QPointF(-35.56, 728.56), QPointF(-21.088, 715.384), QPointF(-9.712, 720.856)); + path.cubicTo(QPointF(0.8, 727.048), QPointF(25.64, 713.08), QPointF(24.632, 699.04)); + path.closeSubpath(); + painter->drawPath(path); + + painter->setPen(QPen(QColor(255, 0, 0, alpha), 0.25, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(br.adjusted(-1, -1, 1, 1)); +} + + +XFormWidget::XFormWidget(QWidget *parent) + : QWidget(parent), textEditor(new QLineEdit) +{ + setWindowTitle(tr("Affine Transformations")); + + view = new XFormView(this); + view->setMinimumSize(200, 200); + + QGroupBox *mainGroup = new QGroupBox(this); + mainGroup->setFixedWidth(180); + mainGroup->setTitle(tr("Affine Transformations")); + + QGroupBox *rotateGroup = new QGroupBox(mainGroup); + rotateGroup->setTitle(tr("Rotate")); + QSlider *rotateSlider = new QSlider(Qt::Horizontal, rotateGroup); + rotateSlider->setRange(0, 3600); + rotateSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QGroupBox *scaleGroup = new QGroupBox(mainGroup); + scaleGroup->setTitle(tr("Scale")); + QSlider *scaleSlider = new QSlider(Qt::Horizontal, scaleGroup); + scaleSlider->setRange(1, 4000); + scaleSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QGroupBox *shearGroup = new QGroupBox(mainGroup); + shearGroup->setTitle(tr("Shear")); + QSlider *shearSlider = new QSlider(Qt::Horizontal, shearGroup); + shearSlider->setRange(-990, 990); + shearSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QGroupBox *typeGroup = new QGroupBox(mainGroup); + typeGroup->setTitle(tr("Type")); + QRadioButton *vectorType = new QRadioButton(typeGroup); + QRadioButton *pixmapType = new QRadioButton(typeGroup); + QRadioButton *textType= new QRadioButton(typeGroup); + vectorType->setText(tr("Vector Image")); + pixmapType->setText(tr("Pixmap")); + textType->setText(tr("Text")); + + QPushButton *resetButton = new QPushButton(mainGroup); + resetButton->setText(tr("Reset Transform")); + + QPushButton *animateButton = new QPushButton(mainGroup); + animateButton->setText(tr("Animate")); + animateButton->setCheckable(true); + + QPushButton *showSourceButton = new QPushButton(mainGroup); + showSourceButton->setText(tr("Show Source")); +#ifdef QT_OPENGL_SUPPORT + QPushButton *enableOpenGLButton = new QPushButton(mainGroup); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(true); + enableOpenGLButton->setChecked(view->usesOpenGL()); + if (!QGLFormat::hasOpenGL()) + enableOpenGLButton->hide(); +#endif + QPushButton *whatsThisButton = new QPushButton(mainGroup); + whatsThisButton->setText(tr("What's This?")); + whatsThisButton->setCheckable(true); + + QHBoxLayout *viewLayout = new QHBoxLayout(this); + viewLayout->addWidget(view); + viewLayout->addWidget(mainGroup); + + QVBoxLayout *rotateGroupLayout = new QVBoxLayout(rotateGroup); + rotateGroupLayout->addWidget(rotateSlider); + + QVBoxLayout *scaleGroupLayout = new QVBoxLayout(scaleGroup); + scaleGroupLayout->addWidget(scaleSlider); + + QVBoxLayout *shearGroupLayout = new QVBoxLayout(shearGroup); + shearGroupLayout->addWidget(shearSlider); + + QVBoxLayout *typeGroupLayout = new QVBoxLayout(typeGroup); + typeGroupLayout->addWidget(vectorType); + typeGroupLayout->addWidget(pixmapType); + typeGroupLayout->addWidget(textType); + typeGroupLayout->addSpacing(4); + typeGroupLayout->addWidget(textEditor); + + QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); + mainGroupLayout->addWidget(rotateGroup); + mainGroupLayout->addWidget(scaleGroup); + mainGroupLayout->addWidget(shearGroup); + mainGroupLayout->addWidget(typeGroup); + mainGroupLayout->addStretch(1); + mainGroupLayout->addWidget(resetButton); + mainGroupLayout->addWidget(animateButton); + mainGroupLayout->addWidget(showSourceButton); +#ifdef QT_OPENGL_SUPPORT + mainGroupLayout->addWidget(enableOpenGLButton); +#endif + mainGroupLayout->addWidget(whatsThisButton); + + connect(rotateSlider, SIGNAL(valueChanged(int)), view, SLOT(changeRotation(int))); + connect(shearSlider, SIGNAL(valueChanged(int)), view, SLOT(changeShear(int))); + connect(scaleSlider, SIGNAL(valueChanged(int)), view, SLOT(changeScale(int))); + + connect(vectorType, SIGNAL(clicked()), view, SLOT(setVectorType())); + connect(pixmapType, SIGNAL(clicked()), view, SLOT(setPixmapType())); + connect(textType, SIGNAL(clicked()), view, SLOT(setTextType())); + connect(textType, SIGNAL(toggled(bool)), textEditor, SLOT(setEnabled(bool))); + connect(textEditor, SIGNAL(textChanged(QString)), view, SLOT(setText(QString))); + + connect(view, SIGNAL(rotationChanged(int)), rotateSlider, SLOT(setValue(int))); + connect(view, SIGNAL(scaleChanged(int)), scaleSlider, SLOT(setValue(int))); + connect(view, SIGNAL(shearChanged(int)), shearSlider, SLOT(setValue(int))); + + connect(resetButton, SIGNAL(clicked()), view, SLOT(reset())); + connect(animateButton, SIGNAL(clicked(bool)), view, SLOT(setAnimation(bool))); + connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool))); + connect(whatsThisButton, SIGNAL(clicked(bool)), view->hoverPoints(), SLOT(setDisabled(bool))); + connect(view, SIGNAL(descriptionEnabledChanged(bool)), view->hoverPoints(), SLOT(setDisabled(bool))); + connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool))); + connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource())); +#ifdef QT_OPENGL_SUPPORT + connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool))); +#endif + view->loadSourceFile(":res/affine/xform.cpp"); + view->loadDescription(":res/affine/xform.html"); + + // defaults + view->reset(); + vectorType->setChecked(true); + textEditor->setText("Qt Affine Transformation Demo"); + textEditor->setEnabled(false); + + animateButton->animateClick(); +} diff --git a/demos/affine/xform.h b/demos/affine/xform.h new file mode 100644 index 0000000000..80e672b0e4 --- /dev/null +++ b/demos/affine/xform.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef XFORM_H +#define XFORM_H + +#include "arthurwidgets.h" + +#include <QBasicTimer> +#include <QPolygonF> + +class HoverPoints; +QT_FORWARD_DECLARE_CLASS(QLineEdit) + +class XFormView : public ArthurFrame +{ +public: + Q_OBJECT + + Q_PROPERTY(XFormType type READ type WRITE setType) + Q_PROPERTY(bool animation READ animation WRITE setAnimation) + Q_PROPERTY(qreal shear READ shear WRITE setShear) + Q_PROPERTY(qreal rotation READ rotation WRITE setRotation) + Q_PROPERTY(qreal scale READ scale WRITE setScale) + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap) + Q_ENUMS(XFormType) + +public: + enum XFormType { VectorType, PixmapType, TextType }; + + XFormView(QWidget *parent); + void paint(QPainter *); + void drawVectorType(QPainter *painter); + void drawPixmapType(QPainter *painter); + void drawTextType(QPainter *painter); + QSize sizeHint() const { return QSize(500, 500); } + + void mousePressEvent(QMouseEvent *e); + void resizeEvent(QResizeEvent *e); + HoverPoints *hoverPoints() { return pts; } + + bool animation() const { return timer.isActive(); } + qreal shear() const { return m_shear; } + qreal scale() const { return m_scale; } + qreal rotation() const { return m_rotation; } + void setShear(qreal s); + void setScale(qreal s); + void setRotation(qreal r); + + XFormType type() const; + QPixmap pixmap() const; + QString text() const; + +public slots: + void setAnimation(bool animate); + void updateCtrlPoints(const QPolygonF &); + void changeRotation(int rotation); + void changeScale(int scale); + void changeShear(int shear); + + void setText(const QString &); + void setPixmap(const QPixmap &); + void setType(XFormType t); + + void setVectorType(); + void setPixmapType(); + void setTextType(); + void reset(); + +signals: + void rotationChanged(int rotation); + void scaleChanged(int scale); + void shearChanged(int shear); + +protected: + void timerEvent(QTimerEvent *e); + void wheelEvent(QWheelEvent *); + +private: + QPolygonF ctrlPoints; + HoverPoints *pts; + qreal m_rotation; + qreal m_scale; + qreal m_shear; + XFormType m_type; + QPixmap m_pixmap; + QString m_text; + QBasicTimer timer; +}; + +class XFormWidget : public QWidget +{ + Q_OBJECT +public: + XFormWidget(QWidget *parent); + +private: + XFormView *view; + QLineEdit *textEditor; +}; + +#endif // XFORM_H diff --git a/demos/affine/xform.html b/demos/affine/xform.html new file mode 100644 index 0000000000..17325ac2a0 --- /dev/null +++ b/demos/affine/xform.html @@ -0,0 +1,23 @@ +<html> +<center> +<h2>Affine Transformations</h2> +</center> + +<p>In this demo we demonstrate Qt's ability to perform affine transformations +on painting operations.</p> + +<p>Transformations can be performed on any kind of graphics drawn using +QPainter. The transformations used to display the vector graphics, images, +and text can be adjusted in the following ways:</p> + +<ul> + <li>Dragging the red circle in the centre of each drawing moves it to a new + position.</li> + <li>Dragging the displaced red circle causes the current drawing to be + rotated about the central circle. Rotation can also be controlled with + the <b>Rotate</b> slider.</li> + <li>Scaling is controlled with the <b>Scale</b> slider.</li> + <li>Each drawing can be sheared with the <b>Shear</b> slider.</li> +</ul> + +</html> diff --git a/demos/books/bookdelegate.cpp b/demos/books/bookdelegate.cpp new file mode 100644 index 0000000000..eb5d95b7b5 --- /dev/null +++ b/demos/books/bookdelegate.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "bookdelegate.h" + +#include <QtGui> + +BookDelegate::BookDelegate(QObject *parent) + : QSqlRelationalDelegate(parent), star(QPixmap(":images/star.png")) +{ +} + +void BookDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (index.column() != 5) { + QStyleOptionViewItemV3 opt = option; + opt.rect.adjust(0, 0, -1, -1); // since we draw the grid ourselves + QSqlRelationalDelegate::paint(painter, opt, index); + } else { + const QAbstractItemModel *model = index.model(); + QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? + (option.state & QStyle::State_Active) ? QPalette::Normal : QPalette::Inactive : QPalette::Disabled; + + if (option.state & QStyle::State_Selected) + painter->fillRect(option.rect, option.palette.color(cg, QPalette::Highlight)); + + int rating = model->data(index, Qt::DisplayRole).toInt(); + int width = star.width(); + int height = star.height(); + int x = option.rect.x(); + int y = option.rect.y() + (option.rect.height() / 2) - (height / 2); + for (int i = 0; i < rating; ++i) { + painter->drawPixmap(x, y, star); + x += width; + } + drawFocus(painter, option, option.rect.adjusted(0, 0, -1, -1)); // since we draw the grid ourselves + } + + QPen pen = painter->pen(); + painter->setPen(option.palette.color(QPalette::Mid)); + painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); + painter->drawLine(option.rect.topRight(), option.rect.bottomRight()); + painter->setPen(pen); +} + +QSize BookDelegate::sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (index.column() == 5) + return QSize(5 * star.width(), star.height()) + QSize(1, 1); + + return QSqlRelationalDelegate::sizeHint(option, index) + QSize(1, 1); // since we draw the grid ourselves +} + +bool BookDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, + const QStyleOptionViewItem &option, + const QModelIndex &index) +{ + if (index.column() != 5) + return QSqlRelationalDelegate::editorEvent(event, model, option, index); + + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); + int stars = qBound(0, int(0.7 + qreal(mouseEvent->pos().x() + - option.rect.x()) / star.width()), 5); + model->setData(index, QVariant(stars)); + return false; //so that the selection can change + } + + return true; +} + +QWidget *BookDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (index.column() != 4) + return QSqlRelationalDelegate::createEditor(parent, option, index); + + // for editing the year, return a spinbox with a range from -1000 to 2100. + QSpinBox *sb = new QSpinBox(parent); + sb->setFrame(false); + sb->setMaximum(2100); + sb->setMinimum(-1000); + + return sb; +} + diff --git a/demos/books/bookdelegate.h b/demos/books/bookdelegate.h new file mode 100644 index 0000000000..bb1d824804 --- /dev/null +++ b/demos/books/bookdelegate.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef BOOKDELEGATE_H +#define BOOKDELEGATE_H + +#include <QModelIndex> +#include <QPixmap> +#include <QSize> +#include <QSqlRelationalDelegate> + +QT_FORWARD_DECLARE_CLASS(QPainter) + +class BookDelegate : public QSqlRelationalDelegate +{ +public: + BookDelegate(QObject *parent); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + + bool editorEvent(QEvent *event, QAbstractItemModel *model, + const QStyleOptionViewItem &option, + const QModelIndex &index); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + +private: + QPixmap star; +}; + +#endif diff --git a/demos/books/books.pro b/demos/books/books.pro new file mode 100644 index 0000000000..ad4009035c --- /dev/null +++ b/demos/books/books.pro @@ -0,0 +1,23 @@ +TEMPLATE = app +INCLUDEPATH += . + +HEADERS = bookdelegate.h bookwindow.h initdb.h +RESOURCES = books.qrc +SOURCES = bookdelegate.cpp main.cpp bookwindow.cpp +FORMS = bookwindow.ui + +QT += sql + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/books +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro images +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/books +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + +wince*: { + CONFIG(debug, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*d4.dll + CONFIG(release, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*[^d]4.dll + sqlPlugins.path = sqldrivers + DEPLOYMENT += sqlPlugins +} diff --git a/demos/books/books.qrc b/demos/books/books.qrc new file mode 100644 index 0000000000..342638ecb0 --- /dev/null +++ b/demos/books/books.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> + <file>images/star.png</file> +</qresource> +</RCC> diff --git a/demos/books/bookwindow.cpp b/demos/books/bookwindow.cpp new file mode 100644 index 0000000000..23e64c2b48 --- /dev/null +++ b/demos/books/bookwindow.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "bookwindow.h" +#include "bookdelegate.h" +#include "initdb.h" + +#include <QtSql> + +BookWindow::BookWindow() +{ + ui.setupUi(this); + + if (!QSqlDatabase::drivers().contains("QSQLITE")) + QMessageBox::critical(this, "Unable to load database", "This demo needs the SQLITE driver"); + + // initialize the database + QSqlError err = initDb(); + if (err.type() != QSqlError::NoError) { + showError(err); + return; + } + + // Create the data model + model = new QSqlRelationalTableModel(ui.bookTable); + model->setEditStrategy(QSqlTableModel::OnManualSubmit); + model->setTable("books"); + + // Remember the indexes of the columns + authorIdx = model->fieldIndex("author"); + genreIdx = model->fieldIndex("genre"); + + // Set the relations to the other database tables + model->setRelation(authorIdx, QSqlRelation("authors", "id", "name")); + model->setRelation(genreIdx, QSqlRelation("genres", "id", "name")); + + // Set the localized header captions + model->setHeaderData(authorIdx, Qt::Horizontal, tr("Author Name")); + model->setHeaderData(genreIdx, Qt::Horizontal, tr("Genre")); + model->setHeaderData(model->fieldIndex("title"), Qt::Horizontal, tr("Title")); + model->setHeaderData(model->fieldIndex("year"), Qt::Horizontal, tr("Year")); + model->setHeaderData(model->fieldIndex("rating"), Qt::Horizontal, tr("Rating")); + + // Populate the model + if (!model->select()) { + showError(model->lastError()); + return; + } + + // Set the model and hide the ID column + ui.bookTable->setModel(model); + ui.bookTable->setItemDelegate(new BookDelegate(ui.bookTable)); + ui.bookTable->setColumnHidden(model->fieldIndex("id"), true); + ui.bookTable->setSelectionMode(QAbstractItemView::SingleSelection); + + // Initialize the Author combo box + ui.authorEdit->setModel(model->relationModel(authorIdx)); + ui.authorEdit->setModelColumn(model->relationModel(authorIdx)->fieldIndex("name")); + + ui.genreEdit->setModel(model->relationModel(genreIdx)); + ui.genreEdit->setModelColumn(model->relationModel(genreIdx)->fieldIndex("name")); + + QDataWidgetMapper *mapper = new QDataWidgetMapper(this); + mapper->setModel(model); + mapper->setItemDelegate(new BookDelegate(this)); + mapper->addMapping(ui.titleEdit, model->fieldIndex("title")); + mapper->addMapping(ui.yearEdit, model->fieldIndex("year")); + mapper->addMapping(ui.authorEdit, authorIdx); + mapper->addMapping(ui.genreEdit, genreIdx); + mapper->addMapping(ui.ratingEdit, model->fieldIndex("rating")); + + connect(ui.bookTable->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + mapper, SLOT(setCurrentModelIndex(QModelIndex))); + + ui.bookTable->setCurrentIndex(model->index(0, 0)); +} + +void BookWindow::showError(const QSqlError &err) +{ + QMessageBox::critical(this, "Unable to initialize Database", + "Error initializing database: " + err.text()); +} + diff --git a/demos/books/bookwindow.h b/demos/books/bookwindow.h new file mode 100644 index 0000000000..96545d7e8b --- /dev/null +++ b/demos/books/bookwindow.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef BOOKWINDOW_H +#define BOOKWINDOW_H + +#include <QtGui> +#include <QtSql> + +#include "ui_bookwindow.h" + + +class BookWindow: public QMainWindow +{ + Q_OBJECT +public: + BookWindow(); + +private: + void showError(const QSqlError &err); + Ui::BookWindow ui; + QSqlRelationalTableModel *model; + int authorIdx, genreIdx; +}; + +#endif diff --git a/demos/books/bookwindow.ui b/demos/books/bookwindow.ui new file mode 100644 index 0000000000..659d324564 --- /dev/null +++ b/demos/books/bookwindow.ui @@ -0,0 +1,149 @@ +<ui version="4.0" > + <author></author> + <comment></comment> + <exportmacro></exportmacro> + <class>BookWindow</class> + <widget class="QMainWindow" name="BookWindow" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>601</width> + <height>420</height> + </rect> + </property> + <property name="windowTitle" > + <string>Books</string> + </property> + <widget class="QWidget" name="centralWidget" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QGroupBox" name="groupBox" > + <property name="title" > + <string>Books</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QTableView" name="bookTable" > + <property name="selectionBehavior" > + <enum>QAbstractItemView::SelectRows</enum> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Details</string> + </property> + <layout class="QFormLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label_5" > + <property name="text" > + <string><b>Title:</b></string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QLineEdit" name="titleEdit" > + <property name="enabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_2_2_2_2" > + <property name="text" > + <string><b>Author: </b></string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QComboBox" name="authorEdit" > + <property name="enabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string><b>Genre:</b></string> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QComboBox" name="genreEdit" > + <property name="enabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string><b>Year:</b></string> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QSpinBox" name="yearEdit" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="prefix" > + <string/> + </property> + <property name="maximum" > + <number>2100</number> + </property> + <property name="minimum" > + <number>-1000</number> + </property> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string><b>Rating:</b></string> + </property> + </widget> + </item> + <item row="4" column="1" > + <widget class="QSpinBox" name="ratingEdit" > + <property name="maximum" > + <number>5</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + <pixmapfunction></pixmapfunction> + <tabstops> + <tabstop>bookTable</tabstop> + <tabstop>titleEdit</tabstop> + <tabstop>authorEdit</tabstop> + <tabstop>genreEdit</tabstop> + <tabstop>yearEdit</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/demos/books/images/star.png b/demos/books/images/star.png Binary files differnew file mode 100644 index 0000000000..87f4464bd5 --- /dev/null +++ b/demos/books/images/star.png diff --git a/demos/books/initdb.h b/demos/books/initdb.h new file mode 100644 index 0000000000..5351ad58e6 --- /dev/null +++ b/demos/books/initdb.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef INITDB_H +#define INITDB_H + +#include <QtSql> + +void addBook(QSqlQuery &q, const QString &title, int year, const QVariant &authorId, + const QVariant &genreId, int rating) +{ + q.addBindValue(title); + q.addBindValue(year); + q.addBindValue(authorId); + q.addBindValue(genreId); + q.addBindValue(rating); + q.exec(); +} + +QVariant addGenre(QSqlQuery &q, const QString &name) +{ + q.addBindValue(name); + q.exec(); + return q.lastInsertId(); +} + +QVariant addAuthor(QSqlQuery &q, const QString &name, const QDate &birthdate) +{ + q.addBindValue(name); + q.addBindValue(birthdate); + q.exec(); + return q.lastInsertId(); +} + +QSqlError initDb() +{ + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName(":memory:"); + + if (!db.open()) + return db.lastError(); + + QStringList tables = db.tables(); + if (tables.contains("books", Qt::CaseInsensitive) + && tables.contains("authors", Qt::CaseInsensitive)) + return QSqlError(); + + QSqlQuery q; + if (!q.exec(QLatin1String("create table books(id integer primary key, title varchar, author integer, genre integer, year integer, rating integer)"))) + return q.lastError(); + if (!q.exec(QLatin1String("create table authors(id integer primary key, name varchar, birthdate date)"))) + return q.lastError(); + if (!q.exec(QLatin1String("create table genres(id integer primary key, name varchar)"))) + return q.lastError(); + + if (!q.prepare(QLatin1String("insert into authors(name, birthdate) values(?, ?)"))) + return q.lastError(); + QVariant asimovId = addAuthor(q, QLatin1String("Isaac Asimov"), QDate(1920, 2, 1)); + QVariant greeneId = addAuthor(q, QLatin1String("Graham Greene"), QDate(1904, 10, 2)); + QVariant pratchettId = addAuthor(q, QLatin1String("Terry Pratchett"), QDate(1948, 4, 28)); + + if (!q.prepare(QLatin1String("insert into genres(name) values(?)"))) + return q.lastError(); + QVariant sfiction = addGenre(q, QLatin1String("Science Fiction")); + QVariant fiction = addGenre(q, QLatin1String("Fiction")); + QVariant fantasy = addGenre(q, QLatin1String("Fantasy")); + + if (!q.prepare(QLatin1String("insert into books(title, year, author, genre, rating) values(?, ?, ?, ?, ?)"))) + return q.lastError(); + addBook(q, QLatin1String("Foundation"), 1951, asimovId, sfiction, 3); + addBook(q, QLatin1String("Foundation and Empire"), 1952, asimovId, sfiction, 4); + addBook(q, QLatin1String("Second Foundation"), 1953, asimovId, sfiction, 3); + addBook(q, QLatin1String("Foundation's Edge"), 1982, asimovId, sfiction, 3); + addBook(q, QLatin1String("Foundation and Earth"), 1986, asimovId, sfiction, 4); + addBook(q, QLatin1String("Prelude to Foundation"), 1988, asimovId, sfiction, 3); + addBook(q, QLatin1String("Forward the Foundation"), 1993, asimovId, sfiction, 3); + addBook(q, QLatin1String("The Power and the Glory"), 1940, greeneId, fiction, 4); + addBook(q, QLatin1String("The Third Man"), 1950, greeneId, fiction, 5); + addBook(q, QLatin1String("Our Man in Havana"), 1958, greeneId, fiction, 4); + addBook(q, QLatin1String("Guards! Guards!"), 1989, pratchettId, fantasy, 3); + addBook(q, QLatin1String("Night Watch"), 2002, pratchettId, fantasy, 3); + addBook(q, QLatin1String("Going Postal"), 2004, pratchettId, fantasy, 3); + + return QSqlError(); +} + +#endif diff --git a/demos/books/main.cpp b/demos/books/main.cpp new file mode 100644 index 0000000000..3481c9a2a8 --- /dev/null +++ b/demos/books/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "bookwindow.h" + +#include <QtGui> + +int main(int argc, char * argv[]) +{ + Q_INIT_RESOURCE(books); + + QApplication app(argc, argv); + + BookWindow win; + win.show(); + + return app.exec(); +} diff --git a/demos/boxes/3rdparty/fbm.c b/demos/boxes/3rdparty/fbm.c new file mode 100644 index 0000000000..98eb87a33b --- /dev/null +++ b/demos/boxes/3rdparty/fbm.c @@ -0,0 +1,207 @@ +/***************************************************************** + + Implementation of the fractional Brownian motion algorithm. These + functions were originally the work of F. Kenton Musgrave. + For documentation of the different functions please refer to the + book: + "Texturing and modeling: a procedural approach" + by David S. Ebert et. al. + +******************************************************************/ + +#if defined (_MSC_VER) +#include <qglobal.h> +#endif + +#include <time.h> +#include <stdlib.h> +#include "fbm.h" + +#if defined(Q_CC_MSVC) +#pragma warning(disable:4244) +#endif + +/* Definitions used by the noise2() functions */ + +//#define B 0x100 +//#define BM 0xff +#define B 0x20 +#define BM 0x1f + +#define N 0x1000 +#define NP 12 /* 2^N */ +#define NM 0xfff + +static int p[B + B + 2]; +static float g3[B + B + 2][3]; +static float g2[B + B + 2][2]; +static float g1[B + B + 2]; +static int start = 1; + +static void init(void); + +#define s_curve(t) ( t * t * (3. - 2. * t) ) + +#define lerp(t, a, b) ( a + t * (b - a) ) + +#define setup(i,b0,b1,r0,r1)\ + t = vec[i] + N;\ + b0 = ((int)t) & BM;\ + b1 = (b0+1) & BM;\ + r0 = t - (int)t;\ + r1 = r0 - 1.; +#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] ) + +/* Fractional Brownian Motion function */ + +double fBm( Vector point, double H, double lacunarity, double octaves, + int init ) +{ + + double value, frequency, remainder; + int i; + static double exponent_array[10]; + float vec[3]; + + /* precompute and store spectral weights */ + if ( init ) { + start = 1; + srand( time(0) ); + /* seize required memory for exponent_array */ + frequency = 1.0; + for (i=0; i<=octaves; i++) { + /* compute weight for each frequency */ + exponent_array[i] = pow( frequency, -H ); + frequency *= lacunarity; + } + } + + value = 0.0; /* initialize vars to proper values */ + frequency = 1.0; + vec[0]=point.x; + vec[1]=point.y; + vec[2]=point.z; + + + /* inner loop of spectral construction */ + for (i=0; i<octaves; i++) { + /* value += noise3( vec ) * exponent_array[i];*/ + value += noise3( vec ) * exponent_array[i]; + vec[0] *= lacunarity; + vec[1] *= lacunarity; + vec[2] *= lacunarity; + } /* for */ + + remainder = octaves - (int)octaves; + if ( remainder ) /* add in ``octaves'' remainder */ + /* ``i'' and spatial freq. are preset in loop above */ + value += remainder * noise3( vec ) * exponent_array[i]; + + return( value ); + +} /* fBm() */ + + +float noise3(float vec[3]) +{ + int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; + float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v; + register int i, j; + + if (start) { + start = 0; + init(); + } + + setup(0, bx0,bx1, rx0,rx1); + setup(1, by0,by1, ry0,ry1); + setup(2, bz0,bz1, rz0,rz1); + + i = p[ bx0 ]; + j = p[ bx1 ]; + + b00 = p[ i + by0 ]; + b10 = p[ j + by0 ]; + b01 = p[ i + by1 ]; + b11 = p[ j + by1 ]; + + t = s_curve(rx0); + sy = s_curve(ry0); + sz = s_curve(rz0); + + + q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0); + q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0); + a = lerp(t, u, v); + + q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0); + q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0); + b = lerp(t, u, v); + + c = lerp(sy, a, b); + + q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1); + q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1); + a = lerp(t, u, v); + + q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1); + q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1); + b = lerp(t, u, v); + + d = lerp(sy, a, b); + + return lerp(sz, c, d); +} + +static void normalize2(float v[2]) +{ + float s; + + s = sqrt(v[0] * v[0] + v[1] * v[1]); + v[0] = v[0] / s; + v[1] = v[1] / s; +} + +static void normalize3(float v[3]) +{ + float s; + + s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + v[0] = v[0] / s; + v[1] = v[1] / s; + v[2] = v[2] / s; +} + +static void init(void) +{ + int i, j, k; + + for (i = 0 ; i < B ; i++) { + p[i] = i; + + g1[i] = (float)((rand() % (B + B)) - B) / B; + + for (j = 0 ; j < 2 ; j++) + g2[i][j] = (float)((rand() % (B + B)) - B) / B; + normalize2(g2[i]); + + for (j = 0 ; j < 3 ; j++) + g3[i][j] = (float)((rand() % (B + B)) - B) / B; + normalize3(g3[i]); + } + + while (--i) { + k = p[i]; + p[i] = p[j = rand() % B]; + p[j] = k; + } + + for (i = 0 ; i < B + 2 ; i++) { + p[B + i] = p[i]; + g1[B + i] = g1[i]; + for (j = 0 ; j < 2 ; j++) + g2[B + i][j] = g2[i][j]; + for (j = 0 ; j < 3 ; j++) + g3[B + i][j] = g3[i][j]; + } +} diff --git a/demos/boxes/3rdparty/fbm.h b/demos/boxes/3rdparty/fbm.h new file mode 100644 index 0000000000..b8a4a99ae4 --- /dev/null +++ b/demos/boxes/3rdparty/fbm.h @@ -0,0 +1,40 @@ +/***************************************************************** + + Prototypes for the fractional Brownian motion algorithm. These + functions were originally the work of F. Kenton Musgrave. For + documentation of the different functions please refer to the book: + "Texturing and modeling: a procedural approach" + by David S. Ebert et. al. + +******************************************************************/ + +#ifndef _fbm_h +#define _fbm_h + +#include <math.h> + +#ifdef __cplusplus +extern "C" { +#endif + +//#define TRUE 1 +//#define FALSE 0 + +typedef struct { + double x; + double y; + double z; +} Vector; + +float noise3(float vec[]); +double fBm( Vector point, double H, double lacunarity, double octaves, + int init ); +#endif + +#ifdef __cplusplus +} +#endif + + + + diff --git a/demos/boxes/basic.fsh b/demos/boxes/basic.fsh new file mode 100644 index 0000000000..175b718883 --- /dev/null +++ b/demos/boxes/basic.fsh @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform vec4 basicColor; + +void main() +{ + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec3 absN = abs(gl_TexCoord[1].xyz); + vec3 texCoord; + if (absN.x > absN.y && absN.x > absN.z) + texCoord = gl_TexCoord[1].yzx; + else if (absN.y > absN.z) + texCoord = gl_TexCoord[1].zxy; + else + texCoord = gl_TexCoord[1].xyz; + texCoord.y *= -sign(texCoord.z); + texCoord += 0.5; + + vec4 texColor = texture2D(tex, texCoord.xy); + vec4 unlitColor = gl_Color * mix(basicColor, vec4(texColor.xyz, 1.0), texColor.w); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/demos/boxes/basic.vsh b/demos/boxes/basic.vsh new file mode 100644 index 0000000000..989b571413 --- /dev/null +++ b/demos/boxes/basic.vsh @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform mat4 view; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_Vertex; + specular = gl_LightSource[0].specular; + ambient = gl_LightSource[0].ambient; + diffuse = gl_LightSource[0].diffuse; + lightDirection = view * gl_LightSource[0].position; + + normal = gl_NormalMatrix * gl_Normal; + position = (gl_ModelViewMatrix * gl_Vertex).xyz; + + gl_FrontColor = gl_Color; + gl_Position = ftransform(); +} diff --git a/demos/boxes/boxes.pro b/demos/boxes/boxes.pro new file mode 100644 index 0000000000..d599a3a0ac --- /dev/null +++ b/demos/boxes/boxes.pro @@ -0,0 +1,49 @@ +###################################################################### +# Automatically generated by qmake (2.01a) ma 3. nov 17:33:30 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += 3rdparty/fbm.h \ + glbuffers.h \ + glextensions.h \ + gltrianglemesh.h \ + qtbox.h \ + roundedbox.h \ + scene.h \ + trackball.h +SOURCES += 3rdparty/fbm.c \ + glbuffers.cpp \ + glextensions.cpp \ + main.cpp \ + qtbox.cpp \ + roundedbox.cpp \ + scene.cpp \ + trackball.cpp + +RESOURCES += boxes.qrc + +QT += opengl + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/boxes +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.html *.jpg *.png *.fsh *.vsh *.par +sources.files -= 3rdparty/fbm.h 3rdparty/fbm.c +sources.files += 3rdparty +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/boxes +INSTALLS += target sources + +wince*: { + DEPLOYMENT_PLUGIN += qjpeg +} + +win32-msvc* { + QMAKE_CXXFLAGS -= -Zm200 + QMAKE_CFLAGS -= -Zm200 + QMAKE_CXXFLAGS += -Zm500 + QMAKE_CFLAGS += -Zm500 +} diff --git a/demos/boxes/boxes.qrc b/demos/boxes/boxes.qrc new file mode 100644 index 0000000000..d27506dc5a --- /dev/null +++ b/demos/boxes/boxes.qrc @@ -0,0 +1,25 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/boxes"> + <file>cubemap_negx.jpg</file> + <file>cubemap_negy.jpg</file> + <file>cubemap_negz.jpg</file> + <file>cubemap_posx.jpg</file> + <file>cubemap_posy.jpg</file> + <file>cubemap_posz.jpg</file> + <file>square.jpg</file> + <file>basic.vsh</file> + <file>basic.fsh</file> + <file>dotted.fsh</file> + <file>fresnel.fsh</file> + <file>glass.fsh</file> + <file>granite.fsh</file> + <file>marble.fsh</file> + <file>reflection.fsh</file> + <file>refraction.fsh</file> + <file>wood.fsh</file> + <file>parameters.par</file> + <file>qt-logo.png</file> + <file>smiley.png</file> + <file>qt-logo.jpg</file> +</qresource> +</RCC> diff --git a/demos/boxes/cubemap_negx.jpg b/demos/boxes/cubemap_negx.jpg Binary files differnew file mode 100644 index 0000000000..07c282eab9 --- /dev/null +++ b/demos/boxes/cubemap_negx.jpg diff --git a/demos/boxes/cubemap_negy.jpg b/demos/boxes/cubemap_negy.jpg Binary files differnew file mode 100644 index 0000000000..46cd2f9cf3 --- /dev/null +++ b/demos/boxes/cubemap_negy.jpg diff --git a/demos/boxes/cubemap_negz.jpg b/demos/boxes/cubemap_negz.jpg Binary files differnew file mode 100644 index 0000000000..40c01ddff3 --- /dev/null +++ b/demos/boxes/cubemap_negz.jpg diff --git a/demos/boxes/cubemap_posx.jpg b/demos/boxes/cubemap_posx.jpg Binary files differnew file mode 100644 index 0000000000..0b42e8a1b1 --- /dev/null +++ b/demos/boxes/cubemap_posx.jpg diff --git a/demos/boxes/cubemap_posy.jpg b/demos/boxes/cubemap_posy.jpg Binary files differnew file mode 100644 index 0000000000..2aca9b1e98 --- /dev/null +++ b/demos/boxes/cubemap_posy.jpg diff --git a/demos/boxes/cubemap_posz.jpg b/demos/boxes/cubemap_posz.jpg Binary files differnew file mode 100644 index 0000000000..2e49173848 --- /dev/null +++ b/demos/boxes/cubemap_posz.jpg diff --git a/demos/boxes/dotted.fsh b/demos/boxes/dotted.fsh new file mode 100644 index 0000000000..8f4621d581 --- /dev/null +++ b/demos/boxes/dotted.fsh @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; + +void main() +{ + vec3 N = normalize(normal); + + gl_MaterialParameters M = gl_FrontMaterial; + + // assume directional light + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + float r1 = length(fract(7.0 * gl_TexCoord[1].xyz) - 0.5); + float r2 = length(fract(5.0 * gl_TexCoord[1].xyz + 0.2) - 0.5); + float r3 = length(fract(11.0 * gl_TexCoord[1].xyz + 0.7) - 0.5); + vec4 rs = vec4(r1, r2, r3, 0.0); + + vec4 unlitColor = gl_Color * (0.8 - clamp(10.0 * (0.4 - rs), 0.0, 0.2)); + unlitColor.w = 1.0; + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/demos/boxes/fresnel.fsh b/demos/boxes/fresnel.fsh new file mode 100644 index 0000000000..02d6b0cc60 --- /dev/null +++ b/demos/boxes/fresnel.fsh @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; +uniform vec4 basicColor; + +void main() +{ + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec3 absN = abs(gl_TexCoord[1].xyz); + vec3 texCoord; + if (absN.x > absN.y && absN.x > absN.z) + texCoord = gl_TexCoord[1].yzx; + else if (absN.y > absN.z) + texCoord = gl_TexCoord[1].zxy; + else + texCoord = gl_TexCoord[1].xyz; + texCoord.y *= -sign(texCoord.z); + texCoord += 0.5; + + vec4 texColor = texture2D(tex, texCoord.xy); + vec4 unlitColor = gl_Color * mix(basicColor, vec4(texColor.xyz, 1.0), texColor.w); + vec4 litColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); + + vec3 R = 2.0 * dot(-position, N) * N + position; + vec4 reflectedColor = textureCube(env, R * mat3(view[0].xyz, view[1].xyz, view[2].xyz)); + gl_FragColor = mix(litColor, reflectedColor, 0.2 + 0.8 * pow(1.0 + dot(N, normalize(position)), 2.0)); +} diff --git a/demos/boxes/glass.fsh b/demos/boxes/glass.fsh new file mode 100644 index 0000000000..9dad845f43 --- /dev/null +++ b/demos/boxes/glass.fsh @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; + +// Some arbitrary values +// Arrays don't work here on glsl < 120, apparently. +//const float coeffs[6] = float[6](1.0/4.0, 1.0/4.1, 1.0/4.2, 1.0/4.3, 1.0/4.4, 1.0/4.5); +float coeffs(int i) +{ + return 1.0 / (3.0 + 0.1 * float(i)); +} + +void main() +{ + vec3 N = normalize(normal); + vec3 I = -normalize(position); + mat3 V = mat3(view[0].xyz, view[1].xyz, view[2].xyz); + float IdotN = dot(I, N); + float scales[6]; + vec3 C[6]; + for (int i = 0; i < 6; ++i) { + scales[i] = (IdotN - sqrt(1.0 - coeffs(i) + coeffs(i) * (IdotN * IdotN))); + C[i] = textureCube(env, (-I + coeffs(i) * N) * V).xyz; + } + vec4 refractedColor = 0.25 * vec4(C[5].x + 2.0*C[0].x + C[1].x, C[1].y + 2.0*C[2].y + C[3].y, + C[3].z + 2.0*C[4].z + C[5].z, 4.0); + + vec3 R = 2.0 * dot(-position, N) * N + position; + vec4 reflectedColor = textureCube(env, R * V); + + gl_FragColor = mix(refractedColor, reflectedColor, 0.4 + 0.6 * pow(1.0 - IdotN, 2.0)); +} diff --git a/demos/boxes/glbuffers.cpp b/demos/boxes/glbuffers.cpp new file mode 100644 index 0000000000..9e5a5ff3a0 --- /dev/null +++ b/demos/boxes/glbuffers.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "glbuffers.h" +#include <QtGui/qmatrix4x4.h> + + +void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) +{ + const GLdouble ymax = zNear * tan(fovy * M_PI / 360.0); + const GLdouble ymin = -ymax; + const GLdouble xmin = ymin * aspect; + const GLdouble xmax = ymax * aspect; + glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); +} + +//============================================================================// +// GLTexture // +//============================================================================// + +GLTexture::GLTexture() : m_texture(0), m_failed(false) +{ + glGenTextures(1, &m_texture); +} + +GLTexture::~GLTexture() +{ + glDeleteTextures(1, &m_texture); +} + +//============================================================================// +// GLTexture2D // +//============================================================================// + +GLTexture2D::GLTexture2D(int width, int height) +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_2D, 0); +} + + +GLTexture2D::GLTexture2D(const QString& fileName, int width, int height) +{ + // TODO: Add error handling. + QImage image(fileName); + + if (image.isNull()) { + m_failed = true; + return; + } + + image = image.convertToFormat(QImage::Format_ARGB32); + + //qDebug() << "Image size:" << image.width() << "x" << image.height(); + if (width <= 0) + width = image.width(); + if (height <= 0) + height = image.height(); + if (width != image.width() || height != image.height()) + image = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + glBindTexture(GL_TEXTURE_2D, m_texture); + + // Works on x86, so probably works on all little-endian systems. + // Does it work on big-endian systems? + glTexImage2D(GL_TEXTURE_2D, 0, 4, image.width(), image.height(), 0, + GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_2D, 0); +} + +void GLTexture2D::load(int width, int height, QRgb *data) +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_2D, 0); +} + +void GLTexture2D::bind() +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + glEnable(GL_TEXTURE_2D); +} + +void GLTexture2D::unbind() +{ + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); +} + + +//============================================================================// +// GLTexture3D // +//============================================================================// + +GLTexture3D::GLTexture3D(int width, int height, int depth) +{ + GLBUFFERS_ASSERT_OPENGL("GLTexture3D::GLTexture3D", glTexImage3D, return) + + glBindTexture(GL_TEXTURE_3D, m_texture); + glTexImage3D(GL_TEXTURE_3D, 0, 4, width, height, depth, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_3D, 0); +} + +void GLTexture3D::load(int width, int height, int depth, QRgb *data) +{ + GLBUFFERS_ASSERT_OPENGL("GLTexture3D::load", glTexImage3D, return) + + glBindTexture(GL_TEXTURE_3D, m_texture); + glTexImage3D(GL_TEXTURE_3D, 0, 4, width, height, depth, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_3D, 0); +} + +void GLTexture3D::bind() +{ + glBindTexture(GL_TEXTURE_3D, m_texture); + glEnable(GL_TEXTURE_3D); +} + +void GLTexture3D::unbind() +{ + glBindTexture(GL_TEXTURE_3D, 0); + glDisable(GL_TEXTURE_3D); +} + +//============================================================================// +// GLTextureCube // +//============================================================================// + +GLTextureCube::GLTextureCube(int size) +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + + for (int i = 0; i < 6; ++i) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 4, size, size, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +GLTextureCube::GLTextureCube(const QStringList& fileNames, int size) +{ + // TODO: Add error handling. + + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + + int index = 0; + foreach (QString file, fileNames) { + QImage image(file); + if (image.isNull()) { + m_failed = true; + break; + } + + image = image.convertToFormat(QImage::Format_ARGB32); + + //qDebug() << "Image size:" << image.width() << "x" << image.height(); + if (size <= 0) + size = image.width(); + if (size != image.width() || size != image.height()) + image = image.scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + // Works on x86, so probably works on all little-endian systems. + // Does it work on big-endian systems? + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index, 0, 4, image.width(), image.height(), 0, + GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); + + if (++index == 6) + break; + } + + // Clear remaining faces. + while (index < 6) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index, 0, 4, size, size, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + ++index; + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +void GLTextureCube::load(int size, int face, QRgb *data) +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, 4, size, size, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +void GLTextureCube::bind() +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + glEnable(GL_TEXTURE_CUBE_MAP); +} + +void GLTextureCube::unbind() +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + glDisable(GL_TEXTURE_CUBE_MAP); +} + +//============================================================================// +// GLFrameBufferObject // +//============================================================================// + +GLFrameBufferObject::GLFrameBufferObject(int width, int height) + : m_fbo(0) + , m_depthBuffer(0) + , m_width(width) + , m_height(height) + , m_failed(false) +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::GLFrameBufferObject", + glGenFramebuffersEXT && glGenRenderbuffersEXT && glBindRenderbufferEXT && glRenderbufferStorageEXT, return) + + // TODO: share depth buffers of same size + glGenFramebuffersEXT(1, &m_fbo); + //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + glGenRenderbuffersEXT(1, &m_depthBuffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_width, m_height); + //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); + //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + +GLFrameBufferObject::~GLFrameBufferObject() +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::~GLFrameBufferObject", + glDeleteFramebuffersEXT && glDeleteRenderbuffersEXT, return) + + glDeleteFramebuffersEXT(1, &m_fbo); + glDeleteRenderbuffersEXT(1, &m_depthBuffer); +} + +void GLFrameBufferObject::setAsRenderTarget(bool state) +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::setAsRenderTarget", glBindFramebufferEXT, return) + + if (state) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, m_width, m_height); + } else { + glPopAttrib(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } +} + +bool GLFrameBufferObject::isComplete() +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::isComplete", glCheckFramebufferStatusEXT, return false) + + return GL_FRAMEBUFFER_COMPLETE_EXT == glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); +} + +//============================================================================// +// GLRenderTargetCube // +//============================================================================// + +GLRenderTargetCube::GLRenderTargetCube(int size) + : GLTextureCube(size) + , m_fbo(size, size) +{ +} + +void GLRenderTargetCube::begin(int face) +{ + GLBUFFERS_ASSERT_OPENGL("GLRenderTargetCube::begin", + glFramebufferTexture2DEXT && glFramebufferRenderbufferEXT, return) + + m_fbo.setAsRenderTarget(true); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, m_texture, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_fbo.m_depthBuffer); +} + +void GLRenderTargetCube::end() +{ + m_fbo.setAsRenderTarget(false); +} + +void GLRenderTargetCube::getViewMatrix(QMatrix4x4& mat, int face) +{ + if (face < 0 || face >= 6) { + qWarning("GLRenderTargetCube::getViewMatrix: 'face' must be in the range [0, 6). (face == %d)", face); + return; + } + + static int perm[6][3] = { + {2, 1, 0}, + {2, 1, 0}, + {0, 2, 1}, + {0, 2, 1}, + {0, 1, 2}, + {0, 1, 2}, + }; + + static float signs[6][3] = { + {-1.0f, -1.0f, -1.0f}, + {+1.0f, -1.0f, +1.0f}, + {+1.0f, +1.0f, -1.0f}, + {+1.0f, -1.0f, +1.0f}, + {+1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, +1.0f}, + }; + + mat.fill(0.0f); + for (int i = 0; i < 3; ++i) + mat(i, perm[face][i]) = signs[face][i]; + mat(3, 3) = 1.0f; +} + +void GLRenderTargetCube::getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ) +{ + static const QMatrix4x4 reference( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f); + + mat = reference; + mat(2, 2) = (nearZ+farZ)/(nearZ-farZ); + mat(2, 3) = 2.0f*nearZ*farZ/(nearZ-farZ); +} diff --git a/demos/boxes/glbuffers.h b/demos/boxes/glbuffers.h new file mode 100644 index 0000000000..fb6455b28c --- /dev/null +++ b/demos/boxes/glbuffers.h @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef GLBUFFERS_H +#define GLBUFFERS_H + +//#include <GL/glew.h> +#include "glextensions.h" + +#include <QtGui> +#include <QtOpenGL> + +#define BUFFER_OFFSET(i) ((char*)0 + (i)) +#define SIZE_OF_MEMBER(cls, member) sizeof(static_cast<cls *>(0)->member) + +#define GLBUFFERS_ASSERT_OPENGL(prefix, assertion, returnStatement) \ +if (m_failed || !(assertion)) { \ + if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \ + m_failed = true; \ + returnStatement; \ +} + +void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); + +QT_BEGIN_NAMESPACE +class QMatrix4x4; +QT_END_NAMESPACE + +class GLTexture +{ +public: + GLTexture(); + virtual ~GLTexture(); + virtual void bind() = 0; + virtual void unbind() = 0; + virtual bool failed() const {return m_failed;} +protected: + GLuint m_texture; + bool m_failed; +}; + +class GLFrameBufferObject +{ +public: + friend class GLRenderTargetCube; + // friend class GLRenderTarget2D; + + GLFrameBufferObject(int width, int height); + virtual ~GLFrameBufferObject(); + bool isComplete(); + virtual bool failed() const {return m_failed;} +protected: + void setAsRenderTarget(bool state = true); + GLuint m_fbo; + GLuint m_depthBuffer; + int m_width, m_height; + bool m_failed; +}; + +class GLTexture2D : public GLTexture +{ +public: + GLTexture2D(int width, int height); + GLTexture2D(const QString& fileName, int width = 0, int height = 0); + void load(int width, int height, QRgb *data); + virtual void bind(); + virtual void unbind(); +}; + +class GLTexture3D : public GLTexture +{ +public: + GLTexture3D(int width, int height, int depth); + // TODO: Implement function below + //GLTexture3D(const QString& fileName, int width = 0, int height = 0); + void load(int width, int height, int depth, QRgb *data); + virtual void bind(); + virtual void unbind(); +}; + +class GLTextureCube : public GLTexture +{ +public: + GLTextureCube(int size); + GLTextureCube(const QStringList& fileNames, int size = 0); + void load(int size, int face, QRgb *data); + virtual void bind(); + virtual void unbind(); +}; + +// TODO: Define and implement class below +//class GLRenderTarget2D : public GLTexture2D + +class GLRenderTargetCube : public GLTextureCube +{ +public: + GLRenderTargetCube(int size); + // begin rendering to one of the cube's faces. 0 <= face < 6 + void begin(int face); + // end rendering + void end(); + virtual bool failed() {return m_failed || m_fbo.failed();} + + static void getViewMatrix(QMatrix4x4& mat, int face); + static void getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ); +private: + GLFrameBufferObject m_fbo; +}; + +struct VertexDescription +{ + enum + { + Null = 0, // Terminates a VertexDescription array + Position, + TexCoord, + Normal, + Color, + }; + int field; // Position, TexCoord, Normal, Color + int type; // GL_FLOAT, GL_UNSIGNED_BYTE + int count; // number of elements + int offset; // field's offset into vertex struct + int index; // 0 (unused at the moment) +}; + +// Implementation of interleaved buffers. +// 'T' is a struct which must include a null-terminated static array +// 'VertexDescription* description'. +// Example: +/* +struct Vertex +{ + GLfloat position[3]; + GLfloat texCoord[2]; + GLfloat normal[3]; + GLbyte color[4]; + static VertexDescription description[]; +}; + +VertexDescription Vertex::description[] = { + {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(Vertex, position) / sizeof(GLfloat), offsetof(Vertex, position), 0}, + {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(Vertex, texCoord) / sizeof(GLfloat), offsetof(Vertex, texCoord), 0}, + {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(Vertex, normal) / sizeof(GLfloat), offsetof(Vertex, normal), 0}, + {VertexDescription::Color, GL_BYTE, SIZE_OF_MEMBER(Vertex, color) / sizeof(GLbyte), offsetof(Vertex, color), 0}, + {VertexDescription::Null, 0, 0, 0, 0}, +}; +*/ +template<class T> +class GLVertexBuffer +{ +public: + GLVertexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW) + : m_length(0) + , m_mode(mode) + , m_buffer(0) + , m_failed(false) + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::GLVertexBuffer", glGenBuffers && glBindBuffer && glBufferData, return) + + glGenBuffers(1, &m_buffer); + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + glBufferData(GL_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode); + } + + ~GLVertexBuffer() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::~GLVertexBuffer", glDeleteBuffers, return) + + glDeleteBuffers(1, &m_buffer); + } + + void bind() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::bind", glBindBuffer, return) + + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) { + switch (desc->field) { + case VertexDescription::Position: + glVertexPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_VERTEX_ARRAY); + break; + case VertexDescription::TexCoord: + glTexCoordPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + break; + case VertexDescription::Normal: + glNormalPointer(desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_NORMAL_ARRAY); + break; + case VertexDescription::Color: + glColorPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_COLOR_ARRAY); + break; + default: + break; + } + } + } + + void unbind() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unbind", glBindBuffer, return) + + glBindBuffer(GL_ARRAY_BUFFER, 0); + for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) { + switch (desc->field) { + case VertexDescription::Position: + glDisableClientState(GL_VERTEX_ARRAY); + break; + case VertexDescription::TexCoord: + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + case VertexDescription::Normal: + glDisableClientState(GL_NORMAL_ARRAY); + break; + case VertexDescription::Color: + glDisableClientState(GL_COLOR_ARRAY); + break; + default: + break; + } + } + } + + int length() const {return m_length;} + + T *lock() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::lock", glBindBuffer && glMapBuffer, return 0) + + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + //glBufferData(GL_ARRAY_BUFFER, m_length, NULL, m_mode); + GLvoid* buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); + m_failed = (buffer == 0); + return reinterpret_cast<T *>(buffer); + } + + void unlock() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unlock", glBindBuffer && glUnmapBuffer, return) + + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + glUnmapBuffer(GL_ARRAY_BUFFER); + } + + bool failed() + { + return m_failed; + } + +private: + int m_length, m_mode; + GLuint m_buffer; + bool m_failed; +}; + +template<class T> +class GLIndexBuffer +{ +public: + GLIndexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW) + : m_length(0) + , m_mode(mode) + , m_buffer(0) + , m_failed(false) + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::GLIndexBuffer", glGenBuffers && glBindBuffer && glBufferData, return) + + glGenBuffers(1, &m_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode); + } + + ~GLIndexBuffer() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::~GLIndexBuffer", glDeleteBuffers, return) + + glDeleteBuffers(1, &m_buffer); + } + + void bind() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::bind", glBindBuffer, return) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + } + + void unbind() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unbind", glBindBuffer, return) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + int length() const {return m_length;} + + T *lock() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::lock", glBindBuffer && glMapBuffer, return 0) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + GLvoid* buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE); + m_failed = (buffer == 0); + return reinterpret_cast<T *>(buffer); + } + + void unlock() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unlock", glBindBuffer && glUnmapBuffer, return) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } + + bool failed() + { + return m_failed; + } + +private: + int m_length, m_mode; + GLuint m_buffer; + bool m_failed; +}; + +#endif diff --git a/demos/boxes/glextensions.cpp b/demos/boxes/glextensions.cpp new file mode 100644 index 0000000000..102159401c --- /dev/null +++ b/demos/boxes/glextensions.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "glextensions.h" + +#define RESOLVE_GL_FUNC(f) ok &= bool((f = (_gl##f) context->getProcAddress(QLatin1String("gl" #f)))); + +bool GLExtensionFunctions::resolve(const QGLContext *context) +{ + bool ok = true; + + RESOLVE_GL_FUNC(GenFramebuffersEXT) + RESOLVE_GL_FUNC(GenRenderbuffersEXT) + RESOLVE_GL_FUNC(BindRenderbufferEXT) + RESOLVE_GL_FUNC(RenderbufferStorageEXT) + RESOLVE_GL_FUNC(DeleteFramebuffersEXT) + RESOLVE_GL_FUNC(DeleteRenderbuffersEXT) + RESOLVE_GL_FUNC(BindFramebufferEXT) + RESOLVE_GL_FUNC(FramebufferTexture2DEXT) + RESOLVE_GL_FUNC(FramebufferRenderbufferEXT) + RESOLVE_GL_FUNC(CheckFramebufferStatusEXT) + + RESOLVE_GL_FUNC(ActiveTexture) + RESOLVE_GL_FUNC(TexImage3D) + + RESOLVE_GL_FUNC(GenBuffers) + RESOLVE_GL_FUNC(BindBuffer) + RESOLVE_GL_FUNC(BufferData) + RESOLVE_GL_FUNC(DeleteBuffers) + RESOLVE_GL_FUNC(MapBuffer) + RESOLVE_GL_FUNC(UnmapBuffer) + + return ok; +} + +bool GLExtensionFunctions::fboSupported() { + return GenFramebuffersEXT + && GenRenderbuffersEXT + && BindRenderbufferEXT + && RenderbufferStorageEXT + && DeleteFramebuffersEXT + && DeleteRenderbuffersEXT + && BindFramebufferEXT + && FramebufferTexture2DEXT + && FramebufferRenderbufferEXT + && CheckFramebufferStatusEXT; +} + +bool GLExtensionFunctions::openGL15Supported() { + return ActiveTexture + && TexImage3D + && GenBuffers + && BindBuffer + && BufferData + && DeleteBuffers + && MapBuffer + && UnmapBuffer; +} + +#undef RESOLVE_GL_FUNC diff --git a/demos/boxes/glextensions.h b/demos/boxes/glextensions.h new file mode 100644 index 0000000000..342e5d8930 --- /dev/null +++ b/demos/boxes/glextensions.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef GLEXTENSIONS_H +#define GLEXTENSIONS_H + +#include <QtOpenGL> + +/* +Functions resolved: + +glGenFramebuffersEXT +glGenRenderbuffersEXT +glBindRenderbufferEXT +glRenderbufferStorageEXT +glDeleteFramebuffersEXT +glDeleteRenderbuffersEXT +glBindFramebufferEXT +glFramebufferTexture2DEXT +glFramebufferRenderbufferEXT +glCheckFramebufferStatusEXT + +glActiveTexture +glTexImage3D + +glGenBuffers +glBindBuffer +glBufferData +glDeleteBuffers +glMapBuffer +glUnmapBuffer +*/ + +#ifndef Q_WS_MAC +# ifndef APIENTRYP +# ifdef APIENTRY +# define APIENTRYP APIENTRY * +# else +# define APIENTRY +# define APIENTRYP * +# endif +# endif +#else +# define APIENTRY +# define APIENTRYP * +#endif + +#ifndef GL_VERSION_1_2 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_BGRA 0x80E1 +#endif + +#ifndef GL_VERSION_1_3 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#endif + +#ifndef GL_ARB_vertex_buffer_object +typedef ptrdiff_t GLsizeiptrARB; +#endif + +#ifndef GL_VERSION_1_5 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_READ_WRITE 0x88BA +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_EXT_framebuffer_object +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#endif + +typedef void (APIENTRY *_glGenFramebuffersEXT) (GLsizei, GLuint *); +typedef void (APIENTRY *_glGenRenderbuffersEXT) (GLsizei, GLuint *); +typedef void (APIENTRY *_glBindRenderbufferEXT) (GLenum, GLuint); +typedef void (APIENTRY *_glRenderbufferStorageEXT) (GLenum, GLenum, GLsizei, GLsizei); +typedef void (APIENTRY *_glDeleteFramebuffersEXT) (GLsizei, const GLuint*); +typedef void (APIENTRY *_glDeleteRenderbuffersEXT) (GLsizei, const GLuint*); +typedef void (APIENTRY *_glBindFramebufferEXT) (GLenum, GLuint); +typedef void (APIENTRY *_glFramebufferTexture2DEXT) (GLenum, GLenum, GLenum, GLuint, GLint); +typedef void (APIENTRY *_glFramebufferRenderbufferEXT) (GLenum, GLenum, GLenum, GLuint); +typedef GLenum (APIENTRY *_glCheckFramebufferStatusEXT) (GLenum); + +typedef void (APIENTRY *_glActiveTexture) (GLenum); +typedef void (APIENTRY *_glTexImage3D) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); + +typedef void (APIENTRY *_glGenBuffers) (GLsizei, GLuint *); +typedef void (APIENTRY *_glBindBuffer) (GLenum, GLuint); +typedef void (APIENTRY *_glBufferData) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum); +typedef void (APIENTRY *_glDeleteBuffers) (GLsizei, const GLuint *); +typedef void *(APIENTRY *_glMapBuffer) (GLenum, GLenum); +typedef GLboolean (APIENTRY *_glUnmapBuffer) (GLenum); + +struct GLExtensionFunctions +{ + bool resolve(const QGLContext *context); + + bool fboSupported(); + bool openGL15Supported(); // the rest: multi-texture, 3D-texture, vertex buffer objects + + _glGenFramebuffersEXT GenFramebuffersEXT; + _glGenRenderbuffersEXT GenRenderbuffersEXT; + _glBindRenderbufferEXT BindRenderbufferEXT; + _glRenderbufferStorageEXT RenderbufferStorageEXT; + _glDeleteFramebuffersEXT DeleteFramebuffersEXT; + _glDeleteRenderbuffersEXT DeleteRenderbuffersEXT; + _glBindFramebufferEXT BindFramebufferEXT; + _glFramebufferTexture2DEXT FramebufferTexture2DEXT; + _glFramebufferRenderbufferEXT FramebufferRenderbufferEXT; + _glCheckFramebufferStatusEXT CheckFramebufferStatusEXT; + + _glActiveTexture ActiveTexture; + _glTexImage3D TexImage3D; + + _glGenBuffers GenBuffers; + _glBindBuffer BindBuffer; + _glBufferData BufferData; + _glDeleteBuffers DeleteBuffers; + _glMapBuffer MapBuffer; + _glUnmapBuffer UnmapBuffer; +}; + +inline GLExtensionFunctions &getGLExtensionFunctions() +{ + static GLExtensionFunctions funcs; + return funcs; +} + +#define glGenFramebuffersEXT getGLExtensionFunctions().GenFramebuffersEXT +#define glGenRenderbuffersEXT getGLExtensionFunctions().GenRenderbuffersEXT +#define glBindRenderbufferEXT getGLExtensionFunctions().BindRenderbufferEXT +#define glRenderbufferStorageEXT getGLExtensionFunctions().RenderbufferStorageEXT +#define glDeleteFramebuffersEXT getGLExtensionFunctions().DeleteFramebuffersEXT +#define glDeleteRenderbuffersEXT getGLExtensionFunctions().DeleteRenderbuffersEXT +#define glBindFramebufferEXT getGLExtensionFunctions().BindFramebufferEXT +#define glFramebufferTexture2DEXT getGLExtensionFunctions().FramebufferTexture2DEXT +#define glFramebufferRenderbufferEXT getGLExtensionFunctions().FramebufferRenderbufferEXT +#define glCheckFramebufferStatusEXT getGLExtensionFunctions().CheckFramebufferStatusEXT + +#define glActiveTexture getGLExtensionFunctions().ActiveTexture +#define glTexImage3D getGLExtensionFunctions().TexImage3D + +#define glGenBuffers getGLExtensionFunctions().GenBuffers +#define glBindBuffer getGLExtensionFunctions().BindBuffer +#define glBufferData getGLExtensionFunctions().BufferData +#define glDeleteBuffers getGLExtensionFunctions().DeleteBuffers +#define glMapBuffer getGLExtensionFunctions().MapBuffer +#define glUnmapBuffer getGLExtensionFunctions().UnmapBuffer + +#endif diff --git a/demos/boxes/gltrianglemesh.h b/demos/boxes/gltrianglemesh.h new file mode 100644 index 0000000000..d0afa35295 --- /dev/null +++ b/demos/boxes/gltrianglemesh.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef GLTRIANGLEMESH_H +#define GLTRIANGLEMESH_H + +//#include <GL/glew.h> +#include "glextensions.h" + +#include <QtGui> +#include <QtOpenGL> + +#include "glbuffers.h" + +template<class TVertex, class TIndex> +class GLTriangleMesh +{ +public: + GLTriangleMesh(int vertexCount, int indexCount) : m_vb(vertexCount), m_ib(indexCount) + { + } + + virtual ~GLTriangleMesh() + { + } + + virtual void draw() + { + if (failed()) + return; + + int type = GL_UNSIGNED_INT; + if (sizeof(TIndex) == sizeof(char)) type = GL_UNSIGNED_BYTE; + if (sizeof(TIndex) == sizeof(short)) type = GL_UNSIGNED_SHORT; + + m_vb.bind(); + m_ib.bind(); + glDrawElements(GL_TRIANGLES, m_ib.length(), type, BUFFER_OFFSET(0)); + m_vb.unbind(); + m_ib.unbind(); + } + + bool failed() + { + return m_vb.failed() || m_ib.failed(); + } +protected: + GLVertexBuffer<TVertex> m_vb; + GLIndexBuffer<TIndex> m_ib; +}; + + +#endif diff --git a/demos/boxes/granite.fsh b/demos/boxes/granite.fsh new file mode 100644 index 0000000000..025153bc26 --- /dev/null +++ b/demos/boxes/granite.fsh @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform sampler3D noise; + +//const vec4 graniteColors[3] = {vec4(0.0, 0.0, 0.0, 1), vec4(0.30, 0.15, 0.10, 1), vec4(0.80, 0.70, 0.75, 1)}; +uniform vec4 graniteColors[3]; + +float steep(float x) +{ + return clamp(5.0 * x - 2.0, 0.0, 1.0); +} + +void main() +{ + vec2 turbulence = vec2(0, 0); + float scale = 1.0; + for (int i = 0; i < 4; ++i) { + turbulence += scale * (texture3D(noise, gl_TexCoord[1].xyz / scale).xy - 0.5); + scale *= 0.5; + } + + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec4 unlitColor = mix(graniteColors[1], mix(graniteColors[0], graniteColors[2], steep(0.5 + turbulence.y)), 4.0 * abs(turbulence.x)); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/demos/boxes/main.cpp b/demos/boxes/main.cpp new file mode 100644 index 0000000000..568031ed41 --- /dev/null +++ b/demos/boxes/main.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <GL/glew.h> +#include "glextensions.h" + +#include "scene.h" + +#include <QtGui> +#include <QGLWidget> + +class GraphicsView : public QGraphicsView +{ +public: + GraphicsView() + { + setWindowTitle(tr("Boxes")); + setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + //setRenderHints(QPainter::SmoothPixmapTransform); + } + +protected: + void resizeEvent(QResizeEvent *event) { + if (scene()) + scene()->setSceneRect(QRect(QPoint(0, 0), event->size())); + QGraphicsView::resizeEvent(event); + } +}; + +inline bool matchString(const char *extensionString, const char *subString) +{ + int subStringLength = strlen(subString); + return (strncmp(extensionString, subString, subStringLength) == 0) + && ((extensionString[subStringLength] == ' ') || (extensionString[subStringLength] == '\0')); +} + +bool necessaryExtensionsSupported() +{ + const char *extensionString = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)); + const char *p = extensionString; + + const int GL_EXT_FBO = 1; + const int GL_ARB_VS = 2; + const int GL_ARB_FS = 4; + const int GL_ARB_SO = 8; + int extensions = 0; + + while (*p) { + if (matchString(p, "GL_EXT_framebuffer_object")) + extensions |= GL_EXT_FBO; + else if (matchString(p, "GL_ARB_vertex_shader")) + extensions |= GL_ARB_VS; + else if (matchString(p, "GL_ARB_fragment_shader")) + extensions |= GL_ARB_FS; + else if (matchString(p, "GL_ARB_shader_objects")) + extensions |= GL_ARB_SO; + while ((*p != ' ') && (*p != '\0')) + ++p; + if (*p == ' ') + ++p; + } + return (extensions == 15); +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_5) == 0) { + QMessageBox::critical(0, "OpenGL features missing", + "OpenGL version 1.5 or higher is required to run this demo.\n" + "The program will now exit."); + return -1; + } + + int maxTextureSize = 1024; + QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); + widget->makeCurrent(); + + if (!necessaryExtensionsSupported()) { + QMessageBox::critical(0, "OpenGL features missing", + "The OpenGL extensions required to run this demo are missing.\n" + "The program will now exit."); + delete widget; + return -2; + } + + // Check if all the necessary functions are resolved. + if (!getGLExtensionFunctions().resolve(widget->context())) { + QMessageBox::critical(0, "OpenGL features missing", + "Failed to resolve OpenGL functions required to run this demo.\n" + "The program will now exit."); + delete widget; + return -3; + } + + // TODO: Make conditional for final release + QMessageBox::information(0, "For your information", + "This demo can be GPU and CPU intensive and may\n" + "work poorly or not at all on your system."); + + widget->makeCurrent(); // The current context must be set before calling Scene's constructor + Scene scene(1024, 768, maxTextureSize); + GraphicsView view; + view.setViewport(widget); + view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + view.setScene(&scene); + view.show(); + + return app.exec(); +} + diff --git a/demos/boxes/marble.fsh b/demos/boxes/marble.fsh new file mode 100644 index 0000000000..fbd1f5c77f --- /dev/null +++ b/demos/boxes/marble.fsh @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform sampler3D noise; + +//const vec4 marbleColors[2] = {vec4(0.9, 0.9, 0.9, 1), vec4(0.6, 0.5, 0.5, 1)}; +uniform vec4 marbleColors[2]; + +void main() +{ + float turbulence = 0.0; + float scale = 1.0; + for (int i = 0; i < 4; ++i) { + turbulence += scale * (texture3D(noise, 0.125 * gl_TexCoord[1].xyz / scale).x - 0.5); + scale *= 0.5; + } + + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec4 unlitColor = mix(marbleColors[0], marbleColors[1], exp(-4.0 * abs(turbulence))); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/demos/boxes/parameters.par b/demos/boxes/parameters.par new file mode 100644 index 0000000000..50e20739b9 --- /dev/null +++ b/demos/boxes/parameters.par @@ -0,0 +1,5 @@ +color basicColor ff0e3d0e +color woodColors ff5e3d33 ffcc9966 +float woodTubulence 0.1 +color graniteColors ff000000 ff4d261a ffccb3bf +color marbleColors ffe6e6e6 ff998080 diff --git a/demos/boxes/qt-logo.jpg b/demos/boxes/qt-logo.jpg Binary files differnew file mode 100644 index 0000000000..4014b4659c --- /dev/null +++ b/demos/boxes/qt-logo.jpg diff --git a/demos/boxes/qt-logo.png b/demos/boxes/qt-logo.png Binary files differnew file mode 100644 index 0000000000..7d3e97eb36 --- /dev/null +++ b/demos/boxes/qt-logo.png diff --git a/demos/boxes/qtbox.cpp b/demos/boxes/qtbox.cpp new file mode 100644 index 0000000000..9916a3540e --- /dev/null +++ b/demos/boxes/qtbox.cpp @@ -0,0 +1,480 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "qtbox.h" + +const qreal ROTATE_SPEED_X = 30.0 / 1000.0; +const qreal ROTATE_SPEED_Y = 20.0 / 1000.0; +const qreal ROTATE_SPEED_Z = 40.0 / 1000.0; +const int MAX_ITEM_SIZE = 512; +const int MIN_ITEM_SIZE = 16; + +//============================================================================// +// ItemBase // +//============================================================================// + +ItemBase::ItemBase(int size, int x, int y) : m_size(size), m_isResizing(false) +{ + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setFlag(QGraphicsItem::ItemIsFocusable, true); + setAcceptHoverEvents(true); + setPos(x, y); + m_startTime = QTime::currentTime(); +} + +ItemBase::~ItemBase() +{ +} + +QRectF ItemBase::boundingRect() const +{ + return QRectF(-m_size / 2, -m_size / 2, m_size, m_size); +} + +void ItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + if (option->state & QStyle::State_Selected) { + painter->setRenderHint(QPainter::Antialiasing, true); + if (option->state & QStyle::State_HasFocus) + painter->setPen(Qt::yellow); + else + painter->setPen(Qt::white); + painter->drawRect(boundingRect()); + + painter->drawLine(m_size / 2 - 9, m_size / 2, m_size / 2, m_size / 2 - 9); + painter->drawLine(m_size / 2 - 6, m_size / 2, m_size / 2, m_size / 2 - 6); + painter->drawLine(m_size / 2 - 3, m_size / 2, m_size / 2, m_size / 2 - 3); + + painter->setRenderHint(QPainter::Antialiasing, false); + } +} + +void ItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + if (!isSelected() && scene()) { + scene()->clearSelection(); + setSelected(true); + } + + QMenu menu; + QAction *delAction = menu.addAction("Delete"); + QAction *newAction = menu.addAction("New"); + QAction *growAction = menu.addAction("Grow"); + QAction *shrinkAction = menu.addAction("Shrink"); + + QAction *selectedAction = menu.exec(event->screenPos()); + + if (selectedAction == delAction) + deleteSelectedItems(scene()); + else if (selectedAction == newAction) + duplicateSelectedItems(scene()); + else if (selectedAction == growAction) + growSelectedItems(scene()); + else if (selectedAction == shrinkAction) + shrinkSelectedItems(scene()); +} + +void ItemBase::duplicateSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList<QGraphicsItem *> selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item); + if (itemBase) + scene->addItem(itemBase->createNew(itemBase->m_size, itemBase->pos().x() + itemBase->m_size, itemBase->pos().y())); + } +} + +void ItemBase::deleteSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList<QGraphicsItem *> selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item); + if (itemBase) + delete itemBase; + } +} + +void ItemBase::growSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList<QGraphicsItem *> selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item); + if (itemBase) { + itemBase->prepareGeometryChange(); + itemBase->m_size *= 2; + if (itemBase->m_size > MAX_ITEM_SIZE) + itemBase->m_size = MAX_ITEM_SIZE; + } + } +} + +void ItemBase::shrinkSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList<QGraphicsItem *> selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item); + if (itemBase) { + itemBase->prepareGeometryChange(); + itemBase->m_size /= 2; + if (itemBase->m_size < MIN_ITEM_SIZE) + itemBase->m_size = MIN_ITEM_SIZE; + } + } +} + +void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_isResizing) { + int dx = int(2.0 * event->pos().x()); + int dy = int(2.0 * event->pos().y()); + prepareGeometryChange(); + m_size = (dx > dy ? dx : dy); + if (m_size < MIN_ITEM_SIZE) + m_size = MIN_ITEM_SIZE; + else if (m_size > MAX_ITEM_SIZE) + m_size = MAX_ITEM_SIZE; + } else { + QGraphicsItem::mouseMoveEvent(event); + } +} + +void ItemBase::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + if (m_isResizing || (isInResizeArea(event->pos()) && isSelected())) + setCursor(Qt::SizeFDiagCursor); + else + setCursor(Qt::ArrowCursor); + QGraphicsItem::hoverMoveEvent(event); +} + +void ItemBase::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + static qreal z = 0.0; + setZValue(z += 1.0); + if (event->button() == Qt::LeftButton && isInResizeArea(event->pos())) { + m_isResizing = true; + } else { + QGraphicsItem::mousePressEvent(event); + } +} + +void ItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && m_isResizing) { + m_isResizing = false; + } else { + QGraphicsItem::mouseReleaseEvent(event); + } +} + +void ItemBase::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Delete: + deleteSelectedItems(scene()); + break; + case Qt::Key_Insert: + duplicateSelectedItems(scene()); + break; + case Qt::Key_Plus: + growSelectedItems(scene()); + break; + case Qt::Key_Minus: + shrinkSelectedItems(scene()); + break; + default: + QGraphicsItem::keyPressEvent(event); + break; + } +} + +void ItemBase::wheelEvent(QGraphicsSceneWheelEvent *event) +{ + prepareGeometryChange(); + m_size = int(m_size * exp(-event->delta() / 600.0)); + if (m_size > MAX_ITEM_SIZE) + m_size = MAX_ITEM_SIZE; + else if (m_size < MIN_ITEM_SIZE) + m_size = MIN_ITEM_SIZE; +} + +int ItemBase::type() const +{ + return Type; +} + + +bool ItemBase::isInResizeArea(const QPointF &pos) +{ + return (-pos.y() < pos.x() - m_size + 9); +} + +//============================================================================// +// QtBox // +//============================================================================// + +QtBox::QtBox(int size, int x, int y) : ItemBase(size, x, y), m_texture(0) +{ + for (int i = 0; i < 8; ++i) { + m_vertices[i].setX(i & 1 ? 0.5f : -0.5f); + m_vertices[i].setY(i & 2 ? 0.5f : -0.5f); + m_vertices[i].setZ(i & 4 ? 0.5f : -0.5f); + } + for (int i = 0; i < 4; ++i) { + m_texCoords[i].setX(i & 1 ? 1.0f : 0.0f); + m_texCoords[i].setY(i & 2 ? 1.0f : 0.0f); + } + m_normals[0] = QVector3D(-1.0f, 0.0f, 0.0f); + m_normals[1] = QVector3D(1.0f, 0.0f, 0.0f); + m_normals[2] = QVector3D(0.0f, -1.0f, 0.0f); + m_normals[3] = QVector3D(0.0f, 1.0f, 0.0f); + m_normals[4] = QVector3D(0.0f, 0.0f, -1.0f); + m_normals[5] = QVector3D(0.0f, 0.0f, 1.0f); +} + +QtBox::~QtBox() +{ + if (m_texture) + delete m_texture; +} + +ItemBase *QtBox::createNew(int size, int x, int y) +{ + return new QtBox(size, x, y); +} + +void QtBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + QRectF rect = boundingRect().translated(pos()); + float width = float(painter->device()->width()); + float height = float(painter->device()->height()); + + float left = 2.0f * float(rect.left()) / width - 1.0f; + float right = 2.0f * float(rect.right()) / width - 1.0f; + float top = 1.0f - 2.0f * float(rect.top()) / height; + float bottom = 1.0f - 2.0f * float(rect.bottom()) / height; + float moveToRectMatrix[] = { + 0.5f * (right - left), 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f * (bottom - top), 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f * (right + left), 0.5f * (bottom + top), 0.0f, 1.0f + }; + + painter->beginNativePainting(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(moveToRectMatrix); + qgluPerspective(60.0, 1.0, 0.01, 10.0); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + //glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_NORMALIZE); + + if(m_texture == 0) + m_texture = new GLTexture2D(":/res/boxes/qt-logo.jpg", 64, 64); + m_texture->bind(); + glEnable(GL_TEXTURE_2D); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + float lightColour[] = {1.0f, 1.0f, 1.0f, 1.0f}; + float lightDir[] = {0.0f, 0.0f, 1.0f, 0.0f}; + glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColour); + glLightfv(GL_LIGHT0, GL_POSITION, lightDir); + glEnable(GL_LIGHT0); + + glTranslatef(0.0f, 0.0f, -1.5f); + glRotatef(ROTATE_SPEED_X * m_startTime.msecsTo(QTime::currentTime()), 1.0f, 0.0f, 0.0f); + glRotatef(ROTATE_SPEED_Y * m_startTime.msecsTo(QTime::currentTime()), 0.0f, 1.0f, 0.0f); + glRotatef(ROTATE_SPEED_Z * m_startTime.msecsTo(QTime::currentTime()), 0.0f, 0.0f, 1.0f); + int dt = m_startTime.msecsTo(QTime::currentTime()); + if (dt < 500) + glScalef(dt / 500.0f, dt / 500.0f, dt / 500.0f); + + for (int dir = 0; dir < 3; ++dir) { + glColor4f(1.0f, 1.0f, 1.0f, 1.0); + + glBegin(GL_TRIANGLE_STRIP); + glNormal3fv(reinterpret_cast<float *>(&m_normals[2 * dir + 0])); + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + glTexCoord2fv(reinterpret_cast<float *>(&m_texCoords[(j << 1) | i])); + glVertex3fv(reinterpret_cast<float *>(&m_vertices[(i << ((dir + 2) % 3)) | (j << ((dir + 1) % 3))])); + } + } + glEnd(); + + glBegin(GL_TRIANGLE_STRIP); + glNormal3fv(reinterpret_cast<float *>(&m_normals[2 * dir + 1])); + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + glTexCoord2fv(reinterpret_cast<float *>(&m_texCoords[(j << 1) | i])); + glVertex3fv(reinterpret_cast<float *>(&m_vertices[(1 << dir) | (i << ((dir + 1) % 3)) | (j << ((dir + 2) % 3))])); + } + } + glEnd(); + } + m_texture->unbind(); + + //glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHT0); + glDisable(GL_NORMALIZE); + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + painter->endNativePainting(); + + ItemBase::paint(painter, option, widget); +} + +//============================================================================// +// CircleItem // +//============================================================================// + +CircleItem::CircleItem(int size, int x, int y) : ItemBase(size, x, y) +{ + m_color = QColor::fromHsv(rand() % 360, 255, 255); +} + +void CircleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + int dt = m_startTime.msecsTo(QTime::currentTime()); + + qreal r0 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 3800) % 4000))); + qreal r1 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 0) % 4000))); + qreal r2 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 1800) % 4000))); + qreal r3 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 2000) % 4000))); + + if (r0 > r1) + r0 = 0.0; + if (r2 > r3) + r2 = 0.0; + + QPainterPath path; + path.moveTo(r1, 0.0); + path.arcTo(-r1, -r1, 2 * r1, 2 * r1, 0.0, 360.0); + path.lineTo(r0, 0.0); + path.arcTo(-r0, -r0, 2 * r0, 2 * r0, 0.0, -360.0); + path.closeSubpath(); + path.moveTo(r3, 0.0); + path.arcTo(-r3, -r3, 2 * r3, 2 * r3, 0.0, 360.0); + path.lineTo(r0, 0.0); + path.arcTo(-r2, -r2, 2 * r2, 2 * r2, 0.0, -360.0); + path.closeSubpath(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->setBrush(QBrush(m_color)); + painter->setPen(Qt::NoPen); + painter->drawPath(path); + painter->setBrush(Qt::NoBrush); + painter->setPen(Qt::SolidLine); + painter->setRenderHint(QPainter::Antialiasing, false); + + ItemBase::paint(painter, option, widget); +} + +ItemBase *CircleItem::createNew(int size, int x, int y) +{ + return new CircleItem(size, x, y); +} + +//============================================================================// +// SquareItem // +//============================================================================// + +SquareItem::SquareItem(int size, int x, int y) : ItemBase(size, x, y) +{ + m_image = QPixmap(":/res/boxes/square.jpg"); +} + +void SquareItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + int dt = m_startTime.msecsTo(QTime::currentTime()); + QTransform oldTransform = painter->worldTransform(); + int dtMod = dt % 2000; + qreal amp = 0.002 * (dtMod < 1000 ? dtMod : 2000 - dtMod) - 1.0; + + qreal scale = 0.6 + 0.2 * amp * amp; + painter->setWorldTransform(QTransform().rotate(15.0 * amp).scale(scale, scale), true); + + painter->drawPixmap(-m_size / 2, -m_size / 2, m_size, m_size, m_image); + + painter->setWorldTransform(oldTransform, false); + ItemBase::paint(painter, option, widget); +} + +ItemBase *SquareItem::createNew(int size, int x, int y) +{ + return new SquareItem(size, x, y); +} diff --git a/demos/boxes/qtbox.h b/demos/boxes/qtbox.h new file mode 100644 index 0000000000..71c1304a60 --- /dev/null +++ b/demos/boxes/qtbox.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef QTBOX_H +#define QTBOX_H + +#include <QtGui> + +#include <QtGui/qvector3d.h> +#include "glbuffers.h" + +class ItemBase : public QGraphicsItem +{ +public: + enum { Type = UserType + 1 }; + + ItemBase(int size, int x, int y); + virtual ~ItemBase(); + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y) = 0; + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void wheelEvent(QGraphicsSceneWheelEvent *event); + virtual int type() const; + bool isInResizeArea(const QPointF &pos); + + static void duplicateSelectedItems(QGraphicsScene *scene); + static void deleteSelectedItems(QGraphicsScene *scene); + static void growSelectedItems(QGraphicsScene *scene); + static void shrinkSelectedItems(QGraphicsScene *scene); + + int m_size; + QTime m_startTime; + bool m_isResizing; +}; + +class QtBox : public ItemBase +{ +public: + QtBox(int size, int x, int y); + virtual ~QtBox(); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y); +private: + QVector3D m_vertices[8]; + QVector3D m_texCoords[4]; + QVector3D m_normals[6]; + GLTexture *m_texture; +}; + +class CircleItem : public ItemBase +{ +public: + CircleItem(int size, int x, int y); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y); + + QColor m_color; +}; + +class SquareItem : public ItemBase +{ +public: + SquareItem(int size, int x, int y); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y); + + QPixmap m_image; +}; + +#endif diff --git a/demos/boxes/reflection.fsh b/demos/boxes/reflection.fsh new file mode 100644 index 0000000000..50b0a4ae06 --- /dev/null +++ b/demos/boxes/reflection.fsh @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; + +void main() +{ + vec3 N = normalize(normal); + vec3 R = 2.0 * dot(-position, N) * N + position; + gl_FragColor = textureCube(env, R * mat3(view[0].xyz, view[1].xyz, view[2].xyz)); +} diff --git a/demos/boxes/refraction.fsh b/demos/boxes/refraction.fsh new file mode 100644 index 0000000000..c846d6ae96 --- /dev/null +++ b/demos/boxes/refraction.fsh @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; + +// Arrays don't work here on glsl < 120, apparently. +//const float coeffs[6] = float[6](1.0/2.0, 1.0/2.1, 1.0/2.2, 1.0/2.3, 1.0/2.4, 1.0/2.5); +float coeffs(int i) +{ + return 1.0 / (2.0 + 0.1 * float(i)); +} + +void main() +{ + vec3 N = normalize(normal); + vec3 I = -normalize(position); + float IdotN = dot(I, N); + float scales[6]; + vec3 C[6]; + for (int i = 0; i < 6; ++i) { + scales[i] = (IdotN - sqrt(1.0 - coeffs(i) + coeffs(i) * (IdotN * IdotN))); + C[i] = textureCube(env, (-I + coeffs(i) * N) * mat3(view[0].xyz, view[1].xyz, view[2].xyz)).xyz; + } + + gl_FragColor = 0.25 * vec4(C[5].x + 2.0*C[0].x + C[1].x, C[1].y + 2.0*C[2].y + C[3].y, + C[3].z + 2.0*C[4].z + C[5].z, 4.0); +} diff --git a/demos/boxes/roundedbox.cpp b/demos/boxes/roundedbox.cpp new file mode 100644 index 0000000000..913cc54235 --- /dev/null +++ b/demos/boxes/roundedbox.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "roundedbox.h" + +//============================================================================// +// P3T2N3Vertex // +//============================================================================// + +VertexDescription P3T2N3Vertex::description[] = { + {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(P3T2N3Vertex, position) / sizeof(float), 0, 0}, + {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(P3T2N3Vertex, texCoord) / sizeof(float), sizeof(QVector3D), 0}, + {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(P3T2N3Vertex, normal) / sizeof(float), sizeof(QVector3D) + sizeof(QVector2D), 0}, + + {VertexDescription::Null, 0, 0, 0, 0}, +}; + +//============================================================================// +// GLRoundedBox // +//============================================================================// + +float lerp(float a, float b, float t) +{ + return a * (1.0f - t) + b * t; +} + +GLRoundedBox::GLRoundedBox(float r, float scale, int n) + : GLTriangleMesh<P3T2N3Vertex, unsigned short>((n+2)*(n+3)*4, (n+1)*(n+1)*24+36+72*(n+1)) +{ + int vidx = 0, iidx = 0; + int vertexCountPerCorner = (n + 2) * (n + 3) / 2; + + P3T2N3Vertex *vp = m_vb.lock(); + unsigned short *ip = m_ib.lock(); + + if (!vp || !ip) { + qWarning("GLRoundedBox::GLRoundedBox: Failed to lock vertex buffer and/or index buffer."); + m_ib.unlock(); + m_vb.unlock(); + return; + } + + for (int corner = 0; corner < 8; ++corner) { + QVector3D centre(corner & 1 ? 1.0f : -1.0f, + corner & 2 ? 1.0f : -1.0f, + corner & 4 ? 1.0f : -1.0f); + int winding = (corner & 1) ^ ((corner >> 1) & 1) ^ (corner >> 2); + int offsX = ((corner ^ 1) - corner) * vertexCountPerCorner; + int offsY = ((corner ^ 2) - corner) * vertexCountPerCorner; + int offsZ = ((corner ^ 4) - corner) * vertexCountPerCorner; + + // Face polygons + if (winding) { + ip[iidx++] = vidx; + ip[iidx++] = vidx + offsX; + ip[iidx++] = vidx + offsY; + + ip[iidx++] = vidx + vertexCountPerCorner - n - 2; + ip[iidx++] = vidx + vertexCountPerCorner - n - 2 + offsY; + ip[iidx++] = vidx + vertexCountPerCorner - n - 2 + offsZ; + + ip[iidx++] = vidx + vertexCountPerCorner - 1; + ip[iidx++] = vidx + vertexCountPerCorner - 1 + offsZ; + ip[iidx++] = vidx + vertexCountPerCorner - 1 + offsX; + } + + for (int i = 0; i < n + 2; ++i) { + + // Edge polygons + if (winding && i < n + 1) { + ip[iidx++] = vidx + i + 1; + ip[iidx++] = vidx; + ip[iidx++] = vidx + offsY + i + 1; + ip[iidx++] = vidx + offsY; + ip[iidx++] = vidx + offsY + i + 1; + ip[iidx++] = vidx; + + ip[iidx++] = vidx + i; + ip[iidx++] = vidx + 2 * i + 2; + ip[iidx++] = vidx + i + offsX; + ip[iidx++] = vidx + 2 * i + offsX + 2; + ip[iidx++] = vidx + i + offsX; + ip[iidx++] = vidx + 2 * i + 2; + + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 1 - i; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 2 - i; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 1 - i + offsZ; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 2 - i + offsZ; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 1 - i + offsZ; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 2 - i; + } + + for (int j = 0; j <= i; ++j) { + QVector3D normal = QVector3D(i - j, j, n + 1 - i).normalized(); + QVector3D offset(0.5f - r, 0.5f - r, 0.5f - r); + QVector3D pos = centre * (offset + r * normal); + + vp[vidx].position = scale * pos; + vp[vidx].normal = centre * normal; + vp[vidx].texCoord = QVector2D(pos.x() + 0.5f, pos.y() + 0.5f); + + // Corner polygons + if (i < n + 1) { + ip[iidx++] = vidx; + ip[iidx++] = vidx + i + 2 - winding; + ip[iidx++] = vidx + i + 1 + winding; + } + if (i < n) { + ip[iidx++] = vidx + i + 1 + winding; + ip[iidx++] = vidx + i + 2 - winding; + ip[iidx++] = vidx + 2 * i + 4; + } + + ++vidx; + } + } + + } + + m_ib.unlock(); + m_vb.unlock(); +} + diff --git a/demos/boxes/roundedbox.h b/demos/boxes/roundedbox.h new file mode 100644 index 0000000000..a19f1a3acc --- /dev/null +++ b/demos/boxes/roundedbox.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef ROUNDEDBOX_H +#define ROUNDEDBOX_H + +//#include <GL/glew.h> +#include "glextensions.h" + +#include <QtGui> +#include <QtOpenGL> + +#include "gltrianglemesh.h" +#include <QtGui/qvector3d.h> +#include <QtGui/qvector2d.h> +#include "glbuffers.h" + +struct P3T2N3Vertex +{ + QVector3D position; + QVector2D texCoord; + QVector3D normal; + static VertexDescription description[]; +}; + +class GLRoundedBox : public GLTriangleMesh<P3T2N3Vertex, unsigned short> +{ +public: + // 0 < r < 0.5, 0 <= n <= 125 + GLRoundedBox(float r = 0.25f, float scale = 1.0f, int n = 10); +}; + + +#endif diff --git a/demos/boxes/scene.cpp b/demos/boxes/scene.cpp new file mode 100644 index 0000000000..85c9a5be70 --- /dev/null +++ b/demos/boxes/scene.cpp @@ -0,0 +1,1085 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QDebug> +#include "scene.h" +#include <QtGui/qmatrix4x4.h> +#include <QtGui/qvector3d.h> + +#include "3rdparty/fbm.h" + +void checkGLErrors(const QString& prefix) +{ + switch (glGetError()) { + case GL_NO_ERROR: + //qDebug() << prefix << tr("No error."); + break; + case GL_INVALID_ENUM: + qDebug() << prefix << QObject::tr("Invalid enum."); + break; + case GL_INVALID_VALUE: + qDebug() << prefix << QObject::tr("Invalid value."); + break; + case GL_INVALID_OPERATION: + qDebug() << prefix << QObject::tr("Invalid operation."); + break; + case GL_STACK_OVERFLOW: + qDebug() << prefix << QObject::tr("Stack overflow."); + break; + case GL_STACK_UNDERFLOW: + qDebug() << prefix << QObject::tr("Stack underflow."); + break; + case GL_OUT_OF_MEMORY: + qDebug() << prefix << QObject::tr("Out of memory."); + break; + default: + qDebug() << prefix << QObject::tr("Unknown error."); + break; + } +} + +//============================================================================// +// ColorEdit // +//============================================================================// + +ColorEdit::ColorEdit(QRgb initialColor, int id) + : m_color(initialColor), m_id(id) +{ + QHBoxLayout *layout = new QHBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + + m_lineEdit = new QLineEdit(QString::number(m_color, 16)); + layout->addWidget(m_lineEdit); + + m_button = new QFrame; + QPalette palette = m_button->palette(); + palette.setColor(QPalette::Window, QColor(m_color)); + m_button->setPalette(palette); + m_button->setAutoFillBackground(true); + m_button->setMinimumSize(32, 0); + m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + m_button->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + layout->addWidget(m_button); + + connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone())); +} + +void ColorEdit::editDone() +{ + bool ok; + QRgb newColor = m_lineEdit->text().toUInt(&ok, 16); + if (ok) + setColor(newColor); +} + +void ColorEdit::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + QColor color(m_color); + QColorDialog dialog(color, 0); + dialog.setOption(QColorDialog::ShowAlphaChannel, true); +// The ifdef block is a workaround for the beta, TODO: remove when bug 238525 is fixed +#ifdef Q_WS_MAC + dialog.setOption(QColorDialog::DontUseNativeDialog, true); +#endif + dialog.move(280, 120); + if (dialog.exec() == QDialog::Rejected) + return; + QRgb newColor = dialog.selectedColor().rgba(); + if (newColor == m_color) + return; + setColor(newColor); + } +} + +void ColorEdit::setColor(QRgb color) +{ + m_color = color; + m_lineEdit->setText(QString::number(m_color, 16)); // "Clean up" text + QPalette palette = m_button->palette(); + palette.setColor(QPalette::Window, QColor(m_color)); + m_button->setPalette(palette); + emit colorChanged(m_color, m_id); +} + +//============================================================================// +// FloatEdit // +//============================================================================// + +FloatEdit::FloatEdit(float initialValue, int id) + : m_value(initialValue), m_id(id) +{ + QHBoxLayout *layout = new QHBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + + m_lineEdit = new QLineEdit(QString::number(m_value)); + layout->addWidget(m_lineEdit); + + connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone())); +} + +void FloatEdit::editDone() +{ + bool ok; + float newValue = m_lineEdit->text().toFloat(&ok); + if (ok) { + m_value = newValue; + m_lineEdit->setText(QString::number(m_value)); // "Clean up" text + emit valueChanged(m_value, m_id); + } +} + +//============================================================================// +// TwoSidedGraphicsWidget // +//============================================================================// + +TwoSidedGraphicsWidget::TwoSidedGraphicsWidget(QGraphicsScene *scene) + : QObject(scene) + , m_current(0) + , m_angle(0) + , m_delta(0) +{ + for (int i = 0; i < 2; ++i) + m_proxyWidgets[i] = 0; +} + +void TwoSidedGraphicsWidget::setWidget(int index, QWidget *widget) +{ + if (index < 0 || index >= 2) + { + qWarning("TwoSidedGraphicsWidget::setWidget: Index out of bounds, index == %d", index); + return; + } + + GraphicsWidget *proxy = new GraphicsWidget; + proxy->setWidget(widget); + + if (m_proxyWidgets[index]) + delete m_proxyWidgets[index]; + m_proxyWidgets[index] = proxy; + + proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache); + proxy->setZValue(1e30); // Make sure the dialog is drawn on top of all other (OpenGL) items + + if (index != m_current) + proxy->setVisible(false); + + qobject_cast<QGraphicsScene *>(parent())->addItem(proxy); +} + +QWidget *TwoSidedGraphicsWidget::widget(int index) +{ + if (index < 0 || index >= 2) + { + qWarning("TwoSidedGraphicsWidget::widget: Index out of bounds, index == %d", index); + return 0; + } + return m_proxyWidgets[index]->widget(); +} + +void TwoSidedGraphicsWidget::flip() +{ + m_delta = (m_current == 0 ? 9 : -9); + animateFlip(); +} + +void TwoSidedGraphicsWidget::animateFlip() +{ + m_angle += m_delta; + if (m_angle == 90) { + int old = m_current; + m_current ^= 1; + m_proxyWidgets[old]->setVisible(false); + m_proxyWidgets[m_current]->setVisible(true); + m_proxyWidgets[m_current]->setGeometry(m_proxyWidgets[old]->geometry()); + } + + QRectF r = m_proxyWidgets[m_current]->boundingRect(); + m_proxyWidgets[m_current]->setTransform(QTransform() + .translate(r.width() / 2, r.height() / 2) + .rotate(m_angle - 180 * m_current, Qt::YAxis) + .translate(-r.width() / 2, -r.height() / 2)); + + if ((m_current == 0 && m_angle > 0) || (m_current == 1 && m_angle < 180)) + QTimer::singleShot(25, this, SLOT(animateFlip())); +} + +QVariant GraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionChange && scene()) { + QRectF rect = boundingRect(); + QPointF pos = value.toPointF(); + QRectF sceneRect = scene()->sceneRect(); + if (pos.x() + rect.left() < sceneRect.left()) + pos.setX(sceneRect.left() - rect.left()); + else if (pos.x() + rect.right() >= sceneRect.right()) + pos.setX(sceneRect.right() - rect.right()); + if (pos.y() + rect.top() < sceneRect.top()) + pos.setY(sceneRect.top() - rect.top()); + else if (pos.y() + rect.bottom() >= sceneRect.bottom()) + pos.setY(sceneRect.bottom() - rect.bottom()); + return pos; + } + return QGraphicsProxyWidget::itemChange(change, value); +} + +void GraphicsWidget::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + setCacheMode(QGraphicsItem::NoCache); + setCacheMode(QGraphicsItem::ItemCoordinateCache); + QGraphicsProxyWidget::resizeEvent(event); +} + +void GraphicsWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + painter->setRenderHint(QPainter::Antialiasing, false); + QGraphicsProxyWidget::paint(painter, option, widget); + //painter->setRenderHint(QPainter::Antialiasing, true); +} + +//============================================================================// +// RenderOptionsDialog // +//============================================================================// + +RenderOptionsDialog::RenderOptionsDialog() + : QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint) +{ + setWindowOpacity(0.75); + setWindowTitle(tr("Options (double click to flip)")); + QGridLayout *layout = new QGridLayout; + setLayout(layout); + layout->setColumnStretch(1, 1); + + int row = 0; + + QCheckBox *check = new QCheckBox(tr("Dynamic cube map")); + check->setCheckState(Qt::Unchecked); + // Dynamic cube maps are only enabled when multi-texturing and render to texture are available. + check->setEnabled(glActiveTexture && glGenFramebuffersEXT); + connect(check, SIGNAL(stateChanged(int)), this, SIGNAL(dynamicCubemapToggled(int))); + layout->addWidget(check, 0, 0, 1, 2); + ++row; + + QPalette palette; + + // Load all .par files + // .par files have a simple syntax for specifying user adjustable uniform variables. + QSet<QByteArray> uniforms; + QList<QString> filter = QStringList("*.par"); + QList<QFileInfo> files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); + + foreach (QFileInfo fileInfo, files) { + QFile file(fileInfo.absoluteFilePath()); + if (file.open(QIODevice::ReadOnly)) { + while (!file.atEnd()) { + QList<QByteArray> tokens = file.readLine().simplified().split(' '); + QList<QByteArray>::const_iterator it = tokens.begin(); + if (it == tokens.end()) + continue; + QByteArray type = *it; + if (++it == tokens.end()) + continue; + QByteArray name = *it; + bool singleElement = (tokens.size() == 3); // type, name and one value + char counter[10] = "000000000"; + int counterPos = 8; // position of last digit + while (++it != tokens.end()) { + m_parameterNames << name; + if (!singleElement) { + m_parameterNames.back() += "["; + m_parameterNames.back() += counter + counterPos; + m_parameterNames.back() += "]"; + int j = 8; // position of last digit + ++counter[j]; + while (j > 0 && counter[j] > '9') { + counter[j] = '0'; + ++counter[--j]; + } + if (j < counterPos) + counterPos = j; + } + + if (type == "color") { + layout->addWidget(new QLabel(m_parameterNames.back())); + bool ok; + ColorEdit *colorEdit = new ColorEdit(it->toUInt(&ok, 16), m_parameterNames.size() - 1); + m_parameterEdits << colorEdit; + layout->addWidget(colorEdit); + connect(colorEdit, SIGNAL(colorChanged(QRgb,int)), this, SLOT(setColorParameter(QRgb,int))); + ++row; + } else if (type == "float") { + layout->addWidget(new QLabel(m_parameterNames.back())); + bool ok; + FloatEdit *floatEdit = new FloatEdit(it->toFloat(&ok), m_parameterNames.size() - 1); + m_parameterEdits << floatEdit; + layout->addWidget(floatEdit); + connect(floatEdit, SIGNAL(valueChanged(float,int)), this, SLOT(setFloatParameter(float,int))); + ++row; + } + } + } + file.close(); + } + } + + layout->addWidget(new QLabel(tr("Texture:"))); + m_textureCombo = new QComboBox; + connect(m_textureCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(textureChanged(int))); + layout->addWidget(m_textureCombo); + ++row; + + layout->addWidget(new QLabel(tr("Shader:"))); + m_shaderCombo = new QComboBox; + connect(m_shaderCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(shaderChanged(int))); + layout->addWidget(m_shaderCombo); + ++row; + + layout->setRowStretch(row, 1); +} + +int RenderOptionsDialog::addTexture(const QString &name) +{ + m_textureCombo->addItem(name); + return m_textureCombo->count() - 1; +} + +int RenderOptionsDialog::addShader(const QString &name) +{ + m_shaderCombo->addItem(name); + return m_shaderCombo->count() - 1; +} + +void RenderOptionsDialog::emitParameterChanged() +{ + foreach (ParameterEdit *edit, m_parameterEdits) + edit->emitChange(); +} + +void RenderOptionsDialog::setColorParameter(QRgb color, int id) +{ + emit colorParameterChanged(m_parameterNames[id], color); +} + +void RenderOptionsDialog::setFloatParameter(float value, int id) +{ + emit floatParameterChanged(m_parameterNames[id], value); +} + +void RenderOptionsDialog::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + emit doubleClicked(); +} + +//============================================================================// +// ItemDialog // +//============================================================================// + +ItemDialog::ItemDialog() + : QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint) +{ + setWindowTitle(tr("Items (double click to flip)")); + setWindowOpacity(0.75); + resize(160, 100); + + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + QPushButton *button; + + button = new QPushButton(tr("Add Qt box")); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(triggerNewQtBox())); + + button = new QPushButton(tr("Add circle")); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(triggerNewCircleItem())); + + button = new QPushButton(tr("Add square")); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(triggerNewSquareItem())); + + layout->addStretch(1); +} + +void ItemDialog::triggerNewQtBox() +{ + emit newItemTriggered(QtBoxItem); +} + +void ItemDialog::triggerNewCircleItem() +{ + emit newItemTriggered(CircleItem); +} + +void ItemDialog::triggerNewSquareItem() +{ + emit newItemTriggered(SquareItem); +} + +void ItemDialog::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + emit doubleClicked(); +} + +//============================================================================// +// Scene // +//============================================================================// + +const static char environmentShaderText[] = + "uniform samplerCube env;" + "void main() {" + "gl_FragColor = textureCube(env, gl_TexCoord[1].xyz);" + "}"; + +Scene::Scene(int width, int height, int maxTextureSize) + : m_distExp(600) + , m_frame(0) + , m_maxTextureSize(maxTextureSize) + , m_currentShader(0) + , m_currentTexture(0) + , m_dynamicCubemap(false) + , m_updateAllCubemaps(true) + , m_box(0) + , m_vertexShader(0) + , m_environmentShader(0) + , m_environmentProgram(0) +{ + setSceneRect(0, 0, width, height); + + m_trackBalls[0] = TrackBall(0.05f, QVector3D(0, 1, 0), TrackBall::Sphere); + m_trackBalls[1] = TrackBall(0.005f, QVector3D(0, 0, 1), TrackBall::Sphere); + m_trackBalls[2] = TrackBall(0.0f, QVector3D(0, 1, 0), TrackBall::Plane); + + m_renderOptions = new RenderOptionsDialog; + m_renderOptions->move(20, 120); + m_renderOptions->resize(m_renderOptions->sizeHint()); + + connect(m_renderOptions, SIGNAL(dynamicCubemapToggled(int)), this, SLOT(toggleDynamicCubemap(int))); + connect(m_renderOptions, SIGNAL(colorParameterChanged(QString,QRgb)), this, SLOT(setColorParameter(QString,QRgb))); + connect(m_renderOptions, SIGNAL(floatParameterChanged(QString,float)), this, SLOT(setFloatParameter(QString,float))); + connect(m_renderOptions, SIGNAL(textureChanged(int)), this, SLOT(setTexture(int))); + connect(m_renderOptions, SIGNAL(shaderChanged(int)), this, SLOT(setShader(int))); + + m_itemDialog = new ItemDialog; + connect(m_itemDialog, SIGNAL(newItemTriggered(ItemDialog::ItemType)), this, SLOT(newItem(ItemDialog::ItemType))); + + TwoSidedGraphicsWidget *twoSided = new TwoSidedGraphicsWidget(this); + twoSided->setWidget(0, m_renderOptions); + twoSided->setWidget(1, m_itemDialog); + + connect(m_renderOptions, SIGNAL(doubleClicked()), twoSided, SLOT(flip())); + connect(m_itemDialog, SIGNAL(doubleClicked()), twoSided, SLOT(flip())); + + addItem(new QtBox(64, width - 64, height - 64)); + addItem(new QtBox(64, width - 64, 64)); + addItem(new QtBox(64, 64, height - 64)); + addItem(new QtBox(64, 64, 64)); + + initGL(); + + m_timer = new QTimer(this); + m_timer->setInterval(20); + connect(m_timer, SIGNAL(timeout()), this, SLOT(update())); + m_timer->start(); + + m_time.start(); +} + +Scene::~Scene() +{ + if (m_box) + delete m_box; + foreach (GLTexture *texture, m_textures) + if (texture) delete texture; + if (m_mainCubemap) + delete m_mainCubemap; + foreach (QGLShaderProgram *program, m_programs) + if (program) delete program; + if (m_vertexShader) + delete m_vertexShader; + foreach (QGLShader *shader, m_fragmentShaders) + if (shader) delete shader; + foreach (GLRenderTargetCube *rt, m_cubemaps) + if (rt) delete rt; + if (m_environmentShader) + delete m_environmentShader; + if (m_environmentProgram) + delete m_environmentProgram; +} + +void Scene::initGL() +{ + m_box = new GLRoundedBox(0.25f, 1.0f, 10); + + m_vertexShader = new QGLShader(QGLShader::Vertex); + m_vertexShader->compileSourceFile(QLatin1String(":/res/boxes/basic.vsh")); + + QStringList list; + list << ":/res/boxes/cubemap_posx.jpg" << ":/res/boxes/cubemap_negx.jpg" << ":/res/boxes/cubemap_posy.jpg" + << ":/res/boxes/cubemap_negy.jpg" << ":/res/boxes/cubemap_posz.jpg" << ":/res/boxes/cubemap_negz.jpg"; + m_environment = new GLTextureCube(list, qMin(1024, m_maxTextureSize)); + m_environmentShader = new QGLShader(QGLShader::Fragment); + m_environmentShader->compileSourceCode(environmentShaderText); + m_environmentProgram = new QGLShaderProgram; + m_environmentProgram->addShader(m_vertexShader); + m_environmentProgram->addShader(m_environmentShader); + m_environmentProgram->link(); + + const int NOISE_SIZE = 128; // for a different size, B and BM in fbm.c must also be changed + m_noise = new GLTexture3D(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE); + QRgb *data = new QRgb[NOISE_SIZE * NOISE_SIZE * NOISE_SIZE]; + memset(data, 0, NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * sizeof(QRgb)); + QRgb *p = data; + float pos[3]; + for (int k = 0; k < NOISE_SIZE; ++k) { + pos[2] = k * (0x20 / (float)NOISE_SIZE); + for (int j = 0; j < NOISE_SIZE; ++j) { + for (int i = 0; i < NOISE_SIZE; ++i) { + for (int byte = 0; byte < 4; ++byte) { + pos[0] = (i + (byte & 1) * 16) * (0x20 / (float)NOISE_SIZE); + pos[1] = (j + (byte & 2) * 8) * (0x20 / (float)NOISE_SIZE); + *p |= (int)(128.0f * (noise3(pos) + 1.0f)) << (byte * 8); + } + ++p; + } + } + } + m_noise->load(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, data); + delete[] data; + + m_mainCubemap = new GLRenderTargetCube(512); + + QStringList filter; + QList<QFileInfo> files; + + // Load all .png files as textures + m_currentTexture = 0; + filter = QStringList("*.png"); + files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); + + foreach (QFileInfo file, files) { + GLTexture *texture = new GLTexture2D(file.absoluteFilePath(), qMin(256, m_maxTextureSize), qMin(256, m_maxTextureSize)); + if (texture->failed()) { + delete texture; + continue; + } + m_textures << texture; + m_renderOptions->addTexture(file.baseName()); + } + + if (m_textures.size() == 0) + m_textures << new GLTexture2D(qMin(64, m_maxTextureSize), qMin(64, m_maxTextureSize)); + + // Load all .fsh files as fragment shaders + m_currentShader = 0; + filter = QStringList("*.fsh"); + files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); + foreach (QFileInfo file, files) { + QGLShaderProgram *program = new QGLShaderProgram; + QGLShader* shader = new QGLShader(QGLShader::Fragment); + shader->compileSourceFile(file.absoluteFilePath()); + // The program does not take ownership over the shaders, so store them in a vector so they can be deleted afterwards. + program->addShader(m_vertexShader); + program->addShader(shader); + if (!program->link()) { + qWarning("Failed to compile and link shader program"); + qWarning("Vertex shader log:"); + qWarning() << m_vertexShader->log(); + qWarning() << "Fragment shader log ( file =" << file.absoluteFilePath() << "):"; + qWarning() << shader->log(); + qWarning("Shader program log:"); + qWarning() << program->log(); + + delete shader; + delete program; + continue; + } + + m_fragmentShaders << shader; + m_programs << program; + m_renderOptions->addShader(file.baseName()); + + program->bind(); + m_cubemaps << ((program->uniformLocation("env") != -1) ? new GLRenderTargetCube(qMin(256, m_maxTextureSize)) : 0); + program->release(); + } + + if (m_programs.size() == 0) + m_programs << new QGLShaderProgram; + + m_renderOptions->emitParameterChanged(); +} + +static void loadMatrix(const QMatrix4x4& m) +{ + // static to prevent glLoadMatrixf to fail on certain drivers + static GLfloat mat[16]; + const qreal *data = m.constData(); + for (int index = 0; index < 16; ++index) + mat[index] = data[index]; + glLoadMatrixf(mat); +} + +static void multMatrix(const QMatrix4x4& m) +{ + // static to prevent glMultMatrixf to fail on certain drivers + static GLfloat mat[16]; + const qreal *data = m.constData(); + for (int index = 0; index < 16; ++index) + mat[index] = data[index]; + glMultMatrixf(mat); +} + +// If one of the boxes should not be rendered, set excludeBox to its index. +// If the main box should not be rendered, set excludeBox to -1. +void Scene::renderBoxes(const QMatrix4x4 &view, int excludeBox) +{ + QMatrix4x4 invView = view.inverted(); + + // If multi-texturing is supported, use three saplers. + if (glActiveTexture) { + glActiveTexture(GL_TEXTURE0); + m_textures[m_currentTexture]->bind(); + glActiveTexture(GL_TEXTURE2); + m_noise->bind(); + glActiveTexture(GL_TEXTURE1); + } else { + m_textures[m_currentTexture]->bind(); + } + + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + + QMatrix4x4 viewRotation(view); + viewRotation(3, 0) = viewRotation(3, 1) = viewRotation(3, 2) = 0.0f; + viewRotation(0, 3) = viewRotation(1, 3) = viewRotation(2, 3) = 0.0f; + viewRotation(3, 3) = 1.0f; + loadMatrix(viewRotation); + glScalef(20.0f, 20.0f, 20.0f); + + // Don't render the environment if the environment texture can't be set for the correct sampler. + if (glActiveTexture) { + m_environment->bind(); + m_environmentProgram->bind(); + m_environmentProgram->setUniformValue("tex", GLint(0)); + m_environmentProgram->setUniformValue("env", GLint(1)); + m_environmentProgram->setUniformValue("noise", GLint(2)); + m_box->draw(); + m_environmentProgram->release(); + m_environment->unbind(); + } + + loadMatrix(view); + + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + + for (int i = 0; i < m_programs.size(); ++i) { + if (i == excludeBox) + continue; + + glPushMatrix(); + QMatrix4x4 m; + m.rotate(m_trackBalls[1].rotation()); + multMatrix(m); + + glRotatef(360.0f * i / m_programs.size(), 0.0f, 0.0f, 1.0f); + glTranslatef(2.0f, 0.0f, 0.0f); + glScalef(0.3f, 0.6f, 0.6f); + + if (glActiveTexture) { + if (m_dynamicCubemap && m_cubemaps[i]) + m_cubemaps[i]->bind(); + else + m_environment->bind(); + } + m_programs[i]->bind(); + m_programs[i]->setUniformValue("tex", GLint(0)); + m_programs[i]->setUniformValue("env", GLint(1)); + m_programs[i]->setUniformValue("noise", GLint(2)); + m_programs[i]->setUniformValue("view", view); + m_programs[i]->setUniformValue("invView", invView); + m_box->draw(); + m_programs[i]->release(); + + if (glActiveTexture) { + if (m_dynamicCubemap && m_cubemaps[i]) + m_cubemaps[i]->unbind(); + else + m_environment->unbind(); + } + glPopMatrix(); + } + + if (-1 != excludeBox) { + QMatrix4x4 m; + m.rotate(m_trackBalls[0].rotation()); + multMatrix(m); + + if (glActiveTexture) { + if (m_dynamicCubemap) + m_mainCubemap->bind(); + else + m_environment->bind(); + } + + m_programs[m_currentShader]->bind(); + m_programs[m_currentShader]->setUniformValue("tex", GLint(0)); + m_programs[m_currentShader]->setUniformValue("env", GLint(1)); + m_programs[m_currentShader]->setUniformValue("noise", GLint(2)); + m_programs[m_currentShader]->setUniformValue("view", view); + m_programs[m_currentShader]->setUniformValue("invView", invView); + m_box->draw(); + m_programs[m_currentShader]->release(); + + if (glActiveTexture) { + if (m_dynamicCubemap) + m_mainCubemap->unbind(); + else + m_environment->unbind(); + } + } + + if (glActiveTexture) { + glActiveTexture(GL_TEXTURE2); + m_noise->unbind(); + glActiveTexture(GL_TEXTURE0); + } + m_textures[m_currentTexture]->unbind(); +} + +void Scene::setStates() +{ + //glClearColor(0.25f, 0.25f, 0.5f, 1.0f); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + //glEnable(GL_COLOR_MATERIAL); + glEnable(GL_TEXTURE_2D); + glEnable(GL_NORMALIZE); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + setLights(); + + float materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0f); +} + +void Scene::setLights() +{ + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + //float lightColour[] = {1.0f, 1.0f, 1.0f, 1.0f}; + float lightDir[] = {0.0f, 0.0f, 1.0f, 0.0f}; + //glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColour); + //glLightfv(GL_LIGHT0, GL_SPECULAR, lightColour); + glLightfv(GL_LIGHT0, GL_POSITION, lightDir); + glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0f); + glEnable(GL_LIGHT0); +} + +void Scene::defaultStates() +{ + //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + //glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHT0); + glDisable(GL_NORMALIZE); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 0.0f); + float defaultMaterialSpecular[] = {0.0f, 0.0f, 0.0f, 1.0f}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defaultMaterialSpecular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); +} + +void Scene::renderCubemaps() +{ + // To speed things up, only update the cubemaps for the small cubes every N frames. + const int N = (m_updateAllCubemaps ? 1 : 3); + + QMatrix4x4 mat; + GLRenderTargetCube::getProjectionMatrix(mat, 0.1f, 100.0f); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + loadMatrix(mat); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + QVector3D center; + + for (int i = m_frame % N; i < m_cubemaps.size(); i += N) { + if (0 == m_cubemaps[i]) + continue; + + float angle = 2.0f * PI * i / m_cubemaps.size(); + + center = m_trackBalls[1].rotation().rotatedVector(QVector3D(cos(angle), sin(angle), 0.0f)); + + for (int face = 0; face < 6; ++face) { + m_cubemaps[i]->begin(face); + + GLRenderTargetCube::getViewMatrix(mat, face); + QVector4D v = QVector4D(-center.x(), -center.y(), -center.z(), 1.0); + mat.setColumn(3, mat * v); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderBoxes(mat, i); + + m_cubemaps[i]->end(); + } + } + + for (int face = 0; face < 6; ++face) { + m_mainCubemap->begin(face); + GLRenderTargetCube::getViewMatrix(mat, face); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderBoxes(mat, -1); + + m_mainCubemap->end(); + } + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + m_updateAllCubemaps = false; +} + +void Scene::drawBackground(QPainter *painter, const QRectF &) +{ + float width = float(painter->device()->width()); + float height = float(painter->device()->height()); + + painter->beginNativePainting(); + setStates(); + + if (m_dynamicCubemap) + renderCubemaps(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + qgluPerspective(60.0, width / height, 0.01, 15.0); + + glMatrixMode(GL_MODELVIEW); + + QMatrix4x4 view; + view.rotate(m_trackBalls[2].rotation()); + view(2, 3) -= 2.0f * exp(m_distExp / 1200.0f); + renderBoxes(view); + + defaultStates(); + ++m_frame; + + painter->endNativePainting(); +} + +QPointF Scene::pixelPosToViewPos(const QPointF& p) +{ + return QPointF(2.0 * float(p.x()) / width() - 1.0, + 1.0 - 2.0 * float(p.y()) / height()); +} + +void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsScene::mouseMoveEvent(event); + if (event->isAccepted()) + return; + + if (event->buttons() & Qt::LeftButton) { + m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } else { + m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + } + + if (event->buttons() & Qt::RightButton) { + m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } else { + m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + } + + if (event->buttons() & Qt::MidButton) { + m_trackBalls[2].move(pixelPosToViewPos(event->scenePos()), QQuaternion()); + event->accept(); + } else { + m_trackBalls[2].release(pixelPosToViewPos(event->scenePos()), QQuaternion()); + } +} + +void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsScene::mousePressEvent(event); + if (event->isAccepted()) + return; + + if (event->buttons() & Qt::LeftButton) { + m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->buttons() & Qt::RightButton) { + m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->buttons() & Qt::MidButton) { + m_trackBalls[2].push(pixelPosToViewPos(event->scenePos()), QQuaternion()); + event->accept(); + } +} + +void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsScene::mouseReleaseEvent(event); + if (event->isAccepted()) + return; + + if (event->button() == Qt::LeftButton) { + m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->button() == Qt::RightButton) { + m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->button() == Qt::MidButton) { + m_trackBalls[2].release(pixelPosToViewPos(event->scenePos()), QQuaternion()); + event->accept(); + } +} + +void Scene::wheelEvent(QGraphicsSceneWheelEvent * event) +{ + QGraphicsScene::wheelEvent(event); + if (!event->isAccepted()) { + m_distExp += event->delta(); + if (m_distExp < -8 * 120) + m_distExp = -8 * 120; + if (m_distExp > 10 * 120) + m_distExp = 10 * 120; + event->accept(); + } +} + +void Scene::setShader(int index) +{ + if (index >= 0 && index < m_fragmentShaders.size()) + m_currentShader = index; +} + +void Scene::setTexture(int index) +{ + if (index >= 0 && index < m_textures.size()) + m_currentTexture = index; +} + +void Scene::toggleDynamicCubemap(int state) +{ + if ((m_dynamicCubemap = (state == Qt::Checked))) + m_updateAllCubemaps = true; +} + +void Scene::setColorParameter(const QString &name, QRgb color) +{ + // set the color in all programs + foreach (QGLShaderProgram *program, m_programs) { + program->bind(); + program->setUniformValue(program->uniformLocation(name), QColor(color)); + program->release(); + } +} + +void Scene::setFloatParameter(const QString &name, float value) +{ + // set the color in all programs + foreach (QGLShaderProgram *program, m_programs) { + program->bind(); + program->setUniformValue(program->uniformLocation(name), value); + program->release(); + } +} + +void Scene::newItem(ItemDialog::ItemType type) +{ + QSize size = sceneRect().size().toSize(); + switch (type) { + case ItemDialog::QtBoxItem: + addItem(new QtBox(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); + break; + case ItemDialog::CircleItem: + addItem(new CircleItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); + break; + case ItemDialog::SquareItem: + addItem(new SquareItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); + break; + default: + break; + } +} diff --git a/demos/boxes/scene.h b/demos/boxes/scene.h new file mode 100644 index 0000000000..d1c65268fb --- /dev/null +++ b/demos/boxes/scene.h @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef SCENE_H +#define SCENE_H + +//#include <GL/glew.h> +#include "glextensions.h" + +#include <QtGui> +#include <QtOpenGL> + +#include "roundedbox.h" +#include "gltrianglemesh.h" +#include "trackball.h" +#include "glbuffers.h" +#include "qtbox.h" + +#define PI 3.14159265358979 + +QT_BEGIN_NAMESPACE +class QMatrix4x4; +QT_END_NAMESPACE + +class ParameterEdit : public QWidget +{ +public: + virtual void emitChange() = 0; +}; + +class ColorEdit : public ParameterEdit +{ + Q_OBJECT +public: + ColorEdit(QRgb initialColor, int id); + QRgb color() const {return m_color;} + virtual void emitChange() {emit colorChanged(m_color, m_id);} +public slots: + void editDone(); +signals: + void colorChanged(QRgb color, int id); +protected: + virtual void mousePressEvent(QMouseEvent *event); + void setColor(QRgb color); // also emits colorChanged() +private: + QGraphicsScene *m_dialogParentScene; + QLineEdit *m_lineEdit; + QFrame *m_button; + QRgb m_color; + int m_id; +}; + +class FloatEdit : public ParameterEdit +{ + Q_OBJECT +public: + FloatEdit(float initialValue, int id); + float value() const {return m_value;} + virtual void emitChange() {emit valueChanged(m_value, m_id);} +public slots: + void editDone(); +signals: + void valueChanged(float value, int id); +private: + QGraphicsScene *m_dialogParentScene; + QLineEdit *m_lineEdit; + float m_value; + int m_id; +}; + +class GraphicsWidget : public QGraphicsProxyWidget +{ +public: + GraphicsWidget() : QGraphicsProxyWidget(0, Qt::Window) {} +protected: + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual void resizeEvent(QGraphicsSceneResizeEvent *event); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +}; + +class TwoSidedGraphicsWidget : public QObject +{ + Q_OBJECT +public: + TwoSidedGraphicsWidget(QGraphicsScene *scene); + void setWidget(int index, QWidget *widget); + QWidget *widget(int index); +public slots: + void flip(); +protected slots: + void animateFlip(); +private: + GraphicsWidget *m_proxyWidgets[2]; + int m_current; + int m_angle; // angle in degrees + int m_delta; +}; + +class RenderOptionsDialog : public QDialog +{ + Q_OBJECT +public: + RenderOptionsDialog(); + int addTexture(const QString &name); + int addShader(const QString &name); + void emitParameterChanged(); +protected slots: + void setColorParameter(QRgb color, int id); + void setFloatParameter(float value, int id); +signals: + void dynamicCubemapToggled(int); + void colorParameterChanged(const QString &, QRgb); + void floatParameterChanged(const QString &, float); + void textureChanged(int); + void shaderChanged(int); + void doubleClicked(); +protected: + virtual void mouseDoubleClickEvent(QMouseEvent *event); + + QVector<QByteArray> m_parameterNames; + QComboBox *m_textureCombo; + QComboBox *m_shaderCombo; + QVector<ParameterEdit *> m_parameterEdits; +}; + +class ItemDialog : public QDialog +{ + Q_OBJECT +public: + enum ItemType { + QtBoxItem, + CircleItem, + SquareItem, + }; + + ItemDialog(); +public slots: + void triggerNewQtBox(); + void triggerNewCircleItem(); + void triggerNewSquareItem(); +signals: + void doubleClicked(); + void newItemTriggered(ItemDialog::ItemType type); +protected: + virtual void mouseDoubleClickEvent(QMouseEvent *event); +}; + +class Scene : public QGraphicsScene +{ + Q_OBJECT +public: + Scene(int width, int height, int maxTextureSize); + ~Scene(); + virtual void drawBackground(QPainter *painter, const QRectF &rect); + +public slots: + void setShader(int index); + void setTexture(int index); + void toggleDynamicCubemap(int state); + void setColorParameter(const QString &name, QRgb color); + void setFloatParameter(const QString &name, float value); + void newItem(ItemDialog::ItemType type); +protected: + void renderBoxes(const QMatrix4x4 &view, int excludeBox = -2); + void setStates(); + void setLights(); + void defaultStates(); + void renderCubemaps(); + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void wheelEvent(QGraphicsSceneWheelEvent * event); +private: + void initGL(); + QPointF pixelPosToViewPos(const QPointF& p); + + QTime m_time; + int m_lastTime; + int m_mouseEventTime; + int m_distExp; + int m_frame; + int m_maxTextureSize; + + int m_currentShader; + int m_currentTexture; + bool m_dynamicCubemap; + bool m_updateAllCubemaps; + + RenderOptionsDialog *m_renderOptions; + ItemDialog *m_itemDialog; + QTimer *m_timer; + GLRoundedBox *m_box; + TrackBall m_trackBalls[3]; + QVector<GLTexture *> m_textures; + GLTextureCube *m_environment; + GLTexture3D *m_noise; + GLRenderTargetCube *m_mainCubemap; + QVector<GLRenderTargetCube *> m_cubemaps; + QVector<QGLShaderProgram *> m_programs; + QGLShader *m_vertexShader; + QVector<QGLShader *> m_fragmentShaders; + QGLShader *m_environmentShader; + QGLShaderProgram *m_environmentProgram; +}; + +#endif diff --git a/demos/boxes/smiley.png b/demos/boxes/smiley.png Binary files differnew file mode 100644 index 0000000000..41cfda6b23 --- /dev/null +++ b/demos/boxes/smiley.png diff --git a/demos/boxes/square.jpg b/demos/boxes/square.jpg Binary files differnew file mode 100644 index 0000000000..03f53bd530 --- /dev/null +++ b/demos/boxes/square.jpg diff --git a/demos/boxes/trackball.cpp b/demos/boxes/trackball.cpp new file mode 100644 index 0000000000..8a6a01484e --- /dev/null +++ b/demos/boxes/trackball.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "trackball.h" +#include "scene.h" + +//============================================================================// +// TrackBall // +//============================================================================// + +TrackBall::TrackBall(TrackMode mode) + : m_angularVelocity(0) + , m_paused(false) + , m_pressed(false) + , m_mode(mode) +{ + m_axis = QVector3D(0, 1, 0); + m_rotation = QQuaternion(); + m_lastTime = QTime::currentTime(); +} + +TrackBall::TrackBall(float angularVelocity, const QVector3D& axis, TrackMode mode) + : m_axis(axis) + , m_angularVelocity(angularVelocity) + , m_paused(false) + , m_pressed(false) + , m_mode(mode) +{ + m_rotation = QQuaternion(); + m_lastTime = QTime::currentTime(); +} + +void TrackBall::push(const QPointF& p, const QQuaternion &) +{ + m_rotation = rotation(); + m_pressed = true; + m_lastTime = QTime::currentTime(); + m_lastPos = p; + m_angularVelocity = 0.0f; +} + +void TrackBall::move(const QPointF& p, const QQuaternion &transformation) +{ + if (!m_pressed) + return; + + QTime currentTime = QTime::currentTime(); + int msecs = m_lastTime.msecsTo(currentTime); + if (msecs <= 20) + return; + + switch (m_mode) { + case Plane: + { + QLineF delta(m_lastPos, p); + m_angularVelocity = 180*delta.length() / (PI*msecs); + m_axis = QVector3D(-delta.dy(), delta.dx(), 0.0f).normalized(); + m_axis = transformation.rotatedVector(m_axis); + m_rotation = QQuaternion::fromAxisAndAngle(m_axis, 180 / PI * delta.length()) * m_rotation; + } + break; + case Sphere: + { + QVector3D lastPos3D = QVector3D(m_lastPos.x(), m_lastPos.y(), 0.0f); + float sqrZ = 1 - QVector3D::dotProduct(lastPos3D, lastPos3D); + if (sqrZ > 0) + lastPos3D.setZ(sqrt(sqrZ)); + else + lastPos3D.normalize(); + + QVector3D currentPos3D = QVector3D(p.x(), p.y(), 0.0f); + sqrZ = 1 - QVector3D::dotProduct(currentPos3D, currentPos3D); + if (sqrZ > 0) + currentPos3D.setZ(sqrt(sqrZ)); + else + currentPos3D.normalize(); + + m_axis = QVector3D::crossProduct(lastPos3D, currentPos3D); + float angle = 180 / PI * asin(sqrt(QVector3D::dotProduct(m_axis, m_axis))); + + m_angularVelocity = angle / msecs; + m_axis.normalize(); + m_axis = transformation.rotatedVector(m_axis); + m_rotation = QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation; + } + break; + } + + + m_lastPos = p; + m_lastTime = currentTime; +} + +void TrackBall::release(const QPointF& p, const QQuaternion &transformation) +{ + // Calling move() caused the rotation to stop if the framerate was too low. + move(p, transformation); + m_pressed = false; +} + +void TrackBall::start() +{ + m_lastTime = QTime::currentTime(); + m_paused = false; +} + +void TrackBall::stop() +{ + m_rotation = rotation(); + m_paused = true; +} + +QQuaternion TrackBall::rotation() const +{ + if (m_paused || m_pressed) + return m_rotation; + + QTime currentTime = QTime::currentTime(); + float angle = m_angularVelocity * m_lastTime.msecsTo(currentTime); + return QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation; +} + diff --git a/demos/boxes/trackball.h b/demos/boxes/trackball.h new file mode 100644 index 0000000000..e43b00d7b3 --- /dev/null +++ b/demos/boxes/trackball.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef TRACKBALL_H +#define TRACKBALL_H + +#include <QtGui> + +#include <QtGui/qvector3d.h> +#include <QtGui/qquaternion.h> + +class TrackBall +{ +public: + enum TrackMode + { + Plane, + Sphere, + }; + TrackBall(TrackMode mode = Sphere); + TrackBall(float angularVelocity, const QVector3D& axis, TrackMode mode = Sphere); + // coordinates in [-1,1]x[-1,1] + void push(const QPointF& p, const QQuaternion &transformation); + void move(const QPointF& p, const QQuaternion &transformation); + void release(const QPointF& p, const QQuaternion &transformation); + void start(); // starts clock + void stop(); // stops clock + QQuaternion rotation() const; +private: + QQuaternion m_rotation; + QVector3D m_axis; + float m_angularVelocity; + + QPointF m_lastPos; + QTime m_lastTime; + bool m_paused; + bool m_pressed; + TrackMode m_mode; +}; + +#endif diff --git a/demos/boxes/wood.fsh b/demos/boxes/wood.fsh new file mode 100644 index 0000000000..8e47b69f9c --- /dev/null +++ b/demos/boxes/wood.fsh @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform sampler3D noise; + +//const vec4 woodColors[2] = {vec4(0.37,0.24,0.20,1), vec4(0.8,0.6,0.4,1)}; +uniform vec4 woodColors[2]; +//const float woodTubulence = 0.1; +uniform float woodTubulence; + +void main() +{ + float r = length(gl_TexCoord[1].yz); + r += woodTubulence * texture3D(noise, 0.25 * gl_TexCoord[1].xyz).x; + + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + float f = fract(16.0 * r); + vec4 unlitColor = mix(woodColors[0], woodColors[1], min(1.25 * f, 5.0 - 5.0 * f)); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/demos/chip/chip.cpp b/demos/chip/chip.cpp new file mode 100644 index 0000000000..6f3b529f16 --- /dev/null +++ b/demos/chip/chip.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "chip.h" + +#include <QtGui> + +Chip::Chip(const QColor &color, int x, int y) +{ + this->x = x; + this->y = y; + this->color = color; + setZValue((x + y) % 2); + + setFlags(ItemIsSelectable | ItemIsMovable); + setAcceptsHoverEvents(true); +} + +QRectF Chip::boundingRect() const +{ + return QRectF(0, 0, 110, 70); +} + +QPainterPath Chip::shape() const +{ + QPainterPath path; + path.addRect(14, 14, 82, 42); + return path; +} + +void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + + QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; + if (option->state & QStyle::State_MouseOver) + fillColor = fillColor.light(125); + + const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform()); + if (lod < 0.2) { + if (lod < 0.125) { + painter->fillRect(QRectF(0, 0, 110, 70), fillColor); + return; + } + + QBrush b = painter->brush(); + painter->setBrush(fillColor); + painter->drawRect(13, 13, 97, 57); + painter->setBrush(b); + return; + } + + QPen oldPen = painter->pen(); + QPen pen = oldPen; + int width = 0; + if (option->state & QStyle::State_Selected) + width += 2; + + pen.setWidth(width); + QBrush b = painter->brush(); + painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100))); + + painter->drawRect(QRect(14, 14, 79, 39)); + painter->setBrush(b); + + if (lod >= 1) { + painter->setPen(QPen(Qt::gray, 1)); + painter->drawLine(15, 54, 94, 54); + painter->drawLine(94, 53, 94, 15); + painter->setPen(QPen(Qt::black, 0)); + } + + // Draw text + if (lod >= 2) { + QFont font("Times", 10); + font.setStyleStrategy(QFont::ForceOutline); + painter->setFont(font); + painter->save(); + painter->scale(0.1, 0.1); + painter->drawText(170, 180, QString("Model: VSC-2000 (Very Small Chip) at %1x%2").arg(x).arg(y)); + painter->drawText(170, 200, QString("Serial number: DLWR-WEER-123L-ZZ33-SDSJ")); + painter->drawText(170, 220, QString("Manufacturer: Chip Manufacturer")); + painter->restore(); + } + + // Draw lines + QVarLengthArray<QLineF, 36> lines; + if (lod >= 0.5) { + for (int i = 0; i <= 10; i += (lod > 0.5 ? 1 : 2)) { + lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5)); + lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62)); + } + for (int i = 0; i <= 6; i += (lod > 0.5 ? 1 : 2)) { + lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5)); + lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5)); + } + } + if (lod >= 0.4) { + const QLineF lineData[] = { + QLineF(25, 35, 35, 35), + QLineF(35, 30, 35, 40), + QLineF(35, 30, 45, 35), + QLineF(35, 40, 45, 35), + QLineF(45, 30, 45, 40), + QLineF(45, 35, 55, 35) + }; + lines.append(lineData, 6); + } + painter->drawLines(lines.data(), lines.size()); + + // Draw red ink + if (stuff.size() > 1) { + QPen p = painter->pen(); + painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->setBrush(Qt::NoBrush); + QPainterPath path; + path.moveTo(stuff.first()); + for (int i = 1; i < stuff.size(); ++i) + path.lineTo(stuff.at(i)); + painter->drawPath(path); + painter->setPen(p); + } +} + +void Chip::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsItem::mousePressEvent(event); + update(); +} + +void Chip::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->modifiers() & Qt::ShiftModifier) { + stuff << event->pos(); + update(); + return; + } + QGraphicsItem::mouseMoveEvent(event); +} + +void Chip::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsItem::mouseReleaseEvent(event); + update(); +} diff --git a/demos/chip/chip.h b/demos/chip/chip.h new file mode 100644 index 0000000000..dca63b71fc --- /dev/null +++ b/demos/chip/chip.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef CHIP_H +#define CHIP_H + +#include <QtGui/QColor> +#include <QtGui/QGraphicsItem> + +class Chip : public QGraphicsItem +{ +public: + Chip(const QColor &color, int x, int y); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + +private: + int x, y; + QColor color; + QList<QPointF> stuff; +}; + +#endif diff --git a/demos/chip/chip.pro b/demos/chip/chip.pro new file mode 100644 index 0000000000..8ff2aa45f1 --- /dev/null +++ b/demos/chip/chip.pro @@ -0,0 +1,20 @@ +RESOURCES += images.qrc + +HEADERS += mainwindow.h view.h chip.h +SOURCES += main.cpp +SOURCES += mainwindow.cpp view.cpp chip.cpp + +contains(QT_CONFIG, opengl):QT += opengl + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/chip +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.png *.pro *.html *.doc images +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/chip +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/demos/chip/fileprint.png b/demos/chip/fileprint.png Binary files differnew file mode 100644 index 0000000000..ba7c02dc18 --- /dev/null +++ b/demos/chip/fileprint.png diff --git a/demos/chip/images.qrc b/demos/chip/images.qrc new file mode 100644 index 0000000000..c7cdf0c4c0 --- /dev/null +++ b/demos/chip/images.qrc @@ -0,0 +1,10 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>qt4logo.png</file> + <file>zoomin.png</file> + <file>zoomout.png</file> + <file>rotateleft.png</file> + <file>rotateright.png</file> + <file>fileprint.png</file> +</qresource> +</RCC> diff --git a/demos/chip/main.cpp b/demos/chip/main.cpp new file mode 100644 index 0000000000..a4353bfde4 --- /dev/null +++ b/demos/chip/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "mainwindow.h" + +#include <QApplication> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(images); + + QApplication app(argc, argv); + app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + + MainWindow window; + window.show(); + + return app.exec(); +} diff --git a/demos/chip/mainwindow.cpp b/demos/chip/mainwindow.cpp new file mode 100644 index 0000000000..825c38823a --- /dev/null +++ b/demos/chip/mainwindow.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "mainwindow.h" +#include "view.h" +#include "chip.h" + +#include <QtGui> + +MainWindow::MainWindow(QWidget *parent) + : QWidget(parent) +{ + populateScene(); + + h1Splitter = new QSplitter; + h2Splitter = new QSplitter; + + QSplitter *vSplitter = new QSplitter; + vSplitter->setOrientation(Qt::Vertical); + vSplitter->addWidget(h1Splitter); + vSplitter->addWidget(h2Splitter); + + View *view = new View("Top left view"); + view->view()->setScene(scene); + h1Splitter->addWidget(view); + + view = new View("Top right view"); + view->view()->setScene(scene); + h1Splitter->addWidget(view); + + view = new View("Bottom left view"); + view->view()->setScene(scene); + h2Splitter->addWidget(view); + + view = new View("Bottom right view"); + view->view()->setScene(scene); + h2Splitter->addWidget(view); + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(vSplitter); + setLayout(layout); + + setWindowTitle(tr("Chip Demo")); +} + +void MainWindow::populateScene() +{ + scene = new QGraphicsScene; + + QImage image(":/qt4logo.png"); + + // Populate scene + int xx = 0; + int nitems = 0; + for (int i = -11000; i < 11000; i += 110) { + ++xx; + int yy = 0; + for (int j = -7000; j < 7000; j += 70) { + ++yy; + qreal x = (i + 11000) / 22000.0; + qreal y = (j + 7000) / 14000.0; + + QColor color(image.pixel(int(image.width() * x), int(image.height() * y))); + QGraphicsItem *item = new Chip(color, xx, yy); + item->setPos(QPointF(i, j)); + scene->addItem(item); + + ++nitems; + } + } +} diff --git a/demos/chip/mainwindow.h b/demos/chip/mainwindow.h new file mode 100644 index 0000000000..9c8ac03638 --- /dev/null +++ b/demos/chip/mainwindow.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QtGui/qwidget.h> + +QT_FORWARD_DECLARE_CLASS(QGraphicsScene) +QT_FORWARD_DECLARE_CLASS(QGraphicsView) +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QSplitter) + +class MainWindow : public QWidget +{ + Q_OBJECT +public: + MainWindow(QWidget *parent = 0); + +private: + void setupMatrix(); + void populateScene(); + + QGraphicsScene *scene; + QSplitter *h1Splitter; + QSplitter *h2Splitter; +}; + +#endif diff --git a/demos/chip/qt4logo.png b/demos/chip/qt4logo.png Binary files differnew file mode 100644 index 0000000000..157e86ed64 --- /dev/null +++ b/demos/chip/qt4logo.png diff --git a/demos/chip/rotateleft.png b/demos/chip/rotateleft.png Binary files differnew file mode 100644 index 0000000000..8cfa931986 --- /dev/null +++ b/demos/chip/rotateleft.png diff --git a/demos/chip/rotateright.png b/demos/chip/rotateright.png Binary files differnew file mode 100644 index 0000000000..ec5e8664a1 --- /dev/null +++ b/demos/chip/rotateright.png diff --git a/demos/chip/view.cpp b/demos/chip/view.cpp new file mode 100644 index 0000000000..49d02ecb52 --- /dev/null +++ b/demos/chip/view.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "view.h" + +#include <QtGui> +#ifndef QT_NO_OPENGL +#include <QtOpenGL> +#endif + +#include <qmath.h> + +void GraphicsView::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() & Qt::ControlModifier) { + if (e->delta() > 0) + view->zoomIn(6); + else + view->zoomOut(6); + e->accept(); + } else { + QGraphicsView::wheelEvent(e); + } +} + +View::View(const QString &name, QWidget *parent) + : QFrame(parent) +{ + setFrameStyle(Sunken | StyledPanel); + graphicsView = new GraphicsView(this); + graphicsView->setRenderHint(QPainter::Antialiasing, false); + graphicsView->setDragMode(QGraphicsView::RubberBandDrag); + graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); + graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + + int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + QSize iconSize(size, size); + + QToolButton *zoomInIcon = new QToolButton; + zoomInIcon->setAutoRepeat(true); + zoomInIcon->setAutoRepeatInterval(33); + zoomInIcon->setAutoRepeatDelay(0); + zoomInIcon->setIcon(QPixmap(":/zoomin.png")); + zoomInIcon->setIconSize(iconSize); + QToolButton *zoomOutIcon = new QToolButton; + zoomOutIcon->setAutoRepeat(true); + zoomOutIcon->setAutoRepeatInterval(33); + zoomOutIcon->setAutoRepeatDelay(0); + zoomOutIcon->setIcon(QPixmap(":/zoomout.png")); + zoomOutIcon->setIconSize(iconSize); + zoomSlider = new QSlider; + zoomSlider->setMinimum(0); + zoomSlider->setMaximum(500); + zoomSlider->setValue(250); + zoomSlider->setTickPosition(QSlider::TicksRight); + + // Zoom slider layout + QVBoxLayout *zoomSliderLayout = new QVBoxLayout; + zoomSliderLayout->addWidget(zoomInIcon); + zoomSliderLayout->addWidget(zoomSlider); + zoomSliderLayout->addWidget(zoomOutIcon); + + QToolButton *rotateLeftIcon = new QToolButton; + rotateLeftIcon->setIcon(QPixmap(":/rotateleft.png")); + rotateLeftIcon->setIconSize(iconSize); + QToolButton *rotateRightIcon = new QToolButton; + rotateRightIcon->setIcon(QPixmap(":/rotateright.png")); + rotateRightIcon->setIconSize(iconSize); + rotateSlider = new QSlider; + rotateSlider->setOrientation(Qt::Horizontal); + rotateSlider->setMinimum(-360); + rotateSlider->setMaximum(360); + rotateSlider->setValue(0); + rotateSlider->setTickPosition(QSlider::TicksBelow); + + // Rotate slider layout + QHBoxLayout *rotateSliderLayout = new QHBoxLayout; + rotateSliderLayout->addWidget(rotateLeftIcon); + rotateSliderLayout->addWidget(rotateSlider); + rotateSliderLayout->addWidget(rotateRightIcon); + + resetButton = new QToolButton; + resetButton->setText(tr("0")); + resetButton->setEnabled(false); + + // Label layout + QHBoxLayout *labelLayout = new QHBoxLayout; + label = new QLabel(name); + label2 = new QLabel(tr("Pointer Mode")); + selectModeButton = new QToolButton; + selectModeButton->setText(tr("Select")); + selectModeButton->setCheckable(true); + selectModeButton->setChecked(true); + dragModeButton = new QToolButton; + dragModeButton->setText(tr("Drag")); + dragModeButton->setCheckable(true); + dragModeButton->setChecked(false); + antialiasButton = new QToolButton; + antialiasButton->setText(tr("Antialiasing")); + antialiasButton->setCheckable(true); + antialiasButton->setChecked(false); + openGlButton = new QToolButton; + openGlButton->setText(tr("OpenGL")); + openGlButton->setCheckable(true); +#ifndef QT_NO_OPENGL + openGlButton->setEnabled(QGLFormat::hasOpenGL()); +#else + openGlButton->setEnabled(false); +#endif + printButton = new QToolButton; + printButton->setIcon(QIcon(QPixmap(":/fileprint.png"))); + + QButtonGroup *pointerModeGroup = new QButtonGroup; + pointerModeGroup->setExclusive(true); + pointerModeGroup->addButton(selectModeButton); + pointerModeGroup->addButton(dragModeButton); + + labelLayout->addWidget(label); + labelLayout->addStretch(); + labelLayout->addWidget(label2); + labelLayout->addWidget(selectModeButton); + labelLayout->addWidget(dragModeButton); + labelLayout->addStretch(); + labelLayout->addWidget(antialiasButton); + labelLayout->addWidget(openGlButton); + labelLayout->addWidget(printButton); + + QGridLayout *topLayout = new QGridLayout; + topLayout->addLayout(labelLayout, 0, 0); + topLayout->addWidget(graphicsView, 1, 0); + topLayout->addLayout(zoomSliderLayout, 1, 1); + topLayout->addLayout(rotateSliderLayout, 2, 0); + topLayout->addWidget(resetButton, 2, 1); + setLayout(topLayout); + + connect(resetButton, SIGNAL(clicked()), this, SLOT(resetView())); + connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); + connect(rotateSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); + connect(graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + connect(graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + connect(selectModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + connect(dragModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + connect(antialiasButton, SIGNAL(toggled(bool)), this, SLOT(toggleAntialiasing())); + connect(openGlButton, SIGNAL(toggled(bool)), this, SLOT(toggleOpenGL())); + connect(rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft())); + connect(rotateRightIcon, SIGNAL(clicked()), this, SLOT(rotateRight())); + connect(zoomInIcon, SIGNAL(clicked()), this, SLOT(zoomIn())); + connect(zoomOutIcon, SIGNAL(clicked()), this, SLOT(zoomOut())); + connect(printButton, SIGNAL(clicked()), this, SLOT(print())); + + setupMatrix(); +} + +QGraphicsView *View::view() const +{ + return static_cast<QGraphicsView *>(graphicsView); +} + +void View::resetView() +{ + zoomSlider->setValue(250); + rotateSlider->setValue(0); + setupMatrix(); + graphicsView->ensureVisible(QRectF(0, 0, 0, 0)); + + resetButton->setEnabled(false); +} + +void View::setResetButtonEnabled() +{ + resetButton->setEnabled(true); +} + +void View::setupMatrix() +{ + qreal scale = qPow(qreal(2), (zoomSlider->value() - 250) / qreal(50)); + + QMatrix matrix; + matrix.scale(scale, scale); + matrix.rotate(rotateSlider->value()); + + graphicsView->setMatrix(matrix); + setResetButtonEnabled(); +} + +void View::togglePointerMode() +{ + graphicsView->setDragMode(selectModeButton->isChecked() + ? QGraphicsView::RubberBandDrag + : QGraphicsView::ScrollHandDrag); + graphicsView->setInteractive(selectModeButton->isChecked()); +} + +void View::toggleOpenGL() +{ +#ifndef QT_NO_OPENGL + graphicsView->setViewport(openGlButton->isChecked() ? new QGLWidget(QGLFormat(QGL::SampleBuffers)) : new QWidget); +#endif +} + +void View::toggleAntialiasing() +{ + graphicsView->setRenderHint(QPainter::Antialiasing, antialiasButton->isChecked()); +} + +void View::print() +{ +#ifndef QT_NO_PRINTER + QPrinter printer; + QPrintDialog dialog(&printer, this); + if (dialog.exec() == QDialog::Accepted) { + QPainter painter(&printer); + graphicsView->render(&painter); + } +#endif +} + +void View::zoomIn(int level) +{ + zoomSlider->setValue(zoomSlider->value() + level); +} + +void View::zoomOut(int level) +{ + zoomSlider->setValue(zoomSlider->value() - level); +} + +void View::rotateLeft() +{ + rotateSlider->setValue(rotateSlider->value() - 10); +} + +void View::rotateRight() +{ + rotateSlider->setValue(rotateSlider->value() + 10); +} + diff --git a/demos/chip/view.h b/demos/chip/view.h new file mode 100644 index 0000000000..15aa2cf4c9 --- /dev/null +++ b/demos/chip/view.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef VIEW_H +#define VIEW_H + +#include <QFrame> +#include <QGraphicsView> + +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QToolButton) + +class View; + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(View *v) : QGraphicsView(), view(v) { } + +protected: + void wheelEvent(QWheelEvent *); + +private: + View *view; +}; + +class View : public QFrame +{ + Q_OBJECT +public: + View(const QString &name, QWidget *parent = 0); + + QGraphicsView *view() const; + +public slots: + void zoomIn(int level = 1); + void zoomOut(int level = 1); + +private slots: + void resetView(); + void setResetButtonEnabled(); + void setupMatrix(); + void togglePointerMode(); + void toggleOpenGL(); + void toggleAntialiasing(); + void print(); + void rotateLeft(); + void rotateRight(); + +private: + GraphicsView *graphicsView; + QLabel *label; + QLabel *label2; + QToolButton *selectModeButton; + QToolButton *dragModeButton; + QToolButton *openGlButton; + QToolButton *antialiasButton; + QToolButton *printButton; + QToolButton *resetButton; + QSlider *zoomSlider; + QSlider *rotateSlider; +}; + +#endif diff --git a/demos/chip/zoomin.png b/demos/chip/zoomin.png Binary files differnew file mode 100644 index 0000000000..8b0daeea48 --- /dev/null +++ b/demos/chip/zoomin.png diff --git a/demos/chip/zoomout.png b/demos/chip/zoomout.png Binary files differnew file mode 100644 index 0000000000..1575dd24f6 --- /dev/null +++ b/demos/chip/zoomout.png diff --git a/demos/composition/composition.cpp b/demos/composition/composition.cpp new file mode 100644 index 0000000000..15f5529611 --- /dev/null +++ b/demos/composition/composition.cpp @@ -0,0 +1,544 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "composition.h" +#include <QBoxLayout> +#include <QRadioButton> +#include <QTimer> +#include <QDateTime> +#include <QSlider> +#include <QMouseEvent> +#include <qmath.h> + +const int animationInterval = 15; // update every 16 ms = ~60FPS + +CompositionWidget::CompositionWidget(QWidget *parent) + : QWidget(parent) +{ + CompositionRenderer *view = new CompositionRenderer(this); + + QGroupBox *mainGroup = new QGroupBox(parent); + mainGroup->setTitle(tr("Composition Modes")); + + QGroupBox *modesGroup = new QGroupBox(mainGroup); + modesGroup->setTitle(tr("Mode")); + + rbClear = new QRadioButton(tr("Clear"), modesGroup); + connect(rbClear, SIGNAL(clicked()), view, SLOT(setClearMode())); + rbSource = new QRadioButton(tr("Source"), modesGroup); + connect(rbSource, SIGNAL(clicked()), view, SLOT(setSourceMode())); + rbDest = new QRadioButton(tr("Destination"), modesGroup); + connect(rbDest, SIGNAL(clicked()), view, SLOT(setDestMode())); + rbSourceOver = new QRadioButton(tr("Source Over"), modesGroup); + connect(rbSourceOver, SIGNAL(clicked()), view, SLOT(setSourceOverMode())); + rbDestOver = new QRadioButton(tr("Destination Over"), modesGroup); + connect(rbDestOver, SIGNAL(clicked()), view, SLOT(setDestOverMode())); + rbSourceIn = new QRadioButton(tr("Source In"), modesGroup); + connect(rbSourceIn, SIGNAL(clicked()), view, SLOT(setSourceInMode())); + rbDestIn = new QRadioButton(tr("Dest In"), modesGroup); + connect(rbDestIn, SIGNAL(clicked()), view, SLOT(setDestInMode())); + rbSourceOut = new QRadioButton(tr("Source Out"), modesGroup); + connect(rbSourceOut, SIGNAL(clicked()), view, SLOT(setSourceOutMode())); + rbDestOut = new QRadioButton(tr("Dest Out"), modesGroup); + connect(rbDestOut, SIGNAL(clicked()), view, SLOT(setDestOutMode())); + rbSourceAtop = new QRadioButton(tr("Source Atop"), modesGroup); + connect(rbSourceAtop, SIGNAL(clicked()), view, SLOT(setSourceAtopMode())); + rbDestAtop = new QRadioButton(tr("Dest Atop"), modesGroup); + connect(rbDestAtop, SIGNAL(clicked()), view, SLOT(setDestAtopMode())); + rbXor = new QRadioButton(tr("Xor"), modesGroup); + connect(rbXor, SIGNAL(clicked()), view, SLOT(setXorMode())); + + rbPlus = new QRadioButton(tr("Plus"), modesGroup); + connect(rbPlus, SIGNAL(clicked()), view, SLOT(setPlusMode())); + rbMultiply = new QRadioButton(tr("Multiply"), modesGroup); + connect(rbMultiply, SIGNAL(clicked()), view, SLOT(setMultiplyMode())); + rbScreen = new QRadioButton(tr("Screen"), modesGroup); + connect(rbScreen, SIGNAL(clicked()), view, SLOT(setScreenMode())); + rbOverlay = new QRadioButton(tr("Overlay"), modesGroup); + connect(rbOverlay, SIGNAL(clicked()), view, SLOT(setOverlayMode())); + rbDarken = new QRadioButton(tr("Darken"), modesGroup); + connect(rbDarken, SIGNAL(clicked()), view, SLOT(setDarkenMode())); + rbLighten = new QRadioButton(tr("Lighten"), modesGroup); + connect(rbLighten, SIGNAL(clicked()), view, SLOT(setLightenMode())); + rbColorDodge = new QRadioButton(tr("Color Dodge"), modesGroup); + connect(rbColorDodge, SIGNAL(clicked()), view, SLOT(setColorDodgeMode())); + rbColorBurn = new QRadioButton(tr("Color Burn"), modesGroup); + connect(rbColorBurn, SIGNAL(clicked()), view, SLOT(setColorBurnMode())); + rbHardLight = new QRadioButton(tr("Hard Light"), modesGroup); + connect(rbHardLight, SIGNAL(clicked()), view, SLOT(setHardLightMode())); + rbSoftLight = new QRadioButton(tr("Soft Light"), modesGroup); + connect(rbSoftLight, SIGNAL(clicked()), view, SLOT(setSoftLightMode())); + rbDifference = new QRadioButton(tr("Difference"), modesGroup); + connect(rbDifference, SIGNAL(clicked()), view, SLOT(setDifferenceMode())); + rbExclusion = new QRadioButton(tr("Exclusion"), modesGroup); + connect(rbExclusion, SIGNAL(clicked()), view, SLOT(setExclusionMode())); + + QGroupBox *circleColorGroup = new QGroupBox(mainGroup); + circleColorGroup->setTitle(tr("Circle color")); + QSlider *circleColorSlider = new QSlider(Qt::Horizontal, circleColorGroup); + circleColorSlider->setRange(0, 359); + circleColorSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + connect(circleColorSlider, SIGNAL(valueChanged(int)), view, SLOT(setCircleColor(int))); + + QGroupBox *circleAlphaGroup = new QGroupBox(mainGroup); + circleAlphaGroup->setTitle(tr("Circle alpha")); + QSlider *circleAlphaSlider = new QSlider(Qt::Horizontal, circleAlphaGroup); + circleAlphaSlider->setRange(0, 255); + circleAlphaSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + connect(circleAlphaSlider, SIGNAL(valueChanged(int)), view, SLOT(setCircleAlpha(int))); + + QPushButton *showSourceButton = new QPushButton(mainGroup); + showSourceButton->setText(tr("Show Source")); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + QPushButton *enableOpenGLButton = new QPushButton(mainGroup); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(true); + enableOpenGLButton->setChecked(view->usesOpenGL()); + + if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) + enableOpenGLButton->hide(); +#endif + QPushButton *whatsThisButton = new QPushButton(mainGroup); + whatsThisButton->setText(tr("What's This?")); + whatsThisButton->setCheckable(true); + + QPushButton *animateButton = new QPushButton(mainGroup); + animateButton->setText(tr("Animated")); + animateButton->setCheckable(true); + animateButton->setChecked(true); + + QHBoxLayout *viewLayout = new QHBoxLayout(this); + viewLayout->addWidget(view); + viewLayout->addWidget(mainGroup); + + QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); + mainGroupLayout->addWidget(circleColorGroup); + mainGroupLayout->addWidget(circleAlphaGroup); + mainGroupLayout->addWidget(modesGroup); + mainGroupLayout->addStretch(); + mainGroupLayout->addWidget(animateButton); + mainGroupLayout->addWidget(whatsThisButton); + mainGroupLayout->addWidget(showSourceButton); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + mainGroupLayout->addWidget(enableOpenGLButton); +#endif + + QGridLayout *modesLayout = new QGridLayout(modesGroup); + modesLayout->addWidget(rbClear, 0, 0); + modesLayout->addWidget(rbSource, 1, 0); + modesLayout->addWidget(rbDest, 2, 0); + modesLayout->addWidget(rbSourceOver, 3, 0); + modesLayout->addWidget(rbDestOver, 4, 0); + modesLayout->addWidget(rbSourceIn, 5, 0); + modesLayout->addWidget(rbDestIn, 6, 0); + modesLayout->addWidget(rbSourceOut, 7, 0); + modesLayout->addWidget(rbDestOut, 8, 0); + modesLayout->addWidget(rbSourceAtop, 9, 0); + modesLayout->addWidget(rbDestAtop, 10, 0); + modesLayout->addWidget(rbXor, 11, 0); + + modesLayout->addWidget(rbPlus, 0, 1); + modesLayout->addWidget(rbMultiply, 1, 1); + modesLayout->addWidget(rbScreen, 2, 1); + modesLayout->addWidget(rbOverlay, 3, 1); + modesLayout->addWidget(rbDarken, 4, 1); + modesLayout->addWidget(rbLighten, 5, 1); + modesLayout->addWidget(rbColorDodge, 6, 1); + modesLayout->addWidget(rbColorBurn, 7, 1); + modesLayout->addWidget(rbHardLight, 8, 1); + modesLayout->addWidget(rbSoftLight, 9, 1); + modesLayout->addWidget(rbDifference, 10, 1); + modesLayout->addWidget(rbExclusion, 11, 1); + + + QVBoxLayout *circleColorLayout = new QVBoxLayout(circleColorGroup); + circleColorLayout->addWidget(circleColorSlider); + + QVBoxLayout *circleAlphaLayout = new QVBoxLayout(circleAlphaGroup); + circleAlphaLayout->addWidget(circleAlphaSlider); + + view->loadDescription(":res/composition/composition.html"); + view->loadSourceFile(":res/composition/composition.cpp"); + + connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool))); + connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool))); + connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource())); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool))); +#endif + connect(animateButton, SIGNAL(toggled(bool)), view, SLOT(setAnimationEnabled(bool))); + + circleColorSlider->setValue(270); + circleAlphaSlider->setValue(200); + rbSourceOut->animateClick(); + + setWindowTitle(tr("Composition Modes")); +} + + +void CompositionWidget::nextMode() +{ + /* + if (!m_animation_enabled) + return; + if (rbClear->isChecked()) rbSource->animateClick(); + if (rbSource->isChecked()) rbDest->animateClick(); + if (rbDest->isChecked()) rbSourceOver->animateClick(); + if (rbSourceOver->isChecked()) rbDestOver->animateClick(); + if (rbDestOver->isChecked()) rbSourceIn->animateClick(); + if (rbSourceIn->isChecked()) rbDestIn->animateClick(); + if (rbDestIn->isChecked()) rbSourceOut->animateClick(); + if (rbSourceOut->isChecked()) rbDestOut->animateClick(); + if (rbDestOut->isChecked()) rbSourceAtop->animateClick(); + if (rbSourceAtop->isChecked()) rbDestAtop->animateClick(); + if (rbDestAtop->isChecked()) rbXor->animateClick(); + if (rbXor->isChecked()) rbClear->animateClick(); + */ +} + +CompositionRenderer::CompositionRenderer(QWidget *parent) + : ArthurFrame(parent) +{ + m_animation_enabled = true; + m_animationTimer = startTimer(animationInterval); +#ifdef Q_WS_QWS + m_image = QPixmap(":res/composition/flower.jpg"); + m_image.setAlphaChannel(QPixmap(":res/composition/flower_alpha.jpg")); +#else + m_image = QImage(":res/composition/flower.jpg"); + m_image.setAlphaChannel(QImage(":res/composition/flower_alpha.jpg")); +#endif + m_circle_alpha = 127; + m_circle_hue = 255; + m_current_object = NoObject; + m_composition_mode = QPainter::CompositionMode_SourceOut; + + m_circle_pos = QPoint(200, 100); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +#ifdef QT_OPENGL_SUPPORT + m_pbuffer = 0; + m_pbuffer_size = 1024; +#endif +} + +QRectF rectangle_around(const QPointF &p, const QSizeF &size = QSize(250, 200)) +{ + QRectF rect(p, size); + rect.translate(-size.width()/2, -size.height()/2); + return rect; +} + +void CompositionRenderer::setAnimationEnabled(bool enabled) +{ + if (m_animation_enabled == enabled) + return; + m_animation_enabled = enabled; + if (enabled) { + Q_ASSERT(!m_animationTimer); + m_animationTimer = startTimer(animationInterval); + } else { + killTimer(m_animationTimer); + m_animationTimer = 0; + } +} + +void CompositionRenderer::updateCirclePos() +{ + if (m_current_object != NoObject) + return; + QDateTime dt = QDateTime::currentDateTime(); + qreal t = (dt.toTime_t() * 1000 + dt.time().msec()) / 1000.0; + + qreal x = width() / qreal(2) + (qCos(t*8/11) + qSin(-t)) * width() / qreal(4); + qreal y = height() / qreal(2) + (qSin(t*6/7) + qCos(t * qreal(1.5))) * height() / qreal(4); + + setCirclePos(QLineF(m_circle_pos, QPointF(x, y)).pointAt(0.02)); +} + +void CompositionRenderer::drawBase(QPainter &p) +{ + p.setPen(Qt::NoPen); + + QLinearGradient rect_gradient(0, 0, 0, height()); + rect_gradient.setColorAt(0, Qt::red); + rect_gradient.setColorAt(.17, Qt::yellow); + rect_gradient.setColorAt(.33, Qt::green); + rect_gradient.setColorAt(.50, Qt::cyan); + rect_gradient.setColorAt(.66, Qt::blue); + rect_gradient.setColorAt(.81, Qt::magenta); + rect_gradient.setColorAt(1, Qt::red); + p.setBrush(rect_gradient); + p.drawRect(width() / 2, 0, width() / 2, height()); + + QLinearGradient alpha_gradient(0, 0, width(), 0); + alpha_gradient.setColorAt(0, Qt::white); + alpha_gradient.setColorAt(0.2, Qt::white); + alpha_gradient.setColorAt(0.5, Qt::transparent); + alpha_gradient.setColorAt(0.8, Qt::white); + alpha_gradient.setColorAt(1, Qt::white); + + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.setBrush(alpha_gradient); + p.drawRect(0, 0, width(), height()); + + p.setCompositionMode(QPainter::CompositionMode_DestinationOver); + + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::SmoothPixmapTransform); +#ifdef Q_WS_QWS + p.drawPixmap(rect(), m_image); +#else + p.drawImage(rect(), m_image); +#endif +} + +void CompositionRenderer::drawSource(QPainter &p) +{ + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setCompositionMode(m_composition_mode); + + QRectF circle_rect = rectangle_around(m_circle_pos); + QColor color = QColor::fromHsvF(m_circle_hue / 360.0, 1, 1, m_circle_alpha / 255.0); + QLinearGradient circle_gradient(circle_rect.topLeft(), circle_rect.bottomRight()); + circle_gradient.setColorAt(0, color.light()); + circle_gradient.setColorAt(0.5, color); + circle_gradient.setColorAt(1, color.dark()); + p.setBrush(circle_gradient); + + p.drawEllipse(circle_rect); +} + +void CompositionRenderer::paint(QPainter *painter) +{ +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + if (usesOpenGL()) { + + int new_pbuf_size = m_pbuffer_size; + if (size().width() > m_pbuffer_size || + size().height() > m_pbuffer_size) + new_pbuf_size *= 2; + + if (size().width() < m_pbuffer_size/2 && + size().height() < m_pbuffer_size/2) + new_pbuf_size /= 2; + + if (!m_pbuffer || new_pbuf_size != m_pbuffer_size) { + if (m_pbuffer) { + m_pbuffer->deleteTexture(m_base_tex); + m_pbuffer->deleteTexture(m_compositing_tex); + delete m_pbuffer; + } + + m_pbuffer = new QGLPixelBuffer(QSize(new_pbuf_size, new_pbuf_size), QGLFormat::defaultFormat(), glWidget()); + m_pbuffer->makeCurrent(); + m_base_tex = m_pbuffer->generateDynamicTexture(); + m_compositing_tex = m_pbuffer->generateDynamicTexture(); + m_pbuffer_size = new_pbuf_size; + } + + if (size() != m_previous_size) { + m_previous_size = size(); + QPainter p(m_pbuffer); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent); + drawBase(p); + p.end(); + m_pbuffer->updateDynamicTexture(m_base_tex); + } + + qreal x_fraction = width()/float(m_pbuffer->width()); + qreal y_fraction = height()/float(m_pbuffer->height()); + + { + QPainter p(m_pbuffer); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent); + + p.save(); // Needed when using the GL1 engine + p.beginNativePainting(); // Needed when using the GL2 engine + + glBindTexture(GL_TEXTURE_2D, m_base_tex); + glEnable(GL_TEXTURE_2D); + glColor4f(1.,1.,1.,1.); + + glBegin(GL_QUADS); + { + glTexCoord2f(0, 1.0); + glVertex2f(0, 0); + + glTexCoord2f(x_fraction, 1.0); + glVertex2f(width(), 0); + + glTexCoord2f(x_fraction, 1.0-y_fraction); + glVertex2f(width(), height()); + + glTexCoord2f(0, 1.0-y_fraction); + glVertex2f(0, height()); + } + glEnd(); + + glDisable(GL_TEXTURE_2D); + + p.endNativePainting(); // Needed when using the GL2 engine + p.restore(); // Needed when using the GL1 engine + + drawSource(p); + p.end(); + m_pbuffer->updateDynamicTexture(m_compositing_tex); + } + + painter->beginNativePainting(); // Needed when using the GL2 engine + glWidget()->makeCurrent(); // Needed when using the GL1 engine + glBindTexture(GL_TEXTURE_2D, m_compositing_tex); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(1.,1.,1.,1.); + glBegin(GL_QUADS); + { + glTexCoord2f(0, 1.0); + glVertex2f(0, 0); + + glTexCoord2f(x_fraction, 1.0); + glVertex2f(width(), 0); + + glTexCoord2f(x_fraction, 1.0-y_fraction); + glVertex2f(width(), height()); + + glTexCoord2f(0, 1.0-y_fraction); + glVertex2f(0, height()); + } + glEnd(); + glDisable(GL_TEXTURE_2D); + painter->endNativePainting(); // Needed when using the GL2 engine + } else +#endif + { + // using a QImage + if (m_buffer.size() != size()) { +#ifdef Q_WS_QWS + m_base_buffer = QPixmap(size()); + m_base_buffer.fill(Qt::transparent); +#else + m_buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied); + m_base_buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied); + + m_base_buffer.fill(0); +#endif + + QPainter p(&m_base_buffer); + + drawBase(p); + } + +#ifdef Q_WS_QWS + m_buffer = m_base_buffer; +#else + memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.byteCount()); +#endif + + { + QPainter p(&m_buffer); + drawSource(p); + } + +#ifdef Q_WS_QWS + painter->drawPixmap(0, 0, m_buffer); +#else + painter->drawImage(0, 0, m_buffer); +#endif + } +} + +void CompositionRenderer::mousePressEvent(QMouseEvent *e) +{ + setDescriptionEnabled(false); + + QRectF circle = rectangle_around(m_circle_pos); + + if (circle.contains(e->pos())) { + m_current_object = Circle; + m_offset = circle.center() - e->pos(); + } else { + m_current_object = NoObject; + } + if (m_animation_enabled) { + killTimer(m_animationTimer); + m_animationTimer = 0; + } +} + +void CompositionRenderer::mouseMoveEvent(QMouseEvent *e) +{ + if (m_current_object == Circle) setCirclePos(e->pos() + m_offset); +} + +void CompositionRenderer::mouseReleaseEvent(QMouseEvent *) +{ + m_current_object = NoObject; + + if (m_animation_enabled) { + Q_ASSERT(!m_animationTimer); + m_animationTimer = startTimer(animationInterval); + } +} + +void CompositionRenderer::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_animationTimer) + updateCirclePos(); +} + +void CompositionRenderer::setCirclePos(const QPointF &pos) +{ + const QRect oldRect = rectangle_around(m_circle_pos).toAlignedRect(); + m_circle_pos = pos; + const QRect newRect = rectangle_around(m_circle_pos).toAlignedRect(); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + if (usesOpenGL()) + update(); + else +#endif + update(oldRect | newRect); +} + diff --git a/demos/composition/composition.h b/demos/composition/composition.h new file mode 100644 index 0000000000..e1b5ed76b8 --- /dev/null +++ b/demos/composition/composition.h @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef COMPOSITION_H +#define COMPOSITION_H + +#include "arthurwidgets.h" + +#include <QPainter> +#include <QEvent> + +QT_FORWARD_DECLARE_CLASS(QPushButton) +QT_FORWARD_DECLARE_CLASS(QRadioButton) + +#ifdef QT_OPENGL_SUPPORT +#include <QtOpenGL> +#endif + +class CompositionWidget : public QWidget +{ + Q_OBJECT + +public: + CompositionWidget(QWidget *parent); + +public slots: +void nextMode(); + +private: + bool m_cycle_enabled; + + QRadioButton *rbClear; + QRadioButton *rbSource; + QRadioButton *rbDest; + QRadioButton *rbSourceOver; + QRadioButton *rbDestOver; + QRadioButton *rbSourceIn; + QRadioButton *rbDestIn; + QRadioButton *rbSourceOut; + QRadioButton *rbDestOut; + QRadioButton *rbSourceAtop; + QRadioButton *rbDestAtop; + QRadioButton *rbXor; + + QRadioButton *rbPlus; + QRadioButton *rbMultiply; + QRadioButton *rbScreen; + QRadioButton *rbOverlay; + QRadioButton *rbDarken; + QRadioButton *rbLighten; + QRadioButton *rbColorDodge; + QRadioButton *rbColorBurn; + QRadioButton *rbHardLight; + QRadioButton *rbSoftLight; + QRadioButton *rbDifference; + QRadioButton *rbExclusion; +}; + +class CompositionRenderer : public ArthurFrame +{ + Q_OBJECT + + enum ObjectType { NoObject, Circle, Rectangle, Image }; + + Q_PROPERTY(int circleColor READ circleColor WRITE setCircleColor) + Q_PROPERTY(int circleAlpha READ circleAlpha WRITE setCircleAlpha) + Q_PROPERTY(bool animation READ animationEnabled WRITE setAnimationEnabled) + +public: + CompositionRenderer(QWidget *parent); + + void paint(QPainter *); + + void setCirclePos(const QPointF &pos); + + QSize sizeHint() const { return QSize(500, 400); } + + bool animationEnabled() const { return m_animation_enabled; } + int circleColor() const { return m_circle_hue; } + int circleAlpha() const { return m_circle_alpha; } + +protected: + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void timerEvent(QTimerEvent *); + +public slots: + void setClearMode() { m_composition_mode = QPainter::CompositionMode_Clear; update(); } + void setSourceMode() { m_composition_mode = QPainter::CompositionMode_Source; update(); } + void setDestMode() { m_composition_mode = QPainter::CompositionMode_Destination; update(); } + void setSourceOverMode() { m_composition_mode = QPainter::CompositionMode_SourceOver; update(); } + void setDestOverMode() { m_composition_mode = QPainter::CompositionMode_DestinationOver; update(); } + void setSourceInMode() { m_composition_mode = QPainter::CompositionMode_SourceIn; update(); } + void setDestInMode() { m_composition_mode = QPainter::CompositionMode_DestinationIn; update(); } + void setSourceOutMode() { m_composition_mode = QPainter::CompositionMode_SourceOut; update(); } + void setDestOutMode() { m_composition_mode = QPainter::CompositionMode_DestinationOut; update(); } + void setSourceAtopMode() { m_composition_mode = QPainter::CompositionMode_SourceAtop; update(); } + void setDestAtopMode() { m_composition_mode = QPainter::CompositionMode_DestinationAtop; update(); } + void setXorMode() { m_composition_mode = QPainter::CompositionMode_Xor; update(); } + + void setPlusMode() { m_composition_mode = QPainter::CompositionMode_Plus; update(); } + void setMultiplyMode() { m_composition_mode = QPainter::CompositionMode_Multiply; update(); } + void setScreenMode() { m_composition_mode = QPainter::CompositionMode_Screen; update(); } + void setOverlayMode() { m_composition_mode = QPainter::CompositionMode_Overlay; update(); } + void setDarkenMode() { m_composition_mode = QPainter::CompositionMode_Darken; update(); } + void setLightenMode() { m_composition_mode = QPainter::CompositionMode_Lighten; update(); } + void setColorDodgeMode() { m_composition_mode = QPainter::CompositionMode_ColorDodge; update(); } + void setColorBurnMode() { m_composition_mode = QPainter::CompositionMode_ColorBurn; update(); } + void setHardLightMode() { m_composition_mode = QPainter::CompositionMode_HardLight; update(); } + void setSoftLightMode() { m_composition_mode = QPainter::CompositionMode_SoftLight; update(); } + void setDifferenceMode() { m_composition_mode = QPainter::CompositionMode_Difference; update(); } + void setExclusionMode() { m_composition_mode = QPainter::CompositionMode_Exclusion; update(); } + + void setCircleAlpha(int alpha) { m_circle_alpha = alpha; update(); } + void setCircleColor(int hue) { m_circle_hue = hue; update(); } + void setAnimationEnabled(bool enabled); + +private: + void updateCirclePos(); + void drawBase(QPainter &p); + void drawSource(QPainter &p); + + QPainter::CompositionMode m_composition_mode; + +#ifdef Q_WS_QWS + QPixmap m_image; + QPixmap m_buffer; + QPixmap m_base_buffer; +#else + QImage m_image; + QImage m_buffer; + QImage m_base_buffer; +#endif + + int m_circle_alpha; + int m_circle_hue; + + QPointF m_circle_pos; + QPointF m_offset; + + ObjectType m_current_object; + bool m_animation_enabled; + int m_animationTimer; + +#ifdef QT_OPENGL_SUPPORT + QGLPixelBuffer *m_pbuffer; + GLuint m_base_tex; + GLuint m_compositing_tex; + int m_pbuffer_size; // width==height==size of pbuffer + QSize m_previous_size; +#endif +}; + +#endif // COMPOSITION_H diff --git a/demos/composition/composition.html b/demos/composition/composition.html new file mode 100644 index 0000000000..1848ad8bd1 --- /dev/null +++ b/demos/composition/composition.html @@ -0,0 +1,23 @@ +<html> + +<h1>Demo for composition modes</h1> + +<p> + This demo shows some of the more advanced composition modes supported by Qt. +</p> + +<p> + The two most common forms of composition are <b>Source</b> and <b>SourceOver</b>. + <b>Source</b> is used to draw opaque objects onto a paint device. In this mode, + each pixel in the source replaces the corresponding pixel in the destination. + In <b>SourceOver</b> composition mode, the source object is transparent and is + drawn on top of the destination. +</p> + +<p> + In addition to these standard modes, Qt defines the complete set of composition + modes as defined by Thomas Porter and Tom Duff. See the <tt>QPainter</tt> documentation + for details. +</p> + +</html> diff --git a/demos/composition/composition.pro b/demos/composition/composition.pro new file mode 100644 index 0000000000..bb5cac5dea --- /dev/null +++ b/demos/composition/composition.pro @@ -0,0 +1,29 @@ +SOURCES += main.cpp composition.cpp +HEADERS += composition.h + +SHARED_FOLDER = ../shared + +include($$SHARED_FOLDER/shared.pri) + +RESOURCES += composition.qrc +contains(QT_CONFIG, opengl) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/composition +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.png *.jpg *.pro *.html +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/composition +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + +win32-msvc* { + QMAKE_CXXFLAGS += /Zm500 + QMAKE_CFLAGS += /Zm500 +} + +wince* { + DEPLOYMENT_PLUGIN += qjpeg +} diff --git a/demos/composition/composition.qrc b/demos/composition/composition.qrc new file mode 100644 index 0000000000..d02c397ee8 --- /dev/null +++ b/demos/composition/composition.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/composition"> + <file>composition.cpp</file> + <file>composition.html</file> + <file>flower.jpg</file> + <file>flower_alpha.jpg</file> +</qresource> +</RCC> diff --git a/demos/composition/flower.jpg b/demos/composition/flower.jpg Binary files differnew file mode 100644 index 0000000000..f8e022c98c --- /dev/null +++ b/demos/composition/flower.jpg diff --git a/demos/composition/flower_alpha.jpg b/demos/composition/flower_alpha.jpg Binary files differnew file mode 100644 index 0000000000..6a3c2a02ef --- /dev/null +++ b/demos/composition/flower_alpha.jpg diff --git a/demos/composition/main.cpp b/demos/composition/main.cpp new file mode 100644 index 0000000000..70eb0f31a9 --- /dev/null +++ b/demos/composition/main.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "composition.h" + +#include <QApplication> +#ifdef QT_OPENGL_SUPPORT +#include <QtOpenGL> +#endif + +int main(int argc, char **argv) +{ + // Q_INIT_RESOURCE(deform); + +#ifdef QT_OPENGL_SUPPORT + QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); +#endif + QApplication app(argc, argv); + + CompositionWidget compWidget(0); + QStyle *arthurStyle = new ArthurStyle(); + compWidget.setStyle(arthurStyle); + + QList<QWidget *> widgets = compWidget.findChildren<QWidget *>(); + foreach (QWidget *w, widgets) + w->setStyle(arthurStyle); + compWidget.show(); + + return app.exec(); +} diff --git a/demos/deform/deform.pro b/demos/deform/deform.pro new file mode 100644 index 0000000000..ee15d2cc3e --- /dev/null +++ b/demos/deform/deform.pro @@ -0,0 +1,24 @@ +SOURCES += main.cpp pathdeform.cpp +HEADERS += pathdeform.h + +SHARED_FOLDER = ../shared + +include($$SHARED_FOLDER/shared.pri) + +RESOURCES += deform.qrc + +contains(QT_CONFIG, opengl) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/deform +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.html +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/deform +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000A63D + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) +} diff --git a/demos/deform/deform.qrc b/demos/deform/deform.qrc new file mode 100644 index 0000000000..2e59ebcfc5 --- /dev/null +++ b/demos/deform/deform.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/deform"> + <file>pathdeform.cpp</file> + <file>pathdeform.html</file> +</qresource> +</RCC> diff --git a/demos/deform/main.cpp b/demos/deform/main.cpp new file mode 100644 index 0000000000..5ddae0dd49 --- /dev/null +++ b/demos/deform/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "pathdeform.h" + +#include <QApplication> +#include <QDebug> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(deform); + + QApplication app(argc, argv); + + bool smallScreen = QApplication::arguments().contains("-small-screen"); + + PathDeformWidget deformWidget(0, smallScreen); + + QStyle *arthurStyle = new ArthurStyle(); + deformWidget.setStyle(arthurStyle); + QList<QWidget *> widgets = deformWidget.findChildren<QWidget *>(); + foreach (QWidget *w, widgets) + w->setStyle(arthurStyle); + + if (smallScreen) + deformWidget.showFullScreen(); + else + deformWidget.show(); + +#ifdef QT_KEYPAD_NAVIGATION + QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); +#endif + return app.exec(); +} diff --git a/demos/deform/pathdeform.cpp b/demos/deform/pathdeform.cpp new file mode 100644 index 0000000000..1806438051 --- /dev/null +++ b/demos/deform/pathdeform.cpp @@ -0,0 +1,647 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "pathdeform.h" + +#include <QApplication> +#include <QtDebug> +#include <QMouseEvent> +#include <QTimerEvent> +#include <QLayout> +#include <QLineEdit> +#include <QPainter> +#include <QSlider> +#include <QLabel> +#include <QDesktopWidget> +#include <qmath.h> + +PathDeformControls::PathDeformControls(QWidget *parent, PathDeformRenderer* renderer, bool smallScreen) + : QWidget(parent) +{ + m_renderer = renderer; + + if (smallScreen) + layoutForSmallScreen(); + else + layoutForDesktop(); +} + + +void PathDeformControls::layoutForDesktop() +{ + QGroupBox* mainGroup = new QGroupBox(this); + mainGroup->setTitle(tr("Controls")); + + QGroupBox *radiusGroup = new QGroupBox(mainGroup); + radiusGroup->setTitle(tr("Lens Radius")); + QSlider *radiusSlider = new QSlider(Qt::Horizontal, radiusGroup); + radiusSlider->setRange(15, 150); + radiusSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QGroupBox *deformGroup = new QGroupBox(mainGroup); + deformGroup->setTitle(tr("Deformation")); + QSlider *deformSlider = new QSlider(Qt::Horizontal, deformGroup); + deformSlider->setRange(-100, 100); + deformSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QGroupBox *fontSizeGroup = new QGroupBox(mainGroup); + fontSizeGroup->setTitle(tr("Font Size")); + QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, fontSizeGroup); + fontSizeSlider->setRange(16, 200); + fontSizeSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QGroupBox *textGroup = new QGroupBox(mainGroup); + textGroup->setTitle(tr("Text")); + QLineEdit *textInput = new QLineEdit(textGroup); + + QPushButton *animateButton = new QPushButton(mainGroup); + animateButton->setText(tr("Animated")); + animateButton->setCheckable(true); + + QPushButton *showSourceButton = new QPushButton(mainGroup); + showSourceButton->setText(tr("Show Source")); + +#ifdef QT_OPENGL_SUPPORT + QPushButton *enableOpenGLButton = new QPushButton(mainGroup); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(true); + enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); + if (!QGLFormat::hasOpenGL()) + enableOpenGLButton->hide(); +#endif + + QPushButton *whatsThisButton = new QPushButton(mainGroup); + whatsThisButton->setText(tr("What's This?")); + whatsThisButton->setCheckable(true); + + + mainGroup->setFixedWidth(180); + + QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); + mainGroupLayout->addWidget(radiusGroup); + mainGroupLayout->addWidget(deformGroup); + mainGroupLayout->addWidget(fontSizeGroup); + mainGroupLayout->addWidget(textGroup); + mainGroupLayout->addWidget(animateButton); + mainGroupLayout->addStretch(1); +#ifdef QT_OPENGL_SUPPORT + mainGroupLayout->addWidget(enableOpenGLButton); +#endif + mainGroupLayout->addWidget(showSourceButton); + mainGroupLayout->addWidget(whatsThisButton); + + QVBoxLayout *radiusGroupLayout = new QVBoxLayout(radiusGroup); + radiusGroupLayout->addWidget(radiusSlider); + + QVBoxLayout *deformGroupLayout = new QVBoxLayout(deformGroup); + deformGroupLayout->addWidget(deformSlider); + + QVBoxLayout *fontSizeGroupLayout = new QVBoxLayout(fontSizeGroup); + fontSizeGroupLayout->addWidget(fontSizeSlider); + + QVBoxLayout *textGroupLayout = new QVBoxLayout(textGroup); + textGroupLayout->addWidget(textInput); + + QVBoxLayout * mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(mainGroup); + mainLayout->setMargin(0); + + connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int))); + connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int))); + connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int))); + connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool))); +#ifdef QT_OPENGL_SUPPORT + connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); +#endif + + connect(textInput, SIGNAL(textChanged(QString)), m_renderer, SLOT(setText(QString))); + connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)), + whatsThisButton, SLOT(setChecked(bool))); + connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool))); + connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource())); + + animateButton->animateClick(); + deformSlider->setValue(80); + fontSizeSlider->setValue(120); + radiusSlider->setValue(100); + textInput->setText(tr("Qt")); +} + +void PathDeformControls::layoutForSmallScreen() +{ + QGroupBox* mainGroup = new QGroupBox(this); + mainGroup->setTitle(tr("Controls")); + + QLabel *radiusLabel = new QLabel(mainGroup); + radiusLabel->setText(tr("Lens Radius:")); + QSlider *radiusSlider = new QSlider(Qt::Horizontal, mainGroup); + radiusSlider->setRange(15, 150); + radiusSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + QLabel *deformLabel = new QLabel(mainGroup); + deformLabel->setText(tr("Deformation:")); + QSlider *deformSlider = new QSlider(Qt::Horizontal, mainGroup); + deformSlider->setRange(-100, 100); + deformSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + QLabel *fontSizeLabel = new QLabel(mainGroup); + fontSizeLabel->setText(tr("Font Size:")); + QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, mainGroup); + fontSizeSlider->setRange(16, 200); + fontSizeSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + QPushButton *animateButton = new QPushButton(tr("Animated"), mainGroup); + animateButton->setCheckable(true); + +#ifdef QT_OPENGL_SUPPORT + QPushButton *enableOpenGLButton = new QPushButton(mainGroup); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(mainGroup); + enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); + if (!QGLFormat::hasOpenGL()) + enableOpenGLButton->hide(); +#endif + + QPushButton *quitButton = new QPushButton(tr("Quit"), mainGroup); + QPushButton *okButton = new QPushButton(tr("OK"), mainGroup); + + + QGridLayout *mainGroupLayout = new QGridLayout(mainGroup); + mainGroupLayout->setMargin(0); + mainGroupLayout->addWidget(radiusLabel, 0, 0, Qt::AlignRight); + mainGroupLayout->addWidget(radiusSlider, 0, 1); + mainGroupLayout->addWidget(deformLabel, 1, 0, Qt::AlignRight); + mainGroupLayout->addWidget(deformSlider, 1, 1); + mainGroupLayout->addWidget(fontSizeLabel, 2, 0, Qt::AlignRight); + mainGroupLayout->addWidget(fontSizeSlider, 2, 1); + mainGroupLayout->addWidget(animateButton, 3,0, 1,2); +#ifdef QT_OPENGL_SUPPORT + mainGroupLayout->addWidget(enableOpenGLButton, 4,0, 1,2); +#endif + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(mainGroup); + mainLayout->addStretch(1); + mainLayout->addWidget(okButton); + mainLayout->addWidget(quitButton); + + connect(quitButton, SIGNAL(clicked()), this, SLOT(emitQuitSignal())); + connect(okButton, SIGNAL(clicked()), this, SLOT(emitOkSignal())); + connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int))); + connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int))); + connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int))); + connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool))); +#ifdef QT_OPENGL_SUPPORT + connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); +#endif + + + animateButton->animateClick(); + deformSlider->setValue(80); + fontSizeSlider->setValue(120); + + QRect screen_size = QApplication::desktop()->screenGeometry(); + radiusSlider->setValue(qMin(screen_size.width(), screen_size.height())/5); + + m_renderer->setText(tr("Qt")); +} + + +void PathDeformControls::emitQuitSignal() +{ emit quitPressed(); } + +void PathDeformControls::emitOkSignal() +{ emit okPressed(); } + + +PathDeformWidget::PathDeformWidget(QWidget *parent, bool smallScreen) + : QWidget(parent) +{ + setWindowTitle(tr("Vector Deformation")); + + m_renderer = new PathDeformRenderer(this, smallScreen); + m_renderer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + // Layouts + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->addWidget(m_renderer); + + m_controls = new PathDeformControls(0, m_renderer, smallScreen); + m_controls->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + + if (!smallScreen) + mainLayout->addWidget(m_controls); + + m_renderer->loadSourceFile(":res/deform/pathdeform.cpp"); + m_renderer->loadDescription(":res/deform/pathdeform.html"); + m_renderer->setDescriptionEnabled(false); + + connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls())); + connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls())); + connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit())); +} + + +void PathDeformWidget::showControls() +{ + m_controls->showFullScreen(); +} + +void PathDeformWidget::hideControls() +{ + m_controls->hide(); +} + +void PathDeformWidget::setStyle( QStyle * style ) +{ + QWidget::setStyle(style); + if (m_controls != 0) + { + m_controls->setStyle(style); + + QList<QWidget *> widgets = m_controls->findChildren<QWidget *>(); + foreach (QWidget *w, widgets) + w->setStyle(style); + } +} + +static inline QRect circle_bounds(const QPointF ¢er, qreal radius, qreal compensation) +{ + return QRect(qRound(center.x() - radius - compensation), + qRound(center.y() - radius - compensation), + qRound((radius + compensation) * 2), + qRound((radius + compensation) * 2)); + +} + +const int LENS_EXTENT = 10; + +PathDeformRenderer::PathDeformRenderer(QWidget *widget, bool smallScreen) + : ArthurFrame(widget) +{ + m_radius = 100; + m_pos = QPointF(m_radius, m_radius); + m_direction = QPointF(1, 1); + m_fontSize = 24; + m_animated = true; + m_repaintTimer.start(25, this); + m_repaintTracker.start(); + m_intensity = 100; + m_smallScreen = smallScreen; + +// m_fpsTimer.start(1000, this); +// m_fpsCounter = 0; + + generateLensPixmap(); +} + +void PathDeformRenderer::setText(const QString &text) +{ + m_text = text; + + QFont f("times new roman,utopia"); + f.setStyleStrategy(QFont::ForceOutline); + f.setPointSize(m_fontSize); + f.setStyleHint(QFont::Times); + + QFontMetrics fm(f); + + m_paths.clear(); + m_pathBounds = QRect(); + + QPointF advance(0, 0); + + bool do_quick = true; + for (int i=0; i<text.size(); ++i) { + if (text.at(i).unicode() >= 0x4ff && text.at(i).unicode() <= 0x1e00) { + do_quick = false; + break; + } + } + + if (do_quick) { + for (int i=0; i<text.size(); ++i) { + QPainterPath path; + path.addText(advance, f, text.mid(i, 1)); + m_pathBounds |= path.boundingRect(); + m_paths << path; + advance += QPointF(fm.width(text.mid(i, 1)), 0); + } + } else { + QPainterPath path; + path.addText(advance, f, text); + m_pathBounds |= path.boundingRect(); + m_paths << path; + } + + for (int i=0; i<m_paths.size(); ++i) + m_paths[i] = m_paths[i] * QMatrix(1, 0, 0, 1, -m_pathBounds.x(), -m_pathBounds.y()); + + update(); +} + + +void PathDeformRenderer::generateLensPixmap() +{ + qreal rad = m_radius + LENS_EXTENT; + + QRect bounds = circle_bounds(QPointF(), rad, 0); + + QPainter painter; + + if (preferImage()) { + m_lens_image = QImage(bounds.size(), QImage::Format_ARGB32_Premultiplied); + m_lens_image.fill(0); + painter.begin(&m_lens_image); + } else { + m_lens_pixmap = QPixmap(bounds.size()); + m_lens_pixmap.fill(Qt::transparent); + painter.begin(&m_lens_pixmap); + } + + QRadialGradient gr(rad, rad, rad, 3 * rad / 5, 3 * rad / 5); + gr.setColorAt(0.0, QColor(255, 255, 255, 191)); + gr.setColorAt(0.2, QColor(255, 255, 127, 191)); + gr.setColorAt(0.9, QColor(150, 150, 200, 63)); + gr.setColorAt(0.95, QColor(0, 0, 0, 127)); + gr.setColorAt(1, QColor(0, 0, 0, 0)); + painter.setRenderHint(QPainter::Antialiasing); + painter.setBrush(gr); + painter.setPen(Qt::NoPen); + painter.drawEllipse(0, 0, bounds.width(), bounds.height()); +} + + +void PathDeformRenderer::setAnimated(bool animated) +{ + m_animated = animated; + + if (m_animated) { +// m_fpsTimer.start(1000, this); +// m_fpsCounter = 0; + m_repaintTimer.start(25, this); + m_repaintTracker.start(); + } else { +// m_fpsTimer.stop(); + m_repaintTimer.stop(); + } +} + +void PathDeformRenderer::timerEvent(QTimerEvent *e) +{ + + if (e->timerId() == m_repaintTimer.timerId()) { + + if (QLineF(QPointF(0,0), m_direction).length() > 1) + m_direction *= 0.995; + qreal time = m_repaintTracker.restart(); + + QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize); + + qreal dx = m_direction.x(); + qreal dy = m_direction.y(); + if (time > 0) { + dx = dx * time * .1; + dy = dy * time * .1; + } + + m_pos += QPointF(dx, dy); + + + + if (m_pos.x() - m_radius < 0) { + m_direction.setX(-m_direction.x()); + m_pos.setX(m_radius); + } else if (m_pos.x() + m_radius > width()) { + m_direction.setX(-m_direction.x()); + m_pos.setX(width() - m_radius); + } + + if (m_pos.y() - m_radius < 0) { + m_direction.setY(-m_direction.y()); + m_pos.setY(m_radius); + } else if (m_pos.y() + m_radius > height()) { + m_direction.setY(-m_direction.y()); + m_pos.setY(height() - m_radius); + } + +#ifdef QT_OPENGL_SUPPORT + if (usesOpenGL()) { + update(); + } else +#endif + { + QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize); + update(rectAfter | rectBefore); + QApplication::syncX(); + } + } +// else if (e->timerId() == m_fpsTimer.timerId()) { +// printf("fps: %d\n", m_fpsCounter); +// emit frameRate(m_fpsCounter); +// m_fpsCounter = 0; + +// } +} + +void PathDeformRenderer::mousePressEvent(QMouseEvent *e) +{ + setDescriptionEnabled(false); + + m_repaintTimer.stop(); + m_offset = QPointF(); + if (QLineF(m_pos, e->pos()).length() <= m_radius) + m_offset = m_pos - e->pos(); + + m_mousePress = e->pos(); + + // If we're not running in small screen mode, always assume we're dragging + m_mouseDrag = !m_smallScreen; + + mouseMoveEvent(e); +} + +void PathDeformRenderer::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->buttons() == Qt::NoButton && m_animated) { + m_repaintTimer.start(10, this); + m_repaintTracker.start(); + } + + if (!m_mouseDrag && m_smallScreen) + emit clicked(); +} + +void PathDeformRenderer::mouseMoveEvent(QMouseEvent *e) +{ + if (!m_mouseDrag && (QLineF(m_mousePress, e->pos()).length() > 25.0) ) + m_mouseDrag = true; + + if (m_mouseDrag) { + QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize); + if (e->type() == QEvent::MouseMove) { + QLineF line(m_pos, e->pos() + m_offset); + line.setLength(line.length() * .1); + QPointF dir(line.dx(), line.dy()); + m_direction = (m_direction + dir) / 2; + } + m_pos = e->pos() + m_offset; +#ifdef QT_OPENGL_SUPPORT + if (usesOpenGL()) { + update(); + } else +#endif + { + QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize); + update(rectBefore | rectAfter); + } + } +} + +QPainterPath PathDeformRenderer::lensDeform(const QPainterPath &source, const QPointF &offset) +{ + QPainterPath path; + path.addPath(source); + + qreal flip = m_intensity / qreal(100); + + for (int i=0; i<path.elementCount(); ++i) { + const QPainterPath::Element &e = path.elementAt(i); + + qreal x = e.x + offset.x(); + qreal y = e.y + offset.y(); + + qreal dx = x - m_pos.x(); + qreal dy = y - m_pos.y(); + qreal len = m_radius - qSqrt(dx * dx + dy * dy); + + if (len > 0) { + path.setElementPositionAt(i, + x + flip * dx * len / m_radius, + y + flip * dy * len / m_radius); + } else { + path.setElementPositionAt(i, x, y); + } + + } + + return path; +} + + +void PathDeformRenderer::paint(QPainter *painter) +{ + int pad_x = 5; + int pad_y = 5; + + int skip_x = qRound(m_pathBounds.width() + pad_x + m_fontSize/2); + int skip_y = qRound(m_pathBounds.height() + pad_y); + + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::black); + + QRectF clip(painter->clipPath().boundingRect()); + + int overlap = pad_x / 2; + + for (int start_y=0; start_y < height(); start_y += skip_y) { + + if (start_y > clip.bottom()) + break; + + int start_x = -overlap; + for (; start_x < width(); start_x += skip_x) { + + if (start_y + skip_y >= clip.top() && + start_x + skip_x >= clip.left() && + start_x <= clip.right()) { + for (int i=0; i<m_paths.size(); ++i) { + QPainterPath path = lensDeform(m_paths[i], QPointF(start_x, start_y)); + painter->drawPath(path); + } + } + } + overlap = skip_x - (start_x - width()); + + } + + if (preferImage()) { + painter->drawImage(m_pos - QPointF(m_radius + LENS_EXTENT, m_radius + LENS_EXTENT), + m_lens_image); + } else { + painter->drawPixmap(m_pos - QPointF(m_radius + LENS_EXTENT, m_radius + LENS_EXTENT), + m_lens_pixmap); + } +} + + + +void PathDeformRenderer::setRadius(int radius) +{ + qreal max = qMax(m_radius, (qreal)radius); + m_radius = radius; + generateLensPixmap(); + if (!m_animated || m_radius < max) { +#ifdef QT_OPENGL_SUPPORT + if (usesOpenGL()) { + update(); + } else +#endif + { + update(circle_bounds(m_pos, max, m_fontSize)); + } + } +} + +void PathDeformRenderer::setIntensity(int intensity) +{ + m_intensity = intensity; + if (!m_animated) { +#ifdef QT_OPENGL_SUPPORT + if (usesOpenGL()) { + update(); + } else +#endif + { + update(circle_bounds(m_pos, m_radius, m_fontSize)); + } + } +} diff --git a/demos/deform/pathdeform.h b/demos/deform/pathdeform.h new file mode 100644 index 0000000000..1305543b85 --- /dev/null +++ b/demos/deform/pathdeform.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef PATHDEFORM_H +#define PATHDEFORM_H + +#include "arthurwidgets.h" + +#include <QPainterPath> +#include <QBasicTimer> +#include <QDateTime> + +class PathDeformRenderer : public ArthurFrame +{ + Q_OBJECT + Q_PROPERTY(bool animated READ animated WRITE setAnimated) + Q_PROPERTY(int radius READ radius WRITE setRadius) + Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize) + Q_PROPERTY(int intensity READ intensity WRITE setIntensity) + Q_PROPERTY(QString text READ text WRITE setText) + +public: + PathDeformRenderer(QWidget *widget, bool smallScreen = false); + + void paint(QPainter *painter); + + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void timerEvent(QTimerEvent *e); + + QSize sizeHint() const { return QSize(600, 500); } + + bool animated() const { return m_animated; } + int radius() const { return int(m_radius); } + int fontSize() const { return m_fontSize; } + int intensity() const { return int(m_intensity); } + QString text() const { return m_text; } + +public slots: + void setRadius(int radius); + void setFontSize(int fontSize) { m_fontSize = fontSize; setText(m_text); } + void setText(const QString &text); + void setIntensity(int intensity); + + void setAnimated(bool animated); + +signals: + void clicked(); +// void frameRate(double fps); + +private: + void generateLensPixmap(); + QPainterPath lensDeform(const QPainterPath &source, const QPointF &offset); + + QBasicTimer m_repaintTimer; +// QBasicTimer m_fpsTimer; +// int m_fpsCounter; + QTime m_repaintTracker; + + QVector<QPainterPath> m_paths; + QVector<QPointF> m_advances; + QRectF m_pathBounds; + QString m_text; + + QPixmap m_lens_pixmap; + QImage m_lens_image; + + int m_fontSize; + bool m_animated; + + qreal m_intensity; + qreal m_radius; + QPointF m_pos; + QPointF m_offset; + QPointF m_direction; + QPointF m_mousePress; + bool m_mouseDrag; + bool m_smallScreen; +}; + +class PathDeformControls : public QWidget +{ + Q_OBJECT +public: + PathDeformControls(QWidget *parent, PathDeformRenderer* renderer, bool smallScreen); +signals: + void okPressed(); + void quitPressed(); +private: + PathDeformRenderer* m_renderer; + void layoutForDesktop(); + void layoutForSmallScreen(); +private slots: + void emitQuitSignal(); + void emitOkSignal(); +}; + +class PathDeformWidget : public QWidget +{ + Q_OBJECT +public: + PathDeformWidget(QWidget *parent, bool smallScreen); + void setStyle ( QStyle * style ); + +private: + PathDeformRenderer *m_renderer; + PathDeformControls *m_controls; + +private slots: + void showControls(); + void hideControls(); +}; + +#endif // PATHDEFORM_H diff --git a/demos/deform/pathdeform.html b/demos/deform/pathdeform.html new file mode 100644 index 0000000000..b3f63a8e0a --- /dev/null +++ b/demos/deform/pathdeform.html @@ -0,0 +1,24 @@ +<html> +<center> +<h2>Vector deformation</h2> +</center> + +<p>This demo shows how to use advanced vector techniques to draw text +using a <code>QPainterPath</code>.</p> + +<p>We define a vector deformation field in the shape of a lens and apply +this to all points in a path. This means that what is rendered on +screen is not pixel manipulation, but modified vector representations of +the glyphs themselves. This is visible from the high quality of the +antialiased edges for the deformed glyphs.</p> + +<p>To get a fairly complex path we allow the user to type in text and +convert the text to paths. This is done using the +<code>QPainterPath::addText()</code> function.</p> + +<p>The lens is drawn using a single call to <code>drawEllipse()</code>, using +a <code>QRadialGradient</code> to fill it with a specialized color table, +giving the effect of the Sun's reflection and a drop shadow. The lens +is cached as a pixmap for better performance.</p> + +</html> diff --git a/demos/demos.pro b/demos/demos.pro new file mode 100644 index 0000000000..f1d5b009a8 --- /dev/null +++ b/demos/demos.pro @@ -0,0 +1,116 @@ +TEMPLATE = subdirs + +!contains(QT_CONFIG, no-gui) { +SUBDIRS = \ + demos_shared \ + demos_deform \ + demos_gradients \ + demos_pathstroke \ + demos_affine \ + demos_composition \ + demos_books \ + demos_interview \ + demos_mainwindow \ + demos_spreadsheet \ + demos_textedit \ + demos_chip \ + demos_embeddeddialogs \ + demos_undo \ + demos_sub-attaq + +symbian: SUBDIRS = \ + demos_shared \ + demos_deform \ + demos_pathstroke + + +wince*: SUBDIRS = \ + demos_shared \ + demos_deform \ + demos_gradients \ + demos_pathstroke \ + demos_affine \ + demos_composition \ + demos_books \ + demos_interview \ + demos_mainwindow \ + demos_spreadsheet \ + demos_textedit \ + # demos_chip \ + demos_embeddeddialogs \ + demos_undo \ + demos_sub-attaq + +contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, opengles2):{ +SUBDIRS += demos_boxes +} + +mac* && !qpa: SUBDIRS += demos_macmainwindow +wince*|symbian|embedded|x11: SUBDIRS += demos_embedded + +!contains(QT_EDITION, Console):!cross_compile:!embedded:!wince*:SUBDIRS += demos_arthurplugin + +!cross_compile:{ +contains(QT_BUILD_PARTS, tools):{ +!wince*:SUBDIRS += demos_sqlbrowser demos_qtdemo +wince*:SUBDIRS += demos_sqlbrowser +} +} +contains(QT_CONFIG, phonon):!static:SUBDIRS += demos_mediaplayer +contains(QT_CONFIG, webkit):contains(QT_CONFIG, svg):!symbian:SUBDIRS += demos_browser +contains(QT_CONFIG, declarative):SUBDIRS += demos_declarative +contains(QT_CONFIG, multimedia):!static:SUBDIRS += demos_spectrum + +# install +sources.files = README *.pro +sources.path = $$[QT_INSTALL_DEMOS] +INSTALLS += sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + +demos_chip.subdir = chip +demos_embeddeddialogs.subdir = embeddeddialogs +demos_embedded.subdir = embedded +# Because of fluidlauncher +demos_embedded.depends = demos_deform demos_pathstroke +demos_shared.subdir = shared +demos_deform.subdir = deform +demos_gradients.subdir = gradients +demos_pathstroke.subdir = pathstroke +demos_affine.subdir = affine +demos_composition.subdir = composition +demos_books.subdir = books +demos_interview.subdir = interview +demos_macmainwindow.subdir = macmainwindow +demos_mainwindow.subdir = mainwindow +demos_spreadsheet.subdir = spreadsheet +demos_textedit.subdir = textedit +demos_arthurplugin.subdir = arthurplugin +demos_sqlbrowser.subdir = sqlbrowser +demos_undo.subdir = undo +demos_qtdemo.subdir = qtdemo +demos_mediaplayer.subdir = qmediaplayer +demos_declarative.subdir = declarative + +#mobile demos. Requires QtMobility sources. Not included in demo build +demos_guitartuner.subdir = mobile/guitartuner +demos_qcamera.subdir = mobile/qcamera +demos_qtbubblelevel.subdir = mobile/qtbubblelevel +demos_quickhit.subdir = mobile/quickhit + +demos_browser.subdir = browser + +demos_boxes.subdir = boxes +demos_sub-attaq.subdir = sub-attaq +demos_spectrum.subdir = spectrum + +#CONFIG += ordered +!ordered { + demos_affine.depends = demos_shared + demos_deform.depends = demos_shared + demos_gradients.depends = demos_shared + demos_composition.depends = demos_shared + demos_arthurplugin.depends = demos_shared + demos_pathstroke.depends = demos_shared +} +} diff --git a/demos/embedded/digiflip/digiflip.cpp b/demos/embedded/digiflip/digiflip.cpp new file mode 100644 index 0000000000..d756f21776 --- /dev/null +++ b/demos/embedded/digiflip/digiflip.cpp @@ -0,0 +1,425 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QtCore> +#include <QtGui> + +class Digits: public QWidget +{ + Q_OBJECT + +public: + + enum { + Slide, + Flip, + Rotate + }; + + Digits(QWidget *parent) + : QWidget(parent) + , m_number(0) + , m_transition(Slide) + { + setAttribute(Qt::WA_OpaquePaintEvent, true); + setAttribute(Qt::WA_NoSystemBackground, true); + connect(&m_animator, SIGNAL(frameChanged(int)), SLOT(update())); + m_animator.setFrameRange(0, 100); + m_animator.setDuration(600); + m_animator.setCurveShape(QTimeLine::EaseInOutCurve); + } + + void setTransition(int tr) { + m_transition = tr; + } + + int transition() const { + return m_transition; + } + + void setNumber(int n) { + if (m_number != n) { + m_number = qBound(0, n, 99); + preparePixmap(); + update(); + } + } + + void flipTo(int n) { + if (m_number != n) { + m_number = qBound(0, n, 99); + m_lastPixmap = m_pixmap; + preparePixmap(); + m_animator.stop(); + m_animator.start(); + } + } + +protected: + + void drawFrame(QPainter *p, const QRect &rect) { + p->setPen(Qt::NoPen); + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0.00, QColor(245, 245, 245)); + gradient.setColorAt(0.49, QColor(192, 192, 192)); + gradient.setColorAt(0.51, QColor(245, 245, 245)); + gradient.setColorAt(1.00, QColor(192, 192, 192)); + p->setBrush(gradient); + QRect r = rect; + p->drawRoundedRect(r, 15, 15, Qt::RelativeSize); + r.adjust(1, 4, -1, -4); + p->setPen(QColor(181, 181, 181)); + p->setBrush(Qt::NoBrush); + p->drawRoundedRect(r, 15, 15, Qt::RelativeSize); + p->setPen(QColor(159, 159, 159)); + int y = rect.top() + rect.height() / 2 - 1; + p->drawLine(rect.left(), y, rect.right(), y); + } + + QPixmap drawDigits(int n, const QRect &rect) { + + int scaleFactor = 2; +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + if (rect.height() > 240) + scaleFactor = 1; +#endif + + QString str = QString::number(n); + if (str.length() == 1) + str.prepend("0"); + + QFont font; + font.setFamily("Helvetica"); + int fontHeight = scaleFactor * 0.55 * rect.height(); + font.setPixelSize(fontHeight); + font.setBold(true); + + QPixmap pixmap(rect.size() * scaleFactor); + pixmap.fill(Qt::transparent); + + QLinearGradient gradient(QPoint(0, 0), QPoint(0, pixmap.height())); + gradient.setColorAt(0.00, QColor(128, 128, 128)); + gradient.setColorAt(0.49, QColor(64, 64, 64)); + gradient.setColorAt(0.51, QColor(128, 128, 128)); + gradient.setColorAt(1.00, QColor(16, 16, 16)); + + QPainter p; + p.begin(&pixmap); + p.setFont(font); + QPen pen; + pen.setBrush(QBrush(gradient)); + p.setPen(pen); + p.drawText(pixmap.rect(), Qt::AlignCenter, str); + p.end(); + + return pixmap.scaledToWidth(width(), Qt::SmoothTransformation); + } + + void preparePixmap() { + m_pixmap = QPixmap(size()); + m_pixmap.fill(Qt::transparent); + QPainter p; + p.begin(&m_pixmap); + p.drawPixmap(0, 0, drawDigits(m_number, rect())); + p.end(); + } + + void resizeEvent(QResizeEvent*) { + preparePixmap(); + update(); + } + + void paintStatic() { + QPainter p(this); + p.fillRect(rect(), Qt::black); + + int pad = width() / 10; + drawFrame(&p, rect().adjusted(pad, pad, -pad, -pad)); + p.drawPixmap(0, 0, m_pixmap); + } + + void paintSlide() { + QPainter p(this); + p.fillRect(rect(), Qt::black); + + int pad = width() / 10; + QRect fr = rect().adjusted(pad, pad, -pad, -pad); + drawFrame(&p, fr); + p.setClipRect(fr); + + int y = height() * m_animator.currentFrame() / 100; + p.drawPixmap(0, y, m_lastPixmap); + p.drawPixmap(0, y - height(), m_pixmap); + } + + void paintFlip() { + QPainter p(this); +#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WINCE_WM) + p.setRenderHint(QPainter::SmoothPixmapTransform, true); + p.setRenderHint(QPainter::Antialiasing, true); +#endif + p.fillRect(rect(), Qt::black); + + int hw = width() / 2; + int hh = height() / 2; + + // behind is the new pixmap + int pad = width() / 10; + QRect fr = rect().adjusted(pad, pad, -pad, -pad); + drawFrame(&p, fr); + p.drawPixmap(0, 0, m_pixmap); + + int index = m_animator.currentFrame(); + + if (index <= 50) { + + // the top part of the old pixmap is flipping + int angle = -180 * index / 100; + QTransform transform; + transform.translate(hw, hh); + transform.rotate(angle, Qt::XAxis); + p.setTransform(transform); + drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh)); + p.drawPixmap(-hw, -hh, m_lastPixmap); + + // the bottom part is still the old pixmap + p.resetTransform(); + p.setClipRect(0, hh, width(), hh); + drawFrame(&p, fr); + p.drawPixmap(0, 0, m_lastPixmap); + } else { + + p.setClipRect(0, hh, width(), hh); + + // the bottom part is still the old pixmap + drawFrame(&p, fr); + p.drawPixmap(0, 0, m_lastPixmap); + + // the bottom part of the new pixmap is flipping + int angle = 180 - 180 * m_animator.currentFrame() / 100; + QTransform transform; + transform.translate(hw, hh); + transform.rotate(angle, Qt::XAxis); + p.setTransform(transform); + drawFrame(&p, fr.adjusted(-hw, -hh, -hw, -hh)); + p.drawPixmap(-hw, -hh, m_pixmap); + + } + + } + + void paintRotate() { + QPainter p(this); + + int pad = width() / 10; + QRect fr = rect().adjusted(pad, pad, -pad, -pad); + drawFrame(&p, fr); + p.setClipRect(fr); + + int angle1 = -180 * m_animator.currentFrame() / 100; + int angle2 = 180 - 180 * m_animator.currentFrame() / 100; + int angle = (m_animator.currentFrame() <= 50) ? angle1 : angle2; + QPixmap pix = (m_animator.currentFrame() <= 50) ? m_lastPixmap : m_pixmap; + + QTransform transform; + transform.translate(width() / 2, height() / 2); + transform.rotate(angle, Qt::XAxis); + + p.setTransform(transform); + p.setRenderHint(QPainter::SmoothPixmapTransform, true); + p.drawPixmap(-width() / 2, -height() / 2, pix); + } + + void paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + if (m_animator.state() == QTimeLine::Running) { + if (m_transition == Slide) + paintSlide(); + if (m_transition == Flip) + paintFlip(); + if (m_transition == Rotate) + paintRotate(); + } else { + paintStatic(); + } + } + +private: + int m_number; + int m_transition; + QPixmap m_pixmap; + QPixmap m_lastPixmap; + QTimeLine m_animator; +}; + +class DigiFlip : public QMainWindow +{ + Q_OBJECT + +public: + DigiFlip(QWidget *parent = 0) + : QMainWindow(parent) + { + m_hour = new Digits(this); + m_hour->show(); + m_minute = new Digits(this); + m_minute->show(); + + QPalette pal = palette(); + pal.setColor(QPalette::Window, Qt::black); + setPalette(pal); + + m_ticker.start(1000, this); + QTime t = QTime::currentTime(); + m_hour->setNumber(t.hour()); + m_minute->setNumber(t.minute()); + updateTime(); + + QAction *slideAction = new QAction("&Slide", this); + QAction *flipAction = new QAction("&Flip", this); + QAction *rotateAction = new QAction("&Rotate", this); + connect(slideAction, SIGNAL(triggered()), SLOT(chooseSlide())); + connect(flipAction, SIGNAL(triggered()), SLOT(chooseFlip())); + connect(rotateAction, SIGNAL(triggered()), SLOT(chooseRotate())); +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + menuBar()->addAction(slideAction); + menuBar()->addAction(flipAction); + menuBar()->addAction(rotateAction); +#else + addAction(slideAction); + addAction(flipAction); + addAction(rotateAction); + setContextMenuPolicy(Qt::ActionsContextMenu); +#endif + } + + void updateTime() { + QTime t = QTime::currentTime(); + m_hour->flipTo(t.hour()); + m_minute->flipTo(t.minute()); + QString str = t.toString("hh:mm:ss"); + str.prepend(": "); + if (m_hour->transition() == Digits::Slide) + str.prepend("Slide"); + if (m_hour->transition() == Digits::Flip) + str.prepend("Flip"); + if (m_hour->transition() == Digits::Rotate) + str.prepend("Rotate"); + setWindowTitle(str); + } + + void switchTransition(int delta) { + int i = (m_hour->transition() + delta + 3) % 3; + m_hour->setTransition(i); + m_minute->setTransition(i); + updateTime(); + } + +protected: + void resizeEvent(QResizeEvent*) { + int digitsWidth = width() / 2; + int digitsHeight = digitsWidth * 1.2; + + int y = (height() - digitsHeight) / 3; + + m_hour->resize(digitsWidth, digitsHeight); + m_hour->move(0, y); + + m_minute->resize(digitsWidth, digitsHeight); + m_minute->move(width() / 2, y); + } + + void timerEvent(QTimerEvent*) { + updateTime(); + } + + void keyPressEvent(QKeyEvent *event) { + if (event->key() == Qt::Key_Right) { + switchTransition(1); + event->accept(); + } + if (event->key() == Qt::Key_Left) { + switchTransition(-1); + event->accept(); + } + } + +private slots: + void chooseSlide() { + m_hour->setTransition(0); + m_minute->setTransition(0); + updateTime(); + } + + void chooseFlip() { + m_hour->setTransition(1); + m_minute->setTransition(1); + updateTime(); + } + + void chooseRotate() { + m_hour->setTransition(2); + m_minute->setTransition(2); + updateTime(); + } + +private: + QBasicTimer m_ticker; + Digits *m_hour; + Digits *m_minute; +}; + +#include "digiflip.moc" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + DigiFlip time; +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + time.showMaximized(); +#else + time.resize(320, 240); + time.show(); +#endif + + return app.exec(); +} diff --git a/demos/embedded/digiflip/digiflip.pro b/demos/embedded/digiflip/digiflip.pro new file mode 100644 index 0000000000..73309db9e5 --- /dev/null +++ b/demos/embedded/digiflip/digiflip.pro @@ -0,0 +1,11 @@ +SOURCES = digiflip.cpp + +symbian { + TARGET.UID3 = 0xA000CF72 + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) +} + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/digiflip +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/digiflip +INSTALLS += target sources diff --git a/demos/embedded/embedded.pro b/demos/embedded/embedded.pro new file mode 100644 index 0000000000..efe3af5122 --- /dev/null +++ b/demos/embedded/embedded.pro @@ -0,0 +1,32 @@ +TEMPLATE = subdirs +SUBDIRS = styledemo raycasting flickable digiflip + +contains(QT_CONFIG, svg) { + SUBDIRS += embeddedsvgviewer \ + desktopservices + fluidlauncher.subdir = fluidlauncher + fluidlauncher.depends = styledemo desktopservices raycasting flickable digiflip lightmaps flightinfo + !vxworks:!qnx:SUBDIRS += fluidlauncher +} + +SUBDIRS += lightmaps +SUBDIRS += flightinfo +contains(QT_CONFIG, svg) { + SUBDIRS += weatherinfo +} + +contains(QT_CONFIG, webkit) { + SUBDIRS += anomaly +} + +contains(QT_CONFIG, declarative) { + # Qml demos require DEPLOYMENT support. Therefore, only symbian. + symbian:SUBDIRS += qmlcalculator qmlclocks qmldialcontrol qmleasing qmlflickr qmlphotoviewer qmltwitter +} + +# install +sources.files = README *.pro +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded +INSTALLS += sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/demos/embedded/flickable/flickable.cpp b/demos/embedded/flickable/flickable.cpp new file mode 100644 index 0000000000..e2d240d64f --- /dev/null +++ b/demos/embedded/flickable/flickable.cpp @@ -0,0 +1,284 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "flickable.h" + +#include <QtCore> +#include <QtGui> + +class FlickableTicker: QObject +{ +public: + FlickableTicker(Flickable *scroller) { + m_scroller = scroller; + } + + void start(int interval) { + if (!m_timer.isActive()) + m_timer.start(interval, this); + } + + void stop() { + m_timer.stop(); + } + +protected: + void timerEvent(QTimerEvent *event) { + Q_UNUSED(event); + m_scroller->tick(); + } + +private: + Flickable *m_scroller; + QBasicTimer m_timer; +}; + +class FlickablePrivate +{ +public: + typedef enum { + Steady, + Pressed, + ManualScroll, + AutoScroll, + Stop + } State; + + State state; + int threshold; + QPoint pressPos; + QPoint offset; + QPoint delta; + QPoint speed; + FlickableTicker *ticker; + QTime timeStamp; + QWidget *target; + QList<QEvent*> ignoreList; +}; + +Flickable::Flickable() +{ + d = new FlickablePrivate; + d->state = FlickablePrivate::Steady; + d->threshold = 10; + d->ticker = new FlickableTicker(this); + d->timeStamp = QTime::currentTime(); + d->target = 0; +} + +Flickable::~Flickable() +{ + delete d; +} + +void Flickable::setThreshold(int th) +{ + if (th >= 0) + d->threshold = th; +} + +int Flickable::threshold() const +{ + return d->threshold; +} + +void Flickable::setAcceptMouseClick(QWidget *target) +{ + d->target = target; +} + +static QPoint deaccelerate(const QPoint &speed, int a = 1, int max = 64) +{ + int x = qBound(-max, speed.x(), max); + int y = qBound(-max, speed.y(), max); + x = (x == 0) ? x : (x > 0) ? qMax(0, x - a) : qMin(0, x + a); + y = (y == 0) ? y : (y > 0) ? qMax(0, y - a) : qMin(0, y + a); + return QPoint(x, y); +} + +void Flickable::handleMousePress(QMouseEvent *event) +{ + event->ignore(); + + if (event->button() != Qt::LeftButton) + return; + + if (d->ignoreList.removeAll(event)) + return; + + switch (d->state) { + + case FlickablePrivate::Steady: + event->accept(); + d->state = FlickablePrivate::Pressed; + d->pressPos = event->pos(); + break; + + case FlickablePrivate::AutoScroll: + event->accept(); + d->state = FlickablePrivate::Stop; + d->speed = QPoint(0, 0); + d->pressPos = event->pos(); + d->offset = scrollOffset(); + d->ticker->stop(); + break; + + default: + break; + } +} + +void Flickable::handleMouseRelease(QMouseEvent *event) +{ + event->ignore(); + + if (event->button() != Qt::LeftButton) + return; + + if (d->ignoreList.removeAll(event)) + return; + + QPoint delta; + + switch (d->state) { + + case FlickablePrivate::Pressed: + event->accept(); + d->state = FlickablePrivate::Steady; + if (d->target) { + QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress, + d->pressPos, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); + QMouseEvent *event2 = new QMouseEvent(*event); + d->ignoreList << event1; + d->ignoreList << event2; + QApplication::postEvent(d->target, event1); + QApplication::postEvent(d->target, event2); + } + break; + + case FlickablePrivate::ManualScroll: + event->accept(); + delta = event->pos() - d->pressPos; + if (d->timeStamp.elapsed() > 100) { + d->timeStamp = QTime::currentTime(); + d->speed = delta - d->delta; + d->delta = delta; + } + d->offset = scrollOffset(); + d->pressPos = event->pos(); + if (d->speed == QPoint(0, 0)) { + d->state = FlickablePrivate::Steady; + } else { + d->speed /= 4; + d->state = FlickablePrivate::AutoScroll; + d->ticker->start(20); + } + break; + + case FlickablePrivate::Stop: + event->accept(); + d->state = FlickablePrivate::Steady; + d->offset = scrollOffset(); + break; + + default: + break; + } +} + +void Flickable::handleMouseMove(QMouseEvent *event) +{ + event->ignore(); + + if (!(event->buttons() & Qt::LeftButton)) + return; + + if (d->ignoreList.removeAll(event)) + return; + + QPoint delta; + + switch (d->state) { + + case FlickablePrivate::Pressed: + case FlickablePrivate::Stop: + delta = event->pos() - d->pressPos; + if (delta.x() > d->threshold || delta.x() < -d->threshold || + delta.y() > d->threshold || delta.y() < -d->threshold) { + d->timeStamp = QTime::currentTime(); + d->state = FlickablePrivate::ManualScroll; + d->delta = QPoint(0, 0); + d->pressPos = event->pos(); + event->accept(); + } + break; + + case FlickablePrivate::ManualScroll: + event->accept(); + delta = event->pos() - d->pressPos; + setScrollOffset(d->offset - delta); + if (d->timeStamp.elapsed() > 100) { + d->timeStamp = QTime::currentTime(); + d->speed = delta - d->delta; + d->delta = delta; + } + break; + + default: + break; + } +} + +void Flickable::tick() +{ + if (d->state == FlickablePrivate:: AutoScroll) { + d->speed = deaccelerate(d->speed); + setScrollOffset(d->offset - d->speed); + d->offset = scrollOffset(); + if (d->speed == QPoint(0, 0)) { + d->state = FlickablePrivate::Steady; + d->ticker->stop(); + } + } else { + d->ticker->stop(); + } +} diff --git a/demos/embedded/flickable/flickable.h b/demos/embedded/flickable/flickable.h new file mode 100644 index 0000000000..69c379c508 --- /dev/null +++ b/demos/embedded/flickable/flickable.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef FLICKABLE_H +#define FLICKABLE_H + +class QMouseEvent; +class QPoint; +class QWidget; + +class FlickableTicker; +class FlickablePrivate; + +class Flickable +{ +public: + + Flickable(); + virtual ~Flickable(); + + void setThreshold(int threshold); + int threshold() const; + + void setAcceptMouseClick(QWidget *target); + + void handleMousePress(QMouseEvent *event); + void handleMouseMove(QMouseEvent *event); + void handleMouseRelease(QMouseEvent *event); + +protected: + virtual QPoint scrollOffset() const = 0; + virtual void setScrollOffset(const QPoint &offset) = 0; + +private: + void tick(); + +private: + FlickablePrivate *d; + friend class FlickableTicker; +}; + +#endif // FLICKABLE_H diff --git a/demos/embedded/flickable/flickable.pro b/demos/embedded/flickable/flickable.pro new file mode 100644 index 0000000000..0fa15d939f --- /dev/null +++ b/demos/embedded/flickable/flickable.pro @@ -0,0 +1,12 @@ +SOURCES = flickable.cpp main.cpp +HEADERS = flickable.h + +symbian { + TARGET.UID3 = 0xA000CF73 + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) +} + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/flickable +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/flickable +INSTALLS += target sources diff --git a/demos/embedded/flickable/main.cpp b/demos/embedded/flickable/main.cpp new file mode 100644 index 0000000000..431a99bfa1 --- /dev/null +++ b/demos/embedded/flickable/main.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QtCore> +#include <QtGui> + +#include "flickable.h" + +// Returns a list of two-word color names +static QStringList colorPairs(int max) +{ + // capitalize the first letter + QStringList colors = QColor::colorNames(); + colors.removeAll("transparent"); + int num = colors.count(); + for (int c = 0; c < num; ++c) + colors[c] = colors[c][0].toUpper() + colors[c].mid(1); + + // combine two colors, e.g. "lime skyblue" + QStringList combinedColors; + for (int i = 0; i < num; ++i) + for (int j = 0; j < num; ++j) + combinedColors << QString("%1 %2").arg(colors[i]).arg(colors[j]); + + // randomize it + colors.clear(); + while (combinedColors.count()) { + int i = qrand() % combinedColors.count(); + colors << combinedColors[i]; + combinedColors.removeAt(i); + if (colors.count() == max) + break; + } + + return colors; +} + +class ColorList : public QWidget, public Flickable +{ + Q_OBJECT + +public: + ColorList(QWidget *parent = 0) + : QWidget(parent) { + m_offset = 0; + m_height = QFontMetrics(font()).height() + 5; + m_highlight = -1; + m_selected = -1; + + QStringList colors = colorPairs(999); + for (int i = 0; i < colors.count(); ++i) { + QString c = colors[i]; + QString str; + str.sprintf("%4d", i + 1); + m_colorNames << (str + " " + c); + + QStringList duet = c.split(' '); + m_firstColor << duet[0]; + m_secondColor << duet[1]; + } + + setAttribute(Qt::WA_OpaquePaintEvent, true); + setAttribute(Qt::WA_NoSystemBackground, true); + + setMouseTracking(true); + Flickable::setAcceptMouseClick(this); + } + +protected: + // reimplement from Flickable + virtual QPoint scrollOffset() const { + return QPoint(0, m_offset); + } + + // reimplement from Flickable + virtual void setScrollOffset(const QPoint &offset) { + int yy = offset.y(); + if (yy != m_offset) { + m_offset = qBound(0, yy, m_height * m_colorNames.count() - height()); + update(); + } + } + +protected: + void paintEvent(QPaintEvent *event) { + QPainter p(this); + p.fillRect(event->rect(), Qt::white); + int start = m_offset / m_height; + int y = start * m_height - m_offset; + if (m_offset <= 0) { + start = 0; + y = -m_offset; + } + int end = start + height() / m_height + 1; + if (end > m_colorNames.count() - 1) + end = m_colorNames.count() - 1; + for (int i = start; i <= end; ++i, y += m_height) { + + p.setBrush(Qt::NoBrush); + p.setPen(Qt::black); + if (i == m_highlight) { + p.fillRect(0, y, width(), m_height, QColor(0, 64, 128)); + p.setPen(Qt::white); + } + if (i == m_selected) { + p.fillRect(0, y, width(), m_height, QColor(0, 128, 240)); + p.setPen(Qt::white); + } + + p.drawText(m_height + 2, y, width(), m_height, Qt::AlignVCenter, m_colorNames[i]); + + p.setPen(Qt::NoPen); + p.setBrush(m_firstColor[i]); + p.drawRect(1, y + 1, m_height - 2, m_height - 2); + p.setBrush(m_secondColor[i]); + p.drawRect(5, y + 5, m_height - 11, m_height - 11); + } + p.end(); + } + + void keyReleaseEvent(QKeyEvent *event) { + if (event->key() == Qt::Key_Down) { + m_offset += 20; + event->accept(); + update(); + return; + } + if (event->key() == Qt::Key_Up) { + m_offset -= 20; + event->accept(); + update(); + return; + } + } + + void mousePressEvent(QMouseEvent *event) { + Flickable::handleMousePress(event); + if (event->isAccepted()) + return; + + if (event->button() == Qt::LeftButton) { + int y = event->pos().y() + m_offset; + int i = y / m_height; + if (i != m_highlight) { + m_highlight = i; + m_selected = -1; + update(); + } + event->accept(); + } + } + + void mouseMoveEvent(QMouseEvent *event) { + Flickable::handleMouseMove(event); + } + + void mouseReleaseEvent(QMouseEvent *event) { + Flickable::handleMouseRelease(event); + if (event->isAccepted()) + return; + + if (event->button() == Qt::LeftButton) { + m_selected = m_highlight; + event->accept(); + update(); + } + } + +private: + int m_offset; + int m_height; + int m_highlight; + int m_selected; + QStringList m_colorNames; + QList<QColor> m_firstColor; + QList<QColor> m_secondColor; +}; + +#include "main.moc" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + ColorList list; + list.setWindowTitle("Kinetic Scrolling"); +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + list.showMaximized(); +#else + list.resize(320, 320); + list.show(); +#endif + + return app.exec(); +} diff --git a/demos/embedded/flightinfo/aircraft.png b/demos/embedded/flightinfo/aircraft.png Binary files differnew file mode 100644 index 0000000000..2312bcc9f0 --- /dev/null +++ b/demos/embedded/flightinfo/aircraft.png diff --git a/demos/embedded/flightinfo/flightinfo.cpp b/demos/embedded/flightinfo/flightinfo.cpp new file mode 100644 index 0000000000..6f7c039973 --- /dev/null +++ b/demos/embedded/flightinfo/flightinfo.cpp @@ -0,0 +1,399 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QtCore> +#include <QtGui> +#include <QtNetwork> + +#include "ui_form.h" + +#define FLIGHTVIEW_URL "http://mobile.flightview.com/TrackByFlight.aspx" +#define FLIGHTVIEW_RANDOM "http://mobile.flightview.com/TrackSampleFlight.aspx" + +// strips all invalid constructs that might trip QXmlStreamReader +static QString sanitized(const QString &xml) +{ + QString data = xml; + + // anything up to the html tag + int i = data.indexOf("<html"); + if (i > 0) + data.remove(0, i - 1); + + // everything inside the head tag + i = data.indexOf("<head"); + if (i > 0) + data.remove(i, data.indexOf("</head>") - i + 7); + + // invalid link for JavaScript code + while (true) { + i = data.indexOf("onclick=\"gotoUrl("); + if (i < 0) + break; + data.remove(i, data.indexOf('\"', i + 9) - i + 1); + } + + // all inline frames + while (true) { + i = data.indexOf("<iframe"); + if (i < 0) + break; + data.remove(i, data.indexOf("</iframe>") - i + 8); + } + + // entities + data.remove(" "); + data.remove("©"); + + return data; +} + +class FlightInfo : public QMainWindow +{ + Q_OBJECT + +private: + + Ui_Form ui; + QUrl m_url; + QDate m_searchDate; + QPixmap m_map; + QNetworkAccessManager m_manager; + QList<QNetworkReply *> mapReplies; + +public: + + FlightInfo(QMainWindow *parent = 0): QMainWindow(parent) { + + QWidget *w = new QWidget(this); + ui.setupUi(w); + setCentralWidget(w); + + ui.searchBar->hide(); + ui.infoBox->hide(); + connect(ui.searchButton, SIGNAL(clicked()), SLOT(startSearch())); + connect(ui.flightEdit, SIGNAL(returnPressed()), SLOT(startSearch())); + + setWindowTitle("Flight Info"); + + // Rendered from the public-domain vectorized aircraft + // http://openclipart.org/media/people/Jarno + m_map = QPixmap(":/aircraft.png"); + + QAction *searchTodayAction = new QAction("Today's Flight", this); + QAction *searchYesterdayAction = new QAction("Yesterday's Flight", this); + QAction *randomAction = new QAction("Random Flight", this); + connect(searchTodayAction, SIGNAL(triggered()), SLOT(today())); + connect(searchYesterdayAction, SIGNAL(triggered()), SLOT(yesterday())); + connect(randomAction, SIGNAL(triggered()), SLOT(randomFlight())); + connect(&m_manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(handleNetworkData(QNetworkReply*))); +#if defined(Q_OS_SYMBIAN) + menuBar()->addAction(searchTodayAction); + menuBar()->addAction(searchYesterdayAction); + menuBar()->addAction(randomAction); +#else + addAction(searchTodayAction); + addAction(searchYesterdayAction); + addAction(randomAction); + setContextMenuPolicy(Qt::ActionsContextMenu); +#endif + } + +private slots: + + void handleNetworkData(QNetworkReply *networkReply) { + if (!networkReply->error()) { + if (!mapReplies.contains(networkReply)) { + // Assume UTF-8 encoded + QByteArray data = networkReply->readAll(); + QString xml = QString::fromUtf8(data); + digest(xml); + } else { + mapReplies.removeOne(networkReply); + m_map.loadFromData(networkReply->readAll()); + update(); + } + } + networkReply->deleteLater(); + } + + void today() { + QDateTime timestamp = QDateTime::currentDateTime(); + m_searchDate = timestamp.date(); + searchFlight(); + } + + void yesterday() { + QDateTime timestamp = QDateTime::currentDateTime(); + timestamp = timestamp.addDays(-1); + m_searchDate = timestamp.date(); + searchFlight(); + } + + void searchFlight() { + ui.searchBar->show(); + ui.infoBox->hide(); + ui.flightStatus->hide(); + ui.flightName->setText("Enter flight number"); + ui.flightEdit->setFocus(); +#ifdef QT_KEYPAD_NAVIGATION + ui.flightEdit->setEditFocus(true); +#endif + m_map = QPixmap(); + update(); + } + + void startSearch() { + ui.searchBar->hide(); + QString flight = ui.flightEdit->text().simplified(); + if (!flight.isEmpty()) + request(flight, m_searchDate); + } + + void randomFlight() { + request(QString(), QDate::currentDate()); + } + +public slots: + + void request(const QString &flightCode, const QDate &date) { + + setWindowTitle("Loading..."); + + QString code = flightCode.simplified(); + QString airlineCode = code.left(2).toUpper(); + QString flightNumber = code.mid(2, code.length()); + + ui.flightName->setText("Searching for " + code); + + m_url = QUrl(FLIGHTVIEW_URL); + m_url.addEncodedQueryItem("view", "detail"); + m_url.addEncodedQueryItem("al", QUrl::toPercentEncoding(airlineCode)); + m_url.addEncodedQueryItem("fn", QUrl::toPercentEncoding(flightNumber)); + m_url.addEncodedQueryItem("dpdat", QUrl::toPercentEncoding(date.toString("yyyyMMdd"))); + + if (code.isEmpty()) { + // random flight as sample + m_url = QUrl(FLIGHTVIEW_RANDOM); + ui.flightName->setText("Getting a random flight..."); + } + + m_manager.get(QNetworkRequest(m_url)); + } + + +private: + + void digest(const QString &content) { + + setWindowTitle("Flight Info"); + QString data = sanitized(content); + + // do we only get the flight list? + // we grab the first leg in the flight list + // then fetch another URL for the real flight info + int i = data.indexOf("a href=\"?view=detail"); + if (i > 0) { + QString href = data.mid(i, data.indexOf('\"', i + 8) - i + 1); + QRegExp regex("dpap=([A-Za-z0-9]+)"); + regex.indexIn(href); + QString airport = regex.cap(1); + m_url.addEncodedQueryItem("dpap", QUrl::toPercentEncoding(airport)); + m_manager.get(QNetworkRequest(m_url)); + return; + } + + QXmlStreamReader xml(data); + bool inFlightName = false; + bool inFlightStatus = false; + bool inFlightMap = false; + bool inFieldName = false; + bool inFieldValue = false; + + QString flightName; + QString flightStatus; + QStringList fieldNames; + QStringList fieldValues; + + while (!xml.atEnd()) { + xml.readNext(); + + if (xml.tokenType() == QXmlStreamReader::StartElement) { + QStringRef className = xml.attributes().value("class"); + inFlightName |= xml.name() == "h1"; + inFlightStatus |= className == "FlightDetailHeaderStatus"; + inFlightMap |= className == "flightMap"; + if (xml.name() == "td" && !className.isEmpty()) { + QString cn = className.toString(); + if (cn.contains("fieldTitle")) { + inFieldName = true; + fieldNames += QString(); + fieldValues += QString(); + } + if (cn.contains("fieldValue")) + inFieldValue = true; + } + if (xml.name() == "img" && inFlightMap) { + QString src = xml.attributes().value("src").toString(); + src.prepend("http://mobile.flightview.com/"); + QUrl url = QUrl::fromPercentEncoding(src.toAscii()); + mapReplies.append(m_manager.get(QNetworkRequest(url))); + } + } + + if (xml.tokenType() == QXmlStreamReader::EndElement) { + inFlightName &= xml.name() != "h1"; + inFlightStatus &= xml.name() != "div"; + inFlightMap &= xml.name() != "div"; + inFieldName &= xml.name() != "td"; + inFieldValue &= xml.name() != "td"; + } + + if (xml.tokenType() == QXmlStreamReader::Characters) { + if (inFlightName) + flightName += xml.text(); + if (inFlightStatus) + flightStatus += xml.text(); + if (inFieldName) + fieldNames.last() += xml.text(); + if (inFieldValue) + fieldValues.last() += xml.text(); + } + } + + if (fieldNames.isEmpty()) { + QString code = ui.flightEdit->text().simplified().left(10); + QString msg = QString("Flight %1 is not found").arg(code); + ui.flightName->setText(msg); + return; + } + + ui.flightName->setText(flightName); + flightStatus.remove("Status: "); + ui.flightStatus->setText(flightStatus); + ui.flightStatus->show(); + + QStringList whiteList; + whiteList << "Departure"; + whiteList << "Arrival"; + whiteList << "Scheduled"; + whiteList << "Takeoff"; + whiteList << "Estimated"; + whiteList << "Term-Gate"; + + QString text; + text = QString("<table width=%1>").arg(width() - 25); + for (int i = 0; i < fieldNames.count(); i++) { + QString fn = fieldNames[i].simplified(); + if (fn.endsWith(':')) + fn = fn.left(fn.length() - 1); + if (!whiteList.contains(fn)) + continue; + + QString fv = fieldValues[i].simplified(); + bool special = false; + special |= fn.startsWith("Departure"); + special |= fn.startsWith("Arrival"); + text += "<tr>"; + if (special) { + text += "<td align=center colspan=2>"; + text += "<b><font size=+1>" + fv + "</font></b>"; + text += "</td>"; + } else { + text += "<td align=right>"; + text += fn; + text += " : "; + text += " "; + text += "</td>"; + text += "<td>"; + text += fv; + text += "</td>"; + } + text += "</tr>"; + } + text += "</table>"; + ui.detailedInfo->setText(text); + ui.infoBox->show(); + } + + void resizeEvent(QResizeEvent *event) { + Q_UNUSED(event); + ui.detailedInfo->setMaximumWidth(width() - 25); + } + + void paintEvent(QPaintEvent *event) { + QMainWindow::paintEvent(event); + QPainter p(this); + p.fillRect(rect(), QColor(131, 171, 210)); + if (!m_map.isNull()) { + int x = (width() - m_map.width()) / 2; + int space = ui.infoBox->pos().y(); + if (!ui.infoBox->isVisible()) + space = height(); + int top = ui.titleBox->height(); + int y = qMax(top, (space - m_map.height()) / 2); + p.drawPixmap(x, y, m_map); + } + p.end(); + } + +}; + + +#include "flightinfo.moc" + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(flightinfo); + + QApplication app(argc, argv); + + FlightInfo w; +#if defined(Q_OS_SYMBIAN) + w.showMaximized(); +#else + w.resize(360, 504); + w.show(); +#endif + + return app.exec(); +} diff --git a/demos/embedded/flightinfo/flightinfo.pro b/demos/embedded/flightinfo/flightinfo.pro new file mode 100644 index 0000000000..c015fdf0af --- /dev/null +++ b/demos/embedded/flightinfo/flightinfo.pro @@ -0,0 +1,17 @@ +TEMPLATE = app +TARGET = flightinfo +SOURCES = flightinfo.cpp +FORMS += form.ui +RESOURCES = flightinfo.qrc +QT += network + +symbian { + TARGET.UID3 = 0xA000CF74 + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + TARGET.CAPABILITY = NetworkServices +} + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/flightinfo +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/flightinfo +INSTALLS += target sources diff --git a/demos/embedded/flightinfo/flightinfo.qrc b/demos/embedded/flightinfo/flightinfo.qrc new file mode 100644 index 0000000000..babea7e0cb --- /dev/null +++ b/demos/embedded/flightinfo/flightinfo.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/" > + <file>aircraft.png</file> + </qresource> +</RCC> diff --git a/demos/embedded/flightinfo/form.ui b/demos/embedded/flightinfo/form.ui new file mode 100644 index 0000000000..3a24c758a6 --- /dev/null +++ b/demos/embedded/flightinfo/form.ui @@ -0,0 +1,226 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>220</width> + <height>171</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="titleBox"> + <property name="styleSheet"> + <string>QFrame { +background-color: #45629a; +} + +QLabel { +color: white; +}</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>4</number> + </property> + <item> + <widget class="QLabel" name="flightName"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Powered by FlightView</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="flightStatus"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string>background-color: white; +color: #45629a;</string> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="text"> + <string>Ready</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="margin"> + <number>4</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="searchBar"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="margin"> + <number>5</number> + </property> + <item> + <widget class="QLineEdit" name="flightEdit"> + <property name="styleSheet"> + <string>color: black; +border: 1px solid black; +background: white; +selection-background-color: lightgray;</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="searchButton"> + <property name="styleSheet"> + <string>color: rgb(255, 255, 255); +background-color: rgb(85, 85, 255); +padding: 2px; +border: 2px solid rgb(0, 0, 127);</string> + </property> + <property name="text"> + <string>Search</string> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>58</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QFrame" name="infoBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="styleSheet"> + <string>QFrame { border: 2px solid white; +border-radius: 10px; +margin: 5px; +background-color: rgba(69, 98, 154, 192); }</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>5</number> + </property> + <item> + <widget class="QLabel" name="detailedInfo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="styleSheet"> + <string>color: white; +border: none; +background-color: none;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::NoTextInteraction</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/demos/embedded/lightmaps/lightmaps.cpp b/demos/embedded/lightmaps/lightmaps.cpp new file mode 100644 index 0000000000..8e64e7370c --- /dev/null +++ b/demos/embedded/lightmaps/lightmaps.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QtCore> +#include <QtGui> +#include <QtNetwork> + +#include <math.h> + +#include "lightmaps.h" +#include "slippymap.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// how long (milliseconds) the user need to hold (after a tap on the screen) +// before triggering the magnifying glass feature +// 701, a prime number, is the sum of 229, 233, 239 +// (all three are also prime numbers, consecutive!) +#define HOLD_TIME 701 + +// maximum size of the magnifier +// Hint: see above to find why I picked this one :) +#define MAX_MAGNIFIER 229 + +LightMaps::LightMaps(QWidget *parent) + : QWidget(parent), pressed(false), snapped(false), zoomed(false), + invert(false) +{ + m_normalMap = new SlippyMap(this); + m_largeMap = new SlippyMap(this); + connect(m_normalMap, SIGNAL(updated(QRect)), SLOT(updateMap(QRect))); + connect(m_largeMap, SIGNAL(updated(QRect)), SLOT(update())); +} + +void LightMaps::setCenter(qreal lat, qreal lng) +{ + m_normalMap->latitude = lat; + m_normalMap->longitude = lng; + m_normalMap->invalidate(); + m_largeMap->latitude = lat; + m_largeMap->longitude = lng; + m_largeMap->invalidate(); +} + +void LightMaps::toggleNightMode() +{ + invert = !invert; + update(); +} + +void LightMaps::updateMap(const QRect &r) +{ + update(r); +} + +void LightMaps::activateZoom() +{ + zoomed = true; + tapTimer.stop(); + m_largeMap->zoom = m_normalMap->zoom + 1; + m_largeMap->width = m_normalMap->width * 2; + m_largeMap->height = m_normalMap->height * 2; + m_largeMap->latitude = m_normalMap->latitude; + m_largeMap->longitude = m_normalMap->longitude; + m_largeMap->invalidate(); + update(); +} + +void LightMaps::resizeEvent(QResizeEvent *) +{ + m_normalMap->width = width(); + m_normalMap->height = height(); + m_normalMap->invalidate(); + m_largeMap->width = m_normalMap->width * 2; + m_largeMap->height = m_normalMap->height * 2; + m_largeMap->invalidate(); +} + +void LightMaps::paintEvent(QPaintEvent *event) +{ + QPainter p; + p.begin(this); + m_normalMap->render(&p, event->rect()); + p.setPen(Qt::black); +#if defined(Q_OS_SYMBIAN) + QFont font = p.font(); + font.setPixelSize(13); + p.setFont(font); +#endif + p.drawText(rect(), Qt::AlignBottom | Qt::TextWordWrap, + "Map data CCBYSA 2009 OpenStreetMap.org contributors"); + p.end(); + + if (zoomed) { + int dim = qMin(width(), height()); + int magnifierSize = qMin(MAX_MAGNIFIER, dim * 2 / 3); + int radius = magnifierSize / 2; + int ring = radius - 15; + QSize box = QSize(magnifierSize, magnifierSize); + + // reupdate our mask + if (maskPixmap.size() != box) { + maskPixmap = QPixmap(box); + maskPixmap.fill(Qt::transparent); + + QRadialGradient g; + g.setCenter(radius, radius); + g.setFocalPoint(radius, radius); + g.setRadius(radius); + g.setColorAt(1.0, QColor(255, 255, 255, 0)); + g.setColorAt(0.5, QColor(128, 128, 128, 255)); + + QPainter mask(&maskPixmap); + mask.setRenderHint(QPainter::Antialiasing); + mask.setCompositionMode(QPainter::CompositionMode_Source); + mask.setBrush(g); + mask.setPen(Qt::NoPen); + mask.drawRect(maskPixmap.rect()); + mask.setBrush(QColor(Qt::transparent)); + mask.drawEllipse(g.center(), ring, ring); + mask.end(); + } + + QPoint center = dragPos - QPoint(0, radius); + center = center + QPoint(0, radius / 2); + QPoint corner = center - QPoint(radius, radius); + + QPoint xy = center * 2 - QPoint(radius, radius); + + // only set the dimension to the magnified portion + if (zoomPixmap.size() != box) { + zoomPixmap = QPixmap(box); + zoomPixmap.fill(Qt::lightGray); + } + if (true) { + QPainter p(&zoomPixmap); + p.translate(-xy); + m_largeMap->render(&p, QRect(xy, box)); + p.end(); + } + + QPainterPath clipPath; + clipPath.addEllipse(center, ring, ring); + + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + p.setClipPath(clipPath); + p.drawPixmap(corner, zoomPixmap); + p.setClipping(false); + p.drawPixmap(corner, maskPixmap); + p.setPen(Qt::gray); + p.drawPath(clipPath); + } + if (invert) { + QPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_Difference); + p.fillRect(event->rect(), Qt::white); + p.end(); + } +} + +void LightMaps::timerEvent(QTimerEvent *) +{ + if (!zoomed) + activateZoom(); + update(); +} + +void LightMaps::mousePressEvent(QMouseEvent *event) +{ + if (event->buttons() != Qt::LeftButton) + return; + pressed = snapped = true; + pressPos = dragPos = event->pos(); + tapTimer.stop(); + tapTimer.start(HOLD_TIME, this); +} + +void LightMaps::mouseMoveEvent(QMouseEvent *event) +{ + if (!event->buttons()) + return; + if (!zoomed) { + if (!pressed || !snapped) { + QPoint delta = event->pos() - pressPos; + pressPos = event->pos(); + m_normalMap->pan(delta); + return; + } else { + const int threshold = 10; + QPoint delta = event->pos() - pressPos; + if (snapped) { + snapped &= delta.x() < threshold; + snapped &= delta.y() < threshold; + snapped &= delta.x() > -threshold; + snapped &= delta.y() > -threshold; + } + if (!snapped) + tapTimer.stop(); + } + } else { + dragPos = event->pos(); + update(); + } +} + +void LightMaps::mouseReleaseEvent(QMouseEvent *) +{ + zoomed = false; + update(); +} + +void LightMaps::keyPressEvent(QKeyEvent *event) +{ + if (!zoomed) { + if (event->key() == Qt::Key_Left) + m_normalMap->pan(QPoint(20, 0)); + if (event->key() == Qt::Key_Right) + m_normalMap->pan(QPoint(-20, 0)); + if (event->key() == Qt::Key_Up) + m_normalMap->pan(QPoint(0, 20)); + if (event->key() == Qt::Key_Down) + m_normalMap->pan(QPoint(0, -20)); + if (event->key() == Qt::Key_Z || event->key() == Qt::Key_Select) { + dragPos = QPoint(width() / 2, height() / 2); + activateZoom(); + } + } else { + if (event->key() == Qt::Key_Z || event->key() == Qt::Key_Select) { + zoomed = false; + update(); + } + QPoint delta(0, 0); + if (event->key() == Qt::Key_Left) + delta = QPoint(-15, 0); + if (event->key() == Qt::Key_Right) + delta = QPoint(15, 0); + if (event->key() == Qt::Key_Up) + delta = QPoint(0, -15); + if (event->key() == Qt::Key_Down) + delta = QPoint(0, 15); + if (delta != QPoint(0, 0)) { + dragPos += delta; + update(); + } + } +} diff --git a/demos/embedded/lightmaps/lightmaps.h b/demos/embedded/lightmaps/lightmaps.h new file mode 100644 index 0000000000..42a80c9f05 --- /dev/null +++ b/demos/embedded/lightmaps/lightmaps.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef LIGHTMAPS_H +#define LIGHTMAPS_H + +#include <QBasicTimer> +#include <QWidget> + +class SlippyMap; + +class LightMaps: public QWidget +{ + Q_OBJECT + +public: + LightMaps(QWidget *parent = 0); + void setCenter(qreal lat, qreal lng); + +public slots: + void toggleNightMode(); + +protected: + void activateZoom(); + void resizeEvent(QResizeEvent *); + void paintEvent(QPaintEvent *event); + void timerEvent(QTimerEvent *); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *); + void keyPressEvent(QKeyEvent *event); + +private slots: + void updateMap(const QRect &r); + +private: + SlippyMap *m_normalMap; + SlippyMap *m_largeMap; + bool pressed; + bool snapped; + QPoint pressPos; + QPoint dragPos; + QBasicTimer tapTimer; + bool zoomed; + QPixmap zoomPixmap; + QPixmap maskPixmap; + bool invert; +}; + +#endif
\ No newline at end of file diff --git a/demos/embedded/lightmaps/lightmaps.pro b/demos/embedded/lightmaps/lightmaps.pro new file mode 100644 index 0000000000..a792e60709 --- /dev/null +++ b/demos/embedded/lightmaps/lightmaps.pro @@ -0,0 +1,21 @@ +TEMPLATE = app +HEADERS = lightmaps.h \ + mapzoom.h \ + slippymap.h +SOURCES = lightmaps.cpp \ + main.cpp \ + mapzoom.cpp \ + slippymap.cpp +QT += network + +symbian { + TARGET.UID3 = 0xA000CF75 + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + TARGET.CAPABILITY = NetworkServices + TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 +} + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/lightmaps +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/lightmaps +INSTALLS += target sources diff --git a/demos/embedded/lightmaps/main.cpp b/demos/embedded/lightmaps/main.cpp new file mode 100644 index 0000000000..34d8d3d066 --- /dev/null +++ b/demos/embedded/lightmaps/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QApplication> +#include "mapzoom.h" + +int main(int argc, char **argv) +{ +#if defined(Q_WS_X11) + QApplication::setGraphicsSystem("raster"); +#endif + + QApplication app(argc, argv); + app.setApplicationName("LightMaps"); + + MapZoom w; +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + w.showMaximized(); +#else + w.resize(600, 450); + w.show(); +#endif + + return app.exec(); +} diff --git a/demos/embedded/lightmaps/mapzoom.cpp b/demos/embedded/lightmaps/mapzoom.cpp new file mode 100644 index 0000000000..6cafc59b1d --- /dev/null +++ b/demos/embedded/lightmaps/mapzoom.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QtNetwork> +#include "lightmaps.h" +#include "mapzoom.h" + +MapZoom::MapZoom() + : QMainWindow(0) +{ + map = new LightMaps(this); + setCentralWidget(map); + map->setFocus(); + + QAction *osloAction = new QAction(tr("&Oslo"), this); + QAction *berlinAction = new QAction(tr("&Berlin"), this); + QAction *jakartaAction = new QAction(tr("&Jakarta"), this); + QAction *nightModeAction = new QAction(tr("Night Mode"), this); + nightModeAction->setCheckable(true); + nightModeAction->setChecked(false); + QAction *osmAction = new QAction(tr("About OpenStreetMap"), this); + connect(osloAction, SIGNAL(triggered()), SLOT(chooseOslo())); + connect(berlinAction, SIGNAL(triggered()), SLOT(chooseBerlin())); + connect(jakartaAction, SIGNAL(triggered()), SLOT(chooseJakarta())); + connect(nightModeAction, SIGNAL(triggered()), map, SLOT(toggleNightMode())); + connect(osmAction, SIGNAL(triggered()), SLOT(aboutOsm())); + +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + menuBar()->addAction(osloAction); + menuBar()->addAction(berlinAction); + menuBar()->addAction(jakartaAction); + menuBar()->addAction(nightModeAction); + menuBar()->addAction(osmAction); +#else + QMenu *menu = menuBar()->addMenu(tr("&Options")); + menu->addAction(osloAction); + menu->addAction(berlinAction); + menu->addAction(jakartaAction); + menu->addSeparator(); + menu->addAction(nightModeAction); + menu->addAction(osmAction); +#endif + + QNetworkConfigurationManager manager; + if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired) { + // Get saved network configuration + QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); + settings.beginGroup(QLatin1String("QtNetwork")); + const QString id = + settings.value(QLatin1String("DefaultNetworkConfiguration")).toString(); + settings.endGroup(); + + // If the saved network configuration is not currently discovered use the system + // default + QNetworkConfiguration config = manager.configurationFromIdentifier(id); + if ((config.state() & QNetworkConfiguration::Discovered) != + QNetworkConfiguration::Discovered) { + config = manager.defaultConfiguration(); + } + + networkSession = new QNetworkSession(config, this); + connect(networkSession, SIGNAL(opened()), this, SLOT(sessionOpened())); + + networkSession->open(); + } else { + networkSession = 0; + } + + setWindowTitle(tr("Light Maps")); +} + +void MapZoom::sessionOpened() +{ + // Save the used configuration + QNetworkConfiguration config = networkSession->configuration(); + QString id; + if (config.type() == QNetworkConfiguration::UserChoice) { + id = networkSession->sessionProperty( + QLatin1String("UserChoiceConfiguration")).toString(); + } else { + id = config.identifier(); + } + + QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); + settings.beginGroup(QLatin1String("QtNetwork")); + settings.setValue(QLatin1String("DefaultNetworkConfiguration"), id); + settings.endGroup(); +} + +void MapZoom::chooseOslo() +{ + map->setCenter(59.9138204, 10.7387413); +} + +void MapZoom::chooseBerlin() +{ + map->setCenter(52.52958999943302, 13.383053541183472); +} + +void MapZoom::chooseJakarta() +{ + map->setCenter(-6.211544, 106.845172); +} + +void MapZoom::aboutOsm() +{ + QDesktopServices::openUrl(QUrl("http://www.openstreetmap.org")); +} diff --git a/demos/embedded/lightmaps/mapzoom.h b/demos/embedded/lightmaps/mapzoom.h new file mode 100644 index 0000000000..0b1ea8b8c7 --- /dev/null +++ b/demos/embedded/lightmaps/mapzoom.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef MAPZOOM_H +#define MAPZOOM_H + +#include <QMainWindow> + +class QNetworkSession; +class LightMaps; + +class MapZoom : public QMainWindow +{ + Q_OBJECT + +public: + MapZoom(); + +private slots: + void sessionOpened(); + void chooseOslo(); + void chooseBerlin(); + void chooseJakarta(); + void aboutOsm(); + +private: + LightMaps *map; + QNetworkSession *networkSession; +}; + +#endif
\ No newline at end of file diff --git a/demos/embedded/lightmaps/slippymap.cpp b/demos/embedded/lightmaps/slippymap.cpp new file mode 100644 index 0000000000..2c76f748bc --- /dev/null +++ b/demos/embedded/lightmaps/slippymap.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <math.h> + +#include <QtGui> +#include <QtNetwork> +#include "slippymap.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +uint qHash(const QPoint& p) +{ + return p.x() * 17 ^ p.y(); +} + +// tile size in pixels +const int tdim = 256; + +QPointF tileForCoordinate(qreal lat, qreal lng, int zoom) +{ + qreal zn = static_cast<qreal>(1 << zoom); + qreal tx = (lng + 180.0) / 360.0; + qreal ty = (1.0 - log(tan(lat * M_PI / 180.0) + + 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0; + return QPointF(tx * zn, ty * zn); +} + +qreal longitudeFromTile(qreal tx, int zoom) +{ + qreal zn = static_cast<qreal>(1 << zoom); + qreal lat = tx / zn * 360.0 - 180.0; + return lat; +} + +qreal latitudeFromTile(qreal ty, int zoom) +{ + qreal zn = static_cast<qreal>(1 << zoom); + qreal n = M_PI - 2 * M_PI * ty / zn; + qreal lng = 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); + return lng; +} + + +SlippyMap::SlippyMap(QObject *parent) + : QObject(parent), width(400), height(300), zoom(15), + latitude(59.9138204), longitude(10.7387413) +{ + m_emptyTile = QPixmap(tdim, tdim); + m_emptyTile.fill(Qt::lightGray); + + QNetworkDiskCache *cache = new QNetworkDiskCache; + cache->setCacheDirectory(QDesktopServices::storageLocation + (QDesktopServices::CacheLocation)); + m_manager.setCache(cache); + connect(&m_manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(handleNetworkData(QNetworkReply*))); +} + +void SlippyMap::invalidate() +{ + if (width <= 0 || height <= 0) + return; + + QPointF ct = tileForCoordinate(latitude, longitude, zoom); + qreal tx = ct.x(); + qreal ty = ct.y(); + + // top-left corner of the center tile + int xp = width / 2 - (tx - floor(tx)) * tdim; + int yp = height / 2 - (ty - floor(ty)) * tdim; + + // first tile vertical and horizontal + int xa = (xp + tdim - 1) / tdim; + int ya = (yp + tdim - 1) / tdim; + int xs = static_cast<int>(tx) - xa; + int ys = static_cast<int>(ty) - ya; + + // offset for top-left tile + m_offset = QPoint(xp - xa * tdim, yp - ya * tdim); + + // last tile vertical and horizontal + int xe = static_cast<int>(tx) + (width - xp - 1) / tdim; + int ye = static_cast<int>(ty) + (height - yp - 1) / tdim; + + // build a rect + m_tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1); + + if (m_url.isEmpty()) + download(); + + emit updated(QRect(0, 0, width, height)); +} + +void SlippyMap::render(QPainter *p, const QRect &rect) +{ + for (int x = 0; x <= m_tilesRect.width(); ++x) + for (int y = 0; y <= m_tilesRect.height(); ++y) { + QPoint tp(x + m_tilesRect.left(), y + m_tilesRect.top()); + QRect box = tileRect(tp); + if (rect.intersects(box)) { + if (m_tilePixmaps.contains(tp)) + p->drawPixmap(box, m_tilePixmaps.value(tp)); + else + p->drawPixmap(box, m_emptyTile); + } + } +} + +void SlippyMap::pan(const QPoint &delta) +{ + QPointF dx = QPointF(delta) / qreal(tdim); + QPointF center = tileForCoordinate(latitude, longitude, zoom) - dx; + latitude = latitudeFromTile(center.y(), zoom); + longitude = longitudeFromTile(center.x(), zoom); + invalidate(); +} + +void SlippyMap::handleNetworkData(QNetworkReply *reply) +{ + QImage img; + QPoint tp = reply->request().attribute(QNetworkRequest::User).toPoint(); + QUrl url = reply->url(); + if (!reply->error()) + if (!img.load(reply, 0)) + img = QImage(); + reply->deleteLater(); + m_tilePixmaps[tp] = QPixmap::fromImage(img); + if (img.isNull()) + m_tilePixmaps[tp] = m_emptyTile; + emit updated(tileRect(tp)); + + // purge unused spaces + QRect bound = m_tilesRect.adjusted(-2, -2, 2, 2); + foreach(QPoint tp, m_tilePixmaps.keys()) + if (!bound.contains(tp)) + m_tilePixmaps.remove(tp); + + download(); +} + +void SlippyMap::download() +{ + QPoint grab(0, 0); + for (int x = 0; x <= m_tilesRect.width(); ++x) + for (int y = 0; y <= m_tilesRect.height(); ++y) { + QPoint tp = m_tilesRect.topLeft() + QPoint(x, y); + if (!m_tilePixmaps.contains(tp)) { + grab = tp; + break; + } + } + if (grab == QPoint(0, 0)) { + m_url = QUrl(); + return; + } + + QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; + m_url = QUrl(path.arg(zoom).arg(grab.x()).arg(grab.y())); + QNetworkRequest request; + request.setUrl(m_url); + request.setRawHeader("User-Agent", "Nokia (Qt) Graphics Dojo 1.0"); + request.setAttribute(QNetworkRequest::User, QVariant(grab)); + m_manager.get(request); +} + +QRect SlippyMap::tileRect(const QPoint &tp) +{ + QPoint t = tp - m_tilesRect.topLeft(); + int x = t.x() * tdim + m_offset.x(); + int y = t.y() * tdim + m_offset.y(); + return QRect(x, y, tdim, tdim); +} diff --git a/demos/embedded/lightmaps/slippymap.h b/demos/embedded/lightmaps/slippymap.h new file mode 100644 index 0000000000..ba43e40c9b --- /dev/null +++ b/demos/embedded/lightmaps/slippymap.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef SLIPPYMAP_H +#define SLIPPYMAP_H + +#include <QNetworkAccessManager> +#include <QPixmap> +#include <QUrl> + +class QNetworkReply; +class QPainter; + +class SlippyMap: public QObject +{ + Q_OBJECT + +public: + SlippyMap(QObject *parent = 0); + void invalidate(); + void render(QPainter *p, const QRect &rect); + void pan(const QPoint &delta); + + int width; + int height; + int zoom; + qreal latitude; + qreal longitude; + +signals: + void updated(const QRect &rect); + +private slots: + void handleNetworkData(QNetworkReply *reply); + void download(); + +protected: + QRect tileRect(const QPoint &tp); + +private: + QPoint m_offset; + QRect m_tilesRect; + QPixmap m_emptyTile; + QHash<QPoint, QPixmap> m_tilePixmaps; + QNetworkAccessManager m_manager; + QUrl m_url; +}; + +#endif
\ No newline at end of file diff --git a/demos/embedded/raycasting/raycasting.cpp b/demos/embedded/raycasting/raycasting.cpp new file mode 100644 index 0000000000..8ca4f8bf74 --- /dev/null +++ b/demos/embedded/raycasting/raycasting.cpp @@ -0,0 +1,391 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QtCore> +#include <QtGui> + +#include <math.h> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define WORLD_SIZE 8 +int world_map[WORLD_SIZE][WORLD_SIZE] = { + { 1, 1, 1, 1, 6, 1, 1, 1 }, + { 1, 0, 0, 1, 0, 0, 0, 7 }, + { 1, 1, 0, 1, 0, 1, 1, 1 }, + { 6, 0, 0, 0, 0, 0, 0, 3 }, + { 1, 8, 8, 0, 8, 0, 8, 1 }, + { 2, 2, 0, 0, 8, 8, 7, 1 }, + { 3, 0, 0, 0, 0, 0, 0, 5 }, + { 2, 2, 2, 2, 7, 4, 4, 4 }, +}; + +#define TEXTURE_SIZE 64 +#define TEXTURE_BLOCK (TEXTURE_SIZE * TEXTURE_SIZE) + +class Raycasting: public QWidget +{ +public: + Raycasting(QWidget *parent = 0) + : QWidget(parent) + , angle(0.5) + , playerPos(1.5, 1.5) + , angleDelta(0) + , moveDelta(0) + , touchDevice(false) { + + // http://www.areyep.com/RIPandMCS-TextureLibrary.html + textureImg.load(":/textures.png"); + textureImg = textureImg.convertToFormat(QImage::Format_ARGB32); + Q_ASSERT(textureImg.width() == TEXTURE_SIZE * 2); + Q_ASSERT(textureImg.bytesPerLine() == 4 * TEXTURE_SIZE * 2); + textureCount = textureImg.height() / TEXTURE_SIZE; + + watch.start(); + ticker.start(25, this); + setAttribute(Qt::WA_OpaquePaintEvent, true); + setMouseTracking(false); + } + + void updatePlayer() { + int interval = qBound(20, watch.elapsed(), 250); + watch.start(); + angle += angleDelta * interval / 1000; + qreal step = moveDelta * interval / 1000; + qreal dx = cos(angle) * step; + qreal dy = sin(angle) * step; + QPointF pos = playerPos + 3 * QPointF(dx, dy); + int xi = static_cast<int>(pos.x()); + int yi = static_cast<int>(pos.y()); + if (world_map[yi][xi] == 0) + playerPos = playerPos + QPointF(dx, dy); + } + + void showFps() { + static QTime frameTick; + static int totalFrame = 0; + if (!(totalFrame & 31)) { + int elapsed = frameTick.elapsed(); + frameTick.start(); + int fps = 32 * 1000 / (1 + elapsed); + setWindowTitle(QString("Raycasting (%1 FPS)").arg(fps)); + } + totalFrame++; + } + + void render() { + + // setup the screen surface + if (buffer.size() != bufferSize) + buffer = QImage(bufferSize, QImage::Format_ARGB32); + int bufw = buffer.width(); + int bufh = buffer.height(); + if (bufw <= 0 || bufh <= 0) + return; + + // we intentionally cheat here, to avoid detach + const uchar *ptr = buffer.bits(); + QRgb *start = (QRgb*)(ptr); + QRgb stride = buffer.bytesPerLine() / 4; + QRgb *finish = start + stride * bufh; + + // prepare the texture pointer + const uchar *src = textureImg.bits(); + const QRgb *texsrc = reinterpret_cast<const QRgb*>(src); + + // cast all rays here + qreal sina = sin(angle); + qreal cosa = cos(angle); + qreal u = cosa - sina; + qreal v = sina + cosa; + qreal du = 2 * sina / bufw; + qreal dv = -2 * cosa / bufw; + + for (int ray = 0; ray < bufw; ++ray, u += du, v += dv) { + // every time this ray advances 'u' units in x direction, + // it also advanced 'v' units in y direction + qreal uu = (u < 0) ? -u : u; + qreal vv = (v < 0) ? -v : v; + qreal duu = 1 / uu; + qreal dvv = 1 / vv; + int stepx = (u < 0) ? -1 : 1; + int stepy = (v < 0) ? -1 : 1; + + // the cell in the map that we need to check + qreal px = playerPos.x(); + qreal py = playerPos.y(); + int mapx = static_cast<int>(px); + int mapy = static_cast<int>(py); + + // the position and texture for the hit + int texture = 0; + qreal hitdist = 0.1; + qreal texofs = 0; + bool dark = false; + + // first hit at constant x and constant y lines + qreal distx = (u > 0) ? (mapx + 1 - px) * duu : (px - mapx) * duu; + qreal disty = (v > 0) ? (mapy + 1 - py) * dvv : (py - mapy) * dvv; + + // loop until we hit something + while (texture <= 0) { + if (distx > disty) { + // shorter distance to a hit in constant y line + hitdist = disty; + disty += dvv; + mapy += stepy; + texture = world_map[mapy][mapx]; + if (texture > 0) { + dark = true; + if (stepy > 0) { + qreal ofs = px + u * (mapy - py) / v; + texofs = ofs - floor(ofs); + } else { + qreal ofs = px + u * (mapy + 1 - py) / v; + texofs = ofs - floor(ofs); + } + } + } else { + // shorter distance to a hit in constant x line + hitdist = distx; + distx += duu; + mapx += stepx; + texture = world_map[mapy][mapx]; + if (texture > 0) { + if (stepx > 0) { + qreal ofs = py + v * (mapx - px) / u; + texofs = ofs - floor(ofs); + } else { + qreal ofs = py + v * (mapx + 1 - px) / u; + texofs = ceil(ofs) - ofs; + } + } + } + } + + // get the texture, note that the texture image + // has two textures horizontally, "normal" vs "dark" + int col = static_cast<int>(texofs * TEXTURE_SIZE); + col = qBound(0, col, TEXTURE_SIZE - 1); + texture = (texture - 1) % textureCount; + const QRgb *tex = texsrc + TEXTURE_BLOCK * texture * 2 + + (TEXTURE_SIZE * 2 * col); + if (dark) + tex += TEXTURE_SIZE; + + // start from the texture center (horizontally) + int h = static_cast<int>(bufw / hitdist / 2); + int dy = (TEXTURE_SIZE << 12) / h; + int p1 = ((TEXTURE_SIZE / 2) << 12) - dy; + int p2 = p1 + dy; + + // start from the screen center (vertically) + // y1 will go up (decrease), y2 will go down (increase) + int y1 = bufh / 2; + int y2 = y1 + 1; + QRgb *pixel1 = start + y1 * stride + ray; + QRgb *pixel2 = pixel1 + stride; + + // map the texture to the sliver + while (y1 >= 0 && y2 < bufh && p1 >= 0) { + *pixel1 = tex[p1 >> 12]; + *pixel2 = tex[p2 >> 12]; + p1 -= dy; + p2 += dy; + --y1; + ++y2; + pixel1 -= stride; + pixel2 += stride; + } + + // ceiling and floor + for (; pixel1 > start; pixel1 -= stride) + *pixel1 = qRgb(0, 0, 0); + for (; pixel2 < finish; pixel2 += stride) + *pixel2 = qRgb(96, 96, 96); + } + + update(QRect(QPoint(0, 0), bufferSize)); + } + +protected: + + void resizeEvent(QResizeEvent*) { +#if defined(Q_OS_WINCE_WM) + touchDevice = true; +#elif defined(Q_OS_SYMBIAN) + // FIXME: use HAL + if (width() > 480 || height() > 480) + touchDevice = true; +#else + touchDevice = false; +#endif + if (touchDevice) { + if (width() < height()) { + trackPad = QRect(0, height() / 2, width(), height() / 2); + centerPad = QPoint(width() / 2, height() * 3 / 4); + bufferSize = QSize(width(), height() / 2); + } else { + trackPad = QRect(width() / 2, 0, width() / 2, height()); + centerPad = QPoint(width() * 3 / 4, height() / 2); + bufferSize = QSize(width() / 2, height()); + } + } else { + trackPad = QRect(); + bufferSize = size(); + } + update(); + } + + void timerEvent(QTimerEvent*) { + updatePlayer(); + render(); + showFps(); + } + + void paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_Source); + + p.drawImage(event->rect(), buffer, event->rect()); + + if (touchDevice && event->rect().intersects(trackPad)) { + p.fillRect(trackPad, Qt::white); + p.setPen(QPen(QColor(224, 224, 224), 6)); + int rad = qMin(trackPad.width(), trackPad.height()) * 0.3; + p.drawEllipse(centerPad, rad, rad); + + p.setPen(Qt::NoPen); + p.setBrush(Qt::gray); + + QPolygon poly; + poly << QPoint(-30, 0); + poly << QPoint(0, -40); + poly << QPoint(30, 0); + + p.translate(centerPad); + for (int i = 0; i < 4; ++i) { + p.rotate(90); + p.translate(0, 20 - rad); + p.drawPolygon(poly); + p.translate(0, rad - 20); + } + } + + p.end(); + } + + void keyPressEvent(QKeyEvent *event) { + event->accept(); + if (event->key() == Qt::Key_Left) + angleDelta = 1.3 * M_PI; + if (event->key() == Qt::Key_Right) + angleDelta = -1.3 * M_PI; + if (event->key() == Qt::Key_Up) + moveDelta = 2.5; + if (event->key() == Qt::Key_Down) + moveDelta = -2.5; + } + + void keyReleaseEvent(QKeyEvent *event) { + event->accept(); + if (event->key() == Qt::Key_Left) + angleDelta = (angleDelta > 0) ? 0 : angleDelta; + if (event->key() == Qt::Key_Right) + angleDelta = (angleDelta < 0) ? 0 : angleDelta; + if (event->key() == Qt::Key_Up) + moveDelta = (moveDelta > 0) ? 0 : moveDelta; + if (event->key() == Qt::Key_Down) + moveDelta = (moveDelta < 0) ? 0 : moveDelta; + } + + void mousePressEvent(QMouseEvent *event) { + qreal dx = centerPad.x() - event->pos().x(); + qreal dy = centerPad.y() - event->pos().y(); + angleDelta = dx * 2 * M_PI / width(); + moveDelta = dy * 10 / height(); + } + + void mouseMoveEvent(QMouseEvent *event) { + qreal dx = centerPad.x() - event->pos().x(); + qreal dy = centerPad.y() - event->pos().y(); + angleDelta = dx * 2 * M_PI / width(); + moveDelta = dy * 10 / height(); + } + + void mouseReleaseEvent(QMouseEvent*) { + angleDelta = 0; + moveDelta = 0; + } + +private: + QTime watch; + QBasicTimer ticker; + QImage buffer; + qreal angle; + QPointF playerPos; + qreal angleDelta; + qreal moveDelta; + QImage textureImg; + int textureCount; + bool touchDevice; + QRect trackPad; + QPoint centerPad; + QSize bufferSize; +}; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + Raycasting w; + w.setWindowTitle("Raycasting"); +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) + w.showMaximized(); +#else + w.resize(640, 480); + w.show(); +#endif + + return app.exec(); +} diff --git a/demos/embedded/raycasting/raycasting.pro b/demos/embedded/raycasting/raycasting.pro new file mode 100644 index 0000000000..bc1692a458 --- /dev/null +++ b/demos/embedded/raycasting/raycasting.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +SOURCES = raycasting.cpp +RESOURCES += raycasting.qrc + +symbian { + TARGET.UID3 = 0xA000CF76 + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) +} + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/raycasting +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/raycasting +INSTALLS += target sources diff --git a/demos/embedded/raycasting/raycasting.qrc b/demos/embedded/raycasting/raycasting.qrc new file mode 100644 index 0000000000..974a06093c --- /dev/null +++ b/demos/embedded/raycasting/raycasting.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/" > + <file>textures.png</file> + </qresource> +</RCC> diff --git a/demos/embedded/raycasting/textures.png b/demos/embedded/raycasting/textures.png Binary files differnew file mode 100644 index 0000000000..2eb1ba7ff6 --- /dev/null +++ b/demos/embedded/raycasting/textures.png diff --git a/demos/embedded/styledemo/files/add.png b/demos/embedded/styledemo/files/add.png Binary files differnew file mode 100755 index 0000000000..fc5c16d4c8 --- /dev/null +++ b/demos/embedded/styledemo/files/add.png diff --git a/demos/embedded/styledemo/files/application.qss b/demos/embedded/styledemo/files/application.qss new file mode 100644 index 0000000000..432fe6bc76 --- /dev/null +++ b/demos/embedded/styledemo/files/application.qss @@ -0,0 +1,125 @@ +QWidget#StyleWidget +{ + background-color: none; + background-image: url(icons:nature_1.jpg); +} + +QLabel, QAbstractButton +{ + font: bold; + color: beige; +} + +QAbstractButton +{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(173,216,230,60%), stop:1 rgba(0,0,139,60%) ); + border-color: black; + border-style: solid; + border-width: 3px; + border-radius: 6px; +} + +QAbstractButton:pressed, QAbstractButton:checked +{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0,0,139,60%), stop:1 rgba(173,216,230,60%) ); +} + +QSpinBox { + padding-left: 24px; + padding-right: 24px; + border-color: darkkhaki; + border-style: solid; + border-radius: 5; + border-width: 3; +} + +QSpinBox::up-button +{ + subcontrol-origin: padding; + subcontrol-position: right; /* position at the top right corner */ + width: 24px; + height: 24px; + border-width: 3px; + +} + +QSpinBox::up-arrow +{ + image: url(icons:add.png); + width: 18px; + height: 18px; +} + + +QSpinBox::down-button +{ + subcontrol-origin: border; + subcontrol-position: left; + width: 24px; + height: 24px; + border-width: 3px; +} + +QSpinBox::down-arrow +{ + image: url(icons:remove.png); + width: 18px; + height: 18px; +} + + +QScrollBar:horizontal +{ + border: 1px solid black; + background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0,0,139,60%), stop:1 rgba(173,216,230,60%) ); + height: 15px; + margin: 0px 20px 0 20px; +} + +QScrollBar::handle:horizontal +{ + border: 1px solid black; + background: rgba(0,0,139,60%); + min-width: 20px; +} + +QScrollBar::add-line:horizontal +{ + border: 1px solid black; + background: rgba(0,0,139,60%); + width: 20px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal +{ + border: 1px solid black; + background: rgba(0,0,139,60%); + width: 20px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal +{ + border: none; + width: 16px; + height: 16px; +} + +QScrollBar:left-arrow:horizontal +{ + image: url(icons:add.png) +} + +QScrollBar::right-arrow:horizontal +{ + image: url(icons:remove.png) +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ + background: none; +} + diff --git a/demos/embedded/styledemo/files/blue.qss b/demos/embedded/styledemo/files/blue.qss new file mode 100644 index 0000000000..ac8671b5e4 --- /dev/null +++ b/demos/embedded/styledemo/files/blue.qss @@ -0,0 +1,38 @@ +* +{ + color: beige; +} + +QLabel, QAbstractButton +{ + font: bold; + color: yellow; +} + +QFrame +{ + background-color: rgba(96,96,255,60%); + border-color: rgb(32,32,196); + border-width: 3px; + border-style: solid; + border-radius: 5; + padding: 3px; +} + +QAbstractButton +{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightblue, stop:0.5 darkblue); + border-width: 3px; + border-color: darkblue; + border-style: solid; + border-radius: 5; + padding: 3px; +} + +QAbstractButton:pressed +{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0.5 darkblue, stop:1 lightblue); + border-color: beige; +} diff --git a/demos/embedded/styledemo/files/khaki.qss b/demos/embedded/styledemo/files/khaki.qss new file mode 100644 index 0000000000..b0d4a0fa6f --- /dev/null +++ b/demos/embedded/styledemo/files/khaki.qss @@ -0,0 +1,99 @@ + +QWidget#StartScreen, QWidget#MainWidget { + border: none; +} + +QWidget#StartScreen, .QFrame { + background-color: beige; +} + +QPushButton, QToolButton { + background-color: palegoldenrod; + border-width: 2px; + border-color: darkkhaki; + border-style: solid; + border-radius: 5; + padding: 3px; + /* min-width: 96px; */ + /* min-height: 48px; */ +} + +QPushButton:hover, QToolButton:hover { + background-color: khaki; +} + +QPushButton:pressed, QToolButton:pressed { + padding-left: 5px; + padding-top: 5px; + background-color: #d0d67c; +} + +QLabel, QAbstractButton { + font: italic "Times New Roman"; +} + +QFrame, QLabel#title { + border-width: 2px; + padding: 1px; + border-style: solid; + border-color: darkkhaki; + border-radius: 5px; +} + +QFrame:focus { + border-width: 3px; + padding: 0px; +} + + +QLabel { + border: none; + padding: 0; + background: none; +} + +QLabel#title { + font: 32px bold; +} + +QSpinBox { + padding-left: 24px; + padding-right: 24px; + border-color: darkkhaki; + border-style: solid; + border-radius: 5; + border-width: 3; +} + +QSpinBox::up-button +{ + subcontrol-origin: padding; + subcontrol-position: right; /* position at the top right corner */ + width: 24px; + height: 24px; + border-width: 3px; + border-image: url(:/files/spindownpng) 1; +} + +QSpinBox::up-arrow { + image: url(:/files/add.png); + width: 12px; + height: 12px; + } + + +QSpinBox::down-button +{ + subcontrol-origin: border; + subcontrol-position: left; + width: 24px; + height: 24px; + border-width: 3px; + border-image: url(:/files/spindownpng) 1; +} + +QSpinBox::down-arrow { + image: url(:/files/remove.png); + width: 12px; + height: 12px; + } diff --git a/demos/embedded/styledemo/files/nature_1.jpg b/demos/embedded/styledemo/files/nature_1.jpg Binary files differnew file mode 100644 index 0000000000..3a04edb96a --- /dev/null +++ b/demos/embedded/styledemo/files/nature_1.jpg diff --git a/demos/embedded/styledemo/files/nostyle.qss b/demos/embedded/styledemo/files/nostyle.qss new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/demos/embedded/styledemo/files/nostyle.qss diff --git a/demos/embedded/styledemo/files/remove.png b/demos/embedded/styledemo/files/remove.png Binary files differnew file mode 100755 index 0000000000..a0ab1fa21a --- /dev/null +++ b/demos/embedded/styledemo/files/remove.png diff --git a/demos/embedded/styledemo/files/transparent.qss b/demos/embedded/styledemo/files/transparent.qss new file mode 100644 index 0000000000..b38eb366f4 --- /dev/null +++ b/demos/embedded/styledemo/files/transparent.qss @@ -0,0 +1,139 @@ +QWidget#StyleWidget +{ + background-color: none; + background-image: url(:/files/nature_1.jpg); +} + +QLabel, QAbstractButton +{ + color: beige; +} + +QFrame, QLabel#title { + border-width: 2px; + padding: 1px; + border-style: solid; + border-color: black; + border-radius: 5px; +} + +QFrame:focus { + border-width: 3px; + padding: 0px; +} + + + +QAbstractButton +{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(173,216,230,60%), stop:1 rgba(0,0,139,60%) ); + border-color: black; + border-style: solid; + border-width: 3px; + border-radius: 6px; +} + +QAbstractButton:pressed, QAbstractButton:checked +{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0,0,139,60%), stop:1 rgba(173,216,230,60%) ); +} + +QSpinBox { + padding-left: 24px; + padding-right: 24px; + border-color: darkkhaki; + border-style: solid; + border-radius: 5; + border-width: 3; +} + +QSpinBox::up-button +{ + subcontrol-origin: padding; + subcontrol-position: right; /* position at the top right corner */ + width: 24px; + height: 24px; + border-width: 3px; + +} + +QSpinBox::up-arrow +{ + image: url(:/files/add.png); + width: 18px; + height: 18px; +} + + +QSpinBox::down-button +{ + subcontrol-origin: border; + subcontrol-position: left; + width: 24px; + height: 24px; + border-width: 3px; +} + +QSpinBox::down-arrow +{ + image: url(:/files/remove.png); + width: 18px; + height: 18px; +} + + +QScrollBar:horizontal +{ + border: 1px solid black; + background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0,0,139,60%), stop:1 rgba(173,216,230,60%) ); + height: 15px; + margin: 0px 20px 0 20px; +} + +QScrollBar::handle:horizontal +{ + border: 1px solid black; + background: rgba(0,0,139,60%); + min-width: 20px; +} + +QScrollBar::add-line:horizontal +{ + border: 1px solid black; + background: rgba(0,0,139,60%); + width: 20px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal +{ + border: 1px solid black; + background: rgba(0,0,139,60%); + width: 20px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal +{ + border: none; + width: 16px; + height: 16px; +} + +QScrollBar:left-arrow:horizontal +{ + image: url(:/files/add.png) +} + +QScrollBar::right-arrow:horizontal +{ + image: url(:/files/remove.png) +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ + background: none; +} + diff --git a/demos/embedded/styledemo/main.cpp b/demos/embedded/styledemo/main.cpp new file mode 100644 index 0000000000..395d40515e --- /dev/null +++ b/demos/embedded/styledemo/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QApplication> + +#include "stylewidget.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Q_INIT_RESOURCE(styledemo); + + app.setApplicationName("style"); + app.setOrganizationName("Nokia"); + app.setOrganizationDomain("com.nokia.qt"); + + StyleWidget widget; + widget.showFullScreen(); + + return app.exec(); +} + diff --git a/demos/embedded/styledemo/styledemo.pro b/demos/embedded/styledemo/styledemo.pro new file mode 100644 index 0000000000..81a45403ad --- /dev/null +++ b/demos/embedded/styledemo/styledemo.pro @@ -0,0 +1,17 @@ +TEMPLATE = app + +# Input +HEADERS += stylewidget.h +FORMS += stylewidget.ui +SOURCES += main.cpp stylewidget.cpp +RESOURCES += styledemo.qrc + +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/styledemo +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro *.html +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embedded/styledemo +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000A63F + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) +} diff --git a/demos/embedded/styledemo/styledemo.qrc b/demos/embedded/styledemo/styledemo.qrc new file mode 100644 index 0000000000..96237d4203 --- /dev/null +++ b/demos/embedded/styledemo/styledemo.qrc @@ -0,0 +1,13 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> + <file>files/add.png</file> + <file>files/blue.qss</file> + <file>files/khaki.qss</file> + <file>files/nostyle.qss</file> + <file>files/transparent.qss</file> + <file>files/application.qss</file> + <file>files/nature_1.jpg</file> + <file>files/remove.png</file> +</qresource> +</RCC> + diff --git a/demos/embedded/styledemo/stylewidget.cpp b/demos/embedded/styledemo/stylewidget.cpp new file mode 100644 index 0000000000..c40e90834a --- /dev/null +++ b/demos/embedded/styledemo/stylewidget.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 <QApplication> +#include <QString> +#include <QFile> + +#include "stylewidget.h" + + + +StyleWidget::StyleWidget(QWidget *parent) + : QFrame(parent) +{ + m_ui.setupUi(this); +} + + +void StyleWidget::on_close_clicked() +{ + close(); +} + +void StyleWidget::on_blueStyle_clicked() +{ + QFile styleSheet(":/files/blue.qss"); + + if (!styleSheet.open(QIODevice::ReadOnly)) { + qWarning("Unable to open :/files/blue.qss"); + return; + } + + qApp->setStyleSheet(styleSheet.readAll()); +} + +void StyleWidget::on_khakiStyle_clicked() +{ + QFile styleSheet(":/files/khaki.qss"); + + if (!styleSheet.open(QIODevice::ReadOnly)) { + qWarning("Unable to open :/files/khaki.qss"); + return; + } + + qApp->setStyleSheet(styleSheet.readAll()); +} + + +void StyleWidget::on_noStyle_clicked() +{ + QFile styleSheet(":/files/nostyle.qss"); + + if (!styleSheet.open(QIODevice::ReadOnly)) { + qWarning("Unable to open :/files/nostyle.qss"); + return; + } + + qApp->setStyleSheet(styleSheet.readAll()); +} + + +void StyleWidget::on_transparentStyle_clicked() +{ + QFile styleSheet(":/files/transparent.qss"); + + if (!styleSheet.open(QIODevice::ReadOnly)) { + qWarning("Unable to open :/files/transparent.qss"); + return; + } + + qApp->setStyleSheet(styleSheet.readAll()); +} + + + diff --git a/demos/embedded/styledemo/stylewidget.h b/demos/embedded/styledemo/stylewidget.h new file mode 100644 index 0000000000..6339f7ad76 --- /dev/null +++ b/demos/embedded/styledemo/stylewidget.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ +#ifndef STYLEWIDGET_H +#define STYLEWIDGET_H + +#include <QFrame> + +#include "ui_stylewidget.h" + +class StyleWidget : public QFrame +{ + Q_OBJECT +public: + StyleWidget(QWidget *parent = 0); + +private: + Ui_StyleWidget m_ui; + +private slots: + void on_close_clicked(); + void on_blueStyle_clicked(); + void on_khakiStyle_clicked(); + void on_noStyle_clicked(); + void on_transparentStyle_clicked(); +}; + +#endif diff --git a/demos/embedded/styledemo/stylewidget.ui b/demos/embedded/styledemo/stylewidget.ui new file mode 100644 index 0000000000..767f44aead --- /dev/null +++ b/demos/embedded/styledemo/stylewidget.ui @@ -0,0 +1,417 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StyleWidget</class> + <widget class="QWidget" name="StyleWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>184</width> + <height>245</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Styles</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <property name="margin"> + <number>4</number> + </property> + <property name="spacing"> + <number>4</number> + </property> + <item row="0" column="0"> + <widget class="QPushButton" name="transparentStyle"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>Transp.</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="autoExclusive"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QPushButton" name="blueStyle"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>Blue</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="autoExclusive"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="khakiStyle"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>Khaki</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="autoExclusive"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="noStyle"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>None</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="autoExclusive"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>4</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Value:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox"> + <property name="focusPolicy"> + <enum>Qt::WheelFocus</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="keyboardTracking"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="3" column="0"> + <widget class="QScrollBar" name="horizontalScrollBar"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>24</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::TabFocus</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QScrollBar" name="horizontalScrollBar_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>24</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::TabFocus</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QPushButton" name="pushButton_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>Show</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QPushButton" name="pushButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>Enable</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="5" column="0" colspan="2"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item row="6" column="0"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="6" column="1"> + <widget class="QPushButton" name="close"> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="text"> + <string>Close</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="StyleDemo.qrc"/> + </resources> + <connections> + <connection> + <sender>horizontalScrollBar</sender> + <signal>valueChanged(int)</signal> + <receiver>horizontalScrollBar_2</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>84</x> + <y>147</y> + </hint> + <hint type="destinationlabel"> + <x>166</x> + <y>147</y> + </hint> + </hints> + </connection> + <connection> + <sender>horizontalScrollBar_2</sender> + <signal>valueChanged(int)</signal> + <receiver>horizontalScrollBar</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>166</x> + <y>147</y> + </hint> + <hint type="destinationlabel"> + <x>84</x> + <y>147</y> + </hint> + </hints> + </connection> + <connection> + <sender>pushButton</sender> + <signal>clicked(bool)</signal> + <receiver>horizontalScrollBar_2</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>166</x> + <y>175</y> + </hint> + <hint type="destinationlabel"> + <x>166</x> + <y>147</y> + </hint> + </hints> + </connection> + <connection> + <sender>pushButton_2</sender> + <signal>clicked(bool)</signal> + <receiver>horizontalScrollBar</receiver> + <slot>setVisible(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>84</x> + <y>175</y> + </hint> + <hint type="destinationlabel"> + <x>84</x> + <y>147</y> + </hint> + </hints> + </connection> + <connection> + <sender>spinBox</sender> + <signal>valueChanged(int)</signal> + <receiver>horizontalScrollBar_2</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>166</x> + <y>115</y> + </hint> + <hint type="destinationlabel"> + <x>166</x> + <y>147</y> + </hint> + </hints> + </connection> + <connection> + <sender>horizontalScrollBar_2</sender> + <signal>valueChanged(int)</signal> + <receiver>spinBox</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>132</x> + <y>132</y> + </hint> + <hint type="destinationlabel"> + <x>135</x> + <y>110</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/demos/embeddeddialogs/No-Ones-Laughing-3.jpg b/demos/embeddeddialogs/No-Ones-Laughing-3.jpg Binary files differnew file mode 100644 index 0000000000..445567fbda --- /dev/null +++ b/demos/embeddeddialogs/No-Ones-Laughing-3.jpg diff --git a/demos/embeddeddialogs/customproxy.cpp b/demos/embeddeddialogs/customproxy.cpp new file mode 100644 index 0000000000..e56823dfbd --- /dev/null +++ b/demos/embeddeddialogs/customproxy.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "customproxy.h" + +#include <QtGui> + +CustomProxy::CustomProxy(QGraphicsItem *parent, Qt::WindowFlags wFlags) + : QGraphicsProxyWidget(parent, wFlags), popupShown(false), currentPopup(0) +{ + timeLine = new QTimeLine(250, this); + connect(timeLine, SIGNAL(valueChanged(qreal)), + this, SLOT(updateStep(qreal))); + connect(timeLine, SIGNAL(stateChanged(QTimeLine::State)), + this, SLOT(stateChanged(QTimeLine::State))); +} + +QRectF CustomProxy::boundingRect() const +{ + return QGraphicsProxyWidget::boundingRect().adjusted(0, 0, 10, 10); +} + +void CustomProxy::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + const QColor color(0, 0, 0, 64); + + QRectF r = windowFrameRect(); + QRectF right(r.right(), r.top() + 10, 10, r.height() - 10); + QRectF bottom(r.left() + 10, r.bottom(), r.width(), 10); + bool intersectsRight = right.intersects(option->exposedRect); + bool intersectsBottom = bottom.intersects(option->exposedRect); + if (intersectsRight && intersectsBottom) { + QPainterPath path; + path.addRect(right); + path.addRect(bottom); + painter->setPen(Qt::NoPen); + painter->setBrush(color); + painter->drawPath(path); + } else if (intersectsBottom) { + painter->fillRect(bottom, color); + } else if (intersectsRight) { + painter->fillRect(right, color); + } + + QGraphicsProxyWidget::paintWindowFrame(painter, option, widget); +} + +void CustomProxy::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsProxyWidget::hoverEnterEvent(event); + scene()->setActiveWindow(this); + if (timeLine->currentValue() != 1) + zoomIn(); +} + +void CustomProxy::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsProxyWidget::hoverLeaveEvent(event); + if (!popupShown && (timeLine->direction() != QTimeLine::Backward || timeLine->currentValue() != 0)) + zoomOut(); +} + +bool CustomProxy::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + if (watched->isWindow() && (event->type() == QEvent::UngrabMouse || event->type() == QEvent::GrabMouse)) { + popupShown = watched->isVisible(); + if (!popupShown && !isUnderMouse()) + zoomOut(); + } + return QGraphicsProxyWidget::sceneEventFilter(watched, event); +} + +QVariant CustomProxy::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemChildAddedChange || change == ItemChildRemovedChange) { + if (change == ItemChildAddedChange) { + currentPopup = qvariant_cast<QGraphicsItem *>(value); + currentPopup->setCacheMode(ItemCoordinateCache); + if (scene()) + currentPopup->installSceneEventFilter(this); + } else if (scene()) { + currentPopup->removeSceneEventFilter(this); + currentPopup = 0; + } + } else if (currentPopup && change == ItemSceneHasChanged) { + currentPopup->installSceneEventFilter(this); + } + return QGraphicsProxyWidget::itemChange(change, value); +} + +void CustomProxy::updateStep(qreal step) +{ + QRectF r = boundingRect(); + setTransform(QTransform() + .translate(r.width() / 2, r.height() / 2) + .rotate(step * 30, Qt::XAxis) + .rotate(step * 10, Qt::YAxis) + .rotate(step * 5, Qt::ZAxis) + .scale(1 + 1.5 * step, 1 + 1.5 * step) + .translate(-r.width() / 2, -r.height() / 2)); +} + +void CustomProxy::stateChanged(QTimeLine::State state) +{ + if (state == QTimeLine::Running) { + if (timeLine->direction() == QTimeLine::Forward) + setCacheMode(ItemCoordinateCache); + } else if (state == QTimeLine::NotRunning) { + if (timeLine->direction() == QTimeLine::Backward) + setCacheMode(DeviceCoordinateCache); + } +} + +void CustomProxy::zoomIn() +{ + if (timeLine->direction() != QTimeLine::Forward) + timeLine->setDirection(QTimeLine::Forward); + if (timeLine->state() == QTimeLine::NotRunning) + timeLine->start(); +} + +void CustomProxy::zoomOut() +{ + if (timeLine->direction() != QTimeLine::Backward) + timeLine->setDirection(QTimeLine::Backward); + if (timeLine->state() == QTimeLine::NotRunning) + timeLine->start(); +} diff --git a/demos/embeddeddialogs/customproxy.h b/demos/embeddeddialogs/customproxy.h new file mode 100644 index 0000000000..67d2152f98 --- /dev/null +++ b/demos/embeddeddialogs/customproxy.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef CUSTOMPROXY_H +#define CUSTOMPROXY_H + +#include <QtCore/qtimeline.h> +#include <QtGui/qgraphicsproxywidget.h> + +class CustomProxy : public QGraphicsProxyWidget +{ + Q_OBJECT +public: + CustomProxy(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); + + QRectF boundingRect() const; + void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + +protected: + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + +private slots: + void updateStep(qreal step); + void stateChanged(QTimeLine::State); + void zoomIn(); + void zoomOut(); + +private: + QTimeLine *timeLine; + bool popupShown; + QGraphicsItem *currentPopup; +}; + +#endif diff --git a/demos/embeddeddialogs/embeddeddialog.cpp b/demos/embeddeddialogs/embeddeddialog.cpp new file mode 100644 index 0000000000..e359afe555 --- /dev/null +++ b/demos/embeddeddialogs/embeddeddialog.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "embeddeddialog.h" +#include "ui_embeddeddialog.h" + +#include <QtGui> + +EmbeddedDialog::EmbeddedDialog(QWidget *parent) + : QDialog(parent) +{ + ui = new Ui_embeddedDialog; + ui->setupUi(this); + ui->layoutDirection->setCurrentIndex(layoutDirection() != Qt::LeftToRight); + + foreach (QString styleName, QStyleFactory::keys()) { + ui->style->addItem(styleName); + if (style()->objectName().toLower() == styleName.toLower()) + ui->style->setCurrentIndex(ui->style->count() - 1); + } + + connect(ui->layoutDirection, SIGNAL(activated(int)), + this, SLOT(layoutDirectionChanged(int))); + connect(ui->spacing, SIGNAL(valueChanged(int)), + this, SLOT(spacingChanged(int))); + connect(ui->fontComboBox, SIGNAL(currentFontChanged(QFont)), + this, SLOT(fontChanged(QFont))); + connect(ui->style, SIGNAL(activated(QString)), + this, SLOT(styleChanged(QString))); +} + +EmbeddedDialog::~EmbeddedDialog() +{ + delete ui; +} + +void EmbeddedDialog::layoutDirectionChanged(int index) +{ + setLayoutDirection(index == 0 ? Qt::LeftToRight : Qt::RightToLeft); +} + +void EmbeddedDialog::spacingChanged(int spacing) +{ + layout()->setSpacing(spacing); + adjustSize(); +} + +void EmbeddedDialog::fontChanged(const QFont &font) +{ + setFont(font); +} + +static void setStyleHelper(QWidget *widget, QStyle *style) +{ + widget->setStyle(style); + widget->setPalette(style->standardPalette()); + foreach (QObject *child, widget->children()) { + if (QWidget *childWidget = qobject_cast<QWidget *>(child)) + setStyleHelper(childWidget, style); + } +} + +void EmbeddedDialog::styleChanged(const QString &styleName) +{ + QStyle *style = QStyleFactory::create(styleName); + if (style) + setStyleHelper(this, style); +} diff --git a/demos/embeddeddialogs/embeddeddialog.h b/demos/embeddeddialogs/embeddeddialog.h new file mode 100644 index 0000000000..54263f64e3 --- /dev/null +++ b/demos/embeddeddialogs/embeddeddialog.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef EMBEDDEDDIALOG_H +#define EMBEDDEDDIALOG_H + +#include <QtGui/qdialog.h> + +QT_FORWARD_DECLARE_CLASS(Ui_embeddedDialog); + +class EmbeddedDialog : public QDialog +{ + Q_OBJECT +public: + EmbeddedDialog(QWidget *parent = 0); + ~EmbeddedDialog(); + +private slots: + void layoutDirectionChanged(int index); + void spacingChanged(int spacing); + void fontChanged(const QFont &font); + void styleChanged(const QString &styleName); + +private: + Ui_embeddedDialog *ui; +}; + +#endif diff --git a/demos/embeddeddialogs/embeddeddialog.ui b/demos/embeddeddialogs/embeddeddialog.ui new file mode 100644 index 0000000000..f967b10085 --- /dev/null +++ b/demos/embeddeddialogs/embeddeddialog.ui @@ -0,0 +1,87 @@ +<ui version="4.0" > + <class>embeddedDialog</class> + <widget class="QDialog" name="embeddedDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>407</width> + <height>134</height> + </rect> + </property> + <property name="windowTitle" > + <string>Embedded Dialog</string> + </property> + <layout class="QFormLayout" name="formLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Layout Direction:</string> + </property> + <property name="buddy" > + <cstring>layoutDirection</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QComboBox" name="layoutDirection" > + <item> + <property name="text" > + <string>Left to Right</string> + </property> + </item> + <item> + <property name="text" > + <string>Right to Left</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Select Font:</string> + </property> + <property name="buddy" > + <cstring>fontComboBox</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QFontComboBox" name="fontComboBox" /> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Style:</string> + </property> + <property name="buddy" > + <cstring>style</cstring> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QComboBox" name="style" /> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Layout spacing:</string> + </property> + <property name="buddy" > + <cstring>spacing</cstring> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QSlider" name="spacing" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/demos/embeddeddialogs/embeddeddialogs.pro b/demos/embeddeddialogs/embeddeddialogs.pro new file mode 100644 index 0000000000..7e403112aa --- /dev/null +++ b/demos/embeddeddialogs/embeddeddialogs.pro @@ -0,0 +1,19 @@ +SOURCES += main.cpp +SOURCES += customproxy.cpp embeddeddialog.cpp +HEADERS += customproxy.h embeddeddialog.h + +FORMS += embeddeddialog.ui +RESOURCES += embeddeddialogs.qrc + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embeddeddialogs +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.png *.jpg *.plist *.icns *.ico *.rc *.pro *.html *.doc images +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embeddeddialogs +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/demos/embeddeddialogs/embeddeddialogs.qrc b/demos/embeddeddialogs/embeddeddialogs.qrc new file mode 100644 index 0000000000..33be5038da --- /dev/null +++ b/demos/embeddeddialogs/embeddeddialogs.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource> + <file>No-Ones-Laughing-3.jpg</file> + </qresource> +</RCC> diff --git a/demos/embeddeddialogs/main.cpp b/demos/embeddeddialogs/main.cpp new file mode 100644 index 0000000000..01f1ca9c0e --- /dev/null +++ b/demos/embeddeddialogs/main.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "customproxy.h" +#include "embeddeddialog.h" + +#include <QtGui> + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(embeddeddialogs); + QApplication app(argc, argv); + + QGraphicsScene scene; + scene.setStickyFocus(true); +#ifndef Q_OS_WINCE + const int gridSize = 10; +#else + const int gridSize = 5; +#endif + + for (int y = 0; y < gridSize; ++y) { + for (int x = 0; x < gridSize; ++x) { + CustomProxy *proxy = new CustomProxy(0, Qt::Window); + proxy->setWidget(new EmbeddedDialog); + + QRectF rect = proxy->boundingRect(); + + proxy->setPos(x * rect.width() * 1.05, y * rect.height() * 1.05); + proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + + scene.addItem(proxy); + } + } + scene.setSceneRect(scene.itemsBoundingRect()); + + QGraphicsView view(&scene); + view.scale(0.5, 0.5); + view.setRenderHints(view.renderHints() | QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg")); + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view.show(); + view.setWindowTitle("Embedded Dialogs Demo"); + return app.exec(); +} diff --git a/demos/gradients/gradients.cpp b/demos/gradients/gradients.cpp new file mode 100644 index 0000000000..8dfc684d66 --- /dev/null +++ b/demos/gradients/gradients.cpp @@ -0,0 +1,516 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "gradients.h" +#include "hoverpoints.h" + +ShadeWidget::ShadeWidget(ShadeType type, QWidget *parent) + : QWidget(parent), m_shade_type(type), m_alpha_gradient(QLinearGradient(0, 0, 0, 0)) +{ + + // Checkers background + if (m_shade_type == ARGBShade) { + QPixmap pm(20, 20); + QPainter pmp(&pm); + pmp.fillRect(0, 0, 10, 10, Qt::lightGray); + pmp.fillRect(10, 10, 10, 10, Qt::lightGray); + pmp.fillRect(0, 10, 10, 10, Qt::darkGray); + pmp.fillRect(10, 0, 10, 10, Qt::darkGray); + pmp.end(); + QPalette pal = palette(); + pal.setBrush(backgroundRole(), QBrush(pm)); + setAutoFillBackground(true); + setPalette(pal); + + } else { + setAttribute(Qt::WA_NoBackground); + + } + + QPolygonF points; + points << QPointF(0, sizeHint().height()) + << QPointF(sizeHint().width(), 0); + + m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape); +// m_hoverPoints->setConnectionType(HoverPoints::LineConnection); + m_hoverPoints->setPoints(points); + m_hoverPoints->setPointLock(0, HoverPoints::LockToLeft); + m_hoverPoints->setPointLock(1, HoverPoints::LockToRight); + m_hoverPoints->setSortType(HoverPoints::XSort); + + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + connect(m_hoverPoints, SIGNAL(pointsChanged(QPolygonF)), this, SIGNAL(colorsChanged())); +} + + +QPolygonF ShadeWidget::points() const +{ + return m_hoverPoints->points(); +} + + +uint ShadeWidget::colorAt(int x) +{ + generateShade(); + + QPolygonF pts = m_hoverPoints->points(); + for (int i=1; i < pts.size(); ++i) { + if (pts.at(i-1).x() <= x && pts.at(i).x() >= x) { + QLineF l(pts.at(i-1), pts.at(i)); + l.setLength(l.length() * ((x - l.x1()) / l.dx())); + return m_shade.pixel(qRound(qMin(l.x2(), (qreal(m_shade.width() - 1)))), + qRound(qMin(l.y2(), qreal(m_shade.height() - 1)))); + } + } + return 0; +} + + +void ShadeWidget::setGradientStops(const QGradientStops &stops) +{ + if (m_shade_type == ARGBShade) { + m_alpha_gradient = QLinearGradient(0, 0, width(), 0); + + for (int i=0; i<stops.size(); ++i) { + QColor c = stops.at(i).second; + m_alpha_gradient.setColorAt(stops.at(i).first, QColor(c.red(), c.green(), c.blue())); + } + + m_shade = QImage(); + generateShade(); + update(); + } +} + + +void ShadeWidget::paintEvent(QPaintEvent *) +{ + generateShade(); + + QPainter p(this); + p.drawImage(0, 0, m_shade); + + p.setPen(QColor(146, 146, 146)); + p.drawRect(0, 0, width() - 1, height() - 1); +} + + +void ShadeWidget::generateShade() +{ + if (m_shade.isNull() || m_shade.size() != size()) { + + if (m_shade_type == ARGBShade) { + m_shade = QImage(size(), QImage::Format_ARGB32_Premultiplied); + m_shade.fill(0); + + QPainter p(&m_shade); + p.fillRect(rect(), m_alpha_gradient); + + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + QLinearGradient fade(0, 0, 0, height()); + fade.setColorAt(0, QColor(0, 0, 0, 255)); + fade.setColorAt(1, QColor(0, 0, 0, 0)); + p.fillRect(rect(), fade); + + } else { + m_shade = QImage(size(), QImage::Format_RGB32); + QLinearGradient shade(0, 0, 0, height()); + shade.setColorAt(1, Qt::black); + + if (m_shade_type == RedShade) + shade.setColorAt(0, Qt::red); + else if (m_shade_type == GreenShade) + shade.setColorAt(0, Qt::green); + else + shade.setColorAt(0, Qt::blue); + + QPainter p(&m_shade); + p.fillRect(rect(), shade); + } + } + + +} + + +GradientEditor::GradientEditor(QWidget *parent) + : QWidget(parent) +{ + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setSpacing(1); + vbox->setMargin(1); + + m_red_shade = new ShadeWidget(ShadeWidget::RedShade, this); + m_green_shade = new ShadeWidget(ShadeWidget::GreenShade, this); + m_blue_shade = new ShadeWidget(ShadeWidget::BlueShade, this); + m_alpha_shade = new ShadeWidget(ShadeWidget::ARGBShade, this); + + vbox->addWidget(m_red_shade); + vbox->addWidget(m_green_shade); + vbox->addWidget(m_blue_shade); + vbox->addWidget(m_alpha_shade); + + connect(m_red_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); + connect(m_green_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); + connect(m_blue_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); + connect(m_alpha_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated())); +} + + +inline static bool x_less_than(const QPointF &p1, const QPointF &p2) +{ + return p1.x() < p2.x(); +} + + +void GradientEditor::pointsUpdated() +{ + qreal w = m_alpha_shade->width(); + + QGradientStops stops; + + QPolygonF points; + + points += m_red_shade->points(); + points += m_green_shade->points(); + points += m_blue_shade->points(); + points += m_alpha_shade->points(); + + qSort(points.begin(), points.end(), x_less_than); + + for (int i=0; i<points.size(); ++i) { + qreal x = int(points.at(i).x()); + if (i < points.size() - 1 && x == points.at(i+1).x()) + continue; + QColor color((0x00ff0000 & m_red_shade->colorAt(int(x))) >> 16, + (0x0000ff00 & m_green_shade->colorAt(int(x))) >> 8, + (0x000000ff & m_blue_shade->colorAt(int(x))), + (0xff000000 & m_alpha_shade->colorAt(int(x))) >> 24); + + if (x / w > 1) + return; + + stops << QGradientStop(x / w, color); + } + + m_alpha_shade->setGradientStops(stops); + + emit gradientStopsChanged(stops); +} + + +static void set_shade_points(const QPolygonF &points, ShadeWidget *shade) +{ + shade->hoverPoints()->setPoints(points); + shade->hoverPoints()->setPointLock(0, HoverPoints::LockToLeft); + shade->hoverPoints()->setPointLock(points.size() - 1, HoverPoints::LockToRight); + shade->update(); +} + +void GradientEditor::setGradientStops(const QGradientStops &stops) +{ + QPolygonF pts_red, pts_green, pts_blue, pts_alpha; + + qreal h_red = m_red_shade->height(); + qreal h_green = m_green_shade->height(); + qreal h_blue = m_blue_shade->height(); + qreal h_alpha = m_alpha_shade->height(); + + for (int i=0; i<stops.size(); ++i) { + qreal pos = stops.at(i).first; + QRgb color = stops.at(i).second.rgba(); + pts_red << QPointF(pos * m_red_shade->width(), h_red - qRed(color) * h_red / 255); + pts_green << QPointF(pos * m_green_shade->width(), h_green - qGreen(color) * h_green / 255); + pts_blue << QPointF(pos * m_blue_shade->width(), h_blue - qBlue(color) * h_blue / 255); + pts_alpha << QPointF(pos * m_alpha_shade->width(), h_alpha - qAlpha(color) * h_alpha / 255); + } + + set_shade_points(pts_red, m_red_shade); + set_shade_points(pts_green, m_green_shade); + set_shade_points(pts_blue, m_blue_shade); + set_shade_points(pts_alpha, m_alpha_shade); + +} + +GradientWidget::GradientWidget(QWidget *parent) + : QWidget(parent) +{ + setWindowTitle(tr("Gradients")); + + m_renderer = new GradientRenderer(this); + + QGroupBox *mainGroup = new QGroupBox(this); + mainGroup->setTitle(tr("Gradients")); + + QGroupBox *editorGroup = new QGroupBox(mainGroup); + editorGroup->setTitle(tr("Color Editor")); + m_editor = new GradientEditor(editorGroup); + + QGroupBox *typeGroup = new QGroupBox(mainGroup); + typeGroup->setTitle(tr("Gradient Type")); + m_linearButton = new QRadioButton(tr("Linear Gradient"), typeGroup); + m_radialButton = new QRadioButton(tr("Radial Gradient"), typeGroup); + m_conicalButton = new QRadioButton(tr("Conical Gradient"), typeGroup); + + QGroupBox *spreadGroup = new QGroupBox(mainGroup); + spreadGroup->setTitle(tr("Spread Method")); + m_padSpreadButton = new QRadioButton(tr("Pad Spread"), spreadGroup); + m_reflectSpreadButton = new QRadioButton(tr("Reflect Spread"), spreadGroup); + m_repeatSpreadButton = new QRadioButton(tr("Repeat Spread"), spreadGroup); + + QGroupBox *defaultsGroup = new QGroupBox(mainGroup); + defaultsGroup->setTitle(tr("Defaults")); + QPushButton *default1Button = new QPushButton(tr("1"), defaultsGroup); + QPushButton *default2Button = new QPushButton(tr("2"), defaultsGroup); + QPushButton *default3Button = new QPushButton(tr("3"), defaultsGroup); + QPushButton *default4Button = new QPushButton(tr("Reset"), editorGroup); + + QPushButton *showSourceButton = new QPushButton(mainGroup); + showSourceButton->setText(tr("Show Source")); +#ifdef QT_OPENGL_SUPPORT + QPushButton *enableOpenGLButton = new QPushButton(mainGroup); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(true); + enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); + if (!QGLFormat::hasOpenGL()) + enableOpenGLButton->hide(); +#endif + QPushButton *whatsThisButton = new QPushButton(mainGroup); + whatsThisButton->setText(tr("What's This?")); + whatsThisButton->setCheckable(true); + + // Layouts + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->addWidget(m_renderer); + mainLayout->addWidget(mainGroup); + + mainGroup->setFixedWidth(180); + QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); + mainGroupLayout->addWidget(editorGroup); + mainGroupLayout->addWidget(typeGroup); + mainGroupLayout->addWidget(spreadGroup); + mainGroupLayout->addWidget(defaultsGroup); + mainGroupLayout->addStretch(1); + mainGroupLayout->addWidget(showSourceButton); +#ifdef QT_OPENGL_SUPPORT + mainGroupLayout->addWidget(enableOpenGLButton); +#endif + mainGroupLayout->addWidget(whatsThisButton); + + QVBoxLayout *editorGroupLayout = new QVBoxLayout(editorGroup); + editorGroupLayout->addWidget(m_editor); + + QVBoxLayout *typeGroupLayout = new QVBoxLayout(typeGroup); + typeGroupLayout->addWidget(m_linearButton); + typeGroupLayout->addWidget(m_radialButton); + typeGroupLayout->addWidget(m_conicalButton); + + QVBoxLayout *spreadGroupLayout = new QVBoxLayout(spreadGroup); + spreadGroupLayout->addWidget(m_padSpreadButton); + spreadGroupLayout->addWidget(m_repeatSpreadButton); + spreadGroupLayout->addWidget(m_reflectSpreadButton); + + QHBoxLayout *defaultsGroupLayout = new QHBoxLayout(defaultsGroup); + defaultsGroupLayout->addWidget(default1Button); + defaultsGroupLayout->addWidget(default2Button); + defaultsGroupLayout->addWidget(default3Button); + editorGroupLayout->addWidget(default4Button); + + connect(m_editor, SIGNAL(gradientStopsChanged(QGradientStops)), + m_renderer, SLOT(setGradientStops(QGradientStops))); + + connect(m_linearButton, SIGNAL(clicked()), m_renderer, SLOT(setLinearGradient())); + connect(m_radialButton, SIGNAL(clicked()), m_renderer, SLOT(setRadialGradient())); + connect(m_conicalButton, SIGNAL(clicked()), m_renderer, SLOT(setConicalGradient())); + + connect(m_padSpreadButton, SIGNAL(clicked()), m_renderer, SLOT(setPadSpread())); + connect(m_reflectSpreadButton, SIGNAL(clicked()), m_renderer, SLOT(setReflectSpread())); + connect(m_repeatSpreadButton, SIGNAL(clicked()), m_renderer, SLOT(setRepeatSpread())); + + connect(default1Button, SIGNAL(clicked()), this, SLOT(setDefault1())); + connect(default2Button, SIGNAL(clicked()), this, SLOT(setDefault2())); + connect(default3Button, SIGNAL(clicked()), this, SLOT(setDefault3())); + connect(default4Button, SIGNAL(clicked()), this, SLOT(setDefault4())); + + connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource())); +#ifdef QT_OPENGL_SUPPORT + connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); +#endif + connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool))); + connect(whatsThisButton, SIGNAL(clicked(bool)), + m_renderer->hoverPoints(), SLOT(setDisabled(bool))); + connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)), + whatsThisButton, SLOT(setChecked(bool))); + connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)), + m_renderer->hoverPoints(), SLOT(setDisabled(bool))); + + m_renderer->loadSourceFile(":res/gradients/gradients.cpp"); + m_renderer->loadDescription(":res/gradients/gradients.html"); + + QTimer::singleShot(50, this, SLOT(setDefault1())); +} + +void GradientWidget::setDefault(int config) +{ + QGradientStops stops; + QPolygonF points; + switch (config) { + case 1: + stops << QGradientStop(0.00, QColor::fromRgba(0)); + stops << QGradientStop(0.04, QColor::fromRgba(0xff131360)); + stops << QGradientStop(0.08, QColor::fromRgba(0xff202ccc)); + stops << QGradientStop(0.42, QColor::fromRgba(0xff93d3f9)); + stops << QGradientStop(0.51, QColor::fromRgba(0xffb3e6ff)); + stops << QGradientStop(0.73, QColor::fromRgba(0xffffffec)); + stops << QGradientStop(0.92, QColor::fromRgba(0xff5353d9)); + stops << QGradientStop(0.96, QColor::fromRgba(0xff262666)); + stops << QGradientStop(1.00, QColor::fromRgba(0)); + m_linearButton->animateClick(); + m_repeatSpreadButton->animateClick(); + break; + + case 2: + stops << QGradientStop(0.00, QColor::fromRgba(0xffffffff)); + stops << QGradientStop(0.11, QColor::fromRgba(0xfff9ffa0)); + stops << QGradientStop(0.13, QColor::fromRgba(0xfff9ff99)); + stops << QGradientStop(0.14, QColor::fromRgba(0xfff3ff86)); + stops << QGradientStop(0.49, QColor::fromRgba(0xff93b353)); + stops << QGradientStop(0.87, QColor::fromRgba(0xff264619)); + stops << QGradientStop(0.96, QColor::fromRgba(0xff0c1306)); + stops << QGradientStop(1.00, QColor::fromRgba(0)); + m_radialButton->animateClick(); + m_padSpreadButton->animateClick(); + break; + + case 3: + stops << QGradientStop(0.00, QColor::fromRgba(0)); + stops << QGradientStop(0.10, QColor::fromRgba(0xffe0cc73)); + stops << QGradientStop(0.17, QColor::fromRgba(0xffc6a006)); + stops << QGradientStop(0.46, QColor::fromRgba(0xff600659)); + stops << QGradientStop(0.72, QColor::fromRgba(0xff0680ac)); + stops << QGradientStop(0.92, QColor::fromRgba(0xffb9d9e6)); + stops << QGradientStop(1.00, QColor::fromRgba(0)); + m_conicalButton->animateClick(); + m_padSpreadButton->animateClick(); + break; + + case 4: + stops << QGradientStop(0.00, QColor::fromRgba(0xff000000)); + stops << QGradientStop(1.00, QColor::fromRgba(0xffffffff)); + break; + + default: + qWarning("bad default: %d\n", config); + break; + } + + QPolygonF pts; + int h_off = m_renderer->width() / 10; + int v_off = m_renderer->height() / 8; + pts << QPointF(m_renderer->width() / 2, m_renderer->height() / 2) + << QPointF(m_renderer->width() / 2 - h_off, m_renderer->height() / 2 - v_off); + + m_editor->setGradientStops(stops); + m_renderer->hoverPoints()->setPoints(pts); + m_renderer->setGradientStops(stops); +} + + +GradientRenderer::GradientRenderer(QWidget *parent) + : ArthurFrame(parent) +{ + m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape); + m_hoverPoints->setPointSize(QSize(20, 20)); + m_hoverPoints->setConnectionType(HoverPoints::NoConnection); + m_hoverPoints->setEditable(false); + + QVector<QPointF> points; + points << QPointF(100, 100) << QPointF(200, 200); + m_hoverPoints->setPoints(points); + + m_spread = QGradient::PadSpread; + m_gradientType = Qt::LinearGradientPattern; +} + +void GradientRenderer::setGradientStops(const QGradientStops &stops) +{ + m_stops = stops; + update(); +} + + +void GradientRenderer::mousePressEvent(QMouseEvent *) +{ + setDescriptionEnabled(false); +} + +void GradientRenderer::paint(QPainter *p) +{ + QPolygonF pts = m_hoverPoints->points(); + + QGradient g; + + if (m_gradientType == Qt::LinearGradientPattern) { + g = QLinearGradient(pts.at(0), pts.at(1)); + + } else if (m_gradientType == Qt::RadialGradientPattern) { + g = QRadialGradient(pts.at(0), qMin(width(), height()) / 3.0, pts.at(1)); + + } else { + QLineF l(pts.at(0), pts.at(1)); + qreal angle = l.angle(QLineF(0, 0, 1, 0)); + if (l.dy() > 0) + angle = 360 - angle; + g = QConicalGradient(pts.at(0), angle); + } + + for (int i=0; i<m_stops.size(); ++i) + g.setColorAt(m_stops.at(i).first, m_stops.at(i).second); + + g.setSpread(m_spread); + + p->setBrush(g); + p->setPen(Qt::NoPen); + + p->drawRect(rect()); + +} diff --git a/demos/gradients/gradients.h b/demos/gradients/gradients.h new file mode 100644 index 0000000000..bdd5c713ec --- /dev/null +++ b/demos/gradients/gradients.h @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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$ +** +****************************************************************************/ + +#ifndef GRADIENTS_H +#define GRADIENTS_H + +#include "arthurwidgets.h" + +#include <QtGui> + +class HoverPoints; + + +class ShadeWidget : public QWidget +{ + Q_OBJECT +public: + enum ShadeType { + RedShade, + GreenShade, + BlueShade, + ARGBShade + }; + + ShadeWidget(ShadeType type, QWidget *parent); + + void setGradientStops(const QGradientStops &stops); + + void paintEvent(QPaintEvent *e); + + QSize sizeHint() const { return QSize(150, 40); } + QPolygonF points() const; + + HoverPoints *hoverPoints() const { return m_hoverPoints; } + + uint colorAt(int x); + +signals: + void colorsChanged(); + +private: + void generateShade(); + + ShadeType m_shade_type; + QImage m_shade; + HoverPoints *m_hoverPoints; + QLinearGradient m_alpha_gradient; +}; + +class GradientEditor : public QWidget +{ + Q_OBJECT +public: + GradientEditor(QWidget *parent); + + void setGradientStops(const QGradientStops &stops); + +public slots: + void pointsUpdated(); + +signals: + void gradientStopsChanged(const QGradientStops &stops); + +private: + ShadeWidget *m_red_shade; + ShadeWidget *m_green_shade; + ShadeWidget *m_blue_shade; + ShadeWidget *m_alpha_shade; +}; + + +class GradientRenderer : public ArthurFrame +{ + Q_OBJECT +public: + GradientRenderer(QWidget *parent); + void paint(QPainter *p); + + QSize sizeHint() const { return QSize(400, 400); } + + HoverPoints *hoverPoints() const { return m_hoverPoints; } + void mousePressEvent(QMouseEvent *e); + +public slots: + void setGradientStops(const QGradientStops &stops); + + void setPadSpread() { m_spread = QGradient::PadSpread; update(); } + void setRepeatSpread() { m_spread = QGradient::RepeatSpread; update(); } + void setReflectSpread() { m_spread = QGradient::ReflectSpread; update(); } + + void setLinearGradient() { m_gradientType = Qt::LinearGradientPattern; update(); } + void setRadialGradient() { m_gradientType = Qt::RadialGradientPattern; update(); } + void setConicalGradient() { m_gradientType = Qt::ConicalGradientPattern; update(); } + + +private: + QGradientStops m_stops; + HoverPoints *m_hoverPoints; + + QGradient::Spread m_spread; + Qt::BrushStyle m_gradientType; +}; + + +class GradientWidget : public QWidget +{ + Q_OBJECT +public: + GradientWidget(QWidget *parent); + +public slots: + void setDefault1() { setDefault(1); } + void setDefault2() { setDefault(2); } + void setDefault3() { setDefault(3); } + void setDefault4() { setDefault(4); } + +private: + void setDefault(int i); + + GradientRenderer *m_renderer; + GradientEditor *m_editor; + + QRadioButton *m_linearButton; + QRadioButton *m_radialButton; + QRadioButton *m_conicalButton; + QRadioButton *m_padSpreadButton; + QRadioButton *m_reflectSpreadButton; + QRadioButton *m_repeatSpreadButton; + +}; + +#endif // GRADIENTS_H diff --git a/demos/gradients/gradients.html b/demos/gradients/gradients.html new file mode 100644 index 0000000000..1ea2c0ed6c --- /dev/null +++ b/demos/gradients/gradients.html @@ -0,0 +1,31 @@ +<html> +<center> +<h2>Gradients</h2> +</center> + +<p>In this demo we show the various types of gradients that can +be used in Qt.</p> + +<p>There are three types of gradients: + +<ul> + <li><b>Linear</b> gradients interpolate colors between start and end + points.</li> + <li><b>Radial</b> gradients interpolate colors between a focal point and the + points on a circle surrounding it.</li> + <li><b>Conical</b> gradients interpolate colors around a center point.</li> +</ul> + +</p> + +<p>The panel on the right contains a color table editor that defines +the colors in the gradient. The three topmost controls determine the red, +green and blue components while the last defines the alpha of the +gradient. You can move points, and add new ones, by clicking with the left +mouse button, and remove points by clicking with the right button.</p> + +<p>There are three default configurations available at the bottom of +the page that are provided as suggestions on how a color table could be +configured.</p> + +</html> diff --git a/demos/gradients/gradients.pro b/demos/gradients/gradients.pro new file mode 100644 index 0000000000..ba8910351a --- /dev/null +++ b/demos/gradients/gradients.pro @@ -0,0 +1,20 @@ +SOURCES += main.cpp gradients.cpp +HEADERS += gradients.h + +SHARED_FOLDER = ../shared + +include($$SHARED_FOLDER/shared.pri) + +RESOURCES += gradients.qrc +contains(QT_CONFIG, opengl) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/gradients +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.html +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/gradients +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/demos/gradients/gradients.qrc b/demos/gradients/gradients.qrc new file mode 100644 index 0000000000..fb971eb17b --- /dev/null +++ b/demos/gradients/gradients.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/gradients"> + <file>gradients.cpp</file> + <file>gradients.html</file> +</qresource> +</RCC> diff --git a/demos/gradients/main.cpp b/demos/gradients/main.cpp new file mode 100644 index 0000000000..a27951ce4a --- /dev/null +++ b/demos/gradients/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "gradients.h" + +#include <QApplication> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(gradients); + + QApplication app(argc, argv); + + GradientWidget gradientWidget(0); + QStyle *arthurStyle = new ArthurStyle(); + gradientWidget.setStyle(arthurStyle); + QList<QWidget *> widgets = gradientWidget.findChildren<QWidget *>(); + foreach (QWidget *w, widgets) { + w->setStyle(arthurStyle); + w->setAttribute(Qt::WA_AcceptTouchEvents); + } + gradientWidget.show(); + + return app.exec(); +} diff --git a/demos/interview/README b/demos/interview/README new file mode 100644 index 0000000000..50894428f6 --- /dev/null +++ b/demos/interview/README @@ -0,0 +1,2 @@ +The interview example shows the same model and selection being shared +between three different views. diff --git a/demos/interview/images/folder.png b/demos/interview/images/folder.png Binary files differnew file mode 100644 index 0000000000..589fd2df59 --- /dev/null +++ b/demos/interview/images/folder.png diff --git a/demos/interview/images/interview.png b/demos/interview/images/interview.png Binary files differnew file mode 100644 index 0000000000..0c3d690258 --- /dev/null +++ b/demos/interview/images/interview.png diff --git a/demos/interview/images/services.png b/demos/interview/images/services.png Binary files differnew file mode 100644 index 0000000000..6b2ad969d4 --- /dev/null +++ b/demos/interview/images/services.png diff --git a/demos/interview/interview.pro b/demos/interview/interview.pro new file mode 100644 index 0000000000..c69f7ba975 --- /dev/null +++ b/demos/interview/interview.pro @@ -0,0 +1,19 @@ +TEMPLATE = app + +CONFIG += qt warn_on +HEADERS += model.h +SOURCES += model.cpp main.cpp +RESOURCES += interview.qrc + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/interview +sources.files = $$SOURCES $$HEADERS $$RESOURCES README *.pro images +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/interview +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) diff --git a/demos/interview/interview.qrc b/demos/interview/interview.qrc new file mode 100644 index 0000000000..b28ea34d8a --- /dev/null +++ b/demos/interview/interview.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> + <file>images/folder.png</file> + <file>images/services.png</file> + <file>images/interview.png</file> +</qresource> +</RCC> diff --git a/demos/interview/main.cpp b/demos/interview/main.cpp new file mode 100644 index 0000000000..85d0e960a6 --- /dev/null +++ b/demos/interview/main.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |