/* ============================================================ * * This file is a part of kipi-plugins project * http://www.kipi-plugins.org * * Date : 2006-10-11 * Description : a plugin to edit pictures metadata * * Copyright (C) 2006-2007 by Gilles Caulier * * 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, 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. * * ============================================================ */ // KDE includes. #include #include #include #include #include #include #include #include #include #include #include // LibKIPI includes. #include // LibKExiv2 includes. #include // Local includes. #include "exifeditdialog.h" #include "iptceditdialog.h" #include "commenteditdialog.h" #include "commentremovedialog.h" #include "plugin_metadataedit.h" #include "plugin_metadataedit.moc" typedef KGenericFactory Factory; K_EXPORT_COMPONENT_FACTORY( kipiplugin_metadataedit, Factory("kipiplugin_metadataedit")) Plugin_MetadataEdit::Plugin_MetadataEdit(TQObject *parent, const char*, const TQStringList&) : KIPI::Plugin( Factory::instance(), parent, "MetadataEdit") { kdDebug( 51001 ) << "Plugin_MetadataEdit plugin loaded" << endl; } void Plugin_MetadataEdit::setup( TQWidget* widget ) { KIPI::Plugin::setup( widget ); m_actionMetadataEdit = new TDEActionMenu(i18n("Metadata"), 0, actionCollection(), "metadataedit"); m_actionMetadataEdit->insert(new TDEAction (i18n("Edit EXIF..."), 0, 0, this, TQT_SLOT(slotEditExif()), actionCollection(), "editexif")); m_actionMetadataEdit->insert(new TDEAction (i18n("Remove EXIF..."), 0, 0, this, TQT_SLOT(slotRemoveExif()), actionCollection(), "removeexif")); m_actionMetadataEdit->insert(new TDEAction (i18n("Import EXIF..."), 0, 0, this, TQT_SLOT(slotImportExif()), actionCollection(), "importexif")); m_actionMetadataEdit->popupMenu()->insertSeparator(); m_actionMetadataEdit->insert(new TDEAction (i18n("Edit IPTC..."), 0, 0, this, TQT_SLOT(slotEditIptc()), actionCollection(), "editiptc")); m_actionMetadataEdit->insert(new TDEAction (i18n("Remove IPTC..."), 0, 0, this, TQT_SLOT(slotRemoveIptc()), actionCollection(), "removeiptc")); m_actionMetadataEdit->insert(new TDEAction (i18n("Import IPTC..."), 0, 0, this, TQT_SLOT(slotImportIptc()), actionCollection(), "importiptc")); m_actionMetadataEdit->popupMenu()->insertSeparator(); m_actionMetadataEdit->insert(new TDEAction (i18n("Edit Captions..."), 0, 0, this, TQT_SLOT(slotEditComments()), actionCollection(), "editcomments")); m_actionMetadataEdit->insert(new TDEAction (i18n("Remove Captions..."), 0, 0, this, TQT_SLOT(slotRemoveComments()), actionCollection(), "removecomments")); addAction( m_actionMetadataEdit ); m_interface = dynamic_cast< KIPI::Interface* >( parent() ); if ( !m_interface ) { kdError( 51000 ) << "Kipi interface is null!" << endl; return; } KIPI::ImageCollection selection = m_interface->currentSelection(); m_actionMetadataEdit->setEnabled( selection.isValid() && !selection.images().isEmpty() ); connect( m_interface, TQT_SIGNAL(selectionChanged(bool)), m_actionMetadataEdit, TQT_SLOT(setEnabled(bool))); } void Plugin_MetadataEdit::slotEditExif() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; KIPIMetadataEditPlugin::EXIFEditDialog dialog(TQT_TQWIDGET(kapp->activeWindow()), images.images(), m_interface); dialog.exec(); m_interface->refreshImages(images.images()); } void Plugin_MetadataEdit::slotRemoveExif() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; if (KMessageBox::warningYesNo( TQT_TQWIDGET(kapp->activeWindow()), i18n("EXIF metadata will be permanently removed from all current selected pictures.\n" "Do you want to continue ?"), i18n("Remove EXIF Metadata")) != KMessageBox::Yes) return; KURL::List imageURLs = images.images(); KURL::List updatedURLs; TQStringList errorFiles; for( KURL::List::iterator it = imageURLs.begin() ; it != imageURLs.end(); ++it) { KURL url = *it; bool ret = false; if (!KExiv2Iface::KExiv2::isReadOnly(url.path())) { ret = true; KExiv2Iface::KExiv2 exiv2Iface; ret &= exiv2Iface.load(url.path()); ret &= exiv2Iface.clearExif(); ret &= exiv2Iface.save(url.path()); } if (!ret) errorFiles.append(url.fileName()); else updatedURLs.append(url); } // We use kipi interface refreshImages() method to tell to host than // metadata from pictures have changed and need to be re-read. m_interface->refreshImages(updatedURLs); if (!errorFiles.isEmpty()) { KMessageBox::errorList( TQT_TQWIDGET(kapp->activeWindow()), i18n("Unable to remove EXIF metadata from:"), errorFiles, i18n("Remove EXIF Metadata")); } } void Plugin_MetadataEdit::slotImportExif() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; KURL importEXIFFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(), TQString(), TQT_TQWIDGET(kapp->activeWindow()), i18n("Select File to Import EXIF metadata") ); if( importEXIFFile.isEmpty() ) return; KExiv2Iface::KExiv2 exiv2Iface; if (!exiv2Iface.load(importEXIFFile.path())) { KMessageBox::error(TQT_TQWIDGET(kapp->activeWindow()), i18n("Cannot load metadata from \"%1\"").arg(importEXIFFile.fileName()), i18n("Import EXIF Metadata")); return; } TQByteArray exifData = exiv2Iface.getExif(); if (exifData.isEmpty()) { KMessageBox::error(TQT_TQWIDGET(kapp->activeWindow()), i18n("\"%1\" do not have EXIF metadata").arg(importEXIFFile.fileName()), i18n("Import EXIF Metadata")); return; } if (KMessageBox::warningYesNo( TQT_TQWIDGET(kapp->activeWindow()), i18n("EXIF metadata from current selected pictures will be permanently " "replaced by the EXIF content of \"%1\".\n" "Do you want to continue ?").arg(importEXIFFile.fileName()), i18n("Import EXIF Metadata")) != KMessageBox::Yes) return; KURL::List imageURLs = images.images(); KURL::List updatedURLs; TQStringList errorFiles; for( KURL::List::iterator it = imageURLs.begin() ; it != imageURLs.end(); ++it) { KURL url = *it; bool ret = false; if (!KExiv2Iface::KExiv2::isReadOnly(url.path())) { ret = true; KExiv2Iface::KExiv2 exiv2Iface; ret &= exiv2Iface.load(url.path()); ret &= exiv2Iface.setExif(exifData); ret &= exiv2Iface.save(url.path()); } if (!ret) errorFiles.append(url.fileName()); else updatedURLs.append(url); } // We use kipi interface refreshImages() method to tell to host than // metadata from pictures have changed and need to be re-read. m_interface->refreshImages(updatedURLs); if (!errorFiles.isEmpty()) { KMessageBox::errorList( TQT_TQWIDGET(kapp->activeWindow()), i18n("Unable to set EXIF metadata from:"), errorFiles, i18n("Import EXIF Metadata")); } } void Plugin_MetadataEdit::slotEditIptc() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; KIPIMetadataEditPlugin::IPTCEditDialog dialog(TQT_TQWIDGET(kapp->activeWindow()), images.images(), m_interface); dialog.exec(); m_interface->refreshImages(images.images()); } void Plugin_MetadataEdit::slotRemoveIptc() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; if (KMessageBox::warningYesNo( TQT_TQWIDGET(kapp->activeWindow()), i18n("IPTC metadata will be permanently removed from all current selected pictures.\n" "Do you want to continue ?"), i18n("Remove IPTC Metadata")) != KMessageBox::Yes) return; KURL::List imageURLs = images.images(); KURL::List updatedURLs; TQStringList errorFiles; for( KURL::List::iterator it = imageURLs.begin() ; it != imageURLs.end(); ++it) { KURL url = *it; bool ret = false; if (!KExiv2Iface::KExiv2::isReadOnly(url.path())) { ret = true; KExiv2Iface::KExiv2 exiv2Iface; ret &= exiv2Iface.load(url.path()); ret &= exiv2Iface.clearIptc(); ret &= exiv2Iface.save(url.path()); } if (!ret) errorFiles.append(url.fileName()); else updatedURLs.append(url); } // We use kipi interface refreshImages() method to tell to host than // metadata from pictures have changed and need to be re-read. m_interface->refreshImages(updatedURLs); if (!errorFiles.isEmpty()) { KMessageBox::errorList( TQT_TQWIDGET(kapp->activeWindow()), i18n("Unable to remove IPTC metadata from:"), errorFiles, i18n("Remove IPTC Metadata")); } } void Plugin_MetadataEdit::slotImportIptc() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; KURL importIPTCFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(), TQString(), TQT_TQWIDGET(kapp->activeWindow()), i18n("Select File to Import IPTC metadata") ); if( importIPTCFile.isEmpty() ) return; KExiv2Iface::KExiv2 exiv2Iface; if (!exiv2Iface.load(importIPTCFile.path())) { KMessageBox::error(TQT_TQWIDGET(kapp->activeWindow()), i18n("Cannot load metadata from \"%1\"").arg(importIPTCFile.fileName()), i18n("Import IPTC Metadata")); return; } TQByteArray iptcData = exiv2Iface.getIptc(); if (iptcData.isEmpty()) { KMessageBox::error(TQT_TQWIDGET(kapp->activeWindow()), i18n("\"%1\" do not have IPTC metadata").arg(importIPTCFile.fileName()), i18n("Import IPTC Metadata")); return; } if (KMessageBox::warningYesNo( TQT_TQWIDGET(kapp->activeWindow()), i18n("IPTC metadata from current selected pictures will be permanently " "replaced by the IPTC content of \"%1\".\n" "Do you want to continue ?").arg(importIPTCFile.fileName()), i18n("Import IPTC Metadata")) != KMessageBox::Yes) return; KURL::List imageURLs = images.images(); KURL::List updatedURLs; TQStringList errorFiles; for( KURL::List::iterator it = imageURLs.begin() ; it != imageURLs.end(); ++it) { KURL url = *it; bool ret = false; if (!KExiv2Iface::KExiv2::isReadOnly(url.path())) { ret = true; KExiv2Iface::KExiv2 exiv2Iface; ret &= exiv2Iface.load(url.path()); ret &= exiv2Iface.setIptc(iptcData); ret &= exiv2Iface.save(url.path()); } if (!ret) errorFiles.append(url.fileName()); else updatedURLs.append(url); } // We use kipi interface refreshImages() method to tell to host than // metadata from pictures have changed and need to be re-read. m_interface->refreshImages(updatedURLs); if (!errorFiles.isEmpty()) { KMessageBox::errorList( TQT_TQWIDGET(kapp->activeWindow()), i18n("Unable to set IPTC metadata from:"), errorFiles, i18n("Import IPTC Metadata")); } } void Plugin_MetadataEdit::slotEditComments() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; KIPIMetadataEditPlugin::CommentEditDialog dlg(TQT_TQWIDGET(kapp->activeWindow())); if (dlg.exec() != KMessageBox::Ok) return; KURL::List imageURLs = images.images(); KURL::List updatedURLs; TQStringList errorFiles; for( KURL::List::iterator it = imageURLs.begin() ; it != imageURLs.end(); ++it) { KURL url = *it; bool ret = false; KIPI::ImageInfo info = m_interface->info(url); info.setDescription(dlg.getComments()); if (!KExiv2Iface::KExiv2::isReadOnly(url.path())) { ret = true; KExiv2Iface::KExiv2 exiv2Iface; ret &= exiv2Iface.load(url.path()); if (dlg.syncEXIFCommentIsChecked()) ret &= exiv2Iface.setExifComment(dlg.getComments()); if (dlg.syncJFIFCommentIsChecked()) ret &= exiv2Iface.setComments(dlg.getComments().utf8()); if (dlg.syncIPTCCaptionIsChecked()) ret &= exiv2Iface.setIptcTagString("Iptc.Application2.Caption", dlg.getComments()); ret &= exiv2Iface.save(url.path()); } if (!ret) errorFiles.append(url.fileName()); else updatedURLs.append(url); } // We use kipi interface refreshImages() method to tell to host than // metadata from pictures have changed and need to be re-read. m_interface->refreshImages(updatedURLs); if (!errorFiles.isEmpty()) { KMessageBox::informationList( TQT_TQWIDGET(kapp->activeWindow()), i18n("Unable to set captions as image metadata from:"), errorFiles, i18n("Edit Image Caption")); } } void Plugin_MetadataEdit::slotRemoveComments() { KIPI::ImageCollection images = m_interface->currentSelection(); if ( !images.isValid() || images.images().isEmpty() ) return; KIPIMetadataEditPlugin::CommentRemoveDialog dlg(TQT_TQWIDGET(kapp->activeWindow())); if (dlg.exec() != KMessageBox::Ok) return; KURL::List imageURLs = images.images(); KURL::List updatedURLs; TQStringList errorFiles; for( KURL::List::iterator it = imageURLs.begin() ; it != imageURLs.end(); ++it) { KURL url = *it; bool ret = false; if (dlg.removeHOSTCommentIsChecked()) { KIPI::ImageInfo info = m_interface->info(url); info.setDescription(TQString()); } if (!KExiv2Iface::KExiv2::isReadOnly(url.path())) { ret = true; KExiv2Iface::KExiv2 exiv2Iface; ret &= exiv2Iface.load(url.path()); if (dlg.removeEXIFCommentIsChecked()) ret &= exiv2Iface.removeExifTag("Exif.Photo.UserComment"); if (dlg.removeJFIFCommentIsChecked()) ret &= exiv2Iface.setComments(TQByteArray()); if (dlg.removeIPTCCaptionIsChecked()) ret &= exiv2Iface.removeIptcTag("Iptc.Application2.Caption"); ret &= exiv2Iface.save(url.path()); } if (!ret) errorFiles.append(url.fileName()); else updatedURLs.append(url); } // We use kipi interface refreshImages() method to tell to host than // metadata from pictures have changed and need to be re-read. m_interface->refreshImages(updatedURLs); if (!errorFiles.isEmpty()) { KMessageBox::informationList( TQT_TQWIDGET(kapp->activeWindow()), i18n("Unable to remove caption as image metadata from:"), errorFiles, i18n("Remove Image Caption")); } } KIPI::Category Plugin_MetadataEdit::category( TDEAction* action ) const { if ( action == m_actionMetadataEdit ) return KIPI::IMAGESPLUGIN; kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl; return KIPI::IMAGESPLUGIN; // no warning from compiler, please }