source: trunk/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp@ 890

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

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

File size: 12.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the 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 "qtgradientstopsmodel.h"
43#include <QtGui/QColor>
44
45QT_BEGIN_NAMESPACE
46
47class QtGradientStopPrivate
48{
49public:
50 qreal m_position;
51 QColor m_color;
52 QtGradientStopsModel *m_model;
53};
54
55qreal QtGradientStop::position() const
56{
57 return d_ptr->m_position;
58}
59
60QColor QtGradientStop::color() const
61{
62 return d_ptr->m_color;
63}
64
65QtGradientStopsModel *QtGradientStop::gradientModel() const
66{
67 return d_ptr->m_model;
68}
69
70void QtGradientStop::setColor(const QColor &color)
71{
72 d_ptr->m_color = color;
73}
74
75void QtGradientStop::setPosition(qreal position)
76{
77 d_ptr->m_position = position;
78}
79
80QtGradientStop::QtGradientStop(QtGradientStopsModel *model)
81 : d_ptr(new QtGradientStopPrivate())
82{
83 d_ptr->m_position = 0;
84 d_ptr->m_color = Qt::white;
85 d_ptr->m_model = model;
86}
87
88QtGradientStop::~QtGradientStop()
89{
90}
91
92class QtGradientStopsModelPrivate
93{
94 QtGradientStopsModel *q_ptr;
95 Q_DECLARE_PUBLIC(QtGradientStopsModel)
96public:
97 QMap<qreal, QtGradientStop *> m_posToStop;
98 QMap<QtGradientStop *, qreal> m_stopToPos;
99 QMap<QtGradientStop *, bool> m_selection;
100 QtGradientStop *m_current;
101};
102
103
104
105QtGradientStopsModel::QtGradientStopsModel(QObject *parent)
106 : QObject(parent), d_ptr(new QtGradientStopsModelPrivate)
107{
108 d_ptr->q_ptr = this;
109 d_ptr->m_current = 0;
110}
111
112QtGradientStopsModel::~QtGradientStopsModel()
113{
114 clear();
115}
116
117QtGradientStopsModel::PositionStopMap QtGradientStopsModel::stops() const
118{
119 return d_ptr->m_posToStop;
120}
121
122QtGradientStop *QtGradientStopsModel::at(qreal pos) const
123{
124 if (d_ptr->m_posToStop.contains(pos))
125 return d_ptr->m_posToStop[pos];
126 return 0;
127}
128
129QColor QtGradientStopsModel::color(qreal pos) const
130{
131 PositionStopMap gradStops = stops();
132 if (gradStops.isEmpty())
133 return QColor::fromRgbF(pos, pos, pos, 1.0);
134 if (gradStops.contains(pos))
135 return gradStops[pos]->color();
136
137 gradStops[pos] = 0;
138 PositionStopMap::ConstIterator itStop = gradStops.constFind(pos);
139 if (itStop == gradStops.constBegin()) {
140 ++itStop;
141 return itStop.value()->color();
142 }
143 if (itStop == --gradStops.constEnd()) {
144 --itStop;
145 return itStop.value()->color();
146 }
147 PositionStopMap::ConstIterator itPrev = itStop;
148 PositionStopMap::ConstIterator itNext = itStop;
149 --itPrev;
150 ++itNext;
151
152 double prevX = itPrev.key();
153 double nextX = itNext.key();
154
155 double coefX = (pos - prevX) / (nextX - prevX);
156 QColor prevCol = itPrev.value()->color();
157 QColor nextCol = itNext.value()->color();
158
159 QColor newColor;
160 newColor.setRgbF((nextCol.redF() - prevCol.redF() ) * coefX + prevCol.redF(),
161 (nextCol.greenF() - prevCol.greenF()) * coefX + prevCol.greenF(),
162 (nextCol.blueF() - prevCol.blueF() ) * coefX + prevCol.blueF(),
163 (nextCol.alphaF() - prevCol.alphaF()) * coefX + prevCol.alphaF());
164 return newColor;
165}
166
167QList<QtGradientStop *> QtGradientStopsModel::selectedStops() const
168{
169 return d_ptr->m_selection.keys();
170}
171
172QtGradientStop *QtGradientStopsModel::currentStop() const
173{
174 return d_ptr->m_current;
175}
176
177bool QtGradientStopsModel::isSelected(QtGradientStop *stop) const
178{
179 if (d_ptr->m_selection.contains(stop))
180 return true;
181 return false;
182}
183
184QtGradientStop *QtGradientStopsModel::addStop(qreal pos, const QColor &color)
185{
186 qreal newPos = pos;
187 if (pos < 0.0)
188 newPos = 0.0;
189 if (pos > 1.0)
190 newPos = 1.0;
191 if (d_ptr->m_posToStop.contains(newPos))
192 return 0;
193 QtGradientStop *stop = new QtGradientStop();
194 stop->setPosition(newPos);
195 stop->setColor(color);
196
197 d_ptr->m_posToStop[newPos] = stop;
198 d_ptr->m_stopToPos[stop] = newPos;
199
200 emit stopAdded(stop);
201
202 return stop;
203}
204
205void QtGradientStopsModel::removeStop(QtGradientStop *stop)
206{
207 if (!d_ptr->m_stopToPos.contains(stop))
208 return;
209 if (currentStop() == stop)
210 setCurrentStop(0);
211 selectStop(stop, false);
212
213 emit stopRemoved(stop);
214
215 qreal pos = d_ptr->m_stopToPos[stop];
216 d_ptr->m_stopToPos.remove(stop);
217 d_ptr->m_posToStop.remove(pos);
218 delete stop;
219}
220
221void QtGradientStopsModel::moveStop(QtGradientStop *stop, qreal newPos)
222{
223 if (!d_ptr->m_stopToPos.contains(stop))
224 return;
225 if (d_ptr->m_posToStop.contains(newPos))
226 return;
227
228 if (newPos > 1.0)
229 newPos = 1.0;
230 else if (newPos < 0.0)
231 newPos = 0.0;
232
233 emit stopMoved(stop, newPos);
234
235 const qreal oldPos = stop->position();
236 stop->setPosition(newPos);
237 d_ptr->m_stopToPos[stop] = newPos;
238 d_ptr->m_posToStop.remove(oldPos);
239 d_ptr->m_posToStop[newPos] = stop;
240}
241
242void QtGradientStopsModel::swapStops(QtGradientStop *stop1, QtGradientStop *stop2)
243{
244 if (stop1 == stop2)
245 return;
246 if (!d_ptr->m_stopToPos.contains(stop1))
247 return;
248 if (!d_ptr->m_stopToPos.contains(stop2))
249 return;
250
251 emit stopsSwapped(stop1, stop2);
252
253 const qreal pos1 = stop1->position();
254 const qreal pos2 = stop2->position();
255 stop1->setPosition(pos2);
256 stop2->setPosition(pos1);
257 d_ptr->m_stopToPos[stop1] = pos2;
258 d_ptr->m_stopToPos[stop2] = pos1;
259 d_ptr->m_posToStop[pos1] = stop2;
260 d_ptr->m_posToStop[pos2] = stop1;
261}
262
263void QtGradientStopsModel::changeStop(QtGradientStop *stop, const QColor &newColor)
264{
265 if (!d_ptr->m_stopToPos.contains(stop))
266 return;
267 if (stop->color() == newColor)
268 return;
269
270 emit stopChanged(stop, newColor);
271
272 stop->setColor(newColor);
273}
274
275void QtGradientStopsModel::selectStop(QtGradientStop *stop, bool select)
276{
277 if (!d_ptr->m_stopToPos.contains(stop))
278 return;
279 bool selected = d_ptr->m_selection.contains(stop);
280 if (select == selected)
281 return;
282
283 emit stopSelected(stop, select);
284
285 if (select)
286 d_ptr->m_selection[stop] = true;
287 else
288 d_ptr->m_selection.remove(stop);
289}
290
291void QtGradientStopsModel::setCurrentStop(QtGradientStop *stop)
292{
293 if (stop && !d_ptr->m_stopToPos.contains(stop))
294 return;
295 if (stop == currentStop())
296 return;
297
298 emit currentStopChanged(stop);
299
300 d_ptr->m_current = stop;
301}
302
303QtGradientStop *QtGradientStopsModel::firstSelected() const
304{
305 PositionStopMap stopList = stops();
306 PositionStopMap::ConstIterator itStop = stopList.constBegin();
307 while (itStop != stopList.constEnd()) {
308 QtGradientStop *stop = itStop.value();
309 if (isSelected(stop))
310 return stop;
311 ++itStop;
312 };
313 return 0;
314}
315
316QtGradientStop *QtGradientStopsModel::lastSelected() const
317{
318 PositionStopMap stopList = stops();
319 PositionStopMap::ConstIterator itStop = stopList.constEnd();
320 while (itStop != stopList.constBegin()) {
321 --itStop;
322
323 QtGradientStop *stop = itStop.value();
324 if (isSelected(stop))
325 return stop;
326 };
327 return 0;
328}
329
330QtGradientStopsModel *QtGradientStopsModel::clone() const
331{
332 QtGradientStopsModel *model = new QtGradientStopsModel();
333
334 QMap<qreal, QtGradientStop *> stopsToClone = stops();
335 QMapIterator<qreal, QtGradientStop *> it(stopsToClone);
336 while (it.hasNext()) {
337 it.next();
338 model->addStop(it.key(), it.value()->color());
339 }
340 // clone selection and current also
341 return model;
342}
343
344void QtGradientStopsModel::moveStops(double newPosition)
345{
346 QtGradientStop *current = currentStop();
347 if (!current)
348 return;
349
350 double newPos = newPosition;
351
352 if (newPos > 1)
353 newPos = 1;
354 else if (newPos < 0)
355 newPos = 0;
356
357 if (newPos == current->position())
358 return;
359
360 double offset = newPos - current->position();
361
362 QtGradientStop *first = firstSelected();
363 QtGradientStop *last = lastSelected();
364
365 if (first && last) { // multiselection
366 double maxOffset = 1.0 - last->position();
367 double minOffset = -first->position();
368
369 if (offset > maxOffset)
370 offset = maxOffset;
371 else if (offset < minOffset)
372 offset = minOffset;
373
374 }
375
376 if (offset == 0)
377 return;
378
379 bool forward = (offset > 0) ? false : true;
380
381 PositionStopMap stopList;
382
383 QList<QtGradientStop *> selected = selectedStops();
384 QListIterator<QtGradientStop *> it(selected);
385 while (it.hasNext()) {
386 QtGradientStop *stop = it.next();
387 stopList[stop->position()] = stop;
388 }
389 stopList[current->position()] = current;
390
391 PositionStopMap::ConstIterator itStop = forward ? stopList.constBegin() : stopList.constEnd();
392 while (itStop != (forward ? stopList.constEnd() : stopList.constBegin())) {
393 if (!forward)
394 --itStop;
395 QtGradientStop *stop = itStop.value();
396 double pos = stop->position() + offset;
397 if (pos > 1)
398 pos = 1;
399 if (pos < 0)
400 pos = 0;
401
402 if (current == stop)
403 pos = newPos;
404
405 QtGradientStop *oldStop = at(pos);
406 if (oldStop && !stopList.values().contains(oldStop))
407 removeStop(oldStop);
408 moveStop(stop, pos);
409
410 if (forward)
411 ++itStop;
412 }
413}
414
415void QtGradientStopsModel::clear()
416{
417 QList<QtGradientStop *> stopsList = stops().values();
418 QListIterator<QtGradientStop *> it(stopsList);
419 while (it.hasNext())
420 removeStop(it.next());
421}
422
423void QtGradientStopsModel::clearSelection()
424{
425 QList<QtGradientStop *> stopsList = selectedStops();
426 QListIterator<QtGradientStop *> it(stopsList);
427 while (it.hasNext())
428 selectStop(it.next(), false);
429}
430
431void QtGradientStopsModel::flipAll()
432{
433 QMap<qreal, QtGradientStop *> stopsMap = stops();
434 QMapIterator<qreal, QtGradientStop *> itStop(stopsMap);
435 itStop.toBack();
436
437 QMap<QtGradientStop *, bool> swappedList;
438
439 while (itStop.hasPrevious()) {
440 itStop.previous();
441
442 QtGradientStop *stop = itStop.value();
443 if (swappedList.contains(stop))
444 continue;
445 const double newPos = 1.0 - itStop.key();
446 if (stopsMap.contains(newPos)) {
447 QtGradientStop *swapped = stopsMap.value(newPos);
448 swappedList[swapped] = true;
449 swapStops(stop, swapped);
450 } else {
451 moveStop(stop, newPos);
452 }
453 }
454}
455
456void QtGradientStopsModel::selectAll()
457{
458 QList<QtGradientStop *> stopsList = stops().values();
459 QListIterator<QtGradientStop *> it(stopsList);
460 while (it.hasNext())
461 selectStop(it.next(), true);
462}
463
464void QtGradientStopsModel::deleteStops()
465{
466 QList<QtGradientStop *> selected = selectedStops();
467 QListIterator<QtGradientStop *> itSel(selected);
468 while (itSel.hasNext()) {
469 QtGradientStop *stop = itSel.next();
470 removeStop(stop);
471 }
472 QtGradientStop *current = currentStop();
473 if (current)
474 removeStop(current);
475}
476
477QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.