diff --git a/libs/ui/forms/wdgpaintopsettings.ui b/libs/ui/forms/wdgpaintopsettings.ui --- a/libs/ui/forms/wdgpaintopsettings.ui +++ b/libs/ui/forms/wdgpaintopsettings.ui @@ -6,7 +6,7 @@ 0 0 - 1134 + 1197 431 @@ -395,22 +395,7 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - 5 - - - 5 - - - 5 - - - 5 - - - 5 - + @@ -535,23 +520,65 @@ - - - - 0 - 0 - - - - Engine Default Preset - - - false - - - false - - + + + + + + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + + 5 + 10 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + 22 + 22 + + + + false + + + false + + + + diff --git a/libs/ui/kis_paintop_box.h b/libs/ui/kis_paintop_box.h --- a/libs/ui/kis_paintop_box.h +++ b/libs/ui/kis_paintop_box.h @@ -122,6 +122,11 @@ void slotCanvasResourceChanged(int key, const QVariant& v); void resourceSelected(KoResource* 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); diff --git a/libs/ui/kis_paintop_box.cc b/libs/ui/kis_paintop_box.cc --- a/libs/ui/kis_paintop_box.cc +++ b/libs/ui/kis_paintop_box.cc @@ -454,6 +454,8 @@ 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(KoResource*)) , SLOT(resourceSelected(KoResource*))); connect(m_presetsChooserPopup, SIGNAL(resourceClicked(KoResource*)) , SLOT(resourceSelected(KoResource*))); @@ -546,6 +548,8 @@ void KisPaintopBox::resourceSelected(KoResource* resource) { + m_presetsPopup->setCreatingBrushFromScratch(false); // show normal UI elements when we are not creating + KisPaintOpPreset* preset = dynamic_cast(resource); if (preset && preset != m_resourceProvider->currentPreset()) { if (!preset->settings()->isLoadable()) @@ -563,6 +567,8 @@ m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } + + } void KisPaintopBox::setCurrentPaintop(const KoID& paintop) @@ -795,6 +801,15 @@ } } +void KisPaintopBox::slotCreatePresetFromScratch(QString paintop) +{ + slotSetPaintop(paintop); // change the paintop settings area and update the UI + m_presetsPopup->setCreatingBrushFromScratch(true); // disable UI elements while creating from scratch + + KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); + m_presetsPopup->resourceSelected(preset.data()); // this helps update the UI on the brush editor +} + void KisPaintopBox::slotCanvasResourceChanged(int key, const QVariant &value) { if (m_viewManager) { @@ -843,7 +858,6 @@ } } - void KisPaintopBox::slotUpdatePreset() { if (!m_resourceProvider->currentPreset()) return; diff --git a/libs/ui/widgets/kis_paintop_presets_popup.h b/libs/ui/widgets/kis_paintop_presets_popup.h --- a/libs/ui/widgets/kis_paintop_presets_popup.h +++ b/libs/ui/widgets/kis_paintop_presets_popup.h @@ -27,6 +27,7 @@ #include #include #include "../kis_paint_ops_model.h" +#include #include #include "widgets/kis_paintop_presets_popup.h" #include "kis_favorite_resource_manager.h" @@ -80,6 +81,9 @@ KisPresetSaveWidget * saveDialog; + // toggle the state when we are creating a brush from scratch + void setCreatingBrushFromScratch(bool enable); + protected: void contextMenuEvent(QContextMenuEvent *) override; void hideEvent(QHideEvent *) override; @@ -96,6 +100,7 @@ void slotRenameBrushActivated(); void slotRenameBrushDeactivated(); void slotSaveRenameCurrentBrush(); + void slotCreateNewBrushPresetEngine(); Q_SIGNALS: void savePresetClicked(); @@ -109,6 +114,7 @@ void eraserBrushOpacityToggled(bool value); void sizeChanged(); void brushEditorShown(); + void createPresetFromScratch(const QString& paintOpName); private Q_SLOTS: void slotSwitchScratchpad(bool visible); @@ -119,8 +125,7 @@ void slotSwitchShowPresets(bool visible); void slotSaveBrushPreset(); void slotSaveNewBrushPreset(); - - + void slotBlackListCurrentPreset(); private: @@ -128,6 +133,12 @@ Private * const m_d; QString current_paintOpId; QList sortedBrushEnginesList; + + + QMenu * newPresetBrushEnginesMenu; + QList newBrushEngineOptions; + + void toggleBrushRenameUIActive(bool isRenaming); }; diff --git a/libs/ui/widgets/kis_paintop_presets_popup.cpp b/libs/ui/widgets/kis_paintop_presets_popup.cpp --- a/libs/ui/widgets/kis_paintop_presets_popup.cpp +++ b/libs/ui/widgets/kis_paintop_presets_popup.cpp @@ -76,6 +76,7 @@ bool detached; bool ignoreHideEvents; + bool isCreatingBrushFromScratch = false; QSize minimumSettingsWidgetSize; QRect detachedGeometry; @@ -126,6 +127,11 @@ m_d->uiWdgPaintOpPresetSettings.renameBrushPresetButton->setToolTip(i18n("Rename the brush preset")); + // creating a new preset from scratch. Part of the brush presets area + // the menu options will get filled up later when we are generating all available paintops + // in the filter drop-down + newPresetBrushEnginesMenu = new QMenu(); + // overwrite existing preset and saving a new preset use the same dialog saveDialog = savePresetWidget; saveDialog->scratchPadSetup(resourceProvider); @@ -180,6 +186,10 @@ m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setPopupMode(QToolButton::InstantPopup); + // loading preset from scratch option + m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setIcon(KisIconUtils::loadIcon("addlayer")); + m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setIcon(KisIconUtils::loadIcon("deletelayer")); + // show/hide buttons KisConfig cfg; @@ -254,9 +264,6 @@ connect(m_d->uiWdgPaintOpPresetSettings.reloadPresetButton, SIGNAL(clicked()), this, SIGNAL(reloadPresetClicked())); - connect(m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset, SIGNAL(clicked()), - this, SIGNAL(defaultPresetClicked())); - connect(m_d->uiWdgPaintOpPresetSettings.dirtyPresetCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(dirtyPresetToggled(bool))); @@ -269,7 +276,7 @@ // preset widget connections connect(m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SIGNAL(resourceSelected(KoResource*)), - this, SIGNAL(signalResourceSelected(KoResource*))); + this, SIGNAL(signalResourceSelected(KoResource*))); connect(m_d->uiWdgPaintOpPresetSettings.reloadPresetButton, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SLOT(updateViewSettings())); @@ -304,11 +311,25 @@ connect(m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatePaintOpFilter())); + + connect(m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset, SIGNAL(clicked()), this, SLOT(slotBlackListCurrentPreset())); + + // setup things like the scene construct images, layers, etc that is a one-time thing m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->setup(); } +void KisPaintOpPresetsPopup::slotBlackListCurrentPreset() +{ + KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); + KisPaintOpPresetSP curPreset = m_d->resourceProvider->currentPreset(); + + if (rServer->resourceByName(curPreset->name())) { + rServer->removeResourceAndBlacklist(curPreset); + } +} + void KisPaintOpPresetsPopup::slotRenameBrushActivated() { @@ -341,10 +362,10 @@ // what happens if you try to change presets. maybe we should auto-hide (or disable) // the presets area in this case if (m_d->uiWdgPaintOpPresetSettings.presetWidget->isVisible()) { - m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset->setVisible(!isRenaming); + m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setVisible(!isRenaming); + m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setVisible(!isRenaming); } - } void KisPaintOpPresetsPopup::slotSaveRenameCurrentBrush() @@ -396,7 +417,6 @@ slotUpdatePresetSettings(); // update visibility of dirty preset and icon } - void KisPaintOpPresetsPopup::slotResourceChanged(int key, const QVariant &value) { if (key == KisCanvasResourceProvider::LodAvailability) { @@ -418,6 +438,7 @@ m_d->settingsWidget = 0; } delete m_d; + delete newPresetBrushEnginesMenu; } void KisPaintOpPresetsPopup::setPaintOpSettingsWidget(QWidget * widget) @@ -515,6 +536,12 @@ } } +void KisPaintOpPresetsPopup::setCreatingBrushFromScratch(bool enabled) +{ + m_d->isCreatingBrushFromScratch = enabled; +} + + void KisPaintOpPresetsPopup::resourceSelected(KoResource* resource) { // this gets called every time the brush editor window is opened @@ -587,9 +614,24 @@ // add an "All" option at the front to show all presets QPixmap emptyPixmap = QPixmap(22,22); emptyPixmap.fill(palette().color(QPalette::Background)); - sortedBrushEnginesList.push_front(KisPaintOpInfo(QString("all_options"), i18n("All"), QString(""), emptyPixmap, 0 )); + + // if we create a new brush from scratch, we need a full list of paintops to choose from + // we don't want "All", so populate the list before that is added + newPresetBrushEnginesMenu->actions().clear(); // clean out list in case we run this again + newBrushEngineOptions.clear(); + + for (int j = 0; j < sortedBrushEnginesList.length(); j++) { + KisAction * newEngineAction = static_cast( newPresetBrushEnginesMenu->addAction(sortedBrushEnginesList[j].name)); + newEngineAction->setObjectName(sortedBrushEnginesList[j].id); // we need the ID for changing the paintop when action triggered + + newBrushEngineOptions.append(newEngineAction); + connect(newEngineAction, SIGNAL(triggered()), this, SLOT(slotCreateNewBrushPresetEngine())); + } + m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setMenu(newPresetBrushEnginesMenu); + // fill the list into the brush combo box + sortedBrushEnginesList.push_front(KisPaintOpInfo(QString("all_options"), i18n("All"), QString(""), emptyPixmap, 0 )); for (int m = 0; m < sortedBrushEnginesList.length(); m++) { m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->addItem(sortedBrushEnginesList[m].icon, sortedBrushEnginesList[m].name, QVariant(sortedBrushEnginesList[m].id)); } @@ -679,8 +721,9 @@ m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setVisible(visible); m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->setVisible(visible); m_d->uiWdgPaintOpPresetSettings.engineFilterLabel->setVisible(visible); - m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset->setVisible(visible); m_d->uiWdgPaintOpPresetSettings.presetsSidebarLabel->setVisible(visible); + m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setVisible(visible); + m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setVisible(visible); // we only want a spacer to work when the toggle icon is present. Otherwise the list of presets will shrink @@ -725,6 +768,14 @@ saveDialog->showDialog(); } +void KisPaintOpPresetsPopup::slotCreateNewBrushPresetEngine() +{ + KisAction *actionThatWasSent = static_cast(sender());// sender() gets what menu item was called + emit createPresetFromScratch(actionThatWasSent->objectName()); + + actionThatWasSent->deleteLater(); +} + void KisPaintOpPresetsPopup::updateViewSettings() { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->updateViewSettings(); @@ -746,6 +797,8 @@ m_d->uiWdgPaintOpPresetSettings.fillSolid->setIcon(KisIconUtils::loadIcon("krita_tool_color_fill")); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete")); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); + m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setIcon(KisIconUtils::loadIcon("addlayer")); + m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setIcon(KisIconUtils::loadIcon("deletelayer")); } void KisPaintOpPresetsPopup::slotUpdatePresetSettings() @@ -757,13 +810,21 @@ return; } - bool isPresetDirty = m_d->resourceProvider->currentPreset()->isPresetDirty(); - - // don't need to reload or overwrite a clean preset - m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(isPresetDirty); - m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(isPresetDirty); - m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(isPresetDirty); + // hide options on UI if we are creating a brush preset from scratch to prevent confusion + if (m_d->isCreatingBrushFromScratch) { + m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(false); + m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(false); + m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setVisible(false); + m_d->uiWdgPaintOpPresetSettings.renameBrushPresetButton->setVisible(false); + } else { + bool isPresetDirty = m_d->resourceProvider->currentPreset()->isPresetDirty(); + // don't need to reload or overwrite a clean preset + m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(isPresetDirty); + m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(isPresetDirty); + m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(isPresetDirty); + m_d->uiWdgPaintOpPresetSettings.renameBrushPresetButton->setVisible(true); + } // update live preview area in here... // don't update the live preview if the widget is not visible.