diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /demos/pathstroke | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'demos/pathstroke')
-rw-r--r-- | demos/pathstroke/main.cpp | 69 | ||||
-rw-r--r-- | demos/pathstroke/pathstroke.cpp | 599 | ||||
-rw-r--r-- | demos/pathstroke/pathstroke.h | 168 | ||||
-rw-r--r-- | demos/pathstroke/pathstroke.html | 20 | ||||
-rw-r--r-- | demos/pathstroke/pathstroke.pro | 20 | ||||
-rw-r--r-- | demos/pathstroke/pathstroke.qrc | 6 |
6 files changed, 882 insertions, 0 deletions
diff --git a/demos/pathstroke/main.cpp b/demos/pathstroke/main.cpp new file mode 100644 index 0000000..613d835 --- /dev/null +++ b/demos/pathstroke/main.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pathstroke.h" +#include <QApplication> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(pathstroke); + + QApplication app(argc, argv); + + bool smallScreen = false; + for (int i=0; i<argc; i++) + if (QString(argv[i]) == "-small-screen") + smallScreen = true; + + PathStrokeWidget pathStrokeWidget(smallScreen); + QStyle *arthurStyle = new ArthurStyle(); + pathStrokeWidget.setStyle(arthurStyle); + QList<QWidget *> widgets = qFindChildren<QWidget *>(&pathStrokeWidget); + foreach (QWidget *w, widgets) + w->setStyle(arthurStyle); + + if (smallScreen) + pathStrokeWidget.showFullScreen(); + else + pathStrokeWidget.show(); + + return app.exec(); +} diff --git a/demos/pathstroke/pathstroke.cpp b/demos/pathstroke/pathstroke.cpp new file mode 100644 index 0000000..d079490 --- /dev/null +++ b/demos/pathstroke/pathstroke.cpp @@ -0,0 +1,599 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pathstroke.h" +#include "arthurstyle.h" +#include "arthurwidgets.h" + +#include <stdio.h> + +extern void draw_round_rect(QPainter *p, const QRect &bounds, int radius); + + +PathStrokeControls::PathStrokeControls(QWidget* parent, PathStrokeRenderer* renderer, bool smallScreen) + : QWidget(parent) +{ + m_renderer = renderer; + + if (smallScreen) + layoutForSmallScreens(); + else + layoutForDesktop(); +} + +void PathStrokeControls::createCommonControls(QWidget* parent) +{ + m_capGroup = new QGroupBox(parent); + m_capGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + QRadioButton *flatCap = new QRadioButton(m_capGroup); + QRadioButton *squareCap = new QRadioButton(m_capGroup); + QRadioButton *roundCap = new QRadioButton(m_capGroup); + m_capGroup->setTitle(tr("Cap Style")); + flatCap->setText(tr("Flat")); + squareCap->setText(tr("Square")); + roundCap->setText(tr("Round")); + flatCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + squareCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + roundCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + m_joinGroup = new QGroupBox(parent); + m_joinGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + QRadioButton *bevelJoin = new QRadioButton(m_joinGroup); + QRadioButton *miterJoin = new QRadioButton(m_joinGroup); + QRadioButton *roundJoin = new QRadioButton(m_joinGroup); + m_joinGroup->setTitle(tr("Join Style")); + bevelJoin->setText(tr("Bevel")); + miterJoin->setText(tr("Miter")); + roundJoin->setText(tr("Round")); + + m_styleGroup = new QGroupBox(parent); + m_styleGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + QRadioButton *solidLine = new QRadioButton(m_styleGroup); + QRadioButton *dashLine = new QRadioButton(m_styleGroup); + QRadioButton *dotLine = new QRadioButton(m_styleGroup); + QRadioButton *dashDotLine = new QRadioButton(m_styleGroup); + QRadioButton *dashDotDotLine = new QRadioButton(m_styleGroup); + QRadioButton *customDashLine = new QRadioButton(m_styleGroup); + m_styleGroup->setTitle(tr("Pen Style")); + + QPixmap line_solid(":res/images/line_solid.png"); + solidLine->setIcon(line_solid); + solidLine->setIconSize(line_solid.size()); + QPixmap line_dashed(":res/images/line_dashed.png"); + dashLine->setIcon(line_dashed); + dashLine->setIconSize(line_dashed.size()); + QPixmap line_dotted(":res/images/line_dotted.png"); + dotLine->setIcon(line_dotted); + dotLine->setIconSize(line_dotted.size()); + QPixmap line_dash_dot(":res/images/line_dash_dot.png"); + dashDotLine->setIcon(line_dash_dot); + dashDotLine->setIconSize(line_dash_dot.size()); + QPixmap line_dash_dot_dot(":res/images/line_dash_dot_dot.png"); + dashDotDotLine->setIcon(line_dash_dot_dot); + dashDotDotLine->setIconSize(line_dash_dot_dot.size()); + customDashLine->setText(tr("Custom")); + + int fixedHeight = bevelJoin->sizeHint().height(); + solidLine->setFixedHeight(fixedHeight); + dashLine->setFixedHeight(fixedHeight); + dotLine->setFixedHeight(fixedHeight); + dashDotLine->setFixedHeight(fixedHeight); + dashDotDotLine->setFixedHeight(fixedHeight); + + m_pathModeGroup = new QGroupBox(parent); + m_pathModeGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + QRadioButton *curveMode = new QRadioButton(m_pathModeGroup); + QRadioButton *lineMode = new QRadioButton(m_pathModeGroup); + m_pathModeGroup->setTitle(tr("Line Style")); + curveMode->setText(tr("Curves")); + lineMode->setText(tr("Lines")); + + + // Layouts + QVBoxLayout *capGroupLayout = new QVBoxLayout(m_capGroup); + capGroupLayout->addWidget(flatCap); + capGroupLayout->addWidget(squareCap); + capGroupLayout->addWidget(roundCap); + + QVBoxLayout *joinGroupLayout = new QVBoxLayout(m_joinGroup); + joinGroupLayout->addWidget(bevelJoin); + joinGroupLayout->addWidget(miterJoin); + joinGroupLayout->addWidget(roundJoin); + + QVBoxLayout *styleGroupLayout = new QVBoxLayout(m_styleGroup); + styleGroupLayout->addWidget(solidLine); + styleGroupLayout->addWidget(dashLine); + styleGroupLayout->addWidget(dotLine); + styleGroupLayout->addWidget(dashDotLine); + styleGroupLayout->addWidget(dashDotDotLine); + styleGroupLayout->addWidget(customDashLine); + + QVBoxLayout *pathModeGroupLayout = new QVBoxLayout(m_pathModeGroup); + pathModeGroupLayout->addWidget(curveMode); + pathModeGroupLayout->addWidget(lineMode); + + + // Connections + connect(flatCap, SIGNAL(clicked()), m_renderer, SLOT(setFlatCap())); + connect(squareCap, SIGNAL(clicked()), m_renderer, SLOT(setSquareCap())); + connect(roundCap, SIGNAL(clicked()), m_renderer, SLOT(setRoundCap())); + + connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin())); + connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin())); + connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin())); + + connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode())); + connect(lineMode, SIGNAL(clicked()), m_renderer, SLOT(setLineMode())); + + connect(solidLine, SIGNAL(clicked()), m_renderer, SLOT(setSolidLine())); + connect(dashLine, SIGNAL(clicked()), m_renderer, SLOT(setDashLine())); + connect(dotLine, SIGNAL(clicked()), m_renderer, SLOT(setDotLine())); + connect(dashDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotLine())); + connect(dashDotDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotDotLine())); + connect(customDashLine, SIGNAL(clicked()), m_renderer, SLOT(setCustomDashLine())); + + // Set the defaults: + flatCap->setChecked(true); + bevelJoin->setChecked(true); + curveMode->setChecked(true); + solidLine->setChecked(true); +} + + +void PathStrokeControls::layoutForDesktop() +{ + QGroupBox *mainGroup = new QGroupBox(this); + mainGroup->setFixedWidth(180); + mainGroup->setTitle(tr("Path Stroking")); + + createCommonControls(mainGroup); + + QGroupBox* penWidthGroup = new QGroupBox(mainGroup); + QSlider *penWidth = new QSlider(Qt::Horizontal, penWidthGroup); + penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + penWidthGroup->setTitle(tr("Pen Width")); + penWidth->setRange(0, 500); + + QPushButton *animated = new QPushButton(mainGroup); + animated->setText(tr("Animate")); + animated->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); + + + // Layouts: + QVBoxLayout *penWidthLayout = new QVBoxLayout(penWidthGroup); + penWidthLayout->addWidget(penWidth); + + QVBoxLayout * mainLayout = new QVBoxLayout(this); + mainLayout->setMargin(0); + mainLayout->addWidget(mainGroup); + + QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); + mainGroupLayout->setMargin(3); + mainGroupLayout->addWidget(m_capGroup); + mainGroupLayout->addWidget(m_joinGroup); + mainGroupLayout->addWidget(m_styleGroup); + mainGroupLayout->addWidget(penWidthGroup); + mainGroupLayout->addWidget(m_pathModeGroup); + mainGroupLayout->addWidget(animated); + mainGroupLayout->addStretch(1); + mainGroupLayout->addWidget(showSourceButton); +#ifdef QT_OPENGL_SUPPORT + mainGroupLayout->addWidget(enableOpenGLButton); +#endif + mainGroupLayout->addWidget(whatsThisButton); + + + // Set up connections + connect(animated, SIGNAL(toggled(bool)), + m_renderer, SLOT(setAnimation(bool))); + + connect(penWidth, SIGNAL(valueChanged(int)), + m_renderer, SLOT(setPenWidth(int))); + + 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(m_renderer, SIGNAL(descriptionEnabledChanged(bool)), + whatsThisButton, SLOT(setChecked(bool))); + + + // Set the defaults + animated->setChecked(true); + penWidth->setValue(50); + +} + +void PathStrokeControls::layoutForSmallScreens() +{ + createCommonControls(this); + + m_capGroup->layout()->setMargin(0); + m_joinGroup->layout()->setMargin(0); + m_styleGroup->layout()->setMargin(0); + m_pathModeGroup->layout()->setMargin(0); + + QPushButton* okBtn = new QPushButton(tr("OK"), this); + okBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + okBtn->setMinimumSize(100,okBtn->minimumSize().height()); + + QPushButton* quitBtn = new QPushButton(tr("Quit"), this); + quitBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + quitBtn->setMinimumSize(100, okBtn->minimumSize().height()); + + QLabel *penWidthLabel = new QLabel(tr(" Width:")); + QSlider *penWidth = new QSlider(Qt::Horizontal, this); + penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + penWidth->setRange(0, 500); + +#ifdef QT_OPENGL_SUPPORT + QPushButton *enableOpenGLButton = new QPushButton(this); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(true); + enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); + if (!QGLFormat::hasOpenGL()) + enableOpenGLButton->hide(); +#endif + + // Layouts: + QHBoxLayout *penWidthLayout = new QHBoxLayout(0); + penWidthLayout->addWidget(penWidthLabel, 0, Qt::AlignRight); + penWidthLayout->addWidget(penWidth); + + QVBoxLayout *leftLayout = new QVBoxLayout(0); + leftLayout->addWidget(m_capGroup); + leftLayout->addWidget(m_joinGroup); +#ifdef QT_OPENGL_SUPPORT + leftLayout->addWidget(enableOpenGLButton); +#endif + leftLayout->addLayout(penWidthLayout); + + QVBoxLayout *rightLayout = new QVBoxLayout(0); + rightLayout->addWidget(m_styleGroup); + rightLayout->addWidget(m_pathModeGroup); + + QGridLayout *mainLayout = new QGridLayout(this); + mainLayout->setMargin(0); + + // Add spacers around the form items so we don't look stupid at higher resolutions + mainLayout->addItem(new QSpacerItem(0,0), 0, 0, 1, 4); + mainLayout->addItem(new QSpacerItem(0,0), 1, 0, 2, 1); + mainLayout->addItem(new QSpacerItem(0,0), 1, 3, 2, 1); + mainLayout->addItem(new QSpacerItem(0,0), 3, 0, 1, 4); + + mainLayout->addLayout(leftLayout, 1, 1); + mainLayout->addLayout(rightLayout, 1, 2); + mainLayout->addWidget(quitBtn, 2, 1, Qt::AlignHCenter | Qt::AlignTop); + mainLayout->addWidget(okBtn, 2, 2, Qt::AlignHCenter | Qt::AlignTop); + +#ifdef QT_OPENGL_SUPPORT + connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); +#endif + + connect(penWidth, SIGNAL(valueChanged(int)), m_renderer, SLOT(setPenWidth(int))); + connect(quitBtn, SIGNAL(clicked()), this, SLOT(emitQuitSignal())); + connect(okBtn, SIGNAL(clicked()), this, SLOT(emitOkSignal())); + + m_renderer->setAnimation(true); + penWidth->setValue(50); +} + +void PathStrokeControls::emitQuitSignal() +{ emit quitPressed(); } + +void PathStrokeControls::emitOkSignal() +{ emit okPressed(); } + + +PathStrokeWidget::PathStrokeWidget(bool smallScreen) +{ + setWindowTitle(tr("Path Stroking")); + + // Widget construction and property setting + m_renderer = new PathStrokeRenderer(this, smallScreen); + + m_controls = new PathStrokeControls(0, m_renderer, smallScreen); + + // Layouting + QHBoxLayout *viewLayout = new QHBoxLayout(this); + viewLayout->addWidget(m_renderer); + + if (!smallScreen) + viewLayout->addWidget(m_controls); + + m_renderer->loadSourceFile(":res/pathstroke/pathstroke.cpp"); + m_renderer->loadDescription(":res/pathstroke/pathstroke.html"); + + 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 PathStrokeWidget::showControls() +{ + m_controls->showFullScreen(); +} + + +void PathStrokeWidget::hideControls() +{ + m_controls->hide(); +} + + +void PathStrokeWidget::setStyle( QStyle * style ) +{ + QWidget::setStyle(style); + if (m_controls != 0) + { + m_controls->setStyle(style); + + QList<QWidget *> widgets = qFindChildren<QWidget *>(m_controls); + foreach (QWidget *w, widgets) + w->setStyle(style); + } +} + + +PathStrokeRenderer::PathStrokeRenderer(QWidget *parent, bool smallScreen) + : ArthurFrame(parent) +{ + m_smallScreen = smallScreen; + m_pointSize = 10; + m_activePoint = -1; + m_capStyle = Qt::FlatCap; + m_joinStyle = Qt::BevelJoin; + m_pathMode = CurveMode; + m_penWidth = 1; + m_penStyle = Qt::SolidLine; + m_wasAnimated = true; + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +void PathStrokeRenderer::paint(QPainter *painter) +{ + if (m_points.isEmpty()) + initializePoints(); + + painter->setRenderHint(QPainter::Antialiasing); + + QPalette pal = palette(); + painter->setPen(Qt::NoPen); + + // Construct the path + QPainterPath path; + path.moveTo(m_points.at(0)); + + if (m_pathMode == LineMode) { + for (int i=1; i<m_points.size(); ++i) { + path.lineTo(m_points.at(i)); + } + } else { + int i=1; + while (i + 2 < m_points.size()) { + path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2)); + i += 3; + } + while (i < m_points.size()) { + path.lineTo(m_points.at(i)); + ++i; + } + } + + // Draw the path + { + QColor lg = Qt::red; + + // The "custom" pen + if (m_penStyle == Qt::NoPen) { + QPainterPathStroker stroker; + stroker.setWidth(m_penWidth); + stroker.setJoinStyle(m_joinStyle); + stroker.setCapStyle(m_capStyle); + + QVector<qreal> dashes; + qreal space = 4; + dashes << 1 << space + << 3 << space + << 9 << space + << 27 << space + << 9 << space + << 3 << space; + stroker.setDashPattern(dashes); + QPainterPath stroke = stroker.createStroke(path); + painter->fillPath(stroke, lg); + + } else { + QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle); + painter->strokePath(path, pen); + } + } + + if (1) { + // Draw the control points + painter->setPen(QColor(50, 100, 120, 200)); + painter->setBrush(QColor(200, 200, 210, 120)); + for (int i=0; i<m_points.size(); ++i) { + QPointF pos = m_points.at(i); + painter->drawEllipse(QRectF(pos.x() - m_pointSize, + pos.y() - m_pointSize, + m_pointSize*2, m_pointSize*2)); + } + painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine)); + painter->setBrush(Qt::NoBrush); + painter->drawPolyline(m_points); + } + +} + +void PathStrokeRenderer::initializePoints() +{ + const int count = 7; + m_points.clear(); + m_vectors.clear(); + + QMatrix m; + qreal rot = 360 / count; + QPointF center(width() / 2, height() / 2); + QMatrix vm; + vm.shear(2, -1); + vm.scale(3, 3); + + for (int i=0; i<count; ++i) { + m_vectors << QPointF(.1f, .25f) * (m * vm); + m_points << QPointF(0, 100) * m + center; + m.rotate(rot); + } +} + +void PathStrokeRenderer::updatePoints() +{ + qreal pad = 10; + qreal left = pad; + qreal right = width() - pad; + qreal top = pad; + qreal bottom = height() - pad; + + Q_ASSERT(m_points.size() == m_vectors.size()); + for (int i=0; i<m_points.size(); ++i) { + + if (i == m_activePoint) + continue; + + QPointF pos = m_points.at(i); + QPointF vec = m_vectors.at(i); + pos += vec; + if (pos.x() < left || pos.x() > right) { + vec.setX(-vec.x()); + pos.setX(pos.x() < left ? left : right); + } if (pos.y() < top || pos.y() > bottom) { + vec.setY(-vec.y()); + pos.setY(pos.y() < top ? top : bottom); + } + m_points[i] = pos; + m_vectors[i] = vec; + } + update(); +} + +void PathStrokeRenderer::mousePressEvent(QMouseEvent *e) +{ + setDescriptionEnabled(false); + m_activePoint = -1; + qreal distance = -1; + for (int i=0; i<m_points.size(); ++i) { + qreal d = QLineF(e->pos(), m_points.at(i)).length(); + if ((distance < 0 && d < 8 * m_pointSize) || d < distance) { + distance = d; + m_activePoint = i; + } + } + + if (m_activePoint != -1) { + m_wasAnimated = m_timer.isActive(); + setAnimation(false); + mouseMoveEvent(e); + } + + // If we're not running in small screen mode, always assume we're dragging + m_mouseDrag = !m_smallScreen; + m_mousePress = e->pos(); +} + +void PathStrokeRenderer::mouseMoveEvent(QMouseEvent *e) +{ + // If we've moved more then 25 pixels, assume user is dragging + if (!m_mouseDrag && QPoint(m_mousePress - e->pos()).manhattanLength() > 25) + m_mouseDrag = true; + + if (m_mouseDrag && m_activePoint >= 0 && m_activePoint < m_points.size()) { + m_points[m_activePoint] = e->pos(); + update(); + } +} + +void PathStrokeRenderer::mouseReleaseEvent(QMouseEvent *) +{ + m_activePoint = -1; + setAnimation(m_wasAnimated); + + if (!m_mouseDrag && m_smallScreen) + emit clicked(); +} + +void PathStrokeRenderer::timerEvent(QTimerEvent *e) +{ + if (e->timerId() == m_timer.timerId()) { + updatePoints(); + QApplication::syncX(); + } // else if (e->timerId() == m_fpsTimer.timerId()) { +// emit frameRate(m_frameCount); +// m_frameCount = 0; +// } +} + +void PathStrokeRenderer::setAnimation(bool animation) +{ + m_timer.stop(); +// m_fpsTimer.stop(); + + if (animation) { + m_timer.start(25, this); +// m_fpsTimer.start(1000, this); +// m_frameCount = 0; + } +} diff --git a/demos/pathstroke/pathstroke.h b/demos/pathstroke/pathstroke.h new file mode 100644 index 0000000..99f17a7 --- /dev/null +++ b/demos/pathstroke/pathstroke.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PATHSTROKE_H +#define PATHSTROKE_H + +#include "arthurwidgets.h" +#include <QtGui> + +class PathStrokeRenderer : public ArthurFrame +{ + Q_OBJECT + Q_PROPERTY(bool animation READ animation WRITE setAnimation) + Q_PROPERTY(qreal penWidth READ realPenWidth WRITE setRealPenWidth) +public: + enum PathMode { CurveMode, LineMode }; + + PathStrokeRenderer(QWidget *parent, bool smallScreen = false); + + void paint(QPainter *); + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void timerEvent(QTimerEvent *e); + + QSize sizeHint() const { return QSize(500, 500); } + + bool animation() const { return m_timer.isActive(); } + + qreal realPenWidth() const { return m_penWidth; } + void setRealPenWidth(qreal penWidth) { m_penWidth = penWidth; update(); } + +signals: + void clicked(); + +public slots: + void setPenWidth(int penWidth) { m_penWidth = penWidth / 10.0; update(); } + void setAnimation(bool animation); + + void setFlatCap() { m_capStyle = Qt::FlatCap; update(); } + void setSquareCap() { m_capStyle = Qt::SquareCap; update(); } + void setRoundCap() { m_capStyle = Qt::RoundCap; update(); } + + void setBevelJoin() { m_joinStyle = Qt::BevelJoin; update(); } + void setMiterJoin() { m_joinStyle = Qt::MiterJoin; update(); } + void setRoundJoin() { m_joinStyle = Qt::RoundJoin; update(); } + + void setCurveMode() { m_pathMode = CurveMode; update(); } + void setLineMode() { m_pathMode = LineMode; update(); } + + void setSolidLine() { m_penStyle = Qt::SolidLine; update(); } + void setDashLine() { m_penStyle = Qt::DashLine; update(); } + void setDotLine() { m_penStyle = Qt::DotLine; update(); } + void setDashDotLine() { m_penStyle = Qt::DashDotLine; update(); } + void setDashDotDotLine() { m_penStyle = Qt::DashDotDotLine; update(); } + void setCustomDashLine() { m_penStyle = Qt::NoPen; update(); } + +private: + void initializePoints(); + void updatePoints(); + + QBasicTimer m_timer; + + PathMode m_pathMode; + + bool m_wasAnimated; + + qreal m_penWidth; + int m_pointCount; + int m_pointSize; + int m_activePoint; + QVector<QPointF> m_points; + QVector<QPointF> m_vectors; + + Qt::PenJoinStyle m_joinStyle; + Qt::PenCapStyle m_capStyle; + + Qt::PenStyle m_penStyle; + + bool m_smallScreen; + QPoint m_mousePress; + bool m_mouseDrag; +}; + +class PathStrokeControls : public QWidget +{ + Q_OBJECT +public: + PathStrokeControls(QWidget* parent, PathStrokeRenderer* renderer, bool smallScreen); + +signals: + void okPressed(); + void quitPressed(); + +private: + PathStrokeRenderer* m_renderer; + + QGroupBox *m_capGroup; + QGroupBox *m_joinGroup; + QGroupBox *m_styleGroup; + QGroupBox *m_pathModeGroup; + + void createCommonControls(QWidget* parent); + void layoutForDesktop(); + void layoutForSmallScreens(); + +private slots: + void emitQuitSignal(); + void emitOkSignal(); + +}; + +class PathStrokeWidget : public QWidget +{ + Q_OBJECT +public: + PathStrokeWidget(bool smallScreen); + void setStyle ( QStyle * style ); + +private: + PathStrokeRenderer *m_renderer; + PathStrokeControls *m_controls; + +private slots: + void showControls(); + void hideControls(); + +}; + +#endif // PATHSTROKE_H diff --git a/demos/pathstroke/pathstroke.html b/demos/pathstroke/pathstroke.html new file mode 100644 index 0000000..9e7e50d --- /dev/null +++ b/demos/pathstroke/pathstroke.html @@ -0,0 +1,20 @@ +<html> +<center> +<h2>Primitive Stroking</h2> +</center> + +<p>In this demo we show some of the various types of pens that can be +used in Qt.</p> + +<p>Qt defines cap styles for how the end points are treated and join +styles for how path segments are joined together. A standard set of +predefined dash patterns are also included that can be used with +<code>QPen</code>.</p> + +<p>In addition to the predefined patterns available in +<code>QPen</code> we also demonstrate direct use of the +<code>QPainterPathStroker</code> class which can be used to define +custom dash patterns. You can see this by enabling the +<i>Custom Pattern</i> option.</p> + +</html> diff --git a/demos/pathstroke/pathstroke.pro b/demos/pathstroke/pathstroke.pro new file mode 100644 index 0000000..50b4de2 --- /dev/null +++ b/demos/pathstroke/pathstroke.pro @@ -0,0 +1,20 @@ +SOURCES += main.cpp pathstroke.cpp +HEADERS += pathstroke.h + +SHARED_FOLDER = ../shared + +include($$SHARED_FOLDER/shared.pri) + +RESOURCES += pathstroke.qrc + +contains(QT_CONFIG, opengl) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/pathstroke +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.html +sources.path = $$[QT_INSTALL_DEMOS]/pathstroke +INSTALLS += target sources + diff --git a/demos/pathstroke/pathstroke.qrc b/demos/pathstroke/pathstroke.qrc new file mode 100644 index 0000000..a9a7234 --- /dev/null +++ b/demos/pathstroke/pathstroke.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/pathstroke"> + <file>pathstroke.cpp</file> + <file>pathstroke.html</file> +</qresource> +</RCC> |