/* * Copyright (c) 2005 Boudewijn Rempt * Copyright (c) 2007 Benjamin Schleimer * * 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 #include #include #include #include #include #include #include "kaction.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 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(KActionCollection * 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 KActionMenu * other = 0; KActionMenu * 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 KActionMenu(i18n("Adjust"), ac, "adjust_filters"); m_filterActionMenus.insert("adjust", am); } else if (s == "artistic" && !m_filterActionMenus.find("artistic")) { am = new KActionMenu(i18n("Artistic"), ac, "artistic_filters"); m_filterActionMenus.insert("artistic", am); } else if (s == "blur" && !m_filterActionMenus.find("blur")) { am = new KActionMenu(i18n("Blur"), ac, "blur_filters"); m_filterActionMenus.insert("blur", am); } else if (s == "colors" && !m_filterActionMenus.find("colors")) { am = new KActionMenu(i18n("Colors"), ac, "color_filters"); m_filterActionMenus.insert("colors", am); } else if (s == "decor" && !m_filterActionMenus.find("decor")) { am = new KActionMenu(i18n("Decor"), ac, "decor_filters"); m_filterActionMenus.insert("decor", am); } else if (s == "edge" && !m_filterActionMenus.find("edge")) { am = new KActionMenu(i18n("Edge Detection"), ac, "edge_filters"); m_filterActionMenus.insert("edge", am); } else if (s == "emboss" && !m_filterActionMenus.find("emboss")) { am = new KActionMenu(i18n("Emboss"), ac, "emboss_filters"); m_filterActionMenus.insert("emboss", am); } else if (s == "enhance" && !m_filterActionMenus.find("enhance")) { am = new KActionMenu(i18n("Enhance"), ac, "enhance_filters"); m_filterActionMenus.insert("enhance", am); } else if (s == "map" && !m_filterActionMenus.find("map")) { am = new KActionMenu(i18n("Map"), ac, "map_filters"); m_filterActionMenus.insert("map", am); } else if (s == "nonphotorealistic" && !m_filterActionMenus.find("nonphotorealistic")) { am = new KActionMenu(i18n("Non-photorealistic"), ac, "nonphotorealistic_filters"); m_filterActionMenus.insert("nonphotorealistic", am); } else if (s == "other" && !m_filterActionMenus.find("other")) { other = new KActionMenu(i18n("Other"), ac, "misc_filters"); m_filterActionMenus.insert("other", other); } } m_reapplyAction = new KAction(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 KAction * a = new KAction(f->menuEntry(), 0, m_filterMapper, TQT_SLOT(map()), ac, TQString("chalk_filter_%1").arg((*it) . id()).ascii()); // Add action to the right submenu KActionMenu * m = m_filterActionMenus.find( f->menuCategory() ); if (m) { m->insert(a); } else { if (!other) { other = new KActionMenu(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(layer.data()); bool enable = !(layer->locked() || !layer->visible() || partLayer); KisPaintLayerSP player = dynamic_cast( 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")); KAction * 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"