diff --git a/krita/ui/kis_canvas_resource_provider.cpp b/krita/ui/kis_canvas_resource_provider.cpp index 4f6d4bda3b..909ca41c22 100644 --- a/krita/ui/kis_canvas_resource_provider.cpp +++ b/krita/ui/kis_canvas_resource_provider.cpp @@ -1,425 +1,435 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_canvas_resource_provider.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ko_favorite_resource_manager.h" #include "kis_config.h" #include "kis_view2.h" #include "canvas/kis_canvas2.h" KisCanvasResourceProvider::KisCanvasResourceProvider(KisView2 * view) : m_view(view) , m_displayProfile(0) { m_fGChanged = true; m_enablefGChange = true; // default to true, so that colour history is working without popup palette } KisCanvasResourceProvider::~KisCanvasResourceProvider() { disconnect(); // in case Qt gets confused } KoCanvasResourceManager* KisCanvasResourceProvider::resourceManager() { return m_resourceManager; } void KisCanvasResourceProvider::setResourceManager(KoCanvasResourceManager *resourceManager) { m_resourceManager = resourceManager; QVariant v; v.setValue(KoColor(Qt::black, m_view->image()->colorSpace())); m_resourceManager->setResource(KoCanvasResourceManager::ForegroundColor, v); v.setValue(KoColor(Qt::white, m_view->image()->colorSpace())); m_resourceManager->setResource(KoCanvasResourceManager::BackgroundColor, v); setCurrentCompositeOp(COMPOSITE_OVER); setMirrorHorizontal(false); setMirrorVertical(false); m_resourceManager->setResource(HdrExposure, 0.0); m_resourceManager->setResource(HdrGamma, 1.0); connect(m_resourceManager, SIGNAL(canvasResourceChanged(int,QVariant)), this, SLOT(slotCanvasResourceChanged(int,QVariant))); m_resourceManager->setResource(KoCanvasResourceManager::ApplicationSpeciality, KoCanvasResourceManager::NoAdvancedText); } KoCanvasBase * KisCanvasResourceProvider::canvas() const { return m_view->canvasBase(); } KoColor KisCanvasResourceProvider::bgColor() const { return m_resourceManager->resource(KoCanvasResourceManager::BackgroundColor).value(); } KoColor KisCanvasResourceProvider::fgColor() const { return m_resourceManager->resource(KoCanvasResourceManager::ForegroundColor).value(); } float KisCanvasResourceProvider::HDRExposure() const { return static_cast(m_resourceManager->resource(HdrExposure).toDouble()); } void KisCanvasResourceProvider::setHDRExposure(float exposure) { m_resourceManager->setResource(HdrExposure, static_cast(exposure)); } float KisCanvasResourceProvider::HDRGamma() const { return static_cast(m_resourceManager->resource(HdrGamma).toDouble()); } void KisCanvasResourceProvider::setHDRGamma(float gamma) { m_resourceManager->setResource(HdrGamma, static_cast(gamma)); } KisPattern * KisCanvasResourceProvider::currentPattern() const { return static_cast(m_resourceManager->resource(CurrentPattern).value()); } KisFilterConfiguration * KisCanvasResourceProvider::currentGeneratorConfiguration() const { return static_cast(m_resourceManager-> resource(CurrentGeneratorConfiguration).value()); } KoAbstractGradient* KisCanvasResourceProvider::currentGradient() const { return static_cast(m_resourceManager->resource(CurrentGradient).value()); } void KisCanvasResourceProvider::resetDisplayProfile(int screen) { KisConfig cfg; m_displayProfile = cfg.displayProfile(screen); emit sigDisplayProfileChanged(m_displayProfile); } const KoColorProfile * KisCanvasResourceProvider::currentDisplayProfile() const { return m_displayProfile; } KisImageWSP KisCanvasResourceProvider::currentImage() const { return m_view->image(); } KisNodeSP KisCanvasResourceProvider::currentNode() const { return m_view->activeNode(); } KisPaintOpPresetSP KisCanvasResourceProvider::currentPreset() const { KisPaintOpPresetSP preset = m_resourceManager->resource(CurrentPaintOpPreset).value(); return preset; } void KisCanvasResourceProvider::slotPatternActivated(KoResource * res) { KisPattern * pattern = dynamic_cast(res); QVariant v = qVariantFromValue((void *) pattern); m_resourceManager->setResource(CurrentPattern, v); emit sigPatternChanged(pattern); } void KisCanvasResourceProvider::slotGeneratorConfigurationActivated(KisFilterConfiguration * res) { KisFilterConfiguration * generatorConfiguration = dynamic_cast(res); QVariant v = qVariantFromValue((void *) generatorConfiguration); m_resourceManager->setResource(CurrentGeneratorConfiguration, v); emit sigGeneratorConfigurationChanged(generatorConfiguration); } void KisCanvasResourceProvider::slotGradientActivated(KoResource *res) { KoAbstractGradient * gradient = dynamic_cast(res); QVariant v = qVariantFromValue((void *) gradient); m_resourceManager->setResource(CurrentGradient, v); emit sigGradientChanged(gradient); } void KisCanvasResourceProvider::setPaintOpPreset(const KisPaintOpPresetSP preset) { Q_ASSERT(preset->valid()); Q_ASSERT(!preset->paintOp().id().isEmpty()); Q_ASSERT(preset->settings()); if (!preset) return; dbgUI << "setPaintOpPreset" << preset->paintOp(); QVariant v; v.setValue(preset); m_resourceManager->setResource(CurrentPaintOpPreset, v); emit sigPaintOpPresetChanged(preset); } void KisCanvasResourceProvider::setBGColor(const KoColor& c) { QVariant v; v.setValue(c); m_resourceManager->setResource(KoCanvasResourceManager::BackgroundColor, v); emit sigBGColorChanged(c); } void KisCanvasResourceProvider::setFGColor(const KoColor& c) { m_fGChanged = true; QVariant v; v.setValue(c); m_resourceManager->setResource(KoCanvasResourceManager::ForegroundColor, v); emit sigFGColorChanged(c); } void KisCanvasResourceProvider::slotSetFGColor(const KoColor& c) { setFGColor(c); } void KisCanvasResourceProvider::slotSetBGColor(const KoColor& c) { setBGColor(c); } void KisCanvasResourceProvider::slotNodeActivated(const KisNodeSP node) { QVariant v; v.setValue(node); m_resourceManager->setResource(CurrentKritaNode, v); emit sigNodeChanged(currentNode()); } void KisCanvasResourceProvider::slotImageSizeChanged() { if (KisImageWSP image = m_view->image()) { float fw = image->width() / image->xRes(); float fh = image->height() / image->yRes(); QSizeF postscriptSize(fw, fh); m_resourceManager->setResource(KoCanvasResourceManager::PageSize, postscriptSize); } } void KisCanvasResourceProvider::slotSetDisplayProfile(const KoColorProfile * profile) { m_displayProfile = const_cast(profile); emit sigDisplayProfileChanged(profile); } void KisCanvasResourceProvider::slotOnScreenResolutionChanged() { KisImageWSP image = m_view->image(); KisCanvas2 *canvas = m_view->canvasBase(); if(!image || !canvas) return; qreal zoomX, zoomY; canvas->coordinatesConverter()->zoom(&zoomX, &zoomY); qreal scaleX = zoomX / image->xRes(); qreal scaleY = zoomY / image->yRes(); emit sigOnScreenResolutionChanged(scaleX, scaleY); } void KisCanvasResourceProvider::slotCanvasResourceChanged(int key, const QVariant & res) { if(key == KoCanvasResourceManager::ForegroundColor || key == KoCanvasResourceManager::BackgroundColor) { KoAbstractGradient* resource = KoResourceServerProvider::instance()->gradientServer()->resources()[0]; KoStopGradient* stopGradient = dynamic_cast(resource); if(stopGradient) { QList stops; stops << KoGradientStop(0.0, fgColor()) << KoGradientStop(1.0, bgColor()); stopGradient->setStops(stops); KoResourceServerProvider::instance()->gradientServer()->updateResource(resource); } resource = KoResourceServerProvider::instance()->gradientServer()->resources()[1]; stopGradient = dynamic_cast(resource); if(stopGradient) { QList stops; stops << KoGradientStop(0.0, fgColor()) << KoGradientStop(1.0, KoColor(QColor(0, 0, 0, 0), fgColor().colorSpace())); stopGradient->setStops(stops); KoResourceServerProvider::instance()->gradientServer()->updateResource(resource); } } switch (key) { case(KoCanvasResourceManager::ForegroundColor): m_fGChanged = true; emit sigFGColorChanged(res.value()); break; case(KoCanvasResourceManager::BackgroundColor): emit sigBGColorChanged(res.value()); break; case(CurrentPattern): emit sigPatternChanged(static_cast(res.value())); break; case(CurrentGeneratorConfiguration): emit sigGeneratorConfigurationChanged(static_cast(res.value())); case(CurrentGradient): emit sigGradientChanged(static_cast(res.value())); break; case(CurrentPaintOpPreset): emit sigPaintOpPresetChanged(currentPreset()); break; case(CurrentKritaNode) : emit sigNodeChanged(currentNode()); break; case(CurrentCompositeOp) : emit sigCompositeOpChanged(currentCompositeOp()); break; case (Opacity): { emit sigOpacityChanged(res.toDouble()); } default: ; // Do nothing }; } void KisCanvasResourceProvider::setCurrentCompositeOp(const QString& compositeOp) { QVariant v; v.setValue(compositeOp); m_resourceManager->setResource(CurrentCompositeOp, v); emit sigCompositeOpChanged(compositeOp); } QString KisCanvasResourceProvider::currentCompositeOp() const { return m_resourceManager->resource(CurrentCompositeOp).value(); } void KisCanvasResourceProvider::slotPainting() { if (m_fGChanged && m_enablefGChange) { emit sigFGColorUsed(fgColor()); m_fGChanged = false; } } void KisCanvasResourceProvider::slotResetEnableFGChange(bool b) { m_enablefGChange = b; } QList KisCanvasResourceProvider::perspectiveGrids() const { return m_perspectiveGrids; } void KisCanvasResourceProvider::addPerspectiveGrid(KisAbstractPerspectiveGrid* grid) { m_perspectiveGrids.append(grid); } void KisCanvasResourceProvider::removePerspectiveGrid(KisAbstractPerspectiveGrid* grid) { m_perspectiveGrids.removeOne(grid); } void KisCanvasResourceProvider::clearPerspectiveGrids() { m_perspectiveGrids.clear(); } void KisCanvasResourceProvider::setMirrorHorizontal(bool mirrorHorizontal) { m_resourceManager->setResource(MirrorHorizontal, mirrorHorizontal); } bool KisCanvasResourceProvider::mirrorHorizontal() const { return m_resourceManager->resource(MirrorHorizontal).toBool(); } void KisCanvasResourceProvider::setMirrorVertical(bool mirrorVertical) { m_resourceManager->setResource(MirrorVertical, mirrorVertical); } bool KisCanvasResourceProvider::mirrorVertical() const { return m_resourceManager->resource(MirrorVertical).toBool(); } void KisCanvasResourceProvider::setOpacity(qreal opacity) { m_resourceManager->setResource(Opacity, opacity); } -qreal KisCanvasResourceProvider::opacity() +qreal KisCanvasResourceProvider::opacity() const { return m_resourceManager->resource(Opacity).toDouble(); } +void KisCanvasResourceProvider::setGlobalAlphaLock(bool lock) +{ + m_resourceManager->setResource(GlobalAlphaLock, lock); +} + +bool KisCanvasResourceProvider::globalAlphaLock() const +{ + return m_resourceManager->resource(GlobalAlphaLock).toBool(); +} + void KisCanvasResourceProvider::notifyLoadingWorkspace(KisWorkspaceResource* workspace) { emit sigLoadingWorkspace(workspace); } void KisCanvasResourceProvider::notifySavingWorkspace(KisWorkspaceResource* workspace) { emit sigSavingWorkspace(workspace); } #include "kis_canvas_resource_provider.moc" diff --git a/krita/ui/kis_canvas_resource_provider.h b/krita/ui/kis_canvas_resource_provider.h index dd6c2b8a25..19778ea89e 100644 --- a/krita/ui/kis_canvas_resource_provider.h +++ b/krita/ui/kis_canvas_resource_provider.h @@ -1,196 +1,200 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CANVAS_RESOURCE_PROVIDER_H_ #define KIS_CANVAS_RESOURCE_PROVIDER_H_ #include #include #include #include #include "kis_types.h" #include "krita_export.h" class KisWorkspaceResource; class KoColorProfile; class KoAbstractGradient; class KoResource; class KoCanvasBase; class KisView2; class KisPattern; class KisFilterConfiguration; class KisAbstractPerspectiveGrid; /** * KisCanvasResourceProvider contains the per-view current settings that * influence painting, like paintop, color, gradients and so on. */ class KRITAUI_EXPORT KisCanvasResourceProvider : public QObject { Q_OBJECT public: enum Resources { HdrExposure = KoCanvasResourceManager::KritaStart + 1, CurrentPattern, CurrentGradient, CurrentDisplayProfile, CurrentImage, CurrentKritaNode, CurrentPaintOpPreset, CurrentGeneratorConfiguration, CurrentCompositeOp, MirrorHorizontal, MirrorVertical, MirrorAxisCenter, Opacity, - HdrGamma + HdrGamma, + GlobalAlphaLock }; KisCanvasResourceProvider(KisView2 * view); ~KisCanvasResourceProvider(); void setResourceManager(KoCanvasResourceManager *resourceManager); KoCanvasResourceManager* resourceManager(); KoCanvasBase * canvas() const; KoColor bgColor() const; void setBGColor(const KoColor& c); KoColor fgColor() const; void setFGColor(const KoColor& c); float HDRExposure() const; void setHDRExposure(float exposure); float HDRGamma() const; void setHDRGamma(float gamma); KisPattern *currentPattern() const; KoAbstractGradient *currentGradient() const; void resetDisplayProfile(int screen = -1); const KoColorProfile * currentDisplayProfile() const; KisImageWSP currentImage() const; KisNodeSP currentNode() const; KisPaintOpPresetSP currentPreset() const; KisFilterConfiguration* currentGeneratorConfiguration() const; void setCurrentCompositeOp(const QString& compositeOp); QString currentCompositeOp() const; QList perspectiveGrids() const; void addPerspectiveGrid(KisAbstractPerspectiveGrid*); void removePerspectiveGrid(KisAbstractPerspectiveGrid*); void clearPerspectiveGrids(); void setMirrorHorizontal(bool mirrorHorizontal); bool mirrorHorizontal() const; void setMirrorVertical(bool mirrorVertical); bool mirrorVertical() const; void setOpacity(qreal opacity); - qreal opacity(); + qreal opacity() const; + + void setGlobalAlphaLock(bool lock); + bool globalAlphaLock() const; void setPaintOpPreset(const KisPaintOpPresetSP preset); ///Notify that the workspace is saved and settings should be saved to it void notifySavingWorkspace(KisWorkspaceResource* workspace); ///Notify that the workspace is loaded and settings can be read void notifyLoadingWorkspace(KisWorkspaceResource* workspace); public slots: void slotSetFGColor(const KoColor& c); void slotSetBGColor(const KoColor& c); void slotPatternActivated(KoResource *pattern); void slotGradientActivated(KoResource *gradient); void slotNodeActivated(const KisNodeSP node); void slotGeneratorConfigurationActivated(KisFilterConfiguration * generatorConfiguration); void slotPainting(); /** * Set the image size in pixels. The resource provider will store * the image size in postscript points. */ // FIXME: this slot doesn't catch the case when image resolution is changed void slotImageSizeChanged(); void slotSetDisplayProfile(const KoColorProfile * profile); void slotOnScreenResolutionChanged(); // This is a flag to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible void slotResetEnableFGChange(bool); private slots: void slotCanvasResourceChanged(int key, const QVariant & res); signals: void sigFGColorChanged(const KoColor &); void sigBGColorChanged(const KoColor &); void sigGradientChanged(KoAbstractGradient *); void sigPatternChanged(KisPattern *); void sigPaintOpPresetChanged(KisPaintOpPresetSP preset); void sigNodeChanged(const KisNodeSP); void sigDisplayProfileChanged(const KoColorProfile *); void sigGeneratorConfigurationChanged(KisFilterConfiguration * generatorConfiguration); void sigFGColorUsed(const KoColor&); void sigCompositeOpChanged(const QString &); void sigOnScreenResolutionChanged(qreal scaleX, qreal scaleY); void sigOpacityChanged(qreal); void sigSavingWorkspace(KisWorkspaceResource* workspace); void sigLoadingWorkspace(KisWorkspaceResource* workspace); private: KisView2 * m_view; KoCanvasResourceManager *m_resourceManager; const KoColorProfile *m_displayProfile; bool m_fGChanged; QList m_perspectiveGrids; // This is a flag to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible bool m_enablefGChange; }; #endif diff --git a/krita/ui/kis_paintop_box.cc b/krita/ui/kis_paintop_box.cc index 7b0a81055a..e97a400458 100644 --- a/krita/ui/kis_paintop_box.cc +++ b/krita/ui/kis_paintop_box.cc @@ -1,809 +1,831 @@ /* * kis_paintop_box.cc - part of KImageShop/Krayon/Krita * * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2009-2011 Sven Langkamp (sven.langkamp@gmail.com) * Copyright (c) 2010 Lukáš Tvrdý * Copyright (C) 2011 Silvio Heinrich * Copyright (C) 2011 Srikanth Tiyyagura * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_paintop_box.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "kis_node_manager.h" #include "kis_view2.h" #include "kis_factory2.h" #include "kis_canvas_resource_provider.h" #include "kis_resource_server_provider.h" #include "ko_favorite_resource_manager.h" #include "kis_config.h" #include "widgets/kis_popup_button.h" #include "widgets/kis_paintop_presets_popup.h" #include "widgets/kis_paintop_presets_chooser_popup.h" #include "widgets/kis_workspace_chooser.h" #include "widgets/kis_paintop_list_widget.h" #include "widgets/kis_slider_spin_box.h" #include "widgets/kis_cmb_composite.h" #include "widgets/kis_widget_chooser.h" #include "tool/kis_tool.h" KisPaintopBox::KisPaintopBox(KisView2 * view, QWidget *parent, const char * name) : QWidget(parent) , m_resourceProvider(view->resourceProvider()) , m_optionWidget(0) , m_settingsWidget(0) , m_presetWidget(0) , m_brushChooser(0) , m_view(view) , m_activePreset(0) , m_previousNode(0) , m_currTabletToolID(KoToolManager::instance()->currentInputDevice()) , m_presetsEnabled(true) , m_blockUpdate(false) { Q_ASSERT(view != 0); KGlobal::mainComponent().dirs()->addResourceType("kis_defaultpresets", "data", "krita/defaultpresets/"); setObjectName(name); KAcceleratorManager::setNoAccel(this); setWindowTitle(i18n("Painter's Toolchest")); m_settingsWidget = new KisPopupButton(this); m_settingsWidget->setIcon(koIcon("paintop_settings_02")); m_settingsWidget->setToolTip(i18n("Edit brush settings")); m_settingsWidget->setFixedSize(32, 32); m_presetWidget = new KisPopupButton(this); m_presetWidget->setIcon(koIcon("paintop_settings_01")); m_presetWidget->setToolTip(i18n("Choose brush preset")); m_presetWidget->setFixedSize(32, 32); m_eraseModeButton = new QToolButton(this); m_eraseModeButton->setFixedSize(32, 32); m_eraseModeButton->setCheckable(true); KAction* eraseAction = new KAction(i18n("Set eraser mode"), m_eraseModeButton); eraseAction->setIcon(koIcon("draw-eraser")); eraseAction->setShortcut(Qt::Key_E); eraseAction->setCheckable(true); m_eraseModeButton->setDefaultAction(eraseAction); m_view->actionCollection()->addAction("erase_action", eraseAction); + m_alphaLockButton = new QToolButton(this); + m_alphaLockButton->setFixedSize(32, 32); + m_alphaLockButton->setCheckable(true); + KAction* alphaLockAction = new KAction(i18n("Preserve Alpha"), m_alphaLockButton); + alphaLockAction->setIcon(koIcon("transparency-unlocked")); + alphaLockAction->setCheckable(true); + m_alphaLockButton->setDefaultAction(alphaLockAction); + m_view->actionCollection()->addAction("preserve_alpha", alphaLockAction); + QToolButton* hMirrorButton = new QToolButton(this); hMirrorButton->setFixedSize(32, 32); hMirrorButton->setCheckable(true); KAction* hMirrorAction = new KAction(i18n("Set horizontal mirror mode"), hMirrorButton); hMirrorAction->setIcon(koIcon("object-flip-horizontal")); hMirrorAction->setCheckable(true); hMirrorButton->setDefaultAction(hMirrorAction); m_view->actionCollection()->addAction("hmirror_action", hMirrorAction); QToolButton* vMirrorButton = new QToolButton(this); vMirrorButton->setFixedSize(32, 32); vMirrorButton->setCheckable(true); KAction* vMirrorAction = new KAction(i18n("Set vertical mirror mode"), vMirrorButton); vMirrorAction->setIcon(koIcon("object-flip-vertical")); vMirrorAction->setCheckable(true); vMirrorButton->setDefaultAction(vMirrorAction); m_view->actionCollection()->addAction("vmirror_action", vMirrorAction); KisConfig cfg; for(int i=0; i<2; ++i) { m_sliderChooser[i] = new KisWidgetChooser(i + 1); KisDoubleSliderSpinBox* slOpacity = m_sliderChooser[i]->addWidget("opacity", i18n("Opacity:")); KisDoubleSliderSpinBox* slFlow = m_sliderChooser[i]->addWidget("flow" , i18n("Flow:")); KisDoubleSliderSpinBox* slSize = m_sliderChooser[i]->addWidget("size" , i18n("Size:")); slOpacity->setRange(0.0, 1.0, 2); slOpacity->setValue(1.0); slOpacity->setSingleStep(0.05); slOpacity->setMinimumWidth(120); slFlow->setRange(0.0, 1.0, 2); slFlow->setValue(1.0); slFlow->setSingleStep(0.05); slFlow->setMinimumWidth(120); slSize->setRange(0.0, 1000.0, 2); slSize->setValue(100.0); slSize->setSingleStep(1); slSize->setExponentRatio(3.0); slSize->setMinimumWidth(120); m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1)); } QLabel* labelMode = new QLabel(i18n("Mode: "), this); labelMode->setAlignment(Qt::AlignVCenter | Qt::AlignRight); m_cmbCompositeOp = new KisCompositeOpComboBox(); m_cmbCompositeOp->setFixedHeight(30); m_paletteButton = new QPushButton(i18n("Save to Palette")); m_paletteButton->setFixedHeight(30); m_workspaceWidget = new KisPopupButton(view); m_workspaceWidget->setIcon(koIcon("document-multiple")); m_workspaceWidget->setToolTip(i18n("Choose workspace")); m_workspaceWidget->setFixedSize(32, 32); m_workspaceWidget->setPopupWidget(new KisWorkspaceChooser(view)); QHBoxLayout* baseLayout = new QHBoxLayout(this); m_paintopWidget = new QWidget(this); baseLayout->addWidget(m_paintopWidget); baseLayout->setContentsMargins(0, 0, 0, 0); KAction* action; m_layout = new QHBoxLayout(m_paintopWidget); m_layout->addWidget(m_settingsWidget); m_layout->addWidget(m_presetWidget); m_layout->setContentsMargins(0, 0, 0, 0); QWidget* compositeActions = new QWidget(this); QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions); compositeLayout->addWidget(labelMode); compositeLayout->addWidget(m_cmbCompositeOp); compositeLayout->addWidget(m_eraseModeButton); + compositeLayout->addWidget(m_alphaLockButton); compositeLayout->setContentsMargins(0, 0, 0, 0); action = new KAction(i18n("Brush composite"), this); view->actionCollection()->addAction("composite_actions", action); action->setDefaultWidget(compositeActions); action = new KAction(i18n("Brush option slider 1"), this); view->actionCollection()->addAction("brushslider1", action); action->setDefaultWidget(m_sliderChooser[0]); connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget())); action = new KAction(i18n("Brush option slider 2"), this); view->actionCollection()->addAction("brushslider2", action); action->setDefaultWidget(m_sliderChooser[1]); connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget())); action = new KAction(i18n("Next Favourite Preset"), this); view->actionCollection()->addAction("next_favorite_preset", action); action->setShortcut(KShortcut(Qt::Key_Right)); connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset())); action = new KAction(i18n("Previous Favourite Preset"), this); view->actionCollection()->addAction("previous_favorite_preset", action); action->setShortcut(KShortcut(Qt::Key_Left)); connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset())); action = new KAction(i18n("Switch to Previous Preset"), this); view->actionCollection()->addAction("previous_preset", action); action->setShortcut(KShortcut(Qt::Key_Slash)); connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset())); QWidget* mirrorActions = new QWidget(this); QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions); mirrorLayout->addWidget(hMirrorButton); mirrorLayout->addWidget(vMirrorButton); mirrorLayout->setContentsMargins(0, 0, 0, 0); action = new KAction(i18n("Mirror"), this); view->actionCollection()->addAction("mirror_actions", action); action->setDefaultWidget(mirrorActions); action = new KAction(i18n("Add to palette"), this); view->actionCollection()->addAction("palette_manager", action); action->setDefaultWidget(m_paletteButton); action = new KAction(i18n("Workspaces"), this); view->actionCollection()->addAction("workspaces", action); action->setDefaultWidget(m_workspaceWidget); m_presetsPopup = new KisPaintOpPresetsPopup(m_resourceProvider); m_settingsWidget->setPopupWidget(m_presetsPopup); m_presetsPopup->switchDetached(); m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup(); m_presetsChooserPopup->setFixedSize(500, 500); m_presetWidget->setPopupWidget(m_presetsChooserPopup); m_prevCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); slotNodeChanged(view->activeNode()); updatePaintops(view->image()->colorSpace()); setCurrentPaintop(defaultPaintOp()); connect(m_presetsPopup , SIGNAL(paintopActivated(QString)) , SLOT(slotSetPaintop(QString))); connect(m_presetsPopup , SIGNAL(savePresetClicked()) , SLOT(slotSaveActivePreset())); connect(m_presetsPopup , SIGNAL(defaultPresetClicked()) , SLOT(slotSetupDefaultPreset())); connect(m_presetsPopup , SIGNAL(presetNameLineEditChanged(QString)) , SLOT(slotWatchPresetNameLineEdit(QString))); connect(m_presetsPopup , SIGNAL(signalResourceSelected(KoResource*)), SLOT(resourceSelected(KoResource*))); connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResource*)) , SLOT(resourceSelected(KoResource*))); connect(m_resourceProvider , SIGNAL(sigNodeChanged(const KisNodeSP)) , SLOT(slotNodeChanged(const KisNodeSP))); connect(m_paletteButton , SIGNAL(clicked()) , SLOT(slotSaveToFavouriteBrushes())); connect(m_cmbCompositeOp , SIGNAL(activated(int)) , SLOT(slotSetCompositeMode(int))); connect(eraseAction , SIGNAL(triggered(bool)) , SLOT(slotToggleEraseMode(bool))); + connect(alphaLockAction , SIGNAL(triggered(bool)) , SLOT(slotToggleAlphaLockMode(bool))); connect(hMirrorAction , SIGNAL(triggered(bool)) , SLOT(slotHorizontalMirrorChanged(bool))); connect(vMirrorAction , SIGNAL(triggered(bool)) , SLOT(slotVerticalMirrorChanged(bool))); connect(m_sliderChooser[0]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[0]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[0]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[1]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[1]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[1]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); //Needed to connect canvas to favorite resource manager m_view->canvasBase()->createFavoriteResourceManager(this); connect(m_view->resourceProvider(), SIGNAL(sigOpacityChanged(qreal)), SLOT(slotOpacityChanged(qreal))); connect(m_view->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), SLOT(slotUnsetEraseMode())); } KisPaintopBox::~KisPaintopBox() { // Do not delete the widget, since it it is global to the application, not owned by the view m_presetsPopup->setPaintOpSettingsWidget(0); qDeleteAll(m_paintopOptionWidgets); } KisPaintOpPresetSP KisPaintopBox::paintOpPresetSP(KoID* paintop) { if(paintop == 0) return m_activePreset->clone(); return activePreset(*paintop); } void KisPaintopBox::updatePaintops(const KoColorSpace* colorSpace) { /* get the list of the factories*/ QList keys = KisPaintOpRegistry::instance()->keys(); QList factoryList; foreach(const QString & paintopId, keys) { KisPaintOpFactory * factory = KisPaintOpRegistry::instance()->get(paintopId); if (KisPaintOpRegistry::instance()->userVisible(KoID(factory->id(), factory->name()), colorSpace)){ factoryList.append(factory); } } m_presetsPopup->setPaintOpList(factoryList); } void KisPaintopBox::resourceSelected(KoResource* resource) { KisPaintOpPreset* preset = dynamic_cast(resource); if (preset) { if(!preset->settings()->isLoadable()) return; setCurrentPaintop(preset->paintOp(), preset->clone()); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } QPixmap KisPaintopBox::paintopPixmap(const KoID& paintop) { QString pixmapName = KisPaintOpRegistry::instance()->pixmap(paintop); if(pixmapName.isEmpty()) return QPixmap(); return QPixmap(KisFactory2::componentData().dirs()->findResource("kis_images", pixmapName)); } KoID KisPaintopBox::currentPaintop() { return m_activePreset->paintOp(); } void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP preset) { if (m_activePreset) { m_previousPreset = m_activePreset->clone(); if (m_optionWidget) { m_optionWidget->writeConfiguration(const_cast(m_activePreset->settings().data())); m_optionWidget->disconnect(this); m_optionWidget->hide(); } m_paintOpPresetMap[m_activePreset->paintOp()] = m_activePreset->clone(); m_tabletToolMap[m_currTabletToolID].preset = m_activePreset->clone(); m_tabletToolMap[m_currTabletToolID].paintOpID = m_activePreset->paintOp(); } preset = (!preset) ? activePreset(paintop) : preset; Q_ASSERT(preset && preset->settings()); if(!m_paintopOptionWidgets.contains(paintop)) m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createSettingsWidget(this); m_optionWidget = m_paintopOptionWidgets[paintop]; // the node should be initialized before the configuration (see KisFilterOp) preset->settings()->setOptionsWidget(m_optionWidget); preset->settings()->setNode(m_resourceProvider->currentNode()); m_optionWidget->setImage(m_view->image()); m_optionWidget->setConfiguration(preset->settings()); m_presetsPopup->setPaintOpSettingsWidget(m_optionWidget); Q_ASSERT(m_optionWidget && m_presetWidget); connect(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotUpdatePreset())); KisPaintOpFactory* paintOp = KisPaintOpRegistry::instance()->get(paintop.id()); QString pixFilename = KisFactory2::componentData().dirs()->findResource("kis_images", paintOp->pixmap()); m_settingsWidget->setIcon(QIcon(pixFilename)); m_resourceProvider->setPaintOpPreset(preset); m_presetsPopup->setCurrentPaintOp(paintop.id()); if (m_presetsPopup->currentPaintOp() != paintop.id()){ // Must change the paintop as the current one is not supported // by the new colorspace. kWarning() << "current paintop " << paintop.name() << " was not set, not supported by colorspace"; } m_activePreset = preset; } KoID KisPaintopBox::defaultPaintOp() { return KoID("paintbrush"); } KisPaintOpPresetSP KisPaintopBox::defaultPreset(const KoID& paintOp) { QString defaultName = paintOp.id() + ".kpp"; QString path = KGlobal::mainComponent().dirs()->findResource("kis_defaultpresets", defaultName); KisPaintOpPresetSP preset = new KisPaintOpPreset(path); if (!preset->load()) { preset = KisPaintOpRegistry::instance()->defaultPreset(paintOp, m_view->image()); } Q_ASSERT(preset); Q_ASSERT(preset->valid()); return preset; } KisPaintOpPresetSP KisPaintopBox::activePreset(const KoID& paintOp) { if (m_paintOpPresetMap[paintOp] == 0) { m_paintOpPresetMap[paintOp] = defaultPreset(paintOp); } return m_paintOpPresetMap[paintOp]; } void KisPaintopBox::updateCompositeOp(QString compositeOpID) { KisNodeSP node = m_resourceProvider->currentNode(); if(node && node->paintDevice()) { if(!node->paintDevice()->colorSpace()->hasCompositeOp(compositeOpID)) compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); int index = m_cmbCompositeOp->indexOf(KoID(compositeOpID)); m_cmbCompositeOp->blockSignals(true); m_cmbCompositeOp->setCurrentIndex(index); m_cmbCompositeOp->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(true); m_eraseModeButton->blockSignals(true); m_eraseModeButton->setChecked(compositeOpID == COMPOSITE_ERASE); m_eraseModeButton->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(false); if(compositeOpID != m_currCompositeOpID) { m_activePreset->settings()->setProperty("CompositeOp", compositeOpID); m_optionWidget->setConfiguration(m_activePreset->settings().data()); m_resourceProvider->setCurrentCompositeOp(compositeOpID); m_prevCompositeOpID = m_currCompositeOpID; m_currCompositeOpID = compositeOpID; } } } void KisPaintopBox::setWidgetState(int flags) { if(flags & (ENABLE_COMPOSITEOP|DISABLE_COMPOSITEOP)) { m_cmbCompositeOp->setEnabled(flags & ENABLE_COMPOSITEOP); m_eraseModeButton->setEnabled(flags & ENABLE_COMPOSITEOP); } if(flags & (ENABLE_PRESETS|DISABLE_PRESETS)) { m_presetWidget->setEnabled(flags & ENABLE_PRESETS); m_settingsWidget->setEnabled(flags & ENABLE_PRESETS); } for(int i=0; i<2; ++i) { if(flags & (ENABLE_OPACITY|DISABLE_OPACITY)) m_sliderChooser[i]->getWidget("opacity")->setEnabled(flags & ENABLE_OPACITY); if(flags & (ENABLE_FLOW|DISABLE_FLOW)) m_sliderChooser[i]->getWidget("flow")->setEnabled(flags & ENABLE_FLOW); if(flags & (ENABLE_SIZE|DISABLE_SIZE)) m_sliderChooser[i]->getWidget("size")->setEnabled(flags & ENABLE_SIZE); } } void KisPaintopBox::setSliderValue(const QString& sliderID, qreal value) { for(int i=0; i<2; ++i) { KisDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget(sliderID); slider->blockSignals(true); slider->setValue(value); slider->blockSignals(false); } } void KisPaintopBox::slotSetPaintop(const QString& paintOpId) { if(KisPaintOpRegistry::instance()->get(paintOpId) != 0) { KoID id(paintOpId, KisPaintOpRegistry::instance()->get(paintOpId)->name()); setCurrentPaintop(id); } } void KisPaintopBox::slotInputDeviceChanged(const KoInputDevice& inputDevice) { TabletToolMap::iterator toolData = m_tabletToolMap.find(inputDevice); if(toolData == m_tabletToolMap.end()) setCurrentPaintop(currentPaintop()); else setCurrentPaintop(toolData->paintOpID, toolData->preset); m_currTabletToolID = TabletToolID(inputDevice); } void KisPaintopBox::slotCurrentNodeChanged(KisNodeSP node) { for(TabletToolMap::iterator itr=m_tabletToolMap.begin(); itr!=m_tabletToolMap.end(); ++itr) { if(itr->preset && itr->preset->settings()) itr->preset->settings()->setNode(node); } } void KisPaintopBox::slotSaveActivePreset() { KisPaintOpPresetSP curPreset = m_resourceProvider->currentPreset(); if (!curPreset) return; m_view->canvasBase()->favoriteResourceManager()->setBlockUpdates(true); KisPaintOpPreset* newPreset = curPreset->clone(); KoResourceServer* rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); QString saveLocation = rServer->saveLocation(); QString name = m_presetsPopup->getPresetName(); QStringList tags; KisPaintOpPreset* resource = rServer->resourceByName(name); if (resource) { tags = rServer->assignedTagsList(resource); rServer->removeResource(resource); } newPreset->setImage(m_presetsPopup->cutOutOverlay()); newPreset->setFilename(saveLocation + name + newPreset->defaultFileExtension()); newPreset->setName(name); m_presetsPopup->changeSavePresetButtonText(true); rServer->addResource(newPreset); foreach(const QString& tag, tags) { rServer->addTag(newPreset, tag); } m_view->canvasBase()->favoriteResourceManager()->setBlockUpdates(false); } void KisPaintopBox::slotUpdatePreset() { // block updates of avoid some over updating of the option widget m_blockUpdate = true; m_optionWidget->writeConfiguration(const_cast(m_activePreset->settings().data())); setSliderValue("size", m_activePreset->settings()->paintOpSize().width()); if(m_activePreset->settings()->hasProperty("OpacityValue")) { qreal opacity = m_activePreset->settings()->getDouble("OpacityValue"); m_resourceProvider->setOpacity(opacity); setSliderValue("opacity", opacity); setWidgetState(ENABLE_OPACITY); } else { m_resourceProvider->setOpacity(1.0); setSliderValue("opacity", 1.0); setWidgetState(DISABLE_OPACITY); } if(m_activePreset->settings()->hasProperty("FlowValue")) { setSliderValue("flow", m_activePreset->settings()->getDouble("FlowValue")); setWidgetState(ENABLE_FLOW); } else { setSliderValue("flow", 1.0); setWidgetState(DISABLE_FLOW); } if(m_activePreset->settings()->hasProperty("CompositeOp")) { updateCompositeOp(m_activePreset->settings()->getString("CompositeOp")); setWidgetState(ENABLE_COMPOSITEOP); } else { updateCompositeOp(KoCompositeOpRegistry::instance().getDefaultCompositeOp().id()); setWidgetState(DISABLE_COMPOSITEOP); } m_blockUpdate = false; } void KisPaintopBox::slotSetupDefaultPreset() { KisPaintOpPresetSP preset = defaultPreset(m_activePreset->paintOp()); preset->settings()->setNode(m_activePreset->settings()->node()); preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setConfiguration(preset->settings()); m_optionWidget->writeConfiguration(const_cast(preset->settings().data())); } void KisPaintopBox::slotNodeChanged(const KisNodeSP node) { // Deconnect colorspace change of previous node if (m_previousNode && m_previousNode->paintDevice()) disconnect(m_previousNode->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); // Reconnect colorspace change of node if(node && node->paintDevice()) { connect(node->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); m_resourceProvider->setCurrentCompositeOp(m_currCompositeOpID); m_previousNode = node; slotColorSpaceChanged(node->colorSpace()); } for(TabletToolMap::iterator itr=m_tabletToolMap.begin(); itr!=m_tabletToolMap.end(); ++itr) { if(itr->preset && itr->preset->settings()) itr->preset->settings()->setNode(node); } } void KisPaintopBox::slotColorSpaceChanged(const KoColorSpace* colorSpace) { m_cmbCompositeOp->getModel()->validateCompositeOps(colorSpace); } void KisPaintopBox::slotToggleEraseMode(bool checked) { if(checked) updateCompositeOp(COMPOSITE_ERASE); else updateCompositeOp(m_prevCompositeOpID); } void KisPaintopBox::slotSetCompositeMode(int index) { if(m_activePreset->settings()->hasProperty("CompositeOp")) { KoID compositeOp; if(m_cmbCompositeOp->entryAt(compositeOp, index)) updateCompositeOp(compositeOp.id()); } } void KisPaintopBox::slotSaveToFavouriteBrushes() { if(!m_view->canvasBase()->favoriteResourceManager()) m_view->canvasBase()->createFavoriteResourceManager(this); else m_view->canvasBase()->favoriteResourceManager()->showPaletteManager(); } void KisPaintopBox::slotWatchPresetNameLineEdit(const QString& text) { KoResourceServer* rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); m_presetsPopup->changeSavePresetButtonText(rServer->resourceByName(text) != 0); } void KisPaintopBox::slotHorizontalMirrorChanged(bool value) { m_resourceProvider->setMirrorHorizontal(value); } void KisPaintopBox::slotVerticalMirrorChanged(bool value) { m_resourceProvider->setMirrorVertical(value); } void KisPaintopBox::sliderChanged(int n) { qreal opacity = m_sliderChooser[n]->getWidget("opacity")->value(); qreal flow = m_sliderChooser[n]->getWidget("flow")->value(); qreal size = m_sliderChooser[n]->getWidget("size")->value(); setSliderValue("opacity", opacity); setSliderValue("flow" , flow ); setSliderValue("size" , size ); if(m_presetsEnabled) { // IMPORTANT: set the PaintOp size before setting the other properties // it wont work the other way qreal sizeDiff = size - m_activePreset->settings()->paintOpSize().width(); m_activePreset->settings()->changePaintOpSize(sizeDiff, 0); if(m_activePreset->settings()->hasProperty("OpacityValue")) m_activePreset->settings()->setProperty("OpacityValue", opacity); if(m_activePreset->settings()->hasProperty("FlowValue")) m_activePreset->settings()->setProperty("FlowValue", flow); m_optionWidget->setConfiguration(m_activePreset->settings().data()); } else m_resourceProvider->setOpacity(opacity); } void KisPaintopBox::slotSlider1Changed() { sliderChanged(0); } void KisPaintopBox::slotSlider2Changed() { sliderChanged(1); } void KisPaintopBox::slotToolChanged(KoCanvasController* canvas, int toolId) { Q_UNUSED(canvas); Q_UNUSED(toolId); QString id = KoToolManager::instance()->activeToolId(); KisTool* tool = dynamic_cast(KoToolManager::instance()->toolById(m_view->canvasBase(), id)); if(tool) { int flags = tool->flags(); if(flags & KisTool::FLAG_USES_CUSTOM_COMPOSITEOP) { setWidgetState(ENABLE_COMPOSITEOP|ENABLE_OPACITY); } else { setWidgetState(DISABLE_COMPOSITEOP|DISABLE_OPACITY); } if(flags & KisTool::FLAG_USES_CUSTOM_PRESET) { setWidgetState(ENABLE_PRESETS|ENABLE_SIZE|ENABLE_FLOW); slotUpdatePreset(); m_presetsEnabled = true; } else { setWidgetState(DISABLE_PRESETS|DISABLE_SIZE|DISABLE_FLOW); m_presetsEnabled = false; } } else setWidgetState(DISABLE_ALL); } void KisPaintopBox::slotOpacityChanged(qreal opacity) { if (m_blockUpdate) { return; } m_blockUpdate = true; for (int i = 0; i < 2; ++i) { KisDoubleSliderSpinBox *opacitySlider = m_sliderChooser[i]->getWidget("opacity"); opacitySlider->blockSignals(true); opacitySlider->setValue(opacity); opacitySlider->blockSignals(false); } if(m_presetsEnabled) { if(m_activePreset->settings()->hasProperty("OpacityValue")) m_activePreset->settings()->setProperty("OpacityValue", opacity); m_optionWidget->setConfiguration(m_activePreset->settings().data()); } m_blockUpdate = false; } void KisPaintopBox::slotPreviousFavoritePreset() { if (!m_view->canvasBase()->favoriteResourceManager()) { m_view->canvasBase()->createFavoriteResourceManager(this); } KoFavoriteResourceManager *mgr = m_view->canvasBase()->favoriteResourceManager(); int i = 0; foreach (const QString &preset, mgr->favoritePresetList()) { if (m_activePreset->name() == preset) { if (i > 0) { mgr->slotChangeActivePaintop(i - 1); } else { mgr->slotChangeActivePaintop(mgr->numFavoritePresets() - 1); } return; } i++; } } void KisPaintopBox::slotNextFavoritePreset() { if (!m_view->canvasBase()->favoriteResourceManager()) { m_view->canvasBase()->createFavoriteResourceManager(this); } KoFavoriteResourceManager *mgr = m_view->canvasBase()->favoriteResourceManager(); int i = 0; foreach (const QString &preset, mgr->favoritePresetList()) { if (m_activePreset->name() == preset) { if (i < mgr->numFavoritePresets() - 1) { mgr->slotChangeActivePaintop(i + 1); } else { mgr->slotChangeActivePaintop(0); } return; } i++; } } void KisPaintopBox::slotSwitchToPreviousPreset() { if (m_previousPreset) { setCurrentPaintop(m_previousPreset->paintOp(), m_previousPreset); } } void KisPaintopBox::slotUnsetEraseMode() { if (m_currCompositeOpID == COMPOSITE_ERASE) { updateCompositeOp(m_prevCompositeOpID); } } + +void KisPaintopBox::slotToggleAlphaLockMode(bool checked) +{ + if (checked) { + m_alphaLockButton->actions()[0]->setIcon(koIcon("transparency-locked")); + } + else { + m_alphaLockButton->actions()[0]->setIcon(koIcon("transparency-unlocked")); + } + m_resourceProvider->setGlobalAlphaLock(checked); +} diff --git a/krita/ui/kis_paintop_box.h b/krita/ui/kis_paintop_box.h index 90e1ad2d00..618f2f5101 100644 --- a/krita/ui/kis_paintop_box.h +++ b/krita/ui/kis_paintop_box.h @@ -1,191 +1,194 @@ /* * kis_paintop_box.h - part of KImageShop/Krayon/Krita * * Copyright (c) 2004-2008 Boudewijn Rempt (boud@valdyas.org) * Copyright (C) 2011 Silvio Heinrich * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PAINTOP_BOX_H_ #define KIS_PAINTOP_BOX_H_ #include #include #include #include #include #include #include class QToolButton; class QPushButton; class QString; class QHBoxLayout; class KoColorSpace; class KoResourceSelector; class KoResource; class KoCompositeOp; class KoCanvasController; class KisView2; class KisCanvasResourceProvider; class KisPopupButton; class KisPaintOpPresetsPopup; class KisPaintOpPresetsChooserPopup; class KisPaintOpSettingsWidget; class KisPaintOpListWidget; class KisCompositeOpComboBox; class KisWidgetChooser; /** * This widget presents all paintops that a user can paint with. * Paintops represent real-world tools or the well-known Shoup * computer equivalents that do nothing but change color. * * XXX: When we have a lot of paintops, replace the listbox * with a table, and for every category a combobox. * * XXX: instead of text, use pretty pictures. */ class KisPaintopBox : public QWidget { Q_OBJECT enum { ENABLE_PRESETS = 0x0001, DISABLE_PRESETS = 0x0002, ENABLE_COMPOSITEOP = 0x0004, DISABLE_COMPOSITEOP = 0x0008, ENABLE_OPACITY = 0x0010, DISABLE_OPACITY = 0x0020, ENABLE_FLOW = 0x0040, DISABLE_FLOW = 0x0080, ENABLE_SIZE = 0x0100, DISABLE_SIZE = 0x0200, ENABLE_ALL = 0x5555, DISABLE_ALL = 0xAAAA }; public: KisPaintopBox(KisView2* view, QWidget* parent, const char* name); KisPaintOpPresetSP paintOpPresetSP(KoID * = 0); KoID currentPaintop(); void setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP preset=0); QPixmap paintopPixmap(const KoID& paintop); ~KisPaintopBox(); public slots: void slotColorSpaceChanged(const KoColorSpace* colorSpace); void slotInputDeviceChanged(const KoInputDevice & inputDevice); void slotCurrentNodeChanged(KisNodeSP node); void slotSaveActivePreset(); void slotUpdatePreset(); void slotSetupDefaultPreset(); void resourceSelected(KoResource* resource); private: KoID defaultPaintOp(); KisPaintOpPresetSP defaultPreset(const KoID& paintOp); KisPaintOpPresetSP activePreset(const KoID& paintOp); void updateCompositeOp(QString compositeOpID); void updatePaintops(const KoColorSpace* colorSpace); void setWidgetState(int flags); void setSliderValue(const QString& sliderID, qreal value); void sliderChanged(int n); private slots: void slotNodeChanged(const KisNodeSP node); void slotToggleEraseMode(bool checked); void slotSetCompositeMode(int index); void slotSetPaintop(const QString& paintOpId); void slotSaveToFavouriteBrushes(); void slotWatchPresetNameLineEdit(const QString& text); void slotHorizontalMirrorChanged(bool value); void slotVerticalMirrorChanged(bool value); void slotSlider1Changed(); void slotSlider2Changed(); void slotToolChanged(KoCanvasController* canvas, int toolId); void slotOpacityChanged(qreal); void slotPreviousFavoritePreset(); void slotNextFavoritePreset(); void slotSwitchToPreviousPreset(); void slotUnsetEraseMode(); + void slotToggleAlphaLockMode(bool); + private: KisCanvasResourceProvider* m_resourceProvider; QHBoxLayout* m_layout; QWidget* m_paintopWidget; KisPaintOpSettingsWidget* m_optionWidget; KisPopupButton* m_settingsWidget; KisPopupButton* m_presetWidget; KisPopupButton* m_brushChooser; KisCompositeOpComboBox* m_cmbCompositeOp; QToolButton* m_eraseModeButton; + QToolButton* m_alphaLockButton; KisPaintOpPresetsPopup* m_presetsPopup; KisPaintOpPresetsChooserPopup* m_presetsChooserPopup; KisView2* m_view; QPushButton* m_paletteButton; KisPopupButton* m_workspaceWidget; KisWidgetChooser* m_sliderChooser[2]; QMap m_paintopOptionWidgets; KisPaintOpPresetSP m_activePreset; KisPaintOpPresetSP m_previousPreset; QString m_prevCompositeOpID; QString m_currCompositeOpID; KisNodeSP m_previousNode; struct TabletToolID { TabletToolID(const KoInputDevice& dev) { uniqueID = dev.uniqueTabletId(); pointer = (dev.pointer() == QTabletEvent::UnknownPointer) ? QTabletEvent::Cursor : dev.pointer(); } bool operator == (const TabletToolID& id) const { return pointer == id.pointer && uniqueID == id.uniqueID; } bool operator < (const TabletToolID& id) const { if(uniqueID == id.uniqueID) return pointer < id.pointer; return uniqueID < id.uniqueID; } QTabletEvent::PointerType pointer; qint64 uniqueID; }; struct TabletToolData { KoID paintOpID; KisPaintOpPresetSP preset; }; typedef QMap TabletToolMap; typedef QMap PaintOpPresetMap; TabletToolMap m_tabletToolMap; PaintOpPresetMap m_paintOpPresetMap; TabletToolID m_currTabletToolID; bool m_presetsEnabled; bool m_blockUpdate; }; #endif //KIS_PAINTOP_BOX_H_ diff --git a/krita/ui/tool/kis_resources_snapshot.cpp b/krita/ui/tool/kis_resources_snapshot.cpp index c7825c6c31..d7e65e04ab 100644 --- a/krita/ui/tool/kis_resources_snapshot.cpp +++ b/krita/ui/tool/kis_resources_snapshot.cpp @@ -1,234 +1,263 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_resources_snapshot.h" #include #include #include "kis_paintop_preset.h" #include "kis_paintop_settings.h" #include "kis_pattern.h" #include "kis_canvas_resource_provider.h" #include "filter/kis_filter_configuration.h" #include "kis_image.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "recorder/kis_recorded_paint_action.h" #include "kis_default_bounds.h" struct KisResourcesSnapshot::Private { - Private() : currentPattern(0), currentGradient(0), - currentGenerator(0), compositeOp(0) + Private() + : currentPattern(0) + , currentGradient(0) + , currentGenerator(0) + , compositeOp(0) { } KisImageWSP image; KisDefaultBoundsBaseSP bounds; KisPostExecutionUndoAdapter *undoAdapter; KoColor currentFgColor; KoColor currentBgColor; KisPattern *currentPattern; KoAbstractGradient *currentGradient; KisPaintOpPresetSP currentPaintOpPreset; KisNodeSP currentNode; qreal currentExposure; KisFilterConfiguration *currentGenerator; QPointF axisCenter; bool mirrorMaskHorizontal; bool mirrorMaskVertical; quint8 opacity; QString compositeOpId; const KoCompositeOp *compositeOp; KisPainter::StrokeStyle strokeStyle; KisPainter::FillStyle fillStyle; + + bool globalAlphaLock; }; KisResourcesSnapshot::KisResourcesSnapshot(KisImageWSP image, KisPostExecutionUndoAdapter *undoAdapter, KoCanvasResourceManager *resourceManager, KisDefaultBoundsBaseSP bounds) : m_d(new Private()) { m_d->image = image; if (!bounds) { bounds = new KisDefaultBounds(m_d->image); } m_d->bounds = bounds; m_d->undoAdapter = undoAdapter; + m_d->currentFgColor = resourceManager->resource(KoCanvasResourceManager::ForegroundColor).value(); m_d->currentBgColor = resourceManager->resource(KoCanvasResourceManager::BackgroundColor).value(); m_d->currentPattern = static_cast(resourceManager->resource(KisCanvasResourceProvider::CurrentPattern).value()); m_d->currentGradient = static_cast(resourceManager->resource(KisCanvasResourceProvider::CurrentGradient).value()); m_d->currentPaintOpPreset = resourceManager->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); m_d->currentExposure = resourceManager->resource(KisCanvasResourceProvider::HdrExposure).toDouble(); m_d->currentGenerator = static_cast(resourceManager->resource(KisCanvasResourceProvider::CurrentGeneratorConfiguration).value()); m_d->axisCenter = resourceManager->resource(KisCanvasResourceProvider::MirrorAxisCenter).toPointF(); if (m_d->axisCenter.isNull()){ QRect bounds = m_d->bounds->bounds(); m_d->axisCenter = QPointF(0.5 * bounds.width(), 0.5 * bounds.height()); } m_d->mirrorMaskHorizontal = resourceManager->resource(KisCanvasResourceProvider::MirrorHorizontal).toBool(); m_d->mirrorMaskVertical = resourceManager->resource(KisCanvasResourceProvider::MirrorVertical).toBool(); qreal normOpacity = resourceManager->resource(KisCanvasResourceProvider::Opacity).toDouble(); m_d->opacity = quint8(normOpacity * OPACITY_OPAQUE_U8); m_d->compositeOpId = resourceManager->resource(KisCanvasResourceProvider::CurrentCompositeOp).toString(); setCurrentNode(resourceManager->resource(KisCanvasResourceProvider::CurrentKritaNode).value()); /** * Fill and Stroke styles are not a part of the resource manager * so the tools should set them manually * TODO: port stroke and fill styles to be a part * of the resource manager */ m_d->strokeStyle = KisPainter::StrokeStyleBrush; m_d->fillStyle = KisPainter::FillStyleNone; + + m_d->globalAlphaLock = resourceManager->resource(KisCanvasResourceProvider::GlobalAlphaLock).toBool(); } KisResourcesSnapshot::~KisResourcesSnapshot() { delete m_d; } void KisResourcesSnapshot::setupPainter(KisPainter* painter) { painter->setBounds(m_d->bounds->bounds()); painter->setPaintColor(m_d->currentFgColor); painter->setBackgroundColor(m_d->currentBgColor); painter->setGenerator(m_d->currentGenerator); painter->setPattern(m_d->currentPattern); painter->setGradient(m_d->currentGradient); - KisPaintLayer *paintLayer; - if ((paintLayer = dynamic_cast(m_d->currentNode.data()))) { - painter->setChannelFlags(paintLayer->channelLockFlags()); + QBitArray lockflags = channelLockFlags(); + if (lockflags.size() > 0) { + painter->setChannelFlags(lockflags); } painter->setOpacity(m_d->opacity); painter->setCompositeOp(m_d->compositeOp); painter->setMirrorInformation(m_d->axisCenter, m_d->mirrorMaskHorizontal, m_d->mirrorMaskVertical); painter->setStrokeStyle(m_d->strokeStyle); painter->setFillStyle(m_d->fillStyle); /** * The paintOp should be initialized the last, because it may * ask the painter for some options while initialization */ painter->setPaintOpPreset(m_d->currentPaintOpPreset, m_d->image); } void KisResourcesSnapshot::setupPaintAction(KisRecordedPaintAction *action) { action->setPaintOpPreset(m_d->currentPaintOpPreset); action->setPaintIncremental(!needsIndirectPainting()); action->setPaintColor(m_d->currentFgColor); action->setBackgroundColor(m_d->currentBgColor); action->setGenerator(m_d->currentGenerator); action->setGradient(m_d->currentGradient); action->setPattern(m_d->currentPattern); action->setOpacity(m_d->opacity / qreal(OPACITY_OPAQUE_U8)); action->setCompositeOp(m_d->compositeOp->id()); action->setStrokeStyle(m_d->strokeStyle); action->setFillStyle(m_d->fillStyle); } KisPostExecutionUndoAdapter* KisResourcesSnapshot::postExecutionUndoAdapter() const { return m_d->undoAdapter; } void KisResourcesSnapshot::setCurrentNode(KisNodeSP node) { m_d->currentNode = node; KisPaintDeviceSP device; if(m_d->currentNode && (device = m_d->currentNode->paintDevice())) { m_d->compositeOp = device->colorSpace()->compositeOp(m_d->compositeOpId); if(!m_d->compositeOp) { m_d->compositeOp = device->colorSpace()->compositeOp(COMPOSITE_OVER); } } } void KisResourcesSnapshot::setStrokeStyle(KisPainter::StrokeStyle strokeStyle) { m_d->strokeStyle = strokeStyle; } void KisResourcesSnapshot::setFillStyle(KisPainter::FillStyle fillStyle) { m_d->fillStyle = fillStyle; } KisNodeSP KisResourcesSnapshot::currentNode() const { return m_d->currentNode; } KisImageWSP KisResourcesSnapshot::image() const { return m_d->image; } bool KisResourcesSnapshot::needsIndirectPainting() const { return !m_d->currentPaintOpPreset->settings()->paintIncremental(); } bool KisResourcesSnapshot::needsAirbrushing() const { return m_d->currentPaintOpPreset->settings()->isAirbrushing(); } int KisResourcesSnapshot::airbrushingRate() const { return m_d->currentPaintOpPreset->settings()->rate(); } quint8 KisResourcesSnapshot::opacity() const { return m_d->opacity; } const KoCompositeOp* KisResourcesSnapshot::compositeOp() const { return m_d->compositeOp; } KisPattern* KisResourcesSnapshot::currentPattern() const { return m_d->currentPattern; } KoColor KisResourcesSnapshot::currentFgColor() const { return m_d->currentFgColor; } KoColor KisResourcesSnapshot::currentBgColor() const { return m_d->currentBgColor; } + +QBitArray KisResourcesSnapshot::channelLockFlags() const +{ + QBitArray channelFlags; + KisPaintLayer *paintLayer; + if ((paintLayer = dynamic_cast(m_d->currentNode.data()))) { + + channelFlags = paintLayer->channelLockFlags(); + if (channelFlags.isEmpty()) { + channelFlags = paintLayer->colorSpace()->channelFlags(true, true); + } + if (m_d->globalAlphaLock) { + channelFlags &= paintLayer->colorSpace()->channelFlags(true, false); + } + else { + channelFlags |= paintLayer->colorSpace()->channelFlags(false, true); + } + } + return channelFlags; +} + diff --git a/krita/ui/tool/kis_resources_snapshot.h b/krita/ui/tool/kis_resources_snapshot.h index 31752aefdc..600d404936 100644 --- a/krita/ui/tool/kis_resources_snapshot.h +++ b/krita/ui/tool/kis_resources_snapshot.h @@ -1,73 +1,76 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_RESOURCES_SNAPSHOT_H #define __KIS_RESOURCES_SNAPSHOT_H #include "kis_shared.h" #include "kis_shared_ptr.h" #include "kis_types.h" #include "krita_export.h" #include "kis_painter.h" #include "kis_default_bounds.h" class KoCanvasResourceManager; class KoCompositeOp; class KisPainter; class KisPostExecutionUndoAdapter; class KisRecordedPaintAction; class KisPattern; class KRITAUI_EXPORT KisResourcesSnapshot : public KisShared { public: KisResourcesSnapshot(KisImageWSP image, KisPostExecutionUndoAdapter *undoAdapter, KoCanvasResourceManager *resourceManager, KisDefaultBoundsBaseSP bounds = 0); ~KisResourcesSnapshot(); void setupPainter(KisPainter *painter); void KDE_DEPRECATED setupPaintAction(KisRecordedPaintAction *action); KisPostExecutionUndoAdapter* postExecutionUndoAdapter() const; void setCurrentNode(KisNodeSP node); void setStrokeStyle(KisPainter::StrokeStyle strokeStyle); void setFillStyle(KisPainter::FillStyle fillStyle); KisNodeSP currentNode() const; KisImageWSP image() const; bool needsIndirectPainting() const; bool needsAirbrushing() const; int airbrushingRate() const; quint8 opacity() const; const KoCompositeOp* compositeOp() const; KisPattern* currentPattern() const; KoColor currentFgColor() const; KoColor currentBgColor() const; + /// @return the channel lock flags of the current node with the global override applied + QBitArray channelLockFlags() const; + private: struct Private; Private * const m_d; }; typedef KisSharedPtr KisResourcesSnapshotSP; #endif /* __KIS_RESOURCES_SNAPSHOT_H */ diff --git a/krita/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp b/krita/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp index 95af0073ab..77e7ef2e40 100644 --- a/krita/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp +++ b/krita/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp @@ -1,190 +1,190 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_painter_based_stroke_strategy.h" #include #include #include "kis_painter.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "kis_selection.h" #include "kis_transaction.h" #include "kis_image.h" #include "kis_distance_information.h" KisPainterBasedStrokeStrategy::PainterInfo::PainterInfo(KisPainter *_painter, KisDistanceInformation *_dragDistance) : painter(_painter), dragDistance(_dragDistance) { } KisPainterBasedStrokeStrategy::PainterInfo::~PainterInfo() { delete(painter); delete(dragDistance); } KisPainterBasedStrokeStrategy::KisPainterBasedStrokeStrategy(const QString &id, const QString &name, KisResourcesSnapshotSP resources, QVector painterInfos) : KisSimpleStrokeStrategy(id, name), m_resources(resources), m_painterInfos(painterInfos), m_transaction(0) { init(); } KisPainterBasedStrokeStrategy::KisPainterBasedStrokeStrategy(const QString &id, const QString &name, KisResourcesSnapshotSP resources, PainterInfo *painterInfo) : KisSimpleStrokeStrategy(id, name), m_resources(resources), m_painterInfos(QVector() << painterInfo), m_transaction(0) { init(); } void KisPainterBasedStrokeStrategy::init() { enableJob(KisSimpleStrokeStrategy::JOB_INIT); enableJob(KisSimpleStrokeStrategy::JOB_FINISH); enableJob(KisSimpleStrokeStrategy::JOB_CANCEL); } KisPaintDeviceSP KisPainterBasedStrokeStrategy::targetDevice() { return m_targetDevice; } KisSelectionSP KisPainterBasedStrokeStrategy::activeSelection() { return m_activeSelection; } void KisPainterBasedStrokeStrategy::initPainters(KisPaintDeviceSP targetDevice, KisSelectionSP selection, bool hasIndirectPainting) { foreach(PainterInfo *info, m_painterInfos) { KisPainter *painter = info->painter; painter->begin(targetDevice, selection); m_resources->setupPainter(painter); if(hasIndirectPainting) { painter->setCompositeOp(targetDevice->colorSpace()->compositeOp(COMPOSITE_ALPHA_DARKEN)); painter->setOpacity(OPACITY_OPAQUE_U8); painter->setChannelFlags(QBitArray()); } } } void KisPainterBasedStrokeStrategy::deletePainters() { foreach(PainterInfo *info, m_painterInfos) { delete info; } m_painterInfos.clear(); } void KisPainterBasedStrokeStrategy::initStrokeCallback() { KisNodeSP node = m_resources->currentNode(); KisPaintDeviceSP paintDevice = node->paintDevice(); KisPaintDeviceSP targetDevice = paintDevice; bool hasIndirectPainting = needsIndirectPainting(); if (hasIndirectPainting) { KisIndirectPaintingSupport *indirect = dynamic_cast(node.data()); if (indirect) { targetDevice = paintDevice->createCompositionSourceDevice(); targetDevice->setParentNode(node); indirect->setTemporaryTarget(targetDevice); indirect->setTemporaryCompositeOp(m_resources->compositeOp()); indirect->setTemporaryOpacity(m_resources->opacity()); - KisPaintLayer *paintLayer = dynamic_cast(node.data()); - if(paintLayer) { - indirect->setTemporaryChannelFlags(paintLayer->channelLockFlags()); + QBitArray channelLockFlags = m_resources->channelLockFlags(); + if (channelLockFlags.size() > 0) { + indirect->setTemporaryChannelFlags(channelLockFlags); } } else { hasIndirectPainting = false; } } KisSelectionSP selection; KisLayerSP layer = dynamic_cast(node.data()); if(layer) { selection = layer->selection(); } else { selection = m_resources->image()->globalSelection(); } m_transaction = new KisTransaction(name(), targetDevice); initPainters(targetDevice, selection, hasIndirectPainting); m_targetDevice = targetDevice; m_activeSelection = selection; } void KisPainterBasedStrokeStrategy::finishStrokeCallback() { KisNodeSP node = m_resources->currentNode(); KisLayerSP layer = dynamic_cast(node.data()); KisIndirectPaintingSupport *indirect = dynamic_cast(node.data()); if(layer && indirect && indirect->hasTemporaryTarget()) { QString transactionText = m_transaction->text(); m_transaction->end(); indirect->mergeToLayer(layer, m_resources->postExecutionUndoAdapter(), transactionText); } else { m_transaction->commit(m_resources->postExecutionUndoAdapter()); } delete m_transaction; deletePainters(); } void KisPainterBasedStrokeStrategy::cancelStrokeCallback() { m_transaction->revert(); delete m_transaction; deletePainters(); KisNodeSP node = m_resources->currentNode(); KisIndirectPaintingSupport *indirect = dynamic_cast(node.data()); if(indirect && indirect->hasTemporaryTarget()) { indirect->setTemporaryTarget(0); } }