Warning, file /office/calligra/libs/widgets/KoFillConfigWidget.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 * Made by Tomislav Lukman (tomislav.lukman@ck.tel.hr) 0003 * Copyright (C) 2012 Jean-Nicolas Artaud <jeannicolasartaud@gmail.com> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KoFillConfigWidget.h" 0022 0023 #include <QToolButton> 0024 #include <QHBoxLayout> 0025 #include <QButtonGroup> 0026 #include <QLabel> 0027 #include <QSizePolicy> 0028 #include <QBitmap> 0029 #include <QAction> 0030 #include <QSharedPointer> 0031 0032 #include <klocalizedstring.h> 0033 0034 #include <KoGroupButton.h> 0035 #include <KoIcon.h> 0036 #include <KoColor.h> 0037 #include <KoColorPopupAction.h> 0038 #include "KoResourceServerProvider.h" 0039 #include "KoResourceServerAdapter.h" 0040 #include "KoResourceSelector.h" 0041 #include <KoSelection.h> 0042 #include <KoToolManager.h> 0043 #include <KoCanvasBase.h> 0044 #include <KoCanvasController.h> 0045 #include <KoCanvasResourceManager.h> 0046 #include <KoDocumentResourceManager.h> 0047 #include <KoShape.h> 0048 #include <KoShapeManager.h> 0049 #include <KoShapeController.h> 0050 #include <KoShapeBackground.h> 0051 #include <KoShapeBackgroundCommand.h> 0052 #include <KoColorBackground.h> 0053 #include <KoGradientBackground.h> 0054 #include <KoPatternBackground.h> 0055 #include <KoImageCollection.h> 0056 #include <KoResourcePopupAction.h> 0057 #include "KoZoomHandler.h" 0058 #include "KoColorPopupButton.h" 0059 0060 static const char* const buttonnone[]={ 0061 "16 16 3 1", 0062 "# c #000000", 0063 "e c #ff0000", 0064 "- c #ffffff", 0065 "################", 0066 "#--------------#", 0067 "#--------------#", 0068 "#--------------#", 0069 "#--------------#", 0070 "#--------------#", 0071 "#--------------#", 0072 "#--------------#", 0073 "#--------------#", 0074 "#--------------#", 0075 "#--------------#", 0076 "#--------------#", 0077 "#--------------#", 0078 "#--------------#", 0079 "#--------------#", 0080 "################"}; 0081 0082 static const char* const buttonsolid[]={ 0083 "16 16 2 1", 0084 "# c #000000", 0085 ". c #969696", 0086 "################", 0087 "#..............#", 0088 "#..............#", 0089 "#..............#", 0090 "#..............#", 0091 "#..............#", 0092 "#..............#", 0093 "#..............#", 0094 "#..............#", 0095 "#..............#", 0096 "#..............#", 0097 "#..............#", 0098 "#..............#", 0099 "#..............#", 0100 "#..............#", 0101 "################"}; 0102 0103 0104 // FIXME: Smoother gradient button. 0105 0106 static const char* const buttongradient[]={ 0107 "16 16 15 1", 0108 "# c #000000", 0109 "n c #101010", 0110 "m c #202020", 0111 "l c #303030", 0112 "k c #404040", 0113 "j c #505050", 0114 "i c #606060", 0115 "h c #707070", 0116 "g c #808080", 0117 "f c #909090", 0118 "e c #a0a0a0", 0119 "d c #b0b0b0", 0120 "c c #c0c0c0", 0121 "b c #d0d0d0", 0122 "a c #e0e0e0", 0123 "################", 0124 "#abcdefghijklmn#", 0125 "#abcdefghijklmn#", 0126 "#abcdefghijklmn#", 0127 "#abcdefghijklmn#", 0128 "#abcdefghijklmn#", 0129 "#abcdefghijklmn#", 0130 "#abcdefghijklmn#", 0131 "#abcdefghijklmn#", 0132 "#abcdefghijklmn#", 0133 "#abcdefghijklmn#", 0134 "#abcdefghijklmn#", 0135 "#abcdefghijklmn#", 0136 "#abcdefghijklmn#", 0137 "#abcdefghijklmn#", 0138 "################"}; 0139 0140 static const char* const buttonpattern[]={ 0141 "16 16 4 1", 0142 ". c #0a0a0a", 0143 "# c #333333", 0144 "a c #a0a0a0", 0145 "b c #ffffffff", 0146 "################", 0147 "#aaaaabbbbaaaaa#", 0148 "#aaaaabbbbaaaaa#", 0149 "#aaaaabbbbaaaaa#", 0150 "#aaaaabbbbaaaaa#", 0151 "#aaaaabbbbaaaaa#", 0152 "#bbbbbaaaabbbbb#", 0153 "#bbbbbaaaabbbbb#", 0154 "#bbbbbaaaabbbbb#", 0155 "#bbbbbaaaabbbbb#", 0156 "#aaaaabbbbaaaaa#", 0157 "#aaaaabbbbaaaaa#", 0158 "#aaaaabbbbaaaaa#", 0159 "#aaaaabbbbaaaaa#", 0160 "#aaaaabbbbaaaaa#", 0161 "################"}; 0162 0163 class Q_DECL_HIDDEN KoFillConfigWidget::Private 0164 { 0165 public: 0166 Private() 0167 : canvas(nullptr) 0168 { 0169 } 0170 /// Apply the gradient stops using the shape background 0171 QSharedPointer<KoShapeBackground> applyFillGradientStops(KoShape *shape, const QGradientStops &stops) 0172 { 0173 if (! shape || ! stops.count()) { 0174 return QSharedPointer<KoShapeBackground>(); 0175 } 0176 0177 KoGradientBackground *newGradient = nullptr; 0178 QSharedPointer<KoGradientBackground> oldGradient = qSharedPointerDynamicCast<KoGradientBackground>(shape->background()); 0179 if (oldGradient) { 0180 // just copy the gradient and set the new stops 0181 QGradient *g = KoFlake::cloneGradient(oldGradient->gradient()); 0182 g->setStops(stops); 0183 newGradient = new KoGradientBackground(g); 0184 newGradient->setTransform(oldGradient->transform()); 0185 } 0186 else { 0187 // No gradient yet, so create a new one. 0188 QLinearGradient *g = new QLinearGradient(QPointF(0, 0), QPointF(1, 1)); 0189 g->setCoordinateMode(QGradient::ObjectBoundingMode); 0190 g->setStops(stops); 0191 newGradient = new KoGradientBackground(g); 0192 } 0193 return QSharedPointer<KoGradientBackground>(newGradient); 0194 } 0195 0196 KoColorPopupButton *colorButton; 0197 QAction *noFillAction; 0198 KoColorPopupAction *colorAction; 0199 KoResourcePopupAction *gradientAction; 0200 KoResourcePopupAction *patternAction; 0201 QButtonGroup *group; 0202 0203 QWidget *spacer; 0204 KoCanvasBase *canvas; 0205 }; 0206 0207 KoFillConfigWidget::KoFillConfigWidget(QWidget *parent) 0208 : QWidget(parent) 0209 , d(new Private()) 0210 { 0211 setObjectName("Fill widget"); 0212 QHBoxLayout *layout = new QHBoxLayout(this); 0213 layout->setMargin(0); 0214 layout->setSpacing(0); 0215 0216 d->group = new QButtonGroup(this); 0217 d->group->setExclusive(true); 0218 0219 // The button for no fill 0220 KoGroupButton *button = new KoGroupButton(KoGroupButton::GroupLeft, this); 0221 QPixmap noFillButtonIcon((const char **) buttonnone); 0222 noFillButtonIcon.setMask(QBitmap(noFillButtonIcon)); 0223 button->setIcon(noFillButtonIcon); 0224 button->setToolTip(i18nc("No stroke or fill", "None")); 0225 button->setCheckable(true); 0226 d->group->addButton(button, None); 0227 layout->addWidget(button); 0228 0229 // The button for solid fill 0230 button = new KoGroupButton(KoGroupButton::GroupCenter, this); 0231 button->setIcon(QPixmap((const char **) buttonsolid)); 0232 button->setToolTip(i18nc("Solid color stroke or fill", "Solid")); 0233 button->setCheckable(true); 0234 d->group->addButton(button, Solid); 0235 layout->addWidget(button); 0236 0237 // The button for gradient fill 0238 button = new KoGroupButton(KoGroupButton::GroupCenter, this); 0239 button->setIcon(QPixmap((const char **) buttongradient)); 0240 button->setToolTip(i18n("Gradient")); 0241 button->setCheckable(true); 0242 d->group->addButton(button, Gradient); 0243 layout->addWidget(button); 0244 0245 // The button for pattern fill 0246 button = new KoGroupButton(KoGroupButton::GroupRight, this); 0247 button->setIcon(QPixmap((const char **) buttonpattern)); 0248 button->setToolTip(i18n("Pattern")); 0249 button->setCheckable(true); 0250 d->group->addButton(button, Pattern); 0251 layout->addWidget(button); 0252 0253 connect(d->group, SIGNAL(buttonClicked(int)), this, SLOT(styleButtonPressed(int))); 0254 0255 d->colorButton = new KoColorPopupButton(this); 0256 d->colorButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 0257 layout->addWidget(d->colorButton); 0258 0259 d->noFillAction = new QAction(nullptr); 0260 0261 d->colorAction = new KoColorPopupAction(d->colorButton); 0262 d->colorAction->setToolTip(i18n("Change the filling color")); 0263 d->colorAction->setCurrentColor(Qt::white); 0264 d->colorButton->setDefaultAction(d->colorAction); 0265 d->colorButton->setPopupMode(QToolButton::InstantPopup); 0266 connect(d->colorAction, SIGNAL(colorChanged(KoColor)), this, SLOT(colorChanged())); 0267 connect(d->colorButton, SIGNAL(iconSizeChanged()), d->colorAction, SLOT(updateIcon())); 0268 0269 // Gradient selector 0270 KoResourceServerProvider *serverProvider = KoResourceServerProvider::instance(); 0271 QSharedPointer<KoAbstractResourceServerAdapter> gradientResourceAdapter(new KoResourceServerAdapter<KoAbstractGradient>(serverProvider->gradientServer())); 0272 d->gradientAction = new KoResourcePopupAction(gradientResourceAdapter, d->colorButton); 0273 d->gradientAction->setToolTip(i18n("Change the filling gradient")); 0274 connect(d->gradientAction, SIGNAL(resourceSelected(QSharedPointer<KoShapeBackground>)), this, SLOT(gradientChanged(QSharedPointer<KoShapeBackground>))); 0275 connect(d->colorButton, SIGNAL(iconSizeChanged()), d->gradientAction, SLOT(updateIcon())); 0276 0277 // Pattern selector 0278 QSharedPointer<KoAbstractResourceServerAdapter>patternResourceAdapter(new KoResourceServerAdapter<KoPattern>(serverProvider->patternServer())); 0279 d->patternAction = new KoResourcePopupAction(patternResourceAdapter, d->colorButton); 0280 d->patternAction->setToolTip(i18n("Change the filling pattern")); 0281 connect(d->patternAction, SIGNAL(resourceSelected(QSharedPointer<KoShapeBackground>)), this, SLOT(patternChanged(QSharedPointer<KoShapeBackground>))); 0282 connect(d->colorButton, SIGNAL(iconSizeChanged()), d->patternAction, SLOT(updateIcon())); 0283 0284 // Spacer 0285 d->spacer = new QWidget(); 0286 d->spacer->setObjectName("SpecialSpacer"); 0287 layout->addWidget(d->spacer); 0288 0289 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0290 KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); 0291 if (selection) { 0292 d->canvas = canvasController->canvas(); 0293 connect(selection, SIGNAL(selectionChanged()), this, SLOT(shapeChanged())); 0294 } 0295 } 0296 0297 KoFillConfigWidget::~KoFillConfigWidget() 0298 { 0299 delete d->noFillAction; 0300 delete d; 0301 } 0302 0303 void KoFillConfigWidget::setCanvas( KoCanvasBase *canvas ) 0304 { 0305 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0306 KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); 0307 0308 connect(selection, SIGNAL(selectionChanged()), this, SLOT(shapeChanged())); 0309 0310 d->canvas = canvas; 0311 } 0312 0313 KoCanvasBase* KoFillConfigWidget::canvas() 0314 { 0315 return d->canvas; 0316 } 0317 0318 QList<KoShape*> KoFillConfigWidget::currentShapes() 0319 { 0320 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0321 KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); 0322 return selection->selectedShapes(); 0323 } 0324 0325 KoShape *KoFillConfigWidget::currentShape() 0326 { 0327 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0328 KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); 0329 return selection->firstSelectedShape(); 0330 } 0331 0332 0333 void KoFillConfigWidget::styleButtonPressed(int buttonId) 0334 { 0335 d->colorButton->setEnabled(true); 0336 switch (buttonId) { 0337 case KoFillConfigWidget::None: 0338 // Direct manipulation 0339 d->colorButton->setDefaultAction(d->noFillAction); 0340 d->colorButton->setDisabled(true); 0341 noColorSelected(); 0342 break; 0343 case KoFillConfigWidget::Solid: 0344 d->colorButton->setDefaultAction(d->colorAction); 0345 colorChanged(); 0346 break; 0347 case KoFillConfigWidget::Gradient: 0348 // Only select mode in the widget, don't set actual gradient :/ 0349 d->colorButton->setDefaultAction(d->gradientAction); 0350 gradientChanged(d->gradientAction->currentBackground()); 0351 break; 0352 case KoFillConfigWidget::Pattern: 0353 // Only select mode in the widget, don't set actual pattern :/ 0354 d->colorButton->setDefaultAction(d->patternAction); 0355 patternChanged(d->patternAction->currentBackground()); 0356 break; 0357 } 0358 d->colorButton->setPopupMode(QToolButton::InstantPopup); 0359 } 0360 0361 void KoFillConfigWidget::noColorSelected() 0362 { 0363 QList<KoShape*> selectedShapes = currentShapes(); 0364 if (selectedShapes.isEmpty()) { 0365 return; 0366 } 0367 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0368 canvasController->canvas()->addCommand(new KoShapeBackgroundCommand(selectedShapes, QSharedPointer<KoShapeBackground>(0))); 0369 } 0370 0371 void KoFillConfigWidget::colorChanged() 0372 { 0373 QList<KoShape*> selectedShapes = currentShapes(); 0374 if (selectedShapes.isEmpty()) { 0375 return; 0376 } 0377 0378 QSharedPointer<KoShapeBackground> fill(new KoColorBackground(d->colorAction->currentColor())); 0379 KUndo2Command *firstCommand = nullptr; 0380 foreach (KoShape *shape, selectedShapes) { 0381 if (! firstCommand) { 0382 firstCommand = new KoShapeBackgroundCommand(shape, fill); 0383 } else { 0384 new KoShapeBackgroundCommand(shape, fill, firstCommand); 0385 } 0386 } 0387 0388 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0389 canvasController->canvas()->addCommand(firstCommand); 0390 } 0391 0392 void KoFillConfigWidget::gradientChanged(QSharedPointer<KoShapeBackground> background) 0393 { 0394 QList<KoShape*> selectedShapes = currentShapes(); 0395 if (selectedShapes.isEmpty()) { 0396 return; 0397 } 0398 0399 QSharedPointer<KoGradientBackground> gradientBackground = qSharedPointerDynamicCast<KoGradientBackground>(background); 0400 if (!gradientBackground) { 0401 return; 0402 } 0403 0404 QGradientStops newStops = gradientBackground->gradient()->stops(); 0405 gradientBackground.clear(); 0406 0407 KUndo2Command *firstCommand = nullptr; 0408 foreach (KoShape *shape, selectedShapes) { 0409 QSharedPointer<KoShapeBackground> fill = d->applyFillGradientStops(shape, newStops); 0410 if (! fill) { 0411 continue; 0412 } 0413 if (! firstCommand) { 0414 firstCommand = new KoShapeBackgroundCommand(shape, fill); 0415 } else { 0416 new KoShapeBackgroundCommand(shape, fill, firstCommand); 0417 } 0418 } 0419 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0420 canvasController->canvas()->addCommand(firstCommand); 0421 } 0422 0423 void KoFillConfigWidget::patternChanged(QSharedPointer<KoShapeBackground> background) 0424 { 0425 QSharedPointer<KoPatternBackground> patternBackground = qSharedPointerDynamicCast<KoPatternBackground>(background); 0426 if (! patternBackground) { 0427 return; 0428 } 0429 0430 QList<KoShape*> selectedShapes = currentShapes(); 0431 if (selectedShapes.isEmpty()) { 0432 return; 0433 } 0434 0435 KoCanvasController *canvasController = KoToolManager::instance()->activeCanvasController(); 0436 KoImageCollection *imageCollection = canvasController->canvas()->shapeController()->resourceManager()->imageCollection(); 0437 if (imageCollection) { 0438 QSharedPointer<KoPatternBackground> fill(new KoPatternBackground(imageCollection)); 0439 fill->setPattern(patternBackground->pattern()); 0440 canvasController->canvas()->addCommand(new KoShapeBackgroundCommand(selectedShapes, fill)); 0441 } 0442 } 0443 0444 void KoFillConfigWidget::shapeChanged() 0445 { 0446 KoShape *shape = currentShape(); 0447 if (! shape) { 0448 d->group->button(KoFillConfigWidget::None)->setChecked(false); 0449 d->group->button(KoFillConfigWidget::Solid)->setChecked(false); 0450 d->group->button(KoFillConfigWidget::Gradient)->setChecked(false); 0451 d->group->button(KoFillConfigWidget::Pattern)->setChecked(false); 0452 d->colorButton->setDisabled(true); 0453 return; 0454 } 0455 0456 d->colorAction->blockSignals(true); 0457 updateWidget(shape); 0458 d->colorAction->blockSignals(false); 0459 } 0460 0461 0462 void KoFillConfigWidget::updateWidget(KoShape *shape) 0463 { 0464 if (! shape) { 0465 return; 0466 } 0467 0468 KoZoomHandler zoomHandler; 0469 const qreal realWidth = zoomHandler.resolutionX() * width(); 0470 const qreal realHeight = zoomHandler.resolutionX() * height(); 0471 0472 const qreal zoom = (realWidth > realHeight) ? realHeight : realWidth; 0473 zoomHandler.setZoom(zoom); 0474 0475 shape->waitUntilReady(zoomHandler, false); 0476 0477 d->colorButton->setEnabled(true); 0478 QSharedPointer<KoShapeBackground> background = shape->background(); 0479 if (! background) { 0480 // No Fill 0481 d->group->button(KoFillConfigWidget::None)->setChecked(true); 0482 d->colorButton->setDefaultAction(d->noFillAction); 0483 d->colorButton->setDisabled(true); 0484 d->colorButton->setPopupMode(QToolButton::InstantPopup); 0485 return; 0486 } 0487 0488 QSharedPointer<KoColorBackground> colorBackground = qSharedPointerDynamicCast<KoColorBackground>(background); 0489 QSharedPointer<KoGradientBackground> gradientBackground = qSharedPointerDynamicCast<KoGradientBackground>(background); 0490 QSharedPointer<KoPatternBackground> patternBackground = qSharedPointerDynamicCast<KoPatternBackground>(background); 0491 0492 if (colorBackground) { 0493 d->colorAction->setCurrentColor(colorBackground->color()); 0494 d->group->button(KoFillConfigWidget::Solid)->setChecked(true); 0495 d->colorButton->setDefaultAction(d->colorAction); 0496 } else if (gradientBackground) { 0497 d->gradientAction->setCurrentBackground(background); 0498 d->group->button(KoFillConfigWidget::Gradient)->setChecked(true); 0499 d->colorButton->setDefaultAction(d->gradientAction); 0500 } else if (patternBackground) { 0501 d->patternAction->setCurrentBackground(background); 0502 d->group->button(KoFillConfigWidget::Pattern)->setChecked(true); 0503 d->colorButton->setDefaultAction(d->patternAction); 0504 } else { 0505 // No Fill 0506 d->group->button(KoFillConfigWidget::None)->setChecked(true); 0507 d->colorButton->setDefaultAction(d->noFillAction); 0508 d->colorButton->setDisabled(true); 0509 } 0510 d->colorButton->setPopupMode(QToolButton::InstantPopup); 0511 }