Warning, file /office/calligra/libs/widgets/KoGradientEditWidget.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2001-2002 Beno�t Vautrin <benoit.vautrin@free.fr>
0003    Copyright (C) 2002-2003 Rob Buis <buis@kde.org>
0004    Copyright (C) 2006-2008,2011 Jan Hambrecht <jaham@gmx.net>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "KoGradientEditWidget.h"
0023 
0024 #include <KoAbstractGradient.h>
0025 #include <KoStopGradient.h>
0026 #include <KoResourceServer.h>
0027 #include <KoResourceServerProvider.h>
0028 #include <KoSliderCombo.h>
0029 #include <KoColorPopupAction.h>
0030 
0031 #include <klocalizedstring.h>
0032 
0033 #include <QDoubleSpinBox>
0034 #include <QComboBox>
0035 #include <QFileInfo>
0036 #include <QPointF>
0037 #include <QLabel>
0038 #include <QPushButton>
0039 #include <QToolButton>
0040 #include <QGridLayout>
0041 #include <QRadialGradient>
0042 #include <QLinearGradient>
0043 #include <QConicalGradient>
0044 
0045 #include <math.h>
0046 
0047 void transferGradientPosition(const QGradient * srcGradient, QGradient * dstGradient)
0048 {
0049     // first check if gradients have the same type
0050     if (srcGradient->type() == dstGradient->type()) {
0051         switch (srcGradient->type()) {
0052         case QGradient::LinearGradient: {
0053             const QLinearGradient * src = static_cast<const QLinearGradient*>(srcGradient);
0054             QLinearGradient * dst = static_cast<QLinearGradient*>(dstGradient);
0055             dst->setStart(src->start());
0056             dst->setFinalStop(src->finalStop());
0057             break;
0058         }
0059         case QGradient::RadialGradient: {
0060             const QRadialGradient * src = static_cast<const QRadialGradient*>(srcGradient);
0061             QRadialGradient * dst = static_cast<QRadialGradient*>(dstGradient);
0062             dst->setCenter(src->center());
0063             dst->setRadius(src->radius());
0064             dst->setFocalPoint(src->focalPoint());
0065             break;
0066         }
0067         case QGradient::ConicalGradient: {
0068             const QConicalGradient * src = static_cast<const QConicalGradient*>(srcGradient);
0069             QConicalGradient * dst = static_cast<QConicalGradient*>(dstGradient);
0070             dst->setCenter(src->center());
0071             dst->setAngle(src->angle());
0072             break;
0073         }
0074         default:
0075             return;
0076         }
0077         return;
0078     }
0079 
0080     // try to preserve gradient positions as best as possible
0081     QPointF start, stop;
0082     switch (srcGradient->type()) {
0083     case QGradient::LinearGradient: {
0084         const QLinearGradient * g = static_cast<const QLinearGradient*>(srcGradient);
0085         start = g->start();
0086         stop = g->finalStop();
0087         break;
0088     }
0089     case QGradient::RadialGradient: {
0090         const QRadialGradient * g = static_cast<const QRadialGradient*>(srcGradient);
0091         start = g->center();
0092         stop = QPointF(g->radius(), 0.0);
0093         break;
0094     }
0095     case QGradient::ConicalGradient: {
0096         const QConicalGradient * g = static_cast<const QConicalGradient*>(srcGradient);
0097         start = g->center();
0098         qreal radAngle = g->angle() * M_PI / 180.0;
0099         stop = QPointF(50.0 * cos(radAngle), 50.*sin(radAngle));
0100         break;
0101     }
0102     default:
0103         start = QPointF(0.0, 0.0);
0104         stop = QPointF(50.0, 50.0);
0105     }
0106 
0107     switch (dstGradient->type()) {
0108     case QGradient::LinearGradient: {
0109         QLinearGradient * g = static_cast<QLinearGradient*>(dstGradient);
0110         g->setStart(start);
0111         g->setFinalStop(stop);
0112         break;
0113     }
0114     case QGradient::RadialGradient: {
0115         QRadialGradient * g = static_cast<QRadialGradient*>(dstGradient);
0116         QPointF diff = stop - start;
0117         qreal radius = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
0118         g->setCenter(start);
0119         g->setFocalPoint(start);
0120         g->setRadius(radius);
0121         break;
0122     }
0123     case QGradient::ConicalGradient: {
0124         QConicalGradient * g = static_cast<QConicalGradient*>(dstGradient);
0125         QPointF diff = stop - start;
0126         qreal angle = atan2(diff.y(), diff.x());
0127         if (angle < 0.0)
0128             angle += 2 * M_PI;
0129         g->setCenter(start);
0130         g->setAngle(angle*180 / M_PI);
0131         break;
0132     }
0133     default:
0134         return;
0135     }
0136 }
0137 
0138 KoGradientEditWidget::KoGradientEditWidget(QWidget* parent)
0139         : QWidget(parent)
0140         , m_gradOpacity(1.0), m_stopIndex(-1), m_checkerPainter(4)
0141         , m_type(QGradient::LinearGradient), m_spread(QGradient::PadSpread)
0142 {
0143     setObjectName("KoGradientEditWidget");
0144     // create a default gradient
0145     m_stops.append(QGradientStop(0.0, Qt::white));
0146     m_stops.append(QGradientStop(1.0, Qt::green));
0147 
0148     setupUI();
0149     setupConnections();
0150     updateUI();
0151 }
0152 
0153 void KoGradientEditWidget::setupUI()
0154 {
0155     QGridLayout* editLayout = new QGridLayout(this);
0156 
0157     int row = 0;
0158     editLayout->addWidget(new QLabel(i18n("Target:"), this), row, 0);
0159     m_gradientTarget = new QComboBox(this);
0160     m_gradientTarget->insertItem(0, i18n("Line"));
0161     m_gradientTarget->insertItem(1, i18n("Fill"));
0162     m_gradientTarget->setCurrentIndex(FillGradient);
0163     editLayout->addWidget(m_gradientTarget, row, 1, 1, 2);
0164 
0165     editLayout->addWidget(new QLabel(i18n("Type:"), this), ++row, 0);
0166     m_gradientType = new QComboBox(this);
0167     m_gradientType->insertItem(0, i18nc("Linear gradient type", "Linear"));
0168     m_gradientType->insertItem(1, i18nc("Radial gradient type", "Radial"));
0169     m_gradientType->insertItem(2, i18nc("Conical gradient type", "Conical"));
0170     editLayout->addWidget(m_gradientType, row, 1, 1, 2);
0171 
0172     editLayout->addWidget(new QLabel(i18n("Repeat:"), this), ++row, 0);
0173     m_gradientRepeat = new QComboBox(this);
0174     m_gradientRepeat->insertItem(0, i18nc("No gradient spread", "None"));
0175     m_gradientRepeat->insertItem(1, i18n("Reflect"));
0176     m_gradientRepeat->insertItem(2, i18n("Repeat"));
0177     editLayout->addWidget(m_gradientRepeat, row, 1, 1, 2);
0178 
0179     editLayout->addWidget(new QLabel(i18n("Overall opacity:"), this), ++row, 0);
0180     m_opacity = new KoSliderCombo(this);
0181     m_opacity->setDecimals(0);
0182     editLayout->addWidget(m_opacity, row, 1, 1, 2);
0183 
0184     editLayout->addWidget(new QLabel(i18n("Color stop:"), this), ++row, 0);
0185     m_stopColor = new QToolButton(this);
0186     editLayout->addWidget(m_stopColor, row, 1);
0187     m_stopPosition = new QDoubleSpinBox(this);
0188     m_stopPosition->setRange(0.0, 1.0);
0189     m_stopPosition->setSingleStep(0.01);
0190     editLayout->addWidget(m_stopPosition, row, 2);
0191     m_actionStopColor = new KoColorPopupAction(this);
0192     m_actionStopColor ->setToolTip(i18n("Stop color."));
0193     m_stopColor->setDefaultAction(m_actionStopColor);
0194 
0195     m_addToPredefs = new QPushButton(i18n("&Add to Predefined Gradients"), this);
0196     editLayout->addWidget(m_addToPredefs, ++row, 0, 1, 3);
0197 
0198     editLayout->setSpacing(3);
0199     editLayout->setMargin(6);
0200     editLayout->setRowMinimumHeight(0, 12);
0201     editLayout->setRowStretch(++row, 1);
0202 }
0203 
0204 void KoGradientEditWidget::setupConnections()
0205 {
0206     connect(m_gradientType, SIGNAL(activated(int)), this, SLOT(combosChange(int)));
0207     connect(m_gradientRepeat, SIGNAL(activated(int)), this, SLOT(combosChange(int)));
0208     connect(m_gradientTarget, SIGNAL(activated(int)), this, SLOT(combosChange(int)));
0209     connect(m_addToPredefs, SIGNAL(clicked()), this, SLOT(addGradientToPredefs()));
0210     connect(m_opacity, SIGNAL(valueChanged(qreal,bool)), this, SLOT(opacityChanged(qreal,bool)));
0211     connect(m_actionStopColor, SIGNAL(colorChanged(KoColor)), this, SLOT(stopChanged()));
0212     connect(m_stopPosition, SIGNAL(valueChanged(double)), this, SLOT(stopChanged()));
0213 }
0214 
0215 void KoGradientEditWidget::blockChildSignals(bool block)
0216 {
0217     m_gradientType->blockSignals(block);
0218     m_gradientRepeat->blockSignals(block);
0219     m_addToPredefs->blockSignals(block);
0220     m_opacity->blockSignals(block);
0221     m_stopColor->blockSignals(block);
0222     m_stopPosition->blockSignals(block);
0223 }
0224 
0225 void KoGradientEditWidget::updateUI()
0226 {
0227     blockChildSignals(true);
0228 
0229     m_gradientType->setCurrentIndex(m_type);
0230     m_gradientRepeat->setCurrentIndex(m_spread);
0231 
0232     uint stopCount = m_stops.count();
0233     qreal opacity = m_stops[0].second.alphaF();
0234     bool equalOpacity = true;
0235     for (uint i = 1; i < stopCount; ++i) {
0236         if (opacity != m_stops[i].second.alphaF()) {
0237             equalOpacity = false;
0238             break;
0239         }
0240     }
0241 
0242     m_opacity->setEnabled(equalOpacity);
0243     if (equalOpacity) {
0244         m_opacity->setValue(opacity * 100);
0245     }
0246 
0247 
0248 
0249     // now update the stop color and opacity
0250     const bool colorStopSelected = m_stopIndex >= 0 && m_stopIndex < m_stops.count();
0251     if (colorStopSelected) {
0252         QColor c = m_stops[m_stopIndex].second;
0253         m_stopPosition->setValue(m_stops[m_stopIndex].first);
0254         m_actionStopColor->setCurrentColor(c);
0255     }
0256     m_stopColor->setEnabled(colorStopSelected);
0257     m_stopPosition->setEnabled(colorStopSelected);
0258 
0259     blockChildSignals(false);
0260 }
0261 
0262 qreal KoGradientEditWidget::opacity() const
0263 {
0264     return m_opacity->value() / 100.0;
0265 }
0266 
0267 void KoGradientEditWidget::setOpacity(qreal opacity)
0268 {
0269     if (opacity < 0.0 || opacity > 1.0)
0270         return;
0271 
0272     m_gradOpacity = opacity;
0273     m_opacity->setValue(int(opacity*100.0));
0274 }
0275 
0276 void KoGradientEditWidget::setStopIndex(int index)
0277 {
0278     m_stopIndex = index;
0279     updateUI();
0280 }
0281 
0282 void KoGradientEditWidget::setGradient(const QGradient & gradient)
0283 {
0284     m_stops = gradient.stops();
0285     m_type = gradient.type();
0286     m_spread = gradient.spread();
0287 
0288     updateUI();
0289 }
0290 
0291 KoGradientEditWidget::GradientTarget KoGradientEditWidget::target()
0292 {
0293     return (GradientTarget)m_gradientTarget->currentIndex();
0294 }
0295 
0296 void KoGradientEditWidget::setTarget(GradientTarget target)
0297 {
0298     m_gradientTarget->setCurrentIndex(target);
0299 }
0300 
0301 QGradient::Spread KoGradientEditWidget::spread() const
0302 {
0303     return m_spread;
0304 }
0305 
0306 void KoGradientEditWidget::setSpread(QGradient::Spread spread)
0307 {
0308     m_spread = spread;
0309     updateUI();
0310 }
0311 
0312 QGradient::Type KoGradientEditWidget::type() const
0313 {
0314     return m_type;
0315 }
0316 
0317 void KoGradientEditWidget::setType(QGradient::Type type)
0318 {
0319     m_type = type;
0320     updateUI();
0321 }
0322 
0323 QGradientStops KoGradientEditWidget::stops() const
0324 {
0325     return m_stops;
0326 }
0327 
0328 void KoGradientEditWidget::setStops(const QGradientStops &stops)
0329 {
0330     m_stops = stops;
0331     updateUI();
0332 }
0333 
0334 void KoGradientEditWidget::combosChange(int)
0335 {
0336     m_type = static_cast<QGradient::Type>(m_gradientType->currentIndex());
0337     m_spread = static_cast<QGradient::Spread>(m_gradientRepeat->currentIndex());
0338 
0339     emit changed();
0340 }
0341 
0342 void KoGradientEditWidget::opacityChanged(qreal value, bool final)
0343 {
0344     Q_UNUSED(final);
0345 
0346     m_gradOpacity = value / 100.0;
0347 
0348     uint stopCount = m_stops.count();
0349     for (uint i = 0; i < stopCount; ++i)
0350         m_stops[i].second.setAlphaF(m_gradOpacity);
0351 
0352     emit changed();
0353 }
0354 
0355 void KoGradientEditWidget::addGradientToPredefs()
0356 {
0357     KoResourceServer<KoAbstractGradient>* server = KoResourceServerProvider::instance()->gradientServer();
0358 
0359     QString savePath = server->saveLocation();
0360 
0361     int i = 1;
0362     QFileInfo fileInfo;
0363 
0364     do {
0365         fileInfo.setFile(savePath + QString("%1.svg").arg(i++, 4, 10, QChar('0')));
0366     } while (fileInfo.exists());
0367 
0368     QGradient * gradient = 0;
0369     switch (m_type) {
0370     case QGradient::LinearGradient:
0371         gradient = new QLinearGradient();
0372         break;
0373     case QGradient::RadialGradient:
0374         gradient = new QRadialGradient();
0375         break;
0376     case QGradient::ConicalGradient:
0377         gradient = new QConicalGradient();
0378         break;
0379     default:
0380         // should not happen
0381         return;
0382     }
0383     gradient->setSpread(m_spread);
0384     gradient->setStops(m_stops);
0385     KoStopGradient * g = KoStopGradient::fromQGradient(gradient);
0386     delete gradient;
0387     if (! g)
0388         return;
0389     g->setFilename(fileInfo.filePath());
0390     g->setValid(true);
0391 
0392     if (! server->addResource(g))
0393         delete g;
0394 }
0395 
0396 void KoGradientEditWidget::stopChanged()
0397 {
0398     if (m_stopIndex >= 0 && m_stopIndex < m_stops.count()) {
0399         m_stops[m_stopIndex].first = m_stopPosition->value();
0400         m_stops[m_stopIndex].second = m_actionStopColor->currentColor();
0401         emit changed();
0402     }
0403 }
0404 
0405