diff --git a/libs/ui/widgets/kis_paintop_presets_popup.cpp b/libs/ui/widgets/kis_paintop_presets_popup.cpp index 345f3fbb1c..eb3b3af162 100644 --- a/libs/ui/widgets/kis_paintop_presets_popup.cpp +++ b/libs/ui/widgets/kis_paintop_presets_popup.cpp @@ -1,594 +1,595 @@ /* This file is part of the KDE project * Copyright (C) 2008 Boudewijn Rempt * Copyright (C) 2010 Lukáš Tvrdý * Copyright (C) 2011 Silvio Heinrich * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "widgets/kis_paintop_presets_popup.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 "kis_config.h" #include "kis_resource_server_provider.h" #include "kis_lod_availability_widget.h" #include "kis_signal_auto_connection.h" // ones from brush engine selector #include struct KisPaintOpPresetsPopup::Private { public: Ui_WdgPaintOpSettings uiWdgPaintOpPresetSettings; QGridLayout *layout; KisPaintOpConfigWidget *settingsWidget; QFont smallFont; KisCanvasResourceProvider *resourceProvider; bool detached; bool ignoreHideEvents; QSize minimumSettingsWidgetSize; QRect detachedGeometry; KisSignalAutoConnectionsStore widgetConnections; }; KisPaintOpPresetsPopup::KisPaintOpPresetsPopup(KisCanvasResourceProvider * resourceProvider, QWidget * parent) : QWidget(parent) , m_d(new Private()) { setObjectName("KisPaintOpPresetsPopup"); setFont(KoDockRegistry::dockFont()); current_paintOpId = ""; m_d->resourceProvider = resourceProvider; m_d->uiWdgPaintOpPresetSettings.setupUi(this); m_d->layout = new QGridLayout(m_d->uiWdgPaintOpPresetSettings.frmOptionWidgetContainer); m_d->layout->setSizeConstraint(QLayout::SetFixedSize); m_d->uiWdgPaintOpPresetSettings.scratchPad->setupScratchPad(resourceProvider, Qt::white); m_d->uiWdgPaintOpPresetSettings.scratchPad->setCutoutOverlayRect(QRect(25, 25, 200, 200)); m_d->uiWdgPaintOpPresetSettings.fillLayer->setIcon(KisIconUtils::loadIcon("document-new")); m_d->uiWdgPaintOpPresetSettings.fillLayer->hide(); m_d->uiWdgPaintOpPresetSettings.fillGradient->setIcon(KisIconUtils::loadIcon("krita_tool_gradient")); m_d->uiWdgPaintOpPresetSettings.fillSolid->setIcon(KisIconUtils::loadIcon("krita_tool_color_fill")); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete")); m_d->uiWdgPaintOpPresetSettings.paintPresetIcon->setIcon(KisIconUtils::loadIcon("krita_tool_freehand")); saveDialog = new KisPresetSaveWidget(this->parentWidget()); saveDialog->scratchPadSetup(resourceProvider); saveDialog->hide(); // DETAIL and THUMBNAIL view changer QMenu* menu = new QMenu(this); menu->setStyleSheet("margin: 6px"); menu->addSection(i18n("Display")); QActionGroup *actionGroup = new QActionGroup(this); KisPresetChooser::ViewMode mode = (KisPresetChooser::ViewMode)KisConfig().presetChooserViewMode(); QAction* action = menu->addAction(KisIconUtils::loadIcon("view-preview"), i18n("Thumbnails"), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotThumbnailMode())); action->setCheckable(true); action->setChecked(mode == KisPresetChooser::THUMBNAIL); action->setActionGroup(actionGroup); action = menu->addAction(KisIconUtils::loadIcon("view-list-details"), i18n("Details"), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotDetailMode())); action->setCheckable(true); action->setChecked(mode == KisPresetChooser::DETAIL); action->setActionGroup(actionGroup); // add horizontal slider for the icon size QSlider* iconSizeSlider = new QSlider(this); iconSizeSlider->setOrientation(Qt::Horizontal); iconSizeSlider->setRange(30, 80); iconSizeSlider->setValue(m_d->uiWdgPaintOpPresetSettings.presetWidget->iconSize()); iconSizeSlider->setMinimumHeight(20); iconSizeSlider->setMinimumWidth(40); iconSizeSlider->setTickInterval(10); QWidgetAction *sliderAction= new QWidgetAction(this); sliderAction->setDefaultWidget(iconSizeSlider); menu->addSection(i18n("Icon Size")); menu->addAction(sliderAction); // configure the button and assign menu m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setMenu(menu); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setPopupMode(QToolButton::InstantPopup); // show/hide buttons KisConfig cfg; m_d->uiWdgPaintOpPresetSettings.showScratchpadButton->setCheckable(true); m_d->uiWdgPaintOpPresetSettings.showScratchpadButton->setChecked(cfg.scratchpadVisible()); m_d->uiWdgPaintOpPresetSettings.showEditorButton->setCheckable(true); m_d->uiWdgPaintOpPresetSettings.showEditorButton->setChecked(true); m_d->uiWdgPaintOpPresetSettings.showPresetsButton->setText(i18n("Presets")); m_d->uiWdgPaintOpPresetSettings.showPresetsButton->setCheckable(true); m_d->uiWdgPaintOpPresetSettings.showPresetsButton->setChecked(false); // use a config to load/save this state slotSwitchShowPresets(false); // hide presets by default // Connections connect(iconSizeSlider, SIGNAL(sliderMoved(int)), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotSetIconSize(int))); connect(iconSizeSlider, SIGNAL(sliderReleased()), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotSaveIconSize())); connect(m_d->uiWdgPaintOpPresetSettings.showScratchpadButton, SIGNAL(clicked(bool)), this, SLOT(slotSwitchScratchpad(bool))); connect(m_d->uiWdgPaintOpPresetSettings.showEditorButton, SIGNAL(clicked(bool)), this, SLOT(slotSwitchShowEditor(bool))); connect(m_d->uiWdgPaintOpPresetSettings.showPresetsButton, SIGNAL(clicked(bool)), this, SLOT(slotSwitchShowPresets(bool))); connect(m_d->uiWdgPaintOpPresetSettings.eraseScratchPad, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillDefault())); connect(m_d->uiWdgPaintOpPresetSettings.fillLayer, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillLayer())); connect(m_d->uiWdgPaintOpPresetSettings.fillGradient, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillGradient())); connect(m_d->uiWdgPaintOpPresetSettings.fillSolid, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillBackground())); connect(m_d->uiWdgPaintOpPresetSettings.paintPresetIcon, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(paintPresetImage())); m_d->settingsWidget = 0; setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); connect(m_d->uiWdgPaintOpPresetSettings.bnSave, SIGNAL(clicked()), this, SIGNAL(savePresetClicked())); connect(m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton, SIGNAL(clicked()), this, SLOT(slotSaveBrushPreset())); connect(m_d->uiWdgPaintOpPresetSettings.reload, 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))); connect(m_d->uiWdgPaintOpPresetSettings.eraserBrushSizeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(eraserBrushSizeToggled(bool))); connect(m_d->uiWdgPaintOpPresetSettings.eraserBrushOpacityCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(eraserBrushOpacityToggled(bool))); connect(m_d->uiWdgPaintOpPresetSettings.bnDefaultPreset, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.txtPreset, SLOT(clear())); connect(m_d->uiWdgPaintOpPresetSettings.txtPreset, SIGNAL(textChanged(QString)), SLOT(slotWatchPresetNameLineEdit())); // preset widget connections connect(m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SIGNAL(resourceSelected(KoResource*)), this, SIGNAL(signalResourceSelected(KoResource*))); connect(m_d->uiWdgPaintOpPresetSettings.bnSave, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SLOT(updateViewSettings())); connect(m_d->uiWdgPaintOpPresetSettings.reload, SIGNAL(clicked()), m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SLOT(updateViewSettings())); m_d->detached = false; m_d->ignoreHideEvents = false; m_d->minimumSettingsWidgetSize = QSize(0, 0); m_d->uiWdgPaintOpPresetSettings.scratchpadControls->setVisible(cfg.scratchpadVisible()); m_d->detachedGeometry = QRect(100, 100, 0, 0); m_d->uiWdgPaintOpPresetSettings.dirtyPresetCheckBox->setChecked(cfg.useDirtyPresets()); m_d->uiWdgPaintOpPresetSettings.eraserBrushSizeCheckBox->setChecked(cfg.useEraserBrushSize()); m_d->uiWdgPaintOpPresetSettings.eraserBrushOpacityCheckBox->setChecked(cfg.useEraserBrushOpacity()); m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setCanvasResourceManager(resourceProvider->resourceManager()); connect(resourceProvider->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), SLOT(slotResourceChanged(int, QVariant))); connect(m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability, SIGNAL(sigUserChangedLodAvailability(bool)), SLOT(slotLodAvailabilityChanged(bool))); slotResourceChanged(KisCanvasResourceProvider::LodAvailability, resourceProvider->resourceManager()-> resource(KisCanvasResourceProvider::LodAvailability)); connect(m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatePaintOpFilter())); } void KisPaintOpPresetsPopup::slotResourceChanged(int key, const QVariant &value) { if (key == KisCanvasResourceProvider::LodAvailability) { m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->slotUserChangedLodAvailability(value.toBool()); } } void KisPaintOpPresetsPopup::slotLodAvailabilityChanged(bool value) { m_d->resourceProvider->resourceManager()->setResource(KisCanvasResourceProvider::LodAvailability, QVariant(value)); } KisPaintOpPresetsPopup::~KisPaintOpPresetsPopup() { if (m_d->settingsWidget) { m_d->layout->removeWidget(m_d->settingsWidget); m_d->settingsWidget->hide(); m_d->settingsWidget->setParent(0); m_d->settingsWidget = 0; } delete m_d; } void KisPaintOpPresetsPopup::setPaintOpSettingsWidget(QWidget * widget) { if (m_d->settingsWidget) { m_d->layout->removeWidget(m_d->settingsWidget); m_d->uiWdgPaintOpPresetSettings.frmOptionWidgetContainer->updateGeometry(); } m_d->layout->update(); updateGeometry(); m_d->widgetConnections.clear(); m_d->settingsWidget = 0; if (widget) { m_d->settingsWidget = dynamic_cast(widget); KIS_ASSERT_RECOVER_RETURN(m_d->settingsWidget); if (m_d->settingsWidget->supportScratchBox()) { showScratchPad(); } else { hideScratchPad(); } m_d->widgetConnections.addConnection(m_d->settingsWidget, SIGNAL(sigConfigurationItemChanged()), this, SLOT(slotUpdateLodAvailability())); widget->setFont(m_d->smallFont); QSize hint = widget->sizeHint(); m_d->minimumSettingsWidgetSize = QSize(qMax(hint.width(), m_d->minimumSettingsWidgetSize.width()), qMax(hint.height(), m_d->minimumSettingsWidgetSize.height())); widget->setMinimumSize(m_d->minimumSettingsWidgetSize); m_d->layout->addWidget(widget); m_d->layout->update(); widget->show(); } slotUpdateLodAvailability(); } void KisPaintOpPresetsPopup::slotUpdateLodAvailability() { if (!m_d->settingsWidget) return; KisPaintopLodLimitations l = m_d->settingsWidget->lodLimitations(); m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setLimitations(l); } void KisPaintOpPresetsPopup::slotWatchPresetNameLineEdit() { QString text = m_d->uiWdgPaintOpPresetSettings.txtPreset->text(); KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); bool overwrite = rServer->resourceByName(text) != 0; KisPaintOpPresetSP preset = m_d->resourceProvider->currentPreset(); bool btnSaveAvailable = preset->valid() && (preset->isPresetDirty() | !overwrite); QString btnText = overwrite ? i18n("Overwrite Preset") : i18n("Save to Presets"); m_d->uiWdgPaintOpPresetSettings.bnSave->setText(btnText); m_d->uiWdgPaintOpPresetSettings.bnSave->setEnabled(btnSaveAvailable); m_d->uiWdgPaintOpPresetSettings.reload->setVisible(true); m_d->uiWdgPaintOpPresetSettings.reload->setEnabled(btnSaveAvailable && overwrite); QFont font = m_d->uiWdgPaintOpPresetSettings.txtPreset->font(); font.setItalic(btnSaveAvailable); m_d->uiWdgPaintOpPresetSettings.txtPreset->setFont(font); } QString KisPaintOpPresetsPopup::getPresetName() const { return m_d->uiWdgPaintOpPresetSettings.txtPreset->text(); } QImage KisPaintOpPresetsPopup::cutOutOverlay() { return m_d->uiWdgPaintOpPresetSettings.scratchPad->cutoutOverlay(); } void KisPaintOpPresetsPopup::contextMenuEvent(QContextMenuEvent *e) { Q_UNUSED(e); } void KisPaintOpPresetsPopup::switchDetached(bool show) { if (parentWidget()) { m_d->detached = !m_d->detached; if (m_d->detached) { m_d->ignoreHideEvents = true; if (show) { parentWidget()->show(); } m_d->ignoreHideEvents = false; } else { KisConfig cfg; parentWidget()->hide(); } KisConfig cfg; cfg.setPaintopPopupDetached(m_d->detached); } } void KisPaintOpPresetsPopup::hideScratchPad() { m_d->uiWdgPaintOpPresetSettings.scratchPad->setEnabled(false); m_d->uiWdgPaintOpPresetSettings.fillGradient->setEnabled(false); m_d->uiWdgPaintOpPresetSettings.fillSolid->setEnabled(false); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setEnabled(false); } void KisPaintOpPresetsPopup::showScratchPad() { m_d->uiWdgPaintOpPresetSettings.scratchPad->setEnabled(true); m_d->uiWdgPaintOpPresetSettings.fillGradient->setEnabled(true); m_d->uiWdgPaintOpPresetSettings.fillSolid->setEnabled(true); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setEnabled(true); } void KisPaintOpPresetsPopup::resourceSelected(KoResource* resource) { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->setCurrentResource(resource); m_d->uiWdgPaintOpPresetSettings.txtPreset->setText(resource->name()); slotWatchPresetNameLineEdit(); // find the display name of the brush engine and append it to the selected preset display QString currentBrushEngineName; for(int i=0; i < sortedBrushEnginesList.length(); i++) { if (sortedBrushEnginesList.at(i).id == currentPaintOpId() ) { currentBrushEngineName = sortedBrushEnginesList.at(i).name; } } QString selectedBrush = resource->name().append(" (").append(currentBrushEngineName).append(" ").append("Engine").append(")"); m_d->uiWdgPaintOpPresetSettings.currentBrushNameLabel->setText(selectedBrush); } bool variantLessThan(const KisPaintOpInfo v1, const KisPaintOpInfo v2) { return v1.priority < v2.priority; } void KisPaintOpPresetsPopup::setPaintOpList(const QList< KisPaintOpFactory* >& list) { m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->clear(); // reset combobox list just in case // create a new list so we can sort it and populate the brush engine combo box sortedBrushEnginesList.clear(); // just in case this function is called again, don't keep adding to the list for(int i=0; i < list.length(); i++) { QString fileName = KoResourcePaths::findResource("kis_images", list.at(i)->pixmap()); QPixmap pixmap(fileName); if(pixmap.isNull()){ pixmap = QPixmap(22,22); pixmap.fill(); } KisPaintOpInfo paintOpInfo; paintOpInfo.id = list.at(i)->id(); paintOpInfo.name = list.at(i)->name(); paintOpInfo.icon = pixmap; paintOpInfo.priority = list.at(i)->priority(); sortedBrushEnginesList.append(paintOpInfo); } qStableSort(sortedBrushEnginesList.begin(), sortedBrushEnginesList.end(), variantLessThan ); // 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 )); // fill the list into the brush combo box for (int m = 0; m < sortedBrushEnginesList.length(); m++) { m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->addItem(sortedBrushEnginesList[m].icon, sortedBrushEnginesList[m].name, QVariant(sortedBrushEnginesList[m].id)); } } void KisPaintOpPresetsPopup::setCurrentPaintOpId(const QString& paintOpId) { current_paintOpId = paintOpId; } QString KisPaintOpPresetsPopup::currentPaintOpId() { return current_paintOpId; } void KisPaintOpPresetsPopup::setPresetImage(const QImage& image) { m_d->uiWdgPaintOpPresetSettings.scratchPad->setPresetImage(image); + saveDialog->scratchPadWidget->setPresetImage(image); } void KisPaintOpPresetsPopup::hideEvent(QHideEvent *event) { if (m_d->ignoreHideEvents) { return; } if (m_d->detached) { m_d->detachedGeometry = window()->geometry(); } QWidget::hideEvent(event); } void KisPaintOpPresetsPopup::showEvent(QShowEvent *) { if (m_d->detached) { window()->setGeometry(m_d->detachedGeometry); } emit brushEditorShown(); } void KisPaintOpPresetsPopup::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); emit sizeChanged(); } bool KisPaintOpPresetsPopup::detached() const { return m_d->detached; } void KisPaintOpPresetsPopup::slotSwitchScratchpad(bool visible) { m_d->uiWdgPaintOpPresetSettings.scratchpadControls->setVisible(visible); KisConfig cfg; cfg.setScratchpadVisible(visible); } void KisPaintOpPresetsPopup::slotSwitchShowEditor(bool visible) { m_d->uiWdgPaintOpPresetSettings.brushEditorSettingsControls->setVisible(visible); } void KisPaintOpPresetsPopup::slotSwitchShowPresets(bool visible) { m_d->uiWdgPaintOpPresetSettings.presetsContainer->setVisible(visible); } void KisPaintOpPresetsPopup::slotUpdatePaintOpFilter() { QVariant userData = m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->currentData(); // grab paintOpID from data QString filterPaintOpId = userData.toString(); if (filterPaintOpId == "all_options") { filterPaintOpId = ""; } m_d->uiWdgPaintOpPresetSettings.presetWidget->setPresetFilter(filterPaintOpId); } void KisPaintOpPresetsPopup::slotSaveBrushPreset() { saveDialog->showDialog(); } void KisPaintOpPresetsPopup::updateViewSettings() { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->updateViewSettings(); } void KisPaintOpPresetsPopup::currentPresetChanged(KisPaintOpPresetSP preset) { m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->setCurrentResource(preset.data()); setCurrentPaintOpId(preset->paintOp().id()); } void KisPaintOpPresetsPopup::updateThemedIcons() { m_d->uiWdgPaintOpPresetSettings.fillLayer->setIcon(KisIconUtils::loadIcon("document-new")); m_d->uiWdgPaintOpPresetSettings.fillLayer->hide(); m_d->uiWdgPaintOpPresetSettings.fillGradient->setIcon(KisIconUtils::loadIcon("krita_tool_gradient")); m_d->uiWdgPaintOpPresetSettings.fillSolid->setIcon(KisIconUtils::loadIcon("krita_tool_color_fill")); m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete")); m_d->uiWdgPaintOpPresetSettings.paintPresetIcon->setIcon(KisIconUtils::loadIcon("krita_tool_freehand")); m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-choose")); } diff --git a/libs/ui/widgets/kis_paintop_presets_save.cpp b/libs/ui/widgets/kis_paintop_presets_save.cpp index ac4f4da435..dc54e58eb5 100644 --- a/libs/ui/widgets/kis_paintop_presets_save.cpp +++ b/libs/ui/widgets/kis_paintop_presets_save.cpp @@ -1,97 +1,101 @@ /* This file is part of the KDE project * Copyright (C) 2017 Scott Petrovic * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "widgets/kis_paintop_presets_save.h" #include KisPresetSaveWidget::KisPresetSaveWidget(QWidget * parent) : KisPaintOpPresetSaveDialog(parent) { } KisPresetSaveWidget::~KisPresetSaveWidget() { } void KisPresetSaveWidget::scratchPadSetup(KisCanvasResourceProvider* resourceProvider) { m_resourceProvider = resourceProvider; this->scratchPadWidget->setupScratchPad(m_resourceProvider, Qt::white); - - // this is setting the area we will "capture" for saving the brush preset. It can potentially be a different - // area that the entire scratchpad - this->scratchPadWidget->setCutoutOverlayRect(QRect(0, 0, scratchPadWidget->height(), scratchPadWidget->width())); } -void KisPresetSaveWidget::showDialog() { +void KisPresetSaveWidget::showDialog() +{ setModal(true); // set the name of the current brush preset area. KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); if (preset) { this->currentBrushNameLabel->setText(preset->name()); } show(); + // this is setting the area we will "capture" for saving the brush preset. It can potentially be a different + // area that the entire scratchpad + this->scratchPadWidget->setCutoutOverlayRect(QRect(0, 0, scratchPadWidget->height(), scratchPadWidget->width())); + + + // we will default to reusing the previous preset thumbnail // have that checked by default, hide the other elements, and load the last preset image connect(clearScratchpadButton, SIGNAL(clicked(bool)), scratchPadWidget, SLOT(fillDefault())); connect(useExistingThumbnailCheckbox, SIGNAL(clicked(bool)), this, SLOT(usePreviousThumbnail(bool))); this->useExistingThumbnailCheckbox->setChecked(true); usePreviousThumbnail(true); QDialog::DialogCode result = (QDialog::DialogCode)this->exec(); if(result) { qDebug() << "stuff ran in the dialog"; } } -void KisPresetSaveWidget::usePreviousThumbnail(bool usePrevious) { +void KisPresetSaveWidget::usePreviousThumbnail(bool usePrevious) +{ // hide other elements if we are using the previous thumbnail this->loadThumbnailGroupBox->setVisible(!usePrevious); this->clearScratchpadButton->setVisible(!usePrevious); // load the previous thumbnail if we are using the existing one - //TODO: figure out why this is grabbing a null image when it runs - // if (usePrevious) { - - // this->scratchPadWidget->paintPresetImage(); - // } + if (usePrevious) { + this->scratchPadWidget->paintPresetImage(); + } else { + scratchPadWidget->fillDefault(); // fill with white if we want a new preview area + } this->scratchPadWidget->allowPainting(!usePrevious); // don't allow drawing if we are using the existing preset } #include "moc_kis_paintop_presets_save.cpp" diff --git a/libs/ui/widgets/kis_scratch_pad.cpp b/libs/ui/widgets/kis_scratch_pad.cpp index 268ce35d22..5df156ff35 100644 --- a/libs/ui/widgets/kis_scratch_pad.cpp +++ b/libs/ui/widgets/kis_scratch_pad.cpp @@ -1,491 +1,492 @@ /* This file is part of the KDE project * Copyright 2010 (C) Boudewijn Rempt * Copyright 2011 (C) Dmitry Kazakov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_scratch_pad.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_config.h" #include "kis_image.h" #include "kis_undo_stores.h" #include "kis_update_scheduler.h" #include "kis_post_execution_undo_adapter.h" #include "kis_scratch_pad_event_filter.h" #include "kis_painting_information_builder.h" #include "kis_tool_freehand_helper.h" #include "kis_image_patch.h" #include "kis_canvas_widget_base.h" #include "kis_layer_projection_plane.h" #include "kis_node_graph_listener.h" class KisScratchPadNodeListener : public KisNodeGraphListener { public: KisScratchPadNodeListener(KisScratchPad *scratchPad) : m_scratchPad(scratchPad) { } void requestProjectionUpdate(KisNode *node, const QRect& rect, bool resetAnimationCache) override { KisNodeGraphListener::requestProjectionUpdate(node, rect, resetAnimationCache); QMutexLocker locker(&m_lock); m_scratchPad->imageUpdated(rect); } private: KisScratchPad *m_scratchPad; QMutex m_lock; }; class KisScratchPadDefaultBounds : public KisDefaultBounds { public: KisScratchPadDefaultBounds(KisScratchPad *scratchPad) : m_scratchPad(scratchPad) { } ~KisScratchPadDefaultBounds() override {} QRect bounds() const override { return m_scratchPad->imageBounds(); } private: Q_DISABLE_COPY(KisScratchPadDefaultBounds) KisScratchPad *m_scratchPad; }; KisScratchPad::KisScratchPad(QWidget *parent) : QWidget(parent) , m_toolMode(HOVERING) , m_paintLayer(0) , m_displayProfile(0) , m_resourceProvider(0) { setAutoFillBackground(false); setMouseTracking(true); m_cursor = KisCursor::load("tool_freehand_cursor.png", 5, 5); setCursor(m_cursor); KisConfig cfg; QImage checkImage = KisCanvasWidgetBase::createCheckersImage(cfg.checkSize()); m_checkBrush = QBrush(checkImage); // We are not supposed to use updates here, // so just set the listener to null m_updateScheduler = new KisUpdateScheduler(0); m_undoStore = new KisSurrogateUndoStore(); m_undoAdapter = new KisPostExecutionUndoAdapter(m_undoStore, m_updateScheduler); m_nodeListener = new KisScratchPadNodeListener(this); connect(this, SIGNAL(sigUpdateCanvas(QRect)), SLOT(slotUpdateCanvas(QRect)), Qt::QueuedConnection); // filter will be deleted by the QObject hierarchy m_eventFilter = new KisScratchPadEventFilter(this); m_infoBuilder = new KisPaintingInformationBuilder(); m_helper = new KisToolFreehandHelper(m_infoBuilder); m_allowPainting = true; m_scaleBorderWidth = 1; } KisScratchPad::~KisScratchPad() { delete m_helper; delete m_infoBuilder; delete m_undoAdapter; delete m_undoStore; delete m_updateScheduler; delete m_nodeListener; } KisScratchPad::Mode KisScratchPad::modeFromButton(Qt::MouseButton button) const { return button == Qt::NoButton ? HOVERING : button == Qt::MidButton ? PANNING : button == Qt::RightButton ? PICKING : PAINTING; } void KisScratchPad::pointerPress(KoPointerEvent *event) { if (!m_allowPainting) return; if (m_toolMode != HOVERING) return; m_toolMode = modeFromButton(event->button()); if (m_toolMode == PAINTING) { beginStroke(event); event->accept(); } else if (m_toolMode == PANNING) { beginPan(event); event->accept(); } else if (m_toolMode == PICKING) { pick(event); event->accept(); } } void KisScratchPad::pointerRelease(KoPointerEvent *event) { if (!m_allowPainting) return; if (modeFromButton(event->button()) != m_toolMode) return; if (m_toolMode == PAINTING) { endStroke(event); m_toolMode = HOVERING; event->accept(); } else if (m_toolMode == PANNING) { endPan(event); m_toolMode = HOVERING; event->accept(); } else if (m_toolMode == PICKING) { event->accept(); m_toolMode = HOVERING; } } void KisScratchPad::pointerMove(KoPointerEvent *event) { if (!m_allowPainting) return; m_helper->cursorMoved(documentToWidget().map(event->point)); if (m_toolMode == PAINTING) { doStroke(event); event->accept(); } else if (m_toolMode == PANNING) { doPan(event); event->accept(); } else if (m_toolMode == PICKING) { pick(event); event->accept(); } } void KisScratchPad::beginStroke(KoPointerEvent *event) { KoCanvasResourceManager *resourceManager = m_resourceProvider->resourceManager(); m_helper->initPaint(event, documentToWidget().map(event->point), resourceManager, 0, 0, m_updateScheduler, m_paintLayer, m_paintLayer->paintDevice()->defaultBounds()); } void KisScratchPad::doStroke(KoPointerEvent *event) { m_helper->paintEvent(event); } void KisScratchPad::endStroke(KoPointerEvent *event) { Q_UNUSED(event); m_helper->endPaint(); } void KisScratchPad::beginPan(KoPointerEvent *event) { setCursor(QCursor(Qt::ClosedHandCursor)); m_panDocPoint = event->point; } void KisScratchPad::doPan(KoPointerEvent *event) { QPointF docOffset = event->point - m_panDocPoint; m_translateTransform.translate(-docOffset.x(), -docOffset.y()); updateTransformations(); update(); } void KisScratchPad::endPan(KoPointerEvent *event) { Q_UNUSED(event); setCursor(m_cursor); } void KisScratchPad::pick(KoPointerEvent *event) { KoColor color; if (KisToolUtils::pick(m_paintLayer->projection(), event->point.toPoint(), &color)) { emit colorSelected(color); } } void KisScratchPad::setOnScreenResolution(qreal scaleX, qreal scaleY) { m_scaleBorderWidth = BORDER_SIZE(qMax(scaleX, scaleY)); m_scaleTransform = QTransform::fromScale(scaleX, scaleY); updateTransformations(); update(); } QTransform KisScratchPad::documentToWidget() const { return m_translateTransform.inverted() * m_scaleTransform; } QTransform KisScratchPad::widgetToDocument() const { return m_scaleTransform.inverted() * m_translateTransform; } void KisScratchPad::updateTransformations() { m_eventFilter->setWidgetToDocumentTransform(widgetToDocument()); } QRect KisScratchPad::imageBounds() const { return widgetToDocument().mapRect(rect()); } void KisScratchPad::imageUpdated(const QRect &rect) { emit sigUpdateCanvas(documentToWidget().mapRect(QRectF(rect)).toAlignedRect()); } void KisScratchPad::slotUpdateCanvas(const QRect &rect) { update(rect); } void KisScratchPad::paintEvent ( QPaintEvent * event ) { if(!m_paintLayer) return; QRectF imageRect = widgetToDocument().mapRect(QRectF(event->rect())); QRect alignedImageRect = imageRect.adjusted(-m_scaleBorderWidth, -m_scaleBorderWidth, m_scaleBorderWidth, m_scaleBorderWidth).toAlignedRect(); QPointF offset = alignedImageRect.topLeft(); m_paintLayer->projectionPlane()->recalculate(alignedImageRect, m_paintLayer); KisPaintDeviceSP projection = m_paintLayer->projection(); QImage image = projection->convertToQImage(m_displayProfile, alignedImageRect.x(), alignedImageRect.y(), alignedImageRect.width(), alignedImageRect.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); QPainter gc(this); gc.fillRect(event->rect(), m_checkBrush); gc.setRenderHints(QPainter::SmoothPixmapTransform); gc.drawImage(QRectF(event->rect()), image, imageRect.translated(-offset)); QBrush brush(Qt::lightGray); QPen pen(brush, 1, Qt::DotLine); gc.setPen(pen); if (m_cutoutOverlay.isValid()) { gc.drawRect(m_cutoutOverlay); } if(!isEnabled()) { QColor color(Qt::lightGray); color.setAlphaF(0.5); QBrush disabledBrush(color); gc.fillRect(event->rect(), disabledBrush); } gc.end(); } void KisScratchPad::setupScratchPad(KisCanvasResourceProvider* resourceProvider, const QColor &defaultColor) { m_resourceProvider = resourceProvider; KisConfig cfg; setDisplayProfile(cfg.displayProfile(QApplication::desktop()->screenNumber(this))); connect(m_resourceProvider, SIGNAL(sigDisplayProfileChanged(const KoColorProfile*)), SLOT(setDisplayProfile(const KoColorProfile*))); connect(m_resourceProvider, SIGNAL(sigOnScreenResolutionChanged(qreal,qreal)), SLOT(setOnScreenResolution(qreal,qreal))); connect(this, SIGNAL(colorSelected(const KoColor&)), m_resourceProvider, SLOT(slotSetFGColor(const KoColor&))); m_defaultColor = KoColor(defaultColor, KoColorSpaceRegistry::instance()->rgb8()); KisPaintDeviceSP paintDevice = new KisPaintDevice(m_defaultColor.colorSpace(), "scratchpad"); m_paintLayer = new KisPaintLayer(0, "ScratchPad", OPACITY_OPAQUE_U8, paintDevice); m_paintLayer->setGraphListener(m_nodeListener); m_paintLayer->paintDevice()->setDefaultBounds(new KisScratchPadDefaultBounds(this)); fillDefault(); } void KisScratchPad::setCutoutOverlayRect(const QRect& rc) { m_cutoutOverlay = rc; } QImage KisScratchPad::cutoutOverlay() const { if(!m_paintLayer) return QImage(); KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice(); + QRect rc = widgetToDocument().mapRect(m_cutoutOverlay); QImage rawImage = paintDevice->convertToQImage(0, rc.x(), rc.y(), rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); QImage scaledImage = rawImage.scaled(m_cutoutOverlay.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); return scaledImage; } void KisScratchPad::setPresetImage(const QImage& image) { m_presetImage = image; } void KisScratchPad::paintPresetImage() { if(!m_paintLayer) return; KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice(); + QRect overlayRect = widgetToDocument().mapRect(m_cutoutOverlay); QRect imageRect(QPoint(), overlayRect.size()); QImage scaledImage = m_presetImage.scaled(overlayRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - KisPaintDeviceSP device = new KisPaintDevice(paintDevice->colorSpace()); device->convertFromQImage(scaledImage, 0); KisPainter painter(paintDevice); painter.bitBlt(overlayRect.topLeft(), device, imageRect); update(); } void KisScratchPad::allowPainting(bool allowEditing) { m_allowPainting = allowEditing; // update the cursor so it doesn't look like we can paint if (m_allowPainting) { this->setCursor(m_cursor); } else { this->setCursor(Qt::ArrowCursor); } } void KisScratchPad::setDisplayProfile(const KoColorProfile *colorProfile) { if (colorProfile) { m_displayProfile = colorProfile; QWidget::update(); } } void KisScratchPad::fillDefault() { if(!m_paintLayer) return; KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice(); paintDevice->setDefaultPixel(m_defaultColor); paintDevice->clear(); update(); } void KisScratchPad::fillGradient() { if(!m_paintLayer) return; KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice(); KoAbstractGradient* gradient = m_resourceProvider->currentGradient(); QRect gradientRect = widgetToDocument().mapRect(rect()); paintDevice->clear(); KisGradientPainter painter(paintDevice); painter.setGradient(gradient); painter.setGradientShape(KisGradientPainter::GradientShapeLinear); painter.paintGradient(gradientRect.topLeft(), gradientRect.bottomRight(), KisGradientPainter::GradientRepeatNone, 0.2, false, gradientRect.left(), gradientRect.top(), gradientRect.width(), gradientRect.height()); update(); } void KisScratchPad::fillBackground() { if(!m_paintLayer) return; KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice(); paintDevice->setDefaultPixel(m_resourceProvider->bgColor()); paintDevice->clear(); update(); } void KisScratchPad::fillLayer() { // TODO }