diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /tools/shared/qtgradienteditor | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'tools/shared/qtgradienteditor')
45 files changed, 9837 insertions, 0 deletions
diff --git a/tools/shared/qtgradienteditor/images/down.png b/tools/shared/qtgradienteditor/images/down.png Binary files differnew file mode 100644 index 0000000..29d1d44 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/down.png diff --git a/tools/shared/qtgradienteditor/images/edit.png b/tools/shared/qtgradienteditor/images/edit.png Binary files differnew file mode 100644 index 0000000..4231bd9 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/edit.png diff --git a/tools/shared/qtgradienteditor/images/editdelete.png b/tools/shared/qtgradienteditor/images/editdelete.png Binary files differnew file mode 100644 index 0000000..df2a147 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/editdelete.png diff --git a/tools/shared/qtgradienteditor/images/minus.png b/tools/shared/qtgradienteditor/images/minus.png Binary files differnew file mode 100644 index 0000000..d6f233d --- /dev/null +++ b/tools/shared/qtgradienteditor/images/minus.png diff --git a/tools/shared/qtgradienteditor/images/plus.png b/tools/shared/qtgradienteditor/images/plus.png Binary files differnew file mode 100644 index 0000000..40df113 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/plus.png diff --git a/tools/shared/qtgradienteditor/images/spreadpad.png b/tools/shared/qtgradienteditor/images/spreadpad.png Binary files differnew file mode 100644 index 0000000..104c0a2 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/spreadpad.png diff --git a/tools/shared/qtgradienteditor/images/spreadreflect.png b/tools/shared/qtgradienteditor/images/spreadreflect.png Binary files differnew file mode 100644 index 0000000..17b82b7 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/spreadreflect.png diff --git a/tools/shared/qtgradienteditor/images/spreadrepeat.png b/tools/shared/qtgradienteditor/images/spreadrepeat.png Binary files differnew file mode 100644 index 0000000..7aea898 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/spreadrepeat.png diff --git a/tools/shared/qtgradienteditor/images/typeconical.png b/tools/shared/qtgradienteditor/images/typeconical.png Binary files differnew file mode 100644 index 0000000..5479811 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/typeconical.png diff --git a/tools/shared/qtgradienteditor/images/typelinear.png b/tools/shared/qtgradienteditor/images/typelinear.png Binary files differnew file mode 100644 index 0000000..dbd8a1f --- /dev/null +++ b/tools/shared/qtgradienteditor/images/typelinear.png diff --git a/tools/shared/qtgradienteditor/images/typeradial.png b/tools/shared/qtgradienteditor/images/typeradial.png Binary files differnew file mode 100644 index 0000000..dc5888d --- /dev/null +++ b/tools/shared/qtgradienteditor/images/typeradial.png diff --git a/tools/shared/qtgradienteditor/images/up.png b/tools/shared/qtgradienteditor/images/up.png Binary files differnew file mode 100644 index 0000000..e437312 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/up.png diff --git a/tools/shared/qtgradienteditor/images/zoomin.png b/tools/shared/qtgradienteditor/images/zoomin.png Binary files differnew file mode 100644 index 0000000..2e586fc --- /dev/null +++ b/tools/shared/qtgradienteditor/images/zoomin.png diff --git a/tools/shared/qtgradienteditor/images/zoomout.png b/tools/shared/qtgradienteditor/images/zoomout.png Binary files differnew file mode 100644 index 0000000..a736d39 --- /dev/null +++ b/tools/shared/qtgradienteditor/images/zoomout.png diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.cpp b/tools/shared/qtgradienteditor/qtcolorbutton.cpp new file mode 100644 index 0000000..6926f60 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtcolorbutton.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtcolorbutton.h" +#include <QtGui/QColorDialog> +#include <QtGui/QPainter> +#include <QtCore/QMimeData> +#include <QtGui/QDragEnterEvent> +#include <QtGui/QApplication> + +QT_BEGIN_NAMESPACE + +class QtColorButtonPrivate +{ + QtColorButton *q_ptr; + Q_DECLARE_PUBLIC(QtColorButton) +public: + QColor m_color; +#ifndef QT_NO_DRAGANDDROP + QColor m_dragColor; + QPoint m_dragStart; + bool m_dragging; +#endif + bool m_backgroundCheckered; + + void slotEditColor(); + QColor shownColor() const; + QPixmap generatePixmap() const; +}; + +void QtColorButtonPrivate::slotEditColor() +{ + bool ok; + const QRgb rgba = QColorDialog::getRgba(m_color.rgba(), &ok, q_ptr); + if (!ok) + return; + const QColor c = QColor::fromRgba(rgba); + if (c == q_ptr->color()) + return; + q_ptr->setColor(c); + emit q_ptr->colorChanged(m_color); +} + +QColor QtColorButtonPrivate::shownColor() const +{ +#ifndef QT_NO_DRAGANDDROP + if (m_dragging) + return m_dragColor; +#endif + return m_color; +} + +QPixmap QtColorButtonPrivate::generatePixmap() const +{ + QPixmap pix(24, 24); + + int pixSize = 20; + QBrush br(shownColor()); + + QPixmap pm(2 * pixSize, 2 * pixSize); + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray); + pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray); + pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray); + pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, shownColor()); + br = QBrush(pm); + + QPainter p(&pix); + int corr = 1; + QRect r = pix.rect().adjusted(corr, corr, -corr, -corr); + p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr); + p.fillRect(r, br); + + p.fillRect(r.width() / 4 + corr, r.height() / 4 + corr, + r.width() / 2, r.height() / 2, + QColor(shownColor().rgb())); + p.drawRect(pix.rect().adjusted(0, 0, -1, -1)); + + return pix; +} + +/////////////// + +QtColorButton::QtColorButton(QWidget *parent) + : QToolButton(parent) +{ + d_ptr = new QtColorButtonPrivate; + d_ptr->q_ptr = this; + d_ptr->m_dragging = false; + d_ptr->m_backgroundCheckered = true; + + setAcceptDrops(true); + + connect(this, SIGNAL(clicked()), this, SLOT(slotEditColor())); + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); +} + +QtColorButton::~QtColorButton() +{ + delete d_ptr; +} + +void QtColorButton::setColor(const QColor &color) +{ + if (d_ptr->m_color == color) + return; + d_ptr->m_color = color; + update(); +} + +QColor QtColorButton::color() const +{ + return d_ptr->m_color; +} + +void QtColorButton::setBackgroundCheckered(bool checkered) +{ + if (d_ptr->m_backgroundCheckered == checkered) + return; + d_ptr->m_backgroundCheckered = checkered; + update(); +} + +bool QtColorButton::isBackgroundCheckered() const +{ + return d_ptr->m_backgroundCheckered; +} + +void QtColorButton::paintEvent(QPaintEvent *event) +{ + QToolButton::paintEvent(event); + if (!isEnabled()) + return; + + const int pixSize = 10; + QBrush br(d_ptr->shownColor()); + if (d_ptr->m_backgroundCheckered) { + QPixmap pm(2 * pixSize, 2 * pixSize); + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, Qt::white); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white); + pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black); + pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black); + pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, d_ptr->shownColor()); + br = QBrush(pm); + } + + QPainter p(this); + const int corr = 4; + QRect r = rect().adjusted(corr, corr, -corr, -corr); + p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr); + p.fillRect(r, br); + + //const int adjX = qRound(r.width() / 4.0); + //const int adjY = qRound(r.height() / 4.0); + //p.fillRect(r.adjusted(adjX, adjY, -adjX, -adjY), + // QColor(d_ptr->shownColor().rgb())); + /* + p.fillRect(r.adjusted(0, r.height() * 3 / 4, 0, 0), + QColor(d_ptr->shownColor().rgb())); + p.fillRect(r.adjusted(0, 0, 0, -r.height() * 3 / 4), + QColor(d_ptr->shownColor().rgb())); + */ + /* + const QColor frameColor0(0, 0, 0, qRound(0.2 * (0xFF - d_ptr->shownColor().alpha()))); + p.setPen(frameColor0); + p.drawRect(r.adjusted(adjX, adjY, -adjX - 1, -adjY - 1)); + */ + + const QColor frameColor1(0, 0, 0, 26); + p.setPen(frameColor1); + p.drawRect(r.adjusted(1, 1, -2, -2)); + const QColor frameColor2(0, 0, 0, 51); + p.setPen(frameColor2); + p.drawRect(r.adjusted(0, 0, -1, -1)); +} + +void QtColorButton::mousePressEvent(QMouseEvent *event) +{ +#ifndef QT_NO_DRAGANDDROP + if (event->button() == Qt::LeftButton) + d_ptr->m_dragStart = event->pos(); +#endif + QToolButton::mousePressEvent(event); +} + +void QtColorButton::mouseMoveEvent(QMouseEvent *event) +{ +#ifndef QT_NO_DRAGANDDROP + if (event->buttons() & Qt::LeftButton && + (d_ptr->m_dragStart - event->pos()).manhattanLength() > QApplication::startDragDistance()) { + QMimeData *mime = new QMimeData; + mime->setColorData(color()); + QDrag *drg = new QDrag(this); + drg->setMimeData(mime); + drg->setPixmap(d_ptr->generatePixmap()); + setDown(false); + event->accept(); + drg->start(); + return; + } +#endif + QToolButton::mouseMoveEvent(event); +} + +#ifndef QT_NO_DRAGANDDROP +void QtColorButton::dragEnterEvent(QDragEnterEvent *event) +{ + const QMimeData *mime = event->mimeData(); + if (!mime->hasColor()) + return; + + event->accept(); + d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData()); + d_ptr->m_dragging = true; + update(); +} + +void QtColorButton::dragLeaveEvent(QDragLeaveEvent *event) +{ + event->accept(); + d_ptr->m_dragging = false; + update(); +} + +void QtColorButton::dropEvent(QDropEvent *event) +{ + event->accept(); + d_ptr->m_dragging = false; + if (d_ptr->m_dragColor == color()) + return; + setColor(d_ptr->m_dragColor); + emit colorChanged(color()); +} +#endif + +QT_END_NAMESPACE + +#include "moc_qtcolorbutton.cpp" diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.h b/tools/shared/qtgradienteditor/qtcolorbutton.h new file mode 100644 index 0000000..fb91452 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtcolorbutton.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCOLORBUTTON_H +#define QTCOLORBUTTON_H + +#include <QtGui/QToolButton> + +QT_BEGIN_NAMESPACE + +class QtColorButton : public QToolButton +{ + Q_OBJECT + Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered) +public: + QtColorButton(QWidget *parent = 0); + ~QtColorButton(); + + bool isBackgroundCheckered() const; + void setBackgroundCheckered(bool checkered); + + QColor color() const; + +public slots: + + void setColor(const QColor &color); + +signals: + void colorChanged(const QColor &color); +protected: + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); +#ifndef QT_NO_DRAGANDDROP + void dragEnterEvent(QDragEnterEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dropEvent(QDropEvent *event); +#endif +private: + class QtColorButtonPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtColorButton) + Q_DISABLE_COPY(QtColorButton) + Q_PRIVATE_SLOT(d_func(), void slotEditColor()) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.pri b/tools/shared/qtgradienteditor/qtcolorbutton.pri new file mode 100644 index 0000000..0e41068 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtcolorbutton.pri @@ -0,0 +1,4 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +SOURCES += $$PWD/qtcolorbutton.cpp +HEADERS += $$PWD/qtcolorbutton.h diff --git a/tools/shared/qtgradienteditor/qtcolorline.cpp b/tools/shared/qtgradienteditor/qtcolorline.cpp new file mode 100644 index 0000000..337726c --- /dev/null +++ b/tools/shared/qtgradienteditor/qtcolorline.cpp @@ -0,0 +1,1124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtcolorline.h" +#include "qdrawutil.h" + +#include <QtGui/QPainter> +#include <QtGui/QPaintEvent> +#include <QtGui/QStyleOption> + +QT_BEGIN_NAMESPACE + +class QtColorLinePrivate +{ + QtColorLine *q_ptr; + Q_DECLARE_PUBLIC(QtColorLine) +public: + QtColorLinePrivate(); + + QColor color() const; + void setColor(const QColor &color); + + QtColorLine::ColorComponent colorComponent() const; + void setColorComponent(QtColorLine::ColorComponent component); + + void setIndicatorSize(int size); + int indicatorSize() const; + + void setIndicatorSpace(int space); + int indicatorSpace() const; + + void setFlip(bool flip); + bool flip() const; + + void setBackgroundCheckered(bool checkered); + bool isBackgroundCheckered() const; + + void setOrientation(Qt::Orientation orientation); + Qt::Orientation orientation() const; + + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); +private: + void checkColor(); + bool isMainPixmapValid() const; + void validate(); + void recreateMainPixmap(); + QSize pixmapSizeFromGeometrySize(const QSize &geometrySize) const; + QPixmap gradientPixmap(int size, Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped = false) const; + QPixmap gradientPixmap(Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped = false) const; + QPixmap hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped = false, + int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const; + QPixmap hueGradientPixmap(Qt::Orientation orientation, bool flipped = false, + int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const; + + QVector<QRect> rects(const QPointF &point) const; + + QColor colorFromPoint(const QPointF &point) const; + QPointF pointFromColor(const QColor &color) const; + + QColor m_color; + QtColorLine::ColorComponent m_component; + bool m_flipped; + bool m_backgroundCheckered; + Qt::Orientation m_orientation; + bool m_dragging; + bool m_combiningAlpha; + int m_indicatorSize; + int m_indicatorSpace; + QPointF m_point; + QPoint m_clickOffset; + + QPixmap m_mainPixmap; + QPixmap m_alphalessPixmap; + QPixmap m_semiAlphaPixmap; + QSize m_pixmapSize; + + struct PixData { + QSize size; + QColor color; + QtColorLine::ColorComponent component; + bool flipped; + Qt::Orientation orientation; + }; + + PixData m_lastValidMainPixmapData; +}; + +QtColorLinePrivate::QtColorLinePrivate() + : m_color(Qt::black), m_component(QtColorLine::Value), + m_flipped(false), m_backgroundCheckered(true), m_orientation(Qt::Horizontal), m_dragging(false), m_combiningAlpha(false) +{ + m_indicatorSize = 22; + m_indicatorSpace = 0; + m_pixmapSize = QSize(0, 0); + m_point = pointFromColor(m_color); +} + +void QtColorLinePrivate::setColor(const QColor &color) +{ + if (m_color == color) + return; + if (!color.isValid()) + return; + if (m_dragging) // Warning perhaps here, recursive call + return; + m_color = color; + checkColor(); + QColor c = colorFromPoint(m_point); + m_point = pointFromColor(m_color); + q_ptr->update(); +} + +QColor QtColorLinePrivate::color() const +{ + return m_color; +} + +void QtColorLinePrivate::setColorComponent(QtColorLine::ColorComponent component) +{ + if (m_component == component) + return; + if (m_dragging) // Warning perhaps here, recursive call + return; + m_component = component; + checkColor(); + m_point = pointFromColor(m_color); + q_ptr->update(); +} + +QtColorLine::ColorComponent QtColorLinePrivate::colorComponent() const +{ + return m_component; +} + +void QtColorLinePrivate::setIndicatorSize(int size) +{ + if (size <= 0) + return; + if (m_dragging) // Warning perhaps here, recursive call + return; + if (m_indicatorSize == size) + return; + m_indicatorSize = size; + m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size()); + q_ptr->update(); + q_ptr->updateGeometry(); +} + +int QtColorLinePrivate::indicatorSize() const +{ + return m_indicatorSize; +} + +void QtColorLinePrivate::setIndicatorSpace(int space) +{ + if (space < 0) + return; + if (m_dragging) // Warning perhaps here, recursive call + return; + if (m_indicatorSpace == space) + return; + m_indicatorSpace = space; + m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size()); + q_ptr->update(); +} + +int QtColorLinePrivate::indicatorSpace() const +{ + return m_indicatorSpace; +} + +void QtColorLinePrivate::setFlip(bool flip) +{ + if (m_dragging) // Warning perhaps here, recursive call + return; + if (m_flipped == flip) + return; + m_flipped = flip; + m_point = pointFromColor(m_color); + q_ptr->update(); +} + +bool QtColorLinePrivate::flip() const +{ + return m_flipped; +} + +void QtColorLinePrivate::setBackgroundCheckered(bool checkered) +{ + if (m_backgroundCheckered == checkered) + return; + m_backgroundCheckered = checkered; + q_ptr->update(); +} + +bool QtColorLinePrivate::isBackgroundCheckered() const +{ + return m_backgroundCheckered; +} + +void QtColorLinePrivate::setOrientation(Qt::Orientation orientation) +{ + if (m_dragging) // Warning perhaps here, recursive call + return; + if (m_orientation == orientation) + return; + + m_orientation = orientation; + if (!q_ptr->testAttribute(Qt::WA_WState_OwnSizePolicy)) { + QSizePolicy sp = q_ptr->sizePolicy(); + sp.transpose(); + q_ptr->setSizePolicy(sp); + q_ptr->setAttribute(Qt::WA_WState_OwnSizePolicy, false); + } + m_point = pointFromColor(m_color); + q_ptr->update(); + q_ptr->updateGeometry(); +} + +Qt::Orientation QtColorLinePrivate::orientation() const +{ + return m_orientation; +} + +void QtColorLinePrivate::checkColor() +{ + switch (m_component) { + case QtColorLine::Red: + case QtColorLine::Green: + case QtColorLine::Blue: + if (m_color.spec() != QColor::Rgb) + m_color = m_color.toRgb(); + break; + case QtColorLine::Hue: + case QtColorLine::Saturation: + case QtColorLine::Value: + if (m_color.spec() != QColor::Hsv) + m_color = m_color.toHsv(); + break; + default: + break; + } + if (m_color.spec() == QColor::Hsv) { + if (m_color.hue() == 360 || m_color.hue() == -1) { + m_color.setHsvF(0.0, m_color.saturationF(), m_color.valueF(), m_color.alphaF()); + } + } +} + +bool QtColorLinePrivate::isMainPixmapValid() const +{ + if (m_mainPixmap.isNull()) { + if (m_pixmapSize.isEmpty()) + return true; + else + return false; + } + if (m_lastValidMainPixmapData.component != m_component) + return false; + if (m_lastValidMainPixmapData.size != m_pixmapSize) + return false; + if (m_lastValidMainPixmapData.flipped != m_flipped) + return false; + if (m_lastValidMainPixmapData.orientation != m_orientation) + return false; + if (m_lastValidMainPixmapData.color == m_color) + return true; + switch (m_component) { + case QtColorLine::Red: + if (m_color.green() == m_lastValidMainPixmapData.color.green() && + m_color.blue() == m_lastValidMainPixmapData.color.blue() && + (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha())) + return true; + break; + case QtColorLine::Green: + if (m_color.red() == m_lastValidMainPixmapData.color.red() && + m_color.blue() == m_lastValidMainPixmapData.color.blue() && + (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha())) + return true; + break; + case QtColorLine::Blue: + if (m_color.red() == m_lastValidMainPixmapData.color.red() && + m_color.green() == m_lastValidMainPixmapData.color.green() && + (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha())) + return true; + break; + case QtColorLine::Hue: + if (m_color.saturation() == m_lastValidMainPixmapData.color.saturation() && + m_color.value() == m_lastValidMainPixmapData.color.value() && + (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha())) + return true; + break; + case QtColorLine::Saturation: + if (m_color.hue() == m_lastValidMainPixmapData.color.hue() && + m_color.value() == m_lastValidMainPixmapData.color.value() && + (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha())) + return true; + break; + case QtColorLine::Value: + if (m_color.hue() == m_lastValidMainPixmapData.color.hue() && + m_color.saturation() == m_lastValidMainPixmapData.color.saturation() && + (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha())) + return true; + break; + case QtColorLine::Alpha: + if (m_color.hue() == m_lastValidMainPixmapData.color.hue() && + m_color.saturation() == m_lastValidMainPixmapData.color.saturation() && + m_color.value() == m_lastValidMainPixmapData.color.value()) + return true; + } + return false; +} + +void QtColorLinePrivate::validate() +{ + if (isMainPixmapValid()) + return; + + recreateMainPixmap(); +} + +QPixmap QtColorLinePrivate::gradientPixmap(Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped) const +{ + int size = m_pixmapSize.width(); + if (orientation == Qt::Vertical) + size = m_pixmapSize.height(); + return gradientPixmap(size, orientation, begin, end, flipped); +} + +QPixmap QtColorLinePrivate::gradientPixmap(int size, Qt::Orientation orientation, + const QColor &begin, const QColor &end, bool flipped) const +{ + int gradW = size; + int gradH = size; + int w = size; + int h = size; + if (orientation == Qt::Horizontal) { + gradH = 0; + h = 1; + } else { + gradW = 0; + w = 1; + } + QColor c1 = begin; + QColor c2 = end; + if (flipped) { + c1 = end; + c2 = begin; + } + QLinearGradient lg(0, 0, gradW, gradH); + lg.setColorAt(0, c1); + lg.setColorAt(1, c2); + QImage img(w, h, QImage::Format_ARGB32); + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, w, h), lg); + return QPixmap::fromImage(img); +} + +QPixmap QtColorLinePrivate::hueGradientPixmap(Qt::Orientation orientation, bool flipped, + int saturation, int value, int alpha) const +{ + int size = m_pixmapSize.width(); + if (orientation == Qt::Vertical) + size = m_pixmapSize.height(); + return hueGradientPixmap(size, orientation, flipped, saturation, value, alpha); +} + +QPixmap QtColorLinePrivate::hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped, + int saturation, int value, int alpha) const +{ + int gradW = size + 1; + int gradH = size + 1; + int w = size; + int h = size; + if (orientation == Qt::Horizontal) { + gradH = 0; + h = 1; + } else { + gradW = 0; + w = 1; + } + QList<QColor> colorList; + colorList << QColor::fromHsv(0, saturation, value, alpha); + colorList << QColor::fromHsv(60, saturation, value, alpha); + colorList << QColor::fromHsv(120, saturation, value, alpha); + colorList << QColor::fromHsv(180, saturation, value, alpha); + colorList << QColor::fromHsv(240, saturation, value, alpha); + colorList << QColor::fromHsv(300, saturation, value, alpha); + colorList << QColor::fromHsv(0, saturation, value, alpha); + QLinearGradient lg(0, 0, gradW, gradH); + for (int i = 0; i <= 6; i++) + lg.setColorAt((double)i / 6.0, flipped ? colorList.at(6 - i) : colorList.at(i)); + QImage img(w, h, QImage::Format_ARGB32); + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, w, h), lg); + return QPixmap::fromImage(img); +} + +void QtColorLinePrivate::recreateMainPixmap() +{ + m_lastValidMainPixmapData.size = m_pixmapSize; + m_lastValidMainPixmapData.component = m_component; + m_lastValidMainPixmapData.color = m_color; + m_lastValidMainPixmapData.flipped = m_flipped; + m_lastValidMainPixmapData.orientation = m_orientation; + + if (m_pixmapSize.isEmpty()) { + m_mainPixmap = QPixmap(); + m_alphalessPixmap = QPixmap(); + m_semiAlphaPixmap = QPixmap(); + return; + } + + if (m_mainPixmap.size() != m_pixmapSize) { + m_mainPixmap = QPixmap(m_pixmapSize); + m_alphalessPixmap = QPixmap(m_pixmapSize); + m_semiAlphaPixmap = QPixmap(m_pixmapSize); + } + + Qt::Orientation orient = m_orientation; + const bool flip = m_flipped; + + const int r = m_color.red(); + const int g = m_color.green(); + const int b = m_color.blue(); + const int h = m_color.hue(); + const int s = m_color.saturation(); + const int v = m_color.value(); + const int a = m_color.alpha(); + const double coef = 0.5; + const int semi = qRound(a * coef + 0xFF * (1.0 - coef)); + + if (m_component == QtColorLine::Hue) { + m_alphalessPixmap = hueGradientPixmap(orient, flip, s, v, 0xFF); + if (m_combiningAlpha) { + m_mainPixmap = hueGradientPixmap(orient, flip, s, v, a); + m_semiAlphaPixmap = hueGradientPixmap(orient, flip, s, v, semi); + } + } else if (m_component == QtColorLine::Saturation) { + m_alphalessPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, 0xFF), QColor::fromHsv(h, 0xFF, v, 0xFF), flip); + if (m_combiningAlpha) { + m_mainPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, a), QColor::fromHsv(h, 0xFF, v, a), flip); + m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, semi), QColor::fromHsv(h, 0xFF, v, semi), flip); + } + } else if (m_component == QtColorLine::Value) { + m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, 0xFF), QColor::fromHsv(h, s, 0xFF, 0xFF), flip); + if (m_combiningAlpha) { + m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, a), QColor::fromHsv(h, s, 0xFF, a), flip); + m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, semi), QColor::fromHsv(h, s, 0xFF, semi), flip); + } + } else if (m_component == QtColorLine::Red) { + m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, 0xFF), QColor::fromRgb(0xFF, g, b, 0xFF), flip); + if (m_combiningAlpha) { + m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, a), QColor::fromRgb(0xFF, g, b, a), flip); + m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, semi), QColor::fromRgb(0xFF, g, b, semi), flip); + } + } else if (m_component == QtColorLine::Green) { + m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, 0xFF), QColor::fromRgb(r, 0xFF, b, 0xFF), flip); + if (m_combiningAlpha) { + m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, a), QColor::fromRgb(r, 0xFF, b, a), flip); + m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, semi), QColor::fromRgb(r, 0xFF, b, semi), flip); + } + } else if (m_component == QtColorLine::Blue) { + m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, 0xFF), QColor::fromRgb(r, g, 0xFF, 0xFF), flip); + if (m_combiningAlpha) { + m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, a), QColor::fromRgb(r, g, 0xFF, a), flip); + m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, semi), QColor::fromRgb(r, g, 0xFF, semi), flip); + } + } else if (m_component == QtColorLine::Alpha) { + m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0), QColor::fromRgb(r, g, b, 0xFF), flip); + +// m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0xFF), QColor::fromRgb(r, g, b, 0xFF), flip); +// m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, semi), QColor::fromRgb(r, g, b, semi), flip); + } + if (!m_combiningAlpha && m_component != QtColorLine::Alpha) + m_mainPixmap = m_alphalessPixmap; +} + +QSize QtColorLinePrivate::pixmapSizeFromGeometrySize( + const QSize &geometrySize) const +{ + QSize size(m_indicatorSize + 2 * m_indicatorSpace - 1, + m_indicatorSize + 2 * m_indicatorSpace - 1); + if (m_orientation == Qt::Horizontal) + size.setHeight(0); + else + size.setWidth(0); + return geometrySize - size; +} + +QColor QtColorLinePrivate::colorFromPoint(const QPointF &point) const +{ + QPointF p = point; + if (p.x() < 0) + p.setX(0.0); + else if (p.x() > 1) + p.setX(1.0); + if (p.y() < 0) + p.setY(0.0); + else if (p.y() > 1) + p.setY(1.0); + + double pos = p.x(); + if (m_orientation == Qt::Vertical) + pos = p.y(); + if (m_flipped) + pos = 1.0 - pos; + QColor c; + qreal hue; + switch (m_component) { + case QtColorLine::Red: + c.setRgbF(pos, m_color.greenF(), m_color.blueF(), m_color.alphaF()); + break; + case QtColorLine::Green: + c.setRgbF(m_color.redF(), pos, m_color.blueF(), m_color.alphaF()); + break; + case QtColorLine::Blue: + c.setRgbF(m_color.redF(), m_color.greenF(), pos, m_color.alphaF()); + break; + case QtColorLine::Hue: + hue = pos; + hue *= 35999.0 / 36000.0; + c.setHsvF(hue, m_color.saturationF(), m_color.valueF(), m_color.alphaF()); + break; + case QtColorLine::Saturation: + c.setHsvF(m_color.hueF(), pos, m_color.valueF(), m_color.alphaF()); + break; + case QtColorLine::Value: + c.setHsvF(m_color.hueF(), m_color.saturationF(), pos, m_color.alphaF()); + break; + case QtColorLine::Alpha: + c.setHsvF(m_color.hueF(), m_color.saturationF(), m_color.valueF(), pos); + break; + } + return c; +} + +QPointF QtColorLinePrivate::pointFromColor(const QColor &color) const +{ + qreal hue = color.hueF(); + if (color.hue() == 360) + hue = 0.0; + else + hue *= 36000.0 / 35999.0; + + double pos = 0.0; + switch (m_component) { + case QtColorLine::Red: + pos = color.redF(); + break; + case QtColorLine::Green: + pos = color.greenF(); + break; + case QtColorLine::Blue: + pos = color.blueF(); + break; + case QtColorLine::Hue: + pos = hue; + break; + case QtColorLine::Saturation: + pos = color.saturationF(); + break; + case QtColorLine::Value: + pos = color.valueF(); + break; + case QtColorLine::Alpha: + pos = color.alphaF(); + break; + } + if (m_flipped) + pos = 1.0 - pos; + QPointF p(pos, pos); + if (m_orientation == Qt::Horizontal) + p.setY(0); + else + p.setX(0); + return p; +} + +QVector<QRect> QtColorLinePrivate::rects(const QPointF &point) const +{ + QRect r = q_ptr->geometry(); + r.moveTo(0, 0); + + int x1 = (int)((r.width() - m_indicatorSize - 2 * m_indicatorSpace) * point.x() + 0.5); + int x2 = x1 + m_indicatorSize + 2 * m_indicatorSpace; + int y1 = (int)((r.height() - m_indicatorSize - 2 * m_indicatorSpace) * point.y() + 0.5); + int y2 = y1 + m_indicatorSize + 2 * m_indicatorSpace; + + QVector<QRect> rects; + if (m_orientation == Qt::Horizontal) { + // r0 r1 r2 + QRect r0(0, 0, x1, r.height()); + QRect r1(x1 + m_indicatorSpace, 0, m_indicatorSize, r.height()); + QRect r2(x2, 0, r.width() - x2, r.height()); + + rects << r0 << r1 << r2; + } else { + // r0 + // r1 + // r2 + QRect r0(0, 0, r.width(), y1); + QRect r1(0, y1 + m_indicatorSpace, r.width(), m_indicatorSize); + QRect r2(0, y2, r.width(), r.height() - y2); + + rects << r0 << r1 << r2; + } + return rects; +} + +void QtColorLinePrivate::resizeEvent(QResizeEvent *event) +{ + m_pixmapSize = pixmapSizeFromGeometrySize(event->size()); +} + +void QtColorLinePrivate::paintEvent(QPaintEvent *) +{ + QRect rect = q_ptr->rect(); + + QVector<QRect> r = rects(m_point); + + QColor cBack = q_ptr->palette().color(QPalette::Active, QPalette::Window); + QColor c = colorFromPoint(m_point); + if (!m_combiningAlpha && m_component != QtColorLine::Alpha) + c.setAlpha(0xFF); + + QPainter p(q_ptr); + if (q_ptr->isEnabled()) { + if (m_backgroundCheckered) { + int pixSize = 20; + QPixmap pm(2 * pixSize, 2 * pixSize); + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, Qt::white); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white); + pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black); + pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black); + pmp.end(); + + p.setBrushOrigin((rect.width() % pixSize + pixSize) / 2, (rect.height() % pixSize + pixSize) / 2); + p.setClipRect(r[1].adjusted(4, 4, -4, -4)); + p.setClipRect(QRect(rect.topLeft(), QPoint(r[1].left() + 0, rect.bottom())), Qt::UniteClip); + p.setClipRect(QRect(QPoint(r[1].right() - 0, rect.top()), rect.bottomRight()), Qt::UniteClip); + p.setClipRect(QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 0)), Qt::UniteClip); + p.setClipRect(QRect(QPoint(rect.left(), r[1].bottom() - 0), rect.bottomRight()), Qt::UniteClip); + /* + p.setClipRect(r[1].adjusted(3, 3, -3, -3)); + p.setClipRect(QRect(rect.topLeft(), QPoint(r[1].left() + 1, rect.bottom())), Qt::UniteClip); + p.setClipRect(QRect(QPoint(r[1].right() - 1, rect.top()), rect.bottomRight()), Qt::UniteClip); + p.setClipRect(QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 1)), Qt::UniteClip); + p.setClipRect(QRect(QPoint(rect.left(), r[1].bottom() - 1), rect.bottomRight()), Qt::UniteClip); + */ + p.fillRect(rect, pm); + p.setBrushOrigin(0, 0); + p.setClipping(false); + } + + validate(); + + QSize fieldSize = pixmapSizeFromGeometrySize(q_ptr->geometry().size()); + + QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace); + int x = posOnField.x(); + int y = posOnField.y(); + int w = fieldSize.width(); + int h = fieldSize.height(); + + QRect r0, r2; + if (m_orientation == Qt::Horizontal) { + r0 = QRect(0, 0, x, m_pixmapSize.height()); + r2 = QRect(x + 1, 0, w - x - 1, m_pixmapSize.height()); + } else { + r0 = QRect(0, 0, m_pixmapSize.width(), y); + r2 = QRect(0, y + 1, m_pixmapSize.width(), h - y - 1); + } + + p.setBrush(m_mainPixmap); + p.setPen(Qt::NoPen); + if (r[0].isValid()) { + p.drawRect(r[0]); + } + if (r[2].isValid()) { + p.setBrushOrigin(r[2].topLeft() - r2.topLeft()); + p.drawRect(r[2]); + } + if (m_indicatorSpace) { + p.setBrush(c); + if (m_orientation == Qt::Horizontal) { + p.drawRect(r[1].adjusted(-m_indicatorSpace, 0, -r[1].width(), 0)); + p.drawRect(r[1].adjusted(r[1].width(), 0, m_indicatorSpace, 0)); + } else { + p.drawRect(r[1].adjusted(0, -m_indicatorSpace, 0, -r[1].height())); + p.drawRect(r[1].adjusted(0, r[1].height(), 0, m_indicatorSpace)); + } + } + + QPen pen(c); + p.setPen(pen); + p.setBrush(Qt::NoBrush); + if (r[1].isValid()) { + p.drawRect(r[1].adjusted(0, 0, -1, -1)); + // p.drawRect(r[1].adjusted(1, 1, -2, -2)); + } + double coef = 9.0 / 10; + p.setPen(Qt::NoPen); + if (m_component != QtColorLine::Alpha && m_combiningAlpha) { + p.setBrush(m_alphalessPixmap); + if (r[0].isValid()) { + p.setBrushOrigin(QPoint(0, 0)); + QRect thinRect1 = r[0]; + QRect thinRect2 = r[0]; + QRect thinRect = r[0]; + if (m_orientation == Qt::Horizontal) { + thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0); + thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef)); + thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef)); + } else { + thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0); + thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0); + thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0); + } + p.drawRect(thinRect1); + p.drawRect(thinRect2); + //p.drawRect(thinRect); + } + if (r[2].isValid()) { + p.setBrushOrigin(r[2].topLeft() - r2.topLeft()); + QRect thinRect1 = r[2]; + QRect thinRect2 = r[2]; + QRect thinRect = r[2]; + if (m_orientation == Qt::Horizontal) { + thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0); + thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef)); + thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef)); + } else { + thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0); + thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0); + thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0); + } + p.drawRect(thinRect1); + p.drawRect(thinRect2); + //p.drawRect(thinRect); + } + /* + +*/ + + + + + + p.setPen(Qt::NoPen); + + p.setBrush(m_semiAlphaPixmap); + if (r[0].isValid()) { + p.setBrushOrigin(QPoint(0, 0)); + QRect thinRect1 = r[0]; + QRect thinRect2 = r[0]; + QRect thinRect = r[0]; + if (m_orientation == Qt::Horizontal) { + thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0); + thinRect1.setBottom(thinRect1.top()); + thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1); + thinRect2.setTop(thinRect2.bottom()); + thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef)); + } else { + thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0); + thinRect1.setRight(thinRect1.left()); + thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0); + thinRect2.setLeft(thinRect2.right()); + thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0); + } + p.drawRect(thinRect1); + p.drawRect(thinRect2); + //p.drawRect(thinRect); + } + if (r[2].isValid()) { + p.setBrushOrigin(r[2].topLeft() - r2.topLeft()); + QRect thinRect1 = r[2]; + QRect thinRect2 = r[2]; + QRect thinRect = r[2]; + if (m_orientation == Qt::Horizontal) { + thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0); + thinRect1.setBottom(thinRect1.top()); + thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1); + thinRect2.setTop(thinRect2.bottom()); + thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef)); + } else { + thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0); + thinRect1.setRight(thinRect1.left()); + thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0); + thinRect2.setLeft(thinRect2.right()); + thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0); + } + p.drawRect(thinRect1); + p.drawRect(thinRect2); + //p.drawRect(thinRect); + } + p.setBrush(m_alphalessPixmap); + if (m_orientation == Qt::Horizontal) { + p.setClipRect(r[1].adjusted(0, qRound(r[1].height() * coef), 0, 0)); + p.setClipRect(r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef)), Qt::UniteClip); + } else { + p.setClipRect(r[1].adjusted(qRound(r[1].width() * coef), 0, 0, 0)); + p.setClipRect(r[1].adjusted(0, 0, -qRound(r[1].width() * coef), 0), Qt::UniteClip); + } + p.setBrush(Qt::NoBrush); + p.setPen(QPen(QColor(c.rgb()))); + + p.drawRect(r[1].adjusted(0, 0, -1, -1)); + // p.drawRect(r[1].adjusted(1, 1, -2, -2)); +/* + p.setBrush(m_semiAlphaPixmap); + if (m_orientation == Qt::Horizontal) { + QRect top = r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef) + 1); + top.setTop(top.bottom()); + QRect bottom = r[1].adjusted(0, qRound(r[1].height() * coef) - 1, 0, 0); + top.setBottom(bottom.top()); + p.setClipRect(top); + p.setClipRect(bottom, Qt::UniteClip); + } else { + + } + QColor semiColor(c.rgb()); + semiColor.setAlpha((c.alpha() + 0xFF) / 2); + p.setPen(QPen(semiColor)); + p.drawRect(r[1].adjusted(0, 0, -1, -1)); + // p.drawRect(r[1].adjusted(1, 1, -2, -2)); +*/ + p.setClipping(false); + } + } + + p.setBrush(Qt::NoBrush); + int lw = 4; + //int br = 1; + int br = 0; + r[1].adjust(br, br, -br, -br); + if (r[1].adjusted(lw, lw, -lw, -lw).isValid()) { + QStyleOptionFrame opt; + opt.init(q_ptr); + opt.rect = r[1]; + opt.lineWidth = 2; + opt.midLineWidth = 1; + if (m_dragging) + opt.state |= QStyle::State_Sunken; + else + opt.state |= QStyle::State_Raised; + q_ptr->style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, q_ptr); + QRect colorRect = r[1].adjusted(lw, lw, -lw, -lw); + if (q_ptr->isEnabled()) { + p.fillRect(colorRect, c); + const QColor frameColor(0, 0, 0, 38); + p.setPen(frameColor); + p.drawRect(colorRect.adjusted(0, 0, -1, -1)); + /* + p.fillRect(colorRect.width() / 4 + colorRect.left(), + colorRect.height() / 4 + colorRect.top(), + colorRect.width() / 2, + colorRect.height() / 2, + QColor(c.rgb())); + */ + /* + if (m_component != QtColorLine::Alpha) { + p.fillRect(colorRect.adjusted(0, colorRect.height() * 4 / 5, 0, 0), QColor(c.rgb())); + p.fillRect(colorRect.adjusted(0, 0, 0, -colorRect.height() * 4 / 5), QColor(c.rgb())); + } + */ + } + } +} + +void QtColorLinePrivate::mousePressEvent(QMouseEvent *event) +{ + if (event->button() != Qt::LeftButton) + return; + + QVector<QRect> r = rects(m_point); + QPoint clickPos = event->pos(); + + QSize fieldSize = q_ptr->geometry().size() - + QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1); + QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace); + m_clickOffset = posOnField - clickPos; + + if (!r[1].contains(clickPos)) + return; + m_dragging = true; + q_ptr->update(); +} + +void QtColorLinePrivate::mouseMoveEvent(QMouseEvent *event) +{ + if (!m_dragging) + return; + QPoint newPos = event->pos(); + + QSize fieldSize = q_ptr->geometry().size() - + QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1); + QPoint newPosOnField = newPos + m_clickOffset; + if (newPosOnField.x() < 0) + newPosOnField.setX(0); + else if (newPosOnField.x() > fieldSize.width()) + newPosOnField.setX(fieldSize.width()); + if (newPosOnField.y() < 0) + newPosOnField.setY(0); + else if (newPosOnField.y() > fieldSize.height()) + newPosOnField.setY(fieldSize.height()); + + double x = (double)newPosOnField.x() / fieldSize.width(); + double y = (double)newPosOnField.y() / fieldSize.height(); + m_point = QPointF(x, y); + QColor color = colorFromPoint(m_point); + if (m_color == color) + return; + m_color = color; + emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above + q_ptr->update(); +} + +void QtColorLinePrivate::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() != Qt::LeftButton) + return; + m_dragging = false; + q_ptr->update(); +} + +void QtColorLinePrivate::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() != Qt::LeftButton) + return; + + QVector<QRect> r = rects(m_point); + QPoint clickPos = event->pos(); + if (!r[0].contains(clickPos) && !r[2].contains(clickPos)) + return; + QPoint newPosOnField = clickPos; + if (r[2].contains(clickPos)) + newPosOnField -= QPoint(m_indicatorSize + 2 * m_indicatorSpace - 2, m_indicatorSize + 2 * m_indicatorSpace - 2); + QSize fieldSize = q_ptr->geometry().size() - + QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1); + + double x = (double)newPosOnField.x() / fieldSize.width(); + double y = (double)newPosOnField.y() / fieldSize.height(); + m_point = QPointF(x, y); + QColor color = colorFromPoint(m_point); + if (m_color == color) + return; + m_color = color; + emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above + q_ptr->update(); +} + +//////////////////////////////////////////////////// + +QtColorLine::QtColorLine(QWidget *parent) + : QWidget(parent) +{ + d_ptr = new QtColorLinePrivate; + d_ptr->q_ptr = this; + + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); +} + +QtColorLine::~QtColorLine() +{ + delete d_ptr; +} + +QSize QtColorLine::minimumSizeHint() const +{ + return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize); +} + +QSize QtColorLine::sizeHint() const +{ + return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize); +} + +void QtColorLine::setColor(const QColor &color) +{ + d_ptr->setColor(color); +} + +QColor QtColorLine::color() const +{ + return d_ptr->color(); +} + +void QtColorLine::setColorComponent(QtColorLine::ColorComponent component) +{ + d_ptr->setColorComponent(component); +} + +QtColorLine::ColorComponent QtColorLine::colorComponent() const +{ + return d_ptr->colorComponent(); +} + +void QtColorLine::setIndicatorSize(int size) +{ + d_ptr->setIndicatorSize(size); +} + +int QtColorLine::indicatorSize() const +{ + return d_ptr->indicatorSize(); +} + +void QtColorLine::setIndicatorSpace(int space) +{ + d_ptr->setIndicatorSpace(space); +} + +int QtColorLine::indicatorSpace() const +{ + return d_ptr->indicatorSpace(); +} + +void QtColorLine::setFlip(bool flip) +{ + d_ptr->setFlip(flip); +} + +bool QtColorLine::flip() const +{ + return d_ptr->flip(); +} + +void QtColorLine::setBackgroundCheckered(bool checkered) +{ + d_ptr->setBackgroundCheckered(checkered); +} + +bool QtColorLine::isBackgroundCheckered() const +{ + return d_ptr->isBackgroundCheckered(); +} + +void QtColorLine::setOrientation(Qt::Orientation orientation) +{ + d_ptr->setOrientation(orientation); +} + +Qt::Orientation QtColorLine::orientation() const +{ + return d_ptr->orientation(); +} +void QtColorLine::resizeEvent(QResizeEvent *event) +{ + d_ptr->resizeEvent(event); +} + +void QtColorLine::paintEvent(QPaintEvent *event) +{ + d_ptr->paintEvent(event); +} + +void QtColorLine::mousePressEvent(QMouseEvent *event) +{ + d_ptr->mousePressEvent(event); +} + +void QtColorLine::mouseMoveEvent(QMouseEvent *event) +{ + d_ptr->mouseMoveEvent(event); +} + +void QtColorLine::mouseReleaseEvent(QMouseEvent *event) +{ + d_ptr->mouseReleaseEvent(event); +} + +void QtColorLine::mouseDoubleClickEvent(QMouseEvent *event) +{ + d_ptr->mouseDoubleClickEvent(event); +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtcolorline.h b/tools/shared/qtgradienteditor/qtcolorline.h new file mode 100644 index 0000000..d5535b1 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtcolorline.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCOLORLINE_H +#define QTCOLORLINE_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QtColorLine : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor) + Q_PROPERTY(int indicatorSpace READ indicatorSpace WRITE setIndicatorSpace) + Q_PROPERTY(int indicatorSize READ indicatorSize WRITE setIndicatorSize) + Q_PROPERTY(bool flip READ flip WRITE setFlip) + Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered) + Q_PROPERTY(ColorComponent colorComponent READ colorComponent WRITE setColorComponent) + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) + Q_ENUMS(ColorComponent) +public: + + enum ColorComponent { + Red, + Green, + Blue, + Hue, + Saturation, + Value, + Alpha + }; + + QSize minimumSizeHint() const; + QSize sizeHint() const; + + QtColorLine(QWidget *parent = 0); + ~QtColorLine(); + + QColor color() const; + + void setIndicatorSize(int size); + int indicatorSize() const; + + void setIndicatorSpace(int space); + int indicatorSpace() const; + + void setFlip(bool flip); + bool flip() const; + + bool isBackgroundCheckered() const; + void setBackgroundCheckered(bool checkered); + + void setOrientation(Qt::Orientation orientation); + Qt::Orientation orientation() const; + + void setColorComponent(ColorComponent component); + ColorComponent colorComponent() const; + +public slots: + + void setColor(const QColor &color); + +signals: + + void colorChanged(const QColor &color); + +protected: + + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + +private: + + class QtColorLinePrivate *d_ptr; + Q_DECLARE_PRIVATE(QtColorLine) + Q_DISABLE_COPY(QtColorLine) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.cpp b/tools/shared/qtgradienteditor/qtgradientdialog.cpp new file mode 100644 index 0000000..950a1d2 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientdialog.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientdialog.h" +#include "ui_qtgradientdialog.h" +#include <QtGui/QPushButton> + +QT_BEGIN_NAMESPACE + +class QtGradientDialogPrivate +{ + QtGradientDialog *q_ptr; + Q_DECLARE_PUBLIC(QtGradientDialog) +public: + + void slotAboutToShowDetails(bool details, int extensionWidthHint); + + Ui::QtGradientDialog m_ui; +}; + +void QtGradientDialogPrivate::slotAboutToShowDetails(bool details, int extensionWidthHint) +{ + if (details) { + q_ptr->resize(q_ptr->size() + QSize(extensionWidthHint, 0)); + } else { + q_ptr->setMinimumSize(1, 1); + q_ptr->resize(q_ptr->size() - QSize(extensionWidthHint, 0)); + q_ptr->setMinimumSize(0, 0); + } +} + +/*! + \class QtGradientDialog + + \brief The QtGradientDialog class provides a dialog for specifying gradients. + + The gradient dialog's function is to allow users to edit gradients. + For example, you might use this in a drawing program to allow the user to set the brush gradient. + + \table + \row + \o \inlineimage qtgradientdialog.png + \o \inlineimage qtgradientdialogextension.png + \header + \o Details extension hidden + \o Details extension visible + \endtable + + Starting from the top of the dialog there are several buttons: + + \image qtgradientdialogtopbuttons.png + + The first three buttons allow for changing a type of the gradient (QGradient::Type), while the second three allow for + changing spread of the gradient (QGradient::Spread). The last button shows or hides the details extension of the dialog. + Conceptually the default view with hidden details provides the full functional control over gradient editing. + The additional extension with details allows to set gradient's parameters more precisely. The visibility + of extension can be controlled by detailsVisible property. Moreover, if you don't want the user to + switch on or off the visibility of extension you can set the detailsButtonVisible property to false. + + Below top buttons there is an area where edited gradient is interactively previewed. + In addition the user can edit gradient type's specific parameters directly in this area by dragging + appropriate handles. + + \table + \row + \o \inlineimage qtgradientdialoglineareditor.png + \o \inlineimage qtgradientdialogradialeditor.png + \o \inlineimage qtgradientdialogconicaleditor.png + \header + \o Editing linear type + \o Editing radial type + \o Editing conical type + \row + \o The user can change the start and final point positions by dragging the circular handles. + \o The user can change the center and focal point positions by dragging the circular handles + and can change the gradient's radius by dragging horizontal or vertical line. + \o The user can change the center point by dragging the circular handle + and can change the gradient's angle by dragging the big wheel. + \endtable + + In the middle of the dialog there is an area where the user can edit gradient stops. + + \table + \row + \o \inlineimage qtgradientdialogstops.png + \o \inlineimage qtgradientdialogstopszoomed.png + \endtable + + The top part of this area contains stop handles, and bottom part shows the preview of gradient stops path. + In order to create a new gradient stop double click inside the view over the desired position. + If you double click on existing stop handle in the top part of the view, clicked handle will be duplicated + (duplicate will contain the same color). + The stop can be activated by clicking on its handle. You can activate previous or next stop by pressing + left or right key respectively. To jump to the first or last stop press home or end key respectively. + The gradient stops editor supports multiselection. + Clicking a handle holding the shift modifier key down will select a range of stops between + the active stop and clicked one. Clicking a handle holding control modifier key down will remove from or + add to selection the clicked stop depending if it was or wasn't already selected respectively. + Multiselection can also be created using rubberband (by pressing the left mouse button outside + of any handle and dragging). + Sometimes it's hard to select a stop because its handle can be partially covered by other handle. + In that case the user can zoom in the view by spinning mouse wheel. + The selected stop handles can be moved by drag & drop. In order to remove selected stops press delete key. + For convenience context menu is provided with the following actions: + + \list + \o New Stop - creates a new gradient stop + \o Delete - removes the active and all selected stops + \o Flip All - mirrors all stops + \o Select All - selects all stops + \o Zoom In - zooms in + \o Zoom Out - zooms out + \o Zoom All - goes back to original 100% zoom + \endlist + + The bottom part of the QtGradientDialog contains a set of widgets allowing to control the color of + the active and selected stops. + + \table + \row + \o \inlineimage qtgradientdialogcolorhsv.png + \o \inlineimage qtgradientdialogcolorrgb.png + \endtable + + + The color button shows the color of the active gradient stop. It also allows for choosing + a color from standard color dialog and applying it to the + active stop and all selected stops. It's also possible to drag a color directly from the color button + and to drop it in gradient stops editor at desired position (it will create new stop with dragged color) + or at desired stop handle (it will change the color of that handle). + + To the right of color button there is a set of 2 radio buttons which allows to switch between + HVS and RGB color spec. + + Finally there are 4 color sliders working either in HSVA (hue saturation value alpha) or + RGBA (red green blue alpha) mode, depending on which radio button is chosen. The radio buttons + can be controlled programatically by spec() and setSpec() methods. The sliders show the + color of the active stop. By double clicking inside color slider you can set directly the desired color. + Changes of slider's are applied to stop selection in the way that the color + component being changed is applied to stops in selection only, while other components + remain unchanged in selected stops (e.g. when the user is changing the saturation, + new saturation is applied to selected stops preventing original hue, value and alpha in multiselection). + + The convenient static functions getGradient() provide modal gradient dialogs, e.g.: + + \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 0 + + In order to have more control over the properties of QtGradientDialog use + standard QDialog::exec() method: + + \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 1 + + \sa {Gradient View Example} +*/ + +/*! + Constructs a gradient dialog with \a parent as parent widget. +*/ + +QtGradientDialog::QtGradientDialog(QWidget *parent) + : QDialog(parent) +{ +// setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + d_ptr = new QtGradientDialogPrivate(); + d_ptr->q_ptr = this; + d_ptr->m_ui.setupUi(this); + QPushButton *button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Ok); + if (button) + button->setAutoDefault(false); + button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Cancel); + if (button) + button->setAutoDefault(false); + connect(d_ptr->m_ui.gradientEditor, SIGNAL(aboutToShowDetails(bool, int)), + this, SLOT(slotAboutToShowDetails(bool, int))); +} + +/*! + Destroys the gradient dialog +*/ + +QtGradientDialog::~QtGradientDialog() +{ + delete d_ptr; +} + +/*! + \property QtGradientDialog::gradient + \brief the gradient of the dialog +*/ +void QtGradientDialog::setGradient(const QGradient &gradient) +{ + d_ptr->m_ui.gradientEditor->setGradient(gradient); +} + +QGradient QtGradientDialog::gradient() const +{ + return d_ptr->m_ui.gradientEditor->gradient(); +} + +/*! + \property QtGradientDialog::backgroundCheckered + \brief whether the background of widgets able to show the colors with alpha channel is checkered. + + \table + \row + \o \inlineimage qtgradientdialogbackgroundcheckered.png + \o \inlineimage qtgradientdialogbackgroundtransparent.png + \row + \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 2 + \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 3 + \endtable + + When this property is set to true (the default) widgets inside gradient dialog like color button, + color sliders, gradient stops editor and gradient editor will show checkered background + in case of transparent colors. Otherwise the background of these widgets is transparent. +*/ + +bool QtGradientDialog::isBackgroundCheckered() const +{ + return d_ptr->m_ui.gradientEditor->isBackgroundCheckered(); +} + +void QtGradientDialog::setBackgroundCheckered(bool checkered) +{ + d_ptr->m_ui.gradientEditor->setBackgroundCheckered(checkered); +} + +/*! + \property QtGradientDialog::detailsVisible + \brief whether details extension is visible. + + When this property is set to true the details extension is visible. By default + this property is set to false and the details extension is hidden. + + \sa detailsButtonVisible +*/ +bool QtGradientDialog::detailsVisible() const +{ + return d_ptr->m_ui.gradientEditor->detailsVisible(); +} + +void QtGradientDialog::setDetailsVisible(bool visible) +{ + d_ptr->m_ui.gradientEditor->setDetailsVisible(visible); +} + +/*! + \property QtGradientDialog::detailsButtonVisible + \brief whether the details button allowing for showing and hiding details extension is visible. + + When this property is set to true (the default) the details button is visible and the user + can show and hide details extension interactively. Otherwise the button is hidden and the details + extension is always visible or hidded depending on the value of detailsVisible property. + + \sa detailsVisible +*/ +bool QtGradientDialog::isDetailsButtonVisible() const +{ + return d_ptr->m_ui.gradientEditor->isDetailsButtonVisible(); +} + +void QtGradientDialog::setDetailsButtonVisible(bool visible) +{ + d_ptr->m_ui.gradientEditor->setDetailsButtonVisible(visible); +} + +/*! + Returns the current QColor::Spec used for the color sliders in the dialog. +*/ +QColor::Spec QtGradientDialog::spec() const +{ + return d_ptr->m_ui.gradientEditor->spec(); +} + +/*! + Sets the current QColor::Spec to \a spec used for the color sliders in the dialog. +*/ +void QtGradientDialog::setSpec(QColor::Spec spec) +{ + d_ptr->m_ui.gradientEditor->setSpec(spec); +} + +/*! + Executes a modal gradient dialog, lets the user to specify a gradient, and returns that gradient. + + If the user clicks \gui OK, the gradient specified by the user is returned. If the user clicks \gui Cancel, the \a initial gradient is returned. + + The dialog is constructed with the given \a parent. \a caption is shown as the window title of the dialog and + \a initial is the initial gradient shown in the dialog. If the \a ok parameter is not-null, + the value it refers to is set to true if the user clicks \gui OK, and set to false if the user clicks \gui Cancel. +*/ +QGradient QtGradientDialog::getGradient(bool *ok, const QGradient &initial, QWidget *parent, const QString &caption) +{ + QtGradientDialog dlg(parent); + if (!caption.isEmpty()) + dlg.setWindowTitle(caption); + dlg.setGradient(initial); + const int res = dlg.exec(); + if (ok) { + *ok = (res == QDialog::Accepted) ? true : false; + } + if (res == QDialog::Accepted) + return dlg.gradient(); + return initial; +} + +/*! + This method calls getGradient(ok, QLinearGradient(), parent, caption). +*/ +QGradient QtGradientDialog::getGradient(bool *ok, QWidget *parent, const QString &caption) +{ + return getGradient(ok, QLinearGradient(), parent, caption); +} + +QT_END_NAMESPACE + +#include "moc_qtgradientdialog.cpp" diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.h b/tools/shared/qtgradienteditor/qtgradientdialog.h new file mode 100644 index 0000000..d3bafc9 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientdialog.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTGRADIENTDIALOG_H +#define QTGRADIENTDIALOG_H + +#include <QtGui/QDialog> + +QT_BEGIN_NAMESPACE + +class QtGradientDialog : public QDialog +{ + Q_OBJECT + Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient) + Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered) + Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible) + Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible) +public: + QtGradientDialog(QWidget *parent = 0); + ~QtGradientDialog(); + + void setGradient(const QGradient &gradient); + QGradient gradient() const; + + bool isBackgroundCheckered() const; + void setBackgroundCheckered(bool checkered); + + bool detailsVisible() const; + void setDetailsVisible(bool visible); + + bool isDetailsButtonVisible() const; + void setDetailsButtonVisible(bool visible); + + QColor::Spec spec() const; + void setSpec(QColor::Spec spec); + + static QGradient getGradient(bool *ok, const QGradient &initial, QWidget *parent = 0, const QString &caption = QString()); + static QGradient getGradient(bool *ok, QWidget *parent = 0, const QString &caption = QString()); + +private: + class QtGradientDialogPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtGradientDialog) + Q_DISABLE_COPY(QtGradientDialog) + Q_PRIVATE_SLOT(d_func(), void slotAboutToShowDetails(bool details, int extensionWidthHint)) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.ui b/tools/shared/qtgradienteditor/qtgradientdialog.ui new file mode 100644 index 0000000..0b3db0b --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientdialog.ui @@ -0,0 +1,121 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>QtGradientDialog</class> + <widget class="QDialog" name="QtGradientDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>178</width> + <height>81</height> + </rect> + </property> + <property name="windowTitle" > + <string>Edit Gradient</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QtGradientEditor" name="gradientEditor" > + <property name="sizePolicy" > + <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QtGradientEditor</class> + <extends>QFrame</extends> + <header>qtgradienteditor.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>QtGradientDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel" > + <x>72</x> + <y>224</y> + </hint> + <hint type="destinationlabel" > + <x>21</x> + <y>243</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>QtGradientDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>168</x> + <y>233</y> + </hint> + <hint type="destinationlabel" > + <x>152</x> + <y>251</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.cpp b/tools/shared/qtgradienteditor/qtgradienteditor.cpp new file mode 100644 index 0000000..42d7767 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradienteditor.cpp @@ -0,0 +1,954 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradienteditor.h" +#include "qtgradientstopscontroller.h" +#include "ui_qtgradienteditor.h" + +QT_BEGIN_NAMESPACE + +class QtGradientEditorPrivate +{ + QtGradientEditor *q_ptr; + Q_DECLARE_PUBLIC(QtGradientEditor) +public: + QtGradientEditorPrivate() : m_gradient(QLinearGradient()) {} + + void slotGradientStopsChanged(const QGradientStops &stops); + void slotTypeChanged(int type); + void slotSpreadChanged(int spread); + void slotStartLinearXChanged(double value); + void slotStartLinearYChanged(double value); + void slotEndLinearXChanged(double value); + void slotEndLinearYChanged(double value); + void slotCentralRadialXChanged(double value); + void slotCentralRadialYChanged(double value); + void slotFocalRadialXChanged(double value); + void slotFocalRadialYChanged(double value); + void slotRadiusRadialChanged(double value); + void slotCentralConicalXChanged(double value); + void slotCentralConicalYChanged(double value); + void slotAngleConicalChanged(double value); + + void slotDetailsChanged(bool details); + + void startLinearChanged(const QPointF &point); + void endLinearChanged(const QPointF &point); + void centralRadialChanged(const QPointF &point); + void focalRadialChanged(const QPointF &point); + void radiusRadialChanged(qreal radius); + void centralConicalChanged(const QPointF &point); + void angleConicalChanged(qreal angle); + + void setStartLinear(const QPointF &point); + void setEndLinear(const QPointF &point); + void setCentralRadial(const QPointF &point); + void setFocalRadial(const QPointF &point); + void setRadiusRadial(qreal radius); + void setCentralConical(const QPointF &point); + void setAngleConical(qreal angle); + + void setType(QGradient::Type type); + void showDetails(bool details); + + void setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max = 1.0, double step = 0.01, int decimals = 3); + void reset(); + void setLayout(bool details); + void layoutDetails(bool details); + bool row4Visible() const; + bool row5Visible() const; + int extensionWidthHint() const; + + void setCombos(bool combos); + + QGradient gradient() const; + void updateGradient(bool emitSignal); + + Ui::QtGradientEditor m_ui; + QtGradientStopsController *m_gradientStopsController; + + QDoubleSpinBox *startLinearXSpinBox; + QDoubleSpinBox *startLinearYSpinBox; + QDoubleSpinBox *endLinearXSpinBox; + QDoubleSpinBox *endLinearYSpinBox; + QDoubleSpinBox *centralRadialXSpinBox; + QDoubleSpinBox *centralRadialYSpinBox; + QDoubleSpinBox *focalRadialXSpinBox; + QDoubleSpinBox *focalRadialYSpinBox; + QDoubleSpinBox *radiusRadialSpinBox; + QDoubleSpinBox *centralConicalXSpinBox; + QDoubleSpinBox *centralConicalYSpinBox; + QDoubleSpinBox *angleConicalSpinBox; + + QButtonGroup *m_typeGroup; + QButtonGroup *m_spreadGroup; + + QGradient::Type m_type; + + QGridLayout *m_gridLayout; + QWidget *m_hiddenWidget; + QGridLayout *m_hiddenLayout; + bool m_details; + bool m_detailsButtonVisible; + bool m_backgroundCheckered; + + QGradient m_gradient; + + bool m_combos; +}; + +QGradient QtGradientEditorPrivate::gradient() const +{ + QGradient *gradient = 0; + switch (m_ui.gradientWidget->gradientType()) { + case QGradient::LinearGradient: + gradient = new QLinearGradient(m_ui.gradientWidget->startLinear(), + m_ui.gradientWidget->endLinear()); + break; + case QGradient::RadialGradient: + gradient = new QRadialGradient(m_ui.gradientWidget->centralRadial(), + m_ui.gradientWidget->radiusRadial(), + m_ui.gradientWidget->focalRadial()); + break; + case QGradient::ConicalGradient: + gradient = new QConicalGradient(m_ui.gradientWidget->centralConical(), + m_ui.gradientWidget->angleConical()); + break; + default: + break; + } + if (!gradient) + return QGradient(); + gradient->setStops(m_ui.gradientWidget->gradientStops()); + gradient->setSpread(m_ui.gradientWidget->gradientSpread()); + gradient->setCoordinateMode(QGradient::StretchToDeviceMode); + QGradient gr = *gradient; + delete gradient; + return gr; +} + +void QtGradientEditorPrivate::updateGradient(bool emitSignal) +{ + QGradient grad = gradient(); + if (m_gradient == grad) + return; + + m_gradient = grad; + if (emitSignal) + emit q_ptr->gradientChanged(m_gradient); +} + +void QtGradientEditorPrivate::setCombos(bool combos) +{ + if (m_combos == combos) + return; + + m_combos = combos; + m_ui.linearButton->setVisible(!m_combos); + m_ui.radialButton->setVisible(!m_combos); + m_ui.conicalButton->setVisible(!m_combos); + m_ui.padButton->setVisible(!m_combos); + m_ui.repeatButton->setVisible(!m_combos); + m_ui.reflectButton->setVisible(!m_combos); + m_ui.typeComboBox->setVisible(m_combos); + m_ui.spreadComboBox->setVisible(m_combos); +} + +void QtGradientEditorPrivate::setLayout(bool details) +{ + QHBoxLayout *hboxLayout = new QHBoxLayout(); + hboxLayout->setObjectName(QString::fromUtf8("hboxLayout")); + hboxLayout->addWidget(m_ui.typeComboBox); + hboxLayout->addWidget(m_ui.spreadComboBox); + QHBoxLayout *typeLayout = new QHBoxLayout(); + typeLayout->setSpacing(0); + typeLayout->addWidget(m_ui.linearButton); + typeLayout->addWidget(m_ui.radialButton); + typeLayout->addWidget(m_ui.conicalButton); + hboxLayout->addLayout(typeLayout); + QHBoxLayout *spreadLayout = new QHBoxLayout(); + spreadLayout->setSpacing(0); + spreadLayout->addWidget(m_ui.padButton); + spreadLayout->addWidget(m_ui.repeatButton); + spreadLayout->addWidget(m_ui.reflectButton); + hboxLayout->addLayout(spreadLayout); + hboxLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + hboxLayout->addWidget(m_ui.detailsButton); + m_gridLayout->addLayout(hboxLayout, 0, 0, 1, 2); + int span = 1; + if (details) + span = 7; + m_gridLayout->addWidget(m_ui.frame, 1, 0, span, 2); + int row = 2; + if (details) { + row = 8; + span = 4; + } + m_gridLayout->addWidget(m_ui.gradientStopsWidget, row, 0, span, 2); + QHBoxLayout *hboxLayout1 = new QHBoxLayout(); + hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1")); + hboxLayout1->addWidget(m_ui.colorLabel); + hboxLayout1->addWidget(m_ui.colorButton); + hboxLayout1->addWidget(m_ui.hsvRadioButton); + hboxLayout1->addWidget(m_ui.rgbRadioButton); + hboxLayout1->addItem(new QSpacerItem(16, 23, QSizePolicy::Expanding, QSizePolicy::Minimum)); + int addRow = 0; + if (details) + addRow = 9; + m_gridLayout->addLayout(hboxLayout1, 3 + addRow, 0, 1, 2); + m_gridLayout->addWidget(m_ui.hLabel, 4 + addRow, 0, 1, 1); + m_gridLayout->addWidget(m_ui.frame_2, 4 + addRow, 1, 1, 1); + m_gridLayout->addWidget(m_ui.sLabel, 5 + addRow, 0, 1, 1); + m_gridLayout->addWidget(m_ui.frame_5, 5 + addRow, 1, 1, 1); + m_gridLayout->addWidget(m_ui.vLabel, 6 + addRow, 0, 1, 1); + m_gridLayout->addWidget(m_ui.frame_3, 6 + addRow, 1, 1, 1); + m_gridLayout->addWidget(m_ui.aLabel, 7 + addRow, 0, 1, 1); + m_gridLayout->addWidget(m_ui.frame_4, 7 + addRow, 1, 1, 1); + + if (details) { + layoutDetails(details); + } +} + +void QtGradientEditorPrivate::layoutDetails(bool details) +{ + QGridLayout *gridLayout = m_gridLayout; + int col = 2; + if (!details) { + col = 0; + if (!m_hiddenWidget) { + m_hiddenWidget = new QWidget(); + m_hiddenLayout = new QGridLayout(m_hiddenWidget); + m_hiddenLayout->setContentsMargins(0, 0, 0, 0); + m_hiddenLayout->setSizeConstraint(QLayout::SetFixedSize); + } + gridLayout = m_hiddenLayout; + } + gridLayout->addWidget(m_ui.label1, 1, col + 0, 1, 1); + gridLayout->addWidget(m_ui.spinBox1, 1, col + 1, 1, 1); + gridLayout->addWidget(m_ui.label2, 2, col + 0, 1, 1); + gridLayout->addWidget(m_ui.spinBox2, 2, col + 1, 1, 1); + gridLayout->addWidget(m_ui.label3, 3, col + 0, 1, 1); + gridLayout->addWidget(m_ui.spinBox3, 3, col + 1, 1, 1); + gridLayout->addWidget(m_ui.label4, 4, col + 0, 1, 1); + gridLayout->addWidget(m_ui.spinBox4, 4, col + 1, 1, 1); + gridLayout->addWidget(m_ui.label5, 5, col + 0, 1, 1); + gridLayout->addWidget(m_ui.spinBox5, 5, col + 1, 1, 1); + gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 6, col + 0, 1, 1); + gridLayout->addWidget(m_ui.line1Widget, 7, col + 0, 1, 2); + gridLayout->addWidget(m_ui.zoomLabel, 8, col + 0, 1, 1); + gridLayout->addWidget(m_ui.zoomWidget, 8, col + 1, 1, 1); + gridLayout->addWidget(m_ui.zoomButtonsWidget, 9, col + 0, 1, 1); + gridLayout->addWidget(m_ui.zoomAllButton, 9, col + 1, 1, 1); + gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Preferred), 10, col + 0, 1, 1); + gridLayout->addWidget(m_ui.line2Widget, 11, col + 0, 1, 2); + gridLayout->addWidget(m_ui.positionLabel, 12, col + 0, 1, 1); + gridLayout->addWidget(m_ui.positionWidget, 12, col + 1, 1, 1); + gridLayout->addWidget(m_ui.hueLabel, 13, col + 0, 1, 1); + gridLayout->addWidget(m_ui.hueWidget, 13, col + 1, 1, 1); + gridLayout->addWidget(m_ui.saturationLabel, 14, col + 0, 1, 1); + gridLayout->addWidget(m_ui.saturationWidget, 14, col + 1, 1, 1); + gridLayout->addWidget(m_ui.valueLabel, 15, col + 0, 1, 1); + gridLayout->addWidget(m_ui.valueWidget, 15, col + 1, 1, 1); + gridLayout->addWidget(m_ui.alphaLabel, 16, col + 0, 1, 1); + gridLayout->addWidget(m_ui.alphaWidget, 16, col + 1, 1, 1); + + if (details) { + if (m_hiddenLayout) { + delete m_hiddenLayout; + m_hiddenLayout = 0; + } + if (m_hiddenWidget) { + delete m_hiddenWidget; + m_hiddenWidget = 0; + } + } +} + +int QtGradientEditorPrivate::extensionWidthHint() const +{ + if (m_details) + return q_ptr->size().width() - m_ui.gradientStopsWidget->size().width(); + + const int space = m_ui.spinBox1->geometry().left() - m_ui.label1->geometry().right(); + + return m_hiddenLayout->minimumSize().width() + space; +} + +void QtGradientEditorPrivate::slotDetailsChanged(bool details) +{ + showDetails(details); +} + +bool QtGradientEditorPrivate::row4Visible() const +{ + if (m_type == QGradient::ConicalGradient) + return false; + return true; +} + +bool QtGradientEditorPrivate::row5Visible() const +{ + if (m_type == QGradient::RadialGradient) + return true; + return false; +} + +void QtGradientEditorPrivate::showDetails(bool details) +{ + if (m_details == details) + return; + + bool blocked = m_ui.detailsButton->signalsBlocked(); + m_ui.detailsButton->blockSignals(true); + m_ui.detailsButton->setChecked(details); + m_ui.detailsButton->blockSignals(blocked); + + bool updates = q_ptr->updatesEnabled(); + q_ptr->setUpdatesEnabled(false); + + if (m_gridLayout) { + m_gridLayout->setEnabled(false); + delete m_gridLayout; + m_gridLayout = 0; + } + + if (!details) { + layoutDetails(details); + } + + emit q_ptr->aboutToShowDetails(details, extensionWidthHint()); + m_details = details; + + m_gridLayout = new QGridLayout(q_ptr); + m_gridLayout->setEnabled(false); + m_gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + m_gridLayout->setContentsMargins(0, 0, 0, 0); + + m_ui.label4->setVisible(row4Visible()); + m_ui.label5->setVisible(row5Visible()); + m_ui.spinBox4->setVisible(row4Visible()); + m_ui.spinBox5->setVisible(row5Visible()); + + setLayout(details); + m_gridLayout->setEnabled(true); + + q_ptr->setUpdatesEnabled(updates); + q_ptr->update(); +} + +void QtGradientEditorPrivate::setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max, double step, int decimals) +{ + bool blocked = spinBox->signalsBlocked(); + spinBox->blockSignals(true); + spinBox->setDecimals(decimals); + spinBox->setMaximum(max); + spinBox->setSingleStep(step); + spinBox->blockSignals(blocked); + QObject::connect(spinBox, SIGNAL(valueChanged(double)), q_ptr, slot); +} + +void QtGradientEditorPrivate::reset() +{ + startLinearXSpinBox = 0; + startLinearYSpinBox = 0; + endLinearXSpinBox = 0; + endLinearYSpinBox = 0; + centralRadialXSpinBox = 0; + centralRadialYSpinBox = 0; + focalRadialXSpinBox = 0; + focalRadialYSpinBox = 0; + radiusRadialSpinBox = 0; + centralConicalXSpinBox = 0; + centralConicalYSpinBox = 0; + angleConicalSpinBox = 0; +} + +void QtGradientEditorPrivate::setType(QGradient::Type type) +{ + if (m_type == type) + return; + + m_type = type; + m_ui.spinBox1->disconnect(SIGNAL(valueChanged(double))); + m_ui.spinBox2->disconnect(SIGNAL(valueChanged(double))); + m_ui.spinBox3->disconnect(SIGNAL(valueChanged(double))); + m_ui.spinBox4->disconnect(SIGNAL(valueChanged(double))); + m_ui.spinBox5->disconnect(SIGNAL(valueChanged(double))); + + reset(); + + bool ena = true; + + if (m_gridLayout) { + ena = m_gridLayout->isEnabled(); + m_gridLayout->setEnabled(false); + } + + bool spreadEnabled = true; + + if (type == QGradient::LinearGradient) { + startLinearXSpinBox = m_ui.spinBox1; + setSpinBox(startLinearXSpinBox, SLOT(slotStartLinearXChanged(double))); + m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Start X", 0, QApplication::UnicodeUTF8)); + + startLinearYSpinBox = m_ui.spinBox2; + setSpinBox(startLinearYSpinBox, SLOT(slotStartLinearYChanged(double))); + m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Start Y", 0, QApplication::UnicodeUTF8)); + + endLinearXSpinBox = m_ui.spinBox3; + setSpinBox(endLinearXSpinBox, SLOT(slotEndLinearXChanged(double))); + m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Final X", 0, QApplication::UnicodeUTF8)); + + endLinearYSpinBox = m_ui.spinBox4; + setSpinBox(endLinearYSpinBox, SLOT(slotEndLinearYChanged(double))); + m_ui.label4->setText(QApplication::translate("QtGradientEditor", "Final Y", 0, QApplication::UnicodeUTF8)); + + setStartLinear(m_ui.gradientWidget->startLinear()); + setEndLinear(m_ui.gradientWidget->endLinear()); + } else if (type == QGradient::RadialGradient) { + centralRadialXSpinBox = m_ui.spinBox1; + setSpinBox(centralRadialXSpinBox, SLOT(slotCentralRadialXChanged(double))); + m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Central X", 0, QApplication::UnicodeUTF8)); + + centralRadialYSpinBox = m_ui.spinBox2; + setSpinBox(centralRadialYSpinBox, SLOT(slotCentralRadialYChanged(double))); + m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Central Y", 0, QApplication::UnicodeUTF8)); + + focalRadialXSpinBox = m_ui.spinBox3; + setSpinBox(focalRadialXSpinBox, SLOT(slotFocalRadialXChanged(double))); + m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Focal X", 0, QApplication::UnicodeUTF8)); + + focalRadialYSpinBox = m_ui.spinBox4; + setSpinBox(focalRadialYSpinBox, SLOT(slotFocalRadialYChanged(double))); + m_ui.label4->setText(QApplication::translate("QtGradientEditor", "Focal Y", 0, QApplication::UnicodeUTF8)); + + radiusRadialSpinBox = m_ui.spinBox5; + setSpinBox(radiusRadialSpinBox, SLOT(slotRadiusRadialChanged(double)), 2.0); + m_ui.label5->setText(QApplication::translate("QtGradientEditor", "Radius", 0, QApplication::UnicodeUTF8)); + + setCentralRadial(m_ui.gradientWidget->centralRadial()); + setFocalRadial(m_ui.gradientWidget->focalRadial()); + setRadiusRadial(m_ui.gradientWidget->radiusRadial()); + } else if (type == QGradient::ConicalGradient) { + centralConicalXSpinBox = m_ui.spinBox1; + setSpinBox(centralConicalXSpinBox, SLOT(slotCentralConicalXChanged(double))); + m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Central X", 0, QApplication::UnicodeUTF8)); + + centralConicalYSpinBox = m_ui.spinBox2; + setSpinBox(centralConicalYSpinBox, SLOT(slotCentralConicalYChanged(double))); + m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Central Y", 0, QApplication::UnicodeUTF8)); + + angleConicalSpinBox = m_ui.spinBox3; + setSpinBox(angleConicalSpinBox, SLOT(slotAngleConicalChanged(double)), 360.0, 1.0, 1); + m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Angle", 0, QApplication::UnicodeUTF8)); + + setCentralConical(m_ui.gradientWidget->centralConical()); + setAngleConical(m_ui.gradientWidget->angleConical()); + + spreadEnabled = false; + } + m_ui.spreadComboBox->setEnabled(spreadEnabled); + m_ui.padButton->setEnabled(spreadEnabled); + m_ui.repeatButton->setEnabled(spreadEnabled); + m_ui.reflectButton->setEnabled(spreadEnabled); + + m_ui.label4->setVisible(row4Visible()); + m_ui.spinBox4->setVisible(row4Visible()); + m_ui.label5->setVisible(row5Visible()); + m_ui.spinBox5->setVisible(row5Visible()); + + if (m_gridLayout) { + m_gridLayout->setEnabled(ena); + } +} + +void QtGradientEditorPrivate::slotGradientStopsChanged(const QGradientStops &stops) +{ + m_ui.gradientWidget->setGradientStops(stops); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotTypeChanged(int idx) +{ + QGradient::Type type = QGradient::NoGradient; + if (idx == 0) + type = QGradient::LinearGradient; + else if (idx == 1) + type = QGradient::RadialGradient; + else if (idx == 2) + type = QGradient::ConicalGradient; + setType(type); + m_ui.typeComboBox->setCurrentIndex(idx); + m_typeGroup->button(idx)->setChecked(true); + m_ui.gradientWidget->setGradientType(type); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotSpreadChanged(int spread) +{ + if (spread == 0) { + m_ui.gradientWidget->setGradientSpread(QGradient::PadSpread); + } else if (spread == 1) { + m_ui.gradientWidget->setGradientSpread(QGradient::RepeatSpread); + } else if (spread == 2) { + m_ui.gradientWidget->setGradientSpread(QGradient::ReflectSpread); + } + m_ui.spreadComboBox->setCurrentIndex(spread); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotStartLinearXChanged(double value) +{ + QPointF point = m_ui.gradientWidget->startLinear(); + point.setX(value); + m_ui.gradientWidget->setStartLinear(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotStartLinearYChanged(double value) +{ + QPointF point = m_ui.gradientWidget->startLinear(); + point.setY(value); + m_ui.gradientWidget->setStartLinear(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotEndLinearXChanged(double value) +{ + QPointF point = m_ui.gradientWidget->endLinear(); + point.setX(value); + m_ui.gradientWidget->setEndLinear(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotEndLinearYChanged(double value) +{ + QPointF point = m_ui.gradientWidget->endLinear(); + point.setY(value); + m_ui.gradientWidget->setEndLinear(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotCentralRadialXChanged(double value) +{ + QPointF point = m_ui.gradientWidget->centralRadial(); + point.setX(value); + m_ui.gradientWidget->setCentralRadial(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotCentralRadialYChanged(double value) +{ + QPointF point = m_ui.gradientWidget->centralRadial(); + point.setY(value); + m_ui.gradientWidget->setCentralRadial(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotFocalRadialXChanged(double value) +{ + QPointF point = m_ui.gradientWidget->focalRadial(); + point.setX(value); + m_ui.gradientWidget->setFocalRadial(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotFocalRadialYChanged(double value) +{ + QPointF point = m_ui.gradientWidget->focalRadial(); + point.setY(value); + m_ui.gradientWidget->setFocalRadial(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotRadiusRadialChanged(double value) +{ + m_ui.gradientWidget->setRadiusRadial(value); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotCentralConicalXChanged(double value) +{ + QPointF point = m_ui.gradientWidget->centralConical(); + point.setX(value); + m_ui.gradientWidget->setCentralConical(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotCentralConicalYChanged(double value) +{ + QPointF point = m_ui.gradientWidget->centralConical(); + point.setY(value); + m_ui.gradientWidget->setCentralConical(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::slotAngleConicalChanged(double value) +{ + m_ui.gradientWidget->setAngleConical(value); + updateGradient(true); +} + +void QtGradientEditorPrivate::startLinearChanged(const QPointF &point) +{ + setStartLinear(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::endLinearChanged(const QPointF &point) +{ + setEndLinear(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::centralRadialChanged(const QPointF &point) +{ + setCentralRadial(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::focalRadialChanged(const QPointF &point) +{ + setFocalRadial(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::radiusRadialChanged(qreal radius) +{ + setRadiusRadial(radius); + updateGradient(true); +} + +void QtGradientEditorPrivate::centralConicalChanged(const QPointF &point) +{ + setCentralConical(point); + updateGradient(true); +} + +void QtGradientEditorPrivate::angleConicalChanged(qreal angle) +{ + setAngleConical(angle); + updateGradient(true); +} + +void QtGradientEditorPrivate::setStartLinear(const QPointF &point) +{ + if (startLinearXSpinBox) + startLinearXSpinBox->setValue(point.x()); + if (startLinearYSpinBox) + startLinearYSpinBox->setValue(point.y()); +} + +void QtGradientEditorPrivate::setEndLinear(const QPointF &point) +{ + if (endLinearXSpinBox) + endLinearXSpinBox->setValue(point.x()); + if (endLinearYSpinBox) + endLinearYSpinBox->setValue(point.y()); +} + +void QtGradientEditorPrivate::setCentralRadial(const QPointF &point) +{ + if (centralRadialXSpinBox) + centralRadialXSpinBox->setValue(point.x()); + if (centralRadialYSpinBox) + centralRadialYSpinBox->setValue(point.y()); +} + +void QtGradientEditorPrivate::setFocalRadial(const QPointF &point) +{ + if (focalRadialXSpinBox) + focalRadialXSpinBox->setValue(point.x()); + if (focalRadialYSpinBox) + focalRadialYSpinBox->setValue(point.y()); +} + +void QtGradientEditorPrivate::setRadiusRadial(qreal radius) +{ + if (radiusRadialSpinBox) + radiusRadialSpinBox->setValue(radius); +} + +void QtGradientEditorPrivate::setCentralConical(const QPointF &point) +{ + if (centralConicalXSpinBox) + centralConicalXSpinBox->setValue(point.x()); + if (centralConicalYSpinBox) + centralConicalYSpinBox->setValue(point.y()); +} + +void QtGradientEditorPrivate::setAngleConical(qreal angle) +{ + if (angleConicalSpinBox) + angleConicalSpinBox->setValue(angle); +} + +QtGradientEditor::QtGradientEditor(QWidget *parent) + : QWidget(parent) +{ + d_ptr = new QtGradientEditorPrivate(); + d_ptr->q_ptr = this; + d_ptr->m_type = QGradient::RadialGradient; + d_ptr->m_ui.setupUi(this); + d_ptr->m_gridLayout = 0; + d_ptr->m_hiddenLayout = 0; + d_ptr->m_hiddenWidget = 0; + bool detailsDefault = false; + d_ptr->m_details = !detailsDefault; + d_ptr->m_detailsButtonVisible = true; + bool checkeredDefault = true; + d_ptr->m_backgroundCheckered = !checkeredDefault; + d_ptr->m_gradientStopsController = new QtGradientStopsController(this); + d_ptr->m_gradientStopsController->setUi(&d_ptr->m_ui); + d_ptr->reset(); + d_ptr->setType(QGradient::LinearGradient); + d_ptr->m_combos = true; + d_ptr->setCombos(!d_ptr->m_combos); + + d_ptr->showDetails(detailsDefault); + setBackgroundCheckered(checkeredDefault); + + d_ptr->setStartLinear(QPointF(0, 0)); + d_ptr->setEndLinear(QPointF(1, 1)); + d_ptr->setCentralRadial(QPointF(0.5, 0.5)); + d_ptr->setFocalRadial(QPointF(0.5, 0.5)); + d_ptr->setRadiusRadial(0.5); + d_ptr->setCentralConical(QPointF(0.5, 0.5)); + d_ptr->setAngleConical(0); + + QIcon icon; + icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowRight), QIcon::Normal, QIcon::Off); + icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowLeft), QIcon::Normal, QIcon::On); + d_ptr->m_ui.detailsButton->setIcon(icon); + + connect(d_ptr->m_ui.detailsButton, SIGNAL(clicked(bool)), this, SLOT(slotDetailsChanged(bool))); + connect(d_ptr->m_gradientStopsController, SIGNAL(gradientStopsChanged(const QGradientStops &)), + this, SLOT(slotGradientStopsChanged(const QGradientStops &))); + + QIcon iconLinear(QLatin1String(":/trolltech/qtgradienteditor/images/typelinear.png")); + QIcon iconRadial(QLatin1String(":/trolltech/qtgradienteditor/images/typeradial.png")); + QIcon iconConical(QLatin1String(":/trolltech/qtgradienteditor/images/typeconical.png")); + + d_ptr->m_ui.typeComboBox->addItem(iconLinear, tr("Linear")); + d_ptr->m_ui.typeComboBox->addItem(iconRadial, tr("Radial")); + d_ptr->m_ui.typeComboBox->addItem(iconConical, tr("Conical")); + + d_ptr->m_ui.linearButton->setIcon(iconLinear); + d_ptr->m_ui.radialButton->setIcon(iconRadial); + d_ptr->m_ui.conicalButton->setIcon(iconConical); + + d_ptr->m_typeGroup = new QButtonGroup(this); + d_ptr->m_typeGroup->addButton(d_ptr->m_ui.linearButton, 0); + d_ptr->m_typeGroup->addButton(d_ptr->m_ui.radialButton, 1); + d_ptr->m_typeGroup->addButton(d_ptr->m_ui.conicalButton, 2); + + connect(d_ptr->m_typeGroup, SIGNAL(buttonClicked(int)), + this, SLOT(slotTypeChanged(int))); + connect(d_ptr->m_ui.typeComboBox, SIGNAL(activated(int)), + this, SLOT(slotTypeChanged(int))); + + QIcon iconPad(QLatin1String(":/trolltech/qtgradienteditor/images/spreadpad.png")); + QIcon iconRepeat(QLatin1String(":/trolltech/qtgradienteditor/images/spreadrepeat.png")); + QIcon iconReflect(QLatin1String(":/trolltech/qtgradienteditor/images/spreadreflect.png")); + + d_ptr->m_ui.spreadComboBox->addItem(iconPad, tr("Pad")); + d_ptr->m_ui.spreadComboBox->addItem(iconRepeat, tr("Repeat")); + d_ptr->m_ui.spreadComboBox->addItem(iconReflect, tr("Reflect")); + + d_ptr->m_ui.padButton->setIcon(iconPad); + d_ptr->m_ui.repeatButton->setIcon(iconRepeat); + d_ptr->m_ui.reflectButton->setIcon(iconReflect); + + d_ptr->m_spreadGroup = new QButtonGroup(this); + d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.padButton, 0); + d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.repeatButton, 1); + d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.reflectButton, 2); + connect(d_ptr->m_spreadGroup, SIGNAL(buttonClicked(int)), + this, SLOT(slotSpreadChanged(int))); + connect(d_ptr->m_ui.spreadComboBox, SIGNAL(activated(int)), + this, SLOT(slotSpreadChanged(int))); + + connect(d_ptr->m_ui.gradientWidget, SIGNAL(startLinearChanged(const QPointF &)), + this, SLOT(startLinearChanged(const QPointF &))); + connect(d_ptr->m_ui.gradientWidget, SIGNAL(endLinearChanged(const QPointF &)), + this, SLOT(endLinearChanged(const QPointF &))); + connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralRadialChanged(const QPointF &)), + this, SLOT(centralRadialChanged(const QPointF &))); + connect(d_ptr->m_ui.gradientWidget, SIGNAL(focalRadialChanged(const QPointF &)), + this, SLOT(focalRadialChanged(const QPointF &))); + connect(d_ptr->m_ui.gradientWidget, SIGNAL(radiusRadialChanged(qreal)), + this, SLOT(radiusRadialChanged(qreal))); + connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralConicalChanged(const QPointF &)), + this, SLOT(centralConicalChanged(const QPointF &))); + connect(d_ptr->m_ui.gradientWidget, SIGNAL(angleConicalChanged(qreal)), + this, SLOT(angleConicalChanged(qreal))); + + QGradientStops stops = gradient().stops(); + d_ptr->m_gradientStopsController->setGradientStops(stops); + d_ptr->m_ui.gradientWidget->setGradientStops(stops); +} + +QtGradientEditor::~QtGradientEditor() +{ + if (d_ptr->m_hiddenWidget) + delete d_ptr->m_hiddenWidget; + delete d_ptr; +} + +void QtGradientEditor::setGradient(const QGradient &grad) +{ + if (grad == gradient()) + return; + + QGradient::Type type = grad.type(); + int idx = 0; + switch (type) { + case QGradient::LinearGradient: idx = 0; break; + case QGradient::RadialGradient: idx = 1; break; + case QGradient::ConicalGradient: idx = 2; break; + default: return; + } + d_ptr->setType(type); + d_ptr->m_ui.typeComboBox->setCurrentIndex(idx); + d_ptr->m_ui.gradientWidget->setGradientType(type); + d_ptr->m_typeGroup->button(idx)->setChecked(true); + + QGradient::Spread spread = grad.spread(); + switch (spread) { + case QGradient::PadSpread: idx = 0; break; + case QGradient::RepeatSpread: idx = 1; break; + case QGradient::ReflectSpread: idx = 2; break; + default: idx = 0; break; + } + d_ptr->m_ui.spreadComboBox->setCurrentIndex(idx); + d_ptr->m_ui.gradientWidget->setGradientSpread(spread); + d_ptr->m_spreadGroup->button(idx)->setChecked(true); + + if (type == QGradient::LinearGradient) { + QLinearGradient *gr = (QLinearGradient *)(&grad); + d_ptr->setStartLinear(gr->start()); + d_ptr->setEndLinear(gr->finalStop()); + d_ptr->m_ui.gradientWidget->setStartLinear(gr->start()); + d_ptr->m_ui.gradientWidget->setEndLinear(gr->finalStop()); + } else if (type == QGradient::RadialGradient) { + QRadialGradient *gr = (QRadialGradient *)(&grad); + d_ptr->setCentralRadial(gr->center()); + d_ptr->setFocalRadial(gr->focalPoint()); + d_ptr->setRadiusRadial(gr->radius()); + d_ptr->m_ui.gradientWidget->setCentralRadial(gr->center()); + d_ptr->m_ui.gradientWidget->setFocalRadial(gr->focalPoint()); + d_ptr->m_ui.gradientWidget->setRadiusRadial(gr->radius()); + } else if (type == QGradient::ConicalGradient) { + QConicalGradient *gr = (QConicalGradient *)(&grad); + d_ptr->setCentralConical(gr->center()); + d_ptr->setAngleConical(gr->angle()); + d_ptr->m_ui.gradientWidget->setCentralConical(gr->center()); + d_ptr->m_ui.gradientWidget->setAngleConical(gr->angle()); + } + + d_ptr->m_gradientStopsController->setGradientStops(grad.stops()); + d_ptr->m_ui.gradientWidget->setGradientStops(grad.stops()); + d_ptr->updateGradient(false); +} + +QGradient QtGradientEditor::gradient() const +{ + return d_ptr->m_gradient; +} + +bool QtGradientEditor::isBackgroundCheckered() const +{ + return d_ptr->m_backgroundCheckered; +} + +void QtGradientEditor::setBackgroundCheckered(bool checkered) +{ + if (d_ptr->m_backgroundCheckered == checkered) + return; + + d_ptr->m_backgroundCheckered = checkered; + d_ptr->m_ui.hueColorLine->setBackgroundCheckered(checkered); + d_ptr->m_ui.saturationColorLine->setBackgroundCheckered(checkered); + d_ptr->m_ui.valueColorLine->setBackgroundCheckered(checkered); + d_ptr->m_ui.alphaColorLine->setBackgroundCheckered(checkered); + d_ptr->m_ui.gradientWidget->setBackgroundCheckered(checkered); + d_ptr->m_ui.gradientStopsWidget->setBackgroundCheckered(checkered); + d_ptr->m_ui.colorButton->setBackgroundCheckered(checkered); +} + +bool QtGradientEditor::detailsVisible() const +{ + return d_ptr->m_details; +} + +void QtGradientEditor::setDetailsVisible(bool visible) +{ + d_ptr->showDetails(visible); +} + +bool QtGradientEditor::isDetailsButtonVisible() const +{ + return d_ptr->m_detailsButtonVisible; +} + +void QtGradientEditor::setDetailsButtonVisible(bool visible) +{ + if (d_ptr->m_detailsButtonVisible == visible) + return; + + d_ptr->m_detailsButtonVisible = visible; + d_ptr->m_ui.detailsButton->setVisible(visible); +} + +QColor::Spec QtGradientEditor::spec() const +{ + return d_ptr->m_gradientStopsController->spec(); +} + +void QtGradientEditor::setSpec(QColor::Spec spec) +{ + d_ptr->m_gradientStopsController->setSpec(spec); +} + +QT_END_NAMESPACE + +#include "moc_qtgradienteditor.cpp" diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.h b/tools/shared/qtgradienteditor/qtgradienteditor.h new file mode 100644 index 0000000..9974065 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradienteditor.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTGRADIENTEDITOR_H +#define QTGRADIENTEDITOR_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QtGradientEditor : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient) + Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered) + Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible) + Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible) +public: + QtGradientEditor(QWidget *parent = 0); + ~QtGradientEditor(); + + void setGradient(const QGradient &gradient); + QGradient gradient() const; + + bool isBackgroundCheckered() const; + void setBackgroundCheckered(bool checkered); + + bool detailsVisible() const; + void setDetailsVisible(bool visible); + + bool isDetailsButtonVisible() const; + void setDetailsButtonVisible(bool visible); + + QColor::Spec spec() const; + void setSpec(QColor::Spec spec); + +signals: + + void gradientChanged(const QGradient &gradient); + void aboutToShowDetails(bool details, int extenstionWidthHint); + +private: + class QtGradientEditorPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtGradientEditor) + Q_DISABLE_COPY(QtGradientEditor) + Q_PRIVATE_SLOT(d_func(), void slotGradientStopsChanged(const QGradientStops &stops)) + Q_PRIVATE_SLOT(d_func(), void slotTypeChanged(int type)) + Q_PRIVATE_SLOT(d_func(), void slotSpreadChanged(int type)) + Q_PRIVATE_SLOT(d_func(), void slotStartLinearXChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotStartLinearYChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotEndLinearXChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotEndLinearYChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotCentralRadialXChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotCentralRadialYChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotFocalRadialXChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotFocalRadialYChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotRadiusRadialChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotCentralConicalXChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotCentralConicalYChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotAngleConicalChanged(double value)) + Q_PRIVATE_SLOT(d_func(), void slotDetailsChanged(bool details)) + Q_PRIVATE_SLOT(d_func(), void startLinearChanged(const QPointF &)) + Q_PRIVATE_SLOT(d_func(), void endLinearChanged(const QPointF &)) + Q_PRIVATE_SLOT(d_func(), void centralRadialChanged(const QPointF &)) + Q_PRIVATE_SLOT(d_func(), void focalRadialChanged(const QPointF &)) + Q_PRIVATE_SLOT(d_func(), void radiusRadialChanged(qreal)) + Q_PRIVATE_SLOT(d_func(), void centralConicalChanged(const QPointF &)) + Q_PRIVATE_SLOT(d_func(), void angleConicalChanged(qreal)) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.pri b/tools/shared/qtgradienteditor/qtgradienteditor.pri new file mode 100644 index 0000000..4cf059e --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradienteditor.pri @@ -0,0 +1,33 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +FORMS += $$PWD/qtgradienteditor.ui \ + $$PWD/qtgradientdialog.ui \ + $$PWD/qtgradientview.ui \ + $$PWD/qtgradientviewdialog.ui +SOURCES += $$PWD/qtgradientstopsmodel.cpp \ + $$PWD/qtgradientstopswidget.cpp \ + $$PWD/qtgradientstopscontroller.cpp \ + $$PWD/qtgradientwidget.cpp \ + $$PWD/qtgradienteditor.cpp \ + $$PWD/qtgradientdialog.cpp \ + $$PWD/qtcolorbutton.cpp \ + $$PWD/qtcolorline.cpp \ + $$PWD/qtgradientview.cpp \ + $$PWD/qtgradientviewdialog.cpp \ + $$PWD/qtgradientmanager.cpp \ + $$PWD/qtgradientutils.cpp +HEADERS += $$PWD/qtgradientstopsmodel.h \ + $$PWD/qtgradientstopswidget.h \ + $$PWD/qtgradientstopscontroller.h \ + $$PWD/qtgradientwidget.h \ + $$PWD/qtgradienteditor.h \ + $$PWD/qtgradientdialog.h \ + $$PWD/qtcolorbutton.h \ + $$PWD/qtcolorline.h \ + $$PWD/qtgradientview.h \ + $$PWD/qtgradientviewdialog.h \ + $$PWD/qtgradientmanager.h \ + $$PWD/qtgradientutils.h +RESOURCES += $$PWD/qtgradienteditor.qrc + +QT += xml diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.qrc b/tools/shared/qtgradienteditor/qtgradienteditor.qrc new file mode 100644 index 0000000..cce7ba6 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradienteditor.qrc @@ -0,0 +1,18 @@ +<!DOCTYPE RCC><RCC version="1.0"> + <qresource prefix="/trolltech/qtgradienteditor"> + <file>images/edit.png</file> + <file>images/zoomin.png</file> + <file>images/zoomout.png</file> + <file>images/up.png</file> + <file>images/down.png</file> + <file>images/plus.png</file> + <file>images/minus.png</file> + <file>images/editdelete.png</file> + <file>images/spreadpad.png</file> + <file>images/spreadrepeat.png</file> + <file>images/spreadreflect.png</file> + <file>images/typelinear.png</file> + <file>images/typeradial.png</file> + <file>images/typeconical.png</file> + </qresource> +</RCC> diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.ui b/tools/shared/qtgradienteditor/qtgradienteditor.ui new file mode 100644 index 0000000..4d103e3 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradienteditor.ui @@ -0,0 +1,1377 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>QtGradientEditor</class> + <widget class="QWidget" name="QtGradientEditor" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>364</width> + <height>518</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <widget class="QFrame" name="frame" > + <property name="geometry" > + <rect> + <x>10</x> + <y>69</y> + <width>193</width> + <height>150</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Expanding" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QtGradientWidget" native="1" name="gradientWidget" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Expanding" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Gradient Editor</string> + </property> + <property name="whatsThis" > + <string>This area shows a preview of the gradient being edited. It also allows you to edit parameters specific to the gradient's type such as start and final point, radius, etc. by drag & drop.</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="label1" > + <property name="geometry" > + <rect> + <x>209</x> + <y>69</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>1</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="spinBox1" > + <property name="geometry" > + <rect> + <x>279</x> + <y>69</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="maximum" > + <double>1.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + <widget class="QLabel" name="label2" > + <property name="geometry" > + <rect> + <x>209</x> + <y>99</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>2</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="spinBox2" > + <property name="geometry" > + <rect> + <x>279</x> + <y>99</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="maximum" > + <double>1.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + <widget class="QLabel" name="label3" > + <property name="geometry" > + <rect> + <x>209</x> + <y>129</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>3</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="spinBox3" > + <property name="geometry" > + <rect> + <x>279</x> + <y>129</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="maximum" > + <double>1.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + <widget class="QLabel" name="label4" > + <property name="geometry" > + <rect> + <x>209</x> + <y>159</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>4</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="spinBox4" > + <property name="geometry" > + <rect> + <x>279</x> + <y>159</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="maximum" > + <double>1.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + <widget class="QLabel" name="label5" > + <property name="geometry" > + <rect> + <x>209</x> + <y>189</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>5</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="spinBox5" > + <property name="geometry" > + <rect> + <x>279</x> + <y>189</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="maximum" > + <double>1.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + <widget class="QtGradientStopsWidget" native="1" name="gradientStopsWidget" > + <property name="geometry" > + <rect> + <x>10</x> + <y>225</y> + <width>193</width> + <height>67</height> + </rect> + </property> + <property name="toolTip" > + <string>Gradient Stops Editor</string> + </property> + <property name="whatsThis" > + <string>This area allows you to edit gradient stops. Double click on the existing stop handle to duplicate it. Double click outside of the existing stop handles to create a new stop. Drag & drop the handle to reposition it. Use right mouse button to popup context menu with extra actions.</string> + </property> + </widget> + <widget class="QLabel" name="zoomLabel" > + <property name="geometry" > + <rect> + <x>209</x> + <y>231</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>Zoom</string> + </property> + </widget> + <widget class="QToolButton" name="zoomAllButton" > + <property name="geometry" > + <rect> + <x>279</x> + <y>260</y> + <width>72</width> + <height>26</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Reset Zoom</string> + </property> + <property name="text" > + <string>Reset Zoom</string> + </property> + </widget> + <widget class="QLabel" name="positionLabel" > + <property name="geometry" > + <rect> + <x>209</x> + <y>304</y> + <width>64</width> + <height>23</height> + </rect> + </property> + <property name="text" > + <string>Position</string> + </property> + </widget> + <widget class="QLabel" name="hLabel" > + <property name="geometry" > + <rect> + <x>10</x> + <y>335</y> + <width>32</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Hue</string> + </property> + <property name="text" > + <string>H</string> + </property> + </widget> + <widget class="QFrame" name="frame_2" > + <property name="geometry" > + <rect> + <x>48</x> + <y>333</y> + <width>155</width> + <height>23</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Ignored" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QtColorLine" native="1" name="hueColorLine" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Hue</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="hueLabel" > + <property name="geometry" > + <rect> + <x>209</x> + <y>335</y> + <width>64</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Hue</string> + </property> + </widget> + <widget class="QLabel" name="sLabel" > + <property name="geometry" > + <rect> + <x>10</x> + <y>364</y> + <width>32</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Saturation</string> + </property> + <property name="text" > + <string>S</string> + </property> + </widget> + <widget class="QFrame" name="frame_5" > + <property name="geometry" > + <rect> + <x>48</x> + <y>362</y> + <width>155</width> + <height>23</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Ignored" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QtColorLine" native="1" name="saturationColorLine" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Saturation</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="saturationLabel" > + <property name="geometry" > + <rect> + <x>209</x> + <y>364</y> + <width>64</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Sat</string> + </property> + </widget> + <widget class="QLabel" name="vLabel" > + <property name="geometry" > + <rect> + <x>10</x> + <y>393</y> + <width>32</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Value</string> + </property> + <property name="text" > + <string>V</string> + </property> + </widget> + <widget class="QFrame" name="frame_3" > + <property name="geometry" > + <rect> + <x>48</x> + <y>391</y> + <width>155</width> + <height>23</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Ignored" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QtColorLine" native="1" name="valueColorLine" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Value</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="valueLabel" > + <property name="geometry" > + <rect> + <x>209</x> + <y>393</y> + <width>64</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Val</string> + </property> + </widget> + <widget class="QLabel" name="aLabel" > + <property name="geometry" > + <rect> + <x>10</x> + <y>422</y> + <width>32</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Alpha</string> + </property> + <property name="text" > + <string>A</string> + </property> + </widget> + <widget class="QFrame" name="frame_4" > + <property name="geometry" > + <rect> + <x>48</x> + <y>420</y> + <width>155</width> + <height>23</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Ignored" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QtColorLine" native="1" name="alphaColorLine" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Alpha</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="alphaLabel" > + <property name="geometry" > + <rect> + <x>209</x> + <y>422</y> + <width>64</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Alpha</string> + </property> + </widget> + <widget class="QComboBox" name="typeComboBox" > + <property name="geometry" > + <rect> + <x>10</x> + <y>40</y> + <width>79</width> + <height>22</height> + </rect> + </property> + <property name="toolTip" > + <string>Type</string> + </property> + </widget> + <widget class="QComboBox" name="spreadComboBox" > + <property name="geometry" > + <rect> + <x>96</x> + <y>40</y> + <width>72</width> + <height>22</height> + </rect> + </property> + <property name="toolTip" > + <string>Spread</string> + </property> + </widget> + <widget class="QLabel" name="colorLabel" > + <property name="geometry" > + <rect> + <x>10</x> + <y>298</y> + <width>32</width> + <height>29</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Color</string> + </property> + </widget> + <widget class="QtColorButton" name="colorButton" > + <property name="geometry" > + <rect> + <x>48</x> + <y>300</y> + <width>26</width> + <height>25</height> + </rect> + </property> + <property name="toolTip" > + <string>Current stop's color</string> + </property> + <property name="text" > + <string/> + </property> + </widget> + <widget class="QRadioButton" name="hsvRadioButton" > + <property name="geometry" > + <rect> + <x>80</x> + <y>301</y> + <width>49</width> + <height>23</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Show HSV specification</string> + </property> + <property name="text" > + <string>HSV</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" name="rgbRadioButton" > + <property name="geometry" > + <rect> + <x>135</x> + <y>301</y> + <width>49</width> + <height>23</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Show RGB specification</string> + </property> + <property name="text" > + <string>RGB</string> + </property> + </widget> + <widget class="QWidget" native="1" name="positionWidget" > + <property name="geometry" > + <rect> + <x>279</x> + <y>304</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QDoubleSpinBox" name="positionSpinBox" > + <property name="toolTip" > + <string>Current stop's position</string> + </property> + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="minimum" > + <double>0.000000000000000</double> + </property> + <property name="maximum" > + <double>1.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + <property name="value" > + <double>0.000000000000000</double> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="hueWidget" > + <property name="geometry" > + <rect> + <x>279</x> + <y>333</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QSpinBox" name="hueSpinBox" > + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="maximum" > + <number>359</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="saturationWidget" > + <property name="geometry" > + <rect> + <x>279</x> + <y>362</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QSpinBox" name="saturationSpinBox" > + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="maximum" > + <number>255</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="valueWidget" > + <property name="geometry" > + <rect> + <x>279</x> + <y>391</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QSpinBox" name="valueSpinBox" > + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="maximum" > + <number>255</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="alphaWidget" > + <property name="geometry" > + <rect> + <x>279</x> + <y>420</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QSpinBox" name="alphaSpinBox" > + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="maximum" > + <number>255</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="zoomWidget" > + <property name="geometry" > + <rect> + <x>279</x> + <y>231</y> + <width>73</width> + <height>23</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QSpinBox" name="zoomSpinBox" > + <property name="keyboardTracking" > + <bool>false</bool> + </property> + <property name="suffix" > + <string>%</string> + </property> + <property name="minimum" > + <number>100</number> + </property> + <property name="maximum" > + <number>10000</number> + </property> + <property name="singleStep" > + <number>100</number> + </property> + <property name="value" > + <number>100</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="line1Widget" > + <property name="geometry" > + <rect> + <x>209</x> + <y>219</y> + <width>143</width> + <height>16</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="Line" name="line1" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="line2Widget" > + <property name="geometry" > + <rect> + <x>209</x> + <y>292</y> + <width>143</width> + <height>16</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="Line" name="line2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" native="1" name="zoomButtonsWidget" > + <property name="geometry" > + <rect> + <x>209</x> + <y>260</y> + <width>64</width> + <height>26</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Maximum" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QToolButton" name="zoomInButton" > + <property name="toolTip" > + <string>Zoom In</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="zoomOutButton" > + <property name="toolTip" > + <string>Zoom Out</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QToolButton" name="detailsButton" > + <property name="geometry" > + <rect> + <x>176</x> + <y>40</y> + <width>25</width> + <height>22</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Ignored" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip" > + <string>Toggle details extension</string> + </property> + <property name="text" > + <string>></string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + <widget class="QToolButton" name="linearButton" > + <property name="geometry" > + <rect> + <x>10</x> + <y>10</y> + <width>30</width> + <height>26</height> + </rect> + </property> + <property name="toolTip" > + <string>Linear Type</string> + </property> + <property name="text" > + <string>...</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + <widget class="QToolButton" name="radialButton" > + <property name="geometry" > + <rect> + <x>40</x> + <y>10</y> + <width>30</width> + <height>26</height> + </rect> + </property> + <property name="toolTip" > + <string>Radial Type</string> + </property> + <property name="text" > + <string>...</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + <widget class="QToolButton" name="conicalButton" > + <property name="geometry" > + <rect> + <x>70</x> + <y>10</y> + <width>30</width> + <height>26</height> + </rect> + </property> + <property name="toolTip" > + <string>Conical Type</string> + </property> + <property name="text" > + <string>...</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + <widget class="QToolButton" name="padButton" > + <property name="geometry" > + <rect> + <x>110</x> + <y>10</y> + <width>30</width> + <height>26</height> + </rect> + </property> + <property name="toolTip" > + <string>Pad Spread</string> + </property> + <property name="text" > + <string>...</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + <widget class="QToolButton" name="repeatButton" > + <property name="geometry" > + <rect> + <x>140</x> + <y>10</y> + <width>30</width> + <height>26</height> + </rect> + </property> + <property name="toolTip" > + <string>Repeat Spread</string> + </property> + <property name="text" > + <string>...</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + <widget class="QToolButton" name="reflectButton" > + <property name="geometry" > + <rect> + <x>170</x> + <y>10</y> + <width>30</width> + <height>26</height> + </rect> + </property> + <property name="toolTip" > + <string>Reflect Spread</string> + </property> + <property name="text" > + <string>...</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + </widget> + <customwidgets> + <customwidget> + <class>QtColorButton</class> + <extends>QToolButton</extends> + <header>qtcolorbutton.h</header> + </customwidget> + <customwidget> + <class>QtColorLine</class> + <extends>QWidget</extends> + <header>qtcolorline.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>QtGradientStopsWidget</class> + <extends>QWidget</extends> + <header>qtgradientstopswidget.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>QtGradientWidget</class> + <extends>QWidget</extends> + <header>qtgradientwidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>typeComboBox</tabstop> + <tabstop>spreadComboBox</tabstop> + <tabstop>detailsButton</tabstop> + <tabstop>spinBox1</tabstop> + <tabstop>spinBox2</tabstop> + <tabstop>spinBox3</tabstop> + <tabstop>spinBox4</tabstop> + <tabstop>spinBox5</tabstop> + <tabstop>zoomSpinBox</tabstop> + <tabstop>zoomInButton</tabstop> + <tabstop>zoomOutButton</tabstop> + <tabstop>zoomAllButton</tabstop> + <tabstop>colorButton</tabstop> + <tabstop>hsvRadioButton</tabstop> + <tabstop>rgbRadioButton</tabstop> + <tabstop>positionSpinBox</tabstop> + <tabstop>hueSpinBox</tabstop> + <tabstop>saturationSpinBox</tabstop> + <tabstop>valueSpinBox</tabstop> + <tabstop>alphaSpinBox</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/tools/shared/qtgradienteditor/qtgradientmanager.cpp b/tools/shared/qtgradienteditor/qtgradientmanager.cpp new file mode 100644 index 0000000..51b5d96 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientmanager.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientmanager.h" +#include <QtGui/QPixmap> +#include <QtCore/QMetaEnum> + +QT_BEGIN_NAMESPACE + +QtGradientManager::QtGradientManager(QObject *parent) + : QObject(parent) +{ +} + +QMap<QString, QGradient> QtGradientManager::gradients() const +{ + return m_idToGradient; +} + +QString QtGradientManager::uniqueId(const QString &id) const +{ + if (!m_idToGradient.contains(id)) + return id; + + QString base = id; + while (base.count() > 0 && base.at(base.count() - 1).isDigit()) + base = base.left(base.count() - 1); + QString newId = base; + int counter = 0; + while (m_idToGradient.contains(newId)) { + ++counter; + newId = base + QString::number(counter); + } + return newId; +} + +QString QtGradientManager::addGradient(const QString &id, const QGradient &gradient) +{ + QString newId = uniqueId(id); + + m_idToGradient[newId] = gradient; + + emit gradientAdded(newId, gradient); + + return newId; +} + +void QtGradientManager::removeGradient(const QString &id) +{ + if (!m_idToGradient.contains(id)) + return; + + emit gradientRemoved(id); + + m_idToGradient.remove(id); +} + +void QtGradientManager::renameGradient(const QString &id, const QString &newId) +{ + if (!m_idToGradient.contains(id)) + return; + + if (newId == id) + return; + + QString changedId = uniqueId(newId); + QGradient gradient = m_idToGradient.value(id); + + emit gradientRenamed(id, changedId); + + m_idToGradient.remove(id); + m_idToGradient[changedId] = gradient; +} + +void QtGradientManager::changeGradient(const QString &id, const QGradient &newGradient) +{ + if (!m_idToGradient.contains(id)) + return; + + if (m_idToGradient.value(id) == newGradient) + return; + + emit gradientChanged(id, newGradient); + + m_idToGradient[id] = newGradient; +} + +void QtGradientManager::clear() +{ + QMap<QString, QGradient> grads = gradients(); + QMapIterator<QString, QGradient> itGrad(grads); + while (itGrad.hasNext()) { + removeGradient(itGrad.next().key()); + } +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtgradientmanager.h b/tools/shared/qtgradienteditor/qtgradientmanager.h new file mode 100644 index 0000000..ff9ebf7 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientmanager.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRADIENTMANAGER_H +#define GRADIENTMANAGER_H + +#include <QtCore/QObject> +#include <QtCore/QMap> +#include <QtCore/QSize> +#include <QtXml/QDomDocument> +#include <QtXml/QDomElement> +#include <QtGui/QGradient> + +QT_BEGIN_NAMESPACE + +class QGradient; +class QPixmap; +class QColor; + +class QtGradientManager : public QObject +{ + Q_OBJECT +public: + QtGradientManager(QObject *parent = 0); + + QMap<QString, QGradient> gradients() const; + + QString uniqueId(const QString &id) const; + +public slots: + + QString addGradient(const QString &id, const QGradient &gradient); + void renameGradient(const QString &id, const QString &newId); + void changeGradient(const QString &id, const QGradient &newGradient); + void removeGradient(const QString &id); + + //utils + void clear(); + +signals: + + void gradientAdded(const QString &id, const QGradient &gradient); + void gradientRenamed(const QString &id, const QString &newId); + void gradientChanged(const QString &id, const QGradient &newGradient); + void gradientRemoved(const QString &id); + +private: + + QMap<QString, QGradient> m_idToGradient; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp b/tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp new file mode 100644 index 0000000..c9ef03b --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp @@ -0,0 +1,726 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientstopscontroller.h" +#include "ui_qtgradienteditor.h" +#include "qtgradientstopsmodel.h" + +#include <QtCore/QTimer> + +QT_BEGIN_NAMESPACE + +class QtGradientStopsControllerPrivate +{ + QtGradientStopsController *q_ptr; + Q_DECLARE_PUBLIC(QtGradientStopsController) +public: + typedef QMap<qreal, QColor> PositionColorMap; + typedef QMap<qreal, QtGradientStop *> PositionStopMap; + + void slotHsvClicked(); + void slotRgbClicked(); + + void slotCurrentStopChanged(QtGradientStop *stop); + void slotStopMoved(QtGradientStop *stop, qreal newPos); + void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2); + void slotStopChanged(QtGradientStop *stop, const QColor &newColor); + void slotStopSelected(QtGradientStop *stop, bool selected); + void slotStopAdded(QtGradientStop *stop); + void slotStopRemoved(QtGradientStop *stop); + void slotUpdatePositionSpinBox(); + + void slotChangeColor(const QColor &color); + void slotChangeHue(const QColor &color); + void slotChangeSaturation(const QColor &color); + void slotChangeValue(const QColor &color); + void slotChangeAlpha(const QColor &color); + void slotChangeHue(int color); + void slotChangeSaturation(int color); + void slotChangeValue(int color); + void slotChangeAlpha(int color); + void slotChangePosition(double value); + + void slotChangeZoom(int value); + void slotZoomIn(); + void slotZoomOut(); + void slotZoomAll(); + void slotZoomChanged(double zoom); + + void enableCurrent(bool enable); + void setColorSpinBoxes(const QColor &color); + PositionColorMap stopsData(const PositionStopMap &stops) const; + QGradientStops makeGradientStops(const PositionColorMap &data) const; + void updateZoom(double zoom); + + QtGradientStopsModel *m_model; + QColor::Spec m_spec; + + Ui::QtGradientEditor *m_ui; +}; + +void QtGradientStopsControllerPrivate::enableCurrent(bool enable) +{ + m_ui->positionLabel->setEnabled(enable); + m_ui->colorLabel->setEnabled(enable); + m_ui->hLabel->setEnabled(enable); + m_ui->sLabel->setEnabled(enable); + m_ui->vLabel->setEnabled(enable); + m_ui->aLabel->setEnabled(enable); + m_ui->hueLabel->setEnabled(enable); + m_ui->saturationLabel->setEnabled(enable); + m_ui->valueLabel->setEnabled(enable); + m_ui->alphaLabel->setEnabled(enable); + + m_ui->positionSpinBox->setEnabled(enable); + m_ui->colorButton->setEnabled(enable); + + m_ui->hueColorLine->setEnabled(enable); + m_ui->saturationColorLine->setEnabled(enable); + m_ui->valueColorLine->setEnabled(enable); + m_ui->alphaColorLine->setEnabled(enable); + + m_ui->hueSpinBox->setEnabled(enable); + m_ui->saturationSpinBox->setEnabled(enable); + m_ui->valueSpinBox->setEnabled(enable); + m_ui->alphaSpinBox->setEnabled(enable); +} + +QtGradientStopsControllerPrivate::PositionColorMap QtGradientStopsControllerPrivate::stopsData(const PositionStopMap &stops) const +{ + PositionColorMap data; + PositionStopMap::ConstIterator itStop = stops.constBegin(); + while (itStop != stops.constEnd()) { + QtGradientStop *stop = itStop.value(); + data[stop->position()] = stop->color(); + + ++itStop; + } + return data; +} + +QGradientStops QtGradientStopsControllerPrivate::makeGradientStops(const PositionColorMap &data) const +{ + QGradientStops stops; + PositionColorMap::ConstIterator itData = data.constBegin(); + while (itData != data.constEnd()) { + stops << QPair<qreal, QColor>(itData.key(), itData.value()); + + ++itData; + } + return stops; +} + +void QtGradientStopsControllerPrivate::updateZoom(double zoom) +{ + m_ui->gradientStopsWidget->setZoom(zoom); + m_ui->zoomSpinBox->blockSignals(true); + m_ui->zoomSpinBox->setValue(qRound(zoom * 100)); + m_ui->zoomSpinBox->blockSignals(false); + bool zoomInEnabled = true; + bool zoomOutEnabled = true; + bool zoomAllEnabled = true; + if (zoom <= 1) { + zoomAllEnabled = false; + zoomOutEnabled = false; + } else if (zoom >= 100) { + zoomInEnabled = false; + } + m_ui->zoomInButton->setEnabled(zoomInEnabled); + m_ui->zoomOutButton->setEnabled(zoomOutEnabled); + m_ui->zoomAllButton->setEnabled(zoomAllEnabled); +} + +void QtGradientStopsControllerPrivate::slotHsvClicked() +{ + QString h = QApplication::translate("qdesigner_internal::QtGradientStopsController", "H", 0, QApplication::UnicodeUTF8); + QString s = QApplication::translate("qdesigner_internal::QtGradientStopsController", "S", 0, QApplication::UnicodeUTF8); + QString v = QApplication::translate("qdesigner_internal::QtGradientStopsController", "V", 0, QApplication::UnicodeUTF8); + + m_ui->hLabel->setText(h); + m_ui->sLabel->setText(s); + m_ui->vLabel->setText(v); + + h = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Hue", 0, QApplication::UnicodeUTF8); + s = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Sat", 0, QApplication::UnicodeUTF8); + v = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Val", 0, QApplication::UnicodeUTF8); + + const QString hue = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Hue", 0, QApplication::UnicodeUTF8); + const QString saturation = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Saturation", 0, QApplication::UnicodeUTF8); + const QString value = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Value", 0, QApplication::UnicodeUTF8); + + m_ui->hLabel->setToolTip(hue); + m_ui->hueLabel->setText(h); + m_ui->hueColorLine->setToolTip(hue); + m_ui->hueColorLine->setColorComponent(QtColorLine::Hue); + + m_ui->sLabel->setToolTip(saturation); + m_ui->saturationLabel->setText(s); + m_ui->saturationColorLine->setToolTip(saturation); + m_ui->saturationColorLine->setColorComponent(QtColorLine::Saturation); + + m_ui->vLabel->setToolTip(value); + m_ui->valueLabel->setText(v); + m_ui->valueColorLine->setToolTip(value); + m_ui->valueColorLine->setColorComponent(QtColorLine::Value); + + setColorSpinBoxes(m_ui->colorButton->color()); +} + +void QtGradientStopsControllerPrivate::slotRgbClicked() +{ + QString r = QApplication::translate("qdesigner_internal::QtGradientStopsController", "R", 0, QApplication::UnicodeUTF8); + QString g = QApplication::translate("qdesigner_internal::QtGradientStopsController", "G", 0, QApplication::UnicodeUTF8); + QString b = QApplication::translate("qdesigner_internal::QtGradientStopsController", "B", 0, QApplication::UnicodeUTF8); + + m_ui->hLabel->setText(r); + m_ui->sLabel->setText(g); + m_ui->vLabel->setText(b); + + QString red = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Red", 0, QApplication::UnicodeUTF8); + QString green = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Green", 0, QApplication::UnicodeUTF8); + QString blue = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Blue", 0, QApplication::UnicodeUTF8); + + m_ui->hLabel->setToolTip(red); + m_ui->hueLabel->setText(red); + m_ui->hueColorLine->setToolTip(red); + m_ui->hueColorLine->setColorComponent(QtColorLine::Red); + + m_ui->sLabel->setToolTip(green); + m_ui->saturationLabel->setText(green); + m_ui->saturationColorLine->setToolTip(green); + m_ui->saturationColorLine->setColorComponent(QtColorLine::Green); + + m_ui->vLabel->setToolTip(blue); + m_ui->valueLabel->setText(blue); + m_ui->valueColorLine->setToolTip(blue); + m_ui->valueColorLine->setColorComponent(QtColorLine::Blue); + + setColorSpinBoxes(m_ui->colorButton->color()); +} + +void QtGradientStopsControllerPrivate::setColorSpinBoxes(const QColor &color) +{ + m_ui->hueSpinBox->blockSignals(true); + m_ui->saturationSpinBox->blockSignals(true); + m_ui->valueSpinBox->blockSignals(true); + m_ui->alphaSpinBox->blockSignals(true); + if (m_ui->hsvRadioButton->isChecked()) { + if (m_ui->hueSpinBox->maximum() != 359) + m_ui->hueSpinBox->setMaximum(359); + if (m_ui->hueSpinBox->value() != color.hue()) + m_ui->hueSpinBox->setValue(color.hue()); + if (m_ui->saturationSpinBox->value() != color.saturation()) + m_ui->saturationSpinBox->setValue(color.saturation()); + if (m_ui->valueSpinBox->value() != color.value()) + m_ui->valueSpinBox->setValue(color.value()); + } else { + if (m_ui->hueSpinBox->maximum() != 255) + m_ui->hueSpinBox->setMaximum(255); + if (m_ui->hueSpinBox->value() != color.red()) + m_ui->hueSpinBox->setValue(color.red()); + if (m_ui->saturationSpinBox->value() != color.green()) + m_ui->saturationSpinBox->setValue(color.green()); + if (m_ui->valueSpinBox->value() != color.blue()) + m_ui->valueSpinBox->setValue(color.blue()); + } + m_ui->alphaSpinBox->setValue(color.alpha()); + m_ui->hueSpinBox->blockSignals(false); + m_ui->saturationSpinBox->blockSignals(false); + m_ui->valueSpinBox->blockSignals(false); + m_ui->alphaSpinBox->blockSignals(false); +} + +void QtGradientStopsControllerPrivate::slotCurrentStopChanged(QtGradientStop *stop) +{ + if (!stop) { + enableCurrent(false); + return; + } + enableCurrent(true); + + QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox())); + + m_ui->colorButton->setColor(stop->color()); + m_ui->hueColorLine->setColor(stop->color()); + m_ui->saturationColorLine->setColor(stop->color()); + m_ui->valueColorLine->setColor(stop->color()); + m_ui->alphaColorLine->setColor(stop->color()); + setColorSpinBoxes(stop->color()); +} + +void QtGradientStopsControllerPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos) +{ + QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox())); + + PositionColorMap stops = stopsData(m_model->stops()); + stops.remove(stop->position()); + stops[newPos] = stop->color(); + + QGradientStops gradStops = makeGradientStops(stops); + emit q_ptr->gradientStopsChanged(gradStops); +} + +void QtGradientStopsControllerPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2) +{ + QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox())); + + PositionColorMap stops = stopsData(m_model->stops()); + const qreal pos1 = stop1->position(); + const qreal pos2 = stop2->position(); + stops[pos1] = stop2->color(); + stops[pos2] = stop1->color(); + + QGradientStops gradStops = makeGradientStops(stops); + emit q_ptr->gradientStopsChanged(gradStops); +} + +void QtGradientStopsControllerPrivate::slotStopAdded(QtGradientStop *stop) +{ + PositionColorMap stops = stopsData(m_model->stops()); + stops[stop->position()] = stop->color(); + + QGradientStops gradStops = makeGradientStops(stops); + emit q_ptr->gradientStopsChanged(gradStops); +} + +void QtGradientStopsControllerPrivate::slotStopRemoved(QtGradientStop *stop) +{ + PositionColorMap stops = stopsData(m_model->stops()); + stops.remove(stop->position()); + + QGradientStops gradStops = makeGradientStops(stops); + emit q_ptr->gradientStopsChanged(gradStops); +} + +void QtGradientStopsControllerPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor) +{ + if (m_model->currentStop() == stop) { + m_ui->colorButton->setColor(newColor); + m_ui->hueColorLine->setColor(newColor); + m_ui->saturationColorLine->setColor(newColor); + m_ui->valueColorLine->setColor(newColor); + m_ui->alphaColorLine->setColor(newColor); + setColorSpinBoxes(newColor); + } + + PositionColorMap stops = stopsData(m_model->stops()); + stops[stop->position()] = newColor; + + QGradientStops gradStops = makeGradientStops(stops); + emit q_ptr->gradientStopsChanged(gradStops); +} + +void QtGradientStopsControllerPrivate::slotStopSelected(QtGradientStop *stop, bool selected) +{ + Q_UNUSED(stop) + Q_UNUSED(selected) + QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox())); +} + +void QtGradientStopsControllerPrivate::slotUpdatePositionSpinBox() +{ + QtGradientStop *current = m_model->currentStop(); + if (!current) + return; + + qreal min = 0.0; + qreal max = 1.0; + const qreal pos = current->position(); + + QtGradientStop *first = m_model->firstSelected(); + QtGradientStop *last = m_model->lastSelected(); + + if (first && last) { + const qreal minPos = pos - first->position() - 0.0004999; + const qreal maxPos = pos + 1.0 - last->position() + 0.0004999; + + if (max > maxPos) + max = maxPos; + if (min < minPos) + min = minPos; + + if (first->position() == 0.0) + min = pos; + if (last->position() == 1.0) + max = pos; + } + + const int spinMin = qRound(m_ui->positionSpinBox->minimum() * 1000); + const int spinMax = qRound(m_ui->positionSpinBox->maximum() * 1000); + + const int newMin = qRound(min * 1000); + const int newMax = qRound(max * 1000); + + m_ui->positionSpinBox->blockSignals(true); + if (spinMin != newMin || spinMax != newMax) { + m_ui->positionSpinBox->setRange((double)newMin / 1000, (double)newMax / 1000); + } + if (m_ui->positionSpinBox->value() != pos) + m_ui->positionSpinBox->setValue(pos); + m_ui->positionSpinBox->blockSignals(false); +} + +void QtGradientStopsControllerPrivate::slotChangeColor(const QColor &color) +{ + QtGradientStop *stop = m_model->currentStop(); + if (!stop) + return; + m_model->changeStop(stop, color); + QList<QtGradientStop *> stops = m_model->selectedStops(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (s != stop) + m_model->changeStop(s, color); + } +} + +void QtGradientStopsControllerPrivate::slotChangeHue(const QColor &color) +{ + QtGradientStop *stop = m_model->currentStop(); + if (!stop) + return; + m_model->changeStop(stop, color); + QList<QtGradientStop *> stops = m_model->selectedStops(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (s != stop) { + QColor c = s->color(); + if (m_ui->hsvRadioButton->isChecked()) + c.setHsvF(color.hueF(), c.saturationF(), c.valueF(), c.alphaF()); + else + c.setRgbF(color.redF(), c.greenF(), c.blueF(), c.alphaF()); + m_model->changeStop(s, c); + } + } +} + +void QtGradientStopsControllerPrivate::slotChangeHue(int color) +{ + QColor c = m_ui->hueColorLine->color(); + if (m_ui->hsvRadioButton->isChecked()) + c.setHsvF((qreal)color / 360.0, c.saturationF(), c.valueF(), c.alphaF()); + else + c.setRed(color); + slotChangeHue(c); +} + +void QtGradientStopsControllerPrivate::slotChangeSaturation(const QColor &color) +{ + QtGradientStop *stop = m_model->currentStop(); + if (!stop) + return; + m_model->changeStop(stop, color); + QList<QtGradientStop *> stops = m_model->selectedStops(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (s != stop) { + QColor c = s->color(); + if (m_ui->hsvRadioButton->isChecked()) { + c.setHsvF(c.hueF(), color.saturationF(), c.valueF(), c.alphaF()); + int hue = c.hue(); + if (hue == 360 || hue == -1) + c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF()); + } else { + c.setRgbF(c.redF(), color.greenF(), c.blueF(), c.alphaF()); + } + m_model->changeStop(s, c); + } + } +} + +void QtGradientStopsControllerPrivate::slotChangeSaturation(int color) +{ + QColor c = m_ui->saturationColorLine->color(); + if (m_ui->hsvRadioButton->isChecked()) + c.setHsvF(c.hueF(), (qreal)color / 255, c.valueF(), c.alphaF()); + else + c.setGreen(color); + slotChangeSaturation(c); +} + +void QtGradientStopsControllerPrivate::slotChangeValue(const QColor &color) +{ + QtGradientStop *stop = m_model->currentStop(); + if (!stop) + return; + m_model->changeStop(stop, color); + QList<QtGradientStop *> stops = m_model->selectedStops(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (s != stop) { + QColor c = s->color(); + if (m_ui->hsvRadioButton->isChecked()) { + c.setHsvF(c.hueF(), c.saturationF(), color.valueF(), c.alphaF()); + int hue = c.hue(); + if (hue == 360 || hue == -1) + c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF()); + } else { + c.setRgbF(c.redF(), c.greenF(), color.blueF(), c.alphaF()); + } + m_model->changeStop(s, c); + } + } +} + +void QtGradientStopsControllerPrivate::slotChangeValue(int color) +{ + QColor c = m_ui->valueColorLine->color(); + if (m_ui->hsvRadioButton->isChecked()) + c.setHsvF(c.hueF(), c.saturationF(), (qreal)color / 255, c.alphaF()); + else + c.setBlue(color); + slotChangeValue(c); +} + +void QtGradientStopsControllerPrivate::slotChangeAlpha(const QColor &color) +{ + QtGradientStop *stop = m_model->currentStop(); + if (!stop) + return; + m_model->changeStop(stop, color); + QList<QtGradientStop *> stops = m_model->selectedStops(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (s != stop) { + QColor c = s->color(); + if (m_ui->hsvRadioButton->isChecked()) { + c.setHsvF(c.hueF(), c.saturationF(), c.valueF(), color.alphaF()); + int hue = c.hue(); + if (hue == 360 || hue == -1) + c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF()); + } else { + c.setRgbF(c.redF(), c.greenF(), c.blueF(), color.alphaF()); + } + m_model->changeStop(s, c); + } + } +} + +void QtGradientStopsControllerPrivate::slotChangeAlpha(int color) +{ + QColor c = m_ui->alphaColorLine->color(); + if (m_ui->hsvRadioButton->isChecked()) + c.setHsvF(c.hueF(), c.saturationF(), c.valueF(), (qreal)color / 255); + else + c.setAlpha(color); + slotChangeAlpha(c); +} + +void QtGradientStopsControllerPrivate::slotChangePosition(double value) +{ + QtGradientStop *stop = m_model->currentStop(); + if (!stop) + return; + + m_model->moveStops(value); +} + +void QtGradientStopsControllerPrivate::slotChangeZoom(int value) +{ + updateZoom(value / 100.0); +} + +void QtGradientStopsControllerPrivate::slotZoomIn() +{ + double newZoom = m_ui->gradientStopsWidget->zoom() * 2; + if (newZoom > 100) + newZoom = 100; + updateZoom(newZoom); +} + +void QtGradientStopsControllerPrivate::slotZoomOut() +{ + double newZoom = m_ui->gradientStopsWidget->zoom() / 2; + if (newZoom < 1) + newZoom = 1; + updateZoom(newZoom); +} + +void QtGradientStopsControllerPrivate::slotZoomAll() +{ + updateZoom(1); +} + +void QtGradientStopsControllerPrivate::slotZoomChanged(double zoom) +{ + updateZoom(zoom); +} + +QtGradientStopsController::QtGradientStopsController(QObject *parent) + : QObject(parent) +{ + d_ptr = new QtGradientStopsControllerPrivate(); + d_ptr->q_ptr = this; + + d_ptr->m_spec = QColor::Hsv; +} + +void QtGradientStopsController::setUi(Ui::QtGradientEditor *ui) +{ + d_ptr->m_ui = ui; + + d_ptr->m_ui->hueColorLine->setColorComponent(QtColorLine::Hue); + d_ptr->m_ui->saturationColorLine->setColorComponent(QtColorLine::Saturation); + d_ptr->m_ui->valueColorLine->setColorComponent(QtColorLine::Value); + d_ptr->m_ui->alphaColorLine->setColorComponent(QtColorLine::Alpha); + + d_ptr->m_model = new QtGradientStopsModel(this); + d_ptr->m_ui->gradientStopsWidget->setGradientStopsModel(d_ptr->m_model); + connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop *)), + this, SLOT(slotCurrentStopChanged(QtGradientStop *))); + connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop *, qreal)), + this, SLOT(slotStopMoved(QtGradientStop *, qreal))); + connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop *, QtGradientStop *)), + this, SLOT(slotStopsSwapped(QtGradientStop *, QtGradientStop *))); + connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop *, const QColor &)), + this, SLOT(slotStopChanged(QtGradientStop *, const QColor &))); + connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop *, bool)), + this, SLOT(slotStopSelected(QtGradientStop *, bool))); + connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop *)), + this, SLOT(slotStopAdded(QtGradientStop *))); + connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop *)), + this, SLOT(slotStopRemoved(QtGradientStop *))); + + connect(d_ptr->m_ui->hueColorLine, SIGNAL(colorChanged(const QColor &)), + this, SLOT(slotChangeHue(const QColor &))); + connect(d_ptr->m_ui->saturationColorLine, SIGNAL(colorChanged(const QColor &)), + this, SLOT(slotChangeSaturation(const QColor &))); + connect(d_ptr->m_ui->valueColorLine, SIGNAL(colorChanged(const QColor &)), + this, SLOT(slotChangeValue(const QColor &))); + connect(d_ptr->m_ui->alphaColorLine, SIGNAL(colorChanged(const QColor &)), + this, SLOT(slotChangeAlpha(const QColor &))); + connect(d_ptr->m_ui->colorButton, SIGNAL(colorChanged(const QColor &)), + this, SLOT(slotChangeColor(const QColor &))); + + connect(d_ptr->m_ui->hueSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotChangeHue(int))); + connect(d_ptr->m_ui->saturationSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotChangeSaturation(int))); + connect(d_ptr->m_ui->valueSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotChangeValue(int))); + connect(d_ptr->m_ui->alphaSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotChangeAlpha(int))); + + connect(d_ptr->m_ui->positionSpinBox, SIGNAL(valueChanged(double)), + this, SLOT(slotChangePosition(double))); + + connect(d_ptr->m_ui->zoomSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotChangeZoom(int))); + connect(d_ptr->m_ui->zoomInButton, SIGNAL(clicked()), + this, SLOT(slotZoomIn())); + connect(d_ptr->m_ui->zoomOutButton, SIGNAL(clicked()), + this, SLOT(slotZoomOut())); + connect(d_ptr->m_ui->zoomAllButton, SIGNAL(clicked()), + this, SLOT(slotZoomAll())); + connect(d_ptr->m_ui->gradientStopsWidget, SIGNAL(zoomChanged(double)), + this, SLOT(slotZoomChanged(double))); + + connect(d_ptr->m_ui->hsvRadioButton, SIGNAL(clicked()), + this, SLOT(slotHsvClicked())); + connect(d_ptr->m_ui->rgbRadioButton, SIGNAL(clicked()), + this, SLOT(slotRgbClicked())); + + d_ptr->enableCurrent(false); + d_ptr->m_ui->zoomInButton->setIcon(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/zoomin.png"))); + d_ptr->m_ui->zoomOutButton->setIcon(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/zoomout.png"))); + d_ptr->updateZoom(1); +} + +QtGradientStopsController::~QtGradientStopsController() +{ + delete d_ptr; +} + +void QtGradientStopsController::setGradientStops(const QGradientStops &stops) +{ + d_ptr->m_model->clear(); + QVectorIterator<QPair<qreal, QColor> > it(stops); + QtGradientStop *first = 0; + while (it.hasNext()) { + QPair<qreal, QColor> pair = it.next(); + QtGradientStop *stop = d_ptr->m_model->addStop(pair.first, pair.second); + if (!first) + first = stop; + } + if (first) + d_ptr->m_model->setCurrentStop(first); +} + +QGradientStops QtGradientStopsController::gradientStops() const +{ + QGradientStops stops; + QList<QtGradientStop *> stopsList = d_ptr->m_model->stops().values(); + QListIterator<QtGradientStop *> itStop(stopsList); + while (itStop.hasNext()) { + QtGradientStop *stop = itStop.next(); + stops << QPair<qreal, QColor>(stop->position(), stop->color()); + } + return stops; +} + +QColor::Spec QtGradientStopsController::spec() const +{ + return d_ptr->m_spec; +} + +void QtGradientStopsController::setSpec(QColor::Spec spec) +{ + if (d_ptr->m_spec == spec) + return; + + d_ptr->m_spec = spec; + if (d_ptr->m_spec == QColor::Rgb) { + d_ptr->m_ui->rgbRadioButton->setChecked(true); + d_ptr->slotRgbClicked(); + } else { + d_ptr->m_ui->hsvRadioButton->setChecked(true); + d_ptr->slotHsvClicked(); + } +} + +QT_END_NAMESPACE + +#include "moc_qtgradientstopscontroller.cpp" diff --git a/tools/shared/qtgradienteditor/qtgradientstopscontroller.h b/tools/shared/qtgradienteditor/qtgradientstopscontroller.h new file mode 100644 index 0000000..9f16fb0 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientstopscontroller.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTGRADIENTSTOPSCONTROLLER_H +#define QTGRADIENTSTOPSCONTROLLER_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +namespace Ui { + class QtGradientEditor; +} + +class QtGradientStopsController : public QObject +{ + Q_OBJECT +public: + QtGradientStopsController(QObject *parent = 0); + ~QtGradientStopsController(); + + void setUi(Ui::QtGradientEditor *editor); + + void setGradientStops(const QGradientStops &stops); + QGradientStops gradientStops() const; + + QColor::Spec spec() const; + void setSpec(QColor::Spec spec); + +signals: + + void gradientStopsChanged(const QGradientStops &stops); + +private: + class QtGradientStopsControllerPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtGradientStopsController) + Q_DISABLE_COPY(QtGradientStopsController) + Q_PRIVATE_SLOT(d_func(), void slotHsvClicked()) + Q_PRIVATE_SLOT(d_func(), void slotRgbClicked()) + Q_PRIVATE_SLOT(d_func(), void slotCurrentStopChanged(QtGradientStop *stop)) + Q_PRIVATE_SLOT(d_func(), void slotStopMoved(QtGradientStop *stop, qreal newPos)) + Q_PRIVATE_SLOT(d_func(), void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)) + Q_PRIVATE_SLOT(d_func(), void slotStopChanged(QtGradientStop *stop, const QColor &newColor)) + Q_PRIVATE_SLOT(d_func(), void slotStopSelected(QtGradientStop *stop, bool selected)) + Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop)) + Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop)) + Q_PRIVATE_SLOT(d_func(), void slotUpdatePositionSpinBox()) + Q_PRIVATE_SLOT(d_func(), void slotChangeColor(const QColor &color)) + Q_PRIVATE_SLOT(d_func(), void slotChangeHue(const QColor &color)) + Q_PRIVATE_SLOT(d_func(), void slotChangeSaturation(const QColor &color)) + Q_PRIVATE_SLOT(d_func(), void slotChangeValue(const QColor &color)) + Q_PRIVATE_SLOT(d_func(), void slotChangeAlpha(const QColor &color)) + Q_PRIVATE_SLOT(d_func(), void slotChangeHue(int)) + Q_PRIVATE_SLOT(d_func(), void slotChangeSaturation(int)) + Q_PRIVATE_SLOT(d_func(), void slotChangeValue(int)) + Q_PRIVATE_SLOT(d_func(), void slotChangeAlpha(int)) + //Q_PRIVATE_SLOT(d_func(), void slotChangePosition(double newPos)) + Q_PRIVATE_SLOT(d_func(), void slotChangePosition(double value)) + Q_PRIVATE_SLOT(d_func(), void slotChangeZoom(int value)) + Q_PRIVATE_SLOT(d_func(), void slotZoomIn()) + Q_PRIVATE_SLOT(d_func(), void slotZoomOut()) + Q_PRIVATE_SLOT(d_func(), void slotZoomAll()) + Q_PRIVATE_SLOT(d_func(), void slotZoomChanged(double)) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp b/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp new file mode 100644 index 0000000..a632c0f --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp @@ -0,0 +1,480 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientstopsmodel.h" +#include <QtGui/QColor> + +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() +{ + delete d_ptr; +} + +class QtGradientStopsModelPrivate +{ + QtGradientStopsModel *q_ptr; + Q_DECLARE_PUBLIC(QtGradientStopsModel) +public: + QMap<qreal, QtGradientStop *> m_posToStop; + QMap<QtGradientStop *, qreal> m_stopToPos; + QMap<QtGradientStop *, bool> 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(); + delete d_ptr; +} + +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<QtGradientStop *> 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<qreal, QtGradientStop *> stopsToClone = stops(); + QMapIterator<qreal, QtGradientStop *> 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<QtGradientStop *> selected = selectedStops(); + QListIterator<QtGradientStop *> 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<QtGradientStop *> stopsList = stops().values(); + QListIterator<QtGradientStop *> it(stopsList); + while (it.hasNext()) + removeStop(it.next()); +} + +void QtGradientStopsModel::clearSelection() +{ + QList<QtGradientStop *> stopsList = selectedStops(); + QListIterator<QtGradientStop *> it(stopsList); + while (it.hasNext()) + selectStop(it.next(), false); +} + +void QtGradientStopsModel::flipAll() +{ + QMap<qreal, QtGradientStop *> stopsMap = stops(); + QMapIterator<qreal, QtGradientStop *> itStop(stopsMap); + itStop.toBack(); + + QMap<QtGradientStop *, bool> 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<QtGradientStop *> stopsList = stops().values(); + QListIterator<QtGradientStop *> it(stopsList); + while (it.hasNext()) + selectStop(it.next(), true); +} + +void QtGradientStopsModel::deleteStops() +{ + QList<QtGradientStop *> selected = selectedStops(); + QListIterator<QtGradientStop *> itSel(selected); + while (itSel.hasNext()) { + QtGradientStop *stop = itSel.next(); + removeStop(stop); + } + QtGradientStop *current = currentStop(); + if (current) + removeStop(current); +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtgradientstopsmodel.h b/tools/shared/qtgradienteditor/qtgradientstopsmodel.h new file mode 100644 index 0000000..d4e6b3c --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientstopsmodel.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTGRADIENTSTOPSMODEL_H +#define QTGRADIENTSTOPSMODEL_H + +#include <QtCore/QObject> +#include <QtCore/QMap> + +QT_BEGIN_NAMESPACE + +class QColor; + +class QtGradientStopsModel; + +class QtGradientStop +{ +public: + qreal position() const; + QColor color() const; + QtGradientStopsModel *gradientModel() const; + +private: + void setColor(const QColor &color); + void setPosition(qreal position); + friend class QtGradientStopsModel; + QtGradientStop(QtGradientStopsModel *model = 0); + ~QtGradientStop(); + class QtGradientStopPrivate *d_ptr; +}; + +class QtGradientStopsModel : public QObject +{ + Q_OBJECT +public: + typedef QMap<qreal, QtGradientStop *> PositionStopMap; + + QtGradientStopsModel(QObject *parent = 0); + ~QtGradientStopsModel(); + + PositionStopMap stops() const; + QtGradientStop *at(qreal pos) const; + QColor color(qreal pos) const; // calculated between points + QList<QtGradientStop *> selectedStops() const; + QtGradientStop *currentStop() const; + bool isSelected(QtGradientStop *stop) const; + QtGradientStop *firstSelected() const; + QtGradientStop *lastSelected() const; + QtGradientStopsModel *clone() const; + + QtGradientStop *addStop(qreal pos, const QColor &color); + void removeStop(QtGradientStop *stop); + void moveStop(QtGradientStop *stop, qreal newPos); + void swapStops(QtGradientStop *stop1, QtGradientStop *stop2); + void changeStop(QtGradientStop *stop, const QColor &newColor); + void selectStop(QtGradientStop *stop, bool select); + void setCurrentStop(QtGradientStop *stop); + + void moveStops(double newPosition); // moves current stop to newPos and all selected stops are moved accordingly + void clear(); + void clearSelection(); + void flipAll(); + void selectAll(); + void deleteStops(); + +signals: + void stopAdded(QtGradientStop *stop); + void stopRemoved(QtGradientStop *stop); + void stopMoved(QtGradientStop *stop, qreal newPos); + void stopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2); + void stopChanged(QtGradientStop *stop, const QColor &newColor); + void stopSelected(QtGradientStop *stop, bool selected); + void currentStopChanged(QtGradientStop *stop); + +private: + class QtGradientStopsModelPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtGradientStopsModel) + Q_DISABLE_COPY(QtGradientStopsModel) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientstopswidget.cpp b/tools/shared/qtgradienteditor/qtgradientstopswidget.cpp new file mode 100644 index 0000000..adaf57d --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientstopswidget.cpp @@ -0,0 +1,1156 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientstopswidget.h" +#include "qtgradientstopsmodel.h" + +#include <QtCore/QMap> +#include <QtGui/QImage> +#include <QtGui/QPainter> +#include <QtGui/QScrollBar> +#include <QtGui/QMouseEvent> +#include <QtGui/QRubberBand> +#include <QtGui/QMenu> + +QT_BEGIN_NAMESPACE + +class QtGradientStopsWidgetPrivate +{ + QtGradientStopsWidget *q_ptr; + Q_DECLARE_PUBLIC(QtGradientStopsWidget) +public: + typedef QMap<qreal, QColor> PositionColorMap; + typedef QMap<QtGradientStop *, qreal> StopPositionMap; + + void slotStopAdded(QtGradientStop *stop); + void slotStopRemoved(QtGradientStop *stop); + void slotStopMoved(QtGradientStop *stop, qreal newPos); + void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2); + void slotStopChanged(QtGradientStop *stop, const QColor &newColor); + void slotStopSelected(QtGradientStop *stop, bool selected); + void slotCurrentStopChanged(QtGradientStop *stop); + void slotNewStop(); + void slotDelete(); + void slotFlipAll(); + void slotSelectAll(); + void slotZoomIn(); + void slotZoomOut(); + void slotResetZoom(); + + double fromViewport(int x) const; + double toViewport(double x) const; + QtGradientStop *stopAt(const QPoint &viewportPos) const; + QList<QtGradientStop *> stopsAt(const QPoint &viewportPos) const; + void setupMove(QtGradientStop *stop, int x); + void ensureVisible(double x); // x = stop position + void ensureVisible(QtGradientStop *stop); + QtGradientStop *newStop(const QPoint &viewportPos); + + bool m_backgroundCheckered; + QtGradientStopsModel *m_model; + double m_handleSize; + int m_scaleFactor; + double m_zoom; + +#ifndef QT_NO_DRAGANDDROP + QtGradientStop *m_dragStop; + QtGradientStop *m_changedStop; + QtGradientStop *m_clonedStop; + QtGradientStopsModel *m_dragModel; + QColor m_dragColor; + void clearDrag(); + void removeClonedStop(); + void restoreChangedStop(); + void changeStop(qreal pos); + void cloneStop(qreal pos); +#endif + + QRubberBand *m_rubber; + QPoint m_clickPos; + + QList<QtGradientStop *> m_stops; + + bool m_moving; + int m_moveOffset; + StopPositionMap m_moveStops; + + PositionColorMap m_moveOriginal; +}; + +double QtGradientStopsWidgetPrivate::fromViewport(int x) const +{ + QSize size = q_ptr->viewport()->size(); + int w = size.width(); + int max = q_ptr->horizontalScrollBar()->maximum(); + int val = q_ptr->horizontalScrollBar()->value(); + return ((double)x * m_scaleFactor + w * val) / (w * (m_scaleFactor + max)); +} + +double QtGradientStopsWidgetPrivate::toViewport(double x) const +{ + QSize size = q_ptr->viewport()->size(); + int w = size.width(); + int max = q_ptr->horizontalScrollBar()->maximum(); + int val = q_ptr->horizontalScrollBar()->value(); + return w * (x * (m_scaleFactor + max) - val) / m_scaleFactor; +} + +QtGradientStop *QtGradientStopsWidgetPrivate::stopAt(const QPoint &viewportPos) const +{ + double posY = m_handleSize / 2; + QListIterator<QtGradientStop *> itStop(m_stops); + while (itStop.hasNext()) { + QtGradientStop *stop = itStop.next(); + + double posX = toViewport(stop->position()); + + double x = viewportPos.x() - posX; + double y = viewportPos.y() - posY; + + if ((m_handleSize * m_handleSize / 4) > (x * x + y * y)) + return stop; + } + return 0; +} + +QList<QtGradientStop *> QtGradientStopsWidgetPrivate::stopsAt(const QPoint &viewportPos) const +{ + QList<QtGradientStop *> stops; + double posY = m_handleSize / 2; + QListIterator<QtGradientStop *> itStop(m_stops); + while (itStop.hasNext()) { + QtGradientStop *stop = itStop.next(); + + double posX = toViewport(stop->position()); + + double x = viewportPos.x() - posX; + double y = viewportPos.y() - posY; + + if ((m_handleSize * m_handleSize / 4) > (x * x + y * y)) + stops.append(stop); + } + return stops; +} + +void QtGradientStopsWidgetPrivate::setupMove(QtGradientStop *stop, int x) +{ + m_model->setCurrentStop(stop); + + int viewportX = qRound(toViewport(stop->position())); + m_moveOffset = x - viewportX; + + QList<QtGradientStop *> stops = m_stops; + m_stops.clear(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (m_model->isSelected(s) || s == stop) { + m_moveStops[s] = s->position() - stop->position(); + m_stops.append(s); + } else { + m_moveOriginal[s->position()] = s->color(); + } + } + itStop.toFront(); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (!m_model->isSelected(s)) + m_stops.append(s); + } + m_stops.removeAll(stop); + m_stops.prepend(stop); +} + +void QtGradientStopsWidgetPrivate::ensureVisible(double x) +{ + double viewX = toViewport(x); + if (viewX < 0 || viewX > q_ptr->viewport()->size().width()) { + int max = q_ptr->horizontalScrollBar()->maximum(); + int newVal = qRound(x * (max + m_scaleFactor) - m_scaleFactor / 2); + q_ptr->horizontalScrollBar()->setValue(newVal); + } +} + +void QtGradientStopsWidgetPrivate::ensureVisible(QtGradientStop *stop) +{ + if (!stop) + return; + ensureVisible(stop->position()); +} + +QtGradientStop *QtGradientStopsWidgetPrivate::newStop(const QPoint &viewportPos) +{ + QtGradientStop *copyStop = stopAt(viewportPos); + double posX = fromViewport(viewportPos.x()); + QtGradientStop *stop = m_model->at(posX); + if (!stop) { + QColor newColor; + if (copyStop) + newColor = copyStop->color(); + else + newColor = m_model->color(posX); + if (!newColor.isValid()) + newColor = Qt::white; + stop = m_model->addStop(posX, newColor); + } + return stop; +} + +void QtGradientStopsWidgetPrivate::slotStopAdded(QtGradientStop *stop) +{ + m_stops.append(stop); + q_ptr->viewport()->update(); +} + +void QtGradientStopsWidgetPrivate::slotStopRemoved(QtGradientStop *stop) +{ + m_stops.removeAll(stop); + q_ptr->viewport()->update(); +} + +void QtGradientStopsWidgetPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos) +{ + Q_UNUSED(stop) + Q_UNUSED(newPos) + q_ptr->viewport()->update(); +} + +void QtGradientStopsWidgetPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2) +{ + Q_UNUSED(stop1) + Q_UNUSED(stop2) + q_ptr->viewport()->update(); +} + +void QtGradientStopsWidgetPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor) +{ + Q_UNUSED(stop) + Q_UNUSED(newColor) + q_ptr->viewport()->update(); +} + +void QtGradientStopsWidgetPrivate::slotStopSelected(QtGradientStop *stop, bool selected) +{ + Q_UNUSED(stop) + Q_UNUSED(selected) + q_ptr->viewport()->update(); +} + +void QtGradientStopsWidgetPrivate::slotCurrentStopChanged(QtGradientStop *stop) +{ + Q_UNUSED(stop) + + if (!m_model) + return; + q_ptr->viewport()->update(); + if (stop) { + m_stops.removeAll(stop); + m_stops.prepend(stop); + } +} + +void QtGradientStopsWidgetPrivate::slotNewStop() +{ + if (!m_model) + return; + + QtGradientStop *stop = newStop(m_clickPos); + + if (!stop) + return; + + m_model->clearSelection(); + m_model->selectStop(stop, true); + m_model->setCurrentStop(stop); +} + +void QtGradientStopsWidgetPrivate::slotDelete() +{ + if (!m_model) + return; + + m_model->deleteStops(); +} + +void QtGradientStopsWidgetPrivate::slotFlipAll() +{ + if (!m_model) + return; + + m_model->flipAll(); +} + +void QtGradientStopsWidgetPrivate::slotSelectAll() +{ + if (!m_model) + return; + + m_model->selectAll(); +} + +void QtGradientStopsWidgetPrivate::slotZoomIn() +{ + double newZoom = q_ptr->zoom() * 2; + if (newZoom > 100) + newZoom = 100; + if (newZoom == q_ptr->zoom()) + return; + + q_ptr->setZoom(newZoom); + emit q_ptr->zoomChanged(q_ptr->zoom()); +} + +void QtGradientStopsWidgetPrivate::slotZoomOut() +{ + double newZoom = q_ptr->zoom() / 2; + if (newZoom < 1) + newZoom = 1; + if (newZoom == q_ptr->zoom()) + return; + + q_ptr->setZoom(newZoom); + emit q_ptr->zoomChanged(q_ptr->zoom()); +} + +void QtGradientStopsWidgetPrivate::slotResetZoom() +{ + if (1 == q_ptr->zoom()) + return; + + q_ptr->setZoom(1); + emit q_ptr->zoomChanged(1); +} + +QtGradientStopsWidget::QtGradientStopsWidget(QWidget *parent) + : QAbstractScrollArea(parent) +{ + d_ptr = new QtGradientStopsWidgetPrivate; + d_ptr->q_ptr = this; + d_ptr->m_backgroundCheckered = true; + d_ptr->m_model = 0; + d_ptr->m_handleSize = 25.0; + d_ptr->m_scaleFactor = 1000; + d_ptr->m_moving = false; + d_ptr->m_zoom = 1; + d_ptr->m_rubber = new QRubberBand(QRubberBand::Rectangle, this); +#ifndef QT_NO_DRAGANDDROP + d_ptr->m_dragStop = 0; + d_ptr->m_changedStop = 0; + d_ptr->m_clonedStop = 0; + d_ptr->m_dragModel = 0; +#endif + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + horizontalScrollBar()->setRange(0, (int)(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1) + 0.5)); + horizontalScrollBar()->setPageStep(d_ptr->m_scaleFactor); + horizontalScrollBar()->setSingleStep(4); + viewport()->setAutoFillBackground(false); + + setAcceptDrops(true); + + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); +} + +QtGradientStopsWidget::~QtGradientStopsWidget() +{ + delete d_ptr; +} + +QSize QtGradientStopsWidget::sizeHint() const +{ + return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->sizeHint().height()); +} + +QSize QtGradientStopsWidget::minimumSizeHint() const +{ + return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->minimumSizeHint().height()); +} + +void QtGradientStopsWidget::setBackgroundCheckered(bool checkered) +{ + if (d_ptr->m_backgroundCheckered == checkered) + return; + d_ptr->m_backgroundCheckered = checkered; + update(); +} + +bool QtGradientStopsWidget::isBackgroundCheckered() const +{ + return d_ptr->m_backgroundCheckered; +} + +void QtGradientStopsWidget::setGradientStopsModel(QtGradientStopsModel *model) +{ + if (d_ptr->m_model == model) + return; + + if (d_ptr->m_model) { + disconnect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop *)), + this, SLOT(slotStopAdded(QtGradientStop *))); + disconnect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop *)), + this, SLOT(slotStopRemoved(QtGradientStop *))); + disconnect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop *, qreal)), + this, SLOT(slotStopMoved(QtGradientStop *, qreal))); + disconnect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop *, QtGradientStop *)), + this, SLOT(slotStopsSwapped(QtGradientStop *, QtGradientStop *))); + disconnect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop *, const QColor &)), + this, SLOT(slotStopChanged(QtGradientStop *, const QColor &))); + disconnect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop *, bool)), + this, SLOT(slotStopSelected(QtGradientStop *, bool))); + disconnect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop *)), + this, SLOT(slotCurrentStopChanged(QtGradientStop *))); + + d_ptr->m_stops.clear(); + } + + d_ptr->m_model = model; + + if (d_ptr->m_model) { + connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop *)), + this, SLOT(slotStopAdded(QtGradientStop *))); + connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop *)), + this, SLOT(slotStopRemoved(QtGradientStop *))); + connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop *, qreal)), + this, SLOT(slotStopMoved(QtGradientStop *, qreal))); + connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop *, QtGradientStop *)), + this, SLOT(slotStopsSwapped(QtGradientStop *, QtGradientStop *))); + connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop *, const QColor &)), + this, SLOT(slotStopChanged(QtGradientStop *, const QColor &))); + connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop *, bool)), + this, SLOT(slotStopSelected(QtGradientStop *, bool))); + connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop *)), + this, SLOT(slotCurrentStopChanged(QtGradientStop *))); + + QList<QtGradientStop *> stops = d_ptr->m_model->stops().values(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) + d_ptr->slotStopAdded(itStop.next()); + + QList<QtGradientStop *> selected = d_ptr->m_model->selectedStops(); + QListIterator<QtGradientStop *> itSelect(selected); + while (itSelect.hasNext()) + d_ptr->slotStopSelected(itSelect.next(), true); + + d_ptr->slotCurrentStopChanged(d_ptr->m_model->currentStop()); + } +} + +void QtGradientStopsWidget::mousePressEvent(QMouseEvent *e) +{ + typedef QtGradientStopsModel::PositionStopMap PositionStopMap; + if (!d_ptr->m_model) + return; + + if (e->button() != Qt::LeftButton) + return; + + d_ptr->m_moving = true; + + d_ptr->m_moveStops.clear(); + d_ptr->m_moveOriginal.clear(); + d_ptr->m_clickPos = e->pos(); + QtGradientStop *stop = d_ptr->stopAt(e->pos()); + if (stop) { + if (e->modifiers() & Qt::ControlModifier) { + d_ptr->m_model->selectStop(stop, !d_ptr->m_model->isSelected(stop)); + } else if (e->modifiers() & Qt::ShiftModifier) { + QtGradientStop *oldCurrent = d_ptr->m_model->currentStop(); + if (oldCurrent) { + PositionStopMap stops = d_ptr->m_model->stops(); + PositionStopMap::ConstIterator itSt = stops.constFind(oldCurrent->position()); + if (itSt != stops.constEnd()) { + while (itSt != stops.constFind(stop->position())) { + d_ptr->m_model->selectStop(itSt.value(), true); + if (oldCurrent->position() < stop->position()) + ++itSt; + else + --itSt; + } + } + } + d_ptr->m_model->selectStop(stop, true); + } else { + if (!d_ptr->m_model->isSelected(stop)) { + d_ptr->m_model->clearSelection(); + d_ptr->m_model->selectStop(stop, true); + } + } + d_ptr->setupMove(stop, e->pos().x()); + } else { + d_ptr->m_model->clearSelection(); + d_ptr->m_rubber->setGeometry(QRect(d_ptr->m_clickPos, QSize())); + d_ptr->m_rubber->show(); + } + viewport()->update(); +} + +void QtGradientStopsWidget::mouseReleaseEvent(QMouseEvent *e) +{ + if (!d_ptr->m_model) + return; + + if (e->button() != Qt::LeftButton) + return; + + d_ptr->m_moving = false; + d_ptr->m_rubber->hide(); + d_ptr->m_moveStops.clear(); + d_ptr->m_moveOriginal.clear(); +} + +void QtGradientStopsWidget::mouseMoveEvent(QMouseEvent *e) +{ + typedef QtGradientStopsWidgetPrivate::PositionColorMap PositionColorMap; + typedef QtGradientStopsModel::PositionStopMap PositionStopMap; + typedef QtGradientStopsWidgetPrivate::StopPositionMap StopPositionMap; + if (!d_ptr->m_model) + return; + + if (!(e->buttons() & Qt::LeftButton)) + return; + + if (!d_ptr->m_moving) + return; + + if (!d_ptr->m_moveStops.isEmpty()) { + double maxOffset = 0.0; + double minOffset = 0.0; + bool first = true; + StopPositionMap::ConstIterator itStop = d_ptr->m_moveStops.constBegin(); + while (itStop != d_ptr->m_moveStops.constEnd()) { + double offset = itStop.value(); + + if (first) { + maxOffset = offset; + minOffset = offset; + first = false; + } else { + if (maxOffset < offset) + maxOffset = offset; + else if (minOffset > offset) + minOffset = offset; + } + ++itStop; + } + + double viewportMin = d_ptr->toViewport(-minOffset); + double viewportMax = d_ptr->toViewport(1.0 - maxOffset); + + PositionStopMap newPositions; + + int viewportX = e->pos().x() - d_ptr->m_moveOffset; + + if (viewportX > viewport()->size().width()) + viewportX = viewport()->size().width(); + else if (viewportX < 0) + viewportX = 0; + + double posX = d_ptr->fromViewport(viewportX); + + if (viewportX > viewportMax) + posX = 1.0 - maxOffset; + else if (viewportX < viewportMin) + posX = -minOffset; + + itStop = d_ptr->m_moveStops.constBegin(); + while (itStop != d_ptr->m_moveStops.constEnd()) { + QtGradientStop *stop = itStop.key(); + + newPositions[posX + itStop.value()] = stop; + + ++itStop; + } + + bool forward = true; + PositionStopMap::ConstIterator itNewPos = newPositions.constBegin(); + if (itNewPos.value()->position() < itNewPos.key()) + forward = false; + + itNewPos = forward ? newPositions.constBegin() : newPositions.constEnd(); + while (itNewPos != (forward ? newPositions.constEnd() : newPositions.constBegin())) { + if (!forward) + --itNewPos; + QtGradientStop *stop = itNewPos.value(); + double newPos = itNewPos.key(); + if (newPos > 1) + newPos = 1; + else if (newPos < 0) + newPos = 0; + + QtGradientStop *existingStop = d_ptr->m_model->at(newPos); + if (existingStop && !d_ptr->m_moveStops.contains(existingStop)) + d_ptr->m_model->removeStop(existingStop); + d_ptr->m_model->moveStop(stop, newPos); + + if (forward) + ++itNewPos; + } + + PositionColorMap::ConstIterator itOld = d_ptr->m_moveOriginal.constBegin(); + while (itOld != d_ptr->m_moveOriginal.constEnd()) { + double position = itOld.key(); + if (!d_ptr->m_model->at(position)) + d_ptr->m_model->addStop(position, itOld.value()); + + ++itOld; + } + + } else { + QRect r(QRect(d_ptr->m_clickPos, e->pos()).normalized()); + r.translate(1, 0); + d_ptr->m_rubber->setGeometry(r); + //d_ptr->m_model->clearSelection(); + + int xv1 = d_ptr->m_clickPos.x(); + int xv2 = e->pos().x(); + if (xv1 > xv2) { + int temp = xv1; + xv1 = xv2; + xv2 = temp; + } + int yv1 = d_ptr->m_clickPos.y(); + int yv2 = e->pos().y(); + if (yv1 > yv2) { + int temp = yv1; + yv1 = yv2; + yv2 = temp; + } + + QPoint p1, p2; + + if (yv2 < d_ptr->m_handleSize / 2) { + p1 = QPoint(xv1, yv2); + p2 = QPoint(xv2, yv2); + } else if (yv1 > d_ptr->m_handleSize / 2) { + p1 = QPoint(xv1, yv1); + p2 = QPoint(xv2, yv1); + } else { + p1 = QPoint(xv1, qRound(d_ptr->m_handleSize / 2)); + p2 = QPoint(xv2, qRound(d_ptr->m_handleSize / 2)); + } + + QList<QtGradientStop *> beginList = d_ptr->stopsAt(p1); + QList<QtGradientStop *> endList = d_ptr->stopsAt(p2); + + double x1 = d_ptr->fromViewport(xv1); + double x2 = d_ptr->fromViewport(xv2); + + QListIterator<QtGradientStop *> itStop(d_ptr->m_stops); + while (itStop.hasNext()) { + QtGradientStop *stop = itStop.next(); + if ((stop->position() >= x1 && stop->position() <= x2) || + beginList.contains(stop) || endList.contains(stop)) + d_ptr->m_model->selectStop(stop, true); + else + d_ptr->m_model->selectStop(stop, false); + } + } +} + +void QtGradientStopsWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + if (!d_ptr->m_model) + return; + + if (e->button() != Qt::LeftButton) + return; + + if (d_ptr->m_clickPos != e->pos()) { + mousePressEvent(e); + return; + } + d_ptr->m_moving = true; + d_ptr->m_moveStops.clear(); + d_ptr->m_moveOriginal.clear(); + + QtGradientStop *stop = d_ptr->newStop(e->pos()); + + if (!stop) + return; + + d_ptr->m_model->clearSelection(); + d_ptr->m_model->selectStop(stop, true); + + d_ptr->setupMove(stop, e->pos().x()); + + viewport()->update(); +} + +void QtGradientStopsWidget::keyPressEvent(QKeyEvent *e) +{ + typedef QtGradientStopsModel::PositionStopMap PositionStopMap; + if (!d_ptr->m_model) + return; + + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) { + d_ptr->m_model->deleteStops(); + } else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right || + e->key() == Qt::Key_Home || e->key() == Qt::Key_End) { + PositionStopMap stops = d_ptr->m_model->stops(); + if (stops.isEmpty()) + return; + QtGradientStop *newCurrent = 0; + QtGradientStop *current = d_ptr->m_model->currentStop(); + if (!current || e->key() == Qt::Key_Home || e->key() == Qt::Key_End) { + if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Home) + newCurrent = stops.constBegin().value(); + else if (e->key() == Qt::Key_Right || e->key() == Qt::Key_End) + newCurrent = (--stops.constEnd()).value(); + } else { + PositionStopMap::ConstIterator itStop = stops.constBegin(); + while (itStop.value() != current) + ++itStop; + if (e->key() == Qt::Key_Left && itStop != stops.constBegin()) + --itStop; + else if (e->key() == Qt::Key_Right && itStop != --stops.constEnd()) + ++itStop; + newCurrent = itStop.value(); + } + d_ptr->m_model->clearSelection(); + d_ptr->m_model->selectStop(newCurrent, true); + d_ptr->m_model->setCurrentStop(newCurrent); + d_ptr->ensureVisible(newCurrent); + } else if (e->key() == Qt::Key_A) { + if (e->modifiers() & Qt::ControlModifier) + d_ptr->m_model->selectAll(); + } +} + +void QtGradientStopsWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e) + if (!d_ptr->m_model) + return; + + QtGradientStopsModel *model = d_ptr->m_model; +#ifndef QT_NO_DRAGANDDROP + if (d_ptr->m_dragModel) + model = d_ptr->m_dragModel; +#endif + + QSize size = viewport()->size(); + int w = size.width(); + double h = size.height() - d_ptr->m_handleSize; + if (w <= 0) + return; + + QPixmap pix(size); + QPainter p; + + if (d_ptr->m_backgroundCheckered) { + int pixSize = 20; + QPixmap pm(2 * pixSize, 2 * pixSize); + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, Qt::white); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white); + pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black); + pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black); + + p.begin(&pix); + p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2); + p.fillRect(viewport()->rect(), pm); + p.setBrushOrigin(0, 0); + } else { + p.begin(viewport()); + } + + double viewBegin = (double)w * horizontalScrollBar()->value() / d_ptr->m_scaleFactor; + + int val = horizontalScrollBar()->value(); + int max = horizontalScrollBar()->maximum(); + + double begin = (double)val / (d_ptr->m_scaleFactor + max); + double end = (double)(val + d_ptr->m_scaleFactor) / (d_ptr->m_scaleFactor + max); + double width = end - begin; + + if (h > 0) { + QLinearGradient lg(0, 0, w, 0); + QMap<qreal, QtGradientStop *> stops = model->stops(); + QMapIterator<qreal, QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *stop = itStop.next().value(); + double pos = stop->position(); + if (pos >= begin && pos <= end) { + double gradPos = (pos - begin) / width; + QColor c = stop->color(); + lg.setColorAt(gradPos, c); + } + //lg.setColorAt(stop->position(), stop->color()); + } + lg.setColorAt(0, model->color(begin)); + lg.setColorAt(1, model->color(end)); + QImage img(w, 1, QImage::Format_ARGB32_Premultiplied); + QPainter p1(&img); + p1.setCompositionMode(QPainter::CompositionMode_Source); + + /* + if (viewBegin != 0) + p1.translate(-viewBegin, 0); + if (d_ptr->m_zoom != 1) + p1.scale(d_ptr->m_zoom, 1); + */ + p1.fillRect(0, 0, w, 1, lg); + + p.fillRect(QRectF(0, d_ptr->m_handleSize, w, h), QPixmap::fromImage(img)); + } + + + double handleWidth = d_ptr->m_handleSize * d_ptr->m_scaleFactor / (w * (d_ptr->m_scaleFactor + max)); + + QColor insideColor = QColor::fromRgb(0x20, 0x20, 0x20, 0xFF); + QColor borderColor = QColor(Qt::white); + QColor drawColor; + QColor back1 = QColor(Qt::lightGray); + QColor back2 = QColor(Qt::darkGray); + QColor back = QColor::fromRgb((back1.red() + back2.red()) / 2, + (back1.green() + back2.green()) / 2, + (back1.blue() + back2.blue()) / 2); + + QPen pen; + p.setRenderHint(QPainter::Antialiasing); + QListIterator<QtGradientStop *> itStop(d_ptr->m_stops); + itStop.toBack(); + while (itStop.hasPrevious()) { + QtGradientStop *stop = itStop.previous(); + double x = stop->position(); + if (x >= begin - handleWidth / 2 && x <= end + handleWidth / 2) { + double viewX = x * w * (d_ptr->m_scaleFactor + max) / d_ptr->m_scaleFactor - viewBegin; + p.save(); + QColor c = stop->color(); +#ifndef QT_NO_DRAGANDDROP + if (stop == d_ptr->m_dragStop) + c = d_ptr->m_dragColor; +#endif + if ((0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF()) * c.alphaF() + + (0.3 * back.redF() + 0.59 * back.greenF() + 0.11 * back.blueF()) * (1.0 - c.alphaF()) < 0.5) { + drawColor = QColor::fromRgb(0xC0, 0xC0, 0xC0, 0xB0); + } else { + drawColor = QColor::fromRgb(0x40, 0x40, 0x40, 0x80); + } + QRectF rect(viewX - d_ptr->m_handleSize / 2, 0, d_ptr->m_handleSize, d_ptr->m_handleSize); + rect.adjust(0.5, 0.5, -0.5, -0.5); + if (h > 0) { + pen.setWidthF(1); + QLinearGradient lg(0, d_ptr->m_handleSize, 0, d_ptr->m_handleSize + h / 2); + lg.setColorAt(0, drawColor); + QColor alphaZero = drawColor; + alphaZero.setAlpha(0); + lg.setColorAt(1, alphaZero); + pen.setBrush(lg); + p.setPen(pen); + p.drawLine(QPointF(viewX, d_ptr->m_handleSize), QPointF(viewX, d_ptr->m_handleSize + h / 2)); + + pen.setWidthF(1); + pen.setBrush(drawColor); + p.setPen(pen); + QRectF r1 = rect.adjusted(0.5, 0.5, -0.5, -0.5); + QRectF r2 = rect.adjusted(1.5, 1.5, -1.5, -1.5); + QColor inColor = QColor::fromRgb(0x80, 0x80, 0x80, 0x80); + if (!d_ptr->m_model->isSelected(stop)) { + p.setBrush(c); + p.drawEllipse(rect); + } else { + pen.setBrush(insideColor); + pen.setWidthF(2); + p.setPen(pen); + p.setBrush(Qt::NoBrush); + p.drawEllipse(r1); + + pen.setBrush(inColor); + pen.setWidthF(1); + p.setPen(pen); + p.setBrush(c); + p.drawEllipse(r2); + } + + if (d_ptr->m_model->currentStop() == stop) { + p.setBrush(Qt::NoBrush); + pen.setWidthF(5); + pen.setBrush(drawColor); + int corr = 4; + if (!d_ptr->m_model->isSelected(stop)) { + corr = 3; + pen.setWidthF(7); + } + p.setPen(pen); + p.drawEllipse(rect.adjusted(corr, corr, -corr, -corr)); + } + + } + p.restore(); + } + } + if (d_ptr->m_backgroundCheckered) { + p.end(); + p.begin(viewport()); + p.drawPixmap(0, 0, pix); + } + p.end(); +} + +void QtGradientStopsWidget::focusInEvent(QFocusEvent *e) +{ + Q_UNUSED(e) + viewport()->update(); +} + +void QtGradientStopsWidget::focusOutEvent(QFocusEvent *e) +{ + Q_UNUSED(e) + viewport()->update(); +} + +void QtGradientStopsWidget::contextMenuEvent(QContextMenuEvent *e) +{ + if (!d_ptr->m_model) + return; + + d_ptr->m_clickPos = e->pos(); + + QMenu menu(this); + QAction *newStopAction = new QAction(tr("New Stop"), &menu); + QAction *deleteAction = new QAction(tr("Delete"), &menu); + QAction *flipAllAction = new QAction(tr("Flip All"), &menu); + QAction *selectAllAction = new QAction(tr("Select All"), &menu); + QAction *zoomInAction = new QAction(tr("Zoom In"), &menu); + QAction *zoomOutAction = new QAction(tr("Zoom Out"), &menu); + QAction *zoomAllAction = new QAction(tr("Reset Zoom"), &menu); + if (d_ptr->m_model->selectedStops().isEmpty() && !d_ptr->m_model->currentStop()) + deleteAction->setEnabled(false); + if (zoom() <= 1) { + zoomOutAction->setEnabled(false); + zoomAllAction->setEnabled(false); + } else if (zoom() >= 100) { + zoomInAction->setEnabled(false); + } + connect(newStopAction, SIGNAL(triggered()), this, SLOT(slotNewStop())); + connect(deleteAction, SIGNAL(triggered()), this, SLOT(slotDelete())); + connect(flipAllAction, SIGNAL(triggered()), this, SLOT(slotFlipAll())); + connect(selectAllAction, SIGNAL(triggered()), this, SLOT(slotSelectAll())); + connect(zoomInAction, SIGNAL(triggered()), this, SLOT(slotZoomIn())); + connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(slotZoomOut())); + connect(zoomAllAction, SIGNAL(triggered()), this, SLOT(slotResetZoom())); + menu.addAction(newStopAction); + menu.addAction(deleteAction); + menu.addAction(flipAllAction); + menu.addAction(selectAllAction); + menu.addSeparator(); + menu.addAction(zoomInAction); + menu.addAction(zoomOutAction); + menu.addAction(zoomAllAction); + menu.exec(e->globalPos()); +} + +void QtGradientStopsWidget::wheelEvent(QWheelEvent *e) +{ + int numDegrees = e->delta() / 8; + int numSteps = numDegrees / 15; + + int shift = numSteps; + if (shift < 0) + shift = -shift; + int pow = 1 << shift; + //const double c = 0.7071067; // 2 steps per doubled value + const double c = 0.5946036; // 4 steps pre doubled value + // in general c = pow(2, 1 / n) / 2; where n is the step + double factor = pow * c; + + double newZoom = zoom(); + if (numSteps < 0) + newZoom /= factor; + else + newZoom *= factor; + if (newZoom > 100) + newZoom = 100; + if (newZoom < 1) + newZoom = 1; + + if (newZoom == zoom()) + return; + + setZoom(newZoom); + emit zoomChanged(zoom()); +} + +#ifndef QT_NO_DRAGANDDROP +void QtGradientStopsWidget::dragEnterEvent(QDragEnterEvent *event) +{ + const QMimeData *mime = event->mimeData(); + if (!mime->hasColor()) + return; + event->accept(); + d_ptr->m_dragModel = d_ptr->m_model->clone(); + + d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData()); + update(); +} + +void QtGradientStopsWidget::dragMoveEvent(QDragMoveEvent *event) +{ + QRectF rect = viewport()->rect(); + rect.adjust(0, d_ptr->m_handleSize, 0, 0); + double x = d_ptr->fromViewport(event->pos().x()); + QtGradientStop *dragStop = d_ptr->stopAt(event->pos()); + if (dragStop) { + event->accept(); + d_ptr->removeClonedStop(); + d_ptr->changeStop(dragStop->position()); + } else if (rect.contains(event->pos())) { + event->accept(); + if (d_ptr->m_model->at(x)) { + d_ptr->removeClonedStop(); + d_ptr->changeStop(x); + } else { + d_ptr->restoreChangedStop(); + d_ptr->cloneStop(x); + } + } else { + event->ignore(); + d_ptr->removeClonedStop(); + d_ptr->restoreChangedStop(); + } + + update(); +} + +void QtGradientStopsWidget::dragLeaveEvent(QDragLeaveEvent *event) +{ + event->accept(); + d_ptr->clearDrag(); + update(); +} + +void QtGradientStopsWidget::dropEvent(QDropEvent *event) +{ + event->accept(); + if (!d_ptr->m_dragModel) + return; + + if (d_ptr->m_changedStop) + d_ptr->m_model->changeStop(d_ptr->m_model->at(d_ptr->m_changedStop->position()), d_ptr->m_dragColor); + else if (d_ptr->m_clonedStop) + d_ptr->m_model->addStop(d_ptr->m_clonedStop->position(), d_ptr->m_dragColor); + + d_ptr->clearDrag(); + update(); +} + +void QtGradientStopsWidgetPrivate::clearDrag() +{ + removeClonedStop(); + restoreChangedStop(); + delete m_dragModel; + m_dragModel = 0; +} + +void QtGradientStopsWidgetPrivate::removeClonedStop() +{ + if (!m_clonedStop) + return; + m_dragModel->removeStop(m_clonedStop); + m_clonedStop = 0; +} + +void QtGradientStopsWidgetPrivate::restoreChangedStop() +{ + if (!m_changedStop) + return; + m_dragModel->changeStop(m_changedStop, m_model->at(m_changedStop->position())->color()); + m_changedStop = 0; + m_dragStop = 0; +} + +void QtGradientStopsWidgetPrivate::changeStop(qreal pos) +{ + QtGradientStop *stop = m_dragModel->at(pos); + if (!stop) + return; + + m_dragModel->changeStop(stop, m_dragColor); + m_changedStop = stop; + m_dragStop = m_model->at(stop->position()); +} + +void QtGradientStopsWidgetPrivate::cloneStop(qreal pos) +{ + if (m_clonedStop) { + m_dragModel->moveStop(m_clonedStop, pos); + return; + } + QtGradientStop *stop = m_dragModel->at(pos); + if (stop) + return; + + m_clonedStop = m_dragModel->addStop(pos, m_dragColor); +} + +#endif + +void QtGradientStopsWidget::setZoom(double zoom) +{ + double z = zoom; + if (z < 1) + z = 1; + else if (z > 100) + z = 100; + + if (d_ptr->m_zoom == z) + return; + + d_ptr->m_zoom = z; + int oldMax = horizontalScrollBar()->maximum(); + int oldVal = horizontalScrollBar()->value(); + horizontalScrollBar()->setRange(0, qRound(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1))); + int newMax = horizontalScrollBar()->maximum(); + double newVal = (oldVal + (double)d_ptr->m_scaleFactor / 2) * (newMax + d_ptr->m_scaleFactor) + / (oldMax + d_ptr->m_scaleFactor) - (double)d_ptr->m_scaleFactor / 2; + horizontalScrollBar()->setValue(qRound(newVal)); + viewport()->update(); +} + +double QtGradientStopsWidget::zoom() const +{ + return d_ptr->m_zoom; +} + +QT_END_NAMESPACE + +#include "moc_qtgradientstopswidget.cpp" diff --git a/tools/shared/qtgradienteditor/qtgradientstopswidget.h b/tools/shared/qtgradienteditor/qtgradientstopswidget.h new file mode 100644 index 0000000..aafea8b --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientstopswidget.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTGRADIENTSTOPSWIDGET_H +#define QTGRADIENTSTOPSWIDGET_H + +#include <QtGui/QAbstractScrollArea> + +QT_BEGIN_NAMESPACE + +class QtGradientStopsModel; +class QtGradientStopsWidgetPrivate; + +class QtGradientStopsWidget : public QAbstractScrollArea +{ + Q_OBJECT + Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered) +public: + QtGradientStopsWidget(QWidget *parent = 0); + ~QtGradientStopsWidget(); + + QSize minimumSizeHint() const; + QSize sizeHint() const; + + bool isBackgroundCheckered() const; + void setBackgroundCheckered(bool checkered); + + void setGradientStopsModel(QtGradientStopsModel *model); + + void setZoom(double zoom); + double zoom() const; + +signals: + + void zoomChanged(double zoom); + +protected: + void paintEvent(QPaintEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseDoubleClickEvent(QMouseEvent *e); + void keyPressEvent(QKeyEvent *e); + void focusInEvent(QFocusEvent *e); + void focusOutEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + void wheelEvent(QWheelEvent *e); +#ifndef QT_NO_DRAGANDDROP + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dropEvent(QDropEvent *event); +#endif + +private: + QtGradientStopsWidgetPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtGradientStopsWidget) + Q_DISABLE_COPY(QtGradientStopsWidget) + Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop)) + Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop)) + Q_PRIVATE_SLOT(d_func(), void slotStopMoved(QtGradientStop *stop, qreal newPos)) + Q_PRIVATE_SLOT(d_func(), void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)) + Q_PRIVATE_SLOT(d_func(), void slotStopChanged(QtGradientStop *stop, const QColor &newColor)) + Q_PRIVATE_SLOT(d_func(), void slotStopSelected(QtGradientStop *stop, bool selected)) + Q_PRIVATE_SLOT(d_func(), void slotCurrentStopChanged(QtGradientStop *stop)) + Q_PRIVATE_SLOT(d_func(), void slotNewStop()) + Q_PRIVATE_SLOT(d_func(), void slotDelete()) + Q_PRIVATE_SLOT(d_func(), void slotFlipAll()) + Q_PRIVATE_SLOT(d_func(), void slotSelectAll()) + Q_PRIVATE_SLOT(d_func(), void slotZoomIn()) + Q_PRIVATE_SLOT(d_func(), void slotZoomOut()) + Q_PRIVATE_SLOT(d_func(), void slotResetZoom()) +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientutils.cpp b/tools/shared/qtgradienteditor/qtgradientutils.cpp new file mode 100644 index 0000000..2456233 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientutils.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientutils.h" +#include "qtgradientmanager.h" +#include <QtGui/QLinearGradient> +#include <QtGui/QRadialGradient> +#include <QtGui/QConicalGradient> +#include <QtXml/QDomDocument> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +static QString gradientTypeToString(QGradient::Type type) +{ + if (type == QGradient::LinearGradient) + return QLatin1String("LinearGradient"); + if (type == QGradient::RadialGradient) + return QLatin1String("RadialGradient"); + if (type == QGradient::ConicalGradient) + return QLatin1String("ConicalGradient"); + return QLatin1String("NoGradient"); +} + +static QGradient::Type stringToGradientType(const QString &name) +{ + if (name == QLatin1String("LinearGradient")) + return QGradient::LinearGradient; + if (name == QLatin1String("RadialGradient")) + return QGradient::RadialGradient; + if (name == QLatin1String("ConicalGradient")) + return QGradient::ConicalGradient; + return QGradient::NoGradient; +} + +static QString gradientSpreadToString(QGradient::Spread spread) +{ + if (spread == QGradient::PadSpread) + return QLatin1String("PadSpread"); + if (spread == QGradient::RepeatSpread) + return QLatin1String("RepeatSpread"); + if (spread == QGradient::ReflectSpread) + return QLatin1String("ReflectSpread"); + return QLatin1String("PadSpread"); +} + +static QGradient::Spread stringToGradientSpread(const QString &name) +{ + if (name == QLatin1String("PadSpread")) + return QGradient::PadSpread; + if (name == QLatin1String("RepeatSpread")) + return QGradient::RepeatSpread; + if (name == QLatin1String("ReflectSpread")) + return QGradient::ReflectSpread; + return QGradient::PadSpread; +} + +static QString gradientCoordinateModeToString(QGradient::CoordinateMode mode) +{ + if (mode == QGradient::LogicalMode) + return QLatin1String("LogicalMode"); + if (mode == QGradient::StretchToDeviceMode) + return QLatin1String("StretchToDeviceMode"); + if (mode == QGradient::ObjectBoundingMode) + return QLatin1String("ObjectBoundingMode"); + return QLatin1String("StretchToDeviceMode"); +} + +static QGradient::CoordinateMode stringToGradientCoordinateMode(const QString &name) +{ + if (name == QLatin1String("LogicalMode")) + return QGradient::LogicalMode; + if (name == QLatin1String("StretchToDeviceMode")) + return QGradient::StretchToDeviceMode; + if (name == QLatin1String("ObjectBoundingMode")) + return QGradient::ObjectBoundingMode; + return QGradient::StretchToDeviceMode; +} + +static QDomElement saveColor(QDomDocument &doc, const QColor &color) +{ + QDomElement colorElem = doc.createElement(QLatin1String("colorData")); + + colorElem.setAttribute(QLatin1String("r"), QString::number(color.red())); + colorElem.setAttribute(QLatin1String("g"), QString::number(color.green())); + colorElem.setAttribute(QLatin1String("b"), QString::number(color.blue())); + colorElem.setAttribute(QLatin1String("a"), QString::number(color.alpha())); + + return colorElem; +} + +static QDomElement saveGradientStop(QDomDocument &doc, const QGradientStop &stop) +{ + QDomElement stopElem = doc.createElement(QLatin1String("stopData")); + + stopElem.setAttribute(QLatin1String("position"), QString::number(stop.first)); + + const QDomElement colorElem = saveColor(doc, stop.second); + stopElem.appendChild(colorElem); + + return stopElem; +} + +static QDomElement saveGradient(QDomDocument &doc, const QGradient &gradient) +{ + QDomElement gradElem = doc.createElement(QLatin1String("gradientData")); + + const QGradient::Type type = gradient.type(); + gradElem.setAttribute(QLatin1String("type"), gradientTypeToString(type)); + gradElem.setAttribute(QLatin1String("spread"), gradientSpreadToString(gradient.spread())); + gradElem.setAttribute(QLatin1String("coordinateMode"), gradientCoordinateModeToString(gradient.coordinateMode())); + + QGradientStops stops = gradient.stops(); + QVectorIterator<QGradientStop > it(stops); + while (it.hasNext()) + gradElem.appendChild(saveGradientStop(doc, it.next())); + + if (type == QGradient::LinearGradient) { + const QLinearGradient &g = *static_cast<const QLinearGradient *>(&gradient); + gradElem.setAttribute(QLatin1String("startX"), QString::number(g.start().x())); + gradElem.setAttribute(QLatin1String("startY"), QString::number(g.start().y())); + gradElem.setAttribute(QLatin1String("endX"), QString::number(g.finalStop().x())); + gradElem.setAttribute(QLatin1String("endY"), QString::number(g.finalStop().y())); + } else if (type == QGradient::RadialGradient) { + const QRadialGradient &g = *static_cast<const QRadialGradient *>(&gradient); + gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x())); + gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y())); + gradElem.setAttribute(QLatin1String("focalX"), QString::number(g.focalPoint().x())); + gradElem.setAttribute(QLatin1String("focalY"), QString::number(g.focalPoint().y())); + gradElem.setAttribute(QLatin1String("radius"), QString::number(g.radius())); + } else if (type == QGradient::ConicalGradient) { + const QConicalGradient &g = *static_cast<const QConicalGradient*>(&gradient); + gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x())); + gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y())); + gradElem.setAttribute(QLatin1String("angle"), QString::number(g.angle())); + } + + return gradElem; +} + +static QColor loadColor(const QDomElement &elem) +{ + if (elem.tagName() != QLatin1String("colorData")) + return QColor(); + + return QColor(elem.attribute(QLatin1String("r")).toInt(), + elem.attribute(QLatin1String("g")).toInt(), + elem.attribute(QLatin1String("b")).toInt(), + elem.attribute(QLatin1String("a")).toInt()); +} + +static QGradientStop loadGradientStop(const QDomElement &elem) +{ + if (elem.tagName() != QLatin1String("stopData")) + return QGradientStop(); + + const qreal pos = static_cast<qreal>(elem.attribute(QLatin1String("position")).toDouble()); + return qMakePair(pos, loadColor(elem.firstChild().toElement())); +} + +static QGradient loadGradient(const QDomElement &elem) +{ + if (elem.tagName() != QLatin1String("gradientData")) + return QLinearGradient(); + + const QGradient::Type type = stringToGradientType(elem.attribute(QLatin1String("type"))); + const QGradient::Spread spread = stringToGradientSpread(elem.attribute(QLatin1String("spread"))); + const QGradient::CoordinateMode mode = stringToGradientCoordinateMode(elem.attribute(QLatin1String("coordinateMode"))); + + QGradient gradient = QLinearGradient(); + + if (type == QGradient::LinearGradient) { + QLinearGradient g; + g.setStart(elem.attribute(QLatin1String("startX")).toDouble(), elem.attribute(QLatin1String("startY")).toDouble()); + g.setFinalStop(elem.attribute(QLatin1String("endX")).toDouble(), elem.attribute(QLatin1String("endY")).toDouble()); + gradient = g; + } else if (type == QGradient::RadialGradient) { + QRadialGradient g; + g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble()); + g.setFocalPoint(elem.attribute(QLatin1String("focalX")).toDouble(), elem.attribute(QLatin1String("focalY")).toDouble()); + g.setRadius(elem.attribute(QLatin1String("radius")).toDouble()); + gradient = g; + } else if (type == QGradient::ConicalGradient) { + QConicalGradient g; + g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble()); + g.setAngle(elem.attribute(QLatin1String("angle")).toDouble()); + gradient = g; + } + + QDomElement stopElem = elem.firstChildElement(); + while (!stopElem.isNull()) { + QGradientStop stop = loadGradientStop(stopElem); + + gradient.setColorAt(stop.first, stop.second); + + stopElem = stopElem.nextSiblingElement(); + } + + gradient.setSpread(spread); + gradient.setCoordinateMode(mode); + + return gradient; +} + +QString QtGradientUtils::saveState(const QtGradientManager *manager) +{ + QDomDocument doc; + + QDomElement rootElem = doc.createElement(QLatin1String("gradients")); + + QMap<QString, QGradient> grads = manager->gradients(); + QMapIterator<QString, QGradient> itGrad(grads); + while (itGrad.hasNext()) { + itGrad.next(); + QDomElement idElem = doc.createElement(QLatin1String("gradient")); + idElem.setAttribute(QLatin1String("name"), itGrad.key()); + QDomElement gradElem = saveGradient(doc, itGrad.value()); + idElem.appendChild(gradElem); + + rootElem.appendChild(idElem); + } + + doc.appendChild(rootElem); + + return doc.toString(); +} + +void QtGradientUtils::restoreState(QtGradientManager *manager, const QString &state) +{ + manager->clear(); + + QDomDocument doc; + doc.setContent(state); + + QDomElement rootElem = doc.documentElement(); + + QDomElement gradElem = rootElem.firstChildElement(); + while (!gradElem.isNull()) { + const QString name = gradElem.attribute(QLatin1String("name")); + const QGradient gradient = loadGradient(gradElem.firstChildElement()); + + manager->addGradient(name, gradient); + gradElem = gradElem.nextSiblingElement(); + } +} + +QPixmap QtGradientUtils::gradientPixmap(const QGradient &gradient, const QSize &size, bool checkeredBackground) +{ + QImage image(size, QImage::Format_ARGB32); + QPainter p(&image); + p.setCompositionMode(QPainter::CompositionMode_Source); + + if (checkeredBackground) { + int pixSize = 20; + QPixmap pm(2 * pixSize, 2 * pixSize); + + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray); + pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray); + pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray); + + p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2); + p.fillRect(0, 0, size.width(), size.height(), pm); + p.setBrushOrigin(0, 0); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + } + + const qreal scaleFactor = 0.999999; + p.scale(scaleFactor, scaleFactor); + QGradient grad = gradient; + grad.setCoordinateMode(QGradient::StretchToDeviceMode); + p.fillRect(QRect(0, 0, size.width(), size.height()), grad); + p.drawRect(QRect(0, 0, size.width() - 1, size.height() - 1)); + + return QPixmap::fromImage(image); +} + +static QString styleSheetFillName(const QGradient &gradient) +{ + QString result; + + switch (gradient.type()) { + case QGradient::LinearGradient: + result += QLatin1String("qlineargradient"); + break; + case QGradient::RadialGradient: + result += QLatin1String("qradialgradient"); + break; + case QGradient::ConicalGradient: + result += QLatin1String("qconicalgradient"); + break; + default: + qWarning() << "QtGradientUtils::styleSheetFillName(): gradient type" << gradient.type() << "not supported!"; + break; + } + + return result; +} + +static QStringList styleSheetParameters(const QGradient &gradient) +{ + QStringList result; + + if (gradient.type() != QGradient::ConicalGradient) { + QString spread; + switch (gradient.spread()) { + case QGradient::PadSpread: + spread = QLatin1String("pad"); + break; + case QGradient::ReflectSpread: + spread = QLatin1String("reflect"); + break; + case QGradient::RepeatSpread: + spread = QLatin1String("repeat"); + break; + default: + qWarning() << "QtGradientUtils::styleSheetParameters(): gradient spread" << gradient.spread() << "not supported!"; + break; + } + result << QLatin1String("spread:") + spread; + } + + switch (gradient.type()) { + case QGradient::LinearGradient: { + const QLinearGradient *linearGradient = static_cast<const QLinearGradient*>(&gradient); + result << QLatin1String("x1:") + QString::number(linearGradient->start().x()) + << QLatin1String("y1:") + QString::number(linearGradient->start().y()) + << QLatin1String("x2:") + QString::number(linearGradient->finalStop().x()) + << QLatin1String("y2:") + QString::number(linearGradient->finalStop().y()); + break; + } + case QGradient::RadialGradient: { + const QRadialGradient *radialGradient = static_cast<const QRadialGradient*>(&gradient); + result << QLatin1String("cx:") + QString::number(radialGradient->center().x()) + << QLatin1String("cy:") + QString::number(radialGradient->center().y()) + << QLatin1String("radius:") + QString::number(radialGradient->radius()) + << QLatin1String("fx:") + QString::number(radialGradient->focalPoint().x()) + << QLatin1String("fy:") + QString::number(radialGradient->focalPoint().y()); + break; + } + case QGradient::ConicalGradient: { + const QConicalGradient *conicalGradient = static_cast<const QConicalGradient*>(&gradient); + result << QLatin1String("cx:") + QString::number(conicalGradient->center().x()) + << QLatin1String("cy:") + QString::number(conicalGradient->center().y()) + << QLatin1String("angle:") + QString::number(conicalGradient->angle()); + break; + } + default: + qWarning() << "QtGradientUtils::styleSheetParameters(): gradient type" << gradient.type() << "not supported!"; + break; + } + + return result; +} + +static QStringList styleSheetStops(const QGradient &gradient) +{ + QStringList result; + foreach (QGradientStop stop, gradient.stops()) { + const QColor color = stop.second; + + const QString stopDescription = QLatin1String("stop:") + QString::number(stop.first) + QLatin1String(" rgba(") + + QString::number(color.red()) + QLatin1String(", ") + + QString::number(color.green()) + QLatin1String(", ") + + QString::number(color.blue()) + QLatin1String(", ") + + QString::number(color.alpha()) + QLatin1Char(')'); + result << stopDescription; + } + + return result; +} + +QString QtGradientUtils::styleSheetCode(const QGradient &gradient) +{ + QStringList gradientParameters; + gradientParameters << styleSheetParameters(gradient) << styleSheetStops(gradient); + + return styleSheetFillName(gradient) + QLatin1Char('(') + gradientParameters.join(QLatin1String(", ")) + QLatin1Char(')'); +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtgradientutils.h b/tools/shared/qtgradienteditor/qtgradientutils.h new file mode 100644 index 0000000..2e35652 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientutils.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRADIENTUTILS_H +#define GRADIENTUTILS_H + +#include <QtGui/QGradient> +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +class QtGradientManager; + +class QtGradientUtils +{ +public: + static QString styleSheetCode(const QGradient &gradient); + // utils methods, they could be outside of this class + static QString saveState(const QtGradientManager *manager); + static void restoreState(QtGradientManager *manager, const QString &state); + + static QPixmap gradientPixmap(const QGradient &gradient, const QSize &size = QSize(64, 64), bool checkeredBackground = false); + +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientview.cpp b/tools/shared/qtgradienteditor/qtgradientview.cpp new file mode 100644 index 0000000..ac8ed17 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientview.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientview.h" +#include "qtgradientmanager.h" +#include "qtgradientdialog.h" +#include "qtgradientutils.h" +#include <QtGui/QPainter> +#include <QtGui/QMessageBox> +#include <QtGui/QClipboard> + +QT_BEGIN_NAMESPACE + +void QtGradientView::slotGradientAdded(const QString &id, const QGradient &gradient) +{ + QListWidgetItem *item = new QListWidgetItem(QtGradientUtils::gradientPixmap(gradient), id, m_ui.listWidget); + item->setToolTip(id); + item->setSizeHint(QSize(72, 84)); + item->setFlags(item->flags() | Qt::ItemIsEditable); + + m_idToItem[id] = item; + m_itemToId[item] = id; +} + +void QtGradientView::slotGradientRenamed(const QString &id, const QString &newId) +{ + if (!m_idToItem.contains(id)) + return; + + QListWidgetItem *item = m_idToItem.value(id); + item->setText(newId); + item->setToolTip(newId); + m_itemToId[item] = newId; + m_idToItem.remove(id); + m_idToItem[newId] = item; +} + +void QtGradientView::slotGradientChanged(const QString &id, const QGradient &newGradient) +{ + if (!m_idToItem.contains(id)) + return; + + QListWidgetItem *item = m_idToItem.value(id); + item->setIcon(QtGradientUtils::gradientPixmap(newGradient)); +} + +void QtGradientView::slotGradientRemoved(const QString &id) +{ + if (!m_idToItem.contains(id)) + return; + + QListWidgetItem *item = m_idToItem.value(id); + delete item; + m_itemToId.remove(item); + m_idToItem.remove(id); +} + +void QtGradientView::slotNewGradient() +{ + bool ok; + QListWidgetItem *item = m_ui.listWidget->currentItem(); + QGradient grad = QLinearGradient(); + if (item) + grad = m_manager->gradients().value(m_itemToId.value(item)); + QGradient gradient = QtGradientDialog::getGradient(&ok, grad, this); + if (!ok) + return; + + QString id = m_manager->addGradient(tr("Grad"), gradient); + m_ui.listWidget->setCurrentItem(m_idToItem.value(id)); +} + +void QtGradientView::slotEditGradient() +{ + bool ok; + QListWidgetItem *item = m_ui.listWidget->currentItem(); + if (!item) + return; + + const QString id = m_itemToId.value(item); + QGradient grad = m_manager->gradients().value(id); + QGradient gradient = QtGradientDialog::getGradient(&ok, grad, this); + if (!ok) + return; + + m_manager->changeGradient(id, gradient); +} + +void QtGradientView::slotRemoveGradient() +{ + QListWidgetItem *item = m_ui.listWidget->currentItem(); + if (!item) + return; + + if (QMessageBox::question(this, tr("Remove Gradient"), + tr("Are you sure you want to remove the selected gradient?"), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Yes) + return; + + const QString id = m_itemToId.value(item); + m_manager->removeGradient(id); +} + +void QtGradientView::slotRenameGradient() +{ + QListWidgetItem *item = m_ui.listWidget->currentItem(); + if (!item) + return; + + m_ui.listWidget->editItem(item); +} + +void QtGradientView::slotRenameGradient(QListWidgetItem *item) +{ + if (!item) + return; + + const QString id = m_itemToId.value(item); + m_manager->renameGradient(id, item->text()); +} + +void QtGradientView::slotCurrentItemChanged(QListWidgetItem *item) +{ + m_editAction->setEnabled(item); + m_renameAction->setEnabled(item); + m_removeAction->setEnabled(item); + emit currentGradientChanged(m_itemToId.value(item)); +} + +void QtGradientView::slotGradientActivated(QListWidgetItem *item) +{ + const QString id = m_itemToId.value(item); + if (!id.isEmpty()) + emit gradientActivated(id); +} + +QtGradientView::QtGradientView(QWidget *parent) + : QWidget(parent) +{ + m_manager = 0; + + m_ui.setupUi(this); + + m_ui.listWidget->setViewMode(QListView::IconMode); + m_ui.listWidget->setMovement(QListView::Static); + m_ui.listWidget->setTextElideMode(Qt::ElideRight); + m_ui.listWidget->setResizeMode(QListWidget::Adjust); + m_ui.listWidget->setIconSize(QSize(64, 64)); + m_ui.listWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + + QPalette pal = m_ui.listWidget->viewport()->palette(); + int pixSize = 18; + QPixmap pm(2 * pixSize, 2 * pixSize); + + QColor c1 = palette().color(QPalette::Midlight); + QColor c2 = palette().color(QPalette::Dark); + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, c1); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, c1); + pmp.fillRect(0, pixSize, pixSize, pixSize, c2); + pmp.fillRect(pixSize, 0, pixSize, pixSize, c2); + + pal.setBrush(QPalette::Base, QBrush(pm)); + m_ui.listWidget->viewport()->setPalette(pal); + + connect(m_ui.listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(slotGradientActivated(QListWidgetItem *))); + connect(m_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(slotRenameGradient(QListWidgetItem *))); + connect(m_ui.listWidget, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(slotCurrentItemChanged(QListWidgetItem *))); + + m_newAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/plus.png")), tr("New..."), this); + m_editAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/edit.png")), tr("Edit..."), this); + m_renameAction = new QAction(tr("Rename"), this); + m_removeAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/minus.png")), tr("Remove"), this); + + connect(m_newAction, SIGNAL(triggered()), this, SLOT(slotNewGradient())); + connect(m_editAction, SIGNAL(triggered()), this, SLOT(slotEditGradient())); + connect(m_removeAction, SIGNAL(triggered()), this, SLOT(slotRemoveGradient())); + connect(m_renameAction, SIGNAL(triggered()), this, SLOT(slotRenameGradient())); + + m_ui.listWidget->addAction(m_newAction); + m_ui.listWidget->addAction(m_editAction); + m_ui.listWidget->addAction(m_renameAction); + m_ui.listWidget->addAction(m_removeAction); + + m_ui.newButton->setDefaultAction(m_newAction); + m_ui.editButton->setDefaultAction(m_editAction); + m_ui.renameButton->setDefaultAction(m_renameAction); + m_ui.removeButton->setDefaultAction(m_removeAction); + + m_ui.listWidget->setContextMenuPolicy(Qt::ActionsContextMenu); +} + +void QtGradientView::setGradientManager(QtGradientManager *manager) +{ + if (m_manager == manager) + return; + + if (m_manager) { + disconnect(m_manager, SIGNAL(gradientAdded(const QString &, const QGradient &)), + this, SLOT(slotGradientAdded(const QString &, const QGradient &))); + disconnect(m_manager, SIGNAL(gradientRenamed(const QString &, const QString &)), + this, SLOT(slotGradientRenamed(const QString &, const QString &))); + disconnect(m_manager, SIGNAL(gradientChanged(const QString &, const QGradient &)), + this, SLOT(slotGradientChanged(const QString &, const QGradient &))); + disconnect(m_manager, SIGNAL(gradientRemoved(const QString &)), + this, SLOT(slotGradientRemoved(const QString &))); + + m_ui.listWidget->clear(); + m_idToItem.clear(); + m_itemToId.clear(); + } + + m_manager = manager; + + if (!m_manager) + return; + + QMap<QString, QGradient> gradients = m_manager->gradients(); + QMapIterator<QString, QGradient> itGrad(gradients); + while (itGrad.hasNext()) { + itGrad.next(); + slotGradientAdded(itGrad.key(), itGrad.value()); + } + + connect(m_manager, SIGNAL(gradientAdded(const QString &, const QGradient &)), + this, SLOT(slotGradientAdded(const QString &, const QGradient &))); + connect(m_manager, SIGNAL(gradientRenamed(const QString &, const QString &)), + this, SLOT(slotGradientRenamed(const QString &, const QString &))); + connect(m_manager, SIGNAL(gradientChanged(const QString &, const QGradient &)), + this, SLOT(slotGradientChanged(const QString &, const QGradient &))); + connect(m_manager, SIGNAL(gradientRemoved(const QString &)), + this, SLOT(slotGradientRemoved(const QString &))); +} + +QtGradientManager *QtGradientView::gradientManager() const +{ + return m_manager; +} + +void QtGradientView::setCurrentGradient(const QString &id) +{ + QListWidgetItem *item = m_idToItem.value(id); + if (!item) + return; + + m_ui.listWidget->setCurrentItem(item); +} + +QString QtGradientView::currentGradient() const +{ + return m_itemToId.value(m_ui.listWidget->currentItem()); +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtgradientview.h b/tools/shared/qtgradienteditor/qtgradientview.h new file mode 100644 index 0000000..b1fafd7 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientview.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRADIENTVIEW_H +#define GRADIENTVIEW_H + +#include <QtGui/QWidget> +#include <QtCore/QMap> +#include "ui_qtgradientview.h" + +QT_BEGIN_NAMESPACE + +class QtGradientManager; +class QListViewItem; +class QAction; + +class QtGradientView : public QWidget +{ + Q_OBJECT +public: + QtGradientView(QWidget *parent = 0); + + void setGradientManager(QtGradientManager *manager); + QtGradientManager *gradientManager() const; + + void setCurrentGradient(const QString &id); + QString currentGradient() const; + +signals: + void currentGradientChanged(const QString &id); + void gradientActivated(const QString &id); + +private slots: + void slotGradientAdded(const QString &id, const QGradient &gradient); + void slotGradientRenamed(const QString &id, const QString &newId); + void slotGradientChanged(const QString &id, const QGradient &newGradient); + void slotGradientRemoved(const QString &id); + void slotNewGradient(); + void slotEditGradient(); + void slotRemoveGradient(); + void slotRenameGradient(); + void slotRenameGradient(QListWidgetItem *item); + void slotCurrentItemChanged(QListWidgetItem *item); + void slotGradientActivated(QListWidgetItem *item); + +private: + QMap<QString, QListWidgetItem *> m_idToItem; + QMap<QListWidgetItem *, QString> m_itemToId; + + QAction *m_newAction; + QAction *m_editAction; + QAction *m_renameAction; + QAction *m_removeAction; + + QtGradientManager *m_manager; + Ui::QtGradientView m_ui; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/shared/qtgradienteditor/qtgradientview.ui b/tools/shared/qtgradienteditor/qtgradientview.ui new file mode 100644 index 0000000..af7267e --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientview.ui @@ -0,0 +1,135 @@ +<ui version="4.0" > + <class>QtGradientView</class> + <widget class="QWidget" name="QtGradientView" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>484</width> + <height>228</height> + </rect> + </property> + <property name="windowTitle" > + <string>Gradient View</string> + </property> + <layout class="QVBoxLayout" > + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" > + <item> + <widget class="QToolButton" name="newButton" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Minimum" hsizetype="Minimum" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>New...</string> + </property> + <property name="toolButtonStyle" > + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="editButton" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Minimum" hsizetype="Minimum" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Edit...</string> + </property> + <property name="toolButtonStyle" > + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="renameButton" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Minimum" hsizetype="Minimum" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Rename</string> + </property> + <property name="toolButtonStyle" > + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="removeButton" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Minimum" hsizetype="Minimum" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Remove</string> + </property> + <property name="toolButtonStyle" > + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>71</width> + <height>26</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QListWidget" name="listWidget" /> + </item> + </layout> + </widget> + <tabstops> + <tabstop>listWidget</tabstop> + <tabstop>newButton</tabstop> + <tabstop>editButton</tabstop> + <tabstop>renameButton</tabstop> + <tabstop>removeButton</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/tools/shared/qtgradienteditor/qtgradientviewdialog.cpp b/tools/shared/qtgradienteditor/qtgradientviewdialog.cpp new file mode 100644 index 0000000..c139ec4 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientviewdialog.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientviewdialog.h" +#include "qtgradientmanager.h" +#include <QtGui/QPushButton> + +QT_BEGIN_NAMESPACE + +QtGradientViewDialog::QtGradientViewDialog(QWidget *parent) + : QDialog(parent) +{ + m_ui.setupUi(this); + m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + connect(m_ui.gradientView, SIGNAL(currentGradientChanged(const QString &)), + this, SLOT(slotGradientSelected(const QString &))); + connect(m_ui.gradientView, SIGNAL(gradientActivated(const QString &)), + this, SLOT(slotGradientActivated(const QString &))); +} + +void QtGradientViewDialog::setGradientManager(QtGradientManager *manager) +{ + m_ui.gradientView->setGradientManager(manager); +} + +QGradient QtGradientViewDialog::getGradient(bool *ok, QtGradientManager *manager, QWidget *parent, const QString &caption) +{ + QtGradientViewDialog dlg(parent); + dlg.setGradientManager(manager); + dlg.setWindowTitle(caption); + QGradient grad = QLinearGradient(); + const int res = dlg.exec(); + if (res == QDialog::Accepted) + grad = dlg.m_ui.gradientView->gradientManager()->gradients().value(dlg.m_ui.gradientView->currentGradient()); + if (ok) + *ok = res == QDialog::Accepted; + return grad; +} + +void QtGradientViewDialog::slotGradientSelected(const QString &id) +{ + m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!id.isEmpty()); +} + +void QtGradientViewDialog::slotGradientActivated(const QString &id) +{ + Q_UNUSED(id) + accept(); +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtgradientviewdialog.h b/tools/shared/qtgradienteditor/qtgradientviewdialog.h new file mode 100644 index 0000000..2ec7cdd --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientviewdialog.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRADIENTVIEWDIALOG_H +#define GRADIENTVIEWDIALOG_H + +#include <QtGui/QWidget> +#include <QtCore/QMap> +#include "ui_qtgradientviewdialog.h" + +QT_BEGIN_NAMESPACE + +class QtGradientManager; + +class QtGradientViewDialog : public QDialog +{ + Q_OBJECT +public: + QtGradientViewDialog(QWidget *parent = 0); + + void setGradientManager(QtGradientManager *manager); + QtGradientManager *gradientManager() const; + + static QGradient getGradient(bool *ok, QtGradientManager *manager, QWidget *parent = 0, const QString &caption = tr("Select Gradient", 0)); + +private slots: + void slotGradientSelected(const QString &id); + void slotGradientActivated(const QString &id); + +private: + Ui::QtGradientViewDialog m_ui; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/tools/shared/qtgradienteditor/qtgradientviewdialog.ui b/tools/shared/qtgradienteditor/qtgradientviewdialog.ui new file mode 100644 index 0000000..ed53209 --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientviewdialog.ui @@ -0,0 +1,121 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>QtGradientViewDialog</class> + <widget class="QDialog" name="QtGradientViewDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>178</width> + <height>72</height> + </rect> + </property> + <property name="windowTitle" > + <string>Select Gradient</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QtGradientView" name="gradientView" > + <property name="sizePolicy" > + <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QtGradientView</class> + <extends>QFrame</extends> + <header>qtgradientview.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>QtGradientViewDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel" > + <x>72</x> + <y>224</y> + </hint> + <hint type="destinationlabel" > + <x>21</x> + <y>243</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>QtGradientViewDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>168</x> + <y>233</y> + </hint> + <hint type="destinationlabel" > + <x>152</x> + <y>251</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/shared/qtgradienteditor/qtgradientwidget.cpp b/tools/shared/qtgradienteditor/qtgradientwidget.cpp new file mode 100644 index 0000000..3f6b48d --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientwidget.cpp @@ -0,0 +1,817 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtgradientwidget.h" +#include <QtCore/QMap> +#include <QtGui/QImage> +#include <QtGui/QPainter> +#include <QtGui/QScrollBar> +#include <QtGui/QMouseEvent> + +#define _USE_MATH_DEFINES + + +#include "math.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +QT_BEGIN_NAMESPACE + +class QtGradientWidgetPrivate +{ + QtGradientWidget *q_ptr; + Q_DECLARE_PUBLIC(QtGradientWidget) +public: + QPointF fromViewport(const QPointF &point) const; + QPointF toViewport(const QPointF &point) const; +// void setupDrag(QtGradientStop *stop, int x); + + QPointF checkRange(const QPointF &point) const; + QRectF pointRect(const QPointF &point, double size) const; + + double correctAngle(double angle) const; + void setAngleConical(double angle); + + void paintPoint(QPainter *painter, const QPointF &point, double size) const; + + double m_handleSize; + bool m_backgroundCheckered; + + QGradientStops m_gradientStops; + QGradient::Type m_gradientType; + QGradient::Spread m_gradientSpread; + QPointF m_startLinear; + QPointF m_endLinear; + QPointF m_centralRadial; + QPointF m_focalRadial; + qreal m_radiusRadial; + QPointF m_centralConical; + qreal m_angleConical; + + enum Handle { + NoHandle, + StartLinearHandle, + EndLinearHandle, + CentralRadialHandle, + FocalRadialHandle, + RadiusRadialHandle, + CentralConicalHandle, + AngleConicalHandle + }; + + Handle m_dragHandle; + QPointF m_dragOffset; + //double m_radiusOffset; + double m_radiusFactor; + double m_dragRadius; + double m_angleOffset; + double m_dragAngle; +}; + +double QtGradientWidgetPrivate::correctAngle(double angle) const +{ + double a = angle; + while (a >= 360) + a -= 360; + while (a < 0) + a += 360; + return a; +} + +void QtGradientWidgetPrivate::setAngleConical(double angle) +{ + double a = correctAngle(angle); + if (m_angleConical == a) + return; + m_angleConical = a; + emit q_ptr->angleConicalChanged(m_angleConical); +} + +QRectF QtGradientWidgetPrivate::pointRect(const QPointF &point, double size) const +{ + return QRectF(point.x() - size / 2, point.y() - size / 2, size, size); +} + +QPointF QtGradientWidgetPrivate::checkRange(const QPointF &point) const +{ + QPointF p = point; + if (p.x() > 1) + p.setX(1); + else if (p.x() < 0) + p.setX(0); + if (p.y() > 1) + p.setY(1); + else if (p.y() < 0) + p.setY(0); + return p; +} + +QPointF QtGradientWidgetPrivate::fromViewport(const QPointF &point) const +{ + QSize size = q_ptr->size(); + return QPointF(point.x() / size.width(), point.y() / size.height()); +} + +QPointF QtGradientWidgetPrivate::toViewport(const QPointF &point) const +{ + QSize size = q_ptr->size(); + return QPointF(point.x() * size.width(), point.y() * size.height()); +} + +void QtGradientWidgetPrivate::paintPoint(QPainter *painter, const QPointF &point, double size) const +{ + QPointF pf = toViewport(point); + QRectF rf = pointRect(pf, size); + + QPen pen; + pen.setWidthF(1); + QColor alphaZero = Qt::white; + alphaZero.setAlpha(0); + + painter->save(); + painter->drawEllipse(rf); + + /* + painter->save(); + + QLinearGradient lgV(0, rf.top(), 0, rf.bottom()); + lgV.setColorAt(0, alphaZero); + lgV.setColorAt(0.25, Qt::white); + lgV.setColorAt(0.25, Qt::white); + lgV.setColorAt(1, alphaZero); + pen.setBrush(lgV); + painter->setPen(pen); + + painter->drawLine(QPointF(pf.x(), rf.top()), QPointF(pf.x(), rf.bottom())); + + QLinearGradient lgH(rf.left(), 0, rf.right(), 0); + lgH.setColorAt(0, alphaZero); + lgH.setColorAt(0.5, Qt::white); + lgH.setColorAt(1, alphaZero); + pen.setBrush(lgH); + painter->setPen(pen); + + painter->drawLine(QPointF(rf.left(), pf.y()), QPointF(rf.right(), pf.y())); + + painter->restore(); + */ + + painter->restore(); +} + +/* +void QtGradientWidgetPrivate::setupDrag(QtGradientStop *stop, int x) +{ + m_model->setCurrentStop(stop); + + int viewportX = qRound(toViewport(stop->position())); + m_dragOffset = x - viewportX; + + QList<QtGradientStop *> stops = m_stops; + m_stops.clear(); + QListIterator<QtGradientStop *> itStop(stops); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (m_model->isSelected(s) || s == stop) { + m_dragStops[s] = s->position() - stop->position(); + m_stops.append(s); + } else { + m_dragOriginal[s->position()] = s->color(); + } + } + itStop.toFront(); + while (itStop.hasNext()) { + QtGradientStop *s = itStop.next(); + if (!m_model->isSelected(s)) + m_stops.append(s); + } + m_stops.removeAll(stop); + m_stops.prepend(stop); +} +*/ +//////////////////////////// + +QtGradientWidget::QtGradientWidget(QWidget *parent) + : QWidget(parent) +{ + d_ptr = new QtGradientWidgetPrivate; + d_ptr->q_ptr = this; + d_ptr->m_backgroundCheckered = true; + d_ptr->m_handleSize = 20.0; + d_ptr->m_gradientType = QGradient::LinearGradient; + d_ptr->m_startLinear = QPointF(0, 0); + d_ptr->m_endLinear = QPointF(1, 1); + d_ptr->m_centralRadial = QPointF(0.5, 0.5); + d_ptr->m_focalRadial = QPointF(0.5, 0.5); + d_ptr->m_radiusRadial = 0.5; + d_ptr->m_centralConical = QPointF(0.5, 0.5); + d_ptr->m_angleConical = 0; + d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle; + + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); +} + +QtGradientWidget::~QtGradientWidget() +{ + delete d_ptr; +} + +QSize QtGradientWidget::sizeHint() const +{ + return QSize(176, 176); +} + +QSize QtGradientWidget::minimumSizeHint() const +{ + return QSize(128, 128); +} + +int QtGradientWidget::heightForWidth(int w) const +{ + return w; +} + +void QtGradientWidget::setBackgroundCheckered(bool checkered) +{ + if (d_ptr->m_backgroundCheckered == checkered) + return; + d_ptr->m_backgroundCheckered = checkered; + update(); +} + +bool QtGradientWidget::isBackgroundCheckered() const +{ + return d_ptr->m_backgroundCheckered; +} + +void QtGradientWidget::mousePressEvent(QMouseEvent *e) +{ + if (e->button() != Qt::LeftButton) + return; + + QPoint p = e->pos(); + if (d_ptr->m_gradientType == QGradient::LinearGradient) { + QPointF startPoint = d_ptr->toViewport(d_ptr->m_startLinear); + double x = p.x() - startPoint.x(); + double y = p.y() - startPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) { + d_ptr->m_dragHandle = QtGradientWidgetPrivate::StartLinearHandle; + d_ptr->m_dragOffset = QPointF(x, y); + update(); + return; + } + + QPointF endPoint = d_ptr->toViewport(d_ptr->m_endLinear); + x = p.x() - endPoint.x(); + y = p.y() - endPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) { + d_ptr->m_dragHandle = QtGradientWidgetPrivate::EndLinearHandle; + d_ptr->m_dragOffset = QPointF(x, y); + update(); + return; + } + } else if (d_ptr->m_gradientType == QGradient::RadialGradient) { + QPointF focalPoint = d_ptr->toViewport(d_ptr->m_focalRadial); + double x = p.x() - focalPoint.x(); + double y = p.y() - focalPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 9) > (x * x + y * y)) { + d_ptr->m_dragHandle = QtGradientWidgetPrivate::FocalRadialHandle; + d_ptr->m_dragOffset = QPointF(x, y); + update(); + return; + } + + QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial); + x = p.x() - centralPoint.x(); + y = p.y() - centralPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) { + d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralRadialHandle; + d_ptr->m_dragOffset = QPointF(x, y); + update(); + return; + } + + QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial); + QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3); + QRectF r1(0, r.y(), size().width(), r.height()); + QRectF r2(r.x(), 0, r.width(), r.y()); + QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height()); + QPointF pF(p.x(), p.y()); + if (r1.contains(pF) || r2.contains(pF) || r3.contains(pF)) { + x = pF.x() / size().width() - d_ptr->m_centralRadial.x(); + y = pF.y() / size().height() - d_ptr->m_centralRadial.y(); + double clickRadius = sqrt(x * x + y * y); + //d_ptr->m_radiusOffset = d_ptr->m_radiusRadial - clickRadius; + d_ptr->m_radiusFactor = d_ptr->m_radiusRadial / clickRadius; + if (d_ptr->m_radiusFactor == 0) + d_ptr->m_radiusFactor = 1; + d_ptr->m_dragRadius = d_ptr->m_radiusRadial; + d_ptr->m_dragHandle = QtGradientWidgetPrivate::RadiusRadialHandle; + mouseMoveEvent(e); + update(); + return; + } + } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) { + QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical); + double x = p.x() - centralPoint.x(); + double y = p.y() - centralPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) { + d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralConicalHandle; + d_ptr->m_dragOffset = QPointF(x, y); + update(); + return; + } + double radius = size().width(); + if (size().height() < radius) + radius = size().height(); + radius /= 2; + double corr = d_ptr->m_handleSize / 3; + radius -= corr; + QPointF vp = d_ptr->toViewport(d_ptr->m_centralConical); + x = p.x() - vp.x(); + y = p.y() - vp.y(); + if (((radius - corr) * (radius - corr) < (x * x + y * y)) && + ((radius + corr) * (radius + corr) > (x * x + y * y))) { + QPointF central = d_ptr->toViewport(d_ptr->m_centralConical); + QPointF current(e->pos().x(), e->pos().y()); + x = current.x() - central.x(); + y = current.y() - central.y(); + x /= size().width() / 2; + y /= size().height() / 2; + double r = sqrt(x * x + y * y); + + double arcSin = asin(y / r); + double arcCos = acos(x / r); + + double angle = arcCos * 180 / M_PI; + if (arcSin > 0) { + angle = -angle; + } + + d_ptr->m_angleOffset = d_ptr->m_angleConical - angle; + d_ptr->m_dragAngle = d_ptr->m_angleConical; + d_ptr->m_dragHandle = QtGradientWidgetPrivate::AngleConicalHandle; + update(); + return; + } + } +} + +void QtGradientWidget::mouseReleaseEvent(QMouseEvent *e) +{ + Q_UNUSED(e) + d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle; + update(); +} + +void QtGradientWidget::mouseMoveEvent(QMouseEvent *e) +{ + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::NoHandle) + return; + + QPointF newPos = QPointF((double)e->pos().x() - d_ptr->m_dragOffset.x(), + (double)e->pos().y() - d_ptr->m_dragOffset.y()); + QPointF newPoint = d_ptr->fromViewport(newPos); + if (newPoint.x() < 0) + newPoint.setX(0); + else if (newPoint.x() > 1) + newPoint.setX(1); + if (newPoint.y() < 0) + newPoint.setY(0); + else if (newPoint.y() > 1) + newPoint.setY(1); + + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle) { + d_ptr->m_startLinear = newPoint; + emit startLinearChanged(newPoint); + } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle) { + d_ptr->m_endLinear = newPoint; + emit endLinearChanged(newPoint); + } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle) { + d_ptr->m_centralRadial = newPoint; + emit centralRadialChanged(newPoint); + } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle) { + d_ptr->m_focalRadial = newPoint; + emit focalRadialChanged(newPoint); + } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) { + QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial); + QPointF pF(e->pos().x(), e->pos().y()); + double x = pF.x() - centralPoint.x(); + double y = pF.y() - centralPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) { + if (d_ptr->m_radiusRadial != d_ptr->m_dragRadius) { + d_ptr->m_radiusRadial = d_ptr->m_dragRadius; + emit radiusRadialChanged(d_ptr->m_radiusRadial); + } + } else { + x = pF.x() / size().width() - d_ptr->m_centralRadial.x(); + y = pF.y() / size().height() - d_ptr->m_centralRadial.y(); + double moveRadius = sqrt(x * x + y * y); + //double newRadius = moveRadius + d_ptr->m_radiusOffset; + double newRadius = moveRadius * d_ptr->m_radiusFactor; + if (newRadius > 2) + newRadius = 2; + d_ptr->m_radiusRadial = newRadius; + emit radiusRadialChanged(d_ptr->m_radiusRadial); + } + } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle) { + d_ptr->m_centralConical = newPoint; + emit centralConicalChanged(newPoint); + } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) { + QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical); + QPointF pF(e->pos().x(), e->pos().y()); + double x = pF.x() - centralPoint.x(); + double y = pF.y() - centralPoint.y(); + + if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) { + if (d_ptr->m_angleConical != d_ptr->m_dragAngle) { + d_ptr->m_angleConical = d_ptr->m_dragAngle; + emit angleConicalChanged(d_ptr->m_angleConical); + } + } else { + QPointF central = d_ptr->toViewport(d_ptr->m_centralConical); + QPointF current = pF; + x = current.x() - central.x(); + y = current.y() - central.y(); + x /= size().width() / 2; + y /= size().height() / 2; + double r = sqrt(x * x + y * y); + + double arcSin = asin(y / r); + double arcCos = acos(x / r); + + double angle = arcCos * 180 / M_PI; + if (arcSin > 0) { + angle = -angle; + } + + angle += d_ptr->m_angleOffset; + + d_ptr->setAngleConical(angle); + } + } + update(); +} + +void QtGradientWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + mousePressEvent(e); +} + +void QtGradientWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e) + + QPainter p(this); + + if (d_ptr->m_backgroundCheckered) { + int pixSize = 40; + QPixmap pm(2 * pixSize, 2 * pixSize); + + QPainter pmp(&pm); + pmp.fillRect(0, 0, pixSize, pixSize, Qt::white); + pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white); + pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black); + pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black); + + p.setBrushOrigin((size().width() % pixSize + pixSize) / 2, (size().height() % pixSize + pixSize) / 2); + p.fillRect(rect(), pm); + p.setBrushOrigin(0, 0); + } + + QGradient *gradient = 0; + switch (d_ptr->m_gradientType) { + case QGradient::LinearGradient: + gradient = new QLinearGradient(d_ptr->m_startLinear, d_ptr->m_endLinear); + break; + case QGradient::RadialGradient: + gradient = new QRadialGradient(d_ptr->m_centralRadial, d_ptr->m_radiusRadial, d_ptr->m_focalRadial); + break; + case QGradient::ConicalGradient: + gradient = new QConicalGradient(d_ptr->m_centralConical, d_ptr->m_angleConical); + break; + default: + break; + } + if (!gradient) + return; + + gradient->setStops(d_ptr->m_gradientStops); + gradient->setSpread(d_ptr->m_gradientSpread); + + p.save(); + p.scale(size().width(), size().height()); + p.fillRect(QRect(0, 0, 1, 1), *gradient); + p.restore(); + + p.setRenderHint(QPainter::Antialiasing); + + QColor c = QColor::fromRgbF(0.5, 0.5, 0.5, 0.5); + QBrush br(c); + p.setBrush(br); + QPen pen(Qt::white); + pen.setWidthF(1); + p.setPen(pen); + QPen dragPen = pen; + dragPen.setWidthF(2); + if (d_ptr->m_gradientType == QGradient::LinearGradient) { + p.save(); + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle) + p.setPen(dragPen); + d_ptr->paintPoint(&p, d_ptr->m_startLinear, d_ptr->m_handleSize); + p.restore(); + + p.save(); + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle) + p.setPen(dragPen); + d_ptr->paintPoint(&p, d_ptr->m_endLinear, d_ptr->m_handleSize); + p.restore(); + } else if (d_ptr->m_gradientType == QGradient::RadialGradient) { + QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial); + + p.save(); + QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3); + QRectF r1(0, r.y(), size().width(), r.height()); + QRectF r2(r.x(), 0, r.width(), r.y()); + QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height()); + p.fillRect(r1, c); + p.fillRect(r2, c); + p.fillRect(r3, c); + p.setBrush(Qt::NoBrush); + p.save(); + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle) + p.setPen(dragPen); + d_ptr->paintPoint(&p, d_ptr->m_centralRadial, d_ptr->m_handleSize); + p.restore(); + + QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial * size().width(), + central.y() - d_ptr->m_radiusRadial * size().height(), + 2 * d_ptr->m_radiusRadial * size().width(), + 2 * d_ptr->m_radiusRadial * size().height()); + p.setClipRect(r1); + p.setClipRect(r2, Qt::UniteClip); + p.setClipRect(r3, Qt::UniteClip); + p.drawEllipse(rect); + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) { + p.save(); + p.setPen(dragPen); + QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(), + central.y() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height(), + 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(), + 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height()); + p.drawEllipse(rect); + + p.restore(); + } + p.restore(); + + p.save(); + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle) + p.setPen(dragPen); + d_ptr->paintPoint(&p, d_ptr->m_focalRadial, 2 * d_ptr->m_handleSize / 3); + p.restore(); + } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) { + double radius = size().width(); + if (size().height() < radius) + radius = size().height(); + radius /= 2; + double corr = d_ptr->m_handleSize / 3; + radius -= corr; + QPointF central = d_ptr->toViewport(d_ptr->m_centralConical); + + p.save(); + p.setBrush(Qt::NoBrush); + QPen pen2(c); + pen2.setWidthF(2 * d_ptr->m_handleSize / 3); + p.setPen(pen2); + p.drawEllipse(d_ptr->pointRect(central, 2 * radius)); + p.restore(); + + p.save(); + p.setBrush(Qt::NoBrush); + int pointCount = 2; + for (int i = 0; i < pointCount; i++) { + QPointF ang(cos(M_PI * (i * 180.0 / pointCount + d_ptr->m_angleConical) / 180) * size().width() / 2, + -sin(M_PI * (i * 180.0 / pointCount + d_ptr->m_angleConical) / 180) * size().height() / 2); + double mod = sqrt(ang.x() * ang.x() + ang.y() * ang.y()); + p.drawLine(QPointF(central.x() + ang.x() * (radius - corr) / mod, + central.y() + ang.y() * (radius - corr) / mod), + QPointF(central.x() + ang.x() * (radius + corr) / mod, + central.y() + ang.y() * (radius + corr) / mod)); + p.drawLine(QPointF(central.x() - ang.x() * (radius - corr) / mod, + central.y() - ang.y() * (radius - corr) / mod), + QPointF(central.x() - ang.x() * (radius + corr) / mod, + central.y() - ang.y() * (radius + corr) / mod)); + } + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) { + p.save(); + p.setPen(dragPen); + QPointF ang(cos(M_PI * (d_ptr->m_angleConical - d_ptr->m_angleOffset) / 180) * size().width() / 2, + -sin(M_PI * (d_ptr->m_angleConical - d_ptr->m_angleOffset) / 180) * size().height() / 2); + double mod = sqrt(ang.x() * ang.x() + ang.y() * ang.y()); + p.drawLine(QPointF(central.x() + ang.x() * (radius - corr) / mod, + central.y() + ang.y() * (radius - corr) / mod), + QPointF(central.x() + ang.x() * (radius + corr) / mod, + central.y() + ang.y() * (radius + corr) / mod)); + p.restore(); + } + + p.restore(); + + p.save(); + if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle) + p.setPen(dragPen); + d_ptr->paintPoint(&p, d_ptr->m_centralConical, d_ptr->m_handleSize); + p.restore(); + + } + + delete gradient; +} + +void QtGradientWidget::setGradientStops(const QGradientStops &stops) +{ + d_ptr->m_gradientStops = stops; + update(); +} + +QGradientStops QtGradientWidget::gradientStops() const +{ + return d_ptr->m_gradientStops; +} + +void QtGradientWidget::setGradientType(QGradient::Type type) +{ + if (type == QGradient::NoGradient) + return; + if (d_ptr->m_gradientType == type) + return; + + d_ptr->m_gradientType = type; + update(); +} + +QGradient::Type QtGradientWidget::gradientType() const +{ + return d_ptr->m_gradientType; +} + +void QtGradientWidget::setGradientSpread(QGradient::Spread spread) +{ + if (d_ptr->m_gradientSpread == spread) + return; + + d_ptr->m_gradientSpread = spread; + update(); +} + +QGradient::Spread QtGradientWidget::gradientSpread() const +{ + return d_ptr->m_gradientSpread; +} + +void QtGradientWidget::setStartLinear(const QPointF &point) +{ + if (d_ptr->m_startLinear == point) + return; + + d_ptr->m_startLinear = d_ptr->checkRange(point); + update(); +} + +QPointF QtGradientWidget::startLinear() const +{ + return d_ptr->m_startLinear; +} + +void QtGradientWidget::setEndLinear(const QPointF &point) +{ + if (d_ptr->m_endLinear == point) + return; + + d_ptr->m_endLinear = d_ptr->checkRange(point); + update(); +} + +QPointF QtGradientWidget::endLinear() const +{ + return d_ptr->m_endLinear; +} + +void QtGradientWidget::setCentralRadial(const QPointF &point) +{ + if (d_ptr->m_centralRadial == point) + return; + + d_ptr->m_centralRadial = point; + update(); +} + +QPointF QtGradientWidget::centralRadial() const +{ + return d_ptr->m_centralRadial; +} + +void QtGradientWidget::setFocalRadial(const QPointF &point) +{ + if (d_ptr->m_focalRadial == point) + return; + + d_ptr->m_focalRadial = point; + update(); +} + +QPointF QtGradientWidget::focalRadial() const +{ + return d_ptr->m_focalRadial; +} + +void QtGradientWidget::setRadiusRadial(qreal radius) +{ + if (d_ptr->m_radiusRadial == radius) + return; + + d_ptr->m_radiusRadial = radius; + update(); +} + +qreal QtGradientWidget::radiusRadial() const +{ + return d_ptr->m_radiusRadial; +} + +void QtGradientWidget::setCentralConical(const QPointF &point) +{ + if (d_ptr->m_centralConical == point) + return; + + d_ptr->m_centralConical = point; + update(); +} + +QPointF QtGradientWidget::centralConical() const +{ + return d_ptr->m_centralConical; +} + +void QtGradientWidget::setAngleConical(qreal angle) +{ + if (d_ptr->m_angleConical == angle) + return; + + d_ptr->m_angleConical = angle; + update(); +} + +qreal QtGradientWidget::angleConical() const +{ + return d_ptr->m_angleConical; +} + +QT_END_NAMESPACE diff --git a/tools/shared/qtgradienteditor/qtgradientwidget.h b/tools/shared/qtgradienteditor/qtgradientwidget.h new file mode 100644 index 0000000..4dc740b --- /dev/null +++ b/tools/shared/qtgradienteditor/qtgradientwidget.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTGRADIENTWIDGET_H +#define QTGRADIENTWIDGET_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QtGradientWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered) +public: + QtGradientWidget(QWidget *parent = 0); + ~QtGradientWidget(); + + QSize minimumSizeHint() const; + QSize sizeHint() const; + int heightForWidth(int w) const; + + bool isBackgroundCheckered() const; + void setBackgroundCheckered(bool checkered); + + QGradientStops gradientStops() const; + + void setGradientType(QGradient::Type type); + QGradient::Type gradientType() const; + + void setGradientSpread(QGradient::Spread spread); + QGradient::Spread gradientSpread() const; + + void setStartLinear(const QPointF &point); + QPointF startLinear() const; + + void setEndLinear(const QPointF &point); + QPointF endLinear() const; + + void setCentralRadial(const QPointF &point); + QPointF centralRadial() const; + + void setFocalRadial(const QPointF &point); + QPointF focalRadial() const; + + void setRadiusRadial(qreal radius); + qreal radiusRadial() const; + + void setCentralConical(const QPointF &point); + QPointF centralConical() const; + + void setAngleConical(qreal angle); + qreal angleConical() const; + +public slots: + void setGradientStops(const QGradientStops &stops); +signals: + + void startLinearChanged(const QPointF &point); + void endLinearChanged(const QPointF &point); + void centralRadialChanged(const QPointF &point); + void focalRadialChanged(const QPointF &point); + void radiusRadialChanged(qreal radius); + void centralConicalChanged(const QPointF &point); + void angleConicalChanged(qreal angle); + +protected: + void paintEvent(QPaintEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseDoubleClickEvent(QMouseEvent *e); + +private: + class QtGradientWidgetPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtGradientWidget) + Q_DISABLE_COPY(QtGradientWidget) +}; + +QT_END_NAMESPACE + +#endif |