/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtgradientstopsmodel.h" #include QT_BEGIN_NAMESPACE class QtGradientStopPrivate { public: qreal m_position; QColor m_color; QtGradientStopsModel *m_model; }; qreal QtGradientStop::position() const { return d_ptr->m_position; } QColor QtGradientStop::color() const { return d_ptr->m_color; } QtGradientStopsModel *QtGradientStop::gradientModel() const { return d_ptr->m_model; } void QtGradientStop::setColor(const QColor &color) { d_ptr->m_color = color; } void QtGradientStop::setPosition(qreal position) { d_ptr->m_position = position; } QtGradientStop::QtGradientStop(QtGradientStopsModel *model) : d_ptr(new QtGradientStopPrivate()) { d_ptr->m_position = 0; d_ptr->m_color = Qt::white; d_ptr->m_model = model; } QtGradientStop::~QtGradientStop() { } class QtGradientStopsModelPrivate { QtGradientStopsModel *q_ptr; Q_DECLARE_PUBLIC(QtGradientStopsModel) public: QMap m_posToStop; QMap m_stopToPos; QMap m_selection; QtGradientStop *m_current; }; QtGradientStopsModel::QtGradientStopsModel(QObject *parent) : QObject(parent), d_ptr(new QtGradientStopsModelPrivate) { d_ptr->q_ptr = this; d_ptr->m_current = 0; } QtGradientStopsModel::~QtGradientStopsModel() { clear(); } QtGradientStopsModel::PositionStopMap QtGradientStopsModel::stops() const { return d_ptr->m_posToStop; } QtGradientStop *QtGradientStopsModel::at(qreal pos) const { if (d_ptr->m_posToStop.contains(pos)) return d_ptr->m_posToStop[pos]; return 0; } QColor QtGradientStopsModel::color(qreal pos) const { PositionStopMap gradStops = stops(); if (gradStops.isEmpty()) return QColor::fromRgbF(pos, pos, pos, 1.0); if (gradStops.contains(pos)) return gradStops[pos]->color(); gradStops[pos] = 0; PositionStopMap::ConstIterator itStop = gradStops.constFind(pos); if (itStop == gradStops.constBegin()) { ++itStop; return itStop.value()->color(); } if (itStop == --gradStops.constEnd()) { --itStop; return itStop.value()->color(); } PositionStopMap::ConstIterator itPrev = itStop; PositionStopMap::ConstIterator itNext = itStop; --itPrev; ++itNext; double prevX = itPrev.key(); double nextX = itNext.key(); double coefX = (pos - prevX) / (nextX - prevX); QColor prevCol = itPrev.value()->color(); QColor nextCol = itNext.value()->color(); QColor newColor; newColor.setRgbF((nextCol.redF() - prevCol.redF() ) * coefX + prevCol.redF(), (nextCol.greenF() - prevCol.greenF()) * coefX + prevCol.greenF(), (nextCol.blueF() - prevCol.blueF() ) * coefX + prevCol.blueF(), (nextCol.alphaF() - prevCol.alphaF()) * coefX + prevCol.alphaF()); return newColor; } QList QtGradientStopsModel::selectedStops() const { return d_ptr->m_selection.keys(); } QtGradientStop *QtGradientStopsModel::currentStop() const { return d_ptr->m_current; } bool QtGradientStopsModel::isSelected(QtGradientStop *stop) const { if (d_ptr->m_selection.contains(stop)) return true; return false; } QtGradientStop *QtGradientStopsModel::addStop(qreal pos, const QColor &color) { qreal newPos = pos; if (pos < 0.0) newPos = 0.0; if (pos > 1.0) newPos = 1.0; if (d_ptr->m_posToStop.contains(newPos)) return 0; QtGradientStop *stop = new QtGradientStop(); stop->setPosition(newPos); stop->setColor(color); d_ptr->m_posToStop[newPos] = stop; d_ptr->m_stopToPos[stop] = newPos; emit stopAdded(stop); return stop; } void QtGradientStopsModel::removeStop(QtGradientStop *stop) { if (!d_ptr->m_stopToPos.contains(stop)) return; if (currentStop() == stop) setCurrentStop(0); selectStop(stop, false); emit stopRemoved(stop); qreal pos = d_ptr->m_stopToPos[stop]; d_ptr->m_stopToPos.remove(stop); d_ptr->m_posToStop.remove(pos); delete stop; } void QtGradientStopsModel::moveStop(QtGradientStop *stop, qreal newPos) { if (!d_ptr->m_stopToPos.contains(stop)) return; if (d_ptr->m_posToStop.contains(newPos)) return; if (newPos > 1.0) newPos = 1.0; else if (newPos < 0.0) newPos = 0.0; emit stopMoved(stop, newPos); const qreal oldPos = stop->position(); stop->setPosition(newPos); d_ptr->m_stopToPos[stop] = newPos; d_ptr->m_posToStop.remove(oldPos); d_ptr->m_posToStop[newPos] = stop; } void QtGradientStopsModel::swapStops(QtGradientStop *stop1, QtGradientStop *stop2) { if (stop1 == stop2) return; if (!d_ptr->m_stopToPos.contains(stop1)) return; if (!d_ptr->m_stopToPos.contains(stop2)) return; emit stopsSwapped(stop1, stop2); const qreal pos1 = stop1->position(); const qreal pos2 = stop2->position(); stop1->setPosition(pos2); stop2->setPosition(pos1); d_ptr->m_stopToPos[stop1] = pos2; d_ptr->m_stopToPos[stop2] = pos1; d_ptr->m_posToStop[pos1] = stop2; d_ptr->m_posToStop[pos2] = stop1; } void QtGradientStopsModel::changeStop(QtGradientStop *stop, const QColor &newColor) { if (!d_ptr->m_stopToPos.contains(stop)) return; if (stop->color() == newColor) return; emit stopChanged(stop, newColor); stop->setColor(newColor); } void QtGradientStopsModel::selectStop(QtGradientStop *stop, bool select) { if (!d_ptr->m_stopToPos.contains(stop)) return; bool selected = d_ptr->m_selection.contains(stop); if (select == selected) return; emit stopSelected(stop, select); if (select) d_ptr->m_selection[stop] = true; else d_ptr->m_selection.remove(stop); } void QtGradientStopsModel::setCurrentStop(QtGradientStop *stop) { if (stop && !d_ptr->m_stopToPos.contains(stop)) return; if (stop == currentStop()) return; emit currentStopChanged(stop); d_ptr->m_current = stop; } QtGradientStop *QtGradientStopsModel::firstSelected() const { PositionStopMap stopList = stops(); PositionStopMap::ConstIterator itStop = stopList.constBegin(); while (itStop != stopList.constEnd()) { QtGradientStop *stop = itStop.value(); if (isSelected(stop)) return stop; ++itStop; }; return 0; } QtGradientStop *QtGradientStopsModel::lastSelected() const { PositionStopMap stopList = stops(); PositionStopMap::ConstIterator itStop = stopList.constEnd(); while (itStop != stopList.constBegin()) { --itStop; QtGradientStop *stop = itStop.value(); if (isSelected(stop)) return stop; }; return 0; } QtGradientStopsModel *QtGradientStopsModel::clone() const { QtGradientStopsModel *model = new QtGradientStopsModel(); QMap stopsToClone = stops(); QMapIterator it(stopsToClone); while (it.hasNext()) { it.next(); model->addStop(it.key(), it.value()->color()); } // clone selection and current also return model; } void QtGradientStopsModel::moveStops(double newPosition) { QtGradientStop *current = currentStop(); if (!current) return; double newPos = newPosition; if (newPos > 1) newPos = 1; else if (newPos < 0) newPos = 0; if (newPos == current->position()) return; double offset = newPos - current->position(); QtGradientStop *first = firstSelected(); QtGradientStop *last = lastSelected(); if (first && last) { // multiselection double maxOffset = 1.0 - last->position(); double minOffset = -first->position(); if (offset > maxOffset) offset = maxOffset; else if (offset < minOffset) offset = minOffset; } if (offset == 0) return; bool forward = (offset > 0) ? false : true; PositionStopMap stopList; QList selected = selectedStops(); QListIterator it(selected); while (it.hasNext()) { QtGradientStop *stop = it.next(); stopList[stop->position()] = stop; } stopList[current->position()] = current; PositionStopMap::ConstIterator itStop = forward ? stopList.constBegin() : stopList.constEnd(); while (itStop != (forward ? stopList.constEnd() : stopList.constBegin())) { if (!forward) --itStop; QtGradientStop *stop = itStop.value(); double pos = stop->position() + offset; if (pos > 1) pos = 1; if (pos < 0) pos = 0; if (current == stop) pos = newPos; QtGradientStop *oldStop = at(pos); if (oldStop && !stopList.values().contains(oldStop)) removeStop(oldStop); moveStop(stop, pos); if (forward) ++itStop; } } void QtGradientStopsModel::clear() { QList stopsList = stops().values(); QListIterator it(stopsList); while (it.hasNext()) removeStop(it.next()); } void QtGradientStopsModel::clearSelection() { QList stopsList = selectedStops(); QListIterator it(stopsList); while (it.hasNext()) selectStop(it.next(), false); } void QtGradientStopsModel::flipAll() { QMap stopsMap = stops(); QMapIterator itStop(stopsMap); itStop.toBack(); QMap swappedList; while (itStop.hasPrevious()) { itStop.previous(); QtGradientStop *stop = itStop.value(); if (swappedList.contains(stop)) continue; const double newPos = 1.0 - itStop.key(); if (stopsMap.contains(newPos)) { QtGradientStop *swapped = stopsMap.value(newPos); swappedList[swapped] = true; swapStops(stop, swapped); } else { moveStop(stop, newPos); } } } void QtGradientStopsModel::selectAll() { QList stopsList = stops().values(); QListIterator it(stopsList); while (it.hasNext()) selectStop(it.next(), true); } void QtGradientStopsModel::deleteStops() { QList selected = selectedStops(); QListIterator itSel(selected); while (itSel.hasNext()) { QtGradientStop *stop = itSel.next(); removeStop(stop); } QtGradientStop *current = currentStop(); if (current) removeStop(current); } QT_END_NAMESPACE