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