kis_paintop_box.cc 53.9 KB
Newer Older
1 2 3 4
/*
 *  kis_paintop_box.cc - part of KImageShop/Krayon/Krita
 *
 *  Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
Sven Langkamp's avatar
Sven Langkamp committed
5
 *  Copyright (c) 2009-2011 Sven Langkamp (sven.langkamp@gmail.com)
6
 *  Copyright (c) 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
7
 *  Copyright (C) 2011 Silvio Heinrich <plassy@web.de>
8
 *  Copyright (C) 2011 Srikanth Tiyyagura <srikanth.tulasiram@gmail.com>
9
 *  Copyright (c) 2014 Mohit Goyal <mohit.bits2011@gmail.com>
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
23
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
 */
25 26

#include "kis_paintop_box.h"
27

28
#include <QHBoxLayout>
29
#include <QLabel>
30
#include <QToolButton>
31
#include <QPixmap>
32
#include <QWidgetAction>
33
#include <QApplication>
34
#include <QMenu>
35
#include <QTime>
36

37
#include <kis_debug.h>
Boudewijn Rempt's avatar
Boudewijn Rempt committed
38 39

#include <kactioncollection.h>
Laurent Montel's avatar
Laurent Montel committed
40
#include <kacceleratormanager.h>
41
#include <QKeySequence>
42

43

44
#include <kis_icon.h>
45
#include <KoColorSpace.h>
46
#include <KoCompositeOpRegistry.h>
Sven Langkamp's avatar
Sven Langkamp committed
47
#include <KoResourceServerAdapter.h>
48
#include <KoToolManager.h>
49
#include <KoColorSpaceRegistry.h>
50

51
#include <kis_paint_device.h>
52 53 54
#include <brushengine/kis_paintop_registry.h>
#include <brushengine/kis_paintop_preset.h>
#include <brushengine/kis_paintop_settings.h>
55
#include <brushengine/kis_paintop_settings_update_proxy.h>
56
#include <kis_config_widget.h>
Boudewijn Rempt's avatar
Boudewijn Rempt committed
57
#include <kis_image.h>
58
#include <kis_node.h>
59
#include <brushengine/kis_paintop_config_widget.h>
60
#include <kis_action.h>
61

62
#include "kis_canvas2.h"
63
#include "kis_node_manager.h"
64
#include "KisViewManager.h"
65
#include "kis_canvas_resource_provider.h"
66
#include "KisResourceServerProvider.h"
67
#include "kis_favorite_resource_manager.h"
68
#include "kis_config.h"
69

70
#include "kis_popup_button.h"
71
#include "widgets/kis_iconwidget.h"
72
#include "widgets/kis_tool_options_popup.h"
73
#include "widgets/kis_paintop_presets_popup.h"
74
#include "widgets/kis_paintop_presets_chooser_popup.h"
Sven Langkamp's avatar
Sven Langkamp committed
75
#include "widgets/kis_workspace_chooser.h"
76 77
#include "widgets/kis_paintop_list_widget.h"
#include "widgets/kis_slider_spin_box.h"
78
#include "widgets/kis_cmb_composite.h"
79 80
#include "widgets/kis_widget_chooser.h"
#include "tool/kis_tool.h"
81
#include "kis_signals_blocker.h"
82
#include "kis_action_manager.h"
83
#include "KisHighlightedToolButton.h"
84

85 86
typedef KoResourceServerSimpleConstruction<KisPaintOpPreset, SharedPointerStoragePolicy<KisPaintOpPresetSP> > KisPaintOpPresetResourceServer;
typedef KoResourceServerAdapter<KisPaintOpPreset, SharedPointerStoragePolicy<KisPaintOpPresetSP> > KisPaintOpPresetResourceServerAdapter;
87

88
KisPaintopBox::KisPaintopBox(KisViewManager *view, QWidget *parent, const char *name)
89
    : QWidget(parent)
90
    , m_resourceProvider(view->canvasResourceProvider())
91
    , m_optionWidget(0)
92 93 94 95
    , m_toolOptionsPopupButton(0)
    , m_brushEditorPopupButton(0)
    , m_presetSelectorPopupButton(0)
    , m_toolOptionsPopup(0)
Boudewijn Rempt's avatar
Boudewijn Rempt committed
96
    , m_viewManager(view)
97
    , m_previousNode(0)
98
    , m_currTabletToolID(KoInputDevice::invalid())
99
    , m_presetsEnabled(true)
100
    , m_blockUpdate(false)
101
    , m_dirtyPresetsEnabled(false)
102
    , m_eraserBrushSizeEnabled(false)
103
    , m_eraserBrushOpacityEnabled(false)
104
{
105
    Q_ASSERT(view != 0);
106 107


108
    setObjectName(name);
109
    KisConfig cfg(true);
110
    m_dirtyPresetsEnabled = cfg.useDirtyPresets();
111
    m_eraserBrushSizeEnabled = cfg.useEraserBrushSize();
112
    m_eraserBrushOpacityEnabled = cfg.useEraserBrushOpacity();
113

114 115
    KAcceleratorManager::setNoAccel(this);

116
    setWindowTitle(i18n("Painter's Toolchest"));
117

118 119 120
    m_favoriteResourceManager = new KisFavoriteResourceManager(this);


121
    KConfigGroup grp =  KSharedConfig::openConfig()->group("krita").group("Toolbar BrushesAndStuff");
122
    int iconsize = grp.readEntry("IconSize", 32);
123

124 125
    if (!cfg.toolOptionsInDocker()) {
        m_toolOptionsPopupButton = new KisPopupButton(this);
126
        m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("configure"));
127 128 129 130
        m_toolOptionsPopupButton->setToolTip(i18n("Tool Settings"));
        m_toolOptionsPopupButton->setFixedSize(iconsize, iconsize);
    }

131
    m_brushEditorPopupButton = new KisIconWidget(this);
132
    m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02"));
133 134 135 136
    m_brushEditorPopupButton->setToolTip(i18n("Edit brush settings"));
    m_brushEditorPopupButton->setFixedSize(iconsize, iconsize);

    m_presetSelectorPopupButton = new KisPopupButton(this);
137
    m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01"));
138 139
    m_presetSelectorPopupButton->setToolTip(i18n("Choose brush preset"));
    m_presetSelectorPopupButton->setFixedSize(iconsize, iconsize);
140

141
    m_eraseModeButton = new KisHighlightedToolButton(this);
142
    m_eraseModeButton->setFixedSize(iconsize, iconsize);
143
    m_eraseModeButton->setCheckable(true);
144

145
    m_eraseAction = m_viewManager->actionManager()->createAction("erase_action");
146
    m_eraseModeButton->setDefaultAction(m_eraseAction);
147

148
    m_reloadButton = new QToolButton(this);
149
    m_reloadButton->setFixedSize(iconsize, iconsize);
150

151
    m_reloadAction = m_viewManager->actionManager()->createAction("reload_preset_action");
152
    m_reloadButton->setDefaultAction(m_reloadAction);
153

154
    m_alphaLockButton = new KisHighlightedToolButton(this);
155
    m_alphaLockButton->setFixedSize(iconsize, iconsize);
156
    m_alphaLockButton->setCheckable(true);
157 158

    KisAction* alphaLockAction = m_viewManager->actionManager()->createAction("preserve_alpha");
159 160
    m_alphaLockButton->setDefaultAction(alphaLockAction);

161 162 163 164 165
    // horizontal and vertical mirror toolbar buttons

    // mirror tool options for the X Mirror
    QMenu *toolbarMenuXMirror = new QMenu();

166
    hideCanvasDecorationsX = m_viewManager->actionManager()->createAction("mirrorX-hideDecorations");
167 168
    toolbarMenuXMirror->addAction(hideCanvasDecorationsX);

169
    lockActionX = m_viewManager->actionManager()->createAction("mirrorX-lock");
170 171
    toolbarMenuXMirror->addAction(lockActionX);

172
    moveToCenterActionX = m_viewManager->actionManager()->createAction("mirrorX-moveToCenter");
173 174 175 176 177 178
    toolbarMenuXMirror->addAction(moveToCenterActionX);


    // mirror tool options for the Y Mirror
    QMenu *toolbarMenuYMirror = new QMenu();

179
    hideCanvasDecorationsY = m_viewManager->actionManager()->createAction("mirrorY-hideDecorations");
180 181 182
    toolbarMenuYMirror->addAction(hideCanvasDecorationsY);


183
    lockActionY = m_viewManager->actionManager()->createAction("mirrorY-lock");
184 185
    toolbarMenuYMirror->addAction(lockActionY);

186
    moveToCenterActionY = m_viewManager->actionManager()->createAction("mirrorY-moveToCenter");
187 188 189 190 191 192
    toolbarMenuYMirror->addAction(moveToCenterActionY);



    // create horizontal and vertical mirror buttons

193
    m_hMirrorButton = new KisHighlightedToolButton(this);
194 195
    int menuPadding = 10;
    m_hMirrorButton->setFixedSize(iconsize + menuPadding, iconsize);
196
    m_hMirrorButton->setCheckable(true);
197
    m_hMirrorAction = m_viewManager->actionManager()->createAction("hmirror_action");
198
    m_hMirrorButton->setDefaultAction(m_hMirrorAction);
199 200
    m_hMirrorButton->setMenu(toolbarMenuXMirror);
    m_hMirrorButton->setPopupMode(QToolButton::MenuButtonPopup);
201

202
    m_vMirrorButton = new KisHighlightedToolButton(this);
203
    m_vMirrorButton->setFixedSize(iconsize + menuPadding, iconsize);
204
    m_vMirrorButton->setCheckable(true);
205
    m_vMirrorAction = m_viewManager->actionManager()->createAction("vmirror_action");
206
    m_vMirrorButton->setDefaultAction(m_vMirrorAction);
207 208 209 210 211 212 213 214
    m_vMirrorButton->setMenu(toolbarMenuYMirror);
    m_vMirrorButton->setPopupMode(QToolButton::MenuButtonPopup);


    // add connections for horizontal and mirrror buttons
    connect(lockActionX, SIGNAL(toggled(bool)), this, SLOT(slotLockXMirrorToggle(bool)));
    connect(lockActionY, SIGNAL(toggled(bool)), this, SLOT(slotLockYMirrorToggle(bool)));

215 216
    connect(moveToCenterActionX, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorX()));
    connect(moveToCenterActionY, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorY()));
217 218 219

    connect(hideCanvasDecorationsX, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorX(bool)));
    connect(hideCanvasDecorationsY, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorY(bool)));
220

221 222 223 224 225 226 227 228 229
    const bool sliderLabels = cfg.sliderLabels();
    int sliderWidth;

    if (sliderLabels) {
        sliderWidth = 150 * logicalDpiX() / 96;
    }
    else {
        sliderWidth = 120 * logicalDpiX() / 96;
    }
230 231

    for (int i = 0; i < 3; ++i) {
232
        m_sliderChooser[i] = new KisWidgetChooser(i + 1);
233

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
        KisDoubleSliderSpinBox* slOpacity;
        KisDoubleSliderSpinBox* slFlow;
        KisDoubleSliderSpinBox* slSize;
        if (sliderLabels) {
            slOpacity = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("opacity");
            slFlow    = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("flow");
            slSize    = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("size");
            slOpacity->setPrefix(QString("%1  ").arg(i18n("Opacity:")));
            slFlow->setPrefix(QString("%1  ").arg(i18n("Flow:")));
            slSize->setPrefix(QString("%1  ").arg(i18n("Size:")));
        }
        else {
            slOpacity = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("opacity", i18n("Opacity:"));
            slFlow    = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("flow", i18n("Flow:"));
            slSize    = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("size", i18n("Size:"));
        }
250

251 252 253
        slOpacity->setRange(0, 100, 0);
        slOpacity->setValue(100);
        slOpacity->setSingleStep(5);
254
        slOpacity->setSuffix(i18n("%"));
Moritz Molch's avatar
Moritz Molch committed
255
        slOpacity->setMinimumWidth(qMax(sliderWidth, slOpacity->sizeHint().width()));
256
        slOpacity->setFixedHeight(iconsize);
257
        slOpacity->setBlockUpdateSignalOnDrag(true);
258

259 260 261
        slFlow->setRange(0, 100, 0);
        slFlow->setValue(100);
        slFlow->setSingleStep(5);
262
        slFlow->setSuffix(i18n("%"));
Moritz Molch's avatar
Moritz Molch committed
263
        slFlow->setMinimumWidth(qMax(sliderWidth, slFlow->sizeHint().width()));
264
        slFlow->setFixedHeight(iconsize);
265
        slFlow->setBlockUpdateSignalOnDrag(true);
266

267
        slSize->setRange(0.01, cfg.readEntry("maximumBrushSize", 1000), 2);
268
        slSize->setValue(100);
269

270
        slSize->setSingleStep(1);
271
        slSize->setExponentRatio(3.0);
272
        slSize->setSuffix(i18n(" px"));
Moritz Molch's avatar
Moritz Molch committed
273
        slSize->setMinimumWidth(qMax(sliderWidth, slSize->sizeHint().width()));
274
        slSize->setFixedHeight(iconsize);
275
        slSize->setBlockUpdateSignalOnDrag(true);
276 277

        m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1));
278
    }
279

280
    m_cmbCompositeOp = new KisCompositeOpComboBox();
281
    m_cmbCompositeOp->setFixedHeight(iconsize);
282
    Q_FOREACH (KisAction * a, m_cmbCompositeOp->blendmodeActions()) {
283
        m_viewManager->actionManager()->addAction(a->text(), a);
284
    }
285

286
    m_workspaceWidget = new KisPopupButton(this);
287
    m_workspaceWidget->setIcon(KisIconUtils::loadIcon("view-choose"));
Sven Langkamp's avatar
Sven Langkamp committed
288
    m_workspaceWidget->setToolTip(i18n("Choose workspace"));
289
    m_workspaceWidget->setFixedSize(iconsize, iconsize);
Sven Langkamp's avatar
Sven Langkamp committed
290
    m_workspaceWidget->setPopupWidget(new KisWorkspaceChooser(view));
291

292 293 294
    QHBoxLayout* baseLayout = new QHBoxLayout(this);
    m_paintopWidget = new QWidget(this);
    baseLayout->addWidget(m_paintopWidget);
295
    baseLayout->setSpacing(4);
296
    baseLayout->setContentsMargins(0, 0, 0, 0);
297

298
    m_layout = new QHBoxLayout(m_paintopWidget);
299 300 301 302 303
    if (!cfg.toolOptionsInDocker()) {
        m_layout->addWidget(m_toolOptionsPopupButton);
    }
    m_layout->addWidget(m_brushEditorPopupButton);
    m_layout->addWidget(m_presetSelectorPopupButton);
304
    m_layout->setSpacing(4);
305
    m_layout->setContentsMargins(0, 0, 0, 0);
306

307 308 309 310
    QWidget* compositeActions = new QWidget(this);
    QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions);
    compositeLayout->addWidget(m_cmbCompositeOp);
    compositeLayout->addWidget(m_eraseModeButton);
311
    compositeLayout->addWidget(m_alphaLockButton);
312

313 314
    compositeLayout->setSpacing(4);
    compositeLayout->setContentsMargins(0, 0, 0, 0);
315

316 317
    compositeLayout->addWidget(m_reloadButton);

318
    QWidgetAction * action;
319

320
    action = new QWidgetAction(this);
321
    view->actionCollection()->addAction("composite_actions", action);
322
    action->setText(i18n("Brush composite"));
323 324
    action->setDefaultWidget(compositeActions);

325
    action = new QWidgetAction(this);
326
    KisActionRegistry::instance()->propertizeAction("brushslider1", action);
327
    view->actionCollection()->addAction("brushslider1", action);
328
    action->setDefaultWidget(m_sliderChooser[0]);
329
    connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget()));
330
    connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[0], SLOT(updateThemedIcons()));
331

332
    action = new QWidgetAction(this);
333
    KisActionRegistry::instance()->propertizeAction("brushslider2", action);
334 335
    view->actionCollection()->addAction("brushslider2", action);
    action->setDefaultWidget(m_sliderChooser[1]);
336
    connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget()));
337
    connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[1], SLOT(updateThemedIcons()));
338

339
    action = new QWidgetAction(this);
340
    KisActionRegistry::instance()->propertizeAction("brushslider3", action);
341 342 343
    view->actionCollection()->addAction("brushslider3", action);
    action->setDefaultWidget(m_sliderChooser[2]);
    connect(action, SIGNAL(triggered()), m_sliderChooser[2], SLOT(showPopupWidget()));
344
        connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[2], SLOT(updateThemedIcons()));
345

346
    action = new QWidgetAction(this);
347
    KisActionRegistry::instance()->propertizeAction("next_favorite_preset", action);
348
    view->actionCollection()->addAction("next_favorite_preset", action);
349 350
    connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset()));

351
    action = new QWidgetAction(this);
352
    KisActionRegistry::instance()->propertizeAction("previous_favorite_preset", action);
353
    view->actionCollection()->addAction("previous_favorite_preset", action);
354 355
    connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset()));

356
    action = new QWidgetAction(this);
357
    KisActionRegistry::instance()->propertizeAction("previous_preset", action);
358
    view->actionCollection()->addAction("previous_preset", action);
359 360
    connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset()));

361
    if (!cfg.toolOptionsInDocker()) {
362
        action = new QWidgetAction(this);
363
        KisActionRegistry::instance()->propertizeAction("show_tool_options", action);
364
        view->actionCollection()->addAction("show_tool_options", action);
365 366 367
        connect(action, SIGNAL(triggered()), m_toolOptionsPopupButton, SLOT(showPopupWidget()));
    }

368
    action = new QWidgetAction(this);
369
    KisActionRegistry::instance()->propertizeAction("show_brush_editor", action);
370
    view->actionCollection()->addAction("show_brush_editor", action);
371 372
    connect(action, SIGNAL(triggered()), m_brushEditorPopupButton, SLOT(showPopupWidget()));

373
    action = new QWidgetAction(this);
374
    KisActionRegistry::instance()->propertizeAction("show_brush_presets", action);
375
    view->actionCollection()->addAction("show_brush_presets", action);
376 377
    connect(action, SIGNAL(triggered()), m_presetSelectorPopupButton, SLOT(showPopupWidget()));

378 379
    QWidget* mirrorActions = new QWidget(this);
    QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions);
380 381
    mirrorLayout->addWidget(m_hMirrorButton);
    mirrorLayout->addWidget(m_vMirrorButton);
382
    mirrorLayout->setSpacing(4);
383
    mirrorLayout->setContentsMargins(0, 0, 0, 0);
384 385

    action = new QWidgetAction(this);
386
    KisActionRegistry::instance()->propertizeAction("mirror_actions", action);
387
    action->setDefaultWidget(mirrorActions);
388
    view->actionCollection()->addAction("mirror_actions", action);
389

390
    action = new QWidgetAction(this);
391
    KisActionRegistry::instance()->propertizeAction("workspaces", action);
392 393
    view->actionCollection()->addAction("workspaces", action);
    action->setDefaultWidget(m_workspaceWidget);
394

395 396 397 398 399 400
    if (!cfg.toolOptionsInDocker()) {
        m_toolOptionsPopup = new KisToolOptionsPopup();
        m_toolOptionsPopupButton->setPopupWidget(m_toolOptionsPopup);
        m_toolOptionsPopup->switchDetached(false);
    }

401

402 403 404
    m_savePresetWidget = new KisPresetSaveWidget(this);

    m_presetsPopup = new KisPaintOpPresetsPopup(m_resourceProvider, m_favoriteResourceManager, m_savePresetWidget);
405
    m_brushEditorPopupButton->setPopupWidget(m_presetsPopup);
406 407
    m_presetsPopup->parentWidget()->setWindowTitle(i18n("Brush Editor"));

408

409
    connect(m_presetsPopup, SIGNAL(brushEditorShown()), SLOT(slotUpdateOptionsWidgetPopup()));
410
    connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_presetsPopup, SLOT(updateThemedIcons()));
411

412
    m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup();
413 414
    m_presetsChooserPopup->setMinimumHeight(550);
    m_presetsChooserPopup->setMinimumWidth(450);
415
    m_presetSelectorPopupButton->setPopupWidget(m_presetsChooserPopup);
416

417
    m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id();
418

419
    slotNodeChanged(view->activeNode());
420 421 422 423
    // Get all the paintops
    QList<QString> keys = KisPaintOpRegistry::instance()->keys();
    QList<KisPaintOpFactory*> factoryList;

424
    Q_FOREACH (const QString & paintopId, keys) {
425 426 427 428
        factoryList.append(KisPaintOpRegistry::instance()->get(paintopId));
    }
    m_presetsPopup->setPaintOpList(factoryList);

429 430 431
    connect(m_presetsPopup       , SIGNAL(paintopActivated(QString))          , SLOT(slotSetPaintop(QString)));
    connect(m_presetsPopup       , SIGNAL(defaultPresetClicked())             , SLOT(slotSetupDefaultPreset()));
    connect(m_presetsPopup       , SIGNAL(signalResourceSelected(KoResource*)), SLOT(resourceSelected(KoResource*)));
432 433
    connect(m_presetsPopup       , SIGNAL(reloadPresetClicked())              , SLOT(slotReloadPreset()));
    connect(m_presetsPopup       , SIGNAL(dirtyPresetToggled(bool))           , SLOT(slotDirtyPresetToggled(bool)));
434
    connect(m_presetsPopup       , SIGNAL(eraserBrushSizeToggled(bool))       , SLOT(slotEraserBrushSizeToggled(bool)));
435
    connect(m_presetsPopup       , SIGNAL(eraserBrushOpacityToggled(bool))       , SLOT(slotEraserBrushOpacityToggled(bool)));
436

437 438
    connect(m_presetsPopup, SIGNAL(createPresetFromScratch(QString)), this, SLOT(slotCreatePresetFromScratch(QString)));

439
    connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResource*))      , SLOT(resourceSelected(KoResource*)));
440 441
    connect(m_presetsChooserPopup, SIGNAL(resourceClicked(KoResource*))      , SLOT(resourceSelected(KoResource*)));

442
    connect(m_resourceProvider   , SIGNAL(sigNodeChanged(KisNodeSP))    , SLOT(slotNodeChanged(KisNodeSP)));
443
    connect(m_cmbCompositeOp     , SIGNAL(currentIndexChanged(int))           , SLOT(slotSetCompositeMode(int)));
444 445
    connect(m_eraseAction          , SIGNAL(toggled(bool))                    , SLOT(slotToggleEraseMode(bool)));
    connect(alphaLockAction      , SIGNAL(toggled(bool))                    , SLOT(slotToggleAlphaLockMode(bool)));
446

447 448
    m_disablePressureAction = m_viewManager->actionManager()->createAction("disable_pressure");
    connect(m_disablePressureAction  , SIGNAL(toggled(bool))                    , SLOT(slotDisablePressureMode(bool)));
449
    m_disablePressureAction->setChecked(true);
450

451 452
    connect(m_hMirrorAction        , SIGNAL(toggled(bool))                    , SLOT(slotHorizontalMirrorChanged(bool)));
    connect(m_vMirrorAction        , SIGNAL(toggled(bool))                    , SLOT(slotVerticalMirrorChanged(bool)));
453
    connect(m_reloadAction         , SIGNAL(triggered())                        , SLOT(slotReloadPreset()));
454

455 456
    connect(m_sliderChooser[0]->getWidget<KisDoubleSliderSpinBox>("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed()));
    connect(m_sliderChooser[0]->getWidget<KisDoubleSliderSpinBox>("flow")   , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed()));
457
    connect(m_sliderChooser[0]->getWidget<KisDoubleSliderSpinBox>("size")   , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed()));
458 459
    connect(m_sliderChooser[1]->getWidget<KisDoubleSliderSpinBox>("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed()));
    connect(m_sliderChooser[1]->getWidget<KisDoubleSliderSpinBox>("flow")   , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed()));
460
    connect(m_sliderChooser[1]->getWidget<KisDoubleSliderSpinBox>("size")   , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed()));
461 462 463
    connect(m_sliderChooser[2]->getWidget<KisDoubleSliderSpinBox>("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed()));
    connect(m_sliderChooser[2]->getWidget<KisDoubleSliderSpinBox>("flow")   , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed()));
    connect(m_sliderChooser[2]->getWidget<KisDoubleSliderSpinBox>("size")   , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed()));
Sven Langkamp's avatar
Sven Langkamp committed
464

465
    //Needed to connect canvas to favorite resource manager
466
    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), SLOT(slotUnsetEraseMode()));
467

468

469
    connect(m_resourceProvider, SIGNAL(sigFGColorUsed(KoColor)), m_favoriteResourceManager, SLOT(slotAddRecentColor(KoColor)));
470

471
    connect(m_resourceProvider, SIGNAL(sigFGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotChangeFGColorSelector(KoColor)));
472
    connect(m_resourceProvider, SIGNAL(sigBGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotSetBGColor(KoColor)));
473 474 475 476
    // cold initialization
    m_favoriteResourceManager->slotChangeFGColorSelector(m_resourceProvider->fgColor());
    m_favoriteResourceManager->slotSetBGColor(m_resourceProvider->bgColor());

477
    connect(m_favoriteResourceManager, SIGNAL(sigSetFGColor(KoColor)), m_resourceProvider, SLOT(slotSetFGColor(KoColor)));
478
    connect(m_favoriteResourceManager, SIGNAL(sigSetBGColor(KoColor)), m_resourceProvider, SLOT(slotSetBGColor(KoColor)));
479
    connect(m_favoriteResourceManager, SIGNAL(sigEnableChangeColor(bool)), m_resourceProvider, SLOT(slotResetEnableFGChange(bool)));
480 481

    connect(view->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateSelectionIcon()));
482 483
    connect(m_resourceProvider->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
            this, SLOT(slotCanvasResourceChanged(int,QVariant)));
484

485
    slotInputDeviceChanged(KoToolManager::instance()->currentInputDevice());
486

487
    KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer();
488 489 490 491 492 493
    m_eraserName = "eraser_circle";
    m_defaultPresetName = "basic_tip_default";
    bool foundEraser = false;
    bool foundTip = false;
    for (int i=0; i<rserver->resourceCount(); i++) {
        KisPaintOpPresetSP resource = rserver->resources().at(i);
494
        if (resource->name().toLower().contains("eraser_circle")) {
495 496 497 498 499 500 501
            m_eraserName = resource->name();
            foundEraser = true;
        } else if (foundEraser == false && (resource->name().toLower().contains("eraser") ||
                                            resource->filename().toLower().contains("eraser"))) {
            m_eraserName = resource->name();
            foundEraser = true;
        }
502
        if (resource->name().toLower().contains("basic_tip_default")) {
503 504 505 506 507 508 509 510
            m_defaultPresetName = resource->name();
            foundTip = true;
        } else if (foundTip == false && (resource->name().toLower().contains("default") ||
                                         resource->filename().toLower().contains("default"))) {
            m_defaultPresetName = resource->name();
            foundTip = true;
        }
    }
511
}
512

513 514
KisPaintopBox::~KisPaintopBox()
{
515
    KisConfig cfg(false);
516 517 518 519
    QMapIterator<TabletToolID, TabletToolData> iter(m_tabletToolMap);
    while (iter.hasNext()) {
        iter.next();
        if ((iter.key().pointer) == QTabletEvent::Eraser) {
520
            cfg.writeEntry(QString("LastEraser") , iter.value().preset->name());
521 522
        }
        else {
523
            cfg.writeEntry(QString("LastPreset"), iter.value().preset->name());
524 525
        }
    }
luz paz's avatar
luz paz committed
526
    // Do not delete the widget, since it is global to the application, not owned by the view
527
    m_presetsPopup->setPaintOpSettingsWidget(0);
528
    qDeleteAll(m_paintopOptionWidgets);
529
    delete m_favoriteResourceManager;
530 531 532 533

    for (int i = 0; i < 3; ++i) {
        delete m_sliderChooser[i];
    }
534
}
Boudewijn Rempt's avatar
Boudewijn Rempt committed
535

536 537 538
void KisPaintopBox::restoreResource(KoResource* resource)
{
    KisPaintOpPreset* preset = dynamic_cast<KisPaintOpPreset*>(resource);
539

540
    if (preset) {
541
        setCurrentPaintop(preset);
542 543 544 545 546 547

        m_presetsPopup->setPresetImage(preset->image());
        m_presetsPopup->resourceSelected(resource);
    }
}

548 549 550 551 552 553 554
void KisPaintopBox::newOptionWidgets(const QList<QPointer<QWidget> > &optionWidgetList)
{
    if (m_toolOptionsPopup) {
        m_toolOptionsPopup->newOptionWidgets(optionWidgetList);
    }
}

555 556
void KisPaintopBox::resourceSelected(KoResource* resource)
{
557 558
    KIS_SAFE_ASSERT_RECOVER_RETURN(m_optionWidget);

559 560
    m_presetsPopup->setCreatingBrushFromScratch(false); // show normal UI elements when we are not creating

561
    KisPaintOpPreset* preset = dynamic_cast<KisPaintOpPreset*>(resource);
562
    if (preset && preset != m_resourceProvider->currentPreset()) {
563
        if (!preset->settings()->isLoadable())
564
            return;
565

566 567 568 569 570 571
        if (!m_dirtyPresetsEnabled) {
            KisSignalsBlocker blocker(m_optionWidget);
            if (!preset->load()) {
                warnKrita << "failed to load the preset.";
            }
        }
572
        //qDebug() << "resourceSelected" << resource->name();
573 574
        setCurrentPaintop(preset);

575 576 577
        m_presetsPopup->setPresetImage(preset->image());
        m_presetsPopup->resourceSelected(resource);
    }
578 579


580 581
}

582
void KisPaintopBox::setCurrentPaintop(const KoID& paintop)
583
{
584 585
    KisPaintOpPresetSP preset = activePreset(paintop);
    Q_ASSERT(preset && preset->settings());
586
    //qDebug() << "setCurrentPaintop();" << paintop << preset;
587
    setCurrentPaintop(preset);
588 589
}

590
void KisPaintopBox::setCurrentPaintop(KisPaintOpPresetSP preset)
591
{
592 593 594

    //qDebug() << "setCurrentPaintop(); " << preset->name();

595
    if (preset == m_resourceProvider->currentPreset()) {
596 597 598 599

        if (preset == m_tabletToolMap[m_currTabletToolID].preset) {
            return;
        }
600 601 602
    }
    Q_ASSERT(preset);
    const KoID& paintop = preset->paintOp();
603 604
    m_presetConnections.clear();

605
    if (m_resourceProvider->currentPreset()) {
606

607
        m_resourceProvider->setPreviousPaintOpPreset(m_resourceProvider->currentPreset());
608 609

        if (m_optionWidget) {
610 611
            m_optionWidget->hide();
        }
612

613 614
    }

615
    if (!m_paintopOptionWidgets.contains(paintop))
616
        m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createConfigWidget(this);
617

618
    m_optionWidget = m_paintopOptionWidgets[paintop];
619

620 621
    KisSignalsBlocker b(m_optionWidget);

622
    preset->setOptionsWidget(m_optionWidget);
623

Boudewijn Rempt's avatar
Boudewijn Rempt committed
624 625
    m_optionWidget->setImage(m_viewManager->image());
    m_optionWidget->setNode(m_viewManager->activeNode());
626

627
    m_presetsPopup->setPaintOpSettingsWidget(m_optionWidget);
628

629 630
    m_resourceProvider->setPaintOpPreset(preset);

631
    Q_ASSERT(m_optionWidget && m_presetSelectorPopupButton);
632

633
    m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotGuiChangedCurrentPreset()));
634 635
    m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfigurationSP)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP)));
    m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfigurationSP)), this, SLOT(slotDropLockedOption(KisPropertiesConfigurationSP)));
636

637

638
    // load the current brush engine icon for the brush editor toolbar button
639

640
    m_brushEditorPopupButton->setResource(preset.data());
641 642
    m_presetsPopup->setCurrentPaintOpId(paintop.id());

643

644 645 646 647 648 649
    ////qDebug() << "\tsetting the new preset for" << m_currTabletToolID.uniqueID << "to" << preset->name();
    m_paintOpPresetMap[m_resourceProvider->currentPreset()->paintOp()] = preset;
    m_tabletToolMap[m_currTabletToolID].preset = preset;
    m_tabletToolMap[m_currTabletToolID].paintOpID = preset->paintOp();


650
    if (m_presetsPopup->currentPaintOpId() != paintop.id()) {
651 652
        // Must change the paintop as the current one is not supported
        // by the new colorspace.
653
        dbgKrita << "current paintop " << paintop.name() << " was not set, not supported by colorspace";
654
    }
655 656 657

    m_currCompositeOpID = preset->settings()->paintOpCompositeOp();
    updateCompositeOp(m_currCompositeOpID);
658 659
}

660
void KisPaintopBox::slotUpdateOptionsWidgetPopup()
661 662 663 664 665
{
    KisPaintOpPresetSP preset = m_resourceProvider->currentPreset();
    KIS_SAFE_ASSERT_RECOVER_RETURN(preset);
    KIS_SAFE_ASSERT_RECOVER_RETURN(m_optionWidget);

666
    m_optionWidget->setConfigurationSafe(preset->settings());
667

668 669
    m_presetsPopup->resourceSelected(preset.data());
    m_presetsPopup->updateViewSettings();
670 671 672 673

    // the m_viewManager->image() is set earlier, but the reference will be missing when the stamp button is pressed
    // need to later do some research on how and when we should be using weak shared pointers (WSP) that creates this situation
    m_optionWidget->setImage(m_viewManager->image());
674 675
}

676
KisPaintOpPresetSP KisPaintopBox::defaultPreset(const KoID& paintOp)
677
{
678
    QString defaultName = paintOp.id() + ".kpp";
679
    QString path = KoResourcePaths::findResource("kis_defaultpresets", defaultName);
680

681
    KisPaintOpPresetSP preset = new KisPaintOpPreset(path);
682

683
    if (!preset->load()) {
684
        preset = KisPaintOpRegistry::instance()->defaultPreset(paintOp);
685 686 687 688
    }

    Q_ASSERT(preset);
    Q_ASSERT(preset->valid());
689

690 691
    return preset;
}
692

693 694
KisPaintOpPresetSP KisPaintopBox::activePreset(const KoID& paintOp)
{
695
    if (m_paintOpPresetMap[paintOp] == 0) {
696
        m_paintOpPresetMap[paintOp] = defaultPreset(paintOp);
697
    }
698

699
    return m_paintOpPresetMap[paintOp];
700 701
}

702
void KisPaintopBox::updateCompositeOp(QString compositeOpID)
703
{
704 705 706
    if (!m_optionWidget) return;
    KisSignalsBlocker blocker(m_optionWidget);

707
    KisNodeSP node = m_resourceProvider->currentNode();
708 709 710

    if (node && node->paintDevice()) {
        if (!node->paintDevice()->colorSpace()->hasCompositeOp(compositeOpID))
711
            compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id();
712

713 714 715 716
        {
            KisSignalsBlocker b1(m_cmbCompositeOp);
            m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID));
        }
717
        if (compositeOpID != m_currCompositeOpID) {
718 719
            m_currCompositeOpID = compositeOpID;
        }
720
        if (compositeOpID == COMPOSITE_ERASE || m_resourceProvider->eraserMode()) {
721 722 723 724 725
            m_eraseModeButton->setChecked(true);
        }
        else {
            m_eraseModeButton->setChecked(false);
        }
726
    }
727 728 729 730 731 732
    else if (!node) {
        KisSignalsBlocker b1(m_cmbCompositeOp);
        m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID));
        m_currCompositeOpID = compositeOpID;

    }
733 734 735 736
}

void KisPaintopBox::setWidgetState(int flags)
{
737
    if (flags & (ENABLE_COMPOSITEOP | DISABLE_COMPOSITEOP)) {
738 739 740
        m_cmbCompositeOp->setEnabled(flags & ENABLE_COMPOSITEOP);
        m_eraseModeButton->setEnabled(flags & ENABLE_COMPOSITEOP);
    }
741 742

    if (flags & (ENABLE_PRESETS | DISABLE_PRESETS)) {
743 744
        m_presetSelectorPopupButton->setEnabled(flags & ENABLE_PRESETS);
        m_brushEditorPopupButton->setEnabled(flags & ENABLE_PRESETS);
745
    }
746 747 748

    for (int i = 0; i < 3; ++i) {
        if (flags & (ENABLE_OPACITY | DISABLE_OPACITY))
749
            m_sliderChooser[i]->getWidget("opacity")->setEnabled(flags & ENABLE_OPACITY);
750 751

        if (flags & (ENABLE_FLOW | DISABLE_FLOW))
752
            m_sliderChooser[i]->getWidget("flow")->setEnabled(flags & ENABLE_FLOW);
753 754

        if (flags & (ENABLE_SIZE | DISABLE_SIZE))
755
            m_sliderChooser[i]->getWidget("size")->setEnabled(flags & ENABLE_SIZE);
756 757 758 759 760
    }
}

void KisPaintopBox::setSliderValue(const QString& sliderID, qreal value)
{
761
    for (int i = 0; i < 3; ++i) {
762
        KisDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget<KisDoubleSliderSpinBox>(sliderID);
763
        KisSignalsBlocker b(slider);
764 765 766 767 768 769 770 771

        if (sliderID == "opacity" || sliderID == "flow") { // opacity and flows UI stored at 0-100%
            slider->setValue(value*100);
        } else {
            slider->setValue(value); // brush size
        }


772 773 774 775 776
    }
}

void KisPaintopBox::slotSetPaintop(const QString& paintOpId)
{
777
    if (KisPaintOpRegistry::instance()->get(paintOpId) != 0) {
778
        KoID id(paintOpId, KisPaintOpRegistry::instance()->get(paintOpId)->name());
779
        //qDebug() << "slotsetpaintop" << id;
780 781 782 783 784 785 786
        setCurrentPaintop(id);
    }
}

void KisPaintopBox::slotInputDeviceChanged(const KoInputDevice& inputDevice)
{
    TabletToolMap::iterator toolData = m_tabletToolMap.find(inputDevice);
787

788 789
    //qDebug() << "slotInputDeviceChanged()" << inputDevice.device() << inputDevice.uniqueTabletId();

790 791
    m_currTabletToolID = TabletToolID(inputDevice);

792
    if (toolData == m_tabletToolMap.end()) {
793
        KisConfig cfg(true);
794
        KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer();
795 796
        KisPaintOpPresetSP preset;
        if (inputDevice.pointer() == QTabletEvent::Eraser) {
797
            preset = rserver->resourceByName(cfg.readEntry<QString>(QString("LastEraser_%1").arg(inputDevice.uniqueTabletId()), m_eraserName));
798
        }
799
        else {
800
            preset = rserver->resourceByName(cfg.readEntry<QString>(QString("LastPreset_%1").arg(inputDevice.uniqueTabletId()), m_defaultPresetName));
801 802 803
            //if (preset)
                //qDebug() << "found stored preset " << preset->name() << "for" << inputDevice.uniqueTabletId();
            //else
804
                //qDebug() << "no preset found for" << inputDevice.uniqueTabletId();
805 806
        }
        if (!preset) {
807
            preset = rserver->resourceByName(m_defaultPresetName);
808
        }
Boudewijn Rempt's avatar
Boudewijn Rempt committed
809
        if (preset) {
810
            //qDebug() << "inputdevicechanged 1" << preset;
811
            setCurrentPaintop(preset);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
812
        }
813 814
    }
    else {
815
        if (toolData->preset) {
816
            //qDebug() << "inputdevicechanged 2" << toolData->preset;
817 818 819
            setCurrentPaintop(toolData->preset);
        }
        else {
820
            //qDebug() << "inputdevicechanged 3" << toolData->paintOpID;
821 822
            setCurrentPaintop(toolData->paintOpID);
        }
823
    }
824 825
}

826 827
void KisPaintopBox::slotCreatePresetFromScratch(QString paintop)
{
828 829 830 831
    //First try to select an available default preset for that engine. If it doesn't exist, then
    //manually set the engine to use a new preset.
    KoID id(paintop, KisPaintOpRegistry::instance()->get(paintop)->name());
    KisPaintOpPresetSP preset = defaultPreset(id);
832 833 834

    slotSetPaintop(paintop);  // change the paintop settings area and update the UI

835 836 837 838 839 840 841
    if (!preset) {
        m_presetsPopup->setCreatingBrushFromScratch(true); // disable UI elements while creating from scratch
        preset = m_resourceProvider->currentPreset();
    } else {
        m_resourceProvider->setPaintOpPreset(preset);
        preset->setOptionsWidget(m_optionWidget);
    }
842 843 844
    m_presetsPopup->resourceSelected(preset.data());  // this helps update the UI on the brush editor
}

845
void KisPaintopBox::slotCanvasResourceChanged(int key, const QVariant &value)
846
{
Boudewijn Rempt's avatar
Boudewijn Rempt committed
847
    if (m_viewManager) {
848
        sender()->blockSignals(true);
849
        KisPaintOpPresetSP preset = m_viewManager->canvasResourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value<KisPaintOpPresetSP>();
850
        if (preset && m_resourceProvider->currentPreset()->name() != preset->name()) {
851 852 853 854
            QString compositeOp = preset->settings()->getString("CompositeOp");
            updateCompositeOp(compositeOp);
            resourceSelected(preset.data());
        }
855 856 857 858 859

        /**
         * Update currently selected preset in both the popup widgets
         */
        m_presetsChooserPopup->canvasResourceChanged(preset);
860

861
        m_presetsPopup->currentPresetChanged(preset);
862

863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
        if (key == KisCanvasResourceProvider::CurrentCompositeOp) {
            if (m_resourceProvider->currentCompositeOp() != m_currCompositeOpID) {
                updateCompositeOp(m_resourceProvider->currentCompositeOp());
            }
        }

        if (key == KisCanvasResourceProvider::Size) {
            setSliderValue("size", m_resourceProvider->size());
        }

        if (key == KisCanvasResourceProvider::Opacity) {
            setSliderValue("opacity", m_resourceProvider->opacity());
        }

        if (key == KisCanvasResourceProvider::Flow) {
            setSliderValue("flow", m_resourceProvider->flow());
879
        }
880 881 882 883 884

        if (key == KisCanvasResourceProvider::EraserMode) {
            m_eraseAction->setChecked(value.toBool());
        }

885 886 887 888
        if (key == KisCanvasResourceProvider::DisablePressure) {
            m_disablePressureAction->setChecked(value.toBool());
        }

889 890 891 892 893 894 895 896
        if (key == KisCanvasResourceProvider::MirrorHorizontal) {
            m_hMirrorAction->setChecked(value.toBool());
        }

        if (key == KisCanvasResourceProvider::MirrorVertical) {
            m_vMirrorAction->setChecked(value.toBool());
        }

897 898 899 900
        sender()->blockSignals(false);
    }
}

901 902
void KisPaintopBox::slotSetupDefaultPreset()
{
903
    KisPaintOpPresetSP preset = defaultPreset(m_resourceProvider->currentPreset()->paintOp());
904 905
    preset->setOptionsWidget(m_optionWidget);
    m_resourceProvider->setPaintOpPreset(preset);
906 907 908 909

    // tell the brush editor that the resource has changed
    // so it can update everything
    m_presetsPopup->resourceSelected(preset.data());
910 911
}

912
void KisPaintopBox::slotNodeChanged(const KisNodeSP node)
913
{
914
    if (m_previousNode.isValid() && m_previousNode->paintDevice())
915
        disconnect(m_previousNode->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*)));
916

917
    // Reconnect colorspace change of node
918
    if (node && node->paintDevice()) {
919 920 921 922
        connect(node->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*)));
        m_resourceProvider->setCurrentCompositeOp(m_currCompositeOpID);
        m_previousNode = node;
        slotColorSpaceChanged(node->colorSpace());
923
    }
924

925 926
    if (m_optionWidget) {
        m_optionWidget->setNode(node);
927
    }
928 929
}

930
void KisPaintopBox::slotColorSpaceChanged(const KoColorSpace* colorSpace)
931
{
932
    m_cmbCompositeOp->validate(colorSpace);
933 934
}

935
void KisPaintopBox::slotToggleEraseMode(bool checked)
936
{
937
    const bool oldEraserMode = m_resourceProvider->eraserMode();
938
    m_resourceProvider->setEraserMode(checked);
939

940
    if (oldEraserMode != checked && m_eraserBrushSizeEnabled) {
941 942 943
        const qreal currentSize = m_resourceProvider->size();

        KisPaintOpSettingsSP settings = m_resourceProvider->currentPreset()->settings();
944

945 946 947 948 949 950 951 952 953 954 955
        // remember brush size. set the eraser size to the normal brush size if not set
        if (checked) {
            settings->setSavedBrushSize(currentSize);
            if (qFuzzyIsNull(settings->savedEraserSize())) {
                settings->setSavedEraserSize(currentSize);
            }
        } else {
            settings->setSavedEraserSize(currentSize);
            if (qFuzzyIsNull(settings->savedBrushSize())) {
                settings->setSavedBrushSize(currentSize);
            }
Boudewijn Rempt's avatar
Boudewijn Rempt committed
956
        }
957

958
        //update value in UI (this is the main place the value is 'stored' in memory)
959 960
        qreal newSize = checked ? settings->savedEraserSize() : settings->savedBrushSize();
        m_resourceProvider->setSize(newSize);
961
    }
Timothée Giet's avatar
Timothée Giet committed
962
   if (oldEraserMode != checked && m_eraserBrushOpacityEnabled) {
963 964 965 966
        const qreal currentOpacity = m_resourceProvider->opacity();

        KisPaintOpSettingsSP settings = m_resourceProvider->currentPreset()->settings();

Timothée Giet's avatar
Timothée Giet committed
967
        // remember brush opacity. set the eraser opacity to the normal brush opacity if not set
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
        if (checked) {
            settings->setSavedBrushOpacity(currentOpacity);
            if (qFuzzyIsNull(settings->savedEraserOpacity())) {
                settings->setSavedEraserOpacity(currentOpacity);
            }
        } else {
            settings->setSavedEraserOpacity(currentOpacity);
            if (qFuzzyIsNull(settings->savedBrushOpacity())) {
                settings->setSavedBrushOpacity(currentOpacity);
            }
        }

        //update value in UI (this is the main place the value is 'stored' in memory)
        qreal newOpacity = checked ? settings->savedEraserOpacity() : settings->savedBrushOpacity();
        m_resourceProvider->setOpacity(newOpacity);
    }