1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qtgradientwidget.h"
41#include <QtCore/QMap>
42#include <QtGui/QImage>
43#include <QtGui/QPainter>
44#include <QtWidgets/QScrollBar>
45#include <QtGui/QMouseEvent>
46#include <QtGui/QRegion>
47
48#ifndef _USE_MATH_DEFINES
49#define _USE_MATH_DEFINES
50#endif
51
52#include "qmath.h"
53
54QT_BEGIN_NAMESPACE
55
56class QtGradientWidgetPrivate
57{
58 QtGradientWidget *q_ptr;
59 Q_DECLARE_PUBLIC(QtGradientWidget)
60public:
61 QPointF fromViewport(const QPointF &point) const;
62 QPointF toViewport(const QPointF &point) const;
63// void setupDrag(QtGradientStop *stop, int x);
64
65 QPointF checkRange(const QPointF &point) const;
66 QRectF pointRect(const QPointF &point, double size) const;
67
68 double correctAngle(double angle) const;
69 void setAngleConical(double angle);
70
71 void paintPoint(QPainter *painter, const QPointF &point, double size) const;
72
73 double m_handleSize;
74 bool m_backgroundCheckered;
75
76 QGradientStops m_gradientStops;
77 QGradient::Type m_gradientType;
78 QGradient::Spread m_gradientSpread;
79 QPointF m_startLinear;
80 QPointF m_endLinear;
81 QPointF m_centralRadial;
82 QPointF m_focalRadial;
83 qreal m_radiusRadial;
84 QPointF m_centralConical;
85 qreal m_angleConical;
86
87 enum Handle {
88 NoHandle,
89 StartLinearHandle,
90 EndLinearHandle,
91 CentralRadialHandle,
92 FocalRadialHandle,
93 RadiusRadialHandle,
94 CentralConicalHandle,
95 AngleConicalHandle
96 };
97
98 Handle m_dragHandle;
99 QPointF m_dragOffset;
100 //double m_radiusOffset;
101 double m_radiusFactor;
102 double m_dragRadius;
103 double m_angleOffset;
104 double m_dragAngle;
105};
106
107double QtGradientWidgetPrivate::correctAngle(double angle) const
108{
109 double a = angle;
110 while (a >= 360)
111 a -= 360;
112 while (a < 0)
113 a += 360;
114 return a;
115}
116
117void QtGradientWidgetPrivate::setAngleConical(double angle)
118{
119 double a = correctAngle(angle);
120 if (m_angleConical == a)
121 return;
122 m_angleConical = a;
123 emit q_ptr->angleConicalChanged(m_angleConical);
124}
125
126QRectF QtGradientWidgetPrivate::pointRect(const QPointF &point, double size) const
127{
128 return QRectF(point.x() - size / 2, point.y() - size / 2, size, size);
129}
130
131QPointF QtGradientWidgetPrivate::checkRange(const QPointF &point) const
132{
133 QPointF p = point;
134 if (p.x() > 1)
135 p.setX(1);
136 else if (p.x() < 0)
137 p.setX(0);
138 if (p.y() > 1)
139 p.setY(1);
140 else if (p.y() < 0)
141 p.setY(0);
142 return p;
143}
144
145QPointF QtGradientWidgetPrivate::fromViewport(const QPointF &point) const
146{
147 QSize size = q_ptr->size();
148 return QPointF(point.x() / size.width(), point.y() / size.height());
149}
150
151QPointF QtGradientWidgetPrivate::toViewport(const QPointF &point) const
152{
153 QSize size = q_ptr->size();
154 return QPointF(point.x() * size.width(), point.y() * size.height());
155}
156
157void QtGradientWidgetPrivate::paintPoint(QPainter *painter, const QPointF &point, double size) const
158{
159 QPointF pf = toViewport(point);
160 QRectF rf = pointRect(pf, size);
161
162 QPen pen;
163 pen.setWidthF(1);
164 QColor alphaZero = Qt::white;
165 alphaZero.setAlpha(0);
166
167 painter->save();
168 painter->drawEllipse(rf);
169
170 /*
171 painter->save();
172
173 QLinearGradient lgV(0, rf.top(), 0, rf.bottom());
174 lgV.setColorAt(0, alphaZero);
175 lgV.setColorAt(0.25, Qt::white);
176 lgV.setColorAt(0.25, Qt::white);
177 lgV.setColorAt(1, alphaZero);
178 pen.setBrush(lgV);
179 painter->setPen(pen);
180
181 painter->drawLine(QPointF(pf.x(), rf.top()), QPointF(pf.x(), rf.bottom()));
182
183 QLinearGradient lgH(rf.left(), 0, rf.right(), 0);
184 lgH.setColorAt(0, alphaZero);
185 lgH.setColorAt(0.5, Qt::white);
186 lgH.setColorAt(1, alphaZero);
187 pen.setBrush(lgH);
188 painter->setPen(pen);
189
190 painter->drawLine(QPointF(rf.left(), pf.y()), QPointF(rf.right(), pf.y()));
191
192 painter->restore();
193 */
194
195 painter->restore();
196}
197
198/*
199void QtGradientWidgetPrivate::setupDrag(QtGradientStop *stop, int x)
200{
201 m_model->setCurrentStop(stop);
202
203 int viewportX = qRound(toViewport(stop->position()));
204 m_dragOffset = x - viewportX;
205
206 const QList<QtGradientStop *> stops = m_stops;
207 m_stops.clear();
208 for (QtGradientStop *s : stops) {
209 if (m_model->isSelected(s) || s == stop) {
210 m_dragStops[s] = s->position() - stop->position();
211 m_stops.append(s);
212 } else {
213 m_dragOriginal[s->position()] = s->color();
214 }
215 }
216 for (QtGradientStop *s : stops) {
217 if (!m_model->isSelected(s))
218 m_stops.append(s);
219 }
220 m_stops.removeAll(stop);
221 m_stops.prepend(stop);
222}
223*/
224////////////////////////////
225
226QtGradientWidget::QtGradientWidget(QWidget *parent)
227 : QWidget(parent), d_ptr(new QtGradientWidgetPrivate)
228{
229 d_ptr->q_ptr = this;
230 d_ptr->m_backgroundCheckered = true;
231 d_ptr->m_handleSize = 20.0;
232 d_ptr->m_gradientType = QGradient::LinearGradient;
233 d_ptr->m_startLinear = QPointF(0, 0);
234 d_ptr->m_endLinear = QPointF(1, 1);
235 d_ptr->m_centralRadial = QPointF(0.5, 0.5);
236 d_ptr->m_focalRadial = QPointF(0.5, 0.5);
237 d_ptr->m_radiusRadial = 0.5;
238 d_ptr->m_centralConical = QPointF(0.5, 0.5);
239 d_ptr->m_angleConical = 0;
240 d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle;
241
242 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
243}
244
245QtGradientWidget::~QtGradientWidget()
246{
247}
248
249QSize QtGradientWidget::sizeHint() const
250{
251 return QSize(176, 176);
252}
253
254QSize QtGradientWidget::minimumSizeHint() const
255{
256 return QSize(128, 128);
257}
258
259int QtGradientWidget::heightForWidth(int w) const
260{
261 return w;
262}
263
264void QtGradientWidget::setBackgroundCheckered(bool checkered)
265{
266 if (d_ptr->m_backgroundCheckered == checkered)
267 return;
268 d_ptr->m_backgroundCheckered = checkered;
269 update();
270}
271
272bool QtGradientWidget::isBackgroundCheckered() const
273{
274 return d_ptr->m_backgroundCheckered;
275}
276
277void QtGradientWidget::mousePressEvent(QMouseEvent *e)
278{
279 if (e->button() != Qt::LeftButton)
280 return;
281
282 QPoint p = e->pos();
283 if (d_ptr->m_gradientType == QGradient::LinearGradient) {
284 QPointF startPoint = d_ptr->toViewport(d_ptr->m_startLinear);
285 double x = p.x() - startPoint.x();
286 double y = p.y() - startPoint.y();
287
288 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
289 d_ptr->m_dragHandle = QtGradientWidgetPrivate::StartLinearHandle;
290 d_ptr->m_dragOffset = QPointF(x, y);
291 update();
292 return;
293 }
294
295 QPointF endPoint = d_ptr->toViewport(d_ptr->m_endLinear);
296 x = p.x() - endPoint.x();
297 y = p.y() - endPoint.y();
298
299 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
300 d_ptr->m_dragHandle = QtGradientWidgetPrivate::EndLinearHandle;
301 d_ptr->m_dragOffset = QPointF(x, y);
302 update();
303 return;
304 }
305 } else if (d_ptr->m_gradientType == QGradient::RadialGradient) {
306 QPointF focalPoint = d_ptr->toViewport(d_ptr->m_focalRadial);
307 double x = p.x() - focalPoint.x();
308 double y = p.y() - focalPoint.y();
309
310 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 9) > (x * x + y * y)) {
311 d_ptr->m_dragHandle = QtGradientWidgetPrivate::FocalRadialHandle;
312 d_ptr->m_dragOffset = QPointF(x, y);
313 update();
314 return;
315 }
316
317 QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial);
318 x = p.x() - centralPoint.x();
319 y = p.y() - centralPoint.y();
320
321 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
322 d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralRadialHandle;
323 d_ptr->m_dragOffset = QPointF(x, y);
324 update();
325 return;
326 }
327
328 QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial);
329 QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3);
330 QRectF r1(0, r.y(), size().width(), r.height());
331 QRectF r2(r.x(), 0, r.width(), r.y());
332 QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height());
333 QPointF pF(p.x(), p.y());
334 if (r1.contains(pF) || r2.contains(pF) || r3.contains(pF)) {
335 x = pF.x() / size().width() - d_ptr->m_centralRadial.x();
336 y = pF.y() / size().height() - d_ptr->m_centralRadial.y();
337 const double clickRadius = hypot(x, y);
338 //d_ptr->m_radiusOffset = d_ptr->m_radiusRadial - clickRadius;
339 d_ptr->m_radiusFactor = d_ptr->m_radiusRadial / clickRadius;
340 if (d_ptr->m_radiusFactor == 0)
341 d_ptr->m_radiusFactor = 1;
342 d_ptr->m_dragRadius = d_ptr->m_radiusRadial;
343 d_ptr->m_dragHandle = QtGradientWidgetPrivate::RadiusRadialHandle;
344 mouseMoveEvent(e);
345 update();
346 return;
347 }
348 } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) {
349 QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical);
350 double x = p.x() - centralPoint.x();
351 double y = p.y() - centralPoint.y();
352
353 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
354 d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralConicalHandle;
355 d_ptr->m_dragOffset = QPointF(x, y);
356 update();
357 return;
358 }
359 double radius = size().width();
360 if (size().height() < radius)
361 radius = size().height();
362 radius /= 2;
363 double corr = d_ptr->m_handleSize / 3;
364 radius -= corr;
365 QPointF vp = d_ptr->toViewport(d_ptr->m_centralConical);
366 x = p.x() - vp.x();
367 y = p.y() - vp.y();
368 if (((radius - corr) * (radius - corr) < (x * x + y * y)) &&
369 ((radius + corr) * (radius + corr) > (x * x + y * y))) {
370 QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
371 QPointF current(e->pos().x(), e->pos().y());
372 x = current.x() - central.x();
373 y = current.y() - central.y();
374 x /= size().width() / 2;
375 y /= size().height() / 2;
376 const double angle = qRadiansToDegrees(atan2(-y, x));
377
378 d_ptr->m_angleOffset = d_ptr->m_angleConical - angle;
379 d_ptr->m_dragAngle = d_ptr->m_angleConical;
380 d_ptr->m_dragHandle = QtGradientWidgetPrivate::AngleConicalHandle;
381 update();
382 return;
383 }
384 }
385}
386
387void QtGradientWidget::mouseReleaseEvent(QMouseEvent *e)
388{
389 Q_UNUSED(e);
390 d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle;
391 update();
392}
393
394void QtGradientWidget::mouseMoveEvent(QMouseEvent *e)
395{
396 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::NoHandle)
397 return;
398
399 const QPointF newPos = e->localPos() - d_ptr->m_dragOffset;
400 QPointF newPoint = d_ptr->fromViewport(newPos);
401 if (newPoint.x() < 0)
402 newPoint.setX(0);
403 else if (newPoint.x() > 1)
404 newPoint.setX(1);
405 if (newPoint.y() < 0)
406 newPoint.setY(0);
407 else if (newPoint.y() > 1)
408 newPoint.setY(1);
409
410 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle) {
411 d_ptr->m_startLinear = newPoint;
412 emit startLinearChanged(newPoint);
413 } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle) {
414 d_ptr->m_endLinear = newPoint;
415 emit endLinearChanged(newPoint);
416 } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle) {
417 d_ptr->m_centralRadial = newPoint;
418 emit centralRadialChanged(newPoint);
419 } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle) {
420 d_ptr->m_focalRadial = newPoint;
421 emit focalRadialChanged(newPoint);
422 } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) {
423 QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial);
424 QPointF pF(e->pos().x(), e->pos().y());
425 double x = pF.x() - centralPoint.x();
426 double y = pF.y() - centralPoint.y();
427
428 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
429 if (d_ptr->m_radiusRadial != d_ptr->m_dragRadius) {
430 d_ptr->m_radiusRadial = d_ptr->m_dragRadius;
431 emit radiusRadialChanged(d_ptr->m_radiusRadial);
432 }
433 } else {
434 x = pF.x() / size().width() - d_ptr->m_centralRadial.x();
435 y = pF.y() / size().height() - d_ptr->m_centralRadial.y();
436 const double moveRadius = hypot(x, y);
437 //double newRadius = moveRadius + d_ptr->m_radiusOffset;
438 double newRadius = moveRadius * d_ptr->m_radiusFactor;
439 if (newRadius > 2)
440 newRadius = 2;
441 d_ptr->m_radiusRadial = newRadius;
442 emit radiusRadialChanged(d_ptr->m_radiusRadial);
443 }
444 } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle) {
445 d_ptr->m_centralConical = newPoint;
446 emit centralConicalChanged(newPoint);
447 } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) {
448 QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical);
449 QPointF pF(e->pos().x(), e->pos().y());
450 double x = pF.x() - centralPoint.x();
451 double y = pF.y() - centralPoint.y();
452
453 if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
454 if (d_ptr->m_angleConical != d_ptr->m_dragAngle) {
455 d_ptr->m_angleConical = d_ptr->m_dragAngle;
456 emit angleConicalChanged(d_ptr->m_angleConical);
457 }
458 } else {
459 QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
460 QPointF current = pF;
461 x = current.x() - central.x();
462 y = current.y() - central.y();
463 x /= size().width() / 2;
464 y /= size().height() / 2;
465
466 const double angle = qRadiansToDegrees(atan2(-y, x)) + d_ptr->m_angleOffset;
467 d_ptr->setAngleConical(angle);
468 }
469 }
470 update();
471}
472
473void QtGradientWidget::mouseDoubleClickEvent(QMouseEvent *e)
474{
475 mousePressEvent(e);
476}
477
478void QtGradientWidget::paintEvent(QPaintEvent *e)
479{
480 Q_UNUSED(e);
481
482 QPainter p(this);
483
484 if (d_ptr->m_backgroundCheckered) {
485 int pixSize = 40;
486 QPixmap pm(2 * pixSize, 2 * pixSize);
487
488 QPainter pmp(&pm);
489 pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
490 pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
491 pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
492 pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
493
494 p.setBrushOrigin((size().width() % pixSize + pixSize) / 2, (size().height() % pixSize + pixSize) / 2);
495 p.fillRect(rect(), pm);
496 p.setBrushOrigin(0, 0);
497 }
498
499 QGradient *gradient = 0;
500 switch (d_ptr->m_gradientType) {
501 case QGradient::LinearGradient:
502 gradient = new QLinearGradient(d_ptr->m_startLinear, d_ptr->m_endLinear);
503 break;
504 case QGradient::RadialGradient:
505 gradient = new QRadialGradient(d_ptr->m_centralRadial, d_ptr->m_radiusRadial, d_ptr->m_focalRadial);
506 break;
507 case QGradient::ConicalGradient:
508 gradient = new QConicalGradient(d_ptr->m_centralConical, d_ptr->m_angleConical);
509 break;
510 default:
511 break;
512 }
513 if (!gradient)
514 return;
515
516 gradient->setStops(d_ptr->m_gradientStops);
517 gradient->setSpread(d_ptr->m_gradientSpread);
518
519 p.save();
520 p.scale(size().width(), size().height());
521 p.fillRect(QRect(0, 0, 1, 1), *gradient);
522 p.restore();
523
524 p.setRenderHint(QPainter::Antialiasing);
525
526 QColor c = QColor::fromRgbF(0.5, 0.5, 0.5, 0.5);
527 QBrush br(c);
528 p.setBrush(br);
529 QPen pen(Qt::white);
530 pen.setWidthF(1);
531 p.setPen(pen);
532 QPen dragPen = pen;
533 dragPen.setWidthF(2);
534 if (d_ptr->m_gradientType == QGradient::LinearGradient) {
535 p.save();
536 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle)
537 p.setPen(dragPen);
538 d_ptr->paintPoint(&p, d_ptr->m_startLinear, d_ptr->m_handleSize);
539 p.restore();
540
541 p.save();
542 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle)
543 p.setPen(dragPen);
544 d_ptr->paintPoint(&p, d_ptr->m_endLinear, d_ptr->m_handleSize);
545 p.restore();
546 } else if (d_ptr->m_gradientType == QGradient::RadialGradient) {
547 QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial);
548
549 p.save();
550 QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3);
551 QRectF r1(0, r.y(), size().width(), r.height());
552 QRectF r2(r.x(), 0, r.width(), r.y());
553 QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height());
554 p.fillRect(r1, c);
555 p.fillRect(r2, c);
556 p.fillRect(r3, c);
557 p.setBrush(Qt::NoBrush);
558 p.save();
559 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle)
560 p.setPen(dragPen);
561 d_ptr->paintPoint(&p, d_ptr->m_centralRadial, d_ptr->m_handleSize);
562 p.restore();
563
564 const QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial * size().width(),
565 central.y() - d_ptr->m_radiusRadial * size().height(),
566 2 * d_ptr->m_radiusRadial * size().width(),
567 2 * d_ptr->m_radiusRadial * size().height());
568 QRegion region(r1.toRect());
569 region += r2.toRect();
570 region += r3.toRect();
571 p.setClipRegion(region);
572
573 p.drawEllipse(rect);
574 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) {
575 p.save();
576 p.setPen(dragPen);
577 QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(),
578 central.y() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height(),
579 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(),
580 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height());
581 p.drawEllipse(rect);
582
583 p.restore();
584 }
585 p.restore();
586
587 p.save();
588 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle)
589 p.setPen(dragPen);
590 d_ptr->paintPoint(&p, d_ptr->m_focalRadial, 2 * d_ptr->m_handleSize / 3);
591 p.restore();
592 } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) {
593 double radius = size().width();
594 if (size().height() < radius)
595 radius = size().height();
596 radius /= 2;
597 double corr = d_ptr->m_handleSize / 3;
598 radius -= corr;
599 QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
600
601 p.save();
602 p.setBrush(Qt::NoBrush);
603 QPen pen2(c);
604 pen2.setWidthF(2 * d_ptr->m_handleSize / 3);
605 p.setPen(pen2);
606 p.drawEllipse(d_ptr->pointRect(central, 2 * radius));
607 p.restore();
608
609 p.save();
610 p.setBrush(Qt::NoBrush);
611 int pointCount = 2;
612 for (int i = 0; i < pointCount; i++) {
613 const qreal angle = qDegreesToRadians(i * 180.0 / pointCount + d_ptr->m_angleConical);
614 const QPointF ray(cos(angle) * size().width() / 2,
615 -sin(angle) * size().height() / 2);
616 const double mod = hypot(ray.x(), ray.y());
617 p.drawLine(QPointF(central.x() + ray.x() * (radius - corr) / mod,
618 central.y() + ray.y() * (radius - corr) / mod),
619 QPointF(central.x() + ray.x() * (radius + corr) / mod,
620 central.y() + ray.y() * (radius + corr) / mod));
621 p.drawLine(QPointF(central.x() - ray.x() * (radius - corr) / mod,
622 central.y() - ray.y() * (radius - corr) / mod),
623 QPointF(central.x() - ray.x() * (radius + corr) / mod,
624 central.y() - ray.y() * (radius + corr) / mod));
625 }
626 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) {
627 p.save();
628 p.setPen(dragPen);
629 const qreal angle = qDegreesToRadians(d_ptr->m_angleConical - d_ptr->m_angleOffset);
630 const QPointF ray(cos(angle) * size().width() / 2,
631 -sin(angle) * size().height() / 2);
632 const double mod = hypot(ray.x(), ray.y());
633 p.drawLine(QPointF(central.x() + ray.x() * (radius - corr) / mod,
634 central.y() + ray.y() * (radius - corr) / mod),
635 QPointF(central.x() + ray.x() * (radius + corr) / mod,
636 central.y() + ray.y() * (radius + corr) / mod));
637 p.restore();
638 }
639
640 p.restore();
641
642 p.save();
643 if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle)
644 p.setPen(dragPen);
645 d_ptr->paintPoint(&p, d_ptr->m_centralConical, d_ptr->m_handleSize);
646 p.restore();
647
648 }
649
650 delete gradient;
651}
652
653void QtGradientWidget::setGradientStops(const QGradientStops &stops)
654{
655 d_ptr->m_gradientStops = stops;
656 update();
657}
658
659QGradientStops QtGradientWidget::gradientStops() const
660{
661 return d_ptr->m_gradientStops;
662}
663
664void QtGradientWidget::setGradientType(QGradient::Type type)
665{
666 if (type == QGradient::NoGradient)
667 return;
668 if (d_ptr->m_gradientType == type)
669 return;
670
671 d_ptr->m_gradientType = type;
672 update();
673}
674
675QGradient::Type QtGradientWidget::gradientType() const
676{
677 return d_ptr->m_gradientType;
678}
679
680void QtGradientWidget::setGradientSpread(QGradient::Spread spread)
681{
682 if (d_ptr->m_gradientSpread == spread)
683 return;
684
685 d_ptr->m_gradientSpread = spread;
686 update();
687}
688
689QGradient::Spread QtGradientWidget::gradientSpread() const
690{
691 return d_ptr->m_gradientSpread;
692}
693
694void QtGradientWidget::setStartLinear(const QPointF &point)
695{
696 if (d_ptr->m_startLinear == point)
697 return;
698
699 d_ptr->m_startLinear = d_ptr->checkRange(point);
700 update();
701}
702
703QPointF QtGradientWidget::startLinear() const
704{
705 return d_ptr->m_startLinear;
706}
707
708void QtGradientWidget::setEndLinear(const QPointF &point)
709{
710 if (d_ptr->m_endLinear == point)
711 return;
712
713 d_ptr->m_endLinear = d_ptr->checkRange(point);
714 update();
715}
716
717QPointF QtGradientWidget::endLinear() const
718{
719 return d_ptr->m_endLinear;
720}
721
722void QtGradientWidget::setCentralRadial(const QPointF &point)
723{
724 if (d_ptr->m_centralRadial == point)
725 return;
726
727 d_ptr->m_centralRadial = point;
728 update();
729}
730
731QPointF QtGradientWidget::centralRadial() const
732{
733 return d_ptr->m_centralRadial;
734}
735
736void QtGradientWidget::setFocalRadial(const QPointF &point)
737{
738 if (d_ptr->m_focalRadial == point)
739 return;
740
741 d_ptr->m_focalRadial = point;
742 update();
743}
744
745QPointF QtGradientWidget::focalRadial() const
746{
747 return d_ptr->m_focalRadial;
748}
749
750void QtGradientWidget::setRadiusRadial(qreal radius)
751{
752 if (d_ptr->m_radiusRadial == radius)
753 return;
754
755 d_ptr->m_radiusRadial = radius;
756 update();
757}
758
759qreal QtGradientWidget::radiusRadial() const
760{
761 return d_ptr->m_radiusRadial;
762}
763
764void QtGradientWidget::setCentralConical(const QPointF &point)
765{
766 if (d_ptr->m_centralConical == point)
767 return;
768
769 d_ptr->m_centralConical = point;
770 update();
771}
772
773QPointF QtGradientWidget::centralConical() const
774{
775 return d_ptr->m_centralConical;
776}
777
778void QtGradientWidget::setAngleConical(qreal angle)
779{
780 if (d_ptr->m_angleConical == angle)
781 return;
782
783 d_ptr->m_angleConical = angle;
784 update();
785}
786
787qreal QtGradientWidget::angleConical() const
788{
789 return d_ptr->m_angleConical;
790}
791
792QT_END_NAMESPACE
793