Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtgradientstopsmodel.cpp
Go to the documentation of this file.
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
5
6#include <QtGui/QColor>
7#include <QtCore/QHash>
8
10
12{
13public:
15 QColor m_color = Qt::white;
17};
18
20{
21 return d_ptr->m_position;
22}
23
24QColor QtGradientStop::color() const
25{
26 return d_ptr->m_color;
27}
28
30{
31 return d_ptr->m_model;
32}
33
34void QtGradientStop::setColor(QColor color)
35{
36 d_ptr->m_color = color;
37}
38
39void QtGradientStop::setPosition(qreal position)
40{
41 d_ptr->m_position = position;
42}
43
44QtGradientStop::QtGradientStop(QtGradientStopsModel *model)
45 : d_ptr(new QtGradientStopPrivate())
46{
47 d_ptr->m_model = model;
48}
49
50QtGradientStop::~QtGradientStop()
51{
52}
53
55{
56 QtGradientStopsModel *q_ptr = nullptr;
57 Q_DECLARE_PUBLIC(QtGradientStopsModel)
58public:
63};
64
65
66
69{
70 d_ptr->q_ptr = this;
71}
72
77
79{
80 return d_ptr->m_posToStop;
81}
82
84{
85 if (d_ptr->m_posToStop.contains(pos))
86 return d_ptr->m_posToStop[pos];
87 return 0;
88}
89
90QColor QtGradientStopsModel::color(qreal pos) const
91{
92 PositionStopMap gradStops = stops();
93 if (gradStops.isEmpty())
94 return QColor::fromRgbF(pos, pos, pos, 1.0);
95 if (gradStops.contains(pos))
96 return gradStops[pos]->color();
97
98 gradStops[pos] = 0;
99 auto itStop = gradStops.constFind(pos);
100 if (itStop == gradStops.constBegin()) {
101 ++itStop;
102 return itStop.value()->color();
103 }
104 if (itStop == --gradStops.constEnd()) {
105 --itStop;
106 return itStop.value()->color();
107 }
108 auto itPrev = itStop;
109 auto itNext = itStop;
110 --itPrev;
111 ++itNext;
112
113 double prevX = itPrev.key();
114 double nextX = itNext.key();
115
116 double coefX = (pos - prevX) / (nextX - prevX);
117 QColor prevCol = itPrev.value()->color();
118 QColor nextCol = itNext.value()->color();
119
120 QColor newColor;
121 newColor.setRgbF((nextCol.redF() - prevCol.redF() ) * coefX + prevCol.redF(),
122 (nextCol.greenF() - prevCol.greenF()) * coefX + prevCol.greenF(),
123 (nextCol.blueF() - prevCol.blueF() ) * coefX + prevCol.blueF(),
124 (nextCol.alphaF() - prevCol.alphaF()) * coefX + prevCol.alphaF());
125 return newColor;
126}
127
129{
130 return d_ptr->m_selection.keys();
131}
132
134{
135 return d_ptr->m_current;
136}
137
139{
140 if (d_ptr->m_selection.contains(stop))
141 return true;
142 return false;
143}
144
146{
147 qreal newPos = pos;
148 if (pos < 0.0)
149 newPos = 0.0;
150 if (pos > 1.0)
151 newPos = 1.0;
152 if (d_ptr->m_posToStop.contains(newPos))
153 return 0;
154 QtGradientStop *stop = new QtGradientStop();
155 stop->setPosition(newPos);
156 stop->setColor(color);
157
158 d_ptr->m_posToStop[newPos] = stop;
159 d_ptr->m_stopToPos[stop] = newPos;
160
161 emit stopAdded(stop);
162
163 return stop;
164}
165
167{
168 if (!d_ptr->m_stopToPos.contains(stop))
169 return;
170 if (currentStop() == stop)
172 selectStop(stop, false);
173
174 emit stopRemoved(stop);
175
176 qreal pos = d_ptr->m_stopToPos[stop];
177 d_ptr->m_stopToPos.remove(stop);
178 d_ptr->m_posToStop.remove(pos);
179 delete stop;
180}
181
183{
184 if (!d_ptr->m_stopToPos.contains(stop))
185 return;
186 if (d_ptr->m_posToStop.contains(newPos))
187 return;
188
189 if (newPos > 1.0)
190 newPos = 1.0;
191 else if (newPos < 0.0)
192 newPos = 0.0;
193
194 emit stopMoved(stop, newPos);
195
196 const qreal oldPos = stop->position();
197 stop->setPosition(newPos);
198 d_ptr->m_stopToPos[stop] = newPos;
199 d_ptr->m_posToStop.remove(oldPos);
200 d_ptr->m_posToStop[newPos] = stop;
201}
202
204{
205 if (stop1 == stop2)
206 return;
207 if (!d_ptr->m_stopToPos.contains(stop1))
208 return;
209 if (!d_ptr->m_stopToPos.contains(stop2))
210 return;
211
212 emit stopsSwapped(stop1, stop2);
213
214 const qreal pos1 = stop1->position();
215 const qreal pos2 = stop2->position();
216 stop1->setPosition(pos2);
217 stop2->setPosition(pos1);
218 d_ptr->m_stopToPos[stop1] = pos2;
219 d_ptr->m_stopToPos[stop2] = pos1;
220 d_ptr->m_posToStop[pos1] = stop2;
221 d_ptr->m_posToStop[pos2] = stop1;
222}
223
224void QtGradientStopsModel::changeStop(QtGradientStop *stop, QColor newColor)
225{
226 if (!d_ptr->m_stopToPos.contains(stop))
227 return;
228 if (stop->color() == newColor)
229 return;
230
231 emit stopChanged(stop, newColor);
232
233 stop->setColor(newColor);
234}
235
237{
238 if (!d_ptr->m_stopToPos.contains(stop))
239 return;
240 bool selected = d_ptr->m_selection.contains(stop);
241 if (select == selected)
242 return;
243
244 emit stopSelected(stop, select);
245
246 if (select)
247 d_ptr->m_selection[stop] = true;
248 else
249 d_ptr->m_selection.remove(stop);
250}
251
253{
254 if (stop && !d_ptr->m_stopToPos.contains(stop))
255 return;
256 if (stop == currentStop())
257 return;
258
259 emit currentStopChanged(stop);
260
261 d_ptr->m_current = stop;
262}
263
265{
266 PositionStopMap stopList = stops();
267 auto itStop = stopList.cbegin();
268 while (itStop != stopList.constEnd()) {
269 QtGradientStop *stop = itStop.value();
270 if (isSelected(stop))
271 return stop;
272 ++itStop;
273 };
274 return 0;
275}
276
278{
279 PositionStopMap stopList = stops();
280 auto itStop = stopList.cend();
281 while (itStop != stopList.constBegin()) {
282 --itStop;
283
284 QtGradientStop *stop = itStop.value();
285 if (isSelected(stop))
286 return stop;
287 };
288 return 0;
289}
290
292{
294
295 QMap<qreal, QtGradientStop *> stopsToClone = stops();
296 for (auto it = stopsToClone.cbegin(), end = stopsToClone.cend(); it != end; ++it)
297 model->addStop(it.key(), it.value()->color());
298 // clone selection and current also
299 return model;
300}
301
302void QtGradientStopsModel::moveStops(double newPosition)
303{
304 QtGradientStop *current = currentStop();
305 if (!current)
306 return;
307
308 double newPos = newPosition;
309
310 if (newPos > 1)
311 newPos = 1;
312 else if (newPos < 0)
313 newPos = 0;
314
315 if (newPos == current->position())
316 return;
317
318 double offset = newPos - current->position();
319
322
323 if (first && last) { // multiselection
324 double maxOffset = 1.0 - last->position();
325 double minOffset = -first->position();
326
327 if (offset > maxOffset)
328 offset = maxOffset;
329 else if (offset < minOffset)
330 offset = minOffset;
331
332 }
333
334 if (offset == 0)
335 return;
336
337 bool forward = (offset > 0) ? false : true;
338
339 PositionStopMap stopList;
340
341 const auto selected = selectedStops();
342 for (QtGradientStop *stop : selected)
343 stopList[stop->position()] = stop;
344 stopList[current->position()] = current;
345
346 auto itStop = forward ? stopList.cbegin() : stopList.cend();
347 while (itStop != (forward ? stopList.constEnd() : stopList.constBegin())) {
348 if (!forward)
349 --itStop;
350 QtGradientStop *stop = itStop.value();
351 double pos = stop->position() + offset;
352 if (pos > 1)
353 pos = 1;
354 if (pos < 0)
355 pos = 0;
356
357 if (current == stop)
358 pos = newPos;
359
360 QtGradientStop *oldStop = at(pos);
361 if (oldStop && !stopList.values().contains(oldStop))
362 removeStop(oldStop);
363 moveStop(stop, pos);
364
365 if (forward)
366 ++itStop;
367 }
368}
369
371{
372 const auto stopsList = stops().values();
373 for (QtGradientStop *stop : stopsList)
374 removeStop(stop);
375}
376
378{
379 const auto stopsList = selectedStops();
380 for (QtGradientStop *stop : stopsList)
381 selectStop(stop, false);
382}
383
385{
386 QMap<qreal, QtGradientStop *> stopsMap = stops();
387 QHash<QtGradientStop *, bool> swappedList;
388 for (auto itStop = stopsMap.keyValueEnd(), begin = stopsMap.keyValueBegin(); itStop != begin;) {
389 --itStop;
390 QtGradientStop *stop = (*itStop).second;
391 if (swappedList.contains(stop))
392 continue;
393 const double newPos = 1.0 - (*itStop).first;
394 if (stopsMap.contains(newPos)) {
395 QtGradientStop *swapped = stopsMap.value(newPos);
396 swappedList[swapped] = true;
397 swapStops(stop, swapped);
398 } else {
399 moveStop(stop, newPos);
400 }
401 }
402}
403
405{
406 const auto stopsMap = stops();
407 for (auto it = stopsMap.cbegin(), end = stopsMap.cend(); it != end; ++it)
408 selectStop(it.value(), true);
409}
410
412{
413 const auto selected = selectedStops();
414 for (QtGradientStop *stop : selected)
415 removeStop(stop);
416 QtGradientStop *current = currentStop();
417 if (current)
418 removeStop(current);
419}
420
421QT_END_NAMESPACE
QtGradientStopsModel * m_model
QtGradientStopsModel * gradientModel() const
QHash< QtGradientStop *, bool > m_selection
QHash< QtGradientStop *, qreal > m_stopToPos
void selectStop(QtGradientStop *stop, bool select)
QList< QtGradientStop * > selectedStops() const
QtGradientStopsModel * clone() const
void removeStop(QtGradientStop *stop)
void changeStop(QtGradientStop *stop, QColor newColor)
QtGradientStop * at(qreal pos) const
bool isSelected(QtGradientStop *stop) const
QtGradientStop * currentStop() const
QtGradientStop * addStop(qreal pos, QColor color)
QtGradientStop * firstSelected() const
void moveStops(double newPosition)
QColor color(qreal pos) const
QtGradientStopsModel(QObject *parent=0)
void swapStops(QtGradientStop *stop1, QtGradientStop *stop2)
PositionStopMap stops() const
QtGradientStop * lastSelected() const
void moveStop(QtGradientStop *stop, qreal newPos)
void setCurrentStop(QtGradientStop *stop)
Combined button and popup list for selecting options.