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