KoColorPopupAction.cpp 7.17 KB
Newer Older
1
/* This file is part of the KDE project
C. Boemann's avatar
C. Boemann committed
2
 * Copyright (c) 2007 C. Boemann <cbo@boemann.dk>
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 * Copyright (C) 2007 Fredy Yanardi <fyanardi@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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 "KoColorPopupAction.h"

#include "KoColorSetWidget.h"
#include "KoTriangleColorSelector.h"
#include "KoColorSlider.h"
#include "KoCheckerBoardPainter.h"
27 28 29 30 31
#include "KoResourceServer.h"
#include "KoResourceServerProvider.h"
#include <KoColorSpaceRegistry.h>
#include <KoColor.h>

32
#include <WidgetsDebug.h>
33
#include <klocalizedstring.h>
34 35 36 37 38 39

#include <QPainter>
#include <QWidgetAction>
#include <QMenu>
#include <QHBoxLayout>
#include <QGridLayout>
40
#include <QToolButton>
41
#include <QPointer>
42 43 44 45

class KoColorPopupAction::KoColorPopupActionPrivate
{
public:
46
    KoColorPopupActionPrivate()
47 48 49 50 51 52 53 54
        : colorSetWidget(0)
        , colorChooser(0)
        , opacitySlider(0)
        , menu(0)
        , checkerPainter(4)
        , showFilter(true)
        , applyMode(true)
        , firstTime(true)
55 56
    {}

Jan Hambrecht's avatar
Jan Hambrecht committed
57 58 59 60
    ~KoColorPopupActionPrivate()
    {
        delete menu;
    }
61

62 63 64 65 66 67 68 69 70 71
    KoColor currentColor;
    KoColor buddyColor;

    KoColorSetWidget *colorSetWidget;
    KoTriangleColorSelector * colorChooser;
    KoColorSlider * opacitySlider;
    QMenu *menu;
    KoCheckerBoardPainter checkerPainter;
    bool showFilter;
    bool applyMode;
72 73

    bool firstTime;
74 75 76
};

KoColorPopupAction::KoColorPopupAction(QObject *parent)
77
    : QAction(parent),
78 79 80 81 82 83
    d(new KoColorPopupActionPrivate())
{
    d->menu = new QMenu();
    QWidget *widget = new QWidget(d->menu);
    QWidgetAction *wdgAction = new QWidgetAction(d->menu);
    d->colorSetWidget = new KoColorSetWidget(widget);
84
    KoResourceServer<KoColorSet>* rServer = KoResourceServerProvider::instance()->paletteServer();
85

86
    QPointer<KoColorSet> defaultColorSet = rServer->resourceByName("Default");
87 88
    if (!defaultColorSet && rServer->resources().count() > 0) {
        defaultColorSet = rServer->resources().first();
89
    }
90
    d->colorSetWidget->setColorSet(defaultColorSet);
91

92 93 94 95 96 97
    d->colorChooser = new KoTriangleColorSelector( widget );
    // prevent mouse release on color selector from closing popup
    d->colorChooser->setAttribute( Qt::WA_NoMousePropagation );
    d->opacitySlider = new KoColorSlider( Qt::Vertical, widget );
    d->opacitySlider->setFixedWidth(25);
    d->opacitySlider->setRange(0, 255);
98
    d->opacitySlider->setValue(255);
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    d->opacitySlider->setToolTip( i18n( "Opacity" ) );

    QGridLayout * layout = new QGridLayout( widget );
    layout->addWidget( d->colorSetWidget, 0, 0, 1, -1 );
    layout->addWidget( d->colorChooser, 1, 0 );
    layout->addWidget( d->opacitySlider, 1, 1 );
    layout->setMargin(4);

    wdgAction->setDefaultWidget(widget);
    d->menu->addAction(wdgAction);
    setMenu(d->menu);
    new QHBoxLayout(d->menu);
    d->menu->layout()->addWidget(widget);
    d->menu->layout()->setMargin(0);

    connect(this, SIGNAL(triggered()), this, SLOT(emitColorChanged()));

116 117 118 119
    connect(d->colorSetWidget, SIGNAL(colorChanged(KoColor,bool)),
            this, SLOT(colorWasSelected(KoColor,bool)));
    connect(d->colorChooser, SIGNAL(colorChanged(QColor)),
            this, SLOT(colorWasEdited(QColor)));
120 121
    connect(d->opacitySlider, SIGNAL(valueChanged(int)),
            this, SLOT(opacityWasChanged(int)));
122 123 124 125 126 127 128
}

KoColorPopupAction::~KoColorPopupAction()
{
    delete d;
}

Cyrille Berger's avatar
Cyrille Berger committed
129
void KoColorPopupAction::setCurrentColor( const KoColor &color )
130
{
Cyrille Berger's avatar
Cyrille Berger committed
131
    KoColor minColor( color );
132 133
    d->currentColor = minColor;

134 135 136 137
    d->colorChooser->blockSignals(true);
    d->colorChooser->slotSetColor(color);
    d->colorChooser->blockSignals(false);

Cyrille Berger's avatar
Cyrille Berger committed
138
    KoColor maxColor( color );
139 140
    minColor.setOpacity( OPACITY_TRANSPARENT_U8 );
    maxColor.setOpacity( OPACITY_OPAQUE_U8 );
141

142 143
    d->opacitySlider->blockSignals( true );
    d->opacitySlider->setColors( minColor, maxColor );
144
    d->opacitySlider->setValue( color.opacityU8() );
145 146 147 148 149
    d->opacitySlider->blockSignals( false );

    updateIcon();
}

Cyrille Berger's avatar
Cyrille Berger committed
150 151 152 153
void KoColorPopupAction::setCurrentColor( const QColor &_color )
{
#ifndef NDEBUG
    if (!_color.isValid()) {
154
        warnWidgets << "Invalid color given, defaulting to black";
Cyrille Berger's avatar
Cyrille Berger committed
155 156 157 158 159 160
    }
#endif
    const QColor color(_color.isValid() ? _color : QColor(0,0,0,255));
    setCurrentColor(KoColor(color, KoColorSpaceRegistry::instance()->rgb8() ));
}

161 162 163 164 165
QColor KoColorPopupAction::currentColor() const
{
    return d->currentColor.toQColor();
}

166 167 168 169 170
KoColor KoColorPopupAction::currentKoColor() const
{
    return d->currentColor;
}

171
void KoColorPopupAction::updateIcon()
172
{
173 174 175 176 177 178 179 180
    QSize iconSize;
    QToolButton *toolButton = dynamic_cast<QToolButton*>(parentWidget());
    if (toolButton) {
        iconSize = QSize(toolButton->iconSize());
    } else {
        iconSize = QSize(16, 16);
    }

181 182
    // This must be a QImage, as drawing to a QPixmap outside the
    // UI thread will cause sporadic crashes.
183 184 185
    QImage pm;

    if (icon().isNull()) {
186 187
        d->applyMode = false;
    }
188

189
    if(d->applyMode) {
190 191 192 193 194 195
        pm = icon().pixmap(iconSize).toImage();
        if (pm.isNull()) {
            pm = QImage(iconSize, QImage::Format_ARGB32_Premultiplied);
            pm.fill(Qt::transparent);
        }
        QPainter p(&pm);
196
        p.fillRect(0, iconSize.height() - 4, iconSize.width(), 4, d->currentColor.toQColor());
197 198 199 200 201
        p.end();
    } else {
        pm = QImage(iconSize, QImage::Format_ARGB32_Premultiplied);
        pm.fill(Qt::transparent);
        QPainter p(&pm);
202 203
        d->checkerPainter.paint(p, QRect(QPoint(),iconSize));
        p.fillRect(0, 0, iconSize.width(), iconSize.height(), d->currentColor.toQColor());
204
        p.end();
205
    }
206
    setIcon(QIcon(QPixmap::fromImage(pm)));
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
}

void KoColorPopupAction::emitColorChanged()
{
    emit colorChanged( d->currentColor );
}

void KoColorPopupAction::colorWasSelected(const KoColor &color, bool final)
{
    d->currentColor = color;
    if (final) {
        menu()->hide();
        emitColorChanged();
    }
    updateIcon();
}

void KoColorPopupAction::colorWasEdited( const QColor &color )
{
    d->currentColor = KoColor( color, KoColorSpaceRegistry::instance()->rgb8() );
227
    quint8 opacity = d->opacitySlider->value();
228 229 230
    d->currentColor.setOpacity( opacity );

    KoColor minColor = d->currentColor;
231
    minColor.setOpacity( OPACITY_TRANSPARENT_U8 );
232
    KoColor maxColor = minColor;
233
    maxColor.setOpacity( OPACITY_OPAQUE_U8 );
234 235 236 237 238 239 240 241 242 243

    d->opacitySlider->setColors( minColor, maxColor );

    emitColorChanged();

    updateIcon();
}

void KoColorPopupAction::opacityWasChanged( int opacity )
{
244
    d->currentColor.setOpacity( quint8(opacity) );
245 246 247

    emitColorChanged();
}