File indexing completed on 2024-05-12 16:02:07
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2007 C. Boemann <cbo@boemann.dk> 0003 * SPDX-FileCopyrightText: 2007 Fredy Yanardi <fyanardi@gmail.com> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "KoColorPopupAction.h" 0009 0010 #include "KoColorSetWidget.h" 0011 #include "KoTriangleColorSelector.h" 0012 #include "KoColorSlider.h" 0013 #include "KoCheckerBoardPainter.h" 0014 #include "KoResourceServer.h" 0015 #include "KoResourceServerProvider.h" 0016 #include <KoColorSpaceRegistry.h> 0017 #include <KoColor.h> 0018 0019 #include <WidgetsDebug.h> 0020 #include <klocalizedstring.h> 0021 0022 #include <QPainter> 0023 #include <QWidgetAction> 0024 #include <QMenu> 0025 #include <QHBoxLayout> 0026 #include <QGridLayout> 0027 #include <QToolButton> 0028 0029 class KoColorPopupAction::KoColorPopupActionPrivate 0030 { 0031 public: 0032 KoColorPopupActionPrivate() 0033 : colorSetWidget(0) 0034 , colorChooser(0) 0035 , opacitySlider(0) 0036 , menu(0) 0037 , checkerPainter(4) 0038 , showFilter(true) 0039 , applyMode(true) 0040 , firstTime(true) 0041 {} 0042 0043 ~KoColorPopupActionPrivate() 0044 { 0045 delete menu; 0046 } 0047 0048 KoColor currentColor; 0049 KoColor buddyColor; 0050 0051 KoColorSetWidget *colorSetWidget; 0052 KoTriangleColorSelector * colorChooser; 0053 KoColorSlider * opacitySlider; 0054 QMenu *menu; 0055 KoCheckerBoardPainter checkerPainter; 0056 bool showFilter; 0057 bool applyMode; 0058 0059 bool firstTime; 0060 }; 0061 0062 KoColorPopupAction::KoColorPopupAction(QObject *parent) 0063 : QAction(parent), 0064 d(new KoColorPopupActionPrivate()) 0065 { 0066 d->menu = new QMenu(); 0067 QWidget *widget = new QWidget(d->menu); 0068 QWidgetAction *wdgAction = new QWidgetAction(d->menu); 0069 d->colorSetWidget = new KoColorSetWidget(widget); 0070 KoResourceServer<KoColorSet>* rServer = KoResourceServerProvider::instance()->paletteServer(); 0071 0072 KoColorSetSP defaultColorSet = rServer->resource("", "", "Default"); 0073 if (!defaultColorSet && rServer->resourceCount() > 0) { 0074 defaultColorSet = rServer->firstResource(); 0075 } 0076 d->colorSetWidget->setColorSet(defaultColorSet); 0077 0078 d->colorChooser = new KoTriangleColorSelector( widget ); 0079 // prevent mouse release on color selector from closing popup 0080 d->colorChooser->setAttribute( Qt::WA_NoMousePropagation ); 0081 d->opacitySlider = new KoColorSlider( Qt::Vertical, widget ); 0082 d->opacitySlider->setFixedWidth(25); 0083 d->opacitySlider->setRange(0, 255); 0084 d->opacitySlider->setValue(255); 0085 d->opacitySlider->setToolTip( i18n( "Opacity" ) ); 0086 0087 QGridLayout * layout = new QGridLayout( widget ); 0088 layout->addWidget( d->colorSetWidget, 0, 0, 1, -1 ); 0089 layout->addWidget( d->colorChooser, 1, 0 ); 0090 layout->addWidget( d->opacitySlider, 1, 1 ); 0091 layout->setMargin(4); 0092 0093 wdgAction->setDefaultWidget(widget); 0094 d->menu->addAction(wdgAction); 0095 setMenu(d->menu); 0096 new QHBoxLayout(d->menu); 0097 d->menu->layout()->addWidget(widget); 0098 d->menu->layout()->setMargin(0); 0099 0100 connect(this, SIGNAL(triggered()), this, SLOT(emitColorChanged())); 0101 0102 connect(d->colorSetWidget, SIGNAL(colorChanged(KoColor,bool)), 0103 this, SLOT(colorWasSelected(KoColor,bool))); 0104 connect(d->colorChooser, SIGNAL(colorChanged(QColor)), 0105 this, SLOT(colorWasEdited(QColor))); 0106 connect(d->opacitySlider, SIGNAL(valueChanged(int)), 0107 this, SLOT(opacityWasChanged(int))); 0108 } 0109 0110 KoColorPopupAction::~KoColorPopupAction() 0111 { 0112 delete d; 0113 } 0114 0115 void KoColorPopupAction::setCurrentColor( const KoColor &color ) 0116 { 0117 KoColor minColor( color ); 0118 d->currentColor = minColor; 0119 0120 d->colorChooser->blockSignals(true); 0121 d->colorChooser->slotSetColor(color); 0122 d->colorChooser->blockSignals(false); 0123 0124 KoColor maxColor( color ); 0125 minColor.setOpacity( OPACITY_TRANSPARENT_U8 ); 0126 maxColor.setOpacity( OPACITY_OPAQUE_U8 ); 0127 0128 d->opacitySlider->blockSignals( true ); 0129 d->opacitySlider->setColors( minColor, maxColor ); 0130 d->opacitySlider->setValue( color.opacityU8() ); 0131 d->opacitySlider->blockSignals( false ); 0132 0133 updateIcon(); 0134 } 0135 0136 void KoColorPopupAction::setCurrentColor( const QColor &_color ) 0137 { 0138 #ifndef NDEBUG 0139 if (!_color.isValid()) { 0140 warnWidgets << "Invalid color given, defaulting to black"; 0141 } 0142 #endif 0143 const QColor color(_color.isValid() ? _color : QColor(0,0,0,255)); 0144 setCurrentColor(KoColor(color, KoColorSpaceRegistry::instance()->rgb8() )); 0145 } 0146 0147 QColor KoColorPopupAction::currentColor() const 0148 { 0149 return d->currentColor.toQColor(); 0150 } 0151 0152 KoColor KoColorPopupAction::currentKoColor() const 0153 { 0154 return d->currentColor; 0155 } 0156 0157 void KoColorPopupAction::updateIcon() 0158 { 0159 QSize iconSize; 0160 QToolButton *toolButton = dynamic_cast<QToolButton*>(parentWidget()); 0161 if (toolButton) { 0162 iconSize = QSize(toolButton->iconSize()); 0163 } else { 0164 iconSize = QSize(16, 16); 0165 } 0166 0167 // This must be a QImage, as drawing to a QPixmap outside the 0168 // UI thread will cause sporadic crashes. 0169 QImage pm; 0170 0171 if (icon().isNull()) { 0172 d->applyMode = false; 0173 } 0174 0175 if(d->applyMode) { 0176 pm = icon().pixmap(iconSize).toImage(); 0177 if (pm.isNull()) { 0178 pm = QImage(iconSize, QImage::Format_ARGB32_Premultiplied); 0179 pm.fill(Qt::transparent); 0180 } 0181 QPainter p(&pm); 0182 p.fillRect(0, iconSize.height() - 4, iconSize.width(), 4, d->currentColor.toQColor()); 0183 p.end(); 0184 } else { 0185 pm = QImage(iconSize, QImage::Format_ARGB32_Premultiplied); 0186 pm.fill(Qt::transparent); 0187 QPainter p(&pm); 0188 d->checkerPainter.paint(p, QRect(QPoint(),iconSize)); 0189 p.fillRect(0, 0, iconSize.width(), iconSize.height(), d->currentColor.toQColor()); 0190 p.end(); 0191 } 0192 setIcon(QIcon(QPixmap::fromImage(pm))); 0193 } 0194 0195 void KoColorPopupAction::emitColorChanged() 0196 { 0197 emit colorChanged( d->currentColor ); 0198 } 0199 0200 void KoColorPopupAction::colorWasSelected(const KoColor &color, bool final) 0201 { 0202 d->currentColor = color; 0203 if (final) { 0204 menu()->hide(); 0205 emitColorChanged(); 0206 } 0207 updateIcon(); 0208 } 0209 0210 void KoColorPopupAction::colorWasEdited( const QColor &color ) 0211 { 0212 d->currentColor = KoColor( color, KoColorSpaceRegistry::instance()->rgb8() ); 0213 quint8 opacity = d->opacitySlider->value(); 0214 d->currentColor.setOpacity( opacity ); 0215 0216 KoColor minColor = d->currentColor; 0217 minColor.setOpacity( OPACITY_TRANSPARENT_U8 ); 0218 KoColor maxColor = minColor; 0219 maxColor.setOpacity( OPACITY_OPAQUE_U8 ); 0220 0221 d->opacitySlider->setColors( minColor, maxColor ); 0222 0223 emitColorChanged(); 0224 0225 updateIcon(); 0226 } 0227 0228 void KoColorPopupAction::opacityWasChanged( int opacity ) 0229 { 0230 d->currentColor.setOpacity( quint8(opacity) ); 0231 0232 emitColorChanged(); 0233 }