7#include <QtGui/qcolor.h>
9#include <QtCore/qhash.h>
23 return d_ptr->m_position;
28 return d_ptr->m_color;
33 return d_ptr->m_model;
38 d_ptr->m_color = color;
43 d_ptr->m_position = position;
47 : d_ptr(
new QtGradientStopPrivate())
49 d_ptr->m_model = model;
59 Q_DECLARE_PUBLIC(QtGradientStopsModel)
82 return d_ptr->m_posToStop;
87 if (d_ptr->m_posToStop.contains(pos))
88 return d_ptr->m_posToStop[pos];
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();
101 auto itStop = gradStops.constFind(pos);
102 if (itStop == gradStops.constBegin()) {
104 return itStop.value()->color();
106 if (itStop == --gradStops.constEnd()) {
108 return itStop.value()->color();
110 auto itPrev = itStop;
111 auto itNext = itStop;
115 double prevX = itPrev.key();
116 double nextX = itNext.key();
118 double coefX = (pos - prevX) / (nextX - prevX);
119 QColor prevCol = itPrev.value()->color();
120 QColor nextCol = itNext.value()->color();
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());
132 return d_ptr->m_selection.keys();
137 return d_ptr->m_current;
142 if (d_ptr->m_selection.contains(stop))
154 if (d_ptr->m_posToStop.contains(newPos))
157 stop->setPosition(newPos);
158 stop->setColor(color);
160 d_ptr->m_posToStop[newPos] = stop;
161 d_ptr->m_stopToPos[stop] = newPos;
163 emit stopAdded(stop);
170 if (!d_ptr->m_stopToPos.contains(stop))
176 emit stopRemoved(stop);
178 qreal pos = d_ptr->m_stopToPos[stop];
179 d_ptr->m_stopToPos.remove(stop);
180 d_ptr->m_posToStop.remove(pos);
186 if (!d_ptr->m_stopToPos.contains(stop))
188 if (d_ptr->m_posToStop.contains(newPos))
193 else if (newPos < 0.0)
196 emit stopMoved(stop, newPos);
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;
209 if (!d_ptr->m_stopToPos.contains(stop1))
211 if (!d_ptr->m_stopToPos.contains(stop2))
214 emit stopsSwapped(stop1, stop2);
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;
228 if (!d_ptr->m_stopToPos.contains(stop))
230 if (stop->color() == newColor)
233 emit stopChanged(stop, newColor);
235 stop->setColor(newColor);
240 if (!d_ptr->m_stopToPos.contains(stop))
242 bool selected = d_ptr->m_selection.contains(stop);
243 if (select == selected)
246 emit stopSelected(stop, select);
249 d_ptr->m_selection[stop] =
true;
251 d_ptr->m_selection.remove(stop);
256 if (stop && !d_ptr->m_stopToPos.contains(stop))
261 emit currentStopChanged(stop);
263 d_ptr->m_current = stop;
268 PositionStopMap stopList = stops();
269 auto itStop = stopList.cbegin();
270 while (itStop != stopList.constEnd()) {
281 PositionStopMap stopList = stops();
282 auto itStop = stopList.cend();
283 while (itStop != stopList.constBegin()) {
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());
310 double newPos = newPosition;
317 if (newPos == current->position())
320 double offset = newPos - current->position();
326 double maxOffset = 1.0 - last->position();
327 double minOffset = -first->position();
329 if (offset > maxOffset)
331 else if (offset < minOffset)
339 bool forward = (offset > 0) ?
false :
true;
341 PositionStopMap stopList;
343 const auto selected = selectedStops();
344 for (QtGradientStop *stop : selected)
345 stopList[stop->position()] = stop;
346 stopList[current->position()] = current;
348 auto itStop = forward ? stopList.cbegin() : stopList.cend();
349 while (itStop != (forward ? stopList.constEnd() : stopList.constBegin())) {
353 double pos = stop->position() + offset;
363 if (oldStop && !stopList.values().contains(oldStop))
374 const auto stopsList = stops().values();
375 for (QtGradientStop *stop : stopsList)
381 const auto stopsList = selectedStops();
382 for (QtGradientStop *stop : stopsList)
383 selectStop(stop,
false);
388 QMap<qreal, QtGradientStop *> stopsMap = stops();
389 QHash<QtGradientStop *,
bool> swappedList;
390 for (
auto itStop = stopsMap.keyValueEnd(), begin = stopsMap.keyValueBegin(); itStop != begin;) {
393 if (swappedList.contains(stop))
395 const double newPos = 1.0 - (*itStop).first;
396 if (stopsMap.contains(newPos)) {
398 swappedList[swapped] =
true;
401 moveStop(stop, newPos);
408 const auto stopsMap = stops();
409 for (
auto it = stopsMap.cbegin(), end = stopsMap.cend(); it != end; ++it)
415 const auto selected = selectedStops();
416 for (QtGradientStop *stop : selected)
QtGradientStopsModel * m_model
QtGradientStopsModel * gradientModel() const
QHash< QtGradientStop *, bool > m_selection
QtGradientStop * m_current
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)
~QtGradientStopsModel() override
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.