File indexing completed on 2024-05-12 16:01:38
0001 /* 0002 * kis_paintop_box.cc - part of KImageShop/Krayon/Krita 0003 * 0004 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt (boud@valdyas.org) 0005 * SPDX-FileCopyrightText: 2009-2011 Sven Langkamp (sven.langkamp@gmail.com) 0006 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com> 0007 * SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de> 0008 * SPDX-FileCopyrightText: 2011 Srikanth Tiyyagura <srikanth.tulasiram@gmail.com> 0009 * SPDX-FileCopyrightText: 2014 Mohit Goyal <mohit.bits2011@gmail.com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 */ 0013 0014 #include "kis_paintop_box.h" 0015 0016 #include <QHBoxLayout> 0017 #include <QLabel> 0018 #include <QToolButton> 0019 #include <QPixmap> 0020 #include <QWidgetAction> 0021 #include <QApplication> 0022 #include <QMenu> 0023 #include <QTime> 0024 0025 #include <kis_debug.h> 0026 #include <kis_types.h> 0027 0028 #include <kactioncollection.h> 0029 #include <kacceleratormanager.h> 0030 #include <QKeySequence> 0031 0032 #include <kis_icon.h> 0033 #include <KoColorSpace.h> 0034 #include <KoCompositeOpRegistry.h> 0035 #include <KoToolManager.h> 0036 #include <KoColorSpaceRegistry.h> 0037 0038 #include <KoResource.h> 0039 #include <KisDirtyStateSaver.h> 0040 0041 #include <kis_paint_device.h> 0042 #include <brushengine/kis_paintop_registry.h> 0043 #include <brushengine/kis_paintop_preset.h> 0044 #include <brushengine/kis_paintop_settings.h> 0045 #include <brushengine/KisPaintOpPresetUpdateProxy.h> 0046 #include <kis_config_widget.h> 0047 #include <kis_image.h> 0048 #include <kis_node.h> 0049 #include <brushengine/kis_paintop_config_widget.h> 0050 #include <kis_action.h> 0051 0052 #include "kis_canvas2.h" 0053 #include "kis_node_manager.h" 0054 #include "KisViewManager.h" 0055 #include "kis_canvas_resource_provider.h" 0056 #include "KisResourceServerProvider.h" 0057 #include "kis_favorite_resource_manager.h" 0058 #include "kis_config.h" 0059 #include "kis_image_config.h" 0060 0061 #include "KisPopupButton.h" 0062 #include "widgets/kis_iconwidget.h" 0063 #include "widgets/kis_tool_options_popup.h" 0064 #include "widgets/kis_paintop_presets_editor.h" 0065 #include "widgets/kis_paintop_presets_chooser_popup.h" 0066 #include "widgets/kis_workspace_chooser.h" 0067 #include "widgets/kis_paintop_list_widget.h" 0068 #include "kis_slider_spin_box.h" 0069 #include "widgets/kis_multipliers_double_slider_spinbox.h" 0070 #include "widgets/kis_cmb_composite.h" 0071 #include "widgets/kis_widget_chooser.h" 0072 #include "tool/kis_tool.h" 0073 #include "kis_signals_blocker.h" 0074 #include "kis_action_manager.h" 0075 #include "KisHighlightedToolButton.h" 0076 #include <KisGlobalResourcesInterface.h> 0077 #include "KisResourceLoader.h" 0078 #include "KisResourceLoaderRegistry.h" 0079 #include "kis_acyclic_signal_connector.h" 0080 #include "KisMainWindow.h" 0081 0082 0083 KisPaintopBox::KisPaintopBox(KisViewManager *viewManager, QWidget *parent, const char *name) 0084 : QWidget(parent) 0085 , m_resourceProvider(viewManager->canvasResourceProvider()) 0086 , m_viewManager(viewManager) 0087 , m_optionWidgetUpdateCompressor(100, KisSignalCompressor::FIRST_ACTIVE) 0088 { 0089 Q_ASSERT(viewManager != 0); 0090 0091 setObjectName(name); 0092 KisConfig cfg(true); 0093 m_dirtyPresetsEnabled = cfg.useDirtyPresets(); 0094 m_eraserBrushSizeEnabled = cfg.useEraserBrushSize(); 0095 m_eraserBrushOpacityEnabled = cfg.useEraserBrushOpacity(); 0096 0097 KAcceleratorManager::setNoAccel(this); 0098 0099 setWindowTitle(i18n("Painter's Toolchest")); 0100 0101 m_favoriteResourceManager = new KisFavoriteResourceManager(this); 0102 0103 KConfigGroup grp = KSharedConfig::openConfig()->group("krita").group("Toolbar BrushesAndStuff"); 0104 int iconsize = grp.readEntry("IconSize", 22); 0105 // NOTE: buttonsize should be the same value as the one used in ktoolbar for all QToolButton 0106 int buttonsize = grp.readEntry("ButtonSize", 32); 0107 0108 if (!cfg.toolOptionsInDocker()) { 0109 m_toolOptionsPopupButton = new KisPopupButton(this); 0110 m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("view-choose")); 0111 m_toolOptionsPopupButton->setToolTip(i18n("Tool Settings")); 0112 m_toolOptionsPopupButton->setFixedSize(buttonsize, buttonsize); 0113 m_toolOptionsPopupButton->setIconSize(QSize(iconsize, iconsize)); 0114 m_toolOptionsPopupButton->setAutoRaise(true); 0115 } 0116 0117 m_brushEditorPopupButton = new KisIconWidget(this); 0118 m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02")); 0119 m_brushEditorPopupButton->setToolTip(i18n("Edit brush settings")); 0120 m_brushEditorPopupButton->setFixedSize(buttonsize, buttonsize); 0121 m_brushEditorPopupButton->setIconSize(QSize(iconsize, iconsize)); 0122 m_brushEditorPopupButton->setAutoRaise(true); 0123 0124 m_presetSelectorPopupButton = new KisIconWidget(this); 0125 m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01")); 0126 m_presetSelectorPopupButton->setToolTip(i18n("Choose brush preset")); 0127 m_presetSelectorPopupButton->setFixedSize(buttonsize, buttonsize); 0128 m_presetSelectorPopupButton->setIconSize(QSize(iconsize, iconsize)); 0129 m_presetSelectorPopupButton->setAutoRaise(true); 0130 m_presetSelectorPopupButton->setArrowVisible(false); 0131 0132 m_eraseModeButton = new KisHighlightedToolButton(this); 0133 m_eraseModeButton->setFixedSize(buttonsize, buttonsize); 0134 m_eraseModeButton->setIconSize(QSize(iconsize, iconsize)); 0135 m_eraseModeButton->setCheckable(true); 0136 m_eraseModeButton->setAutoRaise(true); 0137 0138 0139 m_eraseAction = m_viewManager->actionManager()->createAction("erase_action"); 0140 m_eraseModeButton->setDefaultAction(m_eraseAction); 0141 0142 m_reloadButton = new QToolButton(this); 0143 m_reloadButton->setFixedSize(buttonsize, buttonsize); 0144 m_reloadButton->setIconSize(QSize(iconsize, iconsize)); 0145 m_reloadButton->setAutoRaise(true); // make button flat 0146 0147 0148 m_reloadAction = m_viewManager->actionManager()->createAction("reload_preset_action"); 0149 m_reloadButton->setDefaultAction(m_reloadAction); 0150 0151 m_alphaLockButton = new KisHighlightedToolButton(this); 0152 m_alphaLockButton->setFixedSize(buttonsize, buttonsize); 0153 m_alphaLockButton->setIconSize(QSize(iconsize, iconsize)); 0154 m_alphaLockButton->setCheckable(true); 0155 m_alphaLockButton->setAutoRaise(true); 0156 0157 KisAction* alphaLockAction = m_viewManager->actionManager()->createAction("preserve_alpha"); 0158 m_alphaLockButton->setDefaultAction(alphaLockAction); 0159 0160 // horizontal and vertical mirror toolbar buttons 0161 0162 // mirror tool options for the X Mirror 0163 toolbarMenuXMirror = new QMenu(); 0164 0165 hideCanvasDecorationsX = m_viewManager->actionManager()->createAction("mirrorX-hideDecorations"); 0166 toolbarMenuXMirror->addAction(hideCanvasDecorationsX); 0167 0168 lockActionX = m_viewManager->actionManager()->createAction("mirrorX-lock"); 0169 toolbarMenuXMirror->addAction(lockActionX); 0170 0171 moveToCenterActionX = m_viewManager->actionManager()->createAction("mirrorX-moveToCenter"); 0172 toolbarMenuXMirror->addAction(moveToCenterActionX); 0173 0174 0175 // mirror tool options for the Y Mirror 0176 toolbarMenuYMirror = new QMenu(); 0177 0178 hideCanvasDecorationsY = m_viewManager->actionManager()->createAction("mirrorY-hideDecorations"); 0179 toolbarMenuYMirror->addAction(hideCanvasDecorationsY); 0180 0181 0182 lockActionY = m_viewManager->actionManager()->createAction("mirrorY-lock"); 0183 toolbarMenuYMirror->addAction(lockActionY); 0184 0185 moveToCenterActionY = m_viewManager->actionManager()->createAction("mirrorY-moveToCenter"); 0186 toolbarMenuYMirror->addAction(moveToCenterActionY); 0187 0188 // create horizontal and vertical mirror buttons 0189 0190 m_hMirrorButton = new KisHighlightedToolButton(this); 0191 int menuPadding = 20; 0192 m_hMirrorButton->setFixedSize(buttonsize + menuPadding, buttonsize); 0193 m_hMirrorButton->setIconSize(QSize(iconsize, iconsize)); 0194 m_hMirrorButton->setCheckable(true); 0195 m_hMirrorAction = m_viewManager->actionManager()->createAction("hmirror_action"); 0196 m_hMirrorButton->setDefaultAction(m_hMirrorAction); 0197 m_hMirrorButton->setMenu(toolbarMenuXMirror); 0198 m_hMirrorButton->setPopupMode(QToolButton::MenuButtonPopup); 0199 m_hMirrorButton->setAutoRaise(true); 0200 0201 m_vMirrorButton = new KisHighlightedToolButton(this); 0202 m_vMirrorButton->setFixedSize(buttonsize + menuPadding, buttonsize); 0203 m_vMirrorButton->setIconSize(QSize(iconsize, iconsize)); 0204 m_vMirrorButton->setCheckable(true); 0205 m_vMirrorAction = m_viewManager->actionManager()->createAction("vmirror_action"); 0206 m_vMirrorButton->setDefaultAction(m_vMirrorAction); 0207 m_vMirrorButton->setMenu(toolbarMenuYMirror); 0208 m_vMirrorButton->setPopupMode(QToolButton::MenuButtonPopup); 0209 m_vMirrorButton->setAutoRaise(true); 0210 0211 QAction *wrapAroundAction = m_viewManager->actionManager()->createAction("wrap_around_mode"); 0212 0213 m_wrapAroundButton = new KisHighlightedToolButton(this); 0214 m_wrapAroundButton->setFixedSize(buttonsize, buttonsize); 0215 m_wrapAroundButton->setIconSize(QSize(iconsize, iconsize)); 0216 m_wrapAroundButton->setDefaultAction(wrapAroundAction); 0217 m_wrapAroundButton->setCheckable(true); 0218 m_wrapAroundButton->setAutoRaise(true); 0219 0220 // add connections for horizontal and mirrror buttons 0221 connect(lockActionX, SIGNAL(toggled(bool)), this, SLOT(slotLockXMirrorToggle(bool))); 0222 connect(lockActionY, SIGNAL(toggled(bool)), this, SLOT(slotLockYMirrorToggle(bool))); 0223 0224 connect(moveToCenterActionX, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorX())); 0225 connect(moveToCenterActionY, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorY())); 0226 0227 connect(hideCanvasDecorationsX, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorX(bool))); 0228 connect(hideCanvasDecorationsY, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorY(bool))); 0229 0230 const bool sliderLabels = cfg.sliderLabels(); 0231 int sliderWidth; 0232 0233 if (sliderLabels) { 0234 sliderWidth = 150 * logicalDpiX() / 96; 0235 } 0236 else { 0237 sliderWidth = 120 * logicalDpiX() / 96; 0238 } 0239 0240 for (int i = 0; i < 4; ++i) { 0241 m_sliderChooser[i] = new KisWidgetChooser(i + 1); 0242 0243 KisDoubleSliderSpinBox* slOpacity; 0244 KisDoubleSliderSpinBox* slFlow; 0245 KisDoubleSliderSpinBox* slSize; 0246 KisMultipliersDoubleSliderSpinBox* slPatternSize; 0247 if (sliderLabels) { 0248 slOpacity = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("opacity"); 0249 slFlow = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("flow"); 0250 slSize = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("size"); 0251 slPatternSize = m_sliderChooser[i]->addWidget<KisMultipliersDoubleSliderSpinBox>("patternsize"); 0252 slOpacity->setPrefix(QString("%1 ").arg(i18n("Opacity:"))); 0253 slFlow->setPrefix(QString("%1 ").arg(i18n("Flow:"))); 0254 slSize->setPrefix(QString("%1 ").arg(i18n("Size:"))); 0255 slPatternSize->setPrefix(QString("%1 ").arg(i18n("Pattern Scale:"))); 0256 } 0257 else { 0258 slOpacity = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("opacity", i18n("Opacity:")); 0259 slFlow = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("flow", i18n("Flow:")); 0260 slSize = m_sliderChooser[i]->addWidget<KisDoubleSliderSpinBox>("size", i18n("Size:")); 0261 slPatternSize = m_sliderChooser[i]->addWidget<KisMultipliersDoubleSliderSpinBox>("patternsize", i18n("Pattern Scale:")); 0262 } 0263 0264 slOpacity->setRange(0, 100, 0); 0265 slOpacity->setValue(100); 0266 slOpacity->setSingleStep(5); 0267 slOpacity->setSuffix(i18n("%")); 0268 slOpacity->setMinimumWidth(qMax(sliderWidth, slOpacity->sizeHint().width())); 0269 slOpacity->setFixedHeight(buttonsize); 0270 slOpacity->setBlockUpdateSignalOnDrag(true); 0271 0272 slFlow->setRange(0, 100, 0); 0273 slFlow->setValue(100); 0274 slFlow->setSingleStep(5); 0275 slFlow->setSuffix(i18n("%")); 0276 slFlow->setMinimumWidth(qMax(sliderWidth, slFlow->sizeHint().width())); 0277 slFlow->setFixedHeight(buttonsize); 0278 slFlow->setBlockUpdateSignalOnDrag(true); 0279 0280 slSize->setRange(0.01, KisImageConfig(true).maxBrushSize(), 2); 0281 slSize->setValue(100); 0282 0283 slSize->setSingleStep(1); 0284 slSize->setExponentRatio(3.0); 0285 slSize->setSuffix(i18n(" px")); 0286 slSize->setMinimumWidth(qMax(sliderWidth, slSize->sizeHint().width())); 0287 slSize->setFixedHeight(buttonsize); 0288 slSize->setBlockUpdateSignalOnDrag(true); 0289 0290 slPatternSize->setRange(0.0, 2.0, 2); 0291 slPatternSize->setValue(1.0); 0292 slPatternSize->addMultiplier(0.1); 0293 slPatternSize->addMultiplier(2); 0294 slPatternSize->addMultiplier(10); 0295 0296 slPatternSize->setSingleStep(0.01); 0297 slPatternSize->setSuffix(i18n("x")); 0298 slPatternSize->setMinimumWidth(qMax(sliderWidth, slPatternSize->sizeHint().width())); 0299 slPatternSize->setFixedHeight(buttonsize); 0300 slPatternSize->setBlockUpdateSignalOnDrag(true); 0301 0302 m_sliderChooser[i]->setMinimumWidth(qMax(sliderWidth, slPatternSize->sizeHint().width())); 0303 0304 m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1)); 0305 } 0306 0307 m_cmbCompositeOp = new KisCompositeOpComboBox(); 0308 m_cmbCompositeOp->setFixedHeight(buttonsize); 0309 m_cmbCompositeOp->connectBlendmodeActions(m_viewManager->actionManager()); 0310 0311 KisWorkspaceChooser *workspacePopup = new KisWorkspaceChooser(viewManager); 0312 m_workspaceWidget = new KisPopupButton(this); 0313 m_workspaceWidget->setIcon(KisIconUtils::loadIcon("workspace-chooser")); 0314 m_workspaceWidget->setToolTip(i18n("Choose workspace")); 0315 m_workspaceWidget->setFixedSize(buttonsize, buttonsize); 0316 m_workspaceWidget->setIconSize(QSize(iconsize, iconsize)); 0317 m_workspaceWidget->setPopupWidget(workspacePopup); 0318 m_workspaceWidget->setAutoRaise(true); 0319 m_workspaceWidget->setArrowVisible(false); 0320 0321 m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup(); 0322 m_presetsChooserPopup->setMinimumHeight(550); 0323 m_presetsChooserPopup->setMinimumWidth(450); 0324 m_presetSelectorPopupButton->setPopupWidget(m_presetsChooserPopup); 0325 0326 QHBoxLayout* baseLayout = new QHBoxLayout(this); 0327 m_paintopWidget = new QWidget(this); 0328 baseLayout->addWidget(m_paintopWidget); 0329 baseLayout->setSpacing(4); 0330 baseLayout->setContentsMargins(0, 0, 0, 0); 0331 0332 m_layout = new QHBoxLayout(m_paintopWidget); 0333 if (!cfg.toolOptionsInDocker()) { 0334 m_layout->addWidget(m_toolOptionsPopupButton); 0335 } 0336 m_layout->addWidget(m_brushEditorPopupButton); 0337 m_layout->addWidget(m_presetSelectorPopupButton); 0338 m_layout->setSpacing(4); 0339 m_layout->setContentsMargins(0, 0, 0, 0); 0340 0341 QWidget* compositeActions = new QWidget(this); 0342 QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions); 0343 compositeLayout->addWidget(m_cmbCompositeOp); 0344 compositeLayout->addWidget(m_eraseModeButton); 0345 compositeLayout->addWidget(m_alphaLockButton); 0346 0347 compositeLayout->setSpacing(4); 0348 compositeLayout->setContentsMargins(0, 0, 0, 0); 0349 0350 compositeLayout->addWidget(m_reloadButton); 0351 0352 QWidgetAction * action; 0353 0354 action = new QWidgetAction(this); 0355 viewManager->actionCollection()->addAction("composite_actions", action); 0356 action->setText(i18n("Brush composite")); 0357 action->setDefaultWidget(compositeActions); 0358 0359 action = new QWidgetAction(this); 0360 KisActionRegistry::instance()->propertizeAction("brushslider1", action); 0361 viewManager->actionCollection()->addAction("brushslider1", action); 0362 action->setDefaultWidget(m_sliderChooser[0]); 0363 connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget())); 0364 connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[0], SLOT(updateThemedIcons())); 0365 0366 action = new QWidgetAction(this); 0367 KisActionRegistry::instance()->propertizeAction("brushslider2", action); 0368 viewManager->actionCollection()->addAction("brushslider2", action); 0369 action->setDefaultWidget(m_sliderChooser[1]); 0370 connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget())); 0371 connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[1], SLOT(updateThemedIcons())); 0372 0373 action = new QWidgetAction(this); 0374 KisActionRegistry::instance()->propertizeAction("brushslider3", action); 0375 viewManager->actionCollection()->addAction("brushslider3", action); 0376 action->setDefaultWidget(m_sliderChooser[2]); 0377 connect(action, SIGNAL(triggered()), m_sliderChooser[2], SLOT(showPopupWidget())); 0378 connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[2], SLOT(updateThemedIcons())); 0379 0380 action = new QWidgetAction(this); 0381 KisActionRegistry::instance()->propertizeAction("brushslider4", action); 0382 viewManager->actionCollection()->addAction("brushslider4", action); 0383 action->setDefaultWidget(m_sliderChooser[3]); 0384 connect(action, SIGNAL(triggered()), m_sliderChooser[3], SLOT(showPopupWidget())); 0385 connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[3], SLOT(updateThemedIcons())); 0386 0387 action = new QWidgetAction(this); 0388 KisActionRegistry::instance()->propertizeAction("next_favorite_preset", action); 0389 viewManager->actionCollection()->addAction("next_favorite_preset", action); 0390 connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset())); 0391 0392 action = new QWidgetAction(this); 0393 KisActionRegistry::instance()->propertizeAction("previous_favorite_preset", action); 0394 viewManager->actionCollection()->addAction("previous_favorite_preset", action); 0395 connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset())); 0396 0397 action = new QWidgetAction(this); 0398 KisActionRegistry::instance()->propertizeAction("previous_preset", action); 0399 viewManager->actionCollection()->addAction("previous_preset", action); 0400 connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset())); 0401 0402 if (!cfg.toolOptionsInDocker()) { 0403 action = new QWidgetAction(this); 0404 KisActionRegistry::instance()->propertizeAction("show_tool_options", action); 0405 viewManager->actionCollection()->addAction("show_tool_options", action); 0406 connect(action, SIGNAL(triggered()), m_toolOptionsPopupButton, SLOT(showPopupWidget())); 0407 } 0408 0409 0410 action = new QWidgetAction(this); 0411 KisActionRegistry::instance()->propertizeAction("show_brush_presets", action); 0412 viewManager->actionCollection()->addAction("show_brush_presets", action); 0413 connect(action, SIGNAL(triggered()), m_presetSelectorPopupButton, SLOT(showPopupWidget())); 0414 m_presetsChooserPopup->addAction(action); 0415 0416 QWidget* mirrorActions = new QWidget(this); 0417 QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions); 0418 mirrorLayout->addWidget(m_hMirrorButton); 0419 0420 mirrorLayout->addWidget(m_vMirrorButton); 0421 mirrorLayout->addWidget(m_wrapAroundButton); 0422 mirrorLayout->setSpacing(4); 0423 mirrorLayout->setContentsMargins(0, 0, 0, 0); 0424 0425 action = new QWidgetAction(this); 0426 KisActionRegistry::instance()->propertizeAction("mirror_actions", action); 0427 action->setDefaultWidget(mirrorActions); 0428 viewManager->actionCollection()->addAction("mirror_actions", action); 0429 0430 action = new QWidgetAction(this); 0431 KisActionRegistry::instance()->propertizeAction(ResourceType::Workspaces, action); 0432 viewManager->actionCollection()->addAction(ResourceType::Workspaces, action); 0433 action->setDefaultWidget(m_workspaceWidget); 0434 connect(action, SIGNAL(triggered()), m_workspaceWidget, SLOT(showPopupWidget())); 0435 workspacePopup->addAction(action); 0436 0437 if (!cfg.toolOptionsInDocker()) { 0438 m_toolOptionsPopup = new KisToolOptionsPopup(); 0439 m_toolOptionsPopupButton->setPopupWidget(m_toolOptionsPopup); 0440 } 0441 0442 0443 m_savePresetWidget = new KisPresetSaveWidget(this); 0444 0445 m_presetsEditor = new KisPaintOpPresetsEditor(m_resourceProvider, m_favoriteResourceManager, m_savePresetWidget, m_brushEditorPopupButton); 0446 m_presetsEditor->setWindowTitle(i18n("Brush Editor")); 0447 m_brushEditorPopupButton->setPopupWidget(m_presetsEditor); 0448 m_brushEditorPopupButton->setPopupWidgetDetached(cfg.paintopPopupDetached()); 0449 0450 connect(m_presetsEditor, SIGNAL(brushEditorShown()), SLOT(slotUpdateOptionsWidgetPopup())); 0451 connect(m_presetsEditor, SIGNAL(toggleDetachState(bool)), m_brushEditorPopupButton, SLOT(setPopupWidgetDetached(bool))); 0452 connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_presetsEditor, SLOT(updateThemedIcons())); 0453 0454 action = new QWidgetAction(this); 0455 KisActionRegistry::instance()->propertizeAction("show_brush_editor", action); 0456 viewManager->actionCollection()->addAction("show_brush_editor", action); 0457 connect(action, SIGNAL(toggled(bool)), this, SLOT(togglePresetEditor())); 0458 m_presetsEditor->addAction(action); 0459 0460 m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); 0461 0462 slotNodeChanged(viewManager->activeNode()); 0463 // Get all the paintops 0464 QList<QString> keys = KisPaintOpRegistry::instance()->keys(); 0465 QList<KisPaintOpFactory*> factoryList; 0466 0467 Q_FOREACH (const QString & paintopId, keys) { 0468 factoryList.append(KisPaintOpRegistry::instance()->get(paintopId)); 0469 } 0470 m_presetsEditor->setPaintOpList(factoryList); 0471 0472 connect(m_presetsEditor , SIGNAL(paintopActivated(QString)) , SLOT(slotSetPaintop(QString))); 0473 connect(m_presetsEditor , SIGNAL(defaultPresetClicked()) , SLOT(slotSetupDefaultPreset())); 0474 connect(m_presetsEditor , SIGNAL(signalResourceSelected(KoResourceSP )), SLOT(resourceSelected(KoResourceSP ))); 0475 connect(m_presetsEditor , SIGNAL(reloadPresetClicked()) , SLOT(slotReloadPreset())); 0476 connect(m_presetsEditor , SIGNAL(dirtyPresetToggled(bool)) , SLOT(slotDirtyPresetToggled(bool))); 0477 connect(m_presetsEditor , SIGNAL(eraserBrushSizeToggled(bool)) , SLOT(slotEraserBrushSizeToggled(bool))); 0478 connect(m_presetsEditor , SIGNAL(eraserBrushOpacityToggled(bool)) , SLOT(slotEraserBrushOpacityToggled(bool))); 0479 0480 connect(m_presetsEditor, SIGNAL(createPresetFromScratch(QString)), this, SLOT(slotCreatePresetFromScratch(QString))); 0481 0482 connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResourceSP )) , SLOT(resourceSelected(KoResourceSP ))); 0483 connect(m_presetsChooserPopup, SIGNAL(resourceClicked(KoResourceSP )) , SLOT(resourceSelected(KoResourceSP ))); 0484 0485 connect(m_resourceProvider , SIGNAL(sigNodeChanged(KisNodeSP)) , SLOT(slotNodeChanged(KisNodeSP))); 0486 connect(m_cmbCompositeOp , SIGNAL(currentIndexChanged(int)) , SLOT(slotSetCompositeMode(int))); 0487 connect(m_eraseAction , SIGNAL(toggled(bool)) , SLOT(slotToggleEraseMode(bool))); 0488 connect(alphaLockAction , SIGNAL(toggled(bool)) , SLOT(slotToggleAlphaLockMode(bool))); 0489 0490 m_disablePressureAction = m_viewManager->actionManager()->createAction("disable_pressure"); 0491 connect(m_disablePressureAction , SIGNAL(toggled(bool)) , SLOT(slotDisablePressureMode(bool))); 0492 m_disablePressureAction->setChecked(true); 0493 0494 connect(m_hMirrorAction , SIGNAL(toggled(bool)) , SLOT(slotHorizontalMirrorChanged(bool))); 0495 connect(m_vMirrorAction , SIGNAL(toggled(bool)) , SLOT(slotVerticalMirrorChanged(bool))); 0496 connect(m_reloadAction , SIGNAL(triggered()) , SLOT(slotReloadPreset())); 0497 0498 connect(m_sliderChooser[0]->getWidget<KisDoubleSliderSpinBox>("opacity") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); 0499 connect(m_sliderChooser[0]->getWidget<KisDoubleSliderSpinBox>("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); 0500 connect(m_sliderChooser[0]->getWidget<KisDoubleSliderSpinBox>("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); 0501 connect(m_sliderChooser[0]->getWidget<KisMultipliersDoubleSliderSpinBox>("patternsize"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); 0502 connect(m_sliderChooser[1]->getWidget<KisDoubleSliderSpinBox>("opacity") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); 0503 connect(m_sliderChooser[1]->getWidget<KisDoubleSliderSpinBox>("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); 0504 connect(m_sliderChooser[1]->getWidget<KisDoubleSliderSpinBox>("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); 0505 connect(m_sliderChooser[1]->getWidget<KisMultipliersDoubleSliderSpinBox>("patternsize"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); 0506 connect(m_sliderChooser[2]->getWidget<KisDoubleSliderSpinBox>("opacity") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); 0507 connect(m_sliderChooser[2]->getWidget<KisDoubleSliderSpinBox>("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); 0508 connect(m_sliderChooser[2]->getWidget<KisDoubleSliderSpinBox>("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); 0509 connect(m_sliderChooser[2]->getWidget<KisMultipliersDoubleSliderSpinBox>("patternsize"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); 0510 connect(m_sliderChooser[3]->getWidget<KisDoubleSliderSpinBox>("opacity") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider4Changed())); 0511 connect(m_sliderChooser[3]->getWidget<KisDoubleSliderSpinBox>("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider4Changed())); 0512 connect(m_sliderChooser[3]->getWidget<KisDoubleSliderSpinBox>("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider4Changed())); 0513 connect(m_sliderChooser[3]->getWidget<KisMultipliersDoubleSliderSpinBox>("patternsize"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider4Changed())); 0514 0515 connect(m_resourceProvider, SIGNAL(sigFGColorUsed(KoColor)), m_favoriteResourceManager, SLOT(slotAddRecentColor(KoColor))); 0516 0517 connect(m_resourceProvider, SIGNAL(sigFGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotChangeFGColorSelector(KoColor))); 0518 connect(m_resourceProvider, SIGNAL(sigBGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotSetBGColor(KoColor))); 0519 0520 // cold initialization 0521 m_favoriteResourceManager->slotChangeFGColorSelector(m_resourceProvider->fgColor()); 0522 m_favoriteResourceManager->slotSetBGColor(m_resourceProvider->bgColor()); 0523 0524 connect(m_favoriteResourceManager, SIGNAL(sigSetFGColor(KoColor)), m_resourceProvider, SLOT(slotSetFGColor(KoColor))); 0525 connect(m_favoriteResourceManager, SIGNAL(sigSetBGColor(KoColor)), m_resourceProvider, SLOT(slotSetBGColor(KoColor))); 0526 0527 connect(viewManager->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateSelectionIcon())); 0528 connect(m_resourceProvider->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), 0529 this, SLOT(slotCanvasResourceChanged(int,QVariant))); 0530 connect(m_resourceProvider->resourceManager(), SIGNAL(canvasResourceChangeAttempted(int,QVariant)), 0531 this, SLOT(slotCanvasResourceChangeAttempted(int,QVariant))); 0532 0533 connect(&m_optionWidgetUpdateCompressor, SIGNAL(timeout()), this, SLOT(slotUpdateOptionsWidgetPopup())); 0534 0535 slotInputDeviceChanged(KoToolManager::instance()->currentInputDevice()); 0536 0537 findDefaultPresets(); 0538 } 0539 0540 0541 KisPaintopBox::~KisPaintopBox() 0542 { 0543 KisConfig cfg(false); 0544 QMapIterator<TabletToolID, TabletToolData> iter(m_tabletToolMap); 0545 while (iter.hasNext()) { 0546 iter.next(); 0547 if ((iter.key().pointer) == QTabletEvent::Eraser) { 0548 cfg.writeEntry(QString("LastEraser_%1").arg(iter.key().uniqueTabletId), iter.value().preset->name()); 0549 } 0550 else { 0551 cfg.writeEntry(QString("LastPreset_%1").arg(iter.key().uniqueTabletId), iter.value().preset->name()); 0552 } 0553 } 0554 // Do not delete the widget, since it is global to the application, not owned by the view 0555 m_presetsEditor->setPaintOpSettingsWidget(0); 0556 qDeleteAll(m_paintopOptionWidgets); 0557 delete m_favoriteResourceManager; 0558 0559 delete toolbarMenuXMirror; 0560 delete toolbarMenuYMirror; 0561 0562 for (int i = 0; i < 3; ++i) 0563 { 0564 delete m_sliderChooser[i]; 0565 } 0566 } 0567 0568 void KisPaintopBox::restoreResource(KoResourceSP resource) 0569 { 0570 KisPaintOpPresetSP preset = resource.dynamicCast<KisPaintOpPreset>(); 0571 0572 if (preset) { 0573 setCurrentPaintop(preset); 0574 0575 m_presetsEditor->setPresetImage(preset->image()); 0576 m_presetsEditor->resourceSelected(resource); 0577 } 0578 } 0579 0580 void KisPaintopBox::newOptionWidgets(const QList<QPointer<QWidget> > &optionWidgetList) 0581 { 0582 if (m_toolOptionsPopup) { 0583 m_toolOptionsPopup->newOptionWidgets(optionWidgetList); 0584 } 0585 } 0586 0587 void KisPaintopBox::resourceSelected(KoResourceSP resource) 0588 { 0589 // This happens if no storages were available on startup 0590 if (!m_optionWidget) { 0591 KisPaintOpPresetSP preset = resource.dynamicCast<KisPaintOpPreset>(); 0592 setCurrentPaintop(preset); 0593 return; 0594 } 0595 0596 m_presetsEditor->setCreatingBrushFromScratch(false); // show normal UI elements when we are not creating 0597 0598 KisPaintOpPresetSP preset = resource.dynamicCast<KisPaintOpPreset>(); 0599 0600 if (preset && preset->valid() && preset != m_resourceProvider->currentPreset()) { 0601 if (!m_dirtyPresetsEnabled) { 0602 KisSignalsBlocker blocker(m_optionWidget); 0603 Q_UNUSED(blocker); 0604 0605 KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); 0606 0607 if (!rserver->reloadResource(preset)) { 0608 qWarning() << "failed to reload the preset."; 0609 } 0610 } 0611 0612 dbgResources << "resourceSelected: preset" << preset << (preset ? QString("%1").arg(preset->valid()) : ""); 0613 setCurrentPaintop(preset); 0614 0615 m_presetsEditor->setPresetImage(preset->image()); 0616 m_presetsEditor->resourceSelected(resource); 0617 } 0618 } 0619 0620 void KisPaintopBox::setCurrentPaintop(const KoID& paintop) 0621 { 0622 KisPaintOpPresetSP preset = activePreset(paintop); 0623 setCurrentPaintop(preset); 0624 } 0625 0626 void KisPaintopBox::setCurrentPaintop(KisPaintOpPresetSP preset) 0627 { 0628 if (preset == m_resourceProvider->currentPreset()) { 0629 if (preset == m_tabletToolMap[m_currTabletToolID].preset) { 0630 return; 0631 } 0632 } 0633 Q_ASSERT(preset); 0634 const KoID& paintop = preset->paintOp(); 0635 m_presetConnections.clear(); 0636 0637 if (m_resourceProvider->currentPreset()) { 0638 m_resourceProvider->setPreviousPaintOpPreset(m_resourceProvider->currentPreset()); 0639 0640 if (m_optionWidget) { 0641 m_optionWidget->hide(); 0642 } 0643 0644 } 0645 0646 if (!m_paintopOptionWidgets.contains(paintop)) { 0647 m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createConfigWidget(this); 0648 m_paintopOptionWidgets[paintop]->setResourcesInterface(KisGlobalResourcesInterface::instance()); 0649 m_paintopOptionWidgets[paintop]->setCanvasResourcesInterface(m_viewManager->canvasResourceProvider()->resourceManager()->canvasResourcesInterface()); 0650 } 0651 0652 m_optionWidget = m_paintopOptionWidgets[paintop]; 0653 0654 Q_ASSERT(m_optionWidget && m_presetSelectorPopupButton); 0655 0656 KisSignalsBlocker b(m_optionWidget); 0657 0658 m_optionWidget->setImage(m_viewManager->image()); 0659 m_optionWidget->setNode(m_viewManager->activeNode()); 0660 0661 m_optionWidget->setConfigurationSafe(preset->settings()); 0662 0663 m_presetsEditor->setPaintOpSettingsWidget(m_optionWidget); 0664 0665 m_resourceProvider->setPaintOpPreset(preset); 0666 0667 0668 0669 /// We must connect to the **uncompressed** version of the preset 0670 /// update signal. That is the only way we can guarantee that 0671 /// the signals will not form cycles. As a consequence, we should 0672 /// compress this signal ourselves. 0673 m_optionsWidgetConnections.reset(new KisAcyclicSignalConnector()); 0674 m_optionsWidgetConnections->connectForwardVoid(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotGuiChangedCurrentPreset())); 0675 m_optionsWidgetConnections->connectBackwardVoid(preset->updateProxy(), SIGNAL(sigSettingsChangedUncompressed()), &m_optionWidgetUpdateCompressor, SLOT(start())); 0676 0677 m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfigurationSP)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP))); 0678 m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfigurationSP)), this, SLOT(slotDropLockedOption(KisPropertiesConfigurationSP))); 0679 0680 // load the current preset icon to the preset selector toolbar button 0681 m_presetSelectorPopupButton->setThumbnail(preset->image()); 0682 m_presetsEditor->setCurrentPaintOpId(paintop.id()); 0683 0684 0685 //o() << "\tsetting the new preset for" << m_currTabletToolID.uniqueID << "to" << preset->name(); 0686 m_paintOpPresetMap[m_resourceProvider->currentPreset()->paintOp()] = preset; 0687 m_tabletToolMap[m_currTabletToolID].preset = preset; 0688 m_tabletToolMap[m_currTabletToolID].paintOpID = preset->paintOp(); 0689 0690 0691 if (m_presetsEditor->currentPaintOpId() != paintop.id()) { 0692 // Must change the paintop as the current one is not supported 0693 // by the new colorspace. 0694 dbgKrita << "current paintop " << paintop.name() << " was not set, not supported by colorspace"; 0695 } 0696 0697 m_currCompositeOpID = preset->settings()->paintOpCompositeOp(); 0698 updateCompositeOp(m_currCompositeOpID); 0699 0700 if (preset->settings()->hasPatternSettings()) { 0701 setMultiplierSliderValue("patternsize", preset->settings()->paintOpPatternSize()); 0702 setWidgetState(ENABLE_PATTERNSIZE); 0703 } 0704 else { 0705 setWidgetState(DISABLE_PATTERNSIZE); 0706 } 0707 0708 // MyPaint brushes don't support custom blend modes, they always perform "Normal and Erase" blending. 0709 if (preset->paintOp().id() == "mypaintbrush") { 0710 setWidgetState(DISABLE_COMPOSITEOP); 0711 if (m_resourceProvider->currentCompositeOp() != COMPOSITE_ERASE && m_resourceProvider->currentCompositeOp() != COMPOSITE_OVER) { 0712 m_resourceProvider->setCurrentCompositeOp(COMPOSITE_OVER); 0713 } 0714 } 0715 else { 0716 setWidgetState(ENABLE_COMPOSITEOP); 0717 } 0718 } 0719 0720 void KisPaintopBox::slotUpdateOptionsWidgetPopup() 0721 { 0722 KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); 0723 0724 // This happens when we have a new brush engine for which no default preset exists yet. 0725 if (!preset) return; 0726 0727 // the connection to the preset is maintained even when the editor 0728 // is hidden, so skip the updates 0729 if (!m_presetsEditor->isVisible()) return; 0730 0731 KIS_SAFE_ASSERT_RECOVER_RETURN(preset); 0732 KIS_SAFE_ASSERT_RECOVER_RETURN(m_optionWidget); 0733 0734 m_optionWidget->setConfigurationSafe(preset->settings()); 0735 0736 m_presetsEditor->resourceSelected(preset); 0737 m_presetsEditor->updateViewSettings(); 0738 0739 // the m_viewManager->image() is set earlier, but the reference will be missing when the stamp button is pressed 0740 // need to later do some research on how and when we should be using weak shared pointers (WSP) that creates this situation 0741 m_optionWidget->setImage(m_viewManager->image()); 0742 } 0743 0744 void KisPaintopBox::togglePresetEditor() 0745 { 0746 if (m_brushEditorPopupButton->isPopupWidgetVisible()) { 0747 m_brushEditorPopupButton->hidePopupWidget(); 0748 } else { 0749 m_brushEditorPopupButton->showPopupWidget(); 0750 } 0751 } 0752 0753 KisPaintOpPresetSP KisPaintopBox::defaultPreset(const KoID& paintOp) 0754 { 0755 QString path = ":/presets/" + paintOp.id() + ".kpp"; 0756 0757 if (paintOp.id() == "mypaintbrush") { 0758 path = ":/presets/" + paintOp.id() + ".myb"; 0759 } 0760 0761 dbgResources << "Getting default presets from qrc resources" << path; 0762 0763 KisPaintOpPresetSP preset(new KisPaintOpPreset(path)); 0764 0765 if (!preset->load(KisGlobalResourcesInterface::instance())) { 0766 bool success = false; 0767 0768 QFile file(path); 0769 0770 if (file.open(QIODevice::ReadOnly)) 0771 { 0772 // this is needed specifically for MyPaint brushes 0773 QVector<KisResourceLoaderBase*> loaders = KisResourceLoaderRegistry::instance()->resourceTypeLoaders(ResourceType::PaintOpPresets); 0774 for (int i = 0; i < loaders.count(); i++) { 0775 file.seek(0); // to ensure that one loader reading bytes won't interfere with another 0776 KoResourceSP resource = loaders[i]->load(paintOp.id(), file, KisGlobalResourcesInterface::instance()); 0777 if (resource) { 0778 preset = resource.dynamicCast<KisPaintOpPreset>(); 0779 success = !preset.isNull(); 0780 if (success) { 0781 break; 0782 } 0783 } 0784 } 0785 file.close(); 0786 } 0787 0788 if (!success) { 0789 preset = KisPaintOpRegistry::instance()->defaultPreset(paintOp, KisGlobalResourcesInterface::instance()); 0790 } 0791 } 0792 0793 Q_ASSERT(preset); 0794 Q_ASSERT(preset->valid()); 0795 0796 return preset; 0797 } 0798 0799 KisPaintOpPresetSP KisPaintopBox::activePreset(const KoID& paintOp) 0800 { 0801 if (m_paintOpPresetMap[paintOp] == 0) { 0802 m_paintOpPresetMap[paintOp] = defaultPreset(paintOp); 0803 } 0804 0805 return m_paintOpPresetMap[paintOp]; 0806 } 0807 0808 void KisPaintopBox::updateCompositeOp(QString compositeOpID) 0809 { 0810 if (!m_optionWidget) return; 0811 KisSignalsBlocker blocker(m_optionWidget); 0812 0813 KisNodeSP node = m_resourceProvider->currentNode(); 0814 0815 if (node && node->paintDevice()) { 0816 if (!node->paintDevice()->compositionSourceColorSpace()->hasCompositeOp(compositeOpID)) { 0817 compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); 0818 } 0819 0820 { 0821 KisSignalsBlocker b1(m_cmbCompositeOp); 0822 m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID)); 0823 } 0824 if (compositeOpID != m_currCompositeOpID) { 0825 m_currCompositeOpID = compositeOpID; 0826 } 0827 if (compositeOpID == COMPOSITE_ERASE || m_resourceProvider->eraserMode()) { 0828 m_eraseModeButton->setChecked(true); 0829 } 0830 else { 0831 m_eraseModeButton->setChecked(false); 0832 } 0833 } 0834 else if (!node) { 0835 KisSignalsBlocker b1(m_cmbCompositeOp); 0836 m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID)); 0837 m_currCompositeOpID = compositeOpID; 0838 0839 } 0840 } 0841 0842 void KisPaintopBox::setWidgetState(int flags) 0843 { 0844 if (flags & (ENABLE_COMPOSITEOP | DISABLE_COMPOSITEOP)) { 0845 m_cmbCompositeOp->setEnabled(flags & ENABLE_COMPOSITEOP); 0846 m_eraseModeButton->setEnabled(flags & ENABLE_COMPOSITEOP); 0847 } 0848 0849 if (flags & (ENABLE_PRESETS | DISABLE_PRESETS)) { 0850 m_presetSelectorPopupButton->setEnabled(flags & ENABLE_PRESETS); 0851 m_brushEditorPopupButton->setEnabled(flags & ENABLE_PRESETS); 0852 } 0853 } 0854 0855 void KisPaintopBox::setSliderValue(const QString& sliderID, qreal value) 0856 { 0857 for (int i = 0; i < 4; ++i) { 0858 KisDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget<KisDoubleSliderSpinBox>(sliderID); 0859 KisSignalsBlocker b(slider); 0860 0861 if (sliderID == "opacity" || sliderID == "flow") { // opacity and flows UI stored at 0-100% 0862 slider->setValue(value*100); 0863 } else { 0864 slider->setValue(value); // brush size 0865 } 0866 0867 0868 } 0869 } 0870 0871 void KisPaintopBox::setMultiplierSliderValue(const QString& sliderID, qreal value) 0872 { 0873 for (int i = 0; i < 4; ++i) { 0874 KisMultipliersDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget<KisMultipliersDoubleSliderSpinBox>(sliderID); 0875 if (!slider) continue; 0876 KisSignalsBlocker b(slider); 0877 0878 slider->setValue(value); // brush pattern size 0879 } 0880 } 0881 0882 void KisPaintopBox::slotSetPaintop(const QString& paintOpId) 0883 { 0884 if (KisPaintOpRegistry::instance()->get(paintOpId) != 0) { 0885 KoID id(paintOpId, KisPaintOpRegistry::instance()->get(paintOpId)->name()); 0886 //qDebug() << "slotsetpaintop" << id; 0887 setCurrentPaintop(id); 0888 } 0889 } 0890 0891 void KisPaintopBox::slotInputDeviceChanged(const KoInputDevice& inputDevice) 0892 { 0893 TabletToolMap::iterator toolData = m_tabletToolMap.find(inputDevice); 0894 0895 //qDebug() << "slotInputDeviceChanged()" << inputDevice.device() << inputDevice.uniqueTabletId(); 0896 0897 m_currTabletToolID = TabletToolID(inputDevice); 0898 0899 if (toolData == m_tabletToolMap.end()) { 0900 KisConfig cfg(true); 0901 KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); 0902 KisPaintOpPresetSP preset; 0903 if (inputDevice.pointer() == QTabletEvent::Eraser) { 0904 preset = rserver->resource("", "", cfg.readEntry<QString>(QString("LastEraser_%1").arg(inputDevice.uniqueTabletId()), m_eraserName)); 0905 } 0906 else { 0907 preset = rserver->resource("", "", cfg.readEntry<QString>(QString("LastPreset_%1").arg(inputDevice.uniqueTabletId()), m_defaultPresetName)); 0908 // if (preset) 0909 // qDebug() << "found stored preset " << preset->name() << "for" << inputDevice.uniqueTabletId(); 0910 // else 0911 // qDebug() << "no preset found for" << inputDevice.uniqueTabletId(); 0912 } 0913 if (!preset) { 0914 preset = rserver->resource("", "", m_defaultPresetName); 0915 } 0916 if (preset) { 0917 // qDebug() << "inputdevicechanged 1" << preset; 0918 setCurrentPaintop(preset); 0919 } 0920 } 0921 else { 0922 if (toolData->preset) { 0923 //qDebug() << "inputdevicechanged 2" << toolData->preset; 0924 setCurrentPaintop(toolData->preset); 0925 } 0926 else { 0927 //qDebug() << "inputdevicechanged 3" << toolData->paintOpID; 0928 setCurrentPaintop(toolData->paintOpID); 0929 } 0930 } 0931 } 0932 0933 void KisPaintopBox::slotCreatePresetFromScratch(QString paintop) 0934 { 0935 //First try to select an available default preset for that engine. If it doesn't exist, then 0936 //manually set the engine to use a new preset. 0937 KoID id(paintop, KisPaintOpRegistry::instance()->get(paintop)->name()); 0938 KisPaintOpPresetSP preset = defaultPreset(id); 0939 0940 slotSetPaintop(paintop); // change the paintop settings area and update the UI 0941 0942 if (!preset) { 0943 m_presetsEditor->setCreatingBrushFromScratch(true); // disable UI elements while creating from scratch 0944 preset = m_resourceProvider->currentPreset(); 0945 } else { 0946 m_resourceProvider->setPaintOpPreset(preset); 0947 if (m_optionWidget) { 0948 m_optionWidget->setConfigurationSafe(preset->settings()); 0949 } 0950 } 0951 m_presetsEditor->resourceSelected(preset); // this helps update the UI on the brush editor 0952 } 0953 0954 void KisPaintopBox::slotCanvasResourceChangeAttempted(int key, const QVariant &value) 0955 { 0956 Q_UNUSED(value); 0957 0958 if (key == KoCanvasResource::ForegroundColor) { 0959 slotUnsetEraseMode(); 0960 } 0961 } 0962 0963 void KisPaintopBox::slotCanvasResourceChanged(int key, const QVariant &value) 0964 { 0965 if (m_viewManager) { 0966 sender()->blockSignals(true); 0967 KisPaintOpPresetSP preset = m_viewManager->canvasResourceProvider()->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).value<KisPaintOpPresetSP>(); 0968 if (preset && m_resourceProvider->currentPreset()->name() != preset->name()) { 0969 QString compositeOp = preset->settings()->getString("CompositeOp"); 0970 updateCompositeOp(compositeOp); 0971 resourceSelected(preset); 0972 } 0973 0974 if (key == KoCanvasResource::CurrentPaintOpPreset) { 0975 /** 0976 * Update currently selected preset in both the popup widgets 0977 */ 0978 m_presetsChooserPopup->canvasResourceChanged(preset); 0979 m_presetsEditor->currentPresetChanged(preset); 0980 } 0981 0982 if (key == KoCanvasResource::CurrentCompositeOp) { 0983 if (m_resourceProvider->currentCompositeOp() != m_currCompositeOpID) { 0984 updateCompositeOp(m_resourceProvider->currentCompositeOp()); 0985 } 0986 } 0987 0988 if (key == KoCanvasResource::Size) { 0989 setSliderValue("size", m_resourceProvider->size()); 0990 } 0991 0992 if (key == KoCanvasResource::PatternSize) { 0993 setMultiplierSliderValue("patternsize", m_resourceProvider->patternSize()); 0994 } 0995 0996 if (key == KoCanvasResource::Opacity) { 0997 setSliderValue("opacity", m_resourceProvider->opacity()); 0998 } 0999 1000 if (key == KoCanvasResource::Flow) { 1001 setSliderValue("flow", m_resourceProvider->flow()); 1002 } 1003 1004 if (key == KoCanvasResource::EraserMode) { 1005 m_eraseAction->setChecked(value.toBool()); 1006 } 1007 1008 if (key == KoCanvasResource::DisablePressure) { 1009 m_disablePressureAction->setChecked(value.toBool()); 1010 } 1011 1012 if (key == KoCanvasResource::MirrorHorizontal) { 1013 m_hMirrorAction->setChecked(value.toBool()); 1014 } 1015 1016 if (key == KoCanvasResource::MirrorVertical) { 1017 m_vMirrorAction->setChecked(value.toBool()); 1018 } 1019 1020 sender()->blockSignals(false); 1021 } 1022 } 1023 1024 void KisPaintopBox::slotSetupDefaultPreset() 1025 { 1026 KisPaintOpPresetSP preset = defaultPreset(m_resourceProvider->currentPreset()->paintOp()); 1027 if (m_optionWidget) { 1028 m_optionWidget->setConfigurationSafe(preset->settings()); 1029 } 1030 m_resourceProvider->setPaintOpPreset(preset); 1031 1032 // tell the brush editor that the resource has changed 1033 // so it can update everything 1034 m_presetsEditor->resourceSelected(preset); 1035 } 1036 1037 void KisPaintopBox::slotNodeChanged(const KisNodeSP node) 1038 { 1039 KisNodeSP previousNode(m_currentNode); 1040 if (previousNode && previousNode->paintDevice()) 1041 disconnect(previousNode->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); 1042 1043 // Reconnect colorspace change of node 1044 if (node && node->paintDevice()) { 1045 connect(node->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); 1046 m_resourceProvider->setCurrentCompositeOp(m_currCompositeOpID); 1047 m_currentNode = node; 1048 slotColorSpaceChanged(node->paintDevice()->colorSpace()); 1049 } 1050 1051 if (m_optionWidget) { 1052 m_optionWidget->setNode(node); 1053 } 1054 } 1055 1056 void KisPaintopBox::slotColorSpaceChanged(const KoColorSpace* colorSpace) 1057 { 1058 KisNodeSP node(m_currentNode); 1059 const KoColorSpace *compositionSpace = colorSpace; 1060 if (node && node->paintDevice()) { 1061 // Currently, composition source is enough to determine the available blending mode, 1062 // because either destination is the same (paint layers), or composition happens 1063 // in source space (masks). 1064 compositionSpace = node->paintDevice()->compositionSourceColorSpace(); 1065 } 1066 m_cmbCompositeOp->validate(compositionSpace); 1067 } 1068 1069 void KisPaintopBox::slotToggleEraseMode(bool checked) 1070 { 1071 const bool oldEraserMode = m_resourceProvider->eraserMode(); 1072 m_resourceProvider->setEraserMode(checked); 1073 1074 if (oldEraserMode != checked && m_eraserBrushSizeEnabled) { 1075 const qreal currentSize = m_resourceProvider->size(); 1076 1077 KisPaintOpSettingsSP settings = m_resourceProvider->currentPreset()->settings(); 1078 1079 // remember brush size. set the eraser size to the normal brush size if not set 1080 if (checked) { 1081 settings->setSavedBrushSize(currentSize); 1082 if (qFuzzyIsNull(settings->savedEraserSize())) { 1083 settings->setSavedEraserSize(currentSize); 1084 } 1085 } else { 1086 settings->setSavedEraserSize(currentSize); 1087 if (qFuzzyIsNull(settings->savedBrushSize())) { 1088 settings->setSavedBrushSize(currentSize); 1089 } 1090 } 1091 1092 //update value in UI (this is the main place the value is 'stored' in memory) 1093 qreal newSize = checked ? settings->savedEraserSize() : settings->savedBrushSize(); 1094 m_resourceProvider->setSize(newSize); 1095 } 1096 if (oldEraserMode != checked && m_eraserBrushOpacityEnabled) { 1097 const qreal currentOpacity = m_resourceProvider->opacity(); 1098 1099 KisPaintOpSettingsSP settings = m_resourceProvider->currentPreset()->settings(); 1100 1101 // remember brush opacity. set the eraser opacity to the normal brush opacity if not set 1102 if (checked) { 1103 settings->setSavedBrushOpacity(currentOpacity); 1104 if (qFuzzyIsNull(settings->savedEraserOpacity())) { 1105 settings->setSavedEraserOpacity(currentOpacity); 1106 } 1107 } else { 1108 settings->setSavedEraserOpacity(currentOpacity); 1109 if (qFuzzyIsNull(settings->savedBrushOpacity())) { 1110 settings->setSavedBrushOpacity(currentOpacity); 1111 } 1112 } 1113 1114 //update value in UI (this is the main place the value is 'stored' in memory) 1115 qreal newOpacity = checked ? settings->savedEraserOpacity() : settings->savedBrushOpacity(); 1116 m_resourceProvider->setOpacity(newOpacity); 1117 } 1118 } 1119 1120 void KisPaintopBox::slotSetCompositeMode(int index) 1121 { 1122 Q_UNUSED(index); 1123 QString compositeOp = m_cmbCompositeOp->selectedCompositeOp().id(); 1124 m_resourceProvider->setCurrentCompositeOp(compositeOp); 1125 } 1126 1127 void KisPaintopBox::slotHorizontalMirrorChanged(bool value) 1128 { 1129 m_resourceProvider->setMirrorHorizontal(value); 1130 } 1131 1132 void KisPaintopBox::slotVerticalMirrorChanged(bool value) 1133 { 1134 m_resourceProvider->setMirrorVertical(value); 1135 } 1136 1137 void KisPaintopBox::sliderChanged(int n) 1138 { 1139 if (!m_optionWidget) // widget will not exist if the are no documents open 1140 return; 1141 1142 1143 KisSignalsBlocker blocker(m_optionWidget); 1144 1145 // flow and opacity are shown as 0-100% on the UI, but their data is actually 0-1. Convert those two values 1146 // back for further work 1147 qreal opacity = m_sliderChooser[n]->getWidget<KisDoubleSliderSpinBox>("opacity")->value()/100; 1148 qreal flow = m_sliderChooser[n]->getWidget<KisDoubleSliderSpinBox>("flow")->value()/100; 1149 qreal size = m_sliderChooser[n]->getWidget<KisDoubleSliderSpinBox>("size")->value(); 1150 qreal patternsize = m_sliderChooser[n]->getWidget<KisMultipliersDoubleSliderSpinBox>("patternsize")->value(); 1151 1152 1153 setSliderValue("opacity", opacity); 1154 setSliderValue("flow" , flow); 1155 setSliderValue("size" , size); 1156 setMultiplierSliderValue("patternsize", patternsize); 1157 1158 if (m_presetsEnabled) { 1159 // IMPORTANT: set the PaintOp size before setting the other properties 1160 // it won't work the other way 1161 // TODO: why?! 1162 1163 m_resourceProvider->setSize(size); 1164 m_resourceProvider->setPatternSize(patternsize); 1165 m_resourceProvider->setOpacity(opacity); 1166 m_resourceProvider->setFlow(flow); 1167 1168 1169 KisLockedPropertiesProxySP propertiesProxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(m_resourceProvider->currentPreset()->settings()); 1170 propertiesProxy->setProperty("OpacityValue", opacity); 1171 propertiesProxy->setProperty("FlowValue", flow); 1172 propertiesProxy->setProperty("Texture/Pattern/Scale", patternsize); 1173 m_optionWidget->setConfigurationSafe(m_resourceProvider->currentPreset()->settings().data()); 1174 } else { 1175 m_resourceProvider->setOpacity(opacity); 1176 } 1177 1178 m_presetsEditor->resourceSelected(m_resourceProvider->currentPreset()); 1179 } 1180 1181 void KisPaintopBox::slotSlider1Changed() 1182 { 1183 sliderChanged(0); 1184 } 1185 1186 void KisPaintopBox::slotSlider2Changed() 1187 { 1188 sliderChanged(1); 1189 } 1190 1191 void KisPaintopBox::slotSlider3Changed() 1192 { 1193 sliderChanged(2); 1194 } 1195 1196 void KisPaintopBox::slotSlider4Changed() 1197 { 1198 sliderChanged(3); 1199 } 1200 1201 void KisPaintopBox::slotToolChanged(KoCanvasController* canvas) 1202 { 1203 Q_UNUSED(canvas); 1204 1205 if (!m_viewManager->canvasBase()) return; 1206 1207 QString id = KoToolManager::instance()->activeToolId(); 1208 KisTool* tool = dynamic_cast<KisTool*>(KoToolManager::instance()->toolById(m_viewManager->canvasBase(), id)); 1209 1210 if (tool) { 1211 int flags = tool->flags(); 1212 1213 if (flags & KisTool::FLAG_USES_CUSTOM_COMPOSITEOP) { 1214 setWidgetState(ENABLE_COMPOSITEOP | ENABLE_OPACITY | ENABLE_PATTERNSIZE); 1215 } else { 1216 setWidgetState(DISABLE_COMPOSITEOP | DISABLE_OPACITY | DISABLE_PATTERNSIZE); 1217 } 1218 1219 if (flags & KisTool::FLAG_USES_CUSTOM_PRESET) { 1220 setWidgetState(ENABLE_PRESETS); 1221 if (!m_resourceProvider->currentPreset()) return; 1222 1223 // block updates of avoid some over updating of the option widget 1224 m_blockUpdate = true; 1225 1226 setSliderValue("size", m_resourceProvider->size()); 1227 1228 { 1229 qreal opacity = m_resourceProvider->currentPreset()->settings()->paintOpOpacity(); 1230 m_resourceProvider->setOpacity(opacity); 1231 setSliderValue("opacity", opacity); 1232 setWidgetState(ENABLE_OPACITY); 1233 } 1234 1235 { 1236 setSliderValue("flow", m_resourceProvider->currentPreset()->settings()->paintOpFlow()); 1237 setWidgetState(ENABLE_FLOW); 1238 } 1239 1240 { 1241 setMultiplierSliderValue("patternsize", m_resourceProvider->currentPreset()->settings()->paintOpPatternSize()); 1242 setWidgetState(ENABLE_PATTERNSIZE); 1243 } 1244 1245 // MyPaint brushes don't support custom blend modes, they always perform "Normal and Erase" blending. 1246 if (m_resourceProvider->currentPreset()->paintOp().id() == "mypaintbrush") { 1247 if (m_resourceProvider->currentCompositeOp() != COMPOSITE_ERASE && m_resourceProvider->currentCompositeOp() != COMPOSITE_OVER) { 1248 updateCompositeOp(COMPOSITE_OVER); 1249 } 1250 setWidgetState(DISABLE_COMPOSITEOP); 1251 } else { 1252 updateCompositeOp(m_resourceProvider->currentPreset()->settings()->paintOpCompositeOp()); 1253 setWidgetState(ENABLE_COMPOSITEOP); 1254 } 1255 1256 m_blockUpdate = false; 1257 1258 m_presetsEnabled = true; 1259 } else { 1260 setWidgetState(DISABLE_PRESETS); 1261 m_presetsEnabled = false; 1262 } 1263 1264 if (flags & KisTool::FLAG_USES_CUSTOM_SIZE) { 1265 setWidgetState(ENABLE_SIZE | ENABLE_FLOW | ENABLE_PATTERNSIZE); 1266 } else { 1267 setWidgetState(DISABLE_SIZE | DISABLE_FLOW| DISABLE_PATTERNSIZE); 1268 } 1269 1270 } else setWidgetState(DISABLE_ALL); 1271 } 1272 1273 void KisPaintopBox::slotPreviousFavoritePreset() 1274 { 1275 if (!m_favoriteResourceManager) return; 1276 1277 QVector<QString> presets = m_favoriteResourceManager->favoritePresetNamesList(); 1278 for (int i=0; i < presets.size(); ++i) { 1279 if (m_resourceProvider->currentPreset() && 1280 m_resourceProvider->currentPreset()->name() == presets[i]) { 1281 if (i > 0) { 1282 m_favoriteResourceManager->slotChangeActivePaintop(i - 1); 1283 } else { 1284 m_favoriteResourceManager->slotChangeActivePaintop(m_favoriteResourceManager->numFavoritePresets() - 1); 1285 } 1286 //floating message should have least 2 lines, otherwise 1287 //preset thumbnail will be too small to distinguish 1288 //(because size of image on floating message depends on amount of lines in msg) 1289 m_viewManager->showFloatingMessage( 1290 i18n("%1\nselected", 1291 m_resourceProvider->currentPreset()->name()), 1292 QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); 1293 1294 return; 1295 } 1296 } 1297 } 1298 1299 void KisPaintopBox::slotNextFavoritePreset() 1300 { 1301 if (!m_favoriteResourceManager) return; 1302 1303 QVector<QString> presets = m_favoriteResourceManager->favoritePresetNamesList(); 1304 for(int i = 0; i < presets.size(); ++i) { 1305 if (m_resourceProvider->currentPreset()->name() == presets[i]) { 1306 if (i < m_favoriteResourceManager->numFavoritePresets() - 1) { 1307 m_favoriteResourceManager->slotChangeActivePaintop(i + 1); 1308 } else { 1309 m_favoriteResourceManager->slotChangeActivePaintop(0); 1310 } 1311 m_viewManager->showFloatingMessage( 1312 i18n("%1\nselected", 1313 m_resourceProvider->currentPreset()->name()), 1314 QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); 1315 1316 return; 1317 } 1318 } 1319 } 1320 1321 void KisPaintopBox::slotSwitchToPreviousPreset() 1322 { 1323 if (m_resourceProvider->previousPreset()) { 1324 setCurrentPaintop(m_resourceProvider->previousPreset()); 1325 m_viewManager->showFloatingMessage( 1326 i18n("%1\nselected", 1327 m_resourceProvider->currentPreset()->name()), 1328 QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); 1329 } 1330 } 1331 1332 void KisPaintopBox::slotUnsetEraseMode() 1333 { 1334 m_eraseAction->setChecked(false); 1335 } 1336 1337 void KisPaintopBox::slotToggleAlphaLockMode(bool checked) 1338 { 1339 if (checked) { 1340 m_alphaLockButton->actions()[0]->setIcon(KisIconUtils::loadIcon("bar-transparency-locked")); 1341 } else { 1342 m_alphaLockButton->actions()[0]->setIcon(KisIconUtils::loadIcon("bar-transparency-unlocked")); 1343 } 1344 m_resourceProvider->setGlobalAlphaLock(checked); 1345 } 1346 1347 void KisPaintopBox::slotDisablePressureMode(bool checked) 1348 { 1349 if (checked) { 1350 m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure")); 1351 } else { 1352 m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure_locked")); 1353 } 1354 1355 m_resourceProvider->setDisablePressure(checked); 1356 } 1357 1358 void KisPaintopBox::slotReloadPreset() 1359 { 1360 KisSignalsBlocker blocker(m_optionWidget); 1361 1362 KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); 1363 QSharedPointer<KisPaintOpPreset> preset = m_resourceProvider->currentPreset(); 1364 1365 // Presets that just have been created cannot be reloaded. 1366 if (preset && preset->resourceId() > -1) { 1367 const bool result = rserver->reloadResource(preset); 1368 KIS_SAFE_ASSERT_RECOVER_NOOP(result && "couldn't reload preset"); 1369 } 1370 } 1371 void KisPaintopBox::slotGuiChangedCurrentPreset() // Called only when UI is changed and not when preset is changed 1372 { 1373 KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); 1374 1375 { 1376 /** 1377 * Here we postpone all the settings updates events until the entire writing 1378 * operation will be finished. As soon as it is finished, the updates will be 1379 * emitted happily (if there were any). 1380 */ 1381 1382 KisPaintOpPreset::UpdatedPostponer postponer(preset); 1383 1384 1385 QStringList preserveProperties; 1386 preserveProperties << "lodUserAllowed"; 1387 preserveProperties << "lodSizeThreshold"; 1388 1389 // clear all the properties before dumping the stuff into the preset, 1390 // some of the options add the values incrementally 1391 // (e.g. KisPaintOpUtils::RequiredBrushFilesListTag), therefore they 1392 // may add up if we pass the same preset multiple times 1393 preset->settings()->resetSettings(preserveProperties); 1394 1395 m_optionWidget->writeConfigurationSafe(const_cast<KisPaintOpSettings*>(preset->settings().data())); 1396 } 1397 1398 // we should also update the preset strip to update the status of the "dirty" mark 1399 m_presetsEditor->resourceSelected(m_resourceProvider->currentPreset()); 1400 1401 // TODO!!!!!!!! 1402 //m_presetsPopup->updateViewSettings(); 1403 } 1404 void KisPaintopBox::slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP p) 1405 { 1406 1407 QMapIterator<QString, QVariant> i(p->getProperties()); 1408 while (i.hasNext()) { 1409 i.next(); 1410 m_resourceProvider->currentPreset()->settings()->setProperty(i.key(), QVariant(i.value())); 1411 if (m_resourceProvider->currentPreset()->settings()->hasProperty(i.key() + "_previous")) { 1412 m_resourceProvider->currentPreset()->settings()->removeProperty(i.key() + "_previous"); 1413 } 1414 1415 } 1416 slotGuiChangedCurrentPreset(); 1417 1418 } 1419 1420 void KisPaintopBox::slotDropLockedOption(KisPropertiesConfigurationSP p) 1421 { 1422 KisSignalsBlocker blocker(m_optionWidget); 1423 KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); 1424 1425 { 1426 KisDirtyStateSaver<KisPaintOpPresetSP> dirtySaver(preset); 1427 1428 QMapIterator<QString, QVariant> i(p->getProperties()); 1429 while (i.hasNext()) { 1430 i.next(); 1431 if (preset->settings()->hasProperty(i.key() + "_previous")) { 1432 preset->settings()->setProperty(i.key(), preset->settings()->getProperty(i.key() + "_previous")); 1433 preset->settings()->removeProperty(i.key() + "_previous"); 1434 } 1435 1436 } 1437 } 1438 1439 } 1440 void KisPaintopBox::slotDirtyPresetToggled(bool value) 1441 { 1442 if (!value) { 1443 slotReloadPreset(); 1444 m_presetsEditor->resourceSelected(m_resourceProvider->currentPreset()); 1445 m_presetsEditor->updateViewSettings(); 1446 } 1447 m_dirtyPresetsEnabled = value; 1448 KisConfig cfg(false); 1449 cfg.setUseDirtyPresets(m_dirtyPresetsEnabled); 1450 } 1451 1452 void KisPaintopBox::slotEraserBrushSizeToggled(bool value) 1453 { 1454 m_eraserBrushSizeEnabled = value; 1455 KisConfig cfg(false); 1456 cfg.setUseEraserBrushSize(m_eraserBrushSizeEnabled); 1457 } 1458 1459 void KisPaintopBox::slotEraserBrushOpacityToggled(bool value) 1460 { 1461 m_eraserBrushOpacityEnabled = value; 1462 KisConfig cfg(false); 1463 cfg.setUseEraserBrushOpacity(m_eraserBrushOpacityEnabled); 1464 } 1465 1466 void KisPaintopBox::slotUpdateSelectionIcon() 1467 { 1468 m_hMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-horizontal")); 1469 m_vMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-vertical")); 1470 1471 KisConfig cfg(true); 1472 if (!cfg.toolOptionsInDocker() && m_toolOptionsPopupButton) { 1473 m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("configure")); 1474 } 1475 1476 m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01")); 1477 m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02")); 1478 m_workspaceWidget->setIcon(KisIconUtils::loadIcon("workspace-chooser")); 1479 1480 m_eraseAction->setIcon(KisIconUtils::loadIcon("draw-eraser")); 1481 m_reloadAction->setIcon(KisIconUtils::loadIcon("reload-preset")); 1482 1483 if (m_disablePressureAction->isChecked()) { 1484 m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure")); 1485 } else { 1486 m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure_locked")); 1487 } 1488 } 1489 1490 void KisPaintopBox::slotLockXMirrorToggle(bool toggleLock) { 1491 m_resourceProvider->setMirrorHorizontalLock(toggleLock); 1492 } 1493 1494 void KisPaintopBox::slotLockYMirrorToggle(bool toggleLock) { 1495 m_resourceProvider->setMirrorVerticalLock(toggleLock); 1496 } 1497 1498 void KisPaintopBox::slotHideDecorationMirrorX(bool toggled) { 1499 m_resourceProvider->setMirrorHorizontalHideDecorations(toggled); 1500 } 1501 1502 void KisPaintopBox::slotHideDecorationMirrorY(bool toggled) { 1503 m_resourceProvider->setMirrorVerticalHideDecorations(toggled); 1504 } 1505 1506 void KisPaintopBox::slotMoveToCenterMirrorX() { 1507 m_resourceProvider->mirrorHorizontalMoveCanvasToCenter(); 1508 } 1509 1510 void KisPaintopBox::slotMoveToCenterMirrorY() { 1511 m_resourceProvider->mirrorVerticalMoveCanvasToCenter(); 1512 } 1513 1514 void KisPaintopBox::findDefaultPresets() 1515 { 1516 m_eraserName = "a) Eraser Circle"; 1517 m_defaultPresetName = "b) Basic-5 Size Opacity"; 1518 }