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 tools 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 "qtgradientstopswidget.h"
|
---|
43 | #include "qtgradientstopsmodel.h"
|
---|
44 |
|
---|
45 | #include <QtCore/QMap>
|
---|
46 | #include <QtGui/QImage>
|
---|
47 | #include <QtGui/QPainter>
|
---|
48 | #include <QtGui/QScrollBar>
|
---|
49 | #include <QtGui/QMouseEvent>
|
---|
50 | #include <QtGui/QRubberBand>
|
---|
51 | #include <QtGui/QMenu>
|
---|
52 |
|
---|
53 | QT_BEGIN_NAMESPACE
|
---|
54 |
|
---|
55 | class QtGradientStopsWidgetPrivate
|
---|
56 | {
|
---|
57 | QtGradientStopsWidget *q_ptr;
|
---|
58 | Q_DECLARE_PUBLIC(QtGradientStopsWidget)
|
---|
59 | public:
|
---|
60 | typedef QMap<qreal, QColor> PositionColorMap;
|
---|
61 | typedef QMap<QtGradientStop *, qreal> StopPositionMap;
|
---|
62 |
|
---|
63 | void slotStopAdded(QtGradientStop *stop);
|
---|
64 | void slotStopRemoved(QtGradientStop *stop);
|
---|
65 | void slotStopMoved(QtGradientStop *stop, qreal newPos);
|
---|
66 | void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
|
---|
67 | void slotStopChanged(QtGradientStop *stop, const QColor &newColor);
|
---|
68 | void slotStopSelected(QtGradientStop *stop, bool selected);
|
---|
69 | void slotCurrentStopChanged(QtGradientStop *stop);
|
---|
70 | void slotNewStop();
|
---|
71 | void slotDelete();
|
---|
72 | void slotFlipAll();
|
---|
73 | void slotSelectAll();
|
---|
74 | void slotZoomIn();
|
---|
75 | void slotZoomOut();
|
---|
76 | void slotResetZoom();
|
---|
77 |
|
---|
78 | double fromViewport(int x) const;
|
---|
79 | double toViewport(double x) const;
|
---|
80 | QtGradientStop *stopAt(const QPoint &viewportPos) const;
|
---|
81 | QList<QtGradientStop *> stopsAt(const QPoint &viewportPos) const;
|
---|
82 | void setupMove(QtGradientStop *stop, int x);
|
---|
83 | void ensureVisible(double x); // x = stop position
|
---|
84 | void ensureVisible(QtGradientStop *stop);
|
---|
85 | QtGradientStop *newStop(const QPoint &viewportPos);
|
---|
86 |
|
---|
87 | bool m_backgroundCheckered;
|
---|
88 | QtGradientStopsModel *m_model;
|
---|
89 | double m_handleSize;
|
---|
90 | int m_scaleFactor;
|
---|
91 | double m_zoom;
|
---|
92 |
|
---|
93 | #ifndef QT_NO_DRAGANDDROP
|
---|
94 | QtGradientStop *m_dragStop;
|
---|
95 | QtGradientStop *m_changedStop;
|
---|
96 | QtGradientStop *m_clonedStop;
|
---|
97 | QtGradientStopsModel *m_dragModel;
|
---|
98 | QColor m_dragColor;
|
---|
99 | void clearDrag();
|
---|
100 | void removeClonedStop();
|
---|
101 | void restoreChangedStop();
|
---|
102 | void changeStop(qreal pos);
|
---|
103 | void cloneStop(qreal pos);
|
---|
104 | #endif
|
---|
105 |
|
---|
106 | QRubberBand *m_rubber;
|
---|
107 | QPoint m_clickPos;
|
---|
108 |
|
---|
109 | QList<QtGradientStop *> m_stops;
|
---|
110 |
|
---|
111 | bool m_moving;
|
---|
112 | int m_moveOffset;
|
---|
113 | StopPositionMap m_moveStops;
|
---|
114 |
|
---|
115 | PositionColorMap m_moveOriginal;
|
---|
116 | };
|
---|
117 |
|
---|
118 | double QtGradientStopsWidgetPrivate::fromViewport(int x) const
|
---|
119 | {
|
---|
120 | QSize size = q_ptr->viewport()->size();
|
---|
121 | int w = size.width();
|
---|
122 | int max = q_ptr->horizontalScrollBar()->maximum();
|
---|
123 | int val = q_ptr->horizontalScrollBar()->value();
|
---|
124 | return ((double)x * m_scaleFactor + w * val) / (w * (m_scaleFactor + max));
|
---|
125 | }
|
---|
126 |
|
---|
127 | double QtGradientStopsWidgetPrivate::toViewport(double x) const
|
---|
128 | {
|
---|
129 | QSize size = q_ptr->viewport()->size();
|
---|
130 | int w = size.width();
|
---|
131 | int max = q_ptr->horizontalScrollBar()->maximum();
|
---|
132 | int val = q_ptr->horizontalScrollBar()->value();
|
---|
133 | return w * (x * (m_scaleFactor + max) - val) / m_scaleFactor;
|
---|
134 | }
|
---|
135 |
|
---|
136 | QtGradientStop *QtGradientStopsWidgetPrivate::stopAt(const QPoint &viewportPos) const
|
---|
137 | {
|
---|
138 | double posY = m_handleSize / 2;
|
---|
139 | QListIterator<QtGradientStop *> itStop(m_stops);
|
---|
140 | while (itStop.hasNext()) {
|
---|
141 | QtGradientStop *stop = itStop.next();
|
---|
142 |
|
---|
143 | double posX = toViewport(stop->position());
|
---|
144 |
|
---|
145 | double x = viewportPos.x() - posX;
|
---|
146 | double y = viewportPos.y() - posY;
|
---|
147 |
|
---|
148 | if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
|
---|
149 | return stop;
|
---|
150 | }
|
---|
151 | return 0;
|
---|
152 | }
|
---|
153 |
|
---|
154 | QList<QtGradientStop *> QtGradientStopsWidgetPrivate::stopsAt(const QPoint &viewportPos) const
|
---|
155 | {
|
---|
156 | QList<QtGradientStop *> stops;
|
---|
157 | double posY = m_handleSize / 2;
|
---|
158 | QListIterator<QtGradientStop *> itStop(m_stops);
|
---|
159 | while (itStop.hasNext()) {
|
---|
160 | QtGradientStop *stop = itStop.next();
|
---|
161 |
|
---|
162 | double posX = toViewport(stop->position());
|
---|
163 |
|
---|
164 | double x = viewportPos.x() - posX;
|
---|
165 | double y = viewportPos.y() - posY;
|
---|
166 |
|
---|
167 | if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
|
---|
168 | stops.append(stop);
|
---|
169 | }
|
---|
170 | return stops;
|
---|
171 | }
|
---|
172 |
|
---|
173 | void QtGradientStopsWidgetPrivate::setupMove(QtGradientStop *stop, int x)
|
---|
174 | {
|
---|
175 | m_model->setCurrentStop(stop);
|
---|
176 |
|
---|
177 | int viewportX = qRound(toViewport(stop->position()));
|
---|
178 | m_moveOffset = x - viewportX;
|
---|
179 |
|
---|
180 | QList<QtGradientStop *> stops = m_stops;
|
---|
181 | m_stops.clear();
|
---|
182 | QListIterator<QtGradientStop *> itStop(stops);
|
---|
183 | while (itStop.hasNext()) {
|
---|
184 | QtGradientStop *s = itStop.next();
|
---|
185 | if (m_model->isSelected(s) || s == stop) {
|
---|
186 | m_moveStops[s] = s->position() - stop->position();
|
---|
187 | m_stops.append(s);
|
---|
188 | } else {
|
---|
189 | m_moveOriginal[s->position()] = s->color();
|
---|
190 | }
|
---|
191 | }
|
---|
192 | itStop.toFront();
|
---|
193 | while (itStop.hasNext()) {
|
---|
194 | QtGradientStop *s = itStop.next();
|
---|
195 | if (!m_model->isSelected(s))
|
---|
196 | m_stops.append(s);
|
---|
197 | }
|
---|
198 | m_stops.removeAll(stop);
|
---|
199 | m_stops.prepend(stop);
|
---|
200 | }
|
---|
201 |
|
---|
202 | void QtGradientStopsWidgetPrivate::ensureVisible(double x)
|
---|
203 | {
|
---|
204 | double viewX = toViewport(x);
|
---|
205 | if (viewX < 0 || viewX > q_ptr->viewport()->size().width()) {
|
---|
206 | int max = q_ptr->horizontalScrollBar()->maximum();
|
---|
207 | int newVal = qRound(x * (max + m_scaleFactor) - m_scaleFactor / 2);
|
---|
208 | q_ptr->horizontalScrollBar()->setValue(newVal);
|
---|
209 | }
|
---|
210 | }
|
---|
211 |
|
---|
212 | void QtGradientStopsWidgetPrivate::ensureVisible(QtGradientStop *stop)
|
---|
213 | {
|
---|
214 | if (!stop)
|
---|
215 | return;
|
---|
216 | ensureVisible(stop->position());
|
---|
217 | }
|
---|
218 |
|
---|
219 | QtGradientStop *QtGradientStopsWidgetPrivate::newStop(const QPoint &viewportPos)
|
---|
220 | {
|
---|
221 | QtGradientStop *copyStop = stopAt(viewportPos);
|
---|
222 | double posX = fromViewport(viewportPos.x());
|
---|
223 | QtGradientStop *stop = m_model->at(posX);
|
---|
224 | if (!stop) {
|
---|
225 | QColor newColor;
|
---|
226 | if (copyStop)
|
---|
227 | newColor = copyStop->color();
|
---|
228 | else
|
---|
229 | newColor = m_model->color(posX);
|
---|
230 | if (!newColor.isValid())
|
---|
231 | newColor = Qt::white;
|
---|
232 | stop = m_model->addStop(posX, newColor);
|
---|
233 | }
|
---|
234 | return stop;
|
---|
235 | }
|
---|
236 |
|
---|
237 | void QtGradientStopsWidgetPrivate::slotStopAdded(QtGradientStop *stop)
|
---|
238 | {
|
---|
239 | m_stops.append(stop);
|
---|
240 | q_ptr->viewport()->update();
|
---|
241 | }
|
---|
242 |
|
---|
243 | void QtGradientStopsWidgetPrivate::slotStopRemoved(QtGradientStop *stop)
|
---|
244 | {
|
---|
245 | m_stops.removeAll(stop);
|
---|
246 | q_ptr->viewport()->update();
|
---|
247 | }
|
---|
248 |
|
---|
249 | void QtGradientStopsWidgetPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos)
|
---|
250 | {
|
---|
251 | Q_UNUSED(stop)
|
---|
252 | Q_UNUSED(newPos)
|
---|
253 | q_ptr->viewport()->update();
|
---|
254 | }
|
---|
255 |
|
---|
256 | void QtGradientStopsWidgetPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)
|
---|
257 | {
|
---|
258 | Q_UNUSED(stop1)
|
---|
259 | Q_UNUSED(stop2)
|
---|
260 | q_ptr->viewport()->update();
|
---|
261 | }
|
---|
262 |
|
---|
263 | void QtGradientStopsWidgetPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor)
|
---|
264 | {
|
---|
265 | Q_UNUSED(stop)
|
---|
266 | Q_UNUSED(newColor)
|
---|
267 | q_ptr->viewport()->update();
|
---|
268 | }
|
---|
269 |
|
---|
270 | void QtGradientStopsWidgetPrivate::slotStopSelected(QtGradientStop *stop, bool selected)
|
---|
271 | {
|
---|
272 | Q_UNUSED(stop)
|
---|
273 | Q_UNUSED(selected)
|
---|
274 | q_ptr->viewport()->update();
|
---|
275 | }
|
---|
276 |
|
---|
277 | void QtGradientStopsWidgetPrivate::slotCurrentStopChanged(QtGradientStop *stop)
|
---|
278 | {
|
---|
279 | Q_UNUSED(stop)
|
---|
280 |
|
---|
281 | if (!m_model)
|
---|
282 | return;
|
---|
283 | q_ptr->viewport()->update();
|
---|
284 | if (stop) {
|
---|
285 | m_stops.removeAll(stop);
|
---|
286 | m_stops.prepend(stop);
|
---|
287 | }
|
---|
288 | }
|
---|
289 |
|
---|
290 | void QtGradientStopsWidgetPrivate::slotNewStop()
|
---|
291 | {
|
---|
292 | if (!m_model)
|
---|
293 | return;
|
---|
294 |
|
---|
295 | QtGradientStop *stop = newStop(m_clickPos);
|
---|
296 |
|
---|
297 | if (!stop)
|
---|
298 | return;
|
---|
299 |
|
---|
300 | m_model->clearSelection();
|
---|
301 | m_model->selectStop(stop, true);
|
---|
302 | m_model->setCurrentStop(stop);
|
---|
303 | }
|
---|
304 |
|
---|
305 | void QtGradientStopsWidgetPrivate::slotDelete()
|
---|
306 | {
|
---|
307 | if (!m_model)
|
---|
308 | return;
|
---|
309 |
|
---|
310 | m_model->deleteStops();
|
---|
311 | }
|
---|
312 |
|
---|
313 | void QtGradientStopsWidgetPrivate::slotFlipAll()
|
---|
314 | {
|
---|
315 | if (!m_model)
|
---|
316 | return;
|
---|
317 |
|
---|
318 | m_model->flipAll();
|
---|
319 | }
|
---|
320 |
|
---|
321 | void QtGradientStopsWidgetPrivate::slotSelectAll()
|
---|
322 | {
|
---|
323 | if (!m_model)
|
---|
324 | return;
|
---|
325 |
|
---|
326 | m_model->selectAll();
|
---|
327 | }
|
---|
328 |
|
---|
329 | void QtGradientStopsWidgetPrivate::slotZoomIn()
|
---|
330 | {
|
---|
331 | double newZoom = q_ptr->zoom() * 2;
|
---|
332 | if (newZoom > 100)
|
---|
333 | newZoom = 100;
|
---|
334 | if (newZoom == q_ptr->zoom())
|
---|
335 | return;
|
---|
336 |
|
---|
337 | q_ptr->setZoom(newZoom);
|
---|
338 | emit q_ptr->zoomChanged(q_ptr->zoom());
|
---|
339 | }
|
---|
340 |
|
---|
341 | void QtGradientStopsWidgetPrivate::slotZoomOut()
|
---|
342 | {
|
---|
343 | double newZoom = q_ptr->zoom() / 2;
|
---|
344 | if (newZoom < 1)
|
---|
345 | newZoom = 1;
|
---|
346 | if (newZoom == q_ptr->zoom())
|
---|
347 | return;
|
---|
348 |
|
---|
349 | q_ptr->setZoom(newZoom);
|
---|
350 | emit q_ptr->zoomChanged(q_ptr->zoom());
|
---|
351 | }
|
---|
352 |
|
---|
353 | void QtGradientStopsWidgetPrivate::slotResetZoom()
|
---|
354 | {
|
---|
355 | if (1 == q_ptr->zoom())
|
---|
356 | return;
|
---|
357 |
|
---|
358 | q_ptr->setZoom(1);
|
---|
359 | emit q_ptr->zoomChanged(1);
|
---|
360 | }
|
---|
361 |
|
---|
362 | QtGradientStopsWidget::QtGradientStopsWidget(QWidget *parent)
|
---|
363 | : QAbstractScrollArea(parent), d_ptr(new QtGradientStopsWidgetPrivate)
|
---|
364 | {
|
---|
365 | d_ptr->q_ptr = this;
|
---|
366 | d_ptr->m_backgroundCheckered = true;
|
---|
367 | d_ptr->m_model = 0;
|
---|
368 | d_ptr->m_handleSize = 25.0;
|
---|
369 | d_ptr->m_scaleFactor = 1000;
|
---|
370 | d_ptr->m_moving = false;
|
---|
371 | d_ptr->m_zoom = 1;
|
---|
372 | d_ptr->m_rubber = new QRubberBand(QRubberBand::Rectangle, this);
|
---|
373 | #ifndef QT_NO_DRAGANDDROP
|
---|
374 | d_ptr->m_dragStop = 0;
|
---|
375 | d_ptr->m_changedStop = 0;
|
---|
376 | d_ptr->m_clonedStop = 0;
|
---|
377 | d_ptr->m_dragModel = 0;
|
---|
378 | #endif
|
---|
379 | setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
---|
380 | setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
---|
381 | horizontalScrollBar()->setRange(0, (int)(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1) + 0.5));
|
---|
382 | horizontalScrollBar()->setPageStep(d_ptr->m_scaleFactor);
|
---|
383 | horizontalScrollBar()->setSingleStep(4);
|
---|
384 | viewport()->setAutoFillBackground(false);
|
---|
385 |
|
---|
386 | setAcceptDrops(true);
|
---|
387 |
|
---|
388 | setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
|
---|
389 | }
|
---|
390 |
|
---|
391 | QtGradientStopsWidget::~QtGradientStopsWidget()
|
---|
392 | {
|
---|
393 | }
|
---|
394 |
|
---|
395 | QSize QtGradientStopsWidget::sizeHint() const
|
---|
396 | {
|
---|
397 | return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->sizeHint().height());
|
---|
398 | }
|
---|
399 |
|
---|
400 | QSize QtGradientStopsWidget::minimumSizeHint() const
|
---|
401 | {
|
---|
402 | return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->minimumSizeHint().height());
|
---|
403 | }
|
---|
404 |
|
---|
405 | void QtGradientStopsWidget::setBackgroundCheckered(bool checkered)
|
---|
406 | {
|
---|
407 | if (d_ptr->m_backgroundCheckered == checkered)
|
---|
408 | return;
|
---|
409 | d_ptr->m_backgroundCheckered = checkered;
|
---|
410 | update();
|
---|
411 | }
|
---|
412 |
|
---|
413 | bool QtGradientStopsWidget::isBackgroundCheckered() const
|
---|
414 | {
|
---|
415 | return d_ptr->m_backgroundCheckered;
|
---|
416 | }
|
---|
417 |
|
---|
418 | void QtGradientStopsWidget::setGradientStopsModel(QtGradientStopsModel *model)
|
---|
419 | {
|
---|
420 | if (d_ptr->m_model == model)
|
---|
421 | return;
|
---|
422 |
|
---|
423 | if (d_ptr->m_model) {
|
---|
424 | disconnect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
|
---|
425 | this, SLOT(slotStopAdded(QtGradientStop*)));
|
---|
426 | disconnect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
|
---|
427 | this, SLOT(slotStopRemoved(QtGradientStop*)));
|
---|
428 | disconnect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
|
---|
429 | this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
|
---|
430 | disconnect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
|
---|
431 | this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
|
---|
432 | disconnect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
|
---|
433 | this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
|
---|
434 | disconnect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
|
---|
435 | this, SLOT(slotStopSelected(QtGradientStop*,bool)));
|
---|
436 | disconnect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
|
---|
437 | this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
|
---|
438 |
|
---|
439 | d_ptr->m_stops.clear();
|
---|
440 | }
|
---|
441 |
|
---|
442 | d_ptr->m_model = model;
|
---|
443 |
|
---|
444 | if (d_ptr->m_model) {
|
---|
445 | connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
|
---|
446 | this, SLOT(slotStopAdded(QtGradientStop*)));
|
---|
447 | connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
|
---|
448 | this, SLOT(slotStopRemoved(QtGradientStop*)));
|
---|
449 | connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
|
---|
450 | this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
|
---|
451 | connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
|
---|
452 | this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
|
---|
453 | connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
|
---|
454 | this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
|
---|
455 | connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
|
---|
456 | this, SLOT(slotStopSelected(QtGradientStop*,bool)));
|
---|
457 | connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
|
---|
458 | this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
|
---|
459 |
|
---|
460 | QList<QtGradientStop *> stops = d_ptr->m_model->stops().values();
|
---|
461 | QListIterator<QtGradientStop *> itStop(stops);
|
---|
462 | while (itStop.hasNext())
|
---|
463 | d_ptr->slotStopAdded(itStop.next());
|
---|
464 |
|
---|
465 | QList<QtGradientStop *> selected = d_ptr->m_model->selectedStops();
|
---|
466 | QListIterator<QtGradientStop *> itSelect(selected);
|
---|
467 | while (itSelect.hasNext())
|
---|
468 | d_ptr->slotStopSelected(itSelect.next(), true);
|
---|
469 |
|
---|
470 | d_ptr->slotCurrentStopChanged(d_ptr->m_model->currentStop());
|
---|
471 | }
|
---|
472 | }
|
---|
473 |
|
---|
474 | void QtGradientStopsWidget::mousePressEvent(QMouseEvent *e)
|
---|
475 | {
|
---|
476 | typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
|
---|
477 | if (!d_ptr->m_model)
|
---|
478 | return;
|
---|
479 |
|
---|
480 | if (e->button() != Qt::LeftButton)
|
---|
481 | return;
|
---|
482 |
|
---|
483 | d_ptr->m_moving = true;
|
---|
484 |
|
---|
485 | d_ptr->m_moveStops.clear();
|
---|
486 | d_ptr->m_moveOriginal.clear();
|
---|
487 | d_ptr->m_clickPos = e->pos();
|
---|
488 | QtGradientStop *stop = d_ptr->stopAt(e->pos());
|
---|
489 | if (stop) {
|
---|
490 | if (e->modifiers() & Qt::ControlModifier) {
|
---|
491 | d_ptr->m_model->selectStop(stop, !d_ptr->m_model->isSelected(stop));
|
---|
492 | } else if (e->modifiers() & Qt::ShiftModifier) {
|
---|
493 | QtGradientStop *oldCurrent = d_ptr->m_model->currentStop();
|
---|
494 | if (oldCurrent) {
|
---|
495 | PositionStopMap stops = d_ptr->m_model->stops();
|
---|
496 | PositionStopMap::ConstIterator itSt = stops.constFind(oldCurrent->position());
|
---|
497 | if (itSt != stops.constEnd()) {
|
---|
498 | while (itSt != stops.constFind(stop->position())) {
|
---|
499 | d_ptr->m_model->selectStop(itSt.value(), true);
|
---|
500 | if (oldCurrent->position() < stop->position())
|
---|
501 | ++itSt;
|
---|
502 | else
|
---|
503 | --itSt;
|
---|
504 | }
|
---|
505 | }
|
---|
506 | }
|
---|
507 | d_ptr->m_model->selectStop(stop, true);
|
---|
508 | } else {
|
---|
509 | if (!d_ptr->m_model->isSelected(stop)) {
|
---|
510 | d_ptr->m_model->clearSelection();
|
---|
511 | d_ptr->m_model->selectStop(stop, true);
|
---|
512 | }
|
---|
513 | }
|
---|
514 | d_ptr->setupMove(stop, e->pos().x());
|
---|
515 | } else {
|
---|
516 | d_ptr->m_model->clearSelection();
|
---|
517 | d_ptr->m_rubber->setGeometry(QRect(d_ptr->m_clickPos, QSize()));
|
---|
518 | d_ptr->m_rubber->show();
|
---|
519 | }
|
---|
520 | viewport()->update();
|
---|
521 | }
|
---|
522 |
|
---|
523 | void QtGradientStopsWidget::mouseReleaseEvent(QMouseEvent *e)
|
---|
524 | {
|
---|
525 | if (!d_ptr->m_model)
|
---|
526 | return;
|
---|
527 |
|
---|
528 | if (e->button() != Qt::LeftButton)
|
---|
529 | return;
|
---|
530 |
|
---|
531 | d_ptr->m_moving = false;
|
---|
532 | d_ptr->m_rubber->hide();
|
---|
533 | d_ptr->m_moveStops.clear();
|
---|
534 | d_ptr->m_moveOriginal.clear();
|
---|
535 | }
|
---|
536 |
|
---|
537 | void QtGradientStopsWidget::mouseMoveEvent(QMouseEvent *e)
|
---|
538 | {
|
---|
539 | typedef QtGradientStopsWidgetPrivate::PositionColorMap PositionColorMap;
|
---|
540 | typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
|
---|
541 | typedef QtGradientStopsWidgetPrivate::StopPositionMap StopPositionMap;
|
---|
542 | if (!d_ptr->m_model)
|
---|
543 | return;
|
---|
544 |
|
---|
545 | if (!(e->buttons() & Qt::LeftButton))
|
---|
546 | return;
|
---|
547 |
|
---|
548 | if (!d_ptr->m_moving)
|
---|
549 | return;
|
---|
550 |
|
---|
551 | if (!d_ptr->m_moveStops.isEmpty()) {
|
---|
552 | double maxOffset = 0.0;
|
---|
553 | double minOffset = 0.0;
|
---|
554 | bool first = true;
|
---|
555 | StopPositionMap::ConstIterator itStop = d_ptr->m_moveStops.constBegin();
|
---|
556 | while (itStop != d_ptr->m_moveStops.constEnd()) {
|
---|
557 | double offset = itStop.value();
|
---|
558 |
|
---|
559 | if (first) {
|
---|
560 | maxOffset = offset;
|
---|
561 | minOffset = offset;
|
---|
562 | first = false;
|
---|
563 | } else {
|
---|
564 | if (maxOffset < offset)
|
---|
565 | maxOffset = offset;
|
---|
566 | else if (minOffset > offset)
|
---|
567 | minOffset = offset;
|
---|
568 | }
|
---|
569 | ++itStop;
|
---|
570 | }
|
---|
571 |
|
---|
572 | double viewportMin = d_ptr->toViewport(-minOffset);
|
---|
573 | double viewportMax = d_ptr->toViewport(1.0 - maxOffset);
|
---|
574 |
|
---|
575 | PositionStopMap newPositions;
|
---|
576 |
|
---|
577 | int viewportX = e->pos().x() - d_ptr->m_moveOffset;
|
---|
578 |
|
---|
579 | if (viewportX > viewport()->size().width())
|
---|
580 | viewportX = viewport()->size().width();
|
---|
581 | else if (viewportX < 0)
|
---|
582 | viewportX = 0;
|
---|
583 |
|
---|
584 | double posX = d_ptr->fromViewport(viewportX);
|
---|
585 |
|
---|
586 | if (viewportX > viewportMax)
|
---|
587 | posX = 1.0 - maxOffset;
|
---|
588 | else if (viewportX < viewportMin)
|
---|
589 | posX = -minOffset;
|
---|
590 |
|
---|
591 | itStop = d_ptr->m_moveStops.constBegin();
|
---|
592 | while (itStop != d_ptr->m_moveStops.constEnd()) {
|
---|
593 | QtGradientStop *stop = itStop.key();
|
---|
594 |
|
---|
595 | newPositions[posX + itStop.value()] = stop;
|
---|
596 |
|
---|
597 | ++itStop;
|
---|
598 | }
|
---|
599 |
|
---|
600 | bool forward = true;
|
---|
601 | PositionStopMap::ConstIterator itNewPos = newPositions.constBegin();
|
---|
602 | if (itNewPos.value()->position() < itNewPos.key())
|
---|
603 | forward = false;
|
---|
604 |
|
---|
605 | itNewPos = forward ? newPositions.constBegin() : newPositions.constEnd();
|
---|
606 | while (itNewPos != (forward ? newPositions.constEnd() : newPositions.constBegin())) {
|
---|
607 | if (!forward)
|
---|
608 | --itNewPos;
|
---|
609 | QtGradientStop *stop = itNewPos.value();
|
---|
610 | double newPos = itNewPos.key();
|
---|
611 | if (newPos > 1)
|
---|
612 | newPos = 1;
|
---|
613 | else if (newPos < 0)
|
---|
614 | newPos = 0;
|
---|
615 |
|
---|
616 | QtGradientStop *existingStop = d_ptr->m_model->at(newPos);
|
---|
617 | if (existingStop && !d_ptr->m_moveStops.contains(existingStop))
|
---|
618 | d_ptr->m_model->removeStop(existingStop);
|
---|
619 | d_ptr->m_model->moveStop(stop, newPos);
|
---|
620 |
|
---|
621 | if (forward)
|
---|
622 | ++itNewPos;
|
---|
623 | }
|
---|
624 |
|
---|
625 | PositionColorMap::ConstIterator itOld = d_ptr->m_moveOriginal.constBegin();
|
---|
626 | while (itOld != d_ptr->m_moveOriginal.constEnd()) {
|
---|
627 | double position = itOld.key();
|
---|
628 | if (!d_ptr->m_model->at(position))
|
---|
629 | d_ptr->m_model->addStop(position, itOld.value());
|
---|
630 |
|
---|
631 | ++itOld;
|
---|
632 | }
|
---|
633 |
|
---|
634 | } else {
|
---|
635 | QRect r(QRect(d_ptr->m_clickPos, e->pos()).normalized());
|
---|
636 | r.translate(1, 0);
|
---|
637 | d_ptr->m_rubber->setGeometry(r);
|
---|
638 | //d_ptr->m_model->clearSelection();
|
---|
639 |
|
---|
640 | int xv1 = d_ptr->m_clickPos.x();
|
---|
641 | int xv2 = e->pos().x();
|
---|
642 | if (xv1 > xv2) {
|
---|
643 | int temp = xv1;
|
---|
644 | xv1 = xv2;
|
---|
645 | xv2 = temp;
|
---|
646 | }
|
---|
647 | int yv1 = d_ptr->m_clickPos.y();
|
---|
648 | int yv2 = e->pos().y();
|
---|
649 | if (yv1 > yv2) {
|
---|
650 | int temp = yv1;
|
---|
651 | yv1 = yv2;
|
---|
652 | yv2 = temp;
|
---|
653 | }
|
---|
654 |
|
---|
655 | QPoint p1, p2;
|
---|
656 |
|
---|
657 | if (yv2 < d_ptr->m_handleSize / 2) {
|
---|
658 | p1 = QPoint(xv1, yv2);
|
---|
659 | p2 = QPoint(xv2, yv2);
|
---|
660 | } else if (yv1 > d_ptr->m_handleSize / 2) {
|
---|
661 | p1 = QPoint(xv1, yv1);
|
---|
662 | p2 = QPoint(xv2, yv1);
|
---|
663 | } else {
|
---|
664 | p1 = QPoint(xv1, qRound(d_ptr->m_handleSize / 2));
|
---|
665 | p2 = QPoint(xv2, qRound(d_ptr->m_handleSize / 2));
|
---|
666 | }
|
---|
667 |
|
---|
668 | QList<QtGradientStop *> beginList = d_ptr->stopsAt(p1);
|
---|
669 | QList<QtGradientStop *> endList = d_ptr->stopsAt(p2);
|
---|
670 |
|
---|
671 | double x1 = d_ptr->fromViewport(xv1);
|
---|
672 | double x2 = d_ptr->fromViewport(xv2);
|
---|
673 |
|
---|
674 | QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
|
---|
675 | while (itStop.hasNext()) {
|
---|
676 | QtGradientStop *stop = itStop.next();
|
---|
677 | if ((stop->position() >= x1 && stop->position() <= x2) ||
|
---|
678 | beginList.contains(stop) || endList.contains(stop))
|
---|
679 | d_ptr->m_model->selectStop(stop, true);
|
---|
680 | else
|
---|
681 | d_ptr->m_model->selectStop(stop, false);
|
---|
682 | }
|
---|
683 | }
|
---|
684 | }
|
---|
685 |
|
---|
686 | void QtGradientStopsWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
---|
687 | {
|
---|
688 | if (!d_ptr->m_model)
|
---|
689 | return;
|
---|
690 |
|
---|
691 | if (e->button() != Qt::LeftButton)
|
---|
692 | return;
|
---|
693 |
|
---|
694 | if (d_ptr->m_clickPos != e->pos()) {
|
---|
695 | mousePressEvent(e);
|
---|
696 | return;
|
---|
697 | }
|
---|
698 | d_ptr->m_moving = true;
|
---|
699 | d_ptr->m_moveStops.clear();
|
---|
700 | d_ptr->m_moveOriginal.clear();
|
---|
701 |
|
---|
702 | QtGradientStop *stop = d_ptr->newStop(e->pos());
|
---|
703 |
|
---|
704 | if (!stop)
|
---|
705 | return;
|
---|
706 |
|
---|
707 | d_ptr->m_model->clearSelection();
|
---|
708 | d_ptr->m_model->selectStop(stop, true);
|
---|
709 |
|
---|
710 | d_ptr->setupMove(stop, e->pos().x());
|
---|
711 |
|
---|
712 | viewport()->update();
|
---|
713 | }
|
---|
714 |
|
---|
715 | void QtGradientStopsWidget::keyPressEvent(QKeyEvent *e)
|
---|
716 | {
|
---|
717 | typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
|
---|
718 | if (!d_ptr->m_model)
|
---|
719 | return;
|
---|
720 |
|
---|
721 | if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) {
|
---|
722 | d_ptr->m_model->deleteStops();
|
---|
723 | } else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right ||
|
---|
724 | e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
|
---|
725 | PositionStopMap stops = d_ptr->m_model->stops();
|
---|
726 | if (stops.isEmpty())
|
---|
727 | return;
|
---|
728 | QtGradientStop *newCurrent = 0;
|
---|
729 | QtGradientStop *current = d_ptr->m_model->currentStop();
|
---|
730 | if (!current || e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
|
---|
731 | if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Home)
|
---|
732 | newCurrent = stops.constBegin().value();
|
---|
733 | else if (e->key() == Qt::Key_Right || e->key() == Qt::Key_End)
|
---|
734 | newCurrent = (--stops.constEnd()).value();
|
---|
735 | } else {
|
---|
736 | PositionStopMap::ConstIterator itStop = stops.constBegin();
|
---|
737 | while (itStop.value() != current)
|
---|
738 | ++itStop;
|
---|
739 | if (e->key() == Qt::Key_Left && itStop != stops.constBegin())
|
---|
740 | --itStop;
|
---|
741 | else if (e->key() == Qt::Key_Right && itStop != --stops.constEnd())
|
---|
742 | ++itStop;
|
---|
743 | newCurrent = itStop.value();
|
---|
744 | }
|
---|
745 | d_ptr->m_model->clearSelection();
|
---|
746 | d_ptr->m_model->selectStop(newCurrent, true);
|
---|
747 | d_ptr->m_model->setCurrentStop(newCurrent);
|
---|
748 | d_ptr->ensureVisible(newCurrent);
|
---|
749 | } else if (e->key() == Qt::Key_A) {
|
---|
750 | if (e->modifiers() & Qt::ControlModifier)
|
---|
751 | d_ptr->m_model->selectAll();
|
---|
752 | }
|
---|
753 | }
|
---|
754 |
|
---|
755 | void QtGradientStopsWidget::paintEvent(QPaintEvent *e)
|
---|
756 | {
|
---|
757 | Q_UNUSED(e)
|
---|
758 | if (!d_ptr->m_model)
|
---|
759 | return;
|
---|
760 |
|
---|
761 | QtGradientStopsModel *model = d_ptr->m_model;
|
---|
762 | #ifndef QT_NO_DRAGANDDROP
|
---|
763 | if (d_ptr->m_dragModel)
|
---|
764 | model = d_ptr->m_dragModel;
|
---|
765 | #endif
|
---|
766 |
|
---|
767 | QSize size = viewport()->size();
|
---|
768 | int w = size.width();
|
---|
769 | double h = size.height() - d_ptr->m_handleSize;
|
---|
770 | if (w <= 0)
|
---|
771 | return;
|
---|
772 |
|
---|
773 | QPixmap pix(size);
|
---|
774 | QPainter p;
|
---|
775 |
|
---|
776 | if (d_ptr->m_backgroundCheckered) {
|
---|
777 | int pixSize = 20;
|
---|
778 | QPixmap pm(2 * pixSize, 2 * pixSize);
|
---|
779 | QPainter pmp(&pm);
|
---|
780 | pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
|
---|
781 | pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
|
---|
782 | pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
|
---|
783 | pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
|
---|
784 |
|
---|
785 | p.begin(&pix);
|
---|
786 | p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
|
---|
787 | p.fillRect(viewport()->rect(), pm);
|
---|
788 | p.setBrushOrigin(0, 0);
|
---|
789 | } else {
|
---|
790 | p.begin(viewport());
|
---|
791 | }
|
---|
792 |
|
---|
793 | double viewBegin = (double)w * horizontalScrollBar()->value() / d_ptr->m_scaleFactor;
|
---|
794 |
|
---|
795 | int val = horizontalScrollBar()->value();
|
---|
796 | int max = horizontalScrollBar()->maximum();
|
---|
797 |
|
---|
798 | double begin = (double)val / (d_ptr->m_scaleFactor + max);
|
---|
799 | double end = (double)(val + d_ptr->m_scaleFactor) / (d_ptr->m_scaleFactor + max);
|
---|
800 | double width = end - begin;
|
---|
801 |
|
---|
802 | if (h > 0) {
|
---|
803 | QLinearGradient lg(0, 0, w, 0);
|
---|
804 | QMap<qreal, QtGradientStop *> stops = model->stops();
|
---|
805 | QMapIterator<qreal, QtGradientStop *> itStop(stops);
|
---|
806 | while (itStop.hasNext()) {
|
---|
807 | QtGradientStop *stop = itStop.next().value();
|
---|
808 | double pos = stop->position();
|
---|
809 | if (pos >= begin && pos <= end) {
|
---|
810 | double gradPos = (pos - begin) / width;
|
---|
811 | QColor c = stop->color();
|
---|
812 | lg.setColorAt(gradPos, c);
|
---|
813 | }
|
---|
814 | //lg.setColorAt(stop->position(), stop->color());
|
---|
815 | }
|
---|
816 | lg.setColorAt(0, model->color(begin));
|
---|
817 | lg.setColorAt(1, model->color(end));
|
---|
818 | QImage img(w, 1, QImage::Format_ARGB32_Premultiplied);
|
---|
819 | QPainter p1(&img);
|
---|
820 | p1.setCompositionMode(QPainter::CompositionMode_Source);
|
---|
821 |
|
---|
822 | /*
|
---|
823 | if (viewBegin != 0)
|
---|
824 | p1.translate(-viewBegin, 0);
|
---|
825 | if (d_ptr->m_zoom != 1)
|
---|
826 | p1.scale(d_ptr->m_zoom, 1);
|
---|
827 | */
|
---|
828 | p1.fillRect(0, 0, w, 1, lg);
|
---|
829 |
|
---|
830 | p.fillRect(QRectF(0, d_ptr->m_handleSize, w, h), QPixmap::fromImage(img));
|
---|
831 | }
|
---|
832 |
|
---|
833 |
|
---|
834 | double handleWidth = d_ptr->m_handleSize * d_ptr->m_scaleFactor / (w * (d_ptr->m_scaleFactor + max));
|
---|
835 |
|
---|
836 | QColor insideColor = QColor::fromRgb(0x20, 0x20, 0x20, 0xFF);
|
---|
837 | QColor borderColor = QColor(Qt::white);
|
---|
838 | QColor drawColor;
|
---|
839 | QColor back1 = QColor(Qt::lightGray);
|
---|
840 | QColor back2 = QColor(Qt::darkGray);
|
---|
841 | QColor back = QColor::fromRgb((back1.red() + back2.red()) / 2,
|
---|
842 | (back1.green() + back2.green()) / 2,
|
---|
843 | (back1.blue() + back2.blue()) / 2);
|
---|
844 |
|
---|
845 | QPen pen;
|
---|
846 | p.setRenderHint(QPainter::Antialiasing);
|
---|
847 | QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
|
---|
848 | itStop.toBack();
|
---|
849 | while (itStop.hasPrevious()) {
|
---|
850 | QtGradientStop *stop = itStop.previous();
|
---|
851 | double x = stop->position();
|
---|
852 | if (x >= begin - handleWidth / 2 && x <= end + handleWidth / 2) {
|
---|
853 | double viewX = x * w * (d_ptr->m_scaleFactor + max) / d_ptr->m_scaleFactor - viewBegin;
|
---|
854 | p.save();
|
---|
855 | QColor c = stop->color();
|
---|
856 | #ifndef QT_NO_DRAGANDDROP
|
---|
857 | if (stop == d_ptr->m_dragStop)
|
---|
858 | c = d_ptr->m_dragColor;
|
---|
859 | #endif
|
---|
860 | if ((0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF()) * c.alphaF() +
|
---|
861 | (0.3 * back.redF() + 0.59 * back.greenF() + 0.11 * back.blueF()) * (1.0 - c.alphaF()) < 0.5) {
|
---|
862 | drawColor = QColor::fromRgb(0xC0, 0xC0, 0xC0, 0xB0);
|
---|
863 | } else {
|
---|
864 | drawColor = QColor::fromRgb(0x40, 0x40, 0x40, 0x80);
|
---|
865 | }
|
---|
866 | QRectF rect(viewX - d_ptr->m_handleSize / 2, 0, d_ptr->m_handleSize, d_ptr->m_handleSize);
|
---|
867 | rect.adjust(0.5, 0.5, -0.5, -0.5);
|
---|
868 | if (h > 0) {
|
---|
869 | pen.setWidthF(1);
|
---|
870 | QLinearGradient lg(0, d_ptr->m_handleSize, 0, d_ptr->m_handleSize + h / 2);
|
---|
871 | lg.setColorAt(0, drawColor);
|
---|
872 | QColor alphaZero = drawColor;
|
---|
873 | alphaZero.setAlpha(0);
|
---|
874 | lg.setColorAt(1, alphaZero);
|
---|
875 | pen.setBrush(lg);
|
---|
876 | p.setPen(pen);
|
---|
877 | p.drawLine(QPointF(viewX, d_ptr->m_handleSize), QPointF(viewX, d_ptr->m_handleSize + h / 2));
|
---|
878 |
|
---|
879 | pen.setWidthF(1);
|
---|
880 | pen.setBrush(drawColor);
|
---|
881 | p.setPen(pen);
|
---|
882 | QRectF r1 = rect.adjusted(0.5, 0.5, -0.5, -0.5);
|
---|
883 | QRectF r2 = rect.adjusted(1.5, 1.5, -1.5, -1.5);
|
---|
884 | QColor inColor = QColor::fromRgb(0x80, 0x80, 0x80, 0x80);
|
---|
885 | if (!d_ptr->m_model->isSelected(stop)) {
|
---|
886 | p.setBrush(c);
|
---|
887 | p.drawEllipse(rect);
|
---|
888 | } else {
|
---|
889 | pen.setBrush(insideColor);
|
---|
890 | pen.setWidthF(2);
|
---|
891 | p.setPen(pen);
|
---|
892 | p.setBrush(Qt::NoBrush);
|
---|
893 | p.drawEllipse(r1);
|
---|
894 |
|
---|
895 | pen.setBrush(inColor);
|
---|
896 | pen.setWidthF(1);
|
---|
897 | p.setPen(pen);
|
---|
898 | p.setBrush(c);
|
---|
899 | p.drawEllipse(r2);
|
---|
900 | }
|
---|
901 |
|
---|
902 | if (d_ptr->m_model->currentStop() == stop) {
|
---|
903 | p.setBrush(Qt::NoBrush);
|
---|
904 | pen.setWidthF(5);
|
---|
905 | pen.setBrush(drawColor);
|
---|
906 | int corr = 4;
|
---|
907 | if (!d_ptr->m_model->isSelected(stop)) {
|
---|
908 | corr = 3;
|
---|
909 | pen.setWidthF(7);
|
---|
910 | }
|
---|
911 | p.setPen(pen);
|
---|
912 | p.drawEllipse(rect.adjusted(corr, corr, -corr, -corr));
|
---|
913 | }
|
---|
914 |
|
---|
915 | }
|
---|
916 | p.restore();
|
---|
917 | }
|
---|
918 | }
|
---|
919 | if (d_ptr->m_backgroundCheckered) {
|
---|
920 | p.end();
|
---|
921 | p.begin(viewport());
|
---|
922 | p.drawPixmap(0, 0, pix);
|
---|
923 | }
|
---|
924 | p.end();
|
---|
925 | }
|
---|
926 |
|
---|
927 | void QtGradientStopsWidget::focusInEvent(QFocusEvent *e)
|
---|
928 | {
|
---|
929 | Q_UNUSED(e)
|
---|
930 | viewport()->update();
|
---|
931 | }
|
---|
932 |
|
---|
933 | void QtGradientStopsWidget::focusOutEvent(QFocusEvent *e)
|
---|
934 | {
|
---|
935 | Q_UNUSED(e)
|
---|
936 | viewport()->update();
|
---|
937 | }
|
---|
938 |
|
---|
939 | void QtGradientStopsWidget::contextMenuEvent(QContextMenuEvent *e)
|
---|
940 | {
|
---|
941 | if (!d_ptr->m_model)
|
---|
942 | return;
|
---|
943 |
|
---|
944 | d_ptr->m_clickPos = e->pos();
|
---|
945 |
|
---|
946 | QMenu menu(this);
|
---|
947 | QAction *newStopAction = new QAction(tr("New Stop"), &menu);
|
---|
948 | QAction *deleteAction = new QAction(tr("Delete"), &menu);
|
---|
949 | QAction *flipAllAction = new QAction(tr("Flip All"), &menu);
|
---|
950 | QAction *selectAllAction = new QAction(tr("Select All"), &menu);
|
---|
951 | QAction *zoomInAction = new QAction(tr("Zoom In"), &menu);
|
---|
952 | QAction *zoomOutAction = new QAction(tr("Zoom Out"), &menu);
|
---|
953 | QAction *zoomAllAction = new QAction(tr("Reset Zoom"), &menu);
|
---|
954 | if (d_ptr->m_model->selectedStops().isEmpty() && !d_ptr->m_model->currentStop())
|
---|
955 | deleteAction->setEnabled(false);
|
---|
956 | if (zoom() <= 1) {
|
---|
957 | zoomOutAction->setEnabled(false);
|
---|
958 | zoomAllAction->setEnabled(false);
|
---|
959 | } else if (zoom() >= 100) {
|
---|
960 | zoomInAction->setEnabled(false);
|
---|
961 | }
|
---|
962 | connect(newStopAction, SIGNAL(triggered()), this, SLOT(slotNewStop()));
|
---|
963 | connect(deleteAction, SIGNAL(triggered()), this, SLOT(slotDelete()));
|
---|
964 | connect(flipAllAction, SIGNAL(triggered()), this, SLOT(slotFlipAll()));
|
---|
965 | connect(selectAllAction, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
|
---|
966 | connect(zoomInAction, SIGNAL(triggered()), this, SLOT(slotZoomIn()));
|
---|
967 | connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(slotZoomOut()));
|
---|
968 | connect(zoomAllAction, SIGNAL(triggered()), this, SLOT(slotResetZoom()));
|
---|
969 | menu.addAction(newStopAction);
|
---|
970 | menu.addAction(deleteAction);
|
---|
971 | menu.addAction(flipAllAction);
|
---|
972 | menu.addAction(selectAllAction);
|
---|
973 | menu.addSeparator();
|
---|
974 | menu.addAction(zoomInAction);
|
---|
975 | menu.addAction(zoomOutAction);
|
---|
976 | menu.addAction(zoomAllAction);
|
---|
977 | menu.exec(e->globalPos());
|
---|
978 | }
|
---|
979 |
|
---|
980 | void QtGradientStopsWidget::wheelEvent(QWheelEvent *e)
|
---|
981 | {
|
---|
982 | int numDegrees = e->delta() / 8;
|
---|
983 | int numSteps = numDegrees / 15;
|
---|
984 |
|
---|
985 | int shift = numSteps;
|
---|
986 | if (shift < 0)
|
---|
987 | shift = -shift;
|
---|
988 | int pow = 1 << shift;
|
---|
989 | //const double c = 0.7071067; // 2 steps per doubled value
|
---|
990 | const double c = 0.5946036; // 4 steps pre doubled value
|
---|
991 | // in general c = pow(2, 1 / n) / 2; where n is the step
|
---|
992 | double factor = pow * c;
|
---|
993 |
|
---|
994 | double newZoom = zoom();
|
---|
995 | if (numSteps < 0)
|
---|
996 | newZoom /= factor;
|
---|
997 | else
|
---|
998 | newZoom *= factor;
|
---|
999 | if (newZoom > 100)
|
---|
1000 | newZoom = 100;
|
---|
1001 | if (newZoom < 1)
|
---|
1002 | newZoom = 1;
|
---|
1003 |
|
---|
1004 | if (newZoom == zoom())
|
---|
1005 | return;
|
---|
1006 |
|
---|
1007 | setZoom(newZoom);
|
---|
1008 | emit zoomChanged(zoom());
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | #ifndef QT_NO_DRAGANDDROP
|
---|
1012 | void QtGradientStopsWidget::dragEnterEvent(QDragEnterEvent *event)
|
---|
1013 | {
|
---|
1014 | const QMimeData *mime = event->mimeData();
|
---|
1015 | if (!mime->hasColor())
|
---|
1016 | return;
|
---|
1017 | event->accept();
|
---|
1018 | d_ptr->m_dragModel = d_ptr->m_model->clone();
|
---|
1019 |
|
---|
1020 | d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
|
---|
1021 | update();
|
---|
1022 | }
|
---|
1023 |
|
---|
1024 | void QtGradientStopsWidget::dragMoveEvent(QDragMoveEvent *event)
|
---|
1025 | {
|
---|
1026 | QRectF rect = viewport()->rect();
|
---|
1027 | rect.adjust(0, d_ptr->m_handleSize, 0, 0);
|
---|
1028 | double x = d_ptr->fromViewport(event->pos().x());
|
---|
1029 | QtGradientStop *dragStop = d_ptr->stopAt(event->pos());
|
---|
1030 | if (dragStop) {
|
---|
1031 | event->accept();
|
---|
1032 | d_ptr->removeClonedStop();
|
---|
1033 | d_ptr->changeStop(dragStop->position());
|
---|
1034 | } else if (rect.contains(event->pos())) {
|
---|
1035 | event->accept();
|
---|
1036 | if (d_ptr->m_model->at(x)) {
|
---|
1037 | d_ptr->removeClonedStop();
|
---|
1038 | d_ptr->changeStop(x);
|
---|
1039 | } else {
|
---|
1040 | d_ptr->restoreChangedStop();
|
---|
1041 | d_ptr->cloneStop(x);
|
---|
1042 | }
|
---|
1043 | } else {
|
---|
1044 | event->ignore();
|
---|
1045 | d_ptr->removeClonedStop();
|
---|
1046 | d_ptr->restoreChangedStop();
|
---|
1047 | }
|
---|
1048 |
|
---|
1049 | update();
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | void QtGradientStopsWidget::dragLeaveEvent(QDragLeaveEvent *event)
|
---|
1053 | {
|
---|
1054 | event->accept();
|
---|
1055 | d_ptr->clearDrag();
|
---|
1056 | update();
|
---|
1057 | }
|
---|
1058 |
|
---|
1059 | void QtGradientStopsWidget::dropEvent(QDropEvent *event)
|
---|
1060 | {
|
---|
1061 | event->accept();
|
---|
1062 | if (!d_ptr->m_dragModel)
|
---|
1063 | return;
|
---|
1064 |
|
---|
1065 | if (d_ptr->m_changedStop)
|
---|
1066 | d_ptr->m_model->changeStop(d_ptr->m_model->at(d_ptr->m_changedStop->position()), d_ptr->m_dragColor);
|
---|
1067 | else if (d_ptr->m_clonedStop)
|
---|
1068 | d_ptr->m_model->addStop(d_ptr->m_clonedStop->position(), d_ptr->m_dragColor);
|
---|
1069 |
|
---|
1070 | d_ptr->clearDrag();
|
---|
1071 | update();
|
---|
1072 | }
|
---|
1073 |
|
---|
1074 | void QtGradientStopsWidgetPrivate::clearDrag()
|
---|
1075 | {
|
---|
1076 | removeClonedStop();
|
---|
1077 | restoreChangedStop();
|
---|
1078 | delete m_dragModel;
|
---|
1079 | m_dragModel = 0;
|
---|
1080 | }
|
---|
1081 |
|
---|
1082 | void QtGradientStopsWidgetPrivate::removeClonedStop()
|
---|
1083 | {
|
---|
1084 | if (!m_clonedStop)
|
---|
1085 | return;
|
---|
1086 | m_dragModel->removeStop(m_clonedStop);
|
---|
1087 | m_clonedStop = 0;
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | void QtGradientStopsWidgetPrivate::restoreChangedStop()
|
---|
1091 | {
|
---|
1092 | if (!m_changedStop)
|
---|
1093 | return;
|
---|
1094 | m_dragModel->changeStop(m_changedStop, m_model->at(m_changedStop->position())->color());
|
---|
1095 | m_changedStop = 0;
|
---|
1096 | m_dragStop = 0;
|
---|
1097 | }
|
---|
1098 |
|
---|
1099 | void QtGradientStopsWidgetPrivate::changeStop(qreal pos)
|
---|
1100 | {
|
---|
1101 | QtGradientStop *stop = m_dragModel->at(pos);
|
---|
1102 | if (!stop)
|
---|
1103 | return;
|
---|
1104 |
|
---|
1105 | m_dragModel->changeStop(stop, m_dragColor);
|
---|
1106 | m_changedStop = stop;
|
---|
1107 | m_dragStop = m_model->at(stop->position());
|
---|
1108 | }
|
---|
1109 |
|
---|
1110 | void QtGradientStopsWidgetPrivate::cloneStop(qreal pos)
|
---|
1111 | {
|
---|
1112 | if (m_clonedStop) {
|
---|
1113 | m_dragModel->moveStop(m_clonedStop, pos);
|
---|
1114 | return;
|
---|
1115 | }
|
---|
1116 | QtGradientStop *stop = m_dragModel->at(pos);
|
---|
1117 | if (stop)
|
---|
1118 | return;
|
---|
1119 |
|
---|
1120 | m_clonedStop = m_dragModel->addStop(pos, m_dragColor);
|
---|
1121 | }
|
---|
1122 |
|
---|
1123 | #endif
|
---|
1124 |
|
---|
1125 | void QtGradientStopsWidget::setZoom(double zoom)
|
---|
1126 | {
|
---|
1127 | double z = zoom;
|
---|
1128 | if (z < 1)
|
---|
1129 | z = 1;
|
---|
1130 | else if (z > 100)
|
---|
1131 | z = 100;
|
---|
1132 |
|
---|
1133 | if (d_ptr->m_zoom == z)
|
---|
1134 | return;
|
---|
1135 |
|
---|
1136 | d_ptr->m_zoom = z;
|
---|
1137 | int oldMax = horizontalScrollBar()->maximum();
|
---|
1138 | int oldVal = horizontalScrollBar()->value();
|
---|
1139 | horizontalScrollBar()->setRange(0, qRound(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1)));
|
---|
1140 | int newMax = horizontalScrollBar()->maximum();
|
---|
1141 | double newVal = (oldVal + (double)d_ptr->m_scaleFactor / 2) * (newMax + d_ptr->m_scaleFactor)
|
---|
1142 | / (oldMax + d_ptr->m_scaleFactor) - (double)d_ptr->m_scaleFactor / 2;
|
---|
1143 | horizontalScrollBar()->setValue(qRound(newVal));
|
---|
1144 | viewport()->update();
|
---|
1145 | }
|
---|
1146 |
|
---|
1147 | double QtGradientStopsWidget::zoom() const
|
---|
1148 | {
|
---|
1149 | return d_ptr->m_zoom;
|
---|
1150 | }
|
---|
1151 |
|
---|
1152 | QT_END_NAMESPACE
|
---|
1153 |
|
---|
1154 | #include "moc_qtgradientstopswidget.cpp"
|
---|