source: trunk/demos/pathstroke/pathstroke.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 23.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the demonstration applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "pathstroke.h"
43#include "arthurstyle.h"
44#include "arthurwidgets.h"
45
46#include <stdio.h>
47
48extern void draw_round_rect(QPainter *p, const QRect &bounds, int radius);
49
50
51PathStrokeControls::PathStrokeControls(QWidget* parent, PathStrokeRenderer* renderer, bool smallScreen)
52 : QWidget(parent)
53{
54 m_renderer = renderer;
55
56 if (smallScreen)
57 layoutForSmallScreens();
58 else
59 layoutForDesktop();
60}
61
62void PathStrokeControls::createCommonControls(QWidget* parent)
63{
64 m_capGroup = new QGroupBox(parent);
65 m_capGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
66 QRadioButton *flatCap = new QRadioButton(m_capGroup);
67 QRadioButton *squareCap = new QRadioButton(m_capGroup);
68 QRadioButton *roundCap = new QRadioButton(m_capGroup);
69 m_capGroup->setTitle(tr("Cap Style"));
70 flatCap->setText(tr("Flat"));
71 squareCap->setText(tr("Square"));
72 roundCap->setText(tr("Round"));
73 flatCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
74 squareCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
75 roundCap->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
76
77 m_joinGroup = new QGroupBox(parent);
78 m_joinGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
79 QRadioButton *bevelJoin = new QRadioButton(m_joinGroup);
80 QRadioButton *miterJoin = new QRadioButton(m_joinGroup);
81 QRadioButton *roundJoin = new QRadioButton(m_joinGroup);
82 m_joinGroup->setTitle(tr("Join Style"));
83 bevelJoin->setText(tr("Bevel"));
84 miterJoin->setText(tr("Miter"));
85 roundJoin->setText(tr("Round"));
86
87 m_styleGroup = new QGroupBox(parent);
88 m_styleGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
89 QRadioButton *solidLine = new QRadioButton(m_styleGroup);
90 QRadioButton *dashLine = new QRadioButton(m_styleGroup);
91 QRadioButton *dotLine = new QRadioButton(m_styleGroup);
92 QRadioButton *dashDotLine = new QRadioButton(m_styleGroup);
93 QRadioButton *dashDotDotLine = new QRadioButton(m_styleGroup);
94 QRadioButton *customDashLine = new QRadioButton(m_styleGroup);
95 m_styleGroup->setTitle(tr("Pen Style"));
96
97 QPixmap line_solid(":res/images/line_solid.png");
98 solidLine->setIcon(line_solid);
99 solidLine->setIconSize(line_solid.size());
100 QPixmap line_dashed(":res/images/line_dashed.png");
101 dashLine->setIcon(line_dashed);
102 dashLine->setIconSize(line_dashed.size());
103 QPixmap line_dotted(":res/images/line_dotted.png");
104 dotLine->setIcon(line_dotted);
105 dotLine->setIconSize(line_dotted.size());
106 QPixmap line_dash_dot(":res/images/line_dash_dot.png");
107 dashDotLine->setIcon(line_dash_dot);
108 dashDotLine->setIconSize(line_dash_dot.size());
109 QPixmap line_dash_dot_dot(":res/images/line_dash_dot_dot.png");
110 dashDotDotLine->setIcon(line_dash_dot_dot);
111 dashDotDotLine->setIconSize(line_dash_dot_dot.size());
112 customDashLine->setText(tr("Custom"));
113
114 int fixedHeight = bevelJoin->sizeHint().height();
115 solidLine->setFixedHeight(fixedHeight);
116 dashLine->setFixedHeight(fixedHeight);
117 dotLine->setFixedHeight(fixedHeight);
118 dashDotLine->setFixedHeight(fixedHeight);
119 dashDotDotLine->setFixedHeight(fixedHeight);
120
121 m_pathModeGroup = new QGroupBox(parent);
122 m_pathModeGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
123 QRadioButton *curveMode = new QRadioButton(m_pathModeGroup);
124 QRadioButton *lineMode = new QRadioButton(m_pathModeGroup);
125 m_pathModeGroup->setTitle(tr("Line Style"));
126 curveMode->setText(tr("Curves"));
127 lineMode->setText(tr("Lines"));
128
129
130 // Layouts
131 QVBoxLayout *capGroupLayout = new QVBoxLayout(m_capGroup);
132 capGroupLayout->addWidget(flatCap);
133 capGroupLayout->addWidget(squareCap);
134 capGroupLayout->addWidget(roundCap);
135
136 QVBoxLayout *joinGroupLayout = new QVBoxLayout(m_joinGroup);
137 joinGroupLayout->addWidget(bevelJoin);
138 joinGroupLayout->addWidget(miterJoin);
139 joinGroupLayout->addWidget(roundJoin);
140
141 QVBoxLayout *styleGroupLayout = new QVBoxLayout(m_styleGroup);
142 styleGroupLayout->addWidget(solidLine);
143 styleGroupLayout->addWidget(dashLine);
144 styleGroupLayout->addWidget(dotLine);
145 styleGroupLayout->addWidget(dashDotLine);
146 styleGroupLayout->addWidget(dashDotDotLine);
147 styleGroupLayout->addWidget(customDashLine);
148
149 QVBoxLayout *pathModeGroupLayout = new QVBoxLayout(m_pathModeGroup);
150 pathModeGroupLayout->addWidget(curveMode);
151 pathModeGroupLayout->addWidget(lineMode);
152
153
154 // Connections
155 connect(flatCap, SIGNAL(clicked()), m_renderer, SLOT(setFlatCap()));
156 connect(squareCap, SIGNAL(clicked()), m_renderer, SLOT(setSquareCap()));
157 connect(roundCap, SIGNAL(clicked()), m_renderer, SLOT(setRoundCap()));
158
159 connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin()));
160 connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin()));
161 connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin()));
162
163 connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));
164 connect(lineMode, SIGNAL(clicked()), m_renderer, SLOT(setLineMode()));
165
166 connect(solidLine, SIGNAL(clicked()), m_renderer, SLOT(setSolidLine()));
167 connect(dashLine, SIGNAL(clicked()), m_renderer, SLOT(setDashLine()));
168 connect(dotLine, SIGNAL(clicked()), m_renderer, SLOT(setDotLine()));
169 connect(dashDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotLine()));
170 connect(dashDotDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotDotLine()));
171 connect(customDashLine, SIGNAL(clicked()), m_renderer, SLOT(setCustomDashLine()));
172
173 // Set the defaults:
174 flatCap->setChecked(true);
175 bevelJoin->setChecked(true);
176 curveMode->setChecked(true);
177 solidLine->setChecked(true);
178}
179
180
181void PathStrokeControls::layoutForDesktop()
182{
183 QGroupBox *mainGroup = new QGroupBox(this);
184 mainGroup->setFixedWidth(180);
185 mainGroup->setTitle(tr("Path Stroking"));
186
187 createCommonControls(mainGroup);
188
189 QGroupBox* penWidthGroup = new QGroupBox(mainGroup);
190 QSlider *penWidth = new QSlider(Qt::Horizontal, penWidthGroup);
191 penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
192 penWidthGroup->setTitle(tr("Pen Width"));
193 penWidth->setRange(0, 500);
194
195 QPushButton *animated = new QPushButton(mainGroup);
196 animated->setText(tr("Animate"));
197 animated->setCheckable(true);
198
199 QPushButton *showSourceButton = new QPushButton(mainGroup);
200 showSourceButton->setText(tr("Show Source"));
201#ifdef QT_OPENGL_SUPPORT
202 QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
203 enableOpenGLButton->setText(tr("Use OpenGL"));
204 enableOpenGLButton->setCheckable(true);
205 enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
206 if (!QGLFormat::hasOpenGL())
207 enableOpenGLButton->hide();
208#endif
209 QPushButton *whatsThisButton = new QPushButton(mainGroup);
210 whatsThisButton->setText(tr("What's This?"));
211 whatsThisButton->setCheckable(true);
212
213
214 // Layouts:
215 QVBoxLayout *penWidthLayout = new QVBoxLayout(penWidthGroup);
216 penWidthLayout->addWidget(penWidth);
217
218 QVBoxLayout * mainLayout = new QVBoxLayout(this);
219 mainLayout->setMargin(0);
220 mainLayout->addWidget(mainGroup);
221
222 QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
223 mainGroupLayout->setMargin(3);
224 mainGroupLayout->addWidget(m_capGroup);
225 mainGroupLayout->addWidget(m_joinGroup);
226 mainGroupLayout->addWidget(m_styleGroup);
227 mainGroupLayout->addWidget(penWidthGroup);
228 mainGroupLayout->addWidget(m_pathModeGroup);
229 mainGroupLayout->addWidget(animated);
230 mainGroupLayout->addStretch(1);
231 mainGroupLayout->addWidget(showSourceButton);
232#ifdef QT_OPENGL_SUPPORT
233 mainGroupLayout->addWidget(enableOpenGLButton);
234#endif
235 mainGroupLayout->addWidget(whatsThisButton);
236
237
238 // Set up connections
239 connect(animated, SIGNAL(toggled(bool)),
240 m_renderer, SLOT(setAnimation(bool)));
241
242 connect(penWidth, SIGNAL(valueChanged(int)),
243 m_renderer, SLOT(setPenWidth(int)));
244
245 connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
246#ifdef QT_OPENGL_SUPPORT
247 connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
248#endif
249 connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
250 connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
251 whatsThisButton, SLOT(setChecked(bool)));
252
253
254 // Set the defaults
255 animated->setChecked(true);
256 penWidth->setValue(50);
257
258}
259
260void PathStrokeControls::layoutForSmallScreens()
261{
262 createCommonControls(this);
263
264 m_capGroup->layout()->setMargin(0);
265 m_joinGroup->layout()->setMargin(0);
266 m_styleGroup->layout()->setMargin(0);
267 m_pathModeGroup->layout()->setMargin(0);
268
269 QPushButton* okBtn = new QPushButton(tr("OK"), this);
270 okBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
271 okBtn->setMinimumSize(100,okBtn->minimumSize().height());
272
273 QPushButton* quitBtn = new QPushButton(tr("Quit"), this);
274 quitBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
275 quitBtn->setMinimumSize(100, okBtn->minimumSize().height());
276
277 QLabel *penWidthLabel = new QLabel(tr(" Width:"));
278 QSlider *penWidth = new QSlider(Qt::Horizontal, this);
279 penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
280 penWidth->setRange(0, 500);
281
282#ifdef QT_OPENGL_SUPPORT
283 QPushButton *enableOpenGLButton = new QPushButton(this);
284 enableOpenGLButton->setText(tr("Use OpenGL"));
285 enableOpenGLButton->setCheckable(true);
286 enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
287 if (!QGLFormat::hasOpenGL())
288 enableOpenGLButton->hide();
289#endif
290
291 // Layouts:
292 QHBoxLayout *penWidthLayout = new QHBoxLayout(0);
293 penWidthLayout->addWidget(penWidthLabel, 0, Qt::AlignRight);
294 penWidthLayout->addWidget(penWidth);
295
296 QVBoxLayout *leftLayout = new QVBoxLayout(0);
297 leftLayout->addWidget(m_capGroup);
298 leftLayout->addWidget(m_joinGroup);
299#ifdef QT_OPENGL_SUPPORT
300 leftLayout->addWidget(enableOpenGLButton);
301#endif
302 leftLayout->addLayout(penWidthLayout);
303
304 QVBoxLayout *rightLayout = new QVBoxLayout(0);
305 rightLayout->addWidget(m_styleGroup);
306 rightLayout->addWidget(m_pathModeGroup);
307
308 QGridLayout *mainLayout = new QGridLayout(this);
309 mainLayout->setMargin(0);
310
311 // Add spacers around the form items so we don't look stupid at higher resolutions
312 mainLayout->addItem(new QSpacerItem(0,0), 0, 0, 1, 4);
313 mainLayout->addItem(new QSpacerItem(0,0), 1, 0, 2, 1);
314 mainLayout->addItem(new QSpacerItem(0,0), 1, 3, 2, 1);
315 mainLayout->addItem(new QSpacerItem(0,0), 3, 0, 1, 4);
316
317 mainLayout->addLayout(leftLayout, 1, 1);
318 mainLayout->addLayout(rightLayout, 1, 2);
319 mainLayout->addWidget(quitBtn, 2, 1, Qt::AlignHCenter | Qt::AlignTop);
320 mainLayout->addWidget(okBtn, 2, 2, Qt::AlignHCenter | Qt::AlignTop);
321
322#ifdef QT_OPENGL_SUPPORT
323 connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
324#endif
325
326 connect(penWidth, SIGNAL(valueChanged(int)), m_renderer, SLOT(setPenWidth(int)));
327 connect(quitBtn, SIGNAL(clicked()), this, SLOT(emitQuitSignal()));
328 connect(okBtn, SIGNAL(clicked()), this, SLOT(emitOkSignal()));
329
330 m_renderer->setAnimation(true);
331 penWidth->setValue(50);
332}
333
334void PathStrokeControls::emitQuitSignal()
335{ emit quitPressed(); }
336
337void PathStrokeControls::emitOkSignal()
338{ emit okPressed(); }
339
340
341PathStrokeWidget::PathStrokeWidget(bool smallScreen)
342{
343 setWindowTitle(tr("Path Stroking"));
344
345 // Widget construction and property setting
346 m_renderer = new PathStrokeRenderer(this, smallScreen);
347
348 m_controls = new PathStrokeControls(0, m_renderer, smallScreen);
349
350 // Layouting
351 QHBoxLayout *viewLayout = new QHBoxLayout(this);
352 viewLayout->addWidget(m_renderer);
353
354 if (!smallScreen)
355 viewLayout->addWidget(m_controls);
356
357 m_renderer->loadSourceFile(":res/pathstroke/pathstroke.cpp");
358 m_renderer->loadDescription(":res/pathstroke/pathstroke.html");
359
360 connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls()));
361 connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls()));
362 connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit()));
363}
364
365
366void PathStrokeWidget::showControls()
367{
368 m_controls->showFullScreen();
369}
370
371
372void PathStrokeWidget::hideControls()
373{
374 m_controls->hide();
375}
376
377
378void PathStrokeWidget::setStyle( QStyle * style )
379{
380 QWidget::setStyle(style);
381 if (m_controls != 0)
382 {
383 m_controls->setStyle(style);
384
385 QList<QWidget *> widgets = qFindChildren<QWidget *>(m_controls);
386 foreach (QWidget *w, widgets)
387 w->setStyle(style);
388 }
389}
390
391
392PathStrokeRenderer::PathStrokeRenderer(QWidget *parent, bool smallScreen)
393 : ArthurFrame(parent)
394{
395 m_smallScreen = smallScreen;
396 m_pointSize = 10;
397 m_activePoint = -1;
398 m_capStyle = Qt::FlatCap;
399 m_joinStyle = Qt::BevelJoin;
400 m_pathMode = CurveMode;
401 m_penWidth = 1;
402 m_penStyle = Qt::SolidLine;
403 m_wasAnimated = true;
404 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
405 setAttribute(Qt::WA_AcceptTouchEvents);
406}
407
408void PathStrokeRenderer::paint(QPainter *painter)
409{
410 if (m_points.isEmpty())
411 initializePoints();
412
413 painter->setRenderHint(QPainter::Antialiasing);
414
415 QPalette pal = palette();
416 painter->setPen(Qt::NoPen);
417
418 // Construct the path
419 QPainterPath path;
420 path.moveTo(m_points.at(0));
421
422 if (m_pathMode == LineMode) {
423 for (int i=1; i<m_points.size(); ++i) {
424 path.lineTo(m_points.at(i));
425 }
426 } else {
427 int i=1;
428 while (i + 2 < m_points.size()) {
429 path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2));
430 i += 3;
431 }
432 while (i < m_points.size()) {
433 path.lineTo(m_points.at(i));
434 ++i;
435 }
436 }
437
438 // Draw the path
439 {
440 QColor lg = Qt::red;
441
442 // The "custom" pen
443 if (m_penStyle == Qt::NoPen) {
444 QPainterPathStroker stroker;
445 stroker.setWidth(m_penWidth);
446 stroker.setJoinStyle(m_joinStyle);
447 stroker.setCapStyle(m_capStyle);
448
449 QVector<qreal> dashes;
450 qreal space = 4;
451 dashes << 1 << space
452 << 3 << space
453 << 9 << space
454 << 27 << space
455 << 9 << space
456 << 3 << space;
457 stroker.setDashPattern(dashes);
458 QPainterPath stroke = stroker.createStroke(path);
459 painter->fillPath(stroke, lg);
460
461 } else {
462 QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle);
463 painter->strokePath(path, pen);
464 }
465 }
466
467 if (1) {
468 // Draw the control points
469 painter->setPen(QColor(50, 100, 120, 200));
470 painter->setBrush(QColor(200, 200, 210, 120));
471 for (int i=0; i<m_points.size(); ++i) {
472 QPointF pos = m_points.at(i);
473 painter->drawEllipse(QRectF(pos.x() - m_pointSize,
474 pos.y() - m_pointSize,
475 m_pointSize*2, m_pointSize*2));
476 }
477 painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine));
478 painter->setBrush(Qt::NoBrush);
479 painter->drawPolyline(m_points);
480 }
481
482}
483
484void PathStrokeRenderer::initializePoints()
485{
486 const int count = 7;
487 m_points.clear();
488 m_vectors.clear();
489
490 QMatrix m;
491 qreal rot = 360 / count;
492 QPointF center(width() / 2, height() / 2);
493 QMatrix vm;
494 vm.shear(2, -1);
495 vm.scale(3, 3);
496
497 for (int i=0; i<count; ++i) {
498 m_vectors << QPointF(.1f, .25f) * (m * vm);
499 m_points << QPointF(0, 100) * m + center;
500 m.rotate(rot);
501 }
502}
503
504void PathStrokeRenderer::updatePoints()
505{
506 qreal pad = 10;
507 qreal left = pad;
508 qreal right = width() - pad;
509 qreal top = pad;
510 qreal bottom = height() - pad;
511
512 Q_ASSERT(m_points.size() == m_vectors.size());
513 for (int i=0; i<m_points.size(); ++i) {
514 QPointF pos = m_points.at(i);
515 QPointF vec = m_vectors.at(i);
516 pos += vec;
517 if (pos.x() < left || pos.x() > right) {
518 vec.setX(-vec.x());
519 pos.setX(pos.x() < left ? left : right);
520 } if (pos.y() < top || pos.y() > bottom) {
521 vec.setY(-vec.y());
522 pos.setY(pos.y() < top ? top : bottom);
523 }
524 m_points[i] = pos;
525 m_vectors[i] = vec;
526 }
527 update();
528}
529
530void PathStrokeRenderer::mousePressEvent(QMouseEvent *e)
531{
532 if (!m_fingerPointMapping.isEmpty())
533 return;
534 setDescriptionEnabled(false);
535 m_activePoint = -1;
536 qreal distance = -1;
537 for (int i=0; i<m_points.size(); ++i) {
538 qreal d = QLineF(e->pos(), m_points.at(i)).length();
539 if ((distance < 0 && d < 8 * m_pointSize) || d < distance) {
540 distance = d;
541 m_activePoint = i;
542 }
543 }
544
545 if (m_activePoint != -1) {
546 m_wasAnimated = m_timer.isActive();
547 setAnimation(false);
548 mouseMoveEvent(e);
549 }
550
551 // If we're not running in small screen mode, always assume we're dragging
552 m_mouseDrag = !m_smallScreen;
553 m_mousePress = e->pos();
554}
555
556void PathStrokeRenderer::mouseMoveEvent(QMouseEvent *e)
557{
558 if (!m_fingerPointMapping.isEmpty())
559 return;
560 // If we've moved more then 25 pixels, assume user is dragging
561 if (!m_mouseDrag && QPoint(m_mousePress - e->pos()).manhattanLength() > 25)
562 m_mouseDrag = true;
563
564 if (m_mouseDrag && m_activePoint >= 0 && m_activePoint < m_points.size()) {
565 m_points[m_activePoint] = e->pos();
566 update();
567 }
568}
569
570void PathStrokeRenderer::mouseReleaseEvent(QMouseEvent *)
571{
572 if (!m_fingerPointMapping.isEmpty())
573 return;
574 m_activePoint = -1;
575 setAnimation(m_wasAnimated);
576
577 if (!m_mouseDrag && m_smallScreen)
578 emit clicked();
579}
580
581void PathStrokeRenderer::timerEvent(QTimerEvent *e)
582{
583 if (e->timerId() == m_timer.timerId()) {
584 updatePoints();
585 QApplication::syncX();
586 } // else if (e->timerId() == m_fpsTimer.timerId()) {
587// emit frameRate(m_frameCount);
588// m_frameCount = 0;
589// }
590}
591
592bool PathStrokeRenderer::event(QEvent *e)
593{
594 bool touchBegin = false;
595 switch (e->type()) {
596 case QEvent::TouchBegin:
597 touchBegin = true;
598 case QEvent::TouchUpdate:
599 {
600 const QTouchEvent *const event = static_cast<const QTouchEvent*>(e);
601 const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
602 foreach (const QTouchEvent::TouchPoint &touchPoint, points) {
603 const int id = touchPoint.id();
604 switch (touchPoint.state()) {
605 case Qt::TouchPointPressed:
606 {
607 // find the point, move it
608 QSet<int> activePoints = QSet<int>::fromList(m_fingerPointMapping.values());
609 int activePoint = -1;
610 qreal distance = -1;
611 const int pointsCount = m_points.size();
612 for (int i=0; i<pointsCount; ++i) {
613 if (activePoints.contains(i))
614 continue;
615
616 qreal d = QLineF(touchPoint.pos(), m_points.at(i)).length();
617 if ((distance < 0 && d < 12 * m_pointSize) || d < distance) {
618 distance = d;
619 activePoint = i;
620 }
621 }
622 if (activePoint != -1) {
623 m_fingerPointMapping.insert(touchPoint.id(), activePoint);
624 m_points[activePoint] = touchPoint.pos();
625 }
626 }
627 break;
628 case Qt::TouchPointReleased:
629 {
630 // move the point and release
631 QHash<int,int>::iterator it = m_fingerPointMapping.find(id);
632 m_points[it.value()] = touchPoint.pos();
633 m_fingerPointMapping.erase(it);
634 }
635 break;
636 case Qt::TouchPointMoved:
637 {
638 // move the point
639 const int pointIdx = m_fingerPointMapping.value(id, -1);
640 if (pointIdx >= 0)
641 m_points[pointIdx] = touchPoint.pos();
642 }
643 break;
644 default:
645 break;
646 }
647 }
648 if (m_fingerPointMapping.isEmpty()) {
649 e->ignore();
650 return false;
651 } else {
652 if (touchBegin) {
653 m_wasAnimated = m_timer.isActive();
654 setAnimation(false);
655 }
656 update();
657 return true;
658 }
659 }
660 break;
661 case QEvent::TouchEnd:
662 if (m_fingerPointMapping.isEmpty()) {
663 e->ignore();
664 return false;
665 }
666 m_fingerPointMapping.clear();
667 setAnimation(m_wasAnimated);
668 return true;
669 break;
670 default:
671 break;
672 }
673 return QWidget::event(e);
674}
675
676void PathStrokeRenderer::setAnimation(bool animation)
677{
678 m_timer.stop();
679// m_fpsTimer.stop();
680
681 if (animation) {
682 m_timer.start(25, this);
683// m_fpsTimer.start(1000, this);
684// m_frameCount = 0;
685 }
686}
Note: See TracBrowser for help on using the repository browser.