diff options
Diffstat (limited to 'chalk/ui/kis_filter_manager.cpp')
-rw-r--r-- | chalk/ui/kis_filter_manager.cpp | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/chalk/ui/kis_filter_manager.cpp b/chalk/ui/kis_filter_manager.cpp new file mode 100644 index 000000000..848f99b73 --- /dev/null +++ b/chalk/ui/kis_filter_manager.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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 "tqsignalmapper.h" +#include <tqlayout.h> +#include <tqframe.h> +#include <tqcursor.h> +#include <tqapplication.h> +#include <tdemessagebox.h> +#include <kguiitem.h> + +#include <kis_cursor.h> +#include "tdeaction.h" + +#include "kis_part_layer.h" +#include "kis_id.h" +#include "kis_view.h" +#include "kis_doc.h" +#include "kis_filter.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_paint_layer.h" +#include "kis_filter_manager.h" +#include "kis_filter_config_widget.h" +#include "kis_previewwidget.h" +#include "kis_previewdialog.h" +#include "kis_filter_registry.h" +#include "kis_transaction.h" +#include "kis_undo_adapter.h" +#include "kis_previewdialog.h" +#include "kis_previewwidget.h" +#include "kis_painter.h" +#include "kis_selection.h" +#include "kis_id.h" +#include "kis_canvas_subject.h" +#include "kis_doc.h" +#include "kis_transaction.h" +#include <kis_progress_display_interface.h> + +KisFilterManager::KisFilterManager(KisView * view, KisDoc * doc) + : m_view(view), + m_doc(doc) +{ + // XXX: Store & restore last filter & last filter configuration in session settings + m_reapplyAction = 0; + m_lastFilterConfig = 0; + m_lastDialog = 0; + m_lastFilter = 0; + m_lastWidget = 0; + + m_filterMapper = new TQSignalMapper(this); + + connect(m_filterMapper, TQT_SIGNAL(mapped(int)), this, TQT_SLOT(slotApplyFilter(int))); + +} + +KisFilterManager::~KisFilterManager() +{ + //delete m_reapplyAction; + //delete m_lastFilterConfig; + //delete m_filterMapper; +} + +void KisFilterManager::setup(TDEActionCollection * ac) +{ + KisFilter * f = 0; + int i = 0; + + // Only create the submenu's we've actually got filters for. + // XXX: Make this list extensible after 1.5 + + TDEActionMenu * other = 0; + TDEActionMenu * am = 0; + + m_filterList = KisFilterRegistry::instance()->listKeys(); + + for ( KisIDList::Iterator it = m_filterList.begin(); it != m_filterList.end(); ++it ) { + f = KisFilterRegistry::instance()->get(*it); + if (!f) break; + + TQString s = f->menuCategory(); + if (s == "adjust" && !m_filterActionMenus.find("adjust")) { + am = new TDEActionMenu(i18n("Adjust"), ac, "adjust_filters"); + m_filterActionMenus.insert("adjust", am); + } + + else if (s == "artistic" && !m_filterActionMenus.find("artistic")) { + am = new TDEActionMenu(i18n("Artistic"), ac, "artistic_filters"); + m_filterActionMenus.insert("artistic", am); + } + + else if (s == "blur" && !m_filterActionMenus.find("blur")) { + am = new TDEActionMenu(i18n("Blur"), ac, "blur_filters"); + m_filterActionMenus.insert("blur", am); + } + + else if (s == "colors" && !m_filterActionMenus.find("colors")) { + am = new TDEActionMenu(i18n("Colors"), ac, "color_filters"); + m_filterActionMenus.insert("colors", am); + } + + else if (s == "decor" && !m_filterActionMenus.find("decor")) { + am = new TDEActionMenu(i18n("Decor"), ac, "decor_filters"); + m_filterActionMenus.insert("decor", am); + } + + else if (s == "edge" && !m_filterActionMenus.find("edge")) { + am = new TDEActionMenu(i18n("Edge Detection"), ac, "edge_filters"); + m_filterActionMenus.insert("edge", am); + } + + else if (s == "emboss" && !m_filterActionMenus.find("emboss")) { + am = new TDEActionMenu(i18n("Emboss"), ac, "emboss_filters"); + m_filterActionMenus.insert("emboss", am); + } + + else if (s == "enhance" && !m_filterActionMenus.find("enhance")) { + am = new TDEActionMenu(i18n("Enhance"), ac, "enhance_filters"); + m_filterActionMenus.insert("enhance", am); + } + + else if (s == "map" && !m_filterActionMenus.find("map")) { + am = new TDEActionMenu(i18n("Map"), ac, "map_filters"); + m_filterActionMenus.insert("map", am); + } + + else if (s == "nonphotorealistic" && !m_filterActionMenus.find("nonphotorealistic")) { + am = new TDEActionMenu(i18n("Non-photorealistic"), ac, "nonphotorealistic_filters"); + m_filterActionMenus.insert("nonphotorealistic", am); + } + + else if (s == "other" && !m_filterActionMenus.find("other")) { + other = new TDEActionMenu(i18n("Other"), ac, "misc_filters"); + m_filterActionMenus.insert("other", other); + } + + } + + m_reapplyAction = new TDEAction(i18n("Apply Filter Again"), + "Ctrl+Shift+F", + this, TQT_SLOT(slotApply()), + ac, "filter_apply_again"); + + m_reapplyAction->setEnabled(false); + + f = 0; + i = 0; + for ( KisIDList::Iterator it = m_filterList.begin(); it != m_filterList.end(); ++it ) { + f = KisFilterRegistry::instance()->get(*it); + + if (!f) break; + + // Create action + TDEAction * a = new TDEAction(f->menuEntry(), 0, m_filterMapper, TQT_SLOT(map()), ac, + TQString("chalk_filter_%1").arg((*it) . id()).ascii()); + + // Add action to the right submenu + TDEActionMenu * m = m_filterActionMenus.find( f->menuCategory() ); + if (m) { + m->insert(a); + } + else { + if (!other) { + other = new TDEActionMenu(i18n("Other"), ac, "misc_filters"); + m_filterActionMenus.insert("other", am); + } + other->insert(a); + } + + // Add filter to list of filters for mapper + m_filterMapper->setMapping( a, i ); + + m_filterActions.append( a ); + ++i; + } +} + +void KisFilterManager::updateGUI() +{ + KisImageSP img = m_view->currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(layer.data()); + + bool enable = !(layer->locked() || !layer->visible() || partLayer); + KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>( layer.data()); + if(!player) + { + enable = false; + } + m_reapplyAction->setEnabled(m_lastFilterConfig); + if (m_lastFilterConfig) + m_reapplyAction->setText(i18n("Apply Filter Again") + ": " + + KisFilterRegistry::instance()->get(m_lastFilterConfig->name())->id().name()); + else + m_reapplyAction->setText(i18n("Apply Filter Again")); + + TDEAction * a; + int i = 0; + for (a = m_filterActions.first(); a; a = m_filterActions.next() , i++) { + KisFilter* filter = KisFilterRegistry::instance()->get(m_filterList[i]); + if(player && filter->workWith( player->paintDevice()->colorSpace())) + { + a->setEnabled(enable); + } else { + a->setEnabled(false); + } + } + +} + +void KisFilterManager::slotApply() +{ + apply(); +} + +bool KisFilterManager::apply() +{ + if (!m_lastFilter) return false; + + KisImageSP img = m_view->currentImg(); + if (!img) return false; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return false; + + TQApplication::setOverrideCursor( KisCursor::waitCursor() ); + + //Apply the filter + m_lastFilterConfig = m_lastFilter->configuration(m_lastWidget); + + TQRect r1 = dev->extent(); + TQRect r2 = img->bounds(); + + // Filters should work only on the visible part of an image. + TQRect rect = r1.intersect(r2); + + if (dev->hasSelection()) { + TQRect r3 = dev->selection()->selectedExactRect(); + rect = rect.intersect(r3); + } + + m_lastFilter->enableProgress(); + + m_view->progressDisplay()->setSubject(m_lastFilter, true, true); + m_lastFilter->setProgressDisplay( m_view->progressDisplay()); + + KisTransaction * cmd = 0; + if (img->undo()) cmd = new KisTransaction(m_lastFilter->id().name(), dev); + + m_lastFilter->process(dev, dev, m_lastFilterConfig, rect); + m_reapplyAction->setEnabled(m_lastFilterConfig); + if (m_lastFilterConfig) + m_reapplyAction->setText(i18n("Apply Filter Again") + ": " + + KisFilterRegistry::instance()->get(m_lastFilterConfig->name())->id().name()); + + else + m_reapplyAction->setText(i18n("Apply Filter Again")); + + m_lastFilter->disableProgress(); + TQApplication::restoreOverrideCursor(); + + + if (m_lastFilter->cancelRequested()) { + delete m_lastFilterConfig; + if (cmd) { + cmd->unexecute(); + delete cmd; + } + return false; + + } else { + if (dev->parentLayer()) dev->parentLayer()->setDirty(rect); + m_doc->setModified(true); + if (img->undo() && cmd) img->undoAdapter()->addCommand(cmd); + return true; + } +} + +void KisFilterManager::slotApplyFilter(int i) +{ + KisPreviewDialog * oldDialog = m_lastDialog; + KisFilterConfiguration * oldConfig = m_lastFilterConfig; + KisFilter * oldFilter = m_lastFilter; + + m_lastFilter = KisFilterRegistry::instance()->get(m_filterList[i]); + + if (!m_lastFilter) { + m_lastFilter = oldFilter; + return; + } + + KisImageSP img = m_view->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (dev->colorSpace()->willDegrade(m_lastFilter->colorSpaceIndependence())) { + // Warning bells! + if (m_lastFilter->colorSpaceIndependence() == TO_LAB16) { + if (KMessageBox::warningContinueCancel(m_view, + i18n("The %1 filter will convert your %2 data to 16-bit L*a*b* and vice versa. ") + .arg(m_lastFilter->id().name()) + .arg(dev->colorSpace()->id().name()), + i18n("Filter Will Convert Your Layer Data"), + KGuiItem(i18n("Continue")), + "lab16degradation") != KMessageBox::Continue) return; + + } + else if (m_lastFilter->colorSpaceIndependence() == TO_RGBA8) { + if (KMessageBox::warningContinueCancel(m_view, + i18n("The %1 filter will convert your %2 data to 8-bit RGBA and vice versa. ") + .arg(m_lastFilter->id().name()) + .arg(dev->colorSpace()->id().name()), + i18n("Filter Will Convert Your Layer Data"), + KGuiItem(i18n("Continue")), + "rgba8degradation") != KMessageBox::Continue) return; + } + } + + m_lastFilter->disableProgress(); + + // Create the config dialog + m_lastDialog = new KisPreviewDialog(m_view, m_lastFilter->id().name().ascii(), true, m_lastFilter->id().name()); + TQ_CHECK_PTR(m_lastDialog); + m_lastWidget = m_lastFilter->createConfigurationWidget( (TQWidget*)m_lastDialog->container(), dev ); + + bool accepted = true; + + if( m_lastWidget != 0) + { + connect(m_lastWidget, TQT_SIGNAL(sigPleaseUpdatePreview()), this, TQT_SLOT(slotConfigChanged())); + + m_lastDialog->previewWidget()->slotSetDevice( dev ); + + connect(m_lastDialog->previewWidget(), TQT_SIGNAL(updated()), this, TQT_SLOT(refreshPreview())); + + TQGridLayout *widgetLayout = new TQGridLayout((TQWidget *)m_lastDialog->container(), 1, 1); + + widgetLayout->addWidget(m_lastWidget, 0 , 0); + + m_lastDialog->container()->setMinimumSize(m_lastWidget->minimumSize()); + + refreshPreview(); + + if(m_lastDialog->exec() == TQDialog::Rejected ) + { + accepted = false; + } + } + + if (!accepted || !apply()) { + // Override the old configuration + m_lastFilterConfig = oldConfig; + m_lastDialog = oldDialog; + m_lastFilter = oldFilter; + } else { + delete oldDialog; + delete oldConfig; + } + +} + +void KisFilterManager::slotConfigChanged() +{ + if( m_lastDialog == 0 ) + return; + if(m_lastDialog->previewWidget()->getAutoUpdate()) + { + refreshPreview(); + } else { + m_lastDialog->previewWidget()->needUpdate(); + } +} + + +void KisFilterManager::refreshPreview( ) +{ + if( m_lastDialog == 0 ) return; + + KisFilterConfiguration* config = m_lastFilter->configuration(m_lastWidget); + + // The preview widget is in charge of running the filter so it can optimize the performance + m_lastDialog->previewWidget()->runFilter(m_lastFilter, config); +} + + +#include "kis_filter_manager.moc" |