[calligra] krita: Major fixes for the Krita filtering system

Dmitry Kazakov dimula73 at gmail.com
Thu May 30 19:55:41 UTC 2013


Git commit 8ace3ad4756d1f0a9a1b13997dae54215629af0f by Dmitry Kazakov.
Committed on 30/05/2013 at 20:10.
Pushed by dkazakov into branch 'master'.

Major fixes for the Krita filtering system

Now there is no preview mask thing. All the preview is generated
by the strokes system is absolutely the same way as it is done
for real filtering. This effectively fixes two things:

1) Filter preview for masks
2) Fixes a crash when pressing OK while the preview update is running

The patch also removes the KisFilterHandler thing, because it made
switching filters in the filter dialog fail (you could switch them,
by it didn't have any effect). Now its work is done by a simple
QSignalMapper.

CCMAIL:kimageshop at kde.org

M  +0    -26   krita/image/kis_layer.cc
M  +0    -10   krita/image/kis_layer.h
M  +2    -12   krita/image/tests/kis_layer_test.cpp
M  +0    -1    krita/image/tests/kis_layer_test.h
M  +0    -1    krita/ui/CMakeLists.txt
M  +44   -52   krita/ui/dialogs/kis_dlg_filter.cpp
M  +4    -4    krita/ui/dialogs/kis_dlg_filter.h
D  +0    -181  krita/ui/kis_filter_handler.cc
D  +0    -57   krita/ui/kis_filter_handler.h
M  +174  -29   krita/ui/kis_filter_manager.cc
M  +9    -5    krita/ui/kis_filter_manager.h

http://commits.kde.org/calligra/8ace3ad4756d1f0a9a1b13997dae54215629af0f

diff --git a/krita/image/kis_layer.cc b/krita/image/kis_layer.cc
index 00ee756..96b7216 100644
--- a/krita/image/kis_layer.cc
+++ b/krita/image/kis_layer.cc
@@ -38,7 +38,6 @@
 #include "kis_painter.h"
 #include "kis_mask.h"
 #include "kis_effect_mask.h"
-#include "kis_transparency_mask.h"
 #include "kis_selection_mask.h"
 #include "kis_meta_data_store.h"
 #include "kis_selection.h"
@@ -112,7 +111,6 @@ public:
 
     KisImageWSP image;
     QBitArray channelFlags;
-    KisEffectMaskSP previewMask;
     KisMetaData::Store* metaDataStore;
     KisSafeProjection safeProjection;
     KisCloneLayersList clonesList;
@@ -299,10 +297,6 @@ QList<KisEffectMaskSP> KisLayer::effectMasks() const
 {
     QList<KisEffectMaskSP> masks;
 
-    if (m_d->previewMask && m_d->previewMask->visible()) {
-        masks.append(m_d->previewMask);
-    }
-
     if (childCount() > 0) {
         KoProperties properties;
         properties.setProperty("visible", true);
@@ -319,7 +313,6 @@ QList<KisEffectMaskSP> KisLayer::effectMasks() const
 
 bool KisLayer::hasEffectMasks() const
 {
-    if (m_d->previewMask && m_d->previewMask->visible()) return true;
     if (childCount() == 0) return false;
 
     KoProperties properties;
@@ -559,25 +552,6 @@ QRect KisLayer::exactBounds() const
     return originalDevice ? originalDevice->exactBounds() : QRect();
 }
 
-
-void KisLayer::setPreviewMask(KisEffectMaskSP mask)
-{
-    if (m_d->previewMask) {
-        m_d->previewMask->setParent(0);
-        m_d->previewMask = 0;
-    }
-
-    if (mask) {
-        m_d->previewMask = mask;
-        m_d->previewMask->setParent(this);
-    }
-}
-
-KisEffectMaskSP KisLayer::previewMask() const
-{
-    return m_d->previewMask;
-}
-
 KisLayerSP KisLayer::parentLayer() const
 {
     return dynamic_cast<KisLayer*>(parent().data());
diff --git a/krita/image/kis_layer.h b/krita/image/kis_layer.h
index 3a24c55..eb36e26 100644
--- a/krita/image/kis_layer.h
+++ b/krita/image/kis_layer.h
@@ -235,16 +235,6 @@ public:
     QRect changeRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const;
 
     /**
-     * Set a temporary effect mask on this layer for filter previews.
-     */
-    void setPreviewMask(KisEffectMaskSP mask);
-
-    /**
-     * Retrieve the current preview effect mask
-     */
-    KisEffectMaskSP previewMask() const;
-
-    /**
      * Get the group layer that contains this layer.
      */
     KisLayerSP parentLayer() const;
diff --git a/krita/image/tests/kis_layer_test.cpp b/krita/image/tests/kis_layer_test.cpp
index 61e59b2..500f8b8 100644
--- a/krita/image/tests/kis_layer_test.cpp
+++ b/krita/image/tests/kis_layer_test.cpp
@@ -225,18 +225,6 @@ void KisLayerTest::testMoveLayer()
 
 }
 
-void KisLayerTest::testHasEffectMasks()
-{
-    KisLayerSP layer = new TestLayer(0, "layer1", OPACITY_OPAQUE_U8);
-    QVERIFY(layer->hasEffectMasks() == false);
-    KisFilterMaskSP mask = new KisFilterMask();
-    layer->setPreviewMask(mask);
-    QVERIFY(layer->hasEffectMasks());
-    layer->setPreviewMask(0);
-    QVERIFY(layer->hasEffectMasks() == false);
-}
-
-
     /*
       +----------+
       |root      |
@@ -269,6 +257,8 @@ void KisLayerTest::testMasksChangeRect()
     image->addNode(filterMask1, paintLayer1);
     image->addNode(filterMask2, paintLayer1);
 
+    QVERIFY(paintLayer1->hasEffectMasks());
+
     QRect testRect(10, 10, 100, 100);
     QRect resultRect;
 
diff --git a/krita/image/tests/kis_layer_test.h b/krita/image/tests/kis_layer_test.h
index 6a95443..f190a26 100644
--- a/krita/image/tests/kis_layer_test.h
+++ b/krita/image/tests/kis_layer_test.h
@@ -105,7 +105,6 @@ private slots:
     void testOrdering();
     void testMoveNode();
     void testMoveLayer();
-    void testHasEffectMasks();
     void testMasksChangeRect();
     void testMoveLayerWithMaskThreaded();
 };
diff --git a/krita/ui/CMakeLists.txt b/krita/ui/CMakeLists.txt
index 9ba9c11..9cfa6e9 100644
--- a/krita/ui/CMakeLists.txt
+++ b/krita/ui/CMakeLists.txt
@@ -75,7 +75,6 @@ set(kritaui_LIB_SRCS
     kis_part2.cpp
     kis_factory2.cc
     kis_file_layer.cpp
-    kis_filter_handler.cc
     kis_filter_manager.cc
     kis_filters_model.cc
     kis_flipbook.cpp
diff --git a/krita/ui/dialogs/kis_dlg_filter.cpp b/krita/ui/dialogs/kis_dlg_filter.cpp
index 0fd80d0..373647b 100644
--- a/krita/ui/dialogs/kis_dlg_filter.cpp
+++ b/krita/ui/dialogs/kis_dlg_filter.cpp
@@ -25,32 +25,32 @@
 #include <kis_filter_mask.h>
 #include <kis_node.h>
 #include <kis_layer.h>
-#include <kis_selection.h>
 #include <kis_view2.h>
 #include <kis_config.h>
 
+#include "kis_selection.h"
 #include "kis_node_commands_adapter.h"
+#include "kis_filter_manager.h"
 #include "ui_wdgfilterdialog.h"
 
 
 struct KisFilterDialog::Private {
     Private()
             : currentFilter(0)
-            , mask(0)
             , resizeCount(0)
-            , view(0) {
+            , view(0)
+    {
     }
 
     KisFilterSP currentFilter;
     Ui_FilterDialog uiFilterDialog;
-    KisFilterMaskSP mask;
     KisNodeSP node;
-    KisImageWSP image;
     int resizeCount;
     KisView2 *view;
+    KisFilterManager *filterManager;
 };
 
-KisFilterDialog::KisFilterDialog(KisView2 *view, KisNodeSP node, KisImageWSP image, KisSelectionSP selection) :
+KisFilterDialog::KisFilterDialog(KisView2 *view, KisNodeSP node, KisFilterManager *filterManager) :
         QDialog(view),
         d(new Private)
 {
@@ -58,26 +58,14 @@ KisFilterDialog::KisFilterDialog(KisView2 *view, KisNodeSP node, KisImageWSP ima
 
     d->uiFilterDialog.setupUi(this);
     d->node = node;
-    d->image = image;
     d->view = view;
+    d->filterManager = filterManager;
 
     d->uiFilterDialog.filterSelection->setView(view);
     d->uiFilterDialog.filterSelection->showFilterGallery(KisConfig().showFilterGallery());
 
-    if (d->node->inherits("KisLayer")) {
-        KisLayer *layer = dynamic_cast<KisLayer*>(node.data());
-        d->mask = new KisFilterMask();
-        d->mask->initSelection(selection, layer);
-        layer->setPreviewMask(d->mask);
-
-        d->uiFilterDialog.checkBoxPreview->show();
-        d->uiFilterDialog.pushButtonCreateMaskEffect->show();
-        d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(true);
-        connect(d->uiFilterDialog.pushButtonCreateMaskEffect, SIGNAL(pressed()), SLOT(createMask()));
-    } else {
-        d->uiFilterDialog.checkBoxPreview->hide();
-        d->uiFilterDialog.pushButtonCreateMaskEffect->hide();
-    }
+    d->uiFilterDialog.pushButtonCreateMaskEffect->show();
+    connect(d->uiFilterDialog.pushButtonCreateMaskEffect, SIGNAL(pressed()), SLOT(createMask()));
 
     d->uiFilterDialog.filterSelection->setPaintDevice(d->node->original());
     d->uiFilterDialog.pushButtonOk->setGuiItem(KStandardGuiItem::ok());
@@ -104,41 +92,48 @@ void KisFilterDialog::setFilter(KisFilterSP f)
 {
     Q_ASSERT(f);
     setWindowTitle(f->name());
-    d->currentFilter = f;
     d->uiFilterDialog.filterSelection->setFilter(f);
     updatePreview();
 }
 
-void KisFilterDialog::updatePreview()
+void KisFilterDialog::startApplyingFilter(KisSafeFilterConfigurationSP config)
 {
-    if (!d->currentFilter) return;
+    if (!d->uiFilterDialog.filterSelection->configuration()) return;
 
-    if(d->mask && d->uiFilterDialog.checkBoxPreview->isChecked()) {
-        d->mask->setFilter(d->uiFilterDialog.filterSelection->configuration());
+    if (d->node->inherits("KisLayer")) {
+        config->setChannelFlags(qobject_cast<KisLayer*>(d->node.data())->channelFlags());
     }
 
-    d->node->setDirty();
+    d->filterManager->apply(config);
+}
+
+void KisFilterDialog::updatePreview()
+{
+    if (!d->uiFilterDialog.filterSelection->configuration()) return;
+
+    if (d->uiFilterDialog.checkBoxPreview->isChecked()) {
+        KisSafeFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration());
+        startApplyingFilter(config);
+    }
 
     d->uiFilterDialog.pushButtonOk->setEnabled(true);
 }
 
 void KisFilterDialog::apply()
 {
-    if (!d->currentFilter) return;
-
-    KisSafeFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration());
-    if (d->node->inherits("KisLayer")) {
-        config->setChannelFlags(qobject_cast<KisLayer*>(d->node.data())->channelFlags());
+    if (!d->filterManager->isStrokeRunning()) {
+        KisSafeFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration());
+        startApplyingFilter(config);
     }
-    emit(sigPleaseApplyFilter(config));
+    d->filterManager->finish();
+
     d->uiFilterDialog.pushButtonOk->setEnabled(false);
 }
 
 void KisFilterDialog::close()
 {
-    if (d->mask) {
-        qobject_cast<KisLayer*>(d->node.data())->setPreviewMask(0);;
-        d->node->setDirty();
+    if (d->filterManager->isStrokeRunning()) {
+        d->filterManager->cancel();
     }
 
     KisConfig().setShowFilterGallery(d->uiFilterDialog.filterSelection->isFilterGalleryVisible());
@@ -146,28 +141,29 @@ void KisFilterDialog::close()
 
 void KisFilterDialog::createMask()
 {
-    if (!d->mask) return;
+    if (d->filterManager->isStrokeRunning()) {
+        d->filterManager->cancel();
+    }
 
     KisLayer *layer = dynamic_cast<KisLayer*>(d->node.data());
-    layer->setPreviewMask(0);
+    KisFilterMaskSP mask = new KisFilterMask();
+    mask->initSelection(d->view->selection(), layer);
+    mask->setFilter(d->uiFilterDialog.filterSelection->configuration());
 
-    Q_ASSERT(layer->allowAsChild(d->mask));
-    Q_ASSERT(d->mask->parent() == 0);
+    Q_ASSERT(layer->allowAsChild(mask));
 
     KisNodeCommandsAdapter adapter(d->view);
-    adapter.addNode(d->mask, layer, layer->lastChild());
-
-
-    d->mask = 0;
+    adapter.addNode(mask, layer, layer->lastChild());
     accept();
 }
 
 void KisFilterDialog::previewCheckBoxChange(int state)
 {
-    if (!d->mask) return;
-
-    d->mask->setVisible(state == Qt::Checked);
-    updatePreview();
+    if (state) {
+        updatePreview();
+    } else if (d->filterManager->isStrokeRunning()) {
+        d->filterManager->cancel();
+    }
 
     KConfigGroup group(KGlobal::config(), "filterdialog");
     group.writeEntry("showPreview", d->uiFilterDialog.checkBoxPreview->isChecked());
@@ -190,7 +186,3 @@ void KisFilterDialog::resizeEvent(QResizeEvent* event)
         d->resizeCount++;
     }
 }
-
-
-
-#include "kis_dlg_filter.moc"
diff --git a/krita/ui/dialogs/kis_dlg_filter.h b/krita/ui/dialogs/kis_dlg_filter.h
index 86c1e8c..6f2170e 100644
--- a/krita/ui/dialogs/kis_dlg_filter.h
+++ b/krita/ui/dialogs/kis_dlg_filter.h
@@ -27,6 +27,7 @@
 class KisFilter;
 class KisFilterConfiguration;
 class KisView2;
+class KisFilterManager;
 
 class KisFilterDialog : public QDialog
 {
@@ -35,7 +36,7 @@ class KisFilterDialog : public QDialog
 
 public:
 
-    KisFilterDialog(KisView2 *view, KisNodeSP node, KisImageWSP image, KisSelectionSP selection = 0);
+    KisFilterDialog(KisView2 *view, KisNodeSP node, KisFilterManager *filterManager);
 
     ~KisFilterDialog();
 
@@ -57,9 +58,8 @@ protected slots:
 
     virtual void resizeEvent(QResizeEvent* );
 
-signals:
-
-    void sigPleaseApplyFilter(KisSafeFilterConfigurationSP);
+private:
+    void startApplyingFilter(KisSafeFilterConfigurationSP config);
 
 private:
     struct Private;
diff --git a/krita/ui/kis_filter_handler.cc b/krita/ui/kis_filter_handler.cc
deleted file mode 100644
index 3806a36..0000000
--- a/krita/ui/kis_filter_handler.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *  Copyright (c) 2007 Cyrille Berger <cberger at cberger.net>
- *  Copyright (c) 2007 Boudewijn Rempt <boud at valdyas.org>
- *
- *  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_filter_handler.h"
-#include <kmessagebox.h>
-
-#include "kis_view2.h"
-#include "kis_canvas2.h"
-#include "kis_filter_manager.h"
-#include "dialogs/kis_dlg_filter.h"
-
-#include "strokes/kis_filter_stroke_strategy.h"
-#include "krita_utils.h"
-
-#include <kis_bookmarked_configuration_manager.h>
-#include <filter/kis_filter.h>
-#include <filter/kis_filter_configuration.h>
-
-
-struct KisFilterHandler::Private {
-
-    Private(KisFilterHandler *_q)
-            : view(0)
-            , manager(0)
-            , q(_q)
-    {
-    }
-
-    ~Private() {
-    }
-
-    KisFilterSP filter;
-
-    KisView2* view;
-    KisFilterManager* manager;
-
-    KisSafeFilterConfigurationSP lastConfiguration;
-    KisFilterHandler *q;
-
-    void saveConfiguration(KisFilterSP filter, KisSafeFilterConfigurationSP filterConfig);
-};
-
-void KisFilterHandler::Private::saveConfiguration(KisFilterSP filter, KisSafeFilterConfigurationSP filterConfig)
-{
-    if (filter->bookmarkManager()) {
-        filter->bookmarkManager()->save(KisBookmarkedConfigurationManager::ConfigLastUsed.id(),
-                                        filterConfig.data());
-    }
-
-    lastConfiguration = filterConfig;
-    manager->setLastFilterHandler(q);
-}
-
-
-KisFilterHandler::KisFilterHandler(KisFilterManager* parent, KisFilterSP f, KisView2* view)
-        : QObject(parent)
-        , m_d(new Private(this))
-{
-    m_d->filter = f;
-    m_d->view = view;
-    m_d->manager = parent;
-}
-
-KisFilterHandler::~KisFilterHandler()
-{
-    delete m_d;
-}
-
-void KisFilterHandler::showDialog()
-{
-    /**
-     * HACK ALERT:
-     * Until filters are ported to strokes, there should be a barrier
-     * to finish all the running strokes in the system
-     */
-    m_d->view->image()->barrierLock();
-    m_d->view->image()->unlock();
-
-    KisPaintDeviceSP dev = m_d->view->activeNode()->paintDevice();
-    if (!dev) {
-        qWarning() << "KisFilterHandler::showDialog(): Filtering was requested for illegal active layer!" << m_d->view->activeNode();
-        return;
-    }
-
-    if (dev->colorSpace()->willDegrade(m_d->filter->colorSpaceIndependence())) {
-        // Warning bells!
-        if (m_d->filter->colorSpaceIndependence() == TO_LAB16) {
-            if (KMessageBox::warningContinueCancel(m_d->view,
-                                                   i18n("The %1 filter will convert your %2 data to 16-bit L*a*b* and vice versa. ",
-                                                        m_d->filter->name(),
-                                                        dev->colorSpace()->name()),
-                                                   i18n("Filter Will Convert Your Layer Data"),
-                                                   KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
-                                                   "lab16degradation") != KMessageBox::Continue) return;
-
-        } else if (m_d->filter->colorSpaceIndependence() == TO_RGBA16) {
-            if (KMessageBox::warningContinueCancel(m_d->view,
-                                                   i18n("The %1 filter will convert your %2 data to 16-bit RGBA and vice versa. ",
-                                                        m_d->filter->name() , dev->colorSpace()->name()),
-                                                   i18n("Filter Will Convert Your Layer Data"),
-                                                   KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
-                                                   "rgba16degradation") != KMessageBox::Continue) return;
-        }
-    }
-
-    if (m_d->filter->showConfigurationWidget()) {
-        KisFilterDialog* dialog = new KisFilterDialog(m_d->view , m_d->view->activeNode(), m_d->view->image(), m_d->view->selection());
-        dialog->setFilter(m_d->filter);
-        connect(dialog, SIGNAL(sigPleaseApplyFilter(KisSafeFilterConfigurationSP)),
-                SLOT(apply(KisSafeFilterConfigurationSP)));
-        dialog->setVisible(true);
-        dialog->setAttribute(Qt::WA_DeleteOnClose);
-    } else {
-        apply(KisSafeFilterConfigurationSP(m_d->filter->defaultConfiguration(m_d->view->activeNode()->original())));
-    }
-}
-
-void KisFilterHandler::reapply()
-{
-    apply(m_d->lastConfiguration);
-}
-
-void KisFilterHandler::apply(KisSafeFilterConfigurationSP config)
-{
-    KisSafeFilterConfigurationSP filterConfig(config);
-
-    KisImageWSP image = m_d->view->image();
-    KisPostExecutionUndoAdapter *undoAdapter =
-        image->postExecutionUndoAdapter();
-    KoCanvasResourceManager *resourceManager =
-        m_d->view->canvasBase()->resourceManager();
-
-    KisResourcesSnapshotSP resources =
-        new KisResourcesSnapshot(image,
-                                 undoAdapter,
-                                 resourceManager);
-
-    KisStrokeId strokeId =
-        image->startStroke(new KisFilterStrokeStrategy(m_d->filter,
-                                                       KisSafeFilterConfigurationSP(filterConfig),
-                                                       resources));
-
-    if (m_d->filter->supportsThreading()) {
-        QSize size = KritaUtils::optimalPatchSize();
-        QVector<QRect> rects = KritaUtils::splitRectIntoPatches(image->bounds(), size);
-
-        foreach(const QRect &rc, rects) {
-            image->addJob(strokeId,
-                          new KisFilterStrokeStrategy::Data(rc, true));
-        }
-    } else {
-        image->addJob(strokeId,
-                      new KisFilterStrokeStrategy::Data(image->bounds(), false));
-    }
-
-    image->endStroke(strokeId);
-
-    m_d->saveConfiguration(m_d->filter, filterConfig);
-}
-
-const QString KisFilterHandler::filterName() const
-{
-    return m_d->filter->name();
-}
-
diff --git a/krita/ui/kis_filter_handler.h b/krita/ui/kis_filter_handler.h
deleted file mode 100644
index 9743121..0000000
--- a/krita/ui/kis_filter_handler.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Copyright (c) 2007 Cyrille Berger <cberger at cberger.net>
- *
- *  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_FILTER_HANDLER_H_
-#define _KIS_FILTER_HANDLER_H_
-
-#include <QObject>
-
-#include <kis_types.h>
-
-class KisFilterConfiguration;
-class KisFilterManager;
-class KisLayer;
-class KisView2;
-class QRect;
-
-/**
- * XXX: this class is way too confusing.
- */
-class KisFilterHandler : public QObject
-{
-
-    Q_OBJECT
-
-public:
-
-    KisFilterHandler(KisFilterManager* parent, KisFilterSP f, KisView2* view);
-    ~KisFilterHandler();
-
-    const QString filterName() const;
-
-public slots:
-    void showDialog();
-    void reapply();
-    void apply(KisSafeFilterConfigurationSP filterConfig);
-
-private:
-    struct Private;
-    Private* const m_d;
-};
-
-#endif
diff --git a/krita/ui/kis_filter_manager.cc b/krita/ui/kis_filter_manager.cc
index 6fdca92..48a2f1f 100644
--- a/krita/ui/kis_filter_manager.cc
+++ b/krita/ui/kis_filter_manager.cc
@@ -22,7 +22,9 @@
 #include "kis_filter_manager.moc"
 
 #include <QHash>
+#include <QSignalMapper>
 
+#include <kmessagebox.h>
 #include <kactionmenu.h>
 #include <kactioncollection.h>
 
@@ -31,15 +33,19 @@
 // krita/image
 #include <filter/kis_filter.h>
 #include <filter/kis_filter_registry.h>
-#include <kis_layer.h>
-#include <kis_paint_layer.h>
+#include <filter/kis_filter_configuration.h>
 #include <kis_paint_device.h>
 
 // krita/ui
-#include "kis_filter_handler.h"
 #include "kis_view2.h"
+#include "kis_canvas2.h"
+#include <kis_bookmarked_configuration_manager.h>
 #include <KoColorSpaceRegistry.h>
-#include <KoColorSpaceRegistry.h>
+
+#include "dialogs/kis_dlg_filter.h"
+#include "strokes/kis_filter_stroke_strategy.h"
+#include "krita_utils.h"
+
 
 struct KisFilterManager::Private {
     Private() : reapplyAction(0), actionCollection(0) {
@@ -47,16 +53,24 @@ struct KisFilterManager::Private {
     }
     KAction* reapplyAction;
     QHash<QString, KActionMenu*> filterActionMenus;
-    QHash<QString, KisFilterHandler*> filterHandlers;
     QHash<KisFilter*, KAction*> filters2Action;
-    KActionCollection * actionCollection;
-    KisView2* view;
+    KActionCollection *actionCollection;
+    KisView2 *view;
+
+
+
+
+    KisSafeFilterConfigurationSP lastConfiguration;
+    KisSafeFilterConfigurationSP currentlyAppliedCofiguration;
+    KisStrokeId currentStrokeId;
+
+    QSignalMapper actionsMapper;
 };
 
-KisFilterManager::KisFilterManager(KisView2 * parent, KisDoc2 * doc) : d(new Private)
+KisFilterManager::KisFilterManager(KisView2 * view, KisDoc2 * doc) : d(new Private)
 {
     Q_UNUSED(doc);
-    d->view = parent;
+    d->view = view;
 }
 
 KisFilterManager::~KisFilterManager()
@@ -71,26 +85,33 @@ void KisFilterManager::setup(KActionCollection * ac)
     // Setup reapply action
     d->reapplyAction = new KAction(i18n("Apply Filter Again"), this);
     d->actionCollection->addAction("filter_apply_again", d->reapplyAction);
+
     d->reapplyAction->setEnabled(false);
+    connect(d->reapplyAction, SIGNAL(triggered()), SLOT(reapplyLastFilter()));
+
+    connect(&d->actionsMapper, SIGNAL(mapped(const QString&)), SLOT(showFilterDialog(const QString&)));
 
     // Setup list of filters
-    QList<QString> filterList = KisFilterRegistry::instance()->keys();
-    for (QList<QString>::Iterator it = filterList.begin(); it != filterList.end(); ++it) {
-        insertFilter(*it);
+    foreach (const QString &filterName, KisFilterRegistry::instance()->keys()) {
+        insertFilter(filterName);
     }
+
     connect(KisFilterRegistry::instance(), SIGNAL(filterAdded(QString)), SLOT(insertFilter(const QString &)));
 }
 
-void KisFilterManager::insertFilter(const QString & name)
+void KisFilterManager::insertFilter(const QString & filterName)
 {
     Q_ASSERT(d->actionCollection);
-    KisFilterSP f = KisFilterRegistry::instance()->value(name);
-    Q_ASSERT(f);
-    if (d->filters2Action.keys().contains(f.data())) {
-        warnKrita << "Filter" << name << " has already been inserted";
+
+    KisFilterSP filter = KisFilterRegistry::instance()->value(filterName);
+    Q_ASSERT(filter);
+
+    if (d->filters2Action.keys().contains(filter.data())) {
+        warnKrita << "Filter" << filterName << " has already been inserted";
         return;
     }
-    KoID category = f->menuCategory();
+
+    KoID category = filter->menuCategory();
     KActionMenu* actionMenu = d->filterActionMenus[ category.id()];
     if (!actionMenu) {
         actionMenu = new KActionMenu(category.name(), this);
@@ -98,14 +119,15 @@ void KisFilterManager::insertFilter(const QString & name)
         d->filterActionMenus[category.id()] = actionMenu;
     }
 
-    KisFilterHandler* handler = new KisFilterHandler(this, f, d->view);
+    KAction *action = new KAction(filter->menuEntry(), this);
+    action->setShortcut(filter->shortcut(), KAction::DefaultShortcut);
+    d->actionCollection->addAction(QString("krita_filter_%1").arg(filterName), action);
+    d->filters2Action[filter.data()] = action;
 
-    KAction * a = new KAction(f->menuEntry(), this);
-    a->setShortcut(f->shortcut(), KAction::DefaultShortcut);
-    d->actionCollection->addAction(QString("krita_filter_%1").arg(name), a);
-    d->filters2Action[f.data()] = a;
-    connect(a, SIGNAL(triggered()), handler, SLOT(showDialog()));
-    actionMenu->addAction(a); 
+    actionMenu->addAction(action);
+
+    d->actionsMapper.setMapping(action, filterName);
+    connect(action, SIGNAL(triggered()), &d->actionsMapper, SLOT(map()));
 }
 
 void KisFilterManager::updateGUI()
@@ -129,11 +151,134 @@ void KisFilterManager::updateGUI()
     }
 }
 
-void KisFilterManager::setLastFilterHandler(KisFilterHandler* handler)
+void KisFilterManager::reapplyLastFilter()
 {
-    disconnect(d->reapplyAction, SIGNAL(triggered()), 0 , 0);
-    connect(d->reapplyAction, SIGNAL(triggered()), handler, SLOT(reapply()));
+    if (!d->lastConfiguration) return;
+
+    apply(d->lastConfiguration);
+    finish();
+}
+
+void KisFilterManager::showFilterDialog(const QString &filterId)
+{
+    /**
+     * The UI should show only after every running stroke is finished,
+     * so the barrier is added here.
+     */
+    d->view->image()->barrierLock();
+    d->view->image()->unlock();
+
+    KisPaintDeviceSP dev = d->view->activeNode()->paintDevice();
+    if (!dev) {
+        qWarning() << "KisFilterManager::showFilterDialog(): Filtering was requested for illegal active layer!" << d->view->activeNode();
+        return;
+    }
+
+    KisFilterSP filter = KisFilterRegistry::instance()->value(filterId);
+
+    if (dev->colorSpace()->willDegrade(filter->colorSpaceIndependence())) {
+        // Warning bells!
+        if (filter->colorSpaceIndependence() == TO_LAB16) {
+            if (KMessageBox::warningContinueCancel(d->view,
+                                                   i18n("The %1 filter will convert your %2 data to 16-bit L*a*b* and vice versa. ",
+                                                        filter->name(),
+                                                        dev->colorSpace()->name()),
+                                                   i18n("Filter Will Convert Your Layer Data"),
+                                                   KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
+                                                   "lab16degradation") != KMessageBox::Continue) return;
+
+        } else if (filter->colorSpaceIndependence() == TO_RGBA16) {
+            if (KMessageBox::warningContinueCancel(d->view,
+                                                   i18n("The %1 filter will convert your %2 data to 16-bit RGBA and vice versa. ",
+                                                        filter->name() , dev->colorSpace()->name()),
+                                                   i18n("Filter Will Convert Your Layer Data"),
+                                                   KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
+                                                   "rgba16degradation") != KMessageBox::Continue) return;
+        }
+    }
+
+    if (filter->showConfigurationWidget()) {
+        KisFilterDialog* dialog = new KisFilterDialog(d->view , d->view->activeNode(), this);
+        dialog->setFilter(filter);
+        dialog->setVisible(true);
+        dialog->setAttribute(Qt::WA_DeleteOnClose);
+    } else {
+        apply(KisSafeFilterConfigurationSP(filter->defaultConfiguration(d->view->activeNode()->original())));
+        finish();
+    }
+}
+
+void KisFilterManager::apply(KisSafeFilterConfigurationSP filterConfig)
+{
+    KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name());
+    KisImageWSP image = d->view->image();
+
+    if (d->currentStrokeId) {
+        image->cancelStroke(d->currentStrokeId);
+    }
+
+    KisPostExecutionUndoAdapter *undoAdapter =
+        image->postExecutionUndoAdapter();
+    KoCanvasResourceManager *resourceManager =
+        d->view->canvasBase()->resourceManager();
+
+    KisResourcesSnapshotSP resources =
+        new KisResourcesSnapshot(image,
+                                 undoAdapter,
+                                 resourceManager);
+
+    d->currentStrokeId =
+        image->startStroke(new KisFilterStrokeStrategy(filter,
+                                                       KisSafeFilterConfigurationSP(filterConfig),
+                                                       resources));
+
+    if (filter->supportsThreading()) {
+        QSize size = KritaUtils::optimalPatchSize();
+        QVector<QRect> rects = KritaUtils::splitRectIntoPatches(image->bounds(), size);
+
+        foreach(const QRect &rc, rects) {
+            image->addJob(d->currentStrokeId,
+                          new KisFilterStrokeStrategy::Data(rc, true));
+        }
+    } else {
+        image->addJob(d->currentStrokeId,
+                      new KisFilterStrokeStrategy::Data(image->bounds(), false));
+    }
+
+    d->currentlyAppliedCofiguration = filterConfig;
+}
+
+void KisFilterManager::finish()
+{
+    Q_ASSERT(d->currentStrokeId);
+
+    d->view->image()->endStroke(d->currentStrokeId);
+
+    KisFilterSP filter = KisFilterRegistry::instance()->value(d->currentlyAppliedCofiguration->name());
+    if (filter->bookmarkManager()) {
+        filter->bookmarkManager()->save(KisBookmarkedConfigurationManager::ConfigLastUsed.id(),
+                                       d->currentlyAppliedCofiguration.data());
+    }
+
+    d->lastConfiguration = d->currentlyAppliedCofiguration;
     d->reapplyAction->setEnabled(true);
-    d->reapplyAction->setText(i18n("Apply Filter Again: %1", handler->filterName()));
+    d->reapplyAction->setText(i18n("Apply Filter Again: %1", filter->name()));
+
+    d->currentStrokeId.clear();
+    d->currentlyAppliedCofiguration.clear();
 }
 
+void KisFilterManager::cancel()
+{
+    Q_ASSERT(d->currentStrokeId);
+
+    d->view->image()->cancelStroke(d->currentStrokeId);
+
+    d->currentStrokeId.clear();
+    d->currentlyAppliedCofiguration.clear();
+}
+
+bool KisFilterManager::isStrokeRunning() const
+{
+    return d->currentStrokeId;
+}
diff --git a/krita/ui/kis_filter_manager.h b/krita/ui/kis_filter_manager.h
index 64f0659..6783d11 100644
--- a/krita/ui/kis_filter_manager.h
+++ b/krita/ui/kis_filter_manager.h
@@ -22,13 +22,11 @@
 
 #include <QObject>
 #include <krita_export.h>
+#include <kis_types.h>
 
-class KAction;
 class KisView2;
 class KisDoc2;
-class KisFilter;
 class KActionCollection;
-class KisFilterHandler;
 
 /**
  * Create all the filter actions for the specified view and implement re-apply filter
@@ -45,11 +43,17 @@ public:
 
     void setup(KActionCollection * ac);
     void updateGUI();
-    void setLastFilterHandler(KisFilterHandler* handler);
+
+    void apply(KisSafeFilterConfigurationSP filterConfig);
+    void finish();
+    void cancel();
+    bool isStrokeRunning() const;
 
 private slots:
 
-    void insertFilter(const QString & name);
+    void insertFilter(const QString &name);
+    void showFilterDialog(const QString &filterId);
+    void reapplyLastFilter();
 
 private:
     struct Private;



More information about the kimageshop mailing list