diff --git a/libs/ui/kis_paintop_box.cc b/libs/ui/kis_paintop_box.cc index 858b72ad96..7ad79560b4 100644 --- a/libs/ui/kis_paintop_box.cc +++ b/libs/ui/kis_paintop_box.cc @@ -1,1386 +1,1390 @@ /* * 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 * Copyright (c) 2014 Mohit Goyal * * 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 #include #include #include #include #include #include "kis_canvas2.h" #include "kis_node_manager.h" #include "KisViewManager.h" #include "kis_canvas_resource_provider.h" #include "KisResourceServerProvider.h" #include "kis_favorite_resource_manager.h" #include "kis_config.h" #include "kis_popup_button.h" #include "widgets/kis_iconwidget.h" #include "widgets/kis_tool_options_popup.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" #include "kis_signals_blocker.h" #include "kis_action_manager.h" #include "KisHighlightedToolButton.h" KisPaintopBox::KisPaintopBox(KisViewManager *view, QWidget *parent, const char *name) : QWidget(parent) , m_resourceProvider(view->canvasResourceProvider()) , m_optionWidget(0) , m_toolOptionsPopupButton(0) , m_brushEditorPopupButton(0) , m_presetSelectorPopupButton(0) , m_toolOptionsPopup(0) , m_viewManager(view) , m_previousNode(0) , m_currTabletToolID(KoInputDevice::invalid()) , m_presetsEnabled(true) , m_blockUpdate(false) , m_dirtyPresetsEnabled(false) , m_eraserBrushSizeEnabled(false) , m_eraserBrushOpacityEnabled(false) { Q_ASSERT(view != 0); setObjectName(name); KisConfig cfg(true); m_dirtyPresetsEnabled = cfg.useDirtyPresets(); m_eraserBrushSizeEnabled = cfg.useEraserBrushSize(); m_eraserBrushOpacityEnabled = cfg.useEraserBrushOpacity(); KAcceleratorManager::setNoAccel(this); setWindowTitle(i18n("Painter's Toolchest")); m_favoriteResourceManager = new KisFavoriteResourceManager(this); KConfigGroup grp = KSharedConfig::openConfig()->group("krita").group("Toolbar BrushesAndStuff"); int iconsize = grp.readEntry("IconSize", 32); if (!cfg.toolOptionsInDocker()) { m_toolOptionsPopupButton = new KisPopupButton(this); m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("configure")); m_toolOptionsPopupButton->setToolTip(i18n("Tool Settings")); m_toolOptionsPopupButton->setFixedSize(iconsize, iconsize); } m_brushEditorPopupButton = new KisIconWidget(this); m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02")); m_brushEditorPopupButton->setToolTip(i18n("Edit brush settings")); m_brushEditorPopupButton->setFixedSize(iconsize, iconsize); m_presetSelectorPopupButton = new KisPopupButton(this); m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01")); m_presetSelectorPopupButton->setToolTip(i18n("Choose brush preset")); m_presetSelectorPopupButton->setFixedSize(iconsize, iconsize); m_eraseModeButton = new KisHighlightedToolButton(this); m_eraseModeButton->setFixedSize(iconsize, iconsize); m_eraseModeButton->setCheckable(true); m_eraseAction = m_viewManager->actionManager()->createAction("erase_action"); m_eraseModeButton->setDefaultAction(m_eraseAction); m_reloadButton = new QToolButton(this); m_reloadButton->setFixedSize(iconsize, iconsize); m_reloadAction = m_viewManager->actionManager()->createAction("reload_preset_action"); m_reloadButton->setDefaultAction(m_reloadAction); m_alphaLockButton = new KisHighlightedToolButton(this); m_alphaLockButton->setFixedSize(iconsize, iconsize); m_alphaLockButton->setCheckable(true); KisAction* alphaLockAction = m_viewManager->actionManager()->createAction("preserve_alpha"); m_alphaLockButton->setDefaultAction(alphaLockAction); // horizontal and vertical mirror toolbar buttons // mirror tool options for the X Mirror QMenu *toolbarMenuXMirror = new QMenu(); hideCanvasDecorationsX = m_viewManager->actionManager()->createAction("mirrorX-hideDecorations"); toolbarMenuXMirror->addAction(hideCanvasDecorationsX); lockActionX = m_viewManager->actionManager()->createAction("mirrorX-lock"); toolbarMenuXMirror->addAction(lockActionX); moveToCenterActionX = m_viewManager->actionManager()->createAction("mirrorX-moveToCenter"); toolbarMenuXMirror->addAction(moveToCenterActionX); // mirror tool options for the Y Mirror QMenu *toolbarMenuYMirror = new QMenu(); hideCanvasDecorationsY = m_viewManager->actionManager()->createAction("mirrorY-hideDecorations"); toolbarMenuYMirror->addAction(hideCanvasDecorationsY); lockActionY = m_viewManager->actionManager()->createAction("mirrorY-lock"); toolbarMenuYMirror->addAction(lockActionY); moveToCenterActionY = m_viewManager->actionManager()->createAction("mirrorY-moveToCenter"); toolbarMenuYMirror->addAction(moveToCenterActionY); // create horizontal and vertical mirror buttons m_hMirrorButton = new KisHighlightedToolButton(this); int menuPadding = 10; m_hMirrorButton->setFixedSize(iconsize + menuPadding, iconsize); m_hMirrorButton->setCheckable(true); m_hMirrorAction = m_viewManager->actionManager()->createAction("hmirror_action"); m_hMirrorButton->setDefaultAction(m_hMirrorAction); m_hMirrorButton->setMenu(toolbarMenuXMirror); m_hMirrorButton->setPopupMode(QToolButton::MenuButtonPopup); m_vMirrorButton = new KisHighlightedToolButton(this); m_vMirrorButton->setFixedSize(iconsize + menuPadding, iconsize); m_vMirrorButton->setCheckable(true); m_vMirrorAction = m_viewManager->actionManager()->createAction("vmirror_action"); m_vMirrorButton->setDefaultAction(m_vMirrorAction); m_vMirrorButton->setMenu(toolbarMenuYMirror); m_vMirrorButton->setPopupMode(QToolButton::MenuButtonPopup); // add connections for horizontal and mirrror buttons connect(lockActionX, SIGNAL(toggled(bool)), this, SLOT(slotLockXMirrorToggle(bool))); connect(lockActionY, SIGNAL(toggled(bool)), this, SLOT(slotLockYMirrorToggle(bool))); connect(moveToCenterActionX, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorX())); connect(moveToCenterActionY, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorY())); connect(hideCanvasDecorationsX, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorX(bool))); connect(hideCanvasDecorationsY, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorY(bool))); const bool sliderLabels = cfg.sliderLabels(); int sliderWidth; if (sliderLabels) { sliderWidth = 150 * logicalDpiX() / 96; } else { sliderWidth = 120 * logicalDpiX() / 96; } for (int i = 0; i < 3; ++i) { m_sliderChooser[i] = new KisWidgetChooser(i + 1); KisDoubleSliderSpinBox* slOpacity; KisDoubleSliderSpinBox* slFlow; KisDoubleSliderSpinBox* slSize; if (sliderLabels) { slOpacity = m_sliderChooser[i]->addWidget("opacity"); slFlow = m_sliderChooser[i]->addWidget("flow"); slSize = m_sliderChooser[i]->addWidget("size"); slOpacity->setPrefix(QString("%1 ").arg(i18n("Opacity:"))); slFlow->setPrefix(QString("%1 ").arg(i18n("Flow:"))); slSize->setPrefix(QString("%1 ").arg(i18n("Size:"))); } else { slOpacity = m_sliderChooser[i]->addWidget("opacity", i18n("Opacity:")); slFlow = m_sliderChooser[i]->addWidget("flow", i18n("Flow:")); slSize = m_sliderChooser[i]->addWidget("size", i18n("Size:")); } slOpacity->setRange(0, 100, 0); slOpacity->setValue(100); slOpacity->setSingleStep(5); slOpacity->setSuffix(i18n("%")); slOpacity->setMinimumWidth(qMax(sliderWidth, slOpacity->sizeHint().width())); slOpacity->setFixedHeight(iconsize); slOpacity->setBlockUpdateSignalOnDrag(true); slFlow->setRange(0, 100, 0); slFlow->setValue(100); slFlow->setSingleStep(5); slFlow->setSuffix(i18n("%")); slFlow->setMinimumWidth(qMax(sliderWidth, slFlow->sizeHint().width())); slFlow->setFixedHeight(iconsize); slFlow->setBlockUpdateSignalOnDrag(true); slSize->setRange(0.01, cfg.readEntry("maximumBrushSize", 1000), 2); slSize->setValue(100); slSize->setSingleStep(1); slSize->setExponentRatio(3.0); slSize->setSuffix(i18n(" px")); slSize->setMinimumWidth(qMax(sliderWidth, slSize->sizeHint().width())); slSize->setFixedHeight(iconsize); slSize->setBlockUpdateSignalOnDrag(true); m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1)); } m_cmbCompositeOp = new KisCompositeOpComboBox(); m_cmbCompositeOp->setFixedHeight(iconsize); Q_FOREACH (KisAction * a, m_cmbCompositeOp->blendmodeActions()) { m_viewManager->actionManager()->addAction(a->text(), a); } m_workspaceWidget = new KisPopupButton(this); m_workspaceWidget->setIcon(KisIconUtils::loadIcon("view-choose")); m_workspaceWidget->setToolTip(i18n("Choose workspace")); m_workspaceWidget->setFixedSize(iconsize, iconsize); m_workspaceWidget->setPopupWidget(new KisWorkspaceChooser(view)); QHBoxLayout* baseLayout = new QHBoxLayout(this); m_paintopWidget = new QWidget(this); baseLayout->addWidget(m_paintopWidget); baseLayout->setSpacing(4); baseLayout->setContentsMargins(0, 0, 0, 0); m_layout = new QHBoxLayout(m_paintopWidget); if (!cfg.toolOptionsInDocker()) { m_layout->addWidget(m_toolOptionsPopupButton); } m_layout->addWidget(m_brushEditorPopupButton); m_layout->addWidget(m_presetSelectorPopupButton); m_layout->setSpacing(4); m_layout->setContentsMargins(0, 0, 0, 0); QWidget* compositeActions = new QWidget(this); QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions); compositeLayout->addWidget(m_cmbCompositeOp); compositeLayout->addWidget(m_eraseModeButton); compositeLayout->addWidget(m_alphaLockButton); compositeLayout->setSpacing(4); compositeLayout->setContentsMargins(0, 0, 0, 0); compositeLayout->addWidget(m_reloadButton); QWidgetAction * action; action = new QWidgetAction(this); view->actionCollection()->addAction("composite_actions", action); action->setText(i18n("Brush composite")); action->setDefaultWidget(compositeActions); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("brushslider1", action); view->actionCollection()->addAction("brushslider1", action); action->setDefaultWidget(m_sliderChooser[0]); connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget())); connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[0], SLOT(updateThemedIcons())); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("brushslider2", action); view->actionCollection()->addAction("brushslider2", action); action->setDefaultWidget(m_sliderChooser[1]); connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget())); connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[1], SLOT(updateThemedIcons())); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("brushslider3", action); view->actionCollection()->addAction("brushslider3", action); action->setDefaultWidget(m_sliderChooser[2]); connect(action, SIGNAL(triggered()), m_sliderChooser[2], SLOT(showPopupWidget())); - connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[2], SLOT(updateThemedIcons())); + connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[2], SLOT(updateThemedIcons())); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("next_favorite_preset", action); view->actionCollection()->addAction("next_favorite_preset", action); connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset())); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("previous_favorite_preset", action); view->actionCollection()->addAction("previous_favorite_preset", action); connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset())); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("previous_preset", action); view->actionCollection()->addAction("previous_preset", action); connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset())); if (!cfg.toolOptionsInDocker()) { action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("show_tool_options", action); view->actionCollection()->addAction("show_tool_options", action); connect(action, SIGNAL(triggered()), m_toolOptionsPopupButton, SLOT(showPopupWidget())); } action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("show_brush_editor", action); view->actionCollection()->addAction("show_brush_editor", action); connect(action, SIGNAL(triggered()), m_brushEditorPopupButton, SLOT(showPopupWidget())); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("show_brush_presets", action); view->actionCollection()->addAction("show_brush_presets", action); connect(action, SIGNAL(triggered()), m_presetSelectorPopupButton, SLOT(showPopupWidget())); QWidget* mirrorActions = new QWidget(this); QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions); mirrorLayout->addWidget(m_hMirrorButton); mirrorLayout->addWidget(m_vMirrorButton); mirrorLayout->setSpacing(4); mirrorLayout->setContentsMargins(0, 0, 0, 0); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction("mirror_actions", action); action->setDefaultWidget(mirrorActions); view->actionCollection()->addAction("mirror_actions", action); action = new QWidgetAction(this); KisActionRegistry::instance()->propertizeAction(ResourceType::Workspaces, action); view->actionCollection()->addAction(ResourceType::Workspaces, action); action->setDefaultWidget(m_workspaceWidget); if (!cfg.toolOptionsInDocker()) { m_toolOptionsPopup = new KisToolOptionsPopup(); m_toolOptionsPopupButton->setPopupWidget(m_toolOptionsPopup); m_toolOptionsPopup->switchDetached(false); } m_savePresetWidget = new KisPresetSaveWidget(this); m_presetsPopup = new KisPaintOpPresetsPopup(m_resourceProvider, m_favoriteResourceManager, m_savePresetWidget); m_brushEditorPopupButton->setPopupWidget(m_presetsPopup); m_presetsPopup->parentWidget()->setWindowTitle(i18n("Brush Editor")); connect(m_presetsPopup, SIGNAL(brushEditorShown()), SLOT(slotUpdateOptionsWidgetPopup())); connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_presetsPopup, SLOT(updateThemedIcons())); m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup(); m_presetsChooserPopup->setMinimumHeight(550); m_presetsChooserPopup->setMinimumWidth(450); m_presetSelectorPopupButton->setPopupWidget(m_presetsChooserPopup); m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); slotNodeChanged(view->activeNode()); // Get all the paintops QList keys = KisPaintOpRegistry::instance()->keys(); QList factoryList; Q_FOREACH (const QString & paintopId, keys) { factoryList.append(KisPaintOpRegistry::instance()->get(paintopId)); } m_presetsPopup->setPaintOpList(factoryList); connect(m_presetsPopup , SIGNAL(paintopActivated(QString)) , SLOT(slotSetPaintop(QString))); connect(m_presetsPopup , SIGNAL(defaultPresetClicked()) , SLOT(slotSetupDefaultPreset())); connect(m_presetsPopup , SIGNAL(signalResourceSelected(KoResourceSP )), SLOT(resourceSelected(KoResourceSP ))); connect(m_presetsPopup , SIGNAL(reloadPresetClicked()) , SLOT(slotReloadPreset())); connect(m_presetsPopup , SIGNAL(dirtyPresetToggled(bool)) , SLOT(slotDirtyPresetToggled(bool))); connect(m_presetsPopup , SIGNAL(eraserBrushSizeToggled(bool)) , SLOT(slotEraserBrushSizeToggled(bool))); connect(m_presetsPopup , SIGNAL(eraserBrushOpacityToggled(bool)) , SLOT(slotEraserBrushOpacityToggled(bool))); connect(m_presetsPopup, SIGNAL(createPresetFromScratch(QString)), this, SLOT(slotCreatePresetFromScratch(QString))); connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResourceSP )) , SLOT(resourceSelected(KoResourceSP ))); connect(m_presetsChooserPopup, SIGNAL(resourceClicked(KoResourceSP )) , SLOT(resourceSelected(KoResourceSP ))); connect(m_resourceProvider , SIGNAL(sigNodeChanged(KisNodeSP)) , SLOT(slotNodeChanged(KisNodeSP))); connect(m_cmbCompositeOp , SIGNAL(currentIndexChanged(int)) , SLOT(slotSetCompositeMode(int))); connect(m_eraseAction , SIGNAL(toggled(bool)) , SLOT(slotToggleEraseMode(bool))); connect(alphaLockAction , SIGNAL(toggled(bool)) , SLOT(slotToggleAlphaLockMode(bool))); m_disablePressureAction = m_viewManager->actionManager()->createAction("disable_pressure"); connect(m_disablePressureAction , SIGNAL(toggled(bool)) , SLOT(slotDisablePressureMode(bool))); m_disablePressureAction->setChecked(true); connect(m_hMirrorAction , SIGNAL(toggled(bool)) , SLOT(slotHorizontalMirrorChanged(bool))); connect(m_vMirrorAction , SIGNAL(toggled(bool)) , SLOT(slotVerticalMirrorChanged(bool))); connect(m_reloadAction , SIGNAL(triggered()) , SLOT(slotReloadPreset())); 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())); connect(m_sliderChooser[2]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); connect(m_sliderChooser[2]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); connect(m_sliderChooser[2]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); //Needed to connect canvas to favorite resource manager connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), SLOT(slotUnsetEraseMode())); connect(m_resourceProvider, SIGNAL(sigFGColorUsed(KoColor)), m_favoriteResourceManager, SLOT(slotAddRecentColor(KoColor))); connect(m_resourceProvider, SIGNAL(sigFGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotChangeFGColorSelector(KoColor))); connect(m_resourceProvider, SIGNAL(sigBGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotSetBGColor(KoColor))); // cold initialization m_favoriteResourceManager->slotChangeFGColorSelector(m_resourceProvider->fgColor()); m_favoriteResourceManager->slotSetBGColor(m_resourceProvider->bgColor()); connect(m_favoriteResourceManager, SIGNAL(sigSetFGColor(KoColor)), m_resourceProvider, SLOT(slotSetFGColor(KoColor))); connect(m_favoriteResourceManager, SIGNAL(sigSetBGColor(KoColor)), m_resourceProvider, SLOT(slotSetBGColor(KoColor))); connect(m_favoriteResourceManager, SIGNAL(sigEnableChangeColor(bool)), m_resourceProvider, SLOT(slotResetEnableFGChange(bool))); connect(view->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateSelectionIcon())); connect(m_resourceProvider->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), this, SLOT(slotCanvasResourceChanged(int,QVariant))); slotInputDeviceChanged(KoToolManager::instance()->currentInputDevice()); - KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); - m_eraserName = "eraser_circle"; - m_defaultPresetName = "basic_tip_default"; - bool foundEraser = false; - bool foundTip = false; - for (int i = 0; i < rserver->resourceCount(); i++) { - - KisPaintOpPresetSP resource = rserver->resources()[i]; - - if (resource->name().toLower().contains("eraser_circle")) { - m_eraserName = resource->name(); - foundEraser = true; - } - else if (foundEraser == false && (resource->name().toLower().contains("eraser") || - resource->filename().toLower().contains("eraser"))) { - m_eraserName = resource->name(); - foundEraser = true; - } - - if (resource->name().toLower().contains("basic_tip_default")) { - m_defaultPresetName = resource->name(); - foundTip = true; - } - else if (foundTip == false && (resource->name().toLower().contains("default") || - resource->filename().toLower().contains("default"))) { - m_defaultPresetName = resource->name(); - foundTip = true; - } - } + findDefaultPresets(); } + KisPaintopBox::~KisPaintopBox() { KisConfig cfg(false); QMapIterator iter(m_tabletToolMap); while (iter.hasNext()) { iter.next(); if ((iter.key().pointer) == QTabletEvent::Eraser) { cfg.writeEntry(QString("LastEraser") , iter.value().preset->name()); } else { cfg.writeEntry(QString("LastPreset"), iter.value().preset->name()); } } // Do not delete the widget, since it is global to the application, not owned by the view m_presetsPopup->setPaintOpSettingsWidget(0); qDeleteAll(m_paintopOptionWidgets); delete m_favoriteResourceManager; for (int i = 0; i < 3; ++i) { delete m_sliderChooser[i]; } } void KisPaintopBox::restoreResource(KoResourceSP resource) { KisPaintOpPresetSP preset = resource.dynamicCast(); if (preset) { setCurrentPaintop(preset); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } void KisPaintopBox::newOptionWidgets(const QList > &optionWidgetList) { if (m_toolOptionsPopup) { m_toolOptionsPopup->newOptionWidgets(optionWidgetList); } } void KisPaintopBox::resourceSelected(KoResourceSP resource) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_optionWidget); m_presetsPopup->setCreatingBrushFromScratch(false); // show normal UI elements when we are not creating -// qDebug() << ">>>>>>>>>>>>>>>" << resource -// << (resource ? resource->name() : "") -// << (resource ? QString("%1").arg(resource->valid()) : "") -// << (resource ? QString("%1").arg(resource->filename()) : ""); + // qDebug() << ">>>>>>>>>>>>>>>" << resource + // << (resource ? resource->name() : "") + // << (resource ? QString("%1").arg(resource->valid()) : "") + // << (resource ? QString("%1").arg(resource->filename()) : ""); KisPaintOpPresetSP preset = resource.dynamicCast(); if (preset && preset->valid() && preset != m_resourceProvider->currentPreset()) { qWarning() << "Preset reloading if presets are dirty is broken"; -// if (!preset->settings()->isLoadable()) { -// return; -// } -// if (!m_dirtyPresetsEnabled) { -// KisSignalsBlocker blocker(m_optionWidget); -// Q_UNUSED(blocker) -// if (!preset->load()) { -// qWarning() << "failed to load the preset."; -// } -// } + // if (!preset->settings()->isLoadable()) { + // return; + // } + // if (!m_dirtyPresetsEnabled) { + // KisSignalsBlocker blocker(m_optionWidget); + // Q_UNUSED(blocker) + // if (!preset->load()) { + // qWarning() << "failed to load the preset."; + // } + // } dbgResources << "resourceSelected: preset" << preset << (preset ? QString("%1").arg(preset->valid()) : ""); setCurrentPaintop(preset); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } void KisPaintopBox::setCurrentPaintop(const KoID& paintop) { KisPaintOpPresetSP preset = activePreset(paintop); Q_ASSERT(preset && preset->settings()); //qDebug() << "setCurrentPaintop();" << paintop << preset; setCurrentPaintop(preset); } void KisPaintopBox::setCurrentPaintop(KisPaintOpPresetSP preset) { //qDebug() << "setCurrentPaintop(); " << preset->name(); if (preset == m_resourceProvider->currentPreset()) { if (preset == m_tabletToolMap[m_currTabletToolID].preset) { return; } } Q_ASSERT(preset); const KoID& paintop = preset->paintOp(); m_presetConnections.clear(); if (m_resourceProvider->currentPreset()) { m_resourceProvider->setPreviousPaintOpPreset(m_resourceProvider->currentPreset()); if (m_optionWidget) { m_optionWidget->hide(); } } if (!m_paintopOptionWidgets.contains(paintop)) m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createConfigWidget(this); m_optionWidget = m_paintopOptionWidgets[paintop]; KisSignalsBlocker b(m_optionWidget); preset->setOptionsWidget(m_optionWidget); m_optionWidget->setImage(m_viewManager->image()); m_optionWidget->setNode(m_viewManager->activeNode()); m_presetsPopup->setPaintOpSettingsWidget(m_optionWidget); m_resourceProvider->setPaintOpPreset(preset); Q_ASSERT(m_optionWidget && m_presetSelectorPopupButton); m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotGuiChangedCurrentPreset())); m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfigurationSP)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP))); m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfigurationSP)), this, SLOT(slotDropLockedOption(KisPropertiesConfigurationSP))); // load the current brush engine icon for the brush editor toolbar button m_brushEditorPopupButton->setThumbnail(preset->image()); m_presetsPopup->setCurrentPaintOpId(paintop.id()); ////qDebug() << "\tsetting the new preset for" << m_currTabletToolID.uniqueID << "to" << preset->name(); m_paintOpPresetMap[m_resourceProvider->currentPreset()->paintOp()] = preset; m_tabletToolMap[m_currTabletToolID].preset = preset; m_tabletToolMap[m_currTabletToolID].paintOpID = preset->paintOp(); if (m_presetsPopup->currentPaintOpId() != paintop.id()) { // Must change the paintop as the current one is not supported // by the new colorspace. dbgKrita << "current paintop " << paintop.name() << " was not set, not supported by colorspace"; } m_currCompositeOpID = preset->settings()->paintOpCompositeOp(); updateCompositeOp(m_currCompositeOpID); } void KisPaintopBox::slotUpdateOptionsWidgetPopup() { KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); // This happens when we have a new brush engine for which no default preset exists yet. if (!preset) return; KIS_SAFE_ASSERT_RECOVER_RETURN(preset); KIS_SAFE_ASSERT_RECOVER_RETURN(m_optionWidget); m_optionWidget->setConfigurationSafe(preset->settings()); m_presetsPopup->resourceSelected(preset); m_presetsPopup->updateViewSettings(); // the m_viewManager->image() is set earlier, but the reference will be missing when the stamp button is pressed // need to later do some research on how and when we should be using weak shared pointers (WSP) that creates this situation m_optionWidget->setImage(m_viewManager->image()); } KisPaintOpPresetSP KisPaintopBox::defaultPreset(const KoID& paintOp) { QString defaultName = paintOp.id() + ".kpp"; QString path = KoResourcePaths::findResource("kis_defaultpresets", defaultName); KisPaintOpPresetSP preset(new KisPaintOpPreset(path)); if (!preset->load()) { preset = KisPaintOpRegistry::instance()->defaultPreset(paintOp); } 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) { if (!m_optionWidget) return; KisSignalsBlocker blocker(m_optionWidget); KisNodeSP node = m_resourceProvider->currentNode(); if (node && node->paintDevice()) { if (!node->paintDevice()->colorSpace()->hasCompositeOp(compositeOpID)) compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); { KisSignalsBlocker b1(m_cmbCompositeOp); m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID)); } if (compositeOpID != m_currCompositeOpID) { m_currCompositeOpID = compositeOpID; } if (compositeOpID == COMPOSITE_ERASE || m_resourceProvider->eraserMode()) { m_eraseModeButton->setChecked(true); } else { m_eraseModeButton->setChecked(false); } } else if (!node) { KisSignalsBlocker b1(m_cmbCompositeOp); m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID)); 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_presetSelectorPopupButton->setEnabled(flags & ENABLE_PRESETS); m_brushEditorPopupButton->setEnabled(flags & ENABLE_PRESETS); } for (int i = 0; i < 3; ++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 < 3; ++i) { KisDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget(sliderID); KisSignalsBlocker b(slider); if (sliderID == "opacity" || sliderID == "flow") { // opacity and flows UI stored at 0-100% slider->setValue(value*100); } else { slider->setValue(value); // brush size } } } void KisPaintopBox::slotSetPaintop(const QString& paintOpId) { if (KisPaintOpRegistry::instance()->get(paintOpId) != 0) { KoID id(paintOpId, KisPaintOpRegistry::instance()->get(paintOpId)->name()); //qDebug() << "slotsetpaintop" << id; setCurrentPaintop(id); } } void KisPaintopBox::slotInputDeviceChanged(const KoInputDevice& inputDevice) { TabletToolMap::iterator toolData = m_tabletToolMap.find(inputDevice); //qDebug() << "slotInputDeviceChanged()" << inputDevice.device() << inputDevice.uniqueTabletId(); m_currTabletToolID = TabletToolID(inputDevice); if (toolData == m_tabletToolMap.end()) { KisConfig cfg(true); KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); KisPaintOpPresetSP preset; if (inputDevice.pointer() == QTabletEvent::Eraser) { preset = rserver->resourceByName(cfg.readEntry(QString("LastEraser_%1").arg(inputDevice.uniqueTabletId()), m_eraserName)); } else { preset = rserver->resourceByName(cfg.readEntry(QString("LastPreset_%1").arg(inputDevice.uniqueTabletId()), m_defaultPresetName)); //if (preset) - //qDebug() << "found stored preset " << preset->name() << "for" << inputDevice.uniqueTabletId(); + //qDebug() << "found stored preset " << preset->name() << "for" << inputDevice.uniqueTabletId(); //else - //qDebug() << "no preset found for" << inputDevice.uniqueTabletId(); + //qDebug() << "no preset found for" << inputDevice.uniqueTabletId(); } if (!preset) { preset = rserver->resourceByName(m_defaultPresetName); } if (preset) { //qDebug() << "inputdevicechanged 1" << preset; setCurrentPaintop(preset); } } else { if (toolData->preset) { //qDebug() << "inputdevicechanged 2" << toolData->preset; setCurrentPaintop(toolData->preset); } else { //qDebug() << "inputdevicechanged 3" << toolData->paintOpID; setCurrentPaintop(toolData->paintOpID); } } } void KisPaintopBox::slotCreatePresetFromScratch(QString paintop) { //First try to select an available default preset for that engine. If it doesn't exist, then //manually set the engine to use a new preset. KoID id(paintop, KisPaintOpRegistry::instance()->get(paintop)->name()); KisPaintOpPresetSP preset = defaultPreset(id); slotSetPaintop(paintop); // change the paintop settings area and update the UI if (!preset) { m_presetsPopup->setCreatingBrushFromScratch(true); // disable UI elements while creating from scratch preset = m_resourceProvider->currentPreset(); } else { m_resourceProvider->setPaintOpPreset(preset); preset->setOptionsWidget(m_optionWidget); } m_presetsPopup->resourceSelected(preset); // this helps update the UI on the brush editor } void KisPaintopBox::slotCanvasResourceChanged(int key, const QVariant &value) { if (m_viewManager) { sender()->blockSignals(true); KisPaintOpPresetSP preset = m_viewManager->canvasResourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); if (preset && m_resourceProvider->currentPreset()->name() != preset->name()) { QString compositeOp = preset->settings()->getString("CompositeOp"); updateCompositeOp(compositeOp); resourceSelected(preset); } /** * Update currently selected preset in both the popup widgets */ m_presetsChooserPopup->canvasResourceChanged(preset); m_presetsPopup->currentPresetChanged(preset); if (key == KisCanvasResourceProvider::CurrentCompositeOp) { if (m_resourceProvider->currentCompositeOp() != m_currCompositeOpID) { updateCompositeOp(m_resourceProvider->currentCompositeOp()); } } if (key == KisCanvasResourceProvider::Size) { setSliderValue("size", m_resourceProvider->size()); } if (key == KisCanvasResourceProvider::Opacity) { setSliderValue("opacity", m_resourceProvider->opacity()); } if (key == KisCanvasResourceProvider::Flow) { setSliderValue("flow", m_resourceProvider->flow()); } if (key == KisCanvasResourceProvider::EraserMode) { m_eraseAction->setChecked(value.toBool()); } if (key == KisCanvasResourceProvider::DisablePressure) { m_disablePressureAction->setChecked(value.toBool()); } if (key == KisCanvasResourceProvider::MirrorHorizontal) { m_hMirrorAction->setChecked(value.toBool()); } if (key == KisCanvasResourceProvider::MirrorVertical) { m_vMirrorAction->setChecked(value.toBool()); } sender()->blockSignals(false); } } void KisPaintopBox::slotSetupDefaultPreset() { KisPaintOpPresetSP preset = defaultPreset(m_resourceProvider->currentPreset()->paintOp()); preset->setOptionsWidget(m_optionWidget); m_resourceProvider->setPaintOpPreset(preset); // tell the brush editor that the resource has changed // so it can update everything m_presetsPopup->resourceSelected(preset); } void KisPaintopBox::slotNodeChanged(const KisNodeSP node) { if (m_previousNode.isValid() && 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()); } if (m_optionWidget) { m_optionWidget->setNode(node); } } void KisPaintopBox::slotColorSpaceChanged(const KoColorSpace* colorSpace) { m_cmbCompositeOp->validate(colorSpace); } void KisPaintopBox::slotToggleEraseMode(bool checked) { const bool oldEraserMode = m_resourceProvider->eraserMode(); m_resourceProvider->setEraserMode(checked); if (oldEraserMode != checked && m_eraserBrushSizeEnabled) { const qreal currentSize = m_resourceProvider->size(); KisPaintOpSettingsSP settings = m_resourceProvider->currentPreset()->settings(); // remember brush size. set the eraser size to the normal brush size if not set if (checked) { settings->setSavedBrushSize(currentSize); if (qFuzzyIsNull(settings->savedEraserSize())) { settings->setSavedEraserSize(currentSize); } } else { settings->setSavedEraserSize(currentSize); if (qFuzzyIsNull(settings->savedBrushSize())) { settings->setSavedBrushSize(currentSize); } } //update value in UI (this is the main place the value is 'stored' in memory) qreal newSize = checked ? settings->savedEraserSize() : settings->savedBrushSize(); m_resourceProvider->setSize(newSize); } - if (oldEraserMode != checked && m_eraserBrushOpacityEnabled) { + if (oldEraserMode != checked && m_eraserBrushOpacityEnabled) { const qreal currentOpacity = m_resourceProvider->opacity(); KisPaintOpSettingsSP settings = m_resourceProvider->currentPreset()->settings(); // remember brush opacity. set the eraser opacity to the normal brush opacity if not set if (checked) { settings->setSavedBrushOpacity(currentOpacity); if (qFuzzyIsNull(settings->savedEraserOpacity())) { settings->setSavedEraserOpacity(currentOpacity); } } else { settings->setSavedEraserOpacity(currentOpacity); if (qFuzzyIsNull(settings->savedBrushOpacity())) { settings->setSavedBrushOpacity(currentOpacity); } } //update value in UI (this is the main place the value is 'stored' in memory) qreal newOpacity = checked ? settings->savedEraserOpacity() : settings->savedBrushOpacity(); m_resourceProvider->setOpacity(newOpacity); } } void KisPaintopBox::slotSetCompositeMode(int index) { Q_UNUSED(index); QString compositeOp = m_cmbCompositeOp->selectedCompositeOp().id(); m_resourceProvider->setCurrentCompositeOp(compositeOp); } void KisPaintopBox::slotHorizontalMirrorChanged(bool value) { m_resourceProvider->setMirrorHorizontal(value); } void KisPaintopBox::slotVerticalMirrorChanged(bool value) { m_resourceProvider->setMirrorVertical(value); } void KisPaintopBox::sliderChanged(int n) { if (!m_optionWidget) // widget will not exist if the are no documents open return; KisSignalsBlocker blocker(m_optionWidget); // flow and opacity are shown as 0-100% on the UI, but their data is actually 0-1. Convert those two values // back for further work qreal opacity = m_sliderChooser[n]->getWidget("opacity")->value()/100; qreal flow = m_sliderChooser[n]->getWidget("flow")->value()/100; 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 won't work the other way // TODO: why?! m_resourceProvider->setSize(size); m_resourceProvider->setOpacity(opacity); m_resourceProvider->setFlow(flow); KisLockedPropertiesProxySP propertiesProxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(m_resourceProvider->currentPreset()->settings()); propertiesProxy->setProperty("OpacityValue", opacity); propertiesProxy->setProperty("FlowValue", flow); m_optionWidget->setConfigurationSafe(m_resourceProvider->currentPreset()->settings().data()); } else { m_resourceProvider->setOpacity(opacity); } m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset()); } void KisPaintopBox::slotSlider1Changed() { sliderChanged(0); } void KisPaintopBox::slotSlider2Changed() { sliderChanged(1); } void KisPaintopBox::slotSlider3Changed() { sliderChanged(2); } void KisPaintopBox::slotToolChanged(KoCanvasController* canvas, int toolId) { Q_UNUSED(canvas); Q_UNUSED(toolId); if (!m_viewManager->canvasBase()) return; QString id = KoToolManager::instance()->activeToolId(); KisTool* tool = dynamic_cast(KoToolManager::instance()->toolById(m_viewManager->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); if (!m_resourceProvider->currentPreset()) return; // block updates of avoid some over updating of the option widget m_blockUpdate = true; setSliderValue("size", m_resourceProvider->size()); { qreal opacity = m_resourceProvider->currentPreset()->settings()->paintOpOpacity(); m_resourceProvider->setOpacity(opacity); setSliderValue("opacity", opacity); setWidgetState(ENABLE_OPACITY); } { setSliderValue("flow", m_resourceProvider->currentPreset()->settings()->paintOpFlow()); setWidgetState(ENABLE_FLOW); } { updateCompositeOp(m_resourceProvider->currentPreset()->settings()->paintOpCompositeOp()); setWidgetState(ENABLE_COMPOSITEOP); } m_blockUpdate = false; m_presetsEnabled = true; } else { setWidgetState(DISABLE_PRESETS); m_presetsEnabled = false; } if (flags & KisTool::FLAG_USES_CUSTOM_SIZE) { setWidgetState(ENABLE_SIZE | ENABLE_FLOW); } else { setWidgetState(DISABLE_SIZE | DISABLE_FLOW); } } else setWidgetState(DISABLE_ALL); } void KisPaintopBox::slotPreviousFavoritePreset() { if (!m_favoriteResourceManager) return; QVector presets = m_favoriteResourceManager->favoritePresetList(); for (int i=0; i < presets.size(); ++i) { if (m_resourceProvider->currentPreset() && m_resourceProvider->currentPreset()->name() == presets[i]->name()) { if (i > 0) { m_favoriteResourceManager->slotChangeActivePaintop(i - 1); } else { m_favoriteResourceManager->slotChangeActivePaintop(m_favoriteResourceManager->numFavoritePresets() - 1); } //floating message should have least 2 lines, otherwise //preset thumbnail will be too small to distinguish //(because size of image on floating message depends on amount of lines in msg) m_viewManager->showFloatingMessage( - i18n("%1\nselected", - m_resourceProvider->currentPreset()->name()), - QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); + i18n("%1\nselected", + m_resourceProvider->currentPreset()->name()), + QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); return; } } } void KisPaintopBox::slotNextFavoritePreset() { if (!m_favoriteResourceManager) return; QVector presets = m_favoriteResourceManager->favoritePresetList(); for(int i = 0; i < presets.size(); ++i) { if (m_resourceProvider->currentPreset()->name() == presets[i]->name()) { if (i < m_favoriteResourceManager->numFavoritePresets() - 1) { m_favoriteResourceManager->slotChangeActivePaintop(i + 1); } else { m_favoriteResourceManager->slotChangeActivePaintop(0); } m_viewManager->showFloatingMessage( - i18n("%1\nselected", - m_resourceProvider->currentPreset()->name()), - QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); + i18n("%1\nselected", + m_resourceProvider->currentPreset()->name()), + QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); return; } } } void KisPaintopBox::slotSwitchToPreviousPreset() { if (m_resourceProvider->previousPreset()) { //qDebug() << "slotSwitchToPreviousPreset();" << m_resourceProvider->previousPreset(); setCurrentPaintop(m_resourceProvider->previousPreset()); m_viewManager->showFloatingMessage( - i18n("%1\nselected", - m_resourceProvider->currentPreset()->name()), - QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); + i18n("%1\nselected", + m_resourceProvider->currentPreset()->name()), + QIcon(QPixmap::fromImage(m_resourceProvider->currentPreset()->image()))); } } void KisPaintopBox::slotUnsetEraseMode() { m_eraseAction->setChecked(false); } void KisPaintopBox::slotToggleAlphaLockMode(bool checked) { if (checked) { m_alphaLockButton->actions()[0]->setIcon(KisIconUtils::loadIcon("transparency-locked")); } else { m_alphaLockButton->actions()[0]->setIcon(KisIconUtils::loadIcon("transparency-unlocked")); } m_resourceProvider->setGlobalAlphaLock(checked); } void KisPaintopBox::slotDisablePressureMode(bool checked) { if (checked) { m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure")); } else { m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure_locked")); } m_resourceProvider->setDisablePressure(checked); } void KisPaintopBox::slotReloadPreset() { KisSignalsBlocker blocker(m_optionWidget); // Here using the name and fetching the preset from the server was the only way the load was working. Otherwise it was not loading. KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); QSharedPointer preset = rserver->resourceByName(m_resourceProvider->currentPreset()->name()); if (preset) { preset->load(); } if (m_resourceProvider->currentPreset() != preset) { m_resourceProvider->setPaintOpPreset(preset); } else { /** * HACK ALERT: here we emit a private signal from the resource manager to * ensure that all the subscribers of resource-changed signal got the * notification. That is especially important for * KisPaintopTransformationConnector. See bug 392622. */ emit m_resourceProvider->resourceManager()->canvasResourceChanged( - KisCanvasResourceProvider::CurrentPaintOpPreset, - QVariant::fromValue(preset)); + KisCanvasResourceProvider::CurrentPaintOpPreset, + QVariant::fromValue(preset)); } } void KisPaintopBox::slotGuiChangedCurrentPreset() // Called only when UI is changed and not when preset is changed { KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); { /** * Here we postpone all the settings updates events until the entire writing * operation will be finished. As soon as it is finished, the updates will be * emitted happily (if there were any). */ KisPaintOpPreset::UpdatedPostponer postponer(preset); QStringList preserveProperties; preserveProperties << "lodUserAllowed"; preserveProperties << "lodSizeThreshold"; // clear all the properties before dumping the stuff into the preset, // some of the options add the values incrementally // (e.g. KisPaintOpUtils::RequiredBrushFilesListTag), therefore they // may add up if we pass the same preset multiple times preset->settings()->resetSettings(preserveProperties); m_optionWidget->writeConfigurationSafe(const_cast(preset->settings().data())); } // we should also update the preset strip to update the status of the "dirty" mark m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset()); // TODO!!!!!!!! //m_presetsPopup->updateViewSettings(); } void KisPaintopBox::slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP p) { QMapIterator i(p->getProperties()); while (i.hasNext()) { i.next(); m_resourceProvider->currentPreset()->settings()->setProperty(i.key(), QVariant(i.value())); if (m_resourceProvider->currentPreset()->settings()->hasProperty(i.key() + "_previous")) { m_resourceProvider->currentPreset()->settings()->removeProperty(i.key() + "_previous"); } } slotGuiChangedCurrentPreset(); } void KisPaintopBox::slotDropLockedOption(KisPropertiesConfigurationSP p) { KisSignalsBlocker blocker(m_optionWidget); KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); { KisResourceDirtyStateSaver dirtySaver(preset); QMapIterator i(p->getProperties()); while (i.hasNext()) { i.next(); if (preset->settings()->hasProperty(i.key() + "_previous")) { preset->settings()->setProperty(i.key(), preset->settings()->getProperty(i.key() + "_previous")); preset->settings()->removeProperty(i.key() + "_previous"); } } } } void KisPaintopBox::slotDirtyPresetToggled(bool value) { if (!value) { slotReloadPreset(); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset()); m_presetsPopup->updateViewSettings(); } m_dirtyPresetsEnabled = value; KisConfig cfg(false); cfg.setUseDirtyPresets(m_dirtyPresetsEnabled); } void KisPaintopBox::slotEraserBrushSizeToggled(bool value) { m_eraserBrushSizeEnabled = value; KisConfig cfg(false); cfg.setUseEraserBrushSize(m_eraserBrushSizeEnabled); } void KisPaintopBox::slotEraserBrushOpacityToggled(bool value) { m_eraserBrushOpacityEnabled = value; KisConfig cfg(false); cfg.setUseEraserBrushOpacity(m_eraserBrushOpacityEnabled); } void KisPaintopBox::slotUpdateSelectionIcon() { m_hMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-horizontal")); m_vMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-vertical")); KisConfig cfg(true); if (!cfg.toolOptionsInDocker() && m_toolOptionsPopupButton) { m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("configure")); } m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01")); m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02")); m_workspaceWidget->setIcon(KisIconUtils::loadIcon("view-choose")); m_eraseAction->setIcon(KisIconUtils::loadIcon("draw-eraser")); m_reloadAction->setIcon(KisIconUtils::loadIcon("view-refresh")); if (m_disablePressureAction->isChecked()) { m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure")); } else { m_disablePressureAction->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure_locked")); } } void KisPaintopBox::slotLockXMirrorToggle(bool toggleLock) { m_resourceProvider->setMirrorHorizontalLock(toggleLock); } void KisPaintopBox::slotLockYMirrorToggle(bool toggleLock) { m_resourceProvider->setMirrorVerticalLock(toggleLock); } void KisPaintopBox::slotHideDecorationMirrorX(bool toggled) { m_resourceProvider->setMirrorHorizontalHideDecorations(toggled); } void KisPaintopBox::slotHideDecorationMirrorY(bool toggled) { m_resourceProvider->setMirrorVerticalHideDecorations(toggled); } void KisPaintopBox::slotMoveToCenterMirrorX() { - m_resourceProvider->mirrorHorizontalMoveCanvasToCenter(); + m_resourceProvider->mirrorHorizontalMoveCanvasToCenter(); } void KisPaintopBox::slotMoveToCenterMirrorY() { - m_resourceProvider->mirrorVerticalMoveCanvasToCenter(); + m_resourceProvider->mirrorVerticalMoveCanvasToCenter(); +} + +void KisPaintopBox::findDefaultPresets() +{ + KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); + m_eraserName = "eraser_circle"; + m_defaultPresetName = "basic_tip_default"; + + KisResourceModel *resourceModel = rserver->resourceModel(); + + for (int i = 0; i < resourceModel->rowCount(); i++) { + + QModelIndex idx = resourceModel->index(i, 0); + + QString resourceName = idx.data(Qt::UserRole + KisResourceModel::Name).toString().toLower(); + QString fileName = idx.data(Qt::UserRole + KisResourceModel::Filename).toString().toLower(); + + if (resourceName.contains("eraser_circle")) { + m_eraserName = resourceName; + } + else if (resourceName.contains("eraser") || fileName.contains("eraser")) { + m_eraserName = resourceName; + } + + if (resourceName.contains("basic_tip_default")) { + m_defaultPresetName = resourceName; + } + else if (resourceName.contains("default") || fileName.contains("default")) { + m_defaultPresetName = resourceName; + } + } } diff --git a/libs/ui/kis_paintop_box.h b/libs/ui/kis_paintop_box.h index 2136a5d1f0..6d7fe5dea3 100644 --- a/libs/ui/kis_paintop_box.h +++ b/libs/ui/kis_paintop_box.h @@ -1,264 +1,265 @@ /* * 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 #include #include #include #include #include "kritaui_export.h" #include "kis_signal_auto_connection.h" #include "kis_signal_compressor.h" class QToolButton; class QString; class QHBoxLayout; class KoColorSpace; class KoCanvasController; class KisViewManager; class KisCanvasResourceProvider; class KisPopupButton; class KisIconWidget; class KisToolOptionsPopup; class KisPaintOpPresetsPopup; class KisPaintOpPresetsChooserPopup; class KisPaintOpConfigWidget; class KisCompositeOpComboBox; class KisWidgetChooser; class KisFavoriteResourceManager; class KisAction; class KisPresetSaveWidget; /** * 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. * * To incorporate the dirty preset functionality and locked settings * the following slots are added * void slotReloadPreset(); void slotGuiChangedCurrentPreset(); void slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP p); void slotDropLockedOption(KisPropertiesConfigurationSP p); void slotDirtyPresetToggled(bool); Every time a value is changed in a preset, the preset is made dirty through the onChange() function. For Locked Settings however, a changed Locked Setting will not cause a preset to become dirty. That is because it borrows its values from the KisLockedPropertiesServer. Hence the dirty state of the Preset is kept consistent before and after a writeConfiguration operation in most cases. * 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 KRITAUI_EXPORT 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(KisViewManager* view, QWidget* parent, const char* name); ~KisPaintopBox() override; void restoreResource(KoResourceSP resource); /** * Update the option widgets to the argument ones, removing the currently set widgets. */ void newOptionWidgets(const QList > & optionWidgetList); KisFavoriteResourceManager *favoriteResourcesManager() { return m_favoriteResourceManager; } public Q_SLOTS: void slotColorSpaceChanged(const KoColorSpace* colorSpace); void slotInputDeviceChanged(const KoInputDevice & inputDevice); void slotCanvasResourceChanged(int key, const QVariant& v); void resourceSelected(KoResourceSP resource); /// This should take care of creating a new brush preset from scratch /// It will either load the default brush preset for the engine, /// or create a new empty preset if a default preset does not exist void slotCreatePresetFromScratch(QString paintop); private: void setCurrentPaintop(const KoID& paintop); void setCurrentPaintop(KisPaintOpPresetSP preset); KisPaintOpPresetSP defaultPreset(const KoID& paintOp); KisPaintOpPresetSP activePreset(const KoID& paintOp); void updateCompositeOp(QString compositeOpID); void setWidgetState(int flags); void setSliderValue(const QString& sliderID, qreal value); void sliderChanged(int n); + void findDefaultPresets(); private Q_SLOTS: void slotSetupDefaultPreset(); void slotNodeChanged(const KisNodeSP node); void slotToggleEraseMode(bool checked); void slotSetCompositeMode(int index); void slotSetPaintop(const QString& paintOpId); void slotHorizontalMirrorChanged(bool value); void slotVerticalMirrorChanged(bool value); void slotSlider1Changed(); void slotSlider2Changed(); void slotSlider3Changed(); void slotToolChanged(KoCanvasController* canvas, int toolId); void slotPreviousFavoritePreset(); void slotNextFavoritePreset(); void slotSwitchToPreviousPreset(); void slotUnsetEraseMode(); void slotToggleAlphaLockMode(bool); void slotDisablePressureMode(bool); void slotReloadPreset(); void slotGuiChangedCurrentPreset(); void slotSaveLockedOptionToPreset(KisPropertiesConfigurationSP p); void slotDropLockedOption(KisPropertiesConfigurationSP p); void slotDirtyPresetToggled(bool); void slotEraserBrushSizeToggled(bool); void slotEraserBrushOpacityToggled(bool); void slotUpdateSelectionIcon(); void slotLockXMirrorToggle(bool); void slotLockYMirrorToggle(bool); void slotMoveToCenterMirrorX(); void slotMoveToCenterMirrorY(); void slotHideDecorationMirrorX(bool); void slotHideDecorationMirrorY(bool); void slotUpdateOptionsWidgetPopup(); private: KisCanvasResourceProvider* m_resourceProvider; QHBoxLayout* m_layout; QWidget* m_paintopWidget; KisPaintOpConfigWidget* m_optionWidget; KisPopupButton* m_toolOptionsPopupButton; KisPresetSaveWidget* m_savePresetWidget; KisIconWidget* m_brushEditorPopupButton; KisPopupButton* m_presetSelectorPopupButton; KisCompositeOpComboBox* m_cmbCompositeOp; QToolButton* m_eraseModeButton; QToolButton* m_alphaLockButton; QToolButton* m_hMirrorButton; QToolButton* m_vMirrorButton; KisToolOptionsPopup* m_toolOptionsPopup; KisPaintOpPresetsPopup* m_presetsPopup; KisPaintOpPresetsChooserPopup* m_presetsChooserPopup; KisViewManager* m_viewManager; KisPopupButton* m_workspaceWidget; KisWidgetChooser* m_sliderChooser[3]; QMap m_paintopOptionWidgets; KisFavoriteResourceManager* m_favoriteResourceManager; QToolButton* m_reloadButton; KisAction* m_eraseAction; KisAction* m_reloadAction; KisAction* m_disablePressureAction; QString m_currCompositeOpID; KisNodeWSP m_previousNode; KisAction* m_hMirrorAction; KisAction* m_vMirrorAction; KisAction* hideCanvasDecorationsX; KisAction* lockActionX; KisAction* moveToCenterActionX; KisAction* hideCanvasDecorationsY; KisAction* lockActionY; KisAction* moveToCenterActionY; struct TabletToolID { TabletToolID(const KoInputDevice& dev) { // Only the eraser is special, and we don't look at Cursor pointer = QTabletEvent::Pen; if (dev.pointer() == QTabletEvent::Eraser) { pointer = QTabletEvent::Eraser; } } bool operator == (const TabletToolID& id) const { return pointer == id.pointer; } bool operator < (const TabletToolID& id) const { return pointer < id.pointer; } QTabletEvent::PointerType pointer; }; 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; bool m_dirtyPresetsEnabled; bool m_eraserBrushSizeEnabled; bool m_eraserBrushOpacityEnabled; KisSignalAutoConnectionsStore m_presetConnections; QString m_eraserName; QString m_defaultPresetName; }; #endif //KIS_PAINTOP_BOX_H_ diff --git a/libs/widgets/KoResourceServer.h b/libs/widgets/KoResourceServer.h index 062509c940..9de00ea558 100644 --- a/libs/widgets/KoResourceServer.h +++ b/libs/widgets/KoResourceServer.h @@ -1,266 +1,272 @@ /* This file is part of the KDE project Copyright (c) 1999 Matthias Elter Copyright (c) 2003 Patrick Julien Copyright (c) 2005 Sven Langkamp Copyright (c) 2007 Jan Hambrecht Copyright (C) 2011 Srikanth Tiyyagura Copyright (c) 2013 Sascha Suelzer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KORESOURCESERVER_H #define KORESOURCESERVER_H #include #include #include #include #include #include #include #include "KoResource.h" #include "KoResourceServerObserver.h" #include "KoResourcePaths.h" #include #include #include #include #include "kritawidgets_export.h" #include "WidgetsDebug.h" class KoResource; - /** * KoResourceServer manages the resources of one type. It stores, * loads and saves the resources. To keep track of changes the server * can be observed with a KoResourceServerObserver */ template class KoResourceServer { public: typedef KoResourceServerObserver ObserverType; KoResourceServer(const QString& type) : m_resourceModel(KisResourceModelProvider::resourceModel(type)) , m_type(type) { } virtual ~KoResourceServer() { Q_FOREACH (ObserverType* observer, m_observers) { observer->unsetResourceServer(); } } - // Return the first resource available - QSharedPointer firstResource() const { + /// @return the active resource model + KisResourceModel *resourceModel() const + { + return m_resourceModel; + } + + /// Return the first resource available + QSharedPointer firstResource() const + { return m_resourceModel->resourceForIndex(m_resourceModel->index(0, 0)).dynamicCast(); } int resourceCount() const { return m_resourceModel->rowCount(); } /// Adds an already loaded resource to the server bool addResource(QSharedPointer resource, bool save = true) { if (!resource->valid()) { warnWidgets << "Tried to add an invalid resource!"; return false; } if (m_resourceModel->addResource(resource, save)) { notifyResourceAdded(resource); return true; } return false; } /// Remove a resource from Resource Server but not from a file bool removeResourceFromServer(QSharedPointer resource){ if (m_resourceModel->removeResource(resource)) { notifyRemovingResource(resource); return true; } return false; } QList> resources() { QList> resourceList; for (int row = 0; row < m_resourceModel->rowCount(); ++row) { resourceList << m_resourceModel->resourceForIndex(m_resourceModel->index(row, 0)).dynamicCast(); } return resourceList; } /// Returns path where to save user defined and imported resources to QString saveLocation() { return KoResourcePaths::saveLocation(m_type.toLatin1()); } /** * Creates a new resource from a given file and adds them to the resource server * The base implementation does only load one resource per file, override to implement collections * @param filename file name of the resource file to be imported * @param fileCreation decides whether to create the file in the saveLocation() directory */ bool importResourceFile(const QString &filename) { return m_resourceModel->importResourceFile(filename); } /// Removes the resource file from the resource server void removeResourceFile(const QString & filename) { QFileInfo fi(filename); QSharedPointer resource = resourceByFilename(fi.fileName()); if (!resource) { warnWidgets << "Resource file do not exist "; return; } removeResourceFromServer(resource); } /** * Addes an observer to the server * @param observer the observer to be added * @param notifyLoadedResources determines if the observer should be notified about the already loaded resources */ void addObserver(ObserverType* observer) { if (observer && !m_observers.contains(observer)) { m_observers.append(observer); } } /** * Removes an observer from the server * @param observer the observer to be removed */ void removeObserver(ObserverType* observer) { int index = m_observers.indexOf(observer); if (index < 0) { return; } m_observers.removeAt( index ); } QSharedPointer resourceByFilename(const QString& filename) const { qDebug() << "resourceByFilename" << filename; // if (m_resourcesByFilename.contains(filename)) { // return m_resourcesByFilename[filename]; // } return 0; } QSharedPointer resourceByName(const QString& name) const { qDebug() << "resourceByName" << name; // if (m_resourcesByName.contains(name)) { // return m_resourcesByName[name]; // } return 0; } QSharedPointer resourceByMD5(const QByteArray& md5) const { qDebug() << "resourceByMD5" << md5; // return m_resourcesByMd5.value(md5); return 0; } /** * Call after changing the content of a resource; * Notifies the connected views. */ void updateResource(QSharedPointer resource) { notifyResourceChanged(resource); } // don't use these method directly since it doesn't update views! void addTag(KoResourceSP resource, const QString& tag) { // m_tagStore->addTag(resource, tag); } // don't use these method directly since it doesn't update views! void delTag(KoResourceSP resource, const QString& tag) { // m_tagStore->delTag(resource, tag); } QStringList assignedTagsList(KoResourceSP resource) const { return QStringList(); //m_tagStore->assignedTagsList(resource); } /// Return the currently stored resources in alphabetical order, overwrite for customized sorting virtual QList> sortedResources() { QMap> sortedNames; // Q_FOREACH (const QString &name, m_resourcesByName.keys()) { // sortedNames.insert(name.toLower(), m_resourcesByName[name]); // } return sortedNames.values(); } protected: void notifyResourceAdded(QSharedPointer resource) { Q_FOREACH (ObserverType* observer, m_observers) { observer->resourceAdded(resource); } } void notifyRemovingResource(QSharedPointer resource) { Q_FOREACH (ObserverType* observer, m_observers) { observer->removingResource(resource); } } void notifyResourceChanged(QSharedPointer resource) { Q_FOREACH (ObserverType* observer, m_observers) { observer->resourceChanged(resource); } } private: QList m_observers; KisResourceModel *m_resourceModel {0}; QString m_type; }; #endif // KORESOURCESERVER_H