krita

kis_filter_manager.cc

00001 /*
00002  *  Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "qsignalmapper.h"
00020 #include <qlayout.h>
00021 #include <qframe.h>
00022 #include <qcursor.h>
00023 #include <qapplication.h>
00024 #include <kmessagebox.h>
00025 #include <kguiitem.h>
00026 
00027 #include "kaction.h"
00028 
00029 #include "kis_part_layer.h"
00030 #include "kis_id.h"
00031 #include "kis_view.h"
00032 #include "kis_doc.h"
00033 #include "kis_filter.h"
00034 #include "kis_layer.h"
00035 #include "kis_paint_device.h"
00036 #include "kis_paint_layer.h"
00037 #include "kis_filter_manager.h"
00038 #include "kis_filter_config_widget.h"
00039 #include "kis_previewwidget.h"
00040 #include "kis_previewdialog.h"
00041 #include "kis_filter_registry.h"
00042 #include "kis_transaction.h"
00043 #include "kis_undo_adapter.h"
00044 #include "kis_previewdialog.h"
00045 #include "kis_previewwidget.h"
00046 #include "kis_painter.h"
00047 #include "kis_selection.h"
00048 #include "kis_id.h"
00049 #include "kis_canvas_subject.h"
00050 #include "kis_doc.h"
00051 #include "kis_transaction.h"
00052 #include <kis_progress_display_interface.h>
00053 
00054 KisFilterManager::KisFilterManager(KisView * view, KisDoc * doc)
00055     : m_view(view),
00056     m_doc(doc)
00057 {
00058     connect(&m_delayer, SIGNAL(timeout()), this, SLOT(refreshPreview()));
00059     // XXX: Store & restore last filter & last filter configuration in session settings
00060     m_reapplyAction = 0;
00061     m_lastFilterConfig = 0;
00062     m_lastDialog = 0;
00063     m_lastFilter = 0;
00064     m_lastWidget = 0;
00065 
00066     m_filterMapper = new QSignalMapper(this);
00067 
00068     connect(m_filterMapper, SIGNAL(mapped(int)), this, SLOT(slotApplyFilter(int)));
00069 
00070 }
00071 
00072 KisFilterManager::~KisFilterManager()
00073 {
00074     //delete m_reapplyAction;
00075     //delete m_lastFilterConfig;
00076     //delete m_filterMapper;
00077 }
00078 
00079 void KisFilterManager::setup(KActionCollection * ac)
00080 {
00081     KisFilter * f = 0;
00082     int i = 0;
00083 
00084     // Only create the submenu's we've actually got filters for.
00085     // XXX: Make this list extensible after 1.5
00086 
00087     KActionMenu * other = 0;
00088     KActionMenu * am = 0;
00089 
00090     m_filterList = KisFilterRegistry::instance()->listKeys();
00091 
00092     for ( KisIDList::Iterator it = m_filterList.begin(); it != m_filterList.end(); ++it ) {
00093         f = KisFilterRegistry::instance()->get(*it);
00094         if (!f) break;
00095 
00096         QString s = f->menuCategory();
00097         if (s == "adjust" && !m_filterActionMenus.find("adjust")) {
00098             am = new KActionMenu(i18n("Adjust"), ac, "adjust_filters");
00099             m_filterActionMenus.insert("adjust", am);
00100         }
00101 
00102         else if (s == "artistic" && !m_filterActionMenus.find("artistic")) {
00103             am = new KActionMenu(i18n("Artistic"), ac, "artistic_filters");
00104             m_filterActionMenus.insert("artistic", am);
00105         }
00106 
00107         else if (s == "blur" && !m_filterActionMenus.find("blur")) {
00108             am = new KActionMenu(i18n("Blur"), ac, "blur_filters");
00109             m_filterActionMenus.insert("blur", am);
00110         }
00111 
00112         else if (s == "colors" && !m_filterActionMenus.find("colors")) {
00113             am = new KActionMenu(i18n("Colors"), ac, "color_filters");
00114             m_filterActionMenus.insert("colors", am);
00115         }
00116 
00117         else if (s == "decor" && !m_filterActionMenus.find("decor")) {
00118             am = new KActionMenu(i18n("Decor"), ac, "decor_filters");
00119             m_filterActionMenus.insert("decor", am);
00120         }
00121 
00122         else if (s == "edge" && !m_filterActionMenus.find("edge")) {
00123             am = new KActionMenu(i18n("Edge Detection"), ac, "edge_filters");
00124             m_filterActionMenus.insert("edge", am);
00125         }
00126 
00127         else if (s == "emboss" && !m_filterActionMenus.find("emboss")) {
00128             am = new KActionMenu(i18n("Emboss"), ac, "emboss_filters");
00129             m_filterActionMenus.insert("emboss", am);
00130         }
00131 
00132         else if (s == "enhance" && !m_filterActionMenus.find("enhance")) {
00133             am = new KActionMenu(i18n("Enhance"), ac, "enhance_filters");
00134             m_filterActionMenus.insert("enhance", am);
00135         }
00136 
00137         else if (s == "map" && !m_filterActionMenus.find("map")) {
00138             am = new KActionMenu(i18n("Map"), ac, "map_filters");
00139             m_filterActionMenus.insert("map", am);
00140         }
00141 
00142         else if (s == "nonphotorealistic" && !m_filterActionMenus.find("nonphotorealistic")) {
00143             am = new KActionMenu(i18n("Non-photorealistic"), ac, "nonphotorealistic_filters");
00144             m_filterActionMenus.insert("nonphotorealistic", am);
00145         }
00146 
00147         else if (s == "other" && !m_filterActionMenus.find("other")) {
00148             other = new KActionMenu(i18n("Other"), ac, "misc_filters");
00149             m_filterActionMenus.insert("other", other);
00150         }
00151 
00152     }
00153 
00154     m_reapplyAction = new KAction(i18n("Apply Filter Again"),
00155                 "Ctrl+Shift+F",
00156                 this, SLOT(slotApply()),
00157                 ac, "filter_apply_again");
00158 
00159     m_reapplyAction->setEnabled(false);
00160 
00161     f = 0;
00162     i = 0;
00163     for ( KisIDList::Iterator it = m_filterList.begin(); it != m_filterList.end(); ++it ) {
00164         f = KisFilterRegistry::instance()->get(*it);
00165 
00166         if (!f) break;
00167 
00168         // Create action
00169         KAction * a = new KAction(f->menuEntry(), 0, m_filterMapper, SLOT(map()), ac,
00170                                   QString("krita_filter_%1").arg((*it) . id()).ascii());
00171 
00172         // Add action to the right submenu
00173         KActionMenu * m = m_filterActionMenus.find( f->menuCategory() );
00174         if (m) {
00175             m->insert(a);
00176         }
00177         else {
00178             if (!other) {
00179                 other = new KActionMenu(i18n("Other"), ac, "misc_filters");
00180                 m_filterActionMenus.insert("other", am);
00181             }
00182             other->insert(a);
00183         }
00184 
00185         // Add filter to list of filters for mapper
00186         m_filterMapper->setMapping( a, i );
00187 
00188         m_filterActions.append( a );
00189         ++i;
00190     }
00191 }
00192 
00193 void KisFilterManager::updateGUI()
00194 {
00195     KisImageSP img = m_view->currentImg();
00196     if (!img) return;
00197 
00198     KisLayerSP layer = img->activeLayer();
00199     if (!layer) return;
00200 
00201     KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(layer.data());
00202 
00203     bool enable =  !(layer->locked() || !layer->visible() || partLayer);
00204     KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>( layer.data());
00205     if(!player)
00206     {
00207         enable = false;
00208     }
00209     m_reapplyAction->setEnabled(m_lastFilterConfig);
00210     if (m_lastFilterConfig)
00211         m_reapplyAction->setText(i18n("Apply Filter Again") + ": "
00212             + KisFilterRegistry::instance()->get(m_lastFilterConfig->name())->id().name());
00213     else
00214         m_reapplyAction->setText(i18n("Apply Filter Again"));
00215 
00216     KAction * a;
00217     int i = 0;
00218     for (a = m_filterActions.first(); a; a = m_filterActions.next() , i++) {
00219         KisFilter* filter = KisFilterRegistry::instance()->get(m_filterList[i]);
00220         if(player && filter->workWith( player->paintDevice()->colorSpace()))
00221         {
00222             a->setEnabled(enable);
00223         } else {
00224             a->setEnabled(false);
00225         }
00226     }
00227 
00228 }
00229 
00230 void KisFilterManager::slotApply()
00231 {
00232     apply();
00233 }
00234 
00235 bool KisFilterManager::apply()
00236 {
00237     if (!m_lastFilter) return false;
00238 
00239     KisImageSP img = m_view->currentImg();
00240     if (!img) return false;
00241 
00242     KisPaintDeviceSP dev = img->activeDevice();
00243     if (!dev) return false;
00244 
00245     QApplication::setOverrideCursor( Qt::waitCursor );
00246 
00247     //Apply the filter
00248     m_lastFilterConfig = m_lastFilter->configuration(m_lastWidget);
00249 
00250     QRect r1 = dev->extent();
00251     QRect r2 = img->bounds();
00252 
00253     // Filters should work only on the visible part of an image.
00254     QRect rect = r1.intersect(r2);
00255 
00256     if (dev->hasSelection()) {
00257         QRect r3 = dev->selection()->selectedExactRect();
00258         rect = rect.intersect(r3);
00259     }
00260 
00261     m_lastFilter->enableProgress();
00262 
00263     m_view->progressDisplay()->setSubject(m_lastFilter, true, true);
00264     m_lastFilter->setProgressDisplay( m_view->progressDisplay());
00265 
00266     KisTransaction * cmd = 0;
00267     if (img->undo()) cmd = new KisTransaction(m_lastFilter->id().name(), dev);
00268 
00269     m_lastFilter->process(dev, dev, m_lastFilterConfig, rect);
00270     m_reapplyAction->setEnabled(m_lastFilterConfig);
00271     if (m_lastFilterConfig)
00272         m_reapplyAction->setText(i18n("Apply Filter Again") + ": "
00273             + KisFilterRegistry::instance()->get(m_lastFilterConfig->name())->id().name());
00274 
00275     else
00276         m_reapplyAction->setText(i18n("Apply Filter Again"));
00277 
00278     if (m_lastFilter->cancelRequested()) {
00279         delete m_lastFilterConfig;
00280         if (cmd) {
00281             cmd->unexecute();
00282             delete cmd;
00283         }
00284         m_lastFilter->disableProgress();
00285         QApplication::restoreOverrideCursor();
00286         return false;
00287 
00288     } else {
00289         if (dev->parentLayer()) dev->parentLayer()->setDirty(rect);
00290         m_doc->setModified(true);
00291         if (img->undo() && cmd) img->undoAdapter()->addCommand(cmd);
00292         m_lastFilter->disableProgress();
00293         QApplication::restoreOverrideCursor();
00294         return true;
00295     }
00296 }
00297 
00298 void KisFilterManager::slotApplyFilter(int i)
00299 {
00300     KisPreviewDialog * oldDialog = m_lastDialog;
00301     KisFilterConfiguration * oldConfig = m_lastFilterConfig;
00302     KisFilter * oldFilter = m_lastFilter;
00303 
00304     m_lastFilter = KisFilterRegistry::instance()->get(m_filterList[i]);
00305 
00306     if (!m_lastFilter) {
00307         m_lastFilter = oldFilter;
00308         return;
00309     }
00310 
00311     KisImageSP img = m_view->currentImg();
00312     if (!img) return;
00313 
00314     KisPaintDeviceSP dev = img->activeDevice();
00315     if (!dev) return;
00316 
00317     if (dev->colorSpace()->willDegrade(m_lastFilter->colorSpaceIndependence())) {
00318         // Warning bells!
00319         if (m_lastFilter->colorSpaceIndependence() == TO_LAB16) {
00320             if (KMessageBox::warningContinueCancel(m_view,
00321                                                i18n("The %1 filter will convert your %2 data to 16-bit L*a*b* and vice versa. ")
00322                                                        .arg(m_lastFilter->id().name())
00323                                                        .arg(dev->colorSpace()->id().name()),
00324                                                i18n("Filter Will Convert Your Layer Data"),
00325                                                KGuiItem(i18n("Continue")),
00326                                                "lab16degradation") != KMessageBox::Continue) return;
00327 
00328         }
00329         else if (m_lastFilter->colorSpaceIndependence() == TO_RGBA8) {
00330             if (KMessageBox::warningContinueCancel(m_view,
00331                                                i18n("The %1 filter will convert your %2 data to 8-bit RGBA and vice versa. ")
00332                                                        .arg(m_lastFilter->id().name())
00333                                                        .arg(dev->colorSpace()->id().name()),
00334                                                i18n("Filter Will Convert Your Layer Data"),
00335                                                KGuiItem(i18n("Continue")),
00336                                                "rgba8degradation") != KMessageBox::Continue) return;
00337         }
00338     }
00339 
00340     m_lastFilter->disableProgress();
00341 
00342     // Create the config dialog
00343     m_lastDialog = new KisPreviewDialog(m_view, m_lastFilter->id().name().ascii(), true, m_lastFilter->id().name());
00344     Q_CHECK_PTR(m_lastDialog);
00345     m_lastWidget = m_lastFilter->createConfigurationWidget( (QWidget*)m_lastDialog->container(), dev );
00346 
00347 
00348     if( m_lastWidget != 0)
00349     {
00350         connect(m_lastWidget, SIGNAL(sigPleaseUpdatePreview()), this, SLOT(slotConfigChanged()));
00351 
00352         m_lastDialog->previewWidget()->slotSetDevice( dev );
00353 
00354         connect(m_lastDialog->previewWidget(), SIGNAL(updated()), this, SLOT(refreshPreview()));
00355 
00356         QGridLayout *widgetLayout = new QGridLayout((QWidget *)m_lastDialog->container(), 1, 1);
00357 
00358         widgetLayout->addWidget(m_lastWidget, 0 , 0);
00359 
00360         m_lastDialog->container()->setMinimumSize(m_lastWidget->minimumSize());
00361 
00362         refreshPreview();
00363 
00364         if(m_lastDialog->exec() == QDialog::Rejected )
00365         {
00366             delete m_lastDialog;
00367             m_lastFilterConfig = oldConfig;
00368             m_lastDialog = oldDialog;
00369             m_lastFilter = oldFilter;
00370             return;
00371         }
00372     }
00373 
00374     if (!apply()) {
00375         delete m_lastDialog;
00376         m_lastFilterConfig = oldConfig;
00377         m_lastDialog = oldDialog;
00378         m_lastFilter = oldFilter;
00379     }
00380 
00381 }
00382 
00383 void KisFilterManager::slotConfigChanged()
00384 {
00385     if( m_lastDialog == 0 )
00386         return;
00387     if(m_lastDialog->previewWidget()->getAutoUpdate())
00388     {
00389 //         refreshPreview();
00390       m_delayer.start(1000, true);
00391     } else {
00392         m_lastDialog->previewWidget()->needUpdate();
00393     }
00394 }
00395 
00396 
00397 void KisFilterManager::refreshPreview( )
00398 {
00399     if( m_lastDialog == 0 )
00400         return;
00401 
00402     KisPaintDeviceSP dev = m_lastDialog->previewWidget()->getDevice();
00403     if (!dev) return;
00404 
00405     KisFilterConfiguration* config = m_lastFilter->configuration(m_lastWidget);
00406 
00407     QRect rect = dev->extent();
00408     KisTransaction cmd("Temporary transaction", dev);
00409     m_lastFilter->process(dev, dev, config, rect);
00410     m_lastDialog->previewWidget()->slotUpdate();
00411     cmd.unexecute();
00412 }
00413 
00414 
00415 #include "kis_filter_manager.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys