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