diff --git a/libs/ui/widgets/KoDualColorButton.cpp b/libs/ui/widgets/KoDualColorButton.cpp index 1a49f9c824..acc01f54f6 100644 --- a/libs/ui/widgets/KoDualColorButton.cpp +++ b/libs/ui/widgets/KoDualColorButton.cpp @@ -1,414 +1,402 @@ /* This file is part of the KDE libraries Copyright (C) 1999 Daniel M. Duley This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KoDualColorButton.h" #include "KoColor.h" #include "KoColorDisplayRendererInterface.h" #include #include "dcolorarrow.xbm" #include "dcolorreset.xpm" #include #include "KisDlgInternalColorSelector.h" #include "kis_signals_blocker.h" #include #include #include #include #include #include class Q_DECL_HIDDEN KoDualColorButton::Private { - public: +public: Private(const KoColor &fgColor, const KoColor &bgColor, QWidget *_dialogParent, const KoColorDisplayRendererInterface *_displayRenderer) : dialogParent(_dialogParent) , dragFlag( false ) , miniCtlFlag( false ) , foregroundColor(fgColor) , backgroundColor(bgColor) , displayRenderer(_displayRenderer) { updateArrows(); resetPixmap = QPixmap( (const char **)dcolorreset_xpm ); popDialog = true; } void updateArrows() { arrowBitmap = QPixmap(12,12); arrowBitmap.fill(Qt::transparent); QPainter p(&arrowBitmap); p.setPen(dialogParent->palette().foreground().color()); // arrow pointing left p.drawLine(0, 3, 7, 3); p.drawLine(1, 2, 1, 4); p.drawLine(2, 1, 2, 5); p.drawLine(3, 0, 3, 6); // arrow pointing down p.drawLine(8, 4, 8, 11); p.drawLine(5, 8, 11, 8); p.drawLine(6, 9, 10, 9); p.drawLine(7, 10, 9, 10); } QWidget* dialogParent; QPixmap arrowBitmap; QPixmap resetPixmap; bool dragFlag, miniCtlFlag; KoColor foregroundColor; KoColor backgroundColor; KisDlgInternalColorSelector *colorSelectorDialog; QPoint dragPosition; Selection tmpSelection; bool popDialog; const KoColorDisplayRendererInterface *displayRenderer; void init(KoDualColorButton *q); }; void KoDualColorButton::Private::init(KoDualColorButton *q) { if ( q->sizeHint().isValid() ) q->setMinimumSize( q->sizeHint() ); q->setAcceptDrops( true ); QString caption = i18n("Select a Color"); KisDlgInternalColorSelector::Config config = KisDlgInternalColorSelector::Config(); config.modal = false; colorSelectorDialog = new KisDlgInternalColorSelector(q, foregroundColor, config, caption, displayRenderer); connect(colorSelectorDialog, SIGNAL(signalForegroundColorChosen(KoColor)), q, SLOT(slotSetForeGroundColorFromDialog(KoColor))); connect(q, SIGNAL(foregroundColorChanged(KoColor)), colorSelectorDialog, SLOT(slotColorUpdated(KoColor))); } KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent, QWidget* dialogParent ) : QWidget( parent ), d( new Private(foregroundColor, backgroundColor, dialogParent, KoDumbColorDisplayRenderer::instance()) ) { d->init(this); } KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, const KoColorDisplayRendererInterface *displayRenderer, QWidget *parent, QWidget* dialogParent) : QWidget( parent ), d( new Private(foregroundColor, backgroundColor, dialogParent, displayRenderer) ) { d->init(this); } KoDualColorButton::~KoDualColorButton() { - delete d; + delete d; } KoColor KoDualColorButton::foregroundColor() const { - return d->foregroundColor; + return d->foregroundColor; } KoColor KoDualColorButton::backgroundColor() const { - return d->backgroundColor; + return d->backgroundColor; } bool KoDualColorButton::popDialog() const { - return d->popDialog; + return d->popDialog; } QSize KoDualColorButton::sizeHint() const { - return QSize( 34, 34 ); + return QSize( 34, 34 ); } -void KoDualColorButton::setForegroundColor( const KoColor &color ) +void KoDualColorButton::setForegroundColor(const KoColor &color) { - d->foregroundColor = color; - { - /** + d->foregroundColor = color; + { + /** * The internal color selector might emit the color of a different profile, so * we should break this cycling dependency somehow. */ - KisSignalsBlocker b(d->colorSelectorDialog); - d->colorSelectorDialog->slotColorUpdated(color); - } - repaint(); + KisSignalsBlocker b(d->colorSelectorDialog); + d->colorSelectorDialog->slotColorUpdated(color); + } + repaint(); } void KoDualColorButton::setBackgroundColor( const KoColor &color ) { - d->backgroundColor = color; - repaint(); + d->backgroundColor = color; + repaint(); } void KoDualColorButton::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { d->displayRenderer = displayRenderer; d->colorSelectorDialog->setDisplayRenderer(displayRenderer); connect(d->displayRenderer, SIGNAL(destroyed()), this, SLOT(setDisplayRenderer()), Qt::UniqueConnection); } else { d->displayRenderer = KoDumbColorDisplayRenderer::instance(); } } void KoDualColorButton::setColorSpace(const KoColorSpace *cs) { d->colorSelectorDialog->lockUsedColorSpace(cs); } QColor KoDualColorButton::getColorFromDisplayRenderer(KoColor c) { QColor col; if (d->displayRenderer) { c.convertTo(d->displayRenderer->getPaintingColorSpace()); col = d->displayRenderer->toQColor(c); } else { col = c.toQColor(); } return col; } void KoDualColorButton::setPopDialog( bool popDialog ) { - d->popDialog = popDialog; + d->popDialog = popDialog; } void KoDualColorButton::metrics( QRect &foregroundRect, QRect &backgroundRect ) { - foregroundRect = QRect( 0, 0, width() - 14, height() - 14 ); - backgroundRect = QRect( 14, 14, width() - 14, height() - 14 ); + foregroundRect = QRect( 0, 0, width() - 14, height() - 14 ); + backgroundRect = QRect( 14, 14, width() - 14, height() - 14 ); } void KoDualColorButton::paintEvent(QPaintEvent *) { - QRect foregroundRect; - QRect backgroundRect; + QRect foregroundRect; + QRect backgroundRect; - QPainter painter( this ); + QPainter painter( this ); - metrics( foregroundRect, backgroundRect ); + metrics( foregroundRect, backgroundRect ); - QBrush defBrush = palette().brush( QPalette::Button ); - QBrush foregroundBrush( getColorFromDisplayRenderer(d->foregroundColor), Qt::SolidPattern ); - QBrush backgroundBrush( getColorFromDisplayRenderer(d->backgroundColor), Qt::SolidPattern ); + QBrush defBrush = palette().brush( QPalette::Button ); + QBrush foregroundBrush( getColorFromDisplayRenderer(d->foregroundColor), Qt::SolidPattern ); + QBrush backgroundBrush( getColorFromDisplayRenderer(d->backgroundColor), Qt::SolidPattern ); - qDrawShadeRect( &painter, backgroundRect, palette(), false, 1, 0, - isEnabled() ? &backgroundBrush : &defBrush ); + qDrawShadeRect( &painter, backgroundRect, palette(), false, 1, 0, + isEnabled() ? &backgroundBrush : &defBrush ); - qDrawShadeRect( &painter, foregroundRect, palette(), false, 1, 0, - isEnabled() ? &foregroundBrush : &defBrush ); + qDrawShadeRect( &painter, foregroundRect, palette(), false, 1, 0, + isEnabled() ? &foregroundBrush : &defBrush ); - painter.setPen( palette().color( QPalette::Shadow ) ); + painter.setPen( palette().color( QPalette::Shadow ) ); - painter.drawPixmap( foregroundRect.right() + 2, 1, d->arrowBitmap ); - painter.drawPixmap( 1, foregroundRect.bottom() + 2, d->resetPixmap ); + painter.drawPixmap( foregroundRect.right() + 2, 1, d->arrowBitmap ); + painter.drawPixmap( 1, foregroundRect.bottom() + 2, d->resetPixmap ); } void KoDualColorButton::dragEnterEvent( QDragEnterEvent *event ) { - event->setAccepted( isEnabled() && KColorMimeData::canDecode( event->mimeData() ) ); + event->setAccepted( isEnabled() && KColorMimeData::canDecode( event->mimeData() ) ); } void KoDualColorButton::dropEvent( QDropEvent *event ) { Q_UNUSED(event); -/* QColor color = KColorMimeData::fromMimeData( event->mimeData() ); + /* QColor color = KColorMimeData::fromMimeData( event->mimeData() ); if ( color.isValid() ) { if ( d->selection == Foreground ) { d->foregroundColor = color; emit foregroundColorChanged( color ); } else { d->backgroundColor = color; emit backgroundColorChanged( color ); } repaint(); } */ } void KoDualColorButton::slotSetForeGroundColorFromDialog(const KoColor color) { d->foregroundColor = color; repaint(); emit foregroundColorChanged(d->foregroundColor); } void KoDualColorButton::mousePressEvent( QMouseEvent *event ) { - QRect foregroundRect; - QRect backgroundRect; + QRect foregroundRect; + QRect backgroundRect; - metrics( foregroundRect, backgroundRect ); + metrics( foregroundRect, backgroundRect ); - d->dragPosition = event->pos(); + d->dragPosition = event->pos(); - d->dragFlag = false; + d->dragFlag = false; - if ( foregroundRect.contains( d->dragPosition ) ) { - d->tmpSelection = Foreground; - d->miniCtlFlag = false; - } - else if( backgroundRect.contains( d->dragPosition ) ) { - d->tmpSelection = Background; - d->miniCtlFlag = false; - } - else if ( event->pos().x() > foregroundRect.width() ) { - // We handle the swap and reset controls as soon as the mouse is - // is pressed and ignore further events on this click (mosfet). + if ( foregroundRect.contains( d->dragPosition ) ) { + d->tmpSelection = Foreground; + d->miniCtlFlag = false; + } + else if( backgroundRect.contains( d->dragPosition ) ) { + d->tmpSelection = Background; + d->miniCtlFlag = false; + } + else if ( event->pos().x() > foregroundRect.width() ) { + // We handle the swap and reset controls as soon as the mouse is + // is pressed and ignore further events on this click (mosfet). - KoColor tmp = d->foregroundColor; - d->foregroundColor = d->backgroundColor; - d->backgroundColor = tmp; + KoColor tmp = d->foregroundColor; + d->foregroundColor = d->backgroundColor; + d->backgroundColor = tmp; - emit backgroundColorChanged( d->backgroundColor ); - emit foregroundColorChanged( d->foregroundColor ); + emit backgroundColorChanged( d->backgroundColor ); + emit foregroundColorChanged( d->foregroundColor ); - d->miniCtlFlag = true; - } - else if ( event->pos().x() < backgroundRect.x() ) { - d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::black); - d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::white); + d->miniCtlFlag = true; + } + else if ( event->pos().x() < backgroundRect.x() ) { + d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::black); + d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::white); - emit backgroundColorChanged( d->backgroundColor ); - emit foregroundColorChanged( d->foregroundColor ); + emit backgroundColorChanged( d->backgroundColor ); + emit foregroundColorChanged( d->foregroundColor ); - d->miniCtlFlag = true; - } - repaint(); + d->miniCtlFlag = true; + } + repaint(); } void KoDualColorButton::mouseMoveEvent( QMouseEvent *event ) { - if ( !d->miniCtlFlag ) { - int delay = QApplication::startDragDistance(); - - if ( event->x() >= d->dragPosition.x() + delay || event->x() <= d->dragPosition.x() - delay || - event->y() >= d->dragPosition.y() + delay || event->y() <= d->dragPosition.y() - delay ) { - KColorMimeData::createDrag( d->tmpSelection == Foreground ? - getColorFromDisplayRenderer(d->foregroundColor) : - getColorFromDisplayRenderer(d->backgroundColor), - this )->start(); - d->dragFlag = true; + if ( !d->miniCtlFlag ) { + int delay = QApplication::startDragDistance(); + + if ( event->x() >= d->dragPosition.x() + delay || event->x() <= d->dragPosition.x() - delay || + event->y() >= d->dragPosition.y() + delay || event->y() <= d->dragPosition.y() - delay ) { + KColorMimeData::createDrag( d->tmpSelection == Foreground ? + getColorFromDisplayRenderer(d->foregroundColor) : + getColorFromDisplayRenderer(d->backgroundColor), + this )->start(); + d->dragFlag = true; + } } - } } void KoDualColorButton::mouseReleaseEvent( QMouseEvent *event ) { d->dragFlag = false; if ( d->miniCtlFlag ) return; d->miniCtlFlag = false; QRect foregroundRect; QRect backgroundRect; metrics( foregroundRect, backgroundRect ); if (foregroundRect.contains( event->pos())) { if (d->tmpSelection == Foreground) { if (d->popDialog) { #ifndef Q_OS_MACOS d->colorSelectorDialog->setPreviousColor(d->foregroundColor); - //this should toggle, but I don't know how to implement that... + // this should toggle, but I don't know how to implement that... d->colorSelectorDialog->show(); #else -#ifdef Q_OS_MACOS QColor c = d->foregroundColor.toQColor(); -#else - QColor c = d->displayRenderer->toQColor(d->foregroundColor); -#endif c = QColorDialog::getColor(c, this); if (c.isValid()) { d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(c); emit foregroundColorChanged(d->foregroundColor); } #endif } - else { - emit pleasePopDialog(d->foregroundColor); - } } else { d->foregroundColor = d->backgroundColor; emit foregroundColorChanged( d->foregroundColor ); } - } else if ( backgroundRect.contains( event->pos() )) { + } + else if ( backgroundRect.contains( event->pos() )) { if(d->tmpSelection == Background ) { if( d->popDialog) { #ifndef Q_OS_MACOS KoColor c = d->backgroundColor; - c = KisDlgInternalColorSelector::getModalColorDialog(c, this); + c = KisDlgInternalColorSelector::getModalColorDialog(c, this, d->colorSelectorDialog->windowTitle()); d->backgroundColor = c; emit backgroundColorChanged(d->backgroundColor); #else -#ifdef Q_OS_MACOS QColor c = d->backgroundColor.toQColor(); -#else - QColor c = d->displayRenderer->toQColor(d->backgroundColor); -#endif c = QColorDialog::getColor(c, this); if (c.isValid()) { d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(c); emit backgroundColorChanged(d->backgroundColor); } #endif } - else - emit pleasePopDialog( d->backgroundColor); } else { d->backgroundColor = d->foregroundColor; emit backgroundColorChanged( d->backgroundColor ); } } repaint(); } void KoDualColorButton::changeEvent(QEvent *event) { QWidget::changeEvent(event); switch (event->type()) { case QEvent::StyleChange: case QEvent::PaletteChange: d->updateArrows(); default: break; } } diff --git a/libs/ui/widgets/KoDualColorButton.h b/libs/ui/widgets/KoDualColorButton.h index 6c6e22067d..f5c4deca4f 100644 --- a/libs/ui/widgets/KoDualColorButton.h +++ b/libs/ui/widgets/KoDualColorButton.h @@ -1,186 +1,179 @@ /* This file is part of the KDE libraries Copyright (C) 1999 Daniel M. Duley 2006 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KODUALCOLORBUTTON_H #define KODUALCOLORBUTTON_H #include #include #include class KoColor; class KoColorSpace; /** * @short A widget for selecting two related colors. * * KoDualColorButton allows the user to select two cascaded colors (usually a * foreground and background color). Other features include drag and drop * from other KDE color widgets, a reset to black and white control, and a * swap colors control. * * When the user clicks on the foreground or background rectangle the * rectangle is first sunken and the selectionChanged() signal is emitted. * Further clicks will present a color dialog and emit either the foregroundColorChanged() * or backgroundColorChanged() if a new color is selected. * * Note: With drag and drop when dropping a color the current selected color * will be set, while when dragging a color it will use whatever color * rectangle the mouse was pressed inside. * * @author Daniel M. Duley */ class KRITAUI_EXPORT KoDualColorButton : public QWidget { Q_OBJECT Q_ENUMS( Selection ) Q_PROPERTY( KoColor foregroundColor READ foregroundColor WRITE setForegroundColor ) Q_PROPERTY( KoColor backgroundColor READ backgroundColor WRITE setBackgroundColor ) Q_PROPERTY( bool popDialog READ popDialog WRITE setPopDialog ) public: enum Selection { Foreground, Background }; /** * Constructs a new KoDualColorButton with the supplied foreground and * background colors. * * @param parent The parent widget of the KoDualColorButton. * @param dialogParent The parent widget of the color selection dialog. */ KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent = 0, QWidget* dialogParent = 0 ); KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, const KoColorDisplayRendererInterface *displayRenderer, QWidget *parent = 0, QWidget* dialogParent = 0 ); /** * Destroys the KoDualColorButton. */ ~KoDualColorButton() override; /** * Returns the current foreground color. */ KoColor foregroundColor() const; /** * Returns the current background color. */ KoColor backgroundColor() const; /** * Returns if a dialog with a color chooser will be popped up when clicking * If false then you could/should connect to the pleasePopDialog signal * and pop your own dialog. Just set the current color afterwards. */ bool popDialog() const; /** * Returns the minimum size needed to display the widget and all its * controls. */ QSize sizeHint() const override; public Q_SLOTS: /** * Sets the foreground color. */ void setForegroundColor( const KoColor &color ); /** * Sets the background color. */ void setBackgroundColor( const KoColor &color ); void slotSetForeGroundColorFromDialog (const KoColor color); void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); /** * @brief setColorSpace * set ColorSpace so we can lock the selector. Right now this'll be changed per view-change. * @param cs */ void setColorSpace(const KoColorSpace *cs); /** * @brief getColorFromDisplayRenderer * convenience function to get the right qcolor from the display renderer, including checking * whether the display renderer actually exists. * @param c the kocolor to convert. * @return the qcolor to use for display. */ QColor getColorFromDisplayRenderer(KoColor c); /** * Sets if a dialog with a color chooser should be popped up when clicking * If you set this to false then you could connect to the pleasePopDialog signal * and pop your own dialog. Just set the current color afterwards. */ void setPopDialog( bool popDialog ); Q_SIGNALS: /** * Emitted when the foreground color is changed. */ void foregroundColorChanged( const KoColor &color ); /** * Emitted when the background color is changed. */ void backgroundColorChanged( const KoColor &color ); - /** - * Emitted when the user clicks one of the two color patches. - * You should/could pop you own color chooser dialog in response. - * Also see the popDialog attribute. - */ - void pleasePopDialog( const KoColor &color ); - protected: /** * Sets the supplied rectangles to the proper size and position for the * current widget size. You can reimplement this to change the layout * of the widget. Restrictions are that the swap control will always * be at the top right, the reset control will always be at the bottom * left, and you must leave at least a 14x14 space in those corners. */ virtual void metrics( QRect &foregroundRect, QRect &backgroundRect ); void paintEvent( QPaintEvent *event ) override; void mousePressEvent( QMouseEvent *event ) override; void mouseMoveEvent( QMouseEvent *event ) override; void mouseReleaseEvent( QMouseEvent *event ) override; void dragEnterEvent( QDragEnterEvent *event ) override; void dropEvent( QDropEvent *event ) override; void changeEvent(QEvent *event) override; private: class Private; Private *const d; }; #endif