diff --git a/libs/image/kis_filter_mask.cpp b/libs/image/kis_filter_mask.cpp index 0ef0e01088..c74d5cae8d 100644 --- a/libs/image/kis_filter_mask.cpp +++ b/libs/image/kis_filter_mask.cpp @@ -1,182 +1,179 @@ /* * Copyright (c) 2007 Boudewijn Rempt * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "kis_layer.h" #include "kis_filter_mask.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_selection.h" #include "kis_processing_information.h" #include "kis_node.h" #include "kis_node_visitor.h" #include "kis_processing_visitor.h" #include "kis_busy_progress_indicator.h" #include "kis_transaction.h" #include "kis_painter.h" KisFilterMask::KisFilterMask() : KisEffectMask(), KisNodeFilterInterface(0, false) { setCompositeOpId(COMPOSITE_COPY); } KisFilterMask::~KisFilterMask() { } KisFilterMask::KisFilterMask(const KisFilterMask& rhs) : KisEffectMask(rhs) , KisNodeFilterInterface(rhs) { } QIcon KisFilterMask::icon() const { return KisIconUtils::loadIcon("filterMask"); } void KisFilterMask::setFilter(KisFilterConfigurationSP filterConfig) { - if (parent() && parent()->inherits("KisLayer")) { - filterConfig->setChannelFlags(qobject_cast(parent().data())->channelFlags()); - } KisNodeFilterInterface::setFilter(filterConfig); } QRect KisFilterMask::decorateRect(KisPaintDeviceSP &src, KisPaintDeviceSP &dst, const QRect & rc, PositionToFilthy maskPos) const { Q_UNUSED(maskPos); KisFilterConfigurationSP filterConfig = filter(); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(nodeProgressProxy(), rc); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE( src != dst && "KisFilterMask::decorateRect: " "src must be != dst, because we can't create transactions " "during merge, as it breaks reentrancy", rc); if (!filterConfig) { return QRect(); } KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name()); if (!filter) { warnKrita << "Could not retrieve filter \"" << filterConfig->name() << "\""; return QRect(); } KIS_ASSERT_RECOVER_NOOP(this->busyProgressIndicator()); this->busyProgressIndicator()->update(); filter->process(src, dst, 0, rc, filterConfig.data(), 0); QRect r = filter->changedRect(rc, filterConfig.data(), dst->defaultBounds()->currentLevelOfDetail()); return r; } bool KisFilterMask::accept(KisNodeVisitor &v) { return v.visit(this); } void KisFilterMask::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) { return visitor.visit(this, undoAdapter); } /** * FIXME: try to cache filter pointer inside a Private block */ QRect KisFilterMask::changeRect(const QRect &rect, PositionToFilthy pos) const { /** * FIXME: This check of the emptiness should be done * on the higher/lower level */ if(rect.isEmpty()) return rect; QRect filteredRect = rect; KisFilterConfigurationSP filterConfig = filter(); if (filterConfig) { KisNodeSP parent = this->parent(); const int lod = parent && parent->projection() ? parent->projection()->defaultBounds()->currentLevelOfDetail() : 0; KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name()); filteredRect = filter->changedRect(rect, filterConfig.data(), lod); } /** * We can't paint outside a selection, that is why we call * KisMask::changeRect to crop actual change area in the end */ filteredRect = KisMask::changeRect(filteredRect, pos); /** * FIXME: Think over this solution * Union of rects means that changeRect returns NOT the rect * changed by this very layer, but an accumulated rect changed * by all underlying layers. Just take into account and change * documentation accordingly */ return rect | filteredRect; } QRect KisFilterMask::needRect(const QRect& rect, PositionToFilthy pos) const { Q_UNUSED(pos); /** * FIXME: This check of the emptiness should be done * on the higher/lower level */ if(rect.isEmpty()) return rect; KisFilterConfigurationSP filterConfig = filter(); if (!filterConfig) return rect; KisNodeSP parent = this->parent(); const int lod = parent && parent->projection() ? parent->projection()->defaultBounds()->currentLevelOfDetail() : 0; KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name()); /** * If we need some additional pixels even outside of a selection * for accurate layer filtering, we'll get them! * And no KisMask::needRect will prevent us from doing this! ;) * That's why simply we do not call KisMask::needRect here :) */ return filter->neededRect(rect, filterConfig.data(), lod); } diff --git a/libs/ui/dialogs/kis_dlg_filter.cpp b/libs/ui/dialogs/kis_dlg_filter.cpp index fab63a1f18..21b861bbdd 100644 --- a/libs/ui/dialogs/kis_dlg_filter.cpp +++ b/libs/ui/dialogs/kis_dlg_filter.cpp @@ -1,248 +1,249 @@ /* * Copyright (c) 2007 Cyrille Berger * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_dlg_filter.h" #include #include #include #include #include #include #include +#include #include #include #include "kis_selection.h" #include "kis_node_commands_adapter.h" #include "kis_filter_manager.h" #include "ui_wdgfilterdialog.h" #include "kis_canvas2.h" struct KisDlgFilter::Private { Private(KisFilterManager *_filterManager, KisViewManager *_view) : currentFilter(0) , resizeCount(0) , view(_view) , filterManager(_filterManager) , blockModifyingActionsGuard(new KisInputActionGroupsMaskGuard(view->canvasBase(), ViewTransformActionGroup)) { } KisFilterSP currentFilter; Ui_FilterDialog uiFilterDialog; KisNodeSP node; int resizeCount; KisViewManager *view; KisFilterManager *filterManager; // a special guard object that blocks all the painting input actions while the // dialog is open QScopedPointer blockModifyingActionsGuard; }; KisDlgFilter::KisDlgFilter(KisViewManager *view, KisNodeSP node, KisFilterManager *filterManager, QWidget *parent) : QDialog(parent), d(new Private(filterManager, view)) { setModal(false); d->uiFilterDialog.setupUi(this); d->node = node; d->uiFilterDialog.filterSelection->setView(view); d->uiFilterDialog.filterSelection->showFilterGallery(KisConfig(true).showFilterGallery()); d->uiFilterDialog.pushButtonCreateMaskEffect->show(); connect(d->uiFilterDialog.pushButtonCreateMaskEffect, SIGNAL(pressed()), SLOT(createMask())); connect(d->uiFilterDialog.pushButtonCreateMaskEffect,SIGNAL(pressed()),SLOT(close())); d->uiFilterDialog.filterGalleryToggle->setChecked(d->uiFilterDialog.filterSelection->isFilterGalleryVisible()); d->uiFilterDialog.filterGalleryToggle->setIcon(QPixmap(":/pics/sidebaricon.png")); d->uiFilterDialog.filterGalleryToggle->setMaximumWidth(d->uiFilterDialog.filterGalleryToggle->height()); connect(d->uiFilterDialog.filterSelection, SIGNAL(sigFilterGalleryToggled(bool)), d->uiFilterDialog.filterGalleryToggle, SLOT(setChecked(bool))); connect(d->uiFilterDialog.filterGalleryToggle, SIGNAL(toggled(bool)), d->uiFilterDialog.filterSelection, SLOT(showFilterGallery(bool))); connect(d->uiFilterDialog.filterSelection, SIGNAL(sigSizeChanged()), this, SLOT(slotFilterWidgetSizeChanged())); if (node->inherits("KisMask")) { d->uiFilterDialog.pushButtonCreateMaskEffect->setVisible(false); } d->uiFilterDialog.filterSelection->setPaintDevice(true, d->node->original()); connect(d->uiFilterDialog.buttonBox, SIGNAL(accepted()), SLOT(accept())); connect(d->uiFilterDialog.buttonBox, SIGNAL(rejected()), SLOT(reject())); connect(d->uiFilterDialog.checkBoxPreview, SIGNAL(toggled(bool)), SLOT(enablePreviewToggled(bool))); connect(d->uiFilterDialog.filterSelection, SIGNAL(configurationChanged()), SLOT(filterSelectionChanged())); connect(this, SIGNAL(accepted()), SLOT(slotOnAccept())); connect(this, SIGNAL(rejected()), SLOT(slotOnReject())); KConfigGroup group( KSharedConfig::openConfig(), "filterdialog"); d->uiFilterDialog.checkBoxPreview->setChecked(group.readEntry("showPreview", true)); restoreGeometry(KisConfig(true).readEntry("filterdialog/geometry", QByteArray())); } KisDlgFilter::~KisDlgFilter() { KisConfig(false).writeEntry("filterdialog/geometry", saveGeometry()); delete d; } void KisDlgFilter::setFilter(KisFilterSP f) { Q_ASSERT(f); setDialogTitle(f); d->uiFilterDialog.filterSelection->setFilter(f); d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(f->supportsAdjustmentLayers()); d->currentFilter = f; updatePreview(); } void KisDlgFilter::setDialogTitle(KisFilterSP filter) { setWindowTitle(filter.isNull() ? i18nc("@title:window", "Filter") : i18nc("@title:window", "Filter: %1", filter->name())); } void KisDlgFilter::startApplyingFilter(KisFilterConfigurationSP config) { if (!d->uiFilterDialog.filterSelection->configuration()) return; - if (d->node->inherits("KisLayer")) { - config->setChannelFlags(qobject_cast(d->node.data())->channelFlags()); + if (d->node->inherits("KisPaintLayer")) { + config->setChannelFlags(qobject_cast(d->node.data())->channelLockFlags()); } d->filterManager->apply(config); } void KisDlgFilter::updatePreview() { KisFilterConfigurationSP config = d->uiFilterDialog.filterSelection->configuration(); if (!config) return; bool maskCreationAllowed = !d->currentFilter || d->currentFilter->configurationAllowedForMask(config); d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(maskCreationAllowed); if (d->uiFilterDialog.checkBoxPreview->isChecked()) { KisFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration()); startApplyingFilter(config); } d->uiFilterDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } void KisDlgFilter::adjustSize() { QWidget::adjustSize(); } void KisDlgFilter::slotFilterWidgetSizeChanged() { QMetaObject::invokeMethod(this, "adjustSize", Qt::QueuedConnection); } void KisDlgFilter::slotOnAccept() { if (!d->filterManager->isStrokeRunning()) { KisFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration()); startApplyingFilter(config); } d->filterManager->finish(); d->uiFilterDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); KisConfig(false).setShowFilterGallery(d->uiFilterDialog.filterSelection->isFilterGalleryVisible()); } void KisDlgFilter::slotOnReject() { if (d->filterManager->isStrokeRunning()) { d->filterManager->cancel(); } KisConfig(false).setShowFilterGallery(d->uiFilterDialog.filterSelection->isFilterGalleryVisible()); } void KisDlgFilter::createMask() { if (d->node->inherits("KisMask")) return; if (d->filterManager->isStrokeRunning()) { d->filterManager->cancel(); } KisLayer *layer = qobject_cast(d->node.data()); KisFilterMaskSP mask = new KisFilterMask(); mask->setName(d->currentFilter->name()); mask->initSelection(d->view->selection(), layer); mask->setFilter(d->uiFilterDialog.filterSelection->configuration()); Q_ASSERT(layer->allowAsChild(mask)); KisNodeCommandsAdapter adapter(d->view); adapter.addNode(mask, layer, layer->lastChild()); } void KisDlgFilter::enablePreviewToggled(bool state) { if (state) { updatePreview(); } else if (d->filterManager->isStrokeRunning()) { d->filterManager->cancel(); } KConfigGroup group( KSharedConfig::openConfig(), "filterdialog"); group.writeEntry("showPreview", d->uiFilterDialog.checkBoxPreview->isChecked()); group.config()->sync(); } void KisDlgFilter::filterSelectionChanged() { KisFilterSP filter = d->uiFilterDialog.filterSelection->currentFilter(); setDialogTitle(filter); d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(filter.isNull() ? false : filter->supportsAdjustmentLayers()); updatePreview(); } void KisDlgFilter::resizeEvent(QResizeEvent* event) { QDialog::resizeEvent(event); // // Workaround, after the initialisation don't center the dialog anymore // if(d->resizeCount < 2) { // QWidget* canvas = d->view->canvas(); // QRect rect(canvas->mapToGlobal(canvas->geometry().topLeft()), size()); // int deltaX = (canvas->geometry().width() - geometry().width())/2; // int deltaY = (canvas->geometry().height() - geometry().height())/2; // rect.translate(deltaX, deltaY); // setGeometry(rect); // d->resizeCount++; // } }