1 /*
2  *  Copyright (c) 2007 Cyrille Berger <cberger@cberger.net>
3  *  Copyright (c) 2008 Boudewijn Rempt <boud@valdysa.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "kis_dlg_filter.h"
22 
23 
24 
25 #include <KoResourcePaths.h>
26 #include <QPushButton>
27 #include <filter/kis_filter.h>
28 #include <filter/kis_filter_configuration.h>
29 #include <kis_filter_mask.h>
30 #include <kis_node.h>
31 #include <kis_layer.h>
32 #include <kis_paint_layer.h>
33 #include <KisViewManager.h>
34 #include <kis_config.h>
35 
36 #include "kis_selection.h"
37 #include "kis_node_commands_adapter.h"
38 #include "kis_filter_manager.h"
39 #include "ui_wdgfilterdialog.h"
40 #include "kis_canvas2.h"
41 
42 
43 struct KisDlgFilter::Private {
PrivateKisDlgFilter::Private44     Private(KisFilterManager *_filterManager, KisViewManager *_view)
45             : currentFilter(0)
46             , resizeCount(0)
47             , view(_view)
48             , filterManager(_filterManager)
49             , blockModifyingActionsGuard(new KisInputActionGroupsMaskGuard(view->canvasBase(), ViewTransformActionGroup))
50     {
51     }
52 
53     KisFilterSP currentFilter;
54     Ui_FilterDialog uiFilterDialog;
55     KisNodeSP node;
56     int resizeCount;
57     KisViewManager *view;
58     KisFilterManager *filterManager;
59 
60     // a special guard object that blocks all the painting input actions while the
61     // dialog is open
62     QScopedPointer<KisInputActionGroupsMaskGuard> blockModifyingActionsGuard;
63 };
64 
KisDlgFilter(KisViewManager * view,KisNodeSP node,KisFilterManager * filterManager,QWidget * parent)65 KisDlgFilter::KisDlgFilter(KisViewManager *view, KisNodeSP node, KisFilterManager *filterManager, QWidget *parent) :
66         QDialog(parent),
67         d(new Private(filterManager, view))
68 {
69     setModal(false);
70 
71     d->uiFilterDialog.setupUi(this);
72     d->node = node;
73 
74     d->uiFilterDialog.filterSelection->setView(view);
75     d->uiFilterDialog.filterSelection->showFilterGallery(KisConfig(true).showFilterGallery());
76 
77     d->uiFilterDialog.pushButtonCreateMaskEffect->show();
78     connect(d->uiFilterDialog.pushButtonCreateMaskEffect, SIGNAL(pressed()), SLOT(createMask()));
79     connect(d->uiFilterDialog.pushButtonCreateMaskEffect,SIGNAL(pressed()),SLOT(close()));
80 
81     d->uiFilterDialog.filterGalleryToggle->setChecked(d->uiFilterDialog.filterSelection->isFilterGalleryVisible());
82     d->uiFilterDialog.filterGalleryToggle->setIcon(QPixmap(":/pics/sidebaricon.png"));
83     d->uiFilterDialog.filterGalleryToggle->setMaximumWidth(d->uiFilterDialog.filterGalleryToggle->height());
84     connect(d->uiFilterDialog.filterSelection, SIGNAL(sigFilterGalleryToggled(bool)), d->uiFilterDialog.filterGalleryToggle, SLOT(setChecked(bool)));
85     connect(d->uiFilterDialog.filterGalleryToggle, SIGNAL(toggled(bool)), d->uiFilterDialog.filterSelection, SLOT(showFilterGallery(bool)));
86     connect(d->uiFilterDialog.filterSelection, SIGNAL(sigSizeChanged()), this, SLOT(slotFilterWidgetSizeChanged()));
87 
88     if (node->inherits("KisMask")) {
89         d->uiFilterDialog.pushButtonCreateMaskEffect->setVisible(false);
90     }
91 
92     d->uiFilterDialog.filterSelection->setPaintDevice(true, d->node->paintDevice());
93 
94     connect(d->uiFilterDialog.buttonBox, SIGNAL(accepted()), SLOT(accept()));
95     connect(d->uiFilterDialog.buttonBox, SIGNAL(rejected()), SLOT(reject()));
96     connect(d->uiFilterDialog.checkBoxPreview, SIGNAL(toggled(bool)), SLOT(enablePreviewToggled(bool)));
97 
98     connect(d->uiFilterDialog.filterSelection, SIGNAL(configurationChanged()), SLOT(filterSelectionChanged()));
99 
100     connect(this, SIGNAL(accepted()), SLOT(slotOnAccept()));
101     connect(this, SIGNAL(accepted()), d->uiFilterDialog.filterSelection, SLOT(slotBookMarkCurrentFilter()));
102     connect(this, SIGNAL(rejected()), SLOT(slotOnReject()));
103 
104     KConfigGroup group( KSharedConfig::openConfig(), "filterdialog");
105     d->uiFilterDialog.checkBoxPreview->setChecked(group.readEntry("showPreview", true));
106 
107     restoreGeometry(KisConfig(true).readEntry("filterdialog/geometry", QByteArray()));
108 
109 }
110 
~KisDlgFilter()111 KisDlgFilter::~KisDlgFilter()
112 {
113     KisConfig(false).writeEntry("filterdialog/geometry", saveGeometry());
114     delete d;
115 }
116 
setFilter(KisFilterSP f,KisFilterConfigurationSP overrideDefaultConfig)117 void KisDlgFilter::setFilter(KisFilterSP f, KisFilterConfigurationSP overrideDefaultConfig)
118 {
119     Q_ASSERT(f);
120     setDialogTitle(f);
121     d->uiFilterDialog.filterSelection->setFilter(f, overrideDefaultConfig);
122     d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(f->supportsAdjustmentLayers());
123     d->currentFilter = f;
124     updatePreview();
125 }
126 
setDialogTitle(KisFilterSP filter)127 void KisDlgFilter::setDialogTitle(KisFilterSP filter)
128 {
129     setWindowTitle(filter.isNull() ? i18nc("@title:window", "Filter") : i18nc("@title:window", "Filter: %1", filter->name()));
130 }
131 
startApplyingFilter(KisFilterConfigurationSP config)132 void KisDlgFilter::startApplyingFilter(KisFilterConfigurationSP config)
133 {
134     if (!d->uiFilterDialog.filterSelection->configuration()) return;
135 
136     if (d->node->inherits("KisPaintLayer")) {
137         config->setChannelFlags(qobject_cast<KisPaintLayer*>(d->node.data())->channelLockFlags());
138     }
139 
140     d->filterManager->apply(config);
141 }
142 
updatePreview()143 void KisDlgFilter::updatePreview()
144 {
145     KisFilterConfigurationSP config = d->uiFilterDialog.filterSelection->configuration();
146     if (!config) return;
147 
148     bool maskCreationAllowed = !d->currentFilter || d->currentFilter->configurationAllowedForMask(config);
149     d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(maskCreationAllowed);
150 
151     if (d->uiFilterDialog.checkBoxPreview->isChecked()) {
152         KisFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration());
153         startApplyingFilter(config);
154     }
155 
156     d->uiFilterDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
157 }
158 
adjustSize()159 void KisDlgFilter::adjustSize()
160 {
161     QWidget::adjustSize();
162 }
163 
slotFilterWidgetSizeChanged()164 void KisDlgFilter::slotFilterWidgetSizeChanged()
165 {
166     QMetaObject::invokeMethod(this, "adjustSize", Qt::QueuedConnection);
167 }
168 
slotOnAccept()169 void KisDlgFilter::slotOnAccept()
170 {
171     if (!d->filterManager->isStrokeRunning()) {
172         KisFilterConfigurationSP config(d->uiFilterDialog.filterSelection->configuration());
173         startApplyingFilter(config);
174     }
175 
176     d->filterManager->finish();
177 
178     d->uiFilterDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
179 
180     KisConfig(false).setShowFilterGallery(d->uiFilterDialog.filterSelection->isFilterGalleryVisible());
181 }
182 
slotOnReject()183 void KisDlgFilter::slotOnReject()
184 {
185     if (d->filterManager->isStrokeRunning()) {
186         d->filterManager->cancel();
187     }
188 
189     KisConfig(false).setShowFilterGallery(d->uiFilterDialog.filterSelection->isFilterGalleryVisible());
190 }
191 
createMask()192 void KisDlgFilter::createMask()
193 {
194     if (d->node->inherits("KisMask")) return;
195 
196     if (d->filterManager->isStrokeRunning()) {
197         d->filterManager->cancel();
198     }
199 
200     KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
201     KisFilterMaskSP mask = new KisFilterMask(d->view->image(), i18n("Filter Mask"));
202     mask->setName(d->currentFilter->name());
203     mask->initSelection(d->view->selection(), layer);
204     mask->setFilter(d->uiFilterDialog.filterSelection->configuration());
205 
206     Q_ASSERT(layer->allowAsChild(mask));
207 
208     KisNodeCommandsAdapter adapter(d->view);
209     adapter.addNode(mask, layer, layer->lastChild());
210 }
211 
enablePreviewToggled(bool state)212 void KisDlgFilter::enablePreviewToggled(bool state)
213 {
214     if (state) {
215         updatePreview();
216     } else if (d->filterManager->isStrokeRunning()) {
217         d->filterManager->cancel();
218     }
219 
220     KConfigGroup group( KSharedConfig::openConfig(), "filterdialog");
221     group.writeEntry("showPreview", d->uiFilterDialog.checkBoxPreview->isChecked());
222 
223     group.config()->sync();
224 }
225 
filterSelectionChanged()226 void KisDlgFilter::filterSelectionChanged()
227 {
228     KisFilterSP filter = d->uiFilterDialog.filterSelection->currentFilter();
229     setDialogTitle(filter);
230     d->currentFilter = filter;
231     d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(filter.isNull() ? false : filter->supportsAdjustmentLayers());
232     updatePreview();
233 }
234 
235 
resizeEvent(QResizeEvent * event)236 void KisDlgFilter::resizeEvent(QResizeEvent* event)
237 {
238     QDialog::resizeEvent(event);
239 
240 //    // Workaround, after the initialisation don't center the dialog anymore
241 //    if(d->resizeCount < 2) {
242 //        QWidget* canvas = d->view->canvas();
243 //        QRect rect(canvas->mapToGlobal(canvas->geometry().topLeft()), size());
244 //        int deltaX = (canvas->geometry().width() - geometry().width())/2;
245 //        int deltaY = (canvas->geometry().height() - geometry().height())/2;
246 //        rect.translate(deltaX, deltaY);
247 //        setGeometry(rect);
248 
249 //        d->resizeCount++;
250 //    }
251 }
252