diff options
Diffstat (limited to 'kipi-plugins/batchprocessimages')
57 files changed, 9206 insertions, 0 deletions
diff --git a/kipi-plugins/batchprocessimages/Makefile.am b/kipi-plugins/batchprocessimages/Makefile.am new file mode 100644 index 0000000..6899f56 --- /dev/null +++ b/kipi-plugins/batchprocessimages/Makefile.am @@ -0,0 +1,39 @@ +INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(LIBKEXIV2_CFLAGS) $(all_includes) + +METASOURCES = AUTO +SUBDIRS = data + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = kipiplugin_batchprocessimages.la +kipiplugin_batchprocessimages_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) +# Srcs for the plugin +kipiplugin_batchprocessimages_la_SOURCES = plugin_batchprocessimages.cpp batchprocessimagesitem.cpp \ + outputdialog.cpp imagepreview.cpp renameimagesdialog.cpp \ + borderimagesdialog.cpp borderoptionsdialog.cpp \ + convertimagesdialog.cpp convertoptionsdialog.cpp \ + filterimagesdialog.cpp filteroptionsdialog.cpp \ + colorimagesdialog.cpp coloroptionsdialog.cpp \ + effectimagesdialog.cpp effectoptionsdialog.cpp \ + recompressimagesdialog.cpp recompressoptionsdialog.cpp \ + resizeimagesdialog.cpp resizeoptionsdialog.cpp \ + batchprocessimagesdialog.cpp \ + batchprocessimageslist.cpp \ + renameimagesbase.ui renameimageswidget.cpp + +# Libs needed by the plugin +kipiplugin_batchprocessimages_la_LIBADD = $(LIBKIPI_LIBS) $(LIBKEXIV2_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) + +# LD flags for the plugin +kipiplugin_batchprocessimages_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins + +# Install the desktop file needed to detect the plugin +kde_services_DATA = kipiplugin_batchprocessimages.desktop + +# i18n translation messages +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_batchprocessimages.pot + +kipibatchprocessimagesicondir = $(kde_datadir)/kipiplugin_batchprocessimages/icons +kipibatchprocessimagesicon_ICON = AUTO + + diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp new file mode 100644 index 0000000..e1706a6 --- /dev/null +++ b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp @@ -0,0 +1,1092 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// C Ansi includes + +extern "C" +{ +#include <unistd.h> +} + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qdir.h> +#include <qwidget.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <qwhatsthis.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <qprocess.h> +#include <qcolor.h> +#include <qpainter.h> +#include <qpalette.h> +#include <qimage.h> +#include <qevent.h> +#include <qdragobject.h> +#include <qfileinfo.h> +#include <qhgroupbox.h> +#include <qvgroupbox.h> +#include <qframe.h> +#include <qwmatrix.h> + +// Include files for KDE + +#include <kstandarddirs.h> +#include <kcolorbutton.h> +#include <klocale.h> +#include <kprogress.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kinstance.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <klistview.h> +#include <kimageio.h> +#include <kprocess.h> +#include <klineeditdlg.h> +#include <kio/jobclasses.h> +#include <kio/netaccess.h> +#include <kio/global.h> +#include <kio/previewjob.h> +#include <kbuttonbox.h> +#include <kdiroperator.h> +#include <kdeversion.h> +#include <kurlrequester.h> +#include <klineedit.h> + +// KIPI includes + +#include <libkipi/uploadwidget.h> +#include <libkipi/imagedialog.h> + +// Local includes + +#include "pluginsversion.h" +#include "outputdialog.h" +#include "imagepreview.h" +#include "batchprocessimagesdialog.h" +#include "batchprocessimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +BatchProcessImagesDialog::BatchProcessImagesDialog( KURL::List urlList, KIPI::Interface* interface, + QString caption, QWidget *parent ) + : KDialogBase( KDialogBase::Plain, caption, Help|User1|Cancel, + Cancel, parent, "BatchProcessImagesDialog", false, false, i18n("&Start")), + m_selectedImageFiles( urlList), m_interface( interface ) +{ + // Init. Tmp folder + + KStandardDirs dir; + m_tmpFolder = dir.saveLocation("tmp", "kipi-batchprocessimagesplugin-" + + QString::number(getpid()) ); + + m_convertStatus = NO_PROCESS; + m_progressStatus = 0; + m_ProcessusProc = 0; + m_PreviewProc = 0; + + KImageIO::registerFormats(); + + QWidget* box = plainPage(); + QVBoxLayout *dvlay = new QVBoxLayout(box, 0, KDialog::spacingHint()); + + //--------------------------------------------- + + QHBoxLayout *hlay = new QHBoxLayout( dvlay ); + groupBox1 = new QGroupBox( 0, Qt::Vertical, box ); + groupBox1->layout()->setSpacing(KDialog::spacingHint()); + groupBox1->layout()->setMargin(KDialog::marginHint()); + QGridLayout* grid = new QGridLayout( groupBox1->layout(), 2, 3); + m_labelType = new QLabel( groupBox1 ); + grid->addMultiCellWidget(m_labelType, 0, 0, 0, 0); + + m_Type = new QComboBox(false, groupBox1); + grid->addMultiCellWidget(m_Type, 0, 0, 1, 1); + + m_optionsButton = new QPushButton (groupBox1, "OptionButton"); + m_optionsButton->setText(i18n("Options")); + QWhatsThis::add( m_optionsButton, i18n("<p>You can choose here the options to use " + "for the current process.")); + grid->addMultiCellWidget(m_optionsButton, 0, 0, 2, 2); + + m_smallPreview = new QCheckBox(i18n("Small preview"), groupBox1); + QWhatsThis::add( m_smallPreview, i18n("<p>If you enable this option, " + "all preview effects will be calculated on a small zone " + "of the image (300x300 pixels in the top left corner). " + "Enable this option if you have a slow computer.") ); + m_smallPreview->setChecked( true ); + grid->addMultiCellWidget(m_smallPreview, 1, 1, 0, 1); + + m_previewButton = new QPushButton (groupBox1, "PreviewButton"); + m_previewButton->setText(i18n("&Preview")); + QWhatsThis::add( m_previewButton, i18n("<p>This button builds a process " + "preview for the currently selected image on the list.")); + grid->addMultiCellWidget(m_previewButton, 1, 1, 2, 2); + + hlay->addWidget( groupBox1 ); + + //--------------------------------------------- + + groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("File Operations"), box ); + + m_labelOverWrite = new QLabel (i18n("Overwrite mode:"), groupBox2); + m_overWriteMode = new QComboBox( false, groupBox2 ); + m_overWriteMode->insertItem(i18n("Ask")); + m_overWriteMode->insertItem(i18n("Always Overwrite")); + m_overWriteMode->insertItem(i18n("Rename")); + m_overWriteMode->insertItem(i18n("Skip")); + m_overWriteMode->setCurrentText (i18n("Rename")); + QWhatsThis::add( m_overWriteMode, i18n("<p>Select here the overwrite mode used if your target's image " + "files already exist.") ); + + m_removeOriginal = new QCheckBox(i18n("Remove original"), groupBox2); + QWhatsThis::add( m_removeOriginal, i18n("<p>If you enable this option, " + "all original image files will be removed after processing.") ); + m_removeOriginal->setChecked( false ); + + hlay->addWidget( groupBox2 ); + + //--------------------------------------------- + + groupBox3 = new QHGroupBox( i18n("Target Folder"), box ); + + m_destinationURL = new KURLRequester(groupBox3); + m_destinationURL->setMode(KFile::Directory | KFile::LocalOnly); + KIPI::ImageCollection album = interface->currentAlbum(); + if (album.isValid()) + { + QString url; + if (album.isDirectory()) + { + url = album.uploadPath().path(); + } + else + { + url = QDir::homeDirPath(); + } + m_destinationURL->lineEdit()->setText(url); + } + QWhatsThis::add( m_destinationURL, i18n("<p>Here you can select the target folder which " + "will used by the process.")); + + dvlay->addWidget( groupBox3 ); + + //--------------------------------------------- + + groupBox4 = new QHGroupBox( box ); + QWidget* box41 = new QWidget( groupBox4 ); + QHBoxLayout* lay2 = new QHBoxLayout( box41, 0, spacingHint() ); + m_listFiles = new BatchProcessImagesList( box41 ); + lay2->addWidget( m_listFiles ); + + m_listFiles->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding); + + QVBoxLayout* lay3 = new QVBoxLayout( lay2 ); + m_addImagesButton = new QPushButton ( i18n( "&Add..." ), box41 ); + lay3->addWidget( m_addImagesButton ); + QWhatsThis::add( m_addImagesButton, i18n("<p>Add images to the list.") ); + + m_remImagesButton = new QPushButton ( i18n( "&Remove" ), box41 ); + lay3->addWidget( m_remImagesButton ); + QWhatsThis::add( m_remImagesButton, i18n("<p>Remove selected image from the list.") ); + + m_imageLabel = new QLabel( box41 ); + m_imageLabel->setFixedHeight( 80 ); + m_imageLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter ); + m_imageLabel->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) ); + lay3->addWidget( m_imageLabel ); + QWhatsThis::add( m_imageLabel, i18n( "<p>The preview of the selected image on the list." ) ); + lay3->addStretch( 1 ); + + dvlay->addWidget( groupBox4 ); + + //--------------------------------------------- + + m_progress = new KProgress( box, "Progress" ); + m_progress->setTotalSteps(100); + m_progress->setValue(0); + QWhatsThis::add( m_progress, i18n("<p>This is the current percentage of the task completed.") ); + + dvlay->addWidget( m_progress ); + + //--------------------------------------------- + + connect(m_listFiles, SIGNAL(doubleClicked(QListViewItem *)), + this, SLOT(slotListDoubleClicked(QListViewItem *))); + + connect(this, SIGNAL(user1Clicked()), + this, SLOT(slotProcessStart())); + + connect(m_optionsButton, SIGNAL(clicked()), + this, SLOT(slotOptionsClicked())); + + connect(m_previewButton, SIGNAL(clicked()), + this, SLOT(slotPreview())); + + connect(m_Type, SIGNAL(activated(int)), + this, SLOT(slotTypeChanged(int))); + + connect(m_listFiles, SIGNAL( addedDropItems(QStringList) ), + this, SLOT( slotAddDropItems(QStringList))); + + connect(m_listFiles, SIGNAL( currentChanged( QListViewItem * ) ), + this, SLOT( slotImageSelected( QListViewItem * ))); + + connect(m_addImagesButton, SIGNAL(clicked()), + this, SLOT(slotImagesFilesButtonAdd())); + + connect(m_remImagesButton, SIGNAL(clicked()), + this, SLOT(slotImagesFilesButtonRem())); + + // Get the image files filters from the hosts app. + + m_ImagesFilesSort = m_interface->fileExtensions(); + + dvlay->activate(); +} + +BatchProcessImagesDialog::~BatchProcessImagesDialog() +{ +} + +void BatchProcessImagesDialog::slotImagesFilesButtonAdd( void ) +{ + QStringList ImageFilesList; + + KURL::List urls = KIPI::ImageDialog::getImageURLs( this, m_interface ); + + for ( KURL::List::Iterator it = urls.begin() ; it != urls.end() ; ++it ) + ImageFilesList << (*it).path(); // PENDING(blackie) handle remote URLS + + if ( urls.isEmpty() ) return; + + slotAddDropItems(ImageFilesList); +} + +void BatchProcessImagesDialog::slotImagesFilesButtonRem( void ) +{ + BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>( m_listFiles->currentItem() ); + + if ( pitem ) + { + m_listFiles->takeItem(pitem); + m_listFiles->setSelected( m_listFiles->currentItem(), true ); + m_selectedImageFiles.remove(m_selectedImageFiles.find(pitem->pathSrc())); + delete pitem; + m_nbItem = m_selectedImageFiles.count(); + + if (m_nbItem == 0) + groupBox4->setTitle(i18n("Image Files List")); + else + groupBox4->setTitle(i18n("Image File List (1 item)", "Image File List (%n items)", m_nbItem)); + } +} + +void BatchProcessImagesDialog::slotImageSelected( QListViewItem * item ) +{ + if ( !item || m_listFiles->childCount() == 0 ) + { + m_imageLabel->clear(); + return; + } + + BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>( item ); + if ( !pitem ) return; + + m_imageLabel->clear(); + + QString IdemIndexed = "file:" + pitem->pathSrc(); + + KURL url(IdemIndexed); + + KIO::PreviewJob* m_thumbJob = KIO::filePreview( url, m_imageLabel->height() ); + + connect(m_thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)), + this, SLOT(slotGotPreview(const KFileItem*, const QPixmap&))); +} + +void BatchProcessImagesDialog::slotGotPreview(const KFileItem* url, const QPixmap &pixmap) +{ + QPixmap pix( pixmap ); + + // Rotate the thumbnail compared to the angle the host application dictate + KIPI::ImageInfo info = m_interface->info( url->url() ); + if ( info.angle() != 0 ) + { + QImage img = pix.convertToImage(); + QWMatrix matrix; + + matrix.rotate( info.angle() ); + img = img.xForm( matrix ); + pix.convertFromImage( img ); + } + + m_imageLabel->setPixmap(pix); +} + +void BatchProcessImagesDialog::slotAddDropItems(QStringList filesPath) +{ + if (filesPath.isEmpty()) return; + + for ( QStringList::Iterator it = filesPath.begin() ; it != filesPath.end() ; ++it ) + { + QString currentDropFile = *it; + + // Check if the new item already exist in the list. + + bool findItem = false; + + for ( KURL::List::Iterator it2 = m_selectedImageFiles.begin() ; it2 != m_selectedImageFiles.end() ; ++it2 ) + { + QString currentFile = (*it2).path(); // PENDING(blackie) Handle URL's + + if ( currentFile == currentDropFile ) + findItem = true; + } + + if (findItem == false) + m_selectedImageFiles.append(currentDropFile); + } + + listImageFiles(); +} + +void BatchProcessImagesDialog::closeEvent ( QCloseEvent *e ) +{ + if (!e) return; + + if ( m_PreviewProc != 0 ) + if ( m_PreviewProc->isRunning() ) m_PreviewProc->kill(SIGTERM); + + if ( m_ProcessusProc != 0 ) + if ( m_ProcessusProc->isRunning() ) m_ProcessusProc->kill(SIGTERM); + + e->accept(); +} + +void BatchProcessImagesDialog::slotProcessStart( void ) +{ + if ( m_selectedImageFiles.isEmpty() == true ) + return; + + if ( m_removeOriginal->isChecked() == true ) + { + if ( KMessageBox::warningContinueCancel(this, + i18n("All original image files will be removed from the source Album.\nDo you want to continue?"), + i18n("Delete Original Image Files"), KStdGuiItem::cont(), + "KIPIplugin-BatchProcessImages-AlwaysRemomveOriginalFiles") != KMessageBox::Continue ) + return; + } + + m_convertStatus = UNDER_PROCESS; + disconnect( this, SIGNAL(user1Clicked()), this, SLOT(slotProcessStart())); + showButtonCancel( false ); + setButtonText( User1, i18n("&Stop") ); + connect(this, SIGNAL(user1Clicked()), this, SLOT(slotProcessStop())); + + m_labelType->setEnabled(false); + m_Type->setEnabled(false); + m_optionsButton->setEnabled(false); + m_previewButton->setEnabled(false); + m_smallPreview->setEnabled(false); + + m_labelOverWrite->setEnabled(false); + m_overWriteMode->setEnabled(false); + m_removeOriginal->setEnabled(false); + + m_destinationURL->setEnabled(false); + m_addImagesButton->setEnabled(false); + m_remImagesButton->setEnabled(false); + + m_listFile2Process_iterator = new QListViewItemIterator( m_listFiles ); + startProcess(); +} + +bool BatchProcessImagesDialog::startProcess(void) +{ + if ( m_convertStatus == STOP_PROCESS ) + { + endProcess(); + return true; + } + + QString targetAlbum = m_destinationURL->url(); + + //TODO check if it is valid also for remote URL's + // this is a workarond for bug 117397 + QFileInfo dirInfo(targetAlbum + "/"); + if (!dirInfo.isDir () || !dirInfo.isWritable()) + { + KMessageBox::error(this, i18n("You must specify a writable path for your output file.")); + endProcess(); + return true; + } + + BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() ); + m_listFiles->setCurrentItem(item); + + if ( prepareStartProcess(item, targetAlbum) == false ) // If there is a problem during the + { // preparation -> pass to the next item! + ++*m_listFile2Process_iterator; + ++m_progressStatus; + m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem)); + item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() ); + m_listFiles->setCurrentItem(item); + + if ( m_listFile2Process_iterator->current() ) + { + startProcess(); + return true; + } + else + { + endProcess(); + return true; + } + } + + KURL desturl(targetAlbum + "/" + item->nameDest()); + +#if KDE_VERSION >= 0x30200 + if ( KIO::NetAccess::exists( desturl, false, kapp->activeWindow() ) == true ) +#else + if ( KIO::NetAccess::exists( desturl ) == true ) +#endif + { + switch (overwriteMode()) + { + case OVERWRITE_ASK: + { + int ValRet = KMessageBox::warningYesNoCancel(this, + i18n("The destination file \"%1\" already exists;\n" + "do you want overwrite it?").arg(item->nameDest()), + i18n("Overwrite Destination Image File"), KStdGuiItem::cont()); + + if ( ValRet == KMessageBox::No ) + { + item->changeResult(i18n("Skipped.")); + item->changeError(i18n("destination image file already exists (skipped by user).")); + ++*m_listFile2Process_iterator; + ++m_progressStatus; + m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem)); + + if ( m_listFile2Process_iterator->current() ) + { + startProcess(); + return true; + } + else + { + endProcess(); + return true; + } + } + else if ( ValRet == KMessageBox::Cancel ) + { + processAborted(false); + return false; + } + else + { + item->setDidOverWrite( true ); + } + + break; + } + + case OVERWRITE_RENAME: + { + QFileInfo *Target = new QFileInfo(targetAlbum + "/" + item->nameDest()); + QString newFileName = RenameTargetImageFile(Target); + + if ( newFileName.isNull() ) + { + item->changeResult(i18n("Failed.")); + item->changeError(i18n("destination image file already exists and cannot be renamed.")); + ++*m_listFile2Process_iterator; + ++m_progressStatus; + m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem)); + + if ( m_listFile2Process_iterator->current() ) + { + startProcess(); + return true; + } + else + { + endProcess(); + return true; + } + } + else + { + QFileInfo *newTarget = new QFileInfo(newFileName); + item->changeNameDest(newTarget->fileName()); + } + + break; + } + + case OVERWRITE_SKIP: + { + item->changeResult(i18n("Skipped.")); + item->changeError(i18n("destination image file already exists (skipped automatically).")); + ++*m_listFile2Process_iterator; + ++m_progressStatus; + m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem)); + + if ( m_listFile2Process_iterator->current() ) + { + startProcess(); + return true; + } + else + { + endProcess(); + return true; + } + break; + } + + case OVERWRITE_OVER: // In this case do nothing : 'convert' default mode... + item->setDidOverWrite( true ); + break; + + default: + { + endProcess(); + return true; + break; + } + } + } + + m_commandLine = QString(); + m_ProcessusProc = new KProcess; + m_commandLine.append(makeProcess(m_ProcessusProc, item, targetAlbum)); + + item->changeOutputMess(m_commandLine + "\n\n"); + + connect(m_ProcessusProc, SIGNAL(processExited(KProcess *)), + this, SLOT(slotProcessDone(KProcess*))); + + connect(m_ProcessusProc, SIGNAL(receivedStdout(KProcess *, char*, int)), + this, SLOT(slotReadStd(KProcess*, char*, int))); + + connect(m_ProcessusProc, SIGNAL(receivedStderr(KProcess *, char*, int)), + this, SLOT(slotReadStd(KProcess*, char*, int))); + + bool result = m_ProcessusProc->start(KProcess::NotifyOnExit, KProcess::All); + if(!result) + { + KMessageBox::error(this, i18n("Cannot start 'convert' program from 'ImageMagick' package;\n" + "please check your installation.")); + return false; + } + + return true; +} + +void BatchProcessImagesDialog::slotReadStd(KProcess* /*proc*/, char *buffer, int buflen) +{ + BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() ); + item->changeOutputMess( QString::fromLocal8Bit(buffer, buflen) ); +} + +void BatchProcessImagesDialog::slotProcessDone(KProcess* proc) +{ + if ( m_convertStatus == PROCESS_DONE ) + { + // processAborted() has already been called. No need to show the warning. + return; + } + + BatchProcessImagesItem *item = dynamic_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() ); + m_listFiles->ensureItemVisible(m_listFiles->currentItem()); + + if ( !m_ProcessusProc->normalExit() ) + { + int code = KMessageBox::warningContinueCancel( this, + i18n("The 'convert' program from 'ImageMagick' package has been stopped abnormally"), + i18n("Error running 'convert'") ); + + if ( code == KMessageBox::Cancel ) + { + processAborted(true); + } + else + { + item->changeResult(i18n("Failed.")); + item->changeError(i18n("'convert' program from 'ImageMagick' package has been stopped abnormally.")); + ++*m_listFile2Process_iterator; + ++m_progressStatus; + m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem)); + + if ( m_listFile2Process_iterator->current() ) + startProcess(); + else + endProcess(); + } + return; + } + + int ValRet = proc->exitStatus(); + kdWarning() << "Convert exit (" << ValRet << ")" << endl; + + switch (ValRet) + { + case 0: // Process finished successfully ! + { + item->changeResult(i18n("OK")); + item->changeError(i18n("no processing error")); + processDone(); + + // Save the comments for the converted image + KURL src; + src.setPath( item->pathSrc() ); + KURL dest = m_destinationURL->url(); + dest.addPath( item->nameDest() ); + QString errmsg; + + KURL::List urlList; + urlList.append(src); + urlList.append(dest); + m_interface->refreshImages( urlList ); + + if ( !item->overWrote() ) + { + // Do not add an entry if there was an image at the location already. + bool ok = m_interface->addImage( dest, errmsg ); + + if ( !ok ) + { + int code = KMessageBox::warningContinueCancel( this, + i18n("<qt>Error adding image to application; error message was: " + "<b>%1</b></qt>").arg( errmsg ), + i18n("Error Adding Image to Application") ); + + if ( code == KMessageBox::Cancel ) + { + slotProcessStop(); + break; + } + else + item->changeResult(i18n("Failed.")); + } + } + + if ( src != dest ) + { + KIPI::ImageInfo srcInfo = m_interface->info( src ); + KIPI::ImageInfo destInfo = m_interface->info( dest ); + destInfo.cloneData( srcInfo ); + } + + if ( m_removeOriginal->isChecked() && src != dest ) + { + KURL deleteImage(item->pathSrc()); + +#if KDE_VERSION >= 0x30200 + if ( KIO::NetAccess::del( deleteImage, kapp->activeWindow() ) == false ) +#else + if ( KIO::NetAccess::del( deleteImage ) == false ) +#endif + { + item->changeResult(i18n("Warning:")); + item->changeError(i18n("cannot remove original image file.")); + } + else + m_interface->delImage( item->pathSrc() ); + } + break; + } + case 15: // process aborted ! + { + processAborted(true); + break; + } + default : // Processing error ! + { + item->changeResult(i18n("Failed.")); + item->changeError(i18n("cannot process original image file.")); + break; + } + } + + ++*m_listFile2Process_iterator; + ++m_progressStatus; + m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem)); + + if ( m_listFile2Process_iterator->current() ) + startProcess(); + else + endProcess(); +} + +void BatchProcessImagesDialog::slotListDoubleClicked(QListViewItem *itemClicked) +{ + BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( itemClicked ); + + if (m_convertStatus == PROCESS_DONE) + { + OutputDialog *infoDialog = new OutputDialog(this, + i18n("Image processing error"), + item->outputMess(), + i18n("Image \"%1\": %2\n\nThe output messages are:\n") + .arg(item->nameSrc()).arg(item->error()) + ); + infoDialog->exec(); + } +} + +void BatchProcessImagesDialog::slotPreview(void) +{ + kdWarning() << "BatchProcessImagesDialog::slotPreview" << endl; + + if ( m_listFiles->currentItem() == 0 ) + { + KMessageBox::error(this, i18n("You must select an item from the list to calculate the preview.")); + return; + } + + BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFiles->currentItem() ); + + m_listFiles->setEnabled(false); + m_labelType->setEnabled(false); + m_Type->setEnabled(false); + m_optionsButton->setEnabled(false); + m_previewButton->setEnabled(false); + m_labelOverWrite->setEnabled(false); + m_overWriteMode->setEnabled(false); + m_removeOriginal->setEnabled(false); + m_smallPreview->setEnabled(false); + m_destinationURL->setEnabled(false); + m_addImagesButton->setEnabled(false); + m_remImagesButton->setEnabled(false); + + disconnect( this, SIGNAL(user1Clicked()), + this, SLOT(slotProcessStart())); + + showButtonCancel( false ); + setButtonText( User1, i18n("&Stop") ); + + connect(this, SIGNAL(user1Clicked()), + this, SLOT(slotPreviewStop())); + + m_previewOutput = ""; + m_PreviewProc = new KProcess; + + m_previewOutput.append(makeProcess(m_PreviewProc, item, QString(), true)); + + *m_PreviewProc << m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG"; + m_previewOutput.append( " " + m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG\n\n"); + + connect(m_PreviewProc, SIGNAL(processExited(KProcess *)), + this, SLOT(slotPreviewProcessDone(KProcess*))); + + connect(m_PreviewProc, SIGNAL(receivedStdout(KProcess *, char*, int)), + this, SLOT(slotPreviewReadStd(KProcess*, char*, int))); + + connect(m_PreviewProc, SIGNAL(receivedStderr(KProcess *, char*, int)), + this, SLOT(slotPreviewReadStd(KProcess*, char*, int))); + + bool result = m_PreviewProc->start(KProcess::NotifyOnExit, KProcess::All); + if(!result) + { + KMessageBox::error(this, i18n("Cannot start 'convert' program from 'ImageMagick' package;\n" + "please check your installation.")); + m_previewButton->setEnabled(true); + return; + } +} + +void BatchProcessImagesDialog::slotPreviewReadStd(KProcess* /*proc*/, char *buffer, int buflen) +{ + m_previewOutput.append( QString::fromLocal8Bit(buffer, buflen) ); +} + +void BatchProcessImagesDialog::slotPreviewProcessDone(KProcess* proc) +{ + if (!m_PreviewProc->normalExit()) + { + KMessageBox::error(this, i18n("Cannot run properly 'convert' program from 'ImageMagick' package.")); + m_previewButton->setEnabled(true); + return; + } + + BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFiles->currentItem() ); + int ValRet = proc->exitStatus(); + + kdWarning() << "Convert exit (" << ValRet << ")" << endl; + + if ( ValRet == 0 ) + { + QString cropTitle = ""; + + if ( m_smallPreview->isChecked() ) + cropTitle = i18n(" - small preview"); + + ImagePreview *previewDialog = new ImagePreview( + item->pathSrc(), + m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG", + m_tmpFolder, + m_smallPreview->isChecked(), + false, + m_Type->currentText() + cropTitle, + item->nameSrc(), + this); + previewDialog->exec(); + + KURL deletePreviewImage(m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG"); + +#if KDE_VERSION >= 0x30200 + KIO::NetAccess::del( deletePreviewImage, kapp->activeWindow() ); +#else + KIO::NetAccess::del( deletePreviewImage ); +#endif + } + else + { + OutputDialog *infoDialog = new OutputDialog(this, + i18n("Preview processing error"), + m_previewOutput, + i18n("Cannot process preview for image \"%1\"." + "\nThe output messages are:\n") + .arg(item->nameSrc()) + ); + infoDialog->exec(); + } + + endPreview(); +} + +void BatchProcessImagesDialog::slotPreviewStop( void ) +{ + // Try to kill the current preview process ! + if ( m_PreviewProc->isRunning() == true ) m_PreviewProc->kill(SIGTERM); + + endPreview(); +} + +void BatchProcessImagesDialog::slotProcessStop( void ) +{ + // Try to kill the current process ! + if ( m_ProcessusProc->isRunning() == true ) m_ProcessusProc->kill(SIGTERM); + + // If kill operation failed, Stop the process at the next image ! + if ( m_convertStatus == UNDER_PROCESS ) m_convertStatus = STOP_PROCESS; + + processAborted(true); +} + +void BatchProcessImagesDialog::slotOk() +{ + close(); + saveSettings(); + delete this; +} + +void BatchProcessImagesDialog::listImageFiles(void) +{ + m_nbItem = m_selectedImageFiles.count(); + + if (m_nbItem == 0) groupBox4->setTitle(i18n("Image File List")); + else + groupBox4->setTitle(i18n("Image File List (1 item)", "Image File List (%n items)", m_nbItem)); + + if (m_selectedImageFiles.isEmpty()) return; + + for ( KURL::List::Iterator it = m_selectedImageFiles.begin() ; it != m_selectedImageFiles.end() ; ++it ) + { + QString currentFile = (*it).path(); // PENDING(blackie) Handle URLS + QFileInfo *fi = new QFileInfo(currentFile); + + // Check if the new item already exist in the list. + + bool findItem = false; + + QListViewItemIterator it2( m_listFiles ); + + while ( it2.current() ) + { + BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>(it2.current()); + + if ( pitem->pathSrc() == currentFile.section('/', 0, -1) ) + findItem = true; + + ++it2; + } + + if (findItem == false) + { + QString oldFileName = fi->fileName(); + QString newFileName = oldFileName2NewFileName(oldFileName); + + new BatchProcessImagesItem(m_listFiles, + currentFile.section('/', 0, -1), + oldFileName, + newFileName, + "" + ); + } + + delete fi; + } + + m_listFiles->setCurrentItem( m_listFiles->firstChild()); + m_listFiles->setSelected( m_listFiles->currentItem(), true ); + slotImageSelected(m_listFiles->currentItem()); + m_listFiles->ensureItemVisible(m_listFiles->currentItem()); +} + +void BatchProcessImagesDialog::endPreview(void) +{ + m_listFiles->setEnabled(true); + m_labelType->setEnabled(true); + m_Type->setEnabled(true); + m_previewButton->setEnabled(true); + m_labelOverWrite->setEnabled(true); + m_overWriteMode->setEnabled(true); + m_destinationURL->setEnabled(true); + m_addImagesButton->setEnabled(true); + m_remImagesButton->setEnabled(true); + m_smallPreview->setEnabled(true); + m_removeOriginal->setEnabled(true); + showButtonCancel( true ); + + m_optionsButton->setEnabled(true); // Default status if 'slotTypeChanged' isn't re-implemented. + slotTypeChanged(m_Type->currentItem()); + + setButtonText( User1, i18n("&Start") ); + + disconnect(this, SIGNAL(user1Clicked()), + this, SLOT(slotPreviewStop())); + + connect(this, SIGNAL(user1Clicked()), + this, SLOT(slotProcessStart())); +} + +int BatchProcessImagesDialog::overwriteMode(void) +{ + QString OverWrite = m_overWriteMode->currentText(); + + if (OverWrite == i18n("Ask")) + return OVERWRITE_ASK; + + if (OverWrite == i18n("Rename")) + return OVERWRITE_RENAME; + + if (OverWrite == i18n("Skip")) + return OVERWRITE_SKIP; + + if (OverWrite == i18n("Always Overwrite")) + return OVERWRITE_OVER; + + return OVERWRITE_ASK; +} + +void BatchProcessImagesDialog::processAborted(bool removeFlag) +{ + kdWarning() << "BatchProcessImagesDialog::processAborted" << endl; + + BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() ); + m_listFiles->ensureItemVisible(m_listFiles->currentItem()); + + item->changeResult(i18n("Aborted.")); + item->changeError(i18n("process aborted by user")); + + if (removeFlag == true) // Try to delete de destination ! + { + KURL deleteImage = m_destinationURL->url(); + deleteImage.addPath(item->nameDest()); + +#if KDE_VERSION >= 0x30200 + if ( KIO::NetAccess::exists( deleteImage, false, kapp->activeWindow() ) == true ) + KIO::NetAccess::del( deleteImage, kapp->activeWindow() ); +#else + if ( KIO::NetAccess::exists( deleteImage ) == true ) + KIO::NetAccess::del( deleteImage ); +#endif + } + + endProcess(); +} + +void BatchProcessImagesDialog::endProcess(void) +{ + m_convertStatus = PROCESS_DONE; + setButtonText( User1, i18n("&Close") ); + + disconnect(this, SIGNAL(user1Clicked()), + this, SLOT(slotProcessStop())); + + connect(this, SIGNAL(user1Clicked()), + this, SLOT(slotOk())); +} + +QString BatchProcessImagesDialog::RenameTargetImageFile(QFileInfo *fi) +{ + QString Temp; + int Enumerator = 0; + KURL NewDestUrl; + + do + { + ++Enumerator; + Temp = Temp.setNum( Enumerator ); + NewDestUrl = fi->filePath().left( fi->filePath().findRev('.', -1)) + "_" + Temp + + "." + fi->filePath().section('.', -1 ); + } + while ( Enumerator < 100 && +#if KDE_VERSION >= 0x30200 + KIO::NetAccess::exists( NewDestUrl, true, kapp->activeWindow() ) +#else + KIO::NetAccess::exists( NewDestUrl ) +#endif + == true ); + + if (Enumerator == 100) return QString(); + + return (NewDestUrl.path()); +} + +QString BatchProcessImagesDialog::extractArguments(KProcess *proc) +{ + QString retArguments; + QValueList<QCString> argumentsList = proc->args(); + + for ( QValueList<QCString>::iterator it = argumentsList.begin() ; it != argumentsList.end() ; ++it ) + retArguments.append(*it + " "); + + return (retArguments); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h new file mode 100644 index 0000000..6792781 --- /dev/null +++ b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h @@ -0,0 +1,246 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef BATCHPROCESSIMAGESDIALOG_H +#define BATCHPROCESSIMAGESDIALOG_H + +#define OVERWRITE_ASK 0 +#define OVERWRITE_RENAME 1 +#define OVERWRITE_SKIP 2 +#define OVERWRITE_OVER 3 + +#define NO_PROCESS 0 +#define UNDER_PROCESS 1 +#define PROCESS_DONE 2 +#define STOP_PROCESS 3 + +// Include files for Qt + +#include <qstring.h> +#include <qpushbutton.h> +#include <qguardedptr.h> + +// Include files for KDE + +#include <kio/job.h> +#include <kdialogbase.h> +#include <kdebug.h> +#include <kurl.h> + +// Include files for KIPI + +#include <libkipi/interface.h> + +// Local includes + +#include "batchprocessimagesitem.h" +#include "batchprocessimageslist.h" + +class QLabel; +class QComboBox; +class QCheckBox; +class QFileInfo; +class QPushButton; +class QListViewItemIterator; +class QListViewItem; +class QGroupBox; + +class KProcess; +class KConfig; +class KProgress; +class KURL; +class KURLRequester; +class KFileItem; + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesDialog : public KDialogBase +{ +Q_OBJECT + + public: + // Don't forget to add the 'm_Type' and 'm_labelType' implementation in the constructor of + // children dialog class. + + BatchProcessImagesDialog( KURL::List urlList, KIPI::Interface* interface, QString caption, QWidget *parent=0 ); + ~BatchProcessImagesDialog(); + +protected slots: + void slotProcessStop(void); + +private slots: + + // -------------------------------------------------------------------------------------------------------- + // Standards slots + + void closeEvent ( QCloseEvent *e ); + void slotOk( void ); + + void slotProcessStart(void); + void slotProcessDone(KProcess* proc); + void slotReadStd(KProcess* proc, char *buffer, int buflen); + + void slotPreview(void); + void slotPreviewProcessDone(KProcess* proc); + void slotPreviewReadStd(KProcess* proc, char *buffer, int buflen); + void slotPreviewStop( void ); + + void slotListDoubleClicked(QListViewItem *itemClicked); + + void slotAddDropItems(QStringList filesPath); + + void slotImageSelected( QListViewItem * item ); + void slotGotPreview(const KFileItem* , const QPixmap &pixmap); + + void slotImagesFilesButtonAdd( void ); + void slotImagesFilesButtonRem( void ); + + // -------------------------------------------------------------------------------------------------------- + // Standards virtuals slots for re-implementation + + virtual void slotHelp(void){}; // Called when 'Help' menu option is actived. + virtual void slotOptionsClicked(void){}; // Called when 'Options' button is clicked. + virtual void slotTypeChanged(int){}; // Called when the current type option is changed. + + protected: + + // -------------------------------------------------------------------------------------------------------- + // Standards widgets in the dialog + + QLabel *m_labelOverWrite; + QLabel *m_labelType; + QLabel *m_imageLabel; + + QComboBox *m_overWriteMode; + QComboBox *m_Type; + + KURLRequester *m_destinationURL; + + BatchProcessImagesList *m_listFiles; + KProgress *m_progress; + + QCheckBox *m_removeOriginal; + QCheckBox *m_smallPreview; + + QGroupBox *groupBox1; + QGroupBox *groupBox2; + QGroupBox *groupBox3; + QGroupBox *groupBox4; + QGroupBox *groupBox41; + + QPushButton *m_optionsButton; + QPushButton *m_previewButton; + QPushButton *m_addImagesButton; + QPushButton *m_remImagesButton; + QPushButton *m_helpButton; + + KConfig *m_config; + + int m_convertStatus; + int m_progressStatus; + int m_nbItem; + + KProcess *m_ProcessusProc; + KProcess *m_PreviewProc; + + QListViewItemIterator *m_listFile2Process_iterator; + + QString whatsThis; + QString m_ImagesFilesSort; + QString m_newDir; + QString m_commandLine; + QString m_tmpFolder; + QString m_previewOutput; + KURL::List m_selectedImageFiles; + + KIPI::Interface *m_interface; + + // -------------------------------------------------------------------------------------------------------- + // Standards fonctions + + // Fonctions for ImageMAgick call implementations. + + void processAborted(bool removeFlag=false); // Called when ImageMagick process is stopped by user. + void endPreview(void); // Called when preview process is done or stopped by user. + + // Called for to parse the files overwriting mode selected by user. + + int overwriteMode(void); + + // Called for rename the target current image file name if already exist. + + QString RenameTargetImageFile(QFileInfo *fi); + + // Extract the arguments from a KProcess an merge that in a QString. Used by makeProcess for to + // show the command line arguments (debugging). + + QString extractArguments(KProcess *proc); + + // -------------------------------------------------------------------------------------------------------- + // Standards virtuals fonctions for re-implementation. + + // Called when ImageMagick process is started or for another re-implementation without + // ImageMagick calls (like 'RenameImages' plugin). + + virtual bool startProcess(void); + + // Called when ImageMagick process is done or stopped by user or for another re-implementation without + // ImageMagick calls (like 'RenameImages' plugin). + + virtual void endProcess(void); + + // Fonctions for ImageMagick implementation calls only. + + // Called by 'startProcess' fonction at start. You can checking here some things about the current + // 'item' before the 'startprocess' fonction execution. + + virtual bool prepareStartProcess(BatchProcessImagesItem */*item*/, const QString& /*albumDest*/) { return true; }; + + // Called for to contruct the ImageMagick command line used for to process or preview the image traitements. + // If 'albumDest' = 0L ==> preview process. + + virtual QString makeProcess(KProcess* /*proc*/, BatchProcessImagesItem */*item*/, + const QString& /*albumDest*/ = QString::null, + bool /*previewMode*/ = false) + { return QString::null; }; + + virtual void processDone(){}; + + // Fonctions used for to read and to save the settings in the configuration file. + + virtual void readSettings(void){}; + virtual void saveSettings(void){}; + + // Called for add or update the list of images to process in the dialog. + + virtual void listImageFiles(void); + + // Called by 'listImageFiles' for renamed if necessary the target image file name. + + virtual QString oldFileName2NewFileName(QString fileName) + { return (fileName); }; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // BATCHPROCESSIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp b/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp new file mode 100644 index 0000000..caed54f --- /dev/null +++ b/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp @@ -0,0 +1,115 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qpainter.h> +#include <qlistview.h> + +// Include files for KDE + +#include <klocale.h> + +// Local includes + +#include "batchprocessimagesitem.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +BatchProcessImagesItem::BatchProcessImagesItem(QListView * parent, QString const & pathSrc, + QString const & nameSrc, QString const & nameDest, QString const & result) + : KListViewItem( parent, "", nameSrc, nameDest, result), + _pathSrc(pathSrc), _nameSrc(nameSrc), _nameDest(nameDest), _result(result), + _overwrote( false ), + _reverseSort( false ) +{ + setText(0, pathSrc.section('/', -2, -2)); +} + +BatchProcessImagesItem::~BatchProcessImagesItem() +{ +} + +QString BatchProcessImagesItem::pathSrc() { return _pathSrc; } +QString BatchProcessImagesItem::nameSrc() { return _nameSrc; } +QString BatchProcessImagesItem::nameDest() { return _nameDest; } +QString BatchProcessImagesItem::result() { return _result; } +QString BatchProcessImagesItem::error() { return _error; } +QString BatchProcessImagesItem::outputMess() { return _outputMess; } + +void BatchProcessImagesItem::changeResult(QString text) { setText(3, text); } +void BatchProcessImagesItem::changeError(QString text) { _error = text; } +void BatchProcessImagesItem::changeNameDest(QString text) { _nameDest = text; setText(2, _nameDest); } +void BatchProcessImagesItem::changeOutputMess(QString text) { _outputMess.append(text); } + +void BatchProcessImagesItem::paintCell (QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup _cg( cg ); + + if (text(3) != i18n("OK") && !text(3).isEmpty() ) + { + _cg.setColor( QColorGroup::Text, Qt::red ); + KListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + if (text(3) == i18n("OK") ) + { + _cg.setColor( QColorGroup::Text, Qt::darkGreen ); + KListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + + KListViewItem::paintCell( p, cg, column, width, alignment ); +} + +bool BatchProcessImagesItem::overWrote() +{ + return _overwrote; +} + +void BatchProcessImagesItem::setDidOverWrite( bool b ) +{ + _overwrote = b; +} + +void BatchProcessImagesItem::setKey(const QString& val, bool reverseSort) +{ + _key = val; + _reverseSort = reverseSort; +} + +QString BatchProcessImagesItem::key(int column, bool ) const +{ + if (_key.isNull()) + return text(column); + + return _key; +} + +int BatchProcessImagesItem::compare(QListViewItem * i, int col, bool ascending) const +{ + int weight = _reverseSort ? -1 : 1; + return weight * key(col, ascending).localeAwareCompare(i->key( col, ascending)); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesitem.h b/kipi-plugins/batchprocessimages/batchprocessimagesitem.h new file mode 100644 index 0000000..686ac89 --- /dev/null +++ b/kipi-plugins/batchprocessimages/batchprocessimagesitem.h @@ -0,0 +1,84 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef BATCHPROCESSIMAGESITEM_H +#define BATCHPROCESSIMAGESITEM_H + +// Include files for Qt + +#include <qstring.h> +#include <qobject.h> + +// Include files for KDE + +#include <klistview.h> + +class QPainter; +class QListView; + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem : public KListViewItem +{ +public: + + BatchProcessImagesItem(QListView * parent, QString const & pathSrc, QString const & nameSrc, + QString const & nameDest, QString const & result); + + ~BatchProcessImagesItem(); + + QString pathSrc(); + QString nameSrc(); + QString nameDest(); + QString result(); + QString error(); + QString outputMess(); + bool overWrote(); + void setDidOverWrite( bool b ); + + void changeResult(QString text); + void changeError(QString text); + void changeNameDest(QString text); + void changeOutputMess(QString text); + + void paintCell (QPainter *p, const QColorGroup &cg, int column, int width, int alignment); + + void setKey(const QString& val, bool reverseSort); + QString key(int column, bool ascending) const; + int compare (QListViewItem * i, int col, bool ascending) const; + +private: + QString _pathSrc; + QString _nameSrc; + QString _nameDest; + QString _result; + QString _error; + QString _outputMess; + bool _overwrote; + QString _key; + bool _reverseSort; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // BATCHPROCESSIMAGESITEM_H diff --git a/kipi-plugins/batchprocessimages/batchprocessimageslist.cpp b/kipi-plugins/batchprocessimages/batchprocessimageslist.cpp new file mode 100644 index 0000000..fd0e3fd --- /dev/null +++ b/kipi-plugins/batchprocessimages/batchprocessimageslist.cpp @@ -0,0 +1,113 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qevent.h> +#include <qdragobject.h> +#include <qstrlist.h> +#include <qfileinfo.h> +#include <qwhatsthis.h> +#include <qlistview.h> + +// Include files for KDE + +#include <klocale.h> + +// Local include files + +#include "batchprocessimageslist.h" +#include "batchprocessimageslist.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +BatchProcessImagesList::BatchProcessImagesList(QWidget *parent, const char *name) + : KListView(parent, name) +{ + setAcceptDrops(true); + setDropVisualizer(false); + addColumn(i18n("Source Album")); + addColumn(i18n("Source Image")); + addColumn(i18n("Target Image")); + addColumn(i18n("Result")); + setSorting(3); + setItemMargin(3); + setResizeMode(QListView::LastColumn); + setSelectionMode(QListView::Single); + setAllColumnsShowFocus ( true ); + QWhatsThis::add( this, i18n("<p>You can see here the operations' results " + "during the process. Double-click on an item for more " + "information once the process has ended. " + "<p>You can use the \"Add\" button or drag-and-drop " + "to add some new items to the list. " + "<p>If the items are taken from different Albums " + "the process' results will be merged to the target Album.") ); +} + +void BatchProcessImagesList::dragEnterEvent(QDragEnterEvent *e) +{ + e->accept(QUriDrag::canDecode(e)); +} + +bool BatchProcessImagesList::acceptDrag(QDropEvent* e) const +{ + return ( QUriDrag::canDecode(e) ); +} + +void BatchProcessImagesList::contentsDropEvent(QDropEvent* e) +{ + droppedImagesItems(e); +} + +void BatchProcessImagesList::dropEvent(QDropEvent *e) +{ + droppedImagesItems(e); +} + +void BatchProcessImagesList::droppedImagesItems(QDropEvent *e) +{ + QStrList strList; + QStringList FilesPath; + + if ( !QUriDrag::decode(e, strList) ) return; + + QStrList stringList; + QStrListIterator it(strList); + char *str; + + while ( (str = it.current()) != 0 ) + { + QString filePath = QUriDrag::uriToLocalFile(str); + QFileInfo fileInfo(filePath); + + if (fileInfo.isFile() && fileInfo.exists()) + FilesPath.append(fileInfo.filePath()); + + ++it; + } + + if (FilesPath.isEmpty() == false) + emit addedDropItems(FilesPath); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/batchprocessimageslist.h b/kipi-plugins/batchprocessimages/batchprocessimageslist.h new file mode 100644 index 0000000..4c078c6 --- /dev/null +++ b/kipi-plugins/batchprocessimages/batchprocessimageslist.h @@ -0,0 +1,57 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef BATCHPROCESSIMAGE_H +#define BATCHPROCESSIMAGE_H + +// Include files for Qt + +#include <qobject.h> + +// Include files for KDE + +#include <klistview.h> + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesList : public KListView +{ +Q_OBJECT + +public: + BatchProcessImagesList(QWidget *parent=0, const char *name=0); + +signals: + void addedDropItems(QStringList filesPath); + +protected: + void dragEnterEvent(QDragEnterEvent *e); + void dropEvent(QDropEvent* e); + bool acceptDrag(QDropEvent* e) const; + void contentsDropEvent(QDropEvent* e); + void droppedImagesItems(QDropEvent *e); +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif diff --git a/kipi-plugins/batchprocessimages/borderimagesdialog.cpp b/kipi-plugins/batchprocessimages/borderimagesdialog.cpp new file mode 100644 index 0000000..8ce5894 --- /dev/null +++ b/kipi-plugins/batchprocessimages/borderimagesdialog.cpp @@ -0,0 +1,338 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kcolorbutton.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes + +#include "pluginsversion.h" +#include "kpaboutdata.h" +#include "outputdialog.h" +#include "imagepreview.h" +#include "borderoptionsdialog.h" +#include "borderimagesdialog.h" +#include "borderimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +BorderImagesDialog::BorderImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch-Bordering Images"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch Image-bordering"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin for batch bordering images\n" + "This plugin use the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2008, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + m_nbItem = m_selectedImageFiles.count(); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Images Bordering Options") ); + + m_labelType->setText( i18n("Border:") ); + + m_Type->insertItem(i18n("Solid")); + + // Niepce is Real name. This is the first guy in the world to have build a camera. + m_Type->insertItem("Niepce"); + + m_Type->insertItem(i18n("Raise")); + m_Type->insertItem(i18n("Frame")); + m_Type->setCurrentText(i18n("Niepce")); + whatsThis = i18n("<p>Select here the border type for your images:<p>" + "<b>Solid</b>: just surround the images with a line.<p>" + "<b>Niepce</b>: surround the images with a fine line and a large border " + "(ideal for black and white pictures).<p>" + "<b>Raise</b>: creating a 3D effect around the images.<p>" + "<b>Frame</b>: surround the images with an ornamental border.<p>"); + + QWhatsThis::add( m_Type, whatsThis ); + + //--------------------------------------------- + + readSettings(); + listImageFiles(); +} + +BorderImagesDialog::~BorderImagesDialog() +{ + delete m_about; +} + +void BorderImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("borderimages", "kipi-plugins"); +} + +void BorderImagesDialog::slotOptionsClicked(void) +{ + int Type = m_Type->currentItem(); + BorderOptionsDialog *optionsDialog = new BorderOptionsDialog(this, Type); + + if ( Type == 0 ) // Solid + { + optionsDialog->m_solidBorderWidth->setValue(m_solidWidth); + optionsDialog->m_button_solidBorderColor->setColor(m_solidColor); + } + if ( Type == 1 ) // Niepce + { + optionsDialog->m_lineNiepceBorderWidth->setValue(m_lineNiepceWidth); + optionsDialog->m_button_lineNiepceBorderColor->setColor(m_lineNiepceColor); + optionsDialog->m_NiepceBorderWidth->setValue(m_NiepceWidth); + optionsDialog->m_button_NiepceBorderColor->setColor(m_NiepceColor); + } + if ( Type == 2 ) // Raise + { + optionsDialog->m_raiseBorderWidth->setValue(m_raiseWidth); + } + if ( Type == 3 ) // Frame + { + optionsDialog->m_frameBorderWidth->setValue(m_frameWidth); + optionsDialog->m_frameBevelBorderWidth->setValue(m_bevelWidth); + optionsDialog->m_button_frameBorderColor->setColor(m_frameColor); + } + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + if ( Type == 0 ) // Solid + { + m_solidWidth = optionsDialog->m_solidBorderWidth->value(); + m_solidColor = optionsDialog->m_button_solidBorderColor->color(); + } + if ( Type == 1 ) // Niepce + { + m_lineNiepceWidth = optionsDialog->m_lineNiepceBorderWidth->value(); + m_lineNiepceColor = optionsDialog->m_button_lineNiepceBorderColor->color(); + m_NiepceWidth = optionsDialog->m_NiepceBorderWidth->value(); + m_NiepceColor = optionsDialog->m_button_NiepceBorderColor->color(); + } + if ( Type == 2 ) // Raise + { + m_raiseWidth = optionsDialog->m_raiseBorderWidth->value(); + } + if ( Type == 3 ) // Frame + { + m_frameWidth = optionsDialog->m_frameBorderWidth->value(); + m_bevelWidth = optionsDialog->m_frameBevelBorderWidth->value(); + m_frameColor = optionsDialog->m_button_frameBorderColor->color(); + } + } + + delete optionsDialog; +} + +void BorderImagesDialog::readSettings(void) +{ + // Read all settings from configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("BorderImages Settings"); + + m_Type->setCurrentItem(m_config->readNumEntry("BorderType", 1)); // Niepce per default. + QColor *ColorBlack = new QColor( 0, 0, 0 ); + QColor *ColorWhite = new QColor( 255, 255, 255 ); + m_solidWidth = m_config->readNumEntry("SolidWidth", 25); + m_solidColor = m_config->readColorEntry("SolidColor", ColorBlack); + + m_lineNiepceWidth = m_config->readNumEntry("LineNiepceWidth", 10); + m_lineNiepceColor = m_config->readColorEntry("LineNiepceColor", ColorBlack); + m_NiepceWidth = m_config->readNumEntry("NiepceWidth", 100); + m_NiepceColor = m_config->readColorEntry("NiepceColor", ColorWhite); + + m_raiseWidth = m_config->readNumEntry("RaiseWidth", 50); + + m_frameWidth = m_config->readNumEntry("FrameWidth", 25); + m_bevelWidth = m_config->readNumEntry("BevelWidth", 10); + m_frameColor = m_config->readColorEntry("FrameColor", ColorBlack); + + if (m_config->readEntry("SmallPreview", "true") == "true") + m_smallPreview->setChecked( true ); + else + m_smallPreview->setChecked( false ); + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete ColorWhite; + delete ColorBlack; + delete m_config; +} + +void BorderImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("BorderImages Settings"); + m_config->writeEntry("BorderType", m_Type->currentItem()); + + m_config->writeEntry("SolidWidth", m_solidWidth); + m_config->writeEntry("SolidColor", m_solidColor); + + m_config->writeEntry("LineNiepceWidth", m_lineNiepceWidth); + m_config->writeEntry("LineNiepceColor", m_lineNiepceColor); + m_config->writeEntry("NiepceWidth", m_NiepceWidth); + m_config->writeEntry("NiepceColor", m_NiepceColor); + + m_config->writeEntry("RaiseWidth", m_raiseWidth); + + m_config->writeEntry("FrameWidth", m_frameWidth); + m_config->writeEntry("BevelWidth", m_bevelWidth); + m_config->writeEntry("FrameColor", m_frameColor); + + m_config->writeEntry("SmallPreview", m_smallPreview->isChecked()); + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + + m_config->sync(); + + delete m_config; +} + +QString BorderImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode) +{ + *proc << "convert"; + + if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled ! + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 "); + } + + if (m_Type->currentItem() == 0) // Solid + { + *proc << "-border"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_solidWidth ) + "x"; + Temp2.append(Temp.setNum( m_solidWidth )); + *proc << Temp2; + *proc << "-bordercolor"; + Temp2 = "rgb(" + Temp.setNum(m_solidColor.red()) + ","; + Temp2.append(Temp.setNum(m_solidColor.green()) + ","); + Temp2.append(Temp.setNum(m_solidColor.blue()) + ")"); + *proc << Temp2; + } + + if (m_Type->currentItem() == 1) // Niepce + { + QString Temp, Temp2; + + *proc << "-border"; + Temp2 = Temp.setNum( m_lineNiepceWidth ) + "x"; + Temp2.append(Temp.setNum( m_lineNiepceWidth )); + *proc << Temp2; + + *proc << "-bordercolor"; + Temp2 = "rgb(" + Temp.setNum(m_NiepceColor.red()) + ","; + Temp2.append(Temp.setNum(m_NiepceColor.green()) + ","); + Temp2.append(Temp.setNum(m_NiepceColor.blue()) + ")"); + *proc << Temp2; + + *proc << "-border"; + Temp2 = Temp.setNum( m_NiepceWidth ) + "x"; + Temp2.append(Temp.setNum( m_NiepceWidth )); + *proc << Temp2; + + *proc << "-bordercolor"; + Temp2 = "rgb(" + Temp.setNum(m_lineNiepceColor.red()) + ","; + Temp2.append(Temp.setNum(m_lineNiepceColor.green()) + ","); + Temp2.append(Temp.setNum(m_lineNiepceColor.blue()) + ")"); + *proc << Temp2; + } + + if (m_Type->currentItem() == 2) // Raise + { + *proc << "-raise"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_raiseWidth ) + "x"; + Temp2.append(Temp.setNum( m_raiseWidth )); + *proc << Temp2; + } + + if (m_Type->currentItem() == 3) // Frame + { + *proc << "-frame"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_frameWidth ) + "x"; + Temp2.append(Temp.setNum( m_frameWidth ) + "+"); + Temp2.append(Temp.setNum( m_bevelWidth ) + "+"); + Temp2.append(Temp.setNum( m_bevelWidth ) ); + *proc << Temp2; + *proc << "-mattecolor"; + Temp2 = "rgb(" + Temp.setNum(m_frameColor.red()) + ","; + Temp2.append(Temp.setNum(m_frameColor.green()) + ","); + Temp2.append(Temp.setNum(m_frameColor.blue()) + ")"); + *proc << Temp2; + } + + *proc << "-verbose"; + + *proc << item->pathSrc(); + + if ( !previewMode ) // No preview mode ! + *proc << albumDest + "/" + item->nameDest(); + + return(extractArguments(proc)); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/borderimagesdialog.h b/kipi-plugins/batchprocessimages/borderimagesdialog.h new file mode 100644 index 0000000..f0cd7aa --- /dev/null +++ b/kipi-plugins/batchprocessimages/borderimagesdialog.h @@ -0,0 +1,80 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef BORDERIMAGESDIALOG_H +#define BORDERIMAGESDIALOG_H + +// Local includes + +#include "batchprocessimagesdialog.h" +#include "kpaboutdata.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class BorderImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + BorderImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~BorderImagesDialog(); + + private slots: + + void slotHelp(void); + void slotOptionsClicked(void); + + protected: + + int m_solidWidth; + QColor m_solidColor; + + int m_lineNiepceWidth; + QColor m_lineNiepceColor; + int m_NiepceWidth; + QColor m_NiepceColor; + + int m_raiseWidth; + + int m_frameWidth; + int m_bevelWidth; + QColor m_frameColor; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void readSettings(void); + void saveSettings(void); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // BORDERIMAGESDIALOG_H + diff --git a/kipi-plugins/batchprocessimages/borderoptionsdialog.cpp b/kipi-plugins/batchprocessimages/borderoptionsdialog.cpp new file mode 100644 index 0000000..bc69173 --- /dev/null +++ b/kipi-plugins/batchprocessimages/borderoptionsdialog.cpp @@ -0,0 +1,160 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qstring.h> +#include <qcombobox.h> +#include <qcolor.h> + +// Include files for KDE + +#include <klocale.h> +#include <knuminput.h> +#include <kcolorbutton.h> + +// Local includes + +#include "borderoptionsdialog.h" +#include "borderoptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +BorderOptionsDialog::BorderOptionsDialog(QWidget *parent, int BorderType) + : KDialogBase( parent, "BorderOptionsDialog", true, + i18n("Border Options"), Ok|Cancel, Ok, false) +{ + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + if (BorderType == 0) // Solid + { + QLabel *m_label_solidBorderWidth = new QLabel (i18n("Border width:"), box); + dvlay->addWidget( m_label_solidBorderWidth ); + m_solidBorderWidth = new KIntNumInput(25, box); + m_solidBorderWidth->setRange(1, 1000, 1, true ); + QWhatsThis::add( m_solidBorderWidth, i18n("<p>Select here the border width in pixels.") ); + m_label_solidBorderWidth->setBuddy( m_solidBorderWidth ); + dvlay->addWidget( m_solidBorderWidth ); + + QLabel *m_label_solidColor = new QLabel(i18n("Border color:"), box); + dvlay->addWidget( m_label_solidColor ); + QColor solidBorderColor = QColor( 0, 0, 0 ); // Black per default. + m_button_solidBorderColor = new KColorButton( solidBorderColor, box ); + QWhatsThis::add( m_button_solidBorderColor, i18n( "<p>You can select here the border color." )); + dvlay->addWidget( m_button_solidBorderColor ); + } + + if (BorderType == 1) // Niepce + { + QLabel *m_label_lineNiepceBorderWidth = new QLabel (i18n("Line border width:"), box); + dvlay->addWidget( m_label_lineNiepceBorderWidth ); + m_lineNiepceBorderWidth = new KIntNumInput(10, box); + m_lineNiepceBorderWidth->setRange(1, 500, 1, true ); + QWhatsThis::add( m_lineNiepceBorderWidth, i18n("<p>Select here the line border width in pixels.") ); + m_label_lineNiepceBorderWidth->setBuddy( m_lineNiepceBorderWidth ); + dvlay->addWidget( m_lineNiepceBorderWidth ); + + QLabel *m_label_lineNiepceColor = new QLabel(i18n("Line border color:"), box); + dvlay->addWidget( m_label_lineNiepceColor ); + QColor lineNiepceBorderColor = QColor( 0, 0, 0 ); // Black per default. + m_button_lineNiepceBorderColor = new KColorButton( lineNiepceBorderColor, box ); + QWhatsThis::add( m_button_lineNiepceBorderColor, i18n( "<p>You can select here the line border color." )); + dvlay->addWidget( m_button_lineNiepceBorderColor ); + + QLabel *m_label_NiepceBorderWidth = new QLabel (i18n("Border width:"), box); + dvlay->addWidget( m_label_NiepceBorderWidth ); + m_NiepceBorderWidth = new KIntNumInput(100, box); + m_NiepceBorderWidth->setRange(1, 500, 1, true ); + QWhatsThis::add( m_NiepceBorderWidth, i18n("<p>Select here the border width in pixels.") ); + m_label_NiepceBorderWidth->setBuddy( m_NiepceBorderWidth ); + dvlay->addWidget( m_NiepceBorderWidth ); + + QLabel *m_label_NiepceColor = new QLabel(i18n("Border color:"), box); + dvlay->addWidget( m_label_NiepceColor ); + QColor NiepceBorderColor = QColor( 255, 255, 255 ); // White per default. + m_button_NiepceBorderColor = new KColorButton( NiepceBorderColor, box ); + QWhatsThis::add( m_button_NiepceBorderColor, i18n( "<p>You can select here the border color." )); + dvlay->addWidget( m_button_NiepceBorderColor ); + } + + if (BorderType == 2) // Raise + { + QLabel *m_label_raiseBorderWidth = new QLabel (i18n("Border width:"), box); + dvlay->addWidget( m_label_raiseBorderWidth ); + m_raiseBorderWidth = new KIntNumInput(50, box); + m_raiseBorderWidth->setRange(1, 500, 1, true ); + QWhatsThis::add( m_raiseBorderWidth, i18n("<p>Select here the border width in pixels.") ); + m_label_raiseBorderWidth->setBuddy( m_raiseBorderWidth ); + dvlay->addWidget( m_raiseBorderWidth ); + } + + if (BorderType == 3) // Frame + { + QLabel *m_label_frameBorderWidth = new QLabel (i18n("Border width:"), box); + dvlay->addWidget( m_label_frameBorderWidth ); + m_frameBorderWidth = new KIntNumInput(25, box); + m_frameBorderWidth->setRange(0, 500, 1, true ); + QWhatsThis::add( m_frameBorderWidth, i18n("<p>Select here the border width in pixels.") ); + m_label_frameBorderWidth->setBuddy( m_frameBorderWidth ); + dvlay->addWidget( m_frameBorderWidth ); + + QLabel *m_label_frameBevelBorderWidth = new QLabel (i18n("Bevel width:"), box); + dvlay->addWidget( m_label_frameBevelBorderWidth ); + m_frameBevelBorderWidth = new KIntNumInput(10, box); + m_frameBevelBorderWidth->setRange(0, 250, 1, true ); + QWhatsThis::add( m_frameBevelBorderWidth, i18n("<p>Select here the bevel width in pixels. " + "This value must be <= Border width / 2") ); + m_label_frameBevelBorderWidth->setBuddy( m_frameBevelBorderWidth ); + dvlay->addWidget( m_frameBevelBorderWidth ); + + QLabel *m_label_frameColor = new QLabel(i18n("Border color:"), box); + dvlay->addWidget( m_label_frameColor ); + QColor frameBorderColor = QColor( 0, 0, 0 ); // Black per default. + m_button_frameBorderColor = new KColorButton( frameBorderColor, box ); + QWhatsThis::add( m_button_frameBorderColor, i18n( "<p>You can select here the border color." )); + dvlay->addWidget( m_button_frameBorderColor ); + + connect(m_frameBorderWidth, SIGNAL(valueChanged(int)), this, SLOT(slotFrameBorderWidthChanged(int))); + } +} + +BorderOptionsDialog::~BorderOptionsDialog() +{ +} + +void BorderOptionsDialog::slotFrameBorderWidthChanged (int value) +{ + m_frameBevelBorderWidth->setMaxValue((int)(value / 2)); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/borderoptionsdialog.h b/kipi-plugins/batchprocessimages/borderoptionsdialog.h new file mode 100644 index 0000000..3f2f514 --- /dev/null +++ b/kipi-plugins/batchprocessimages/borderoptionsdialog.h @@ -0,0 +1,64 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef BORDEROPTIONSDIALOG_H +#define BORDEROPTIONSDIALOG_H + +// Include files for KDE + +#include <kdialogbase.h> + +class KIntNumInput; +class KColorButton; + +namespace KIPIBatchProcessImagesPlugin +{ + +class BorderOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + BorderOptionsDialog(QWidget *parent=0, int BorderType = 0); + ~BorderOptionsDialog(); + + KIntNumInput *m_solidBorderWidth; + KColorButton *m_button_solidBorderColor; + + KIntNumInput *m_lineNiepceBorderWidth; + KColorButton *m_button_lineNiepceBorderColor; + KIntNumInput *m_NiepceBorderWidth; + KColorButton *m_button_NiepceBorderColor; + + KIntNumInput *m_raiseBorderWidth; + + KIntNumInput *m_frameBorderWidth; + KIntNumInput *m_frameBevelBorderWidth; + KColorButton *m_button_frameBorderColor; + + private slots: + void slotFrameBorderWidthChanged (int value); +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // BORDEROPTIONSDIALOG_H diff --git a/kipi-plugins/batchprocessimages/colorimagesdialog.cpp b/kipi-plugins/batchprocessimages/colorimagesdialog.cpp new file mode 100644 index 0000000..33be98e --- /dev/null +++ b/kipi-plugins/batchprocessimages/colorimagesdialog.cpp @@ -0,0 +1,325 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes + +#include "pluginsversion.h" +#include "kpaboutdata.h" +#include "coloroptionsdialog.h" +#include "outputdialog.h" +#include "imagepreview.h" +#include "colorimagesdialog.h" +#include "colorimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +ColorImagesDialog::ColorImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch Image-Color Processing"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch image-color enhancement"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin for batch image-color enhancement\n" + "This plugin use the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + m_nbItem = m_selectedImageFiles.count(); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Image Coloring Options") ); + + m_labelType->setText( i18n("Filter:") ); + + m_Type->insertItem(i18n("Decrease Contrast")); + m_Type->insertItem(i18n("Depth")); // 1 + m_Type->insertItem(i18n("Equalize")); + m_Type->insertItem(i18n("Fuzz")); // 3 + m_Type->insertItem(i18n("Gray Scales")); + m_Type->insertItem(i18n("Increase Contrast")); + m_Type->insertItem(i18n("Monochrome")); + m_Type->insertItem(i18n("Negate")); + m_Type->insertItem(i18n("Normalize")); + m_Type->insertItem(i18n("Segment")); // 9 + m_Type->insertItem(i18n("Trim")); + m_Type->setCurrentText(i18n("Normalize")); + whatsThis = i18n("<p>Select here the color enhancement type for your images:<p>" + "<b>Decrease contrast</b>: reduce the image contrast. The algorithm " + "reduces the intensity difference between the lighter and darker elements " + "of the image.<p>" + "<b>Depth</b>: change the color depth of the image.<p>" + "<b>Equalize</b>: perform histogram equalization to the image.<p>" + "<b>Fuzz</b>: merging colors within a distance, i.e. consider them to be equal.<p>" + "<b>Gray scales</b>: convert color images to grayscale images.<p>" + "<b>Increase contrast</b>: enhance the image contrast. The algorithm enhances " + "the intensity differences between the lighter and darker elements of the image.<p>" + "<b>Monochrome</b>: transform the image to black and white.<p>" + "<b>Negate</b>: replace every pixel with its complementary color. The red, green, " + "and blue intensities of an image are negated. White becomes black, yellow becomes " + "blue, etc.<p>" + "<b>Normalize</b>: transform image to span the full range of color values. " + "This is a contrast enhancement technique. The algorithm enhances the contrast " + "of a colored image by adjusting the pixels color to span the entire range of " + "colors available.<p>" + "<b>Segment</b>: segment an image by analyzing the histograms of the color " + "components and identifying units that are homogeneous with the fuzzy c-means " + "technique.<p>" + "<b>Trim</b>: trim an image (fuzz reverse technic). The algorithm remove edges " + "that are the background color from the image.<p>"); + + QWhatsThis::add( m_Type, whatsThis ); + + //--------------------------------------------- + + readSettings(); + listImageFiles(); + slotTypeChanged(m_Type->currentItem()); +} + +ColorImagesDialog::~ColorImagesDialog() +{ + delete m_about; +} + +void ColorImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("colorimages", + "kipi-plugins"); +} + +void ColorImagesDialog::slotTypeChanged(int type) +{ + if ( type == 1 || // Depth + type == 3 || // Fuzz + type == 9 // Segment + ) + m_optionsButton->setEnabled(true); + else + m_optionsButton->setEnabled(false); +} + +void ColorImagesDialog::slotOptionsClicked(void) +{ + int Type = m_Type->currentItem(); + ColorOptionsDialog *optionsDialog = new ColorOptionsDialog(this, Type); + + if ( Type == 1) // Depth + optionsDialog->m_depthValue->setCurrentText(m_depthValue); + + if ( Type == 3) // Fuzz + optionsDialog->m_fuzzDistance->setValue(m_fuzzDistance); + + if ( Type == 9) // Segment + { + optionsDialog->m_segmentCluster->setValue(m_segmentCluster); + optionsDialog->m_segmentSmooth->setValue(m_segmentSmooth); + } + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + if ( Type == 1) // Depth + m_depthValue = optionsDialog->m_depthValue->currentText(); + + if ( Type == 3) // Fuzz + m_fuzzDistance = optionsDialog->m_fuzzDistance->value(); + + if ( Type == 9) // Segment + { + m_segmentCluster = optionsDialog->m_segmentCluster->value(); + m_segmentSmooth = optionsDialog->m_segmentSmooth->value(); + } + } + + delete optionsDialog; +} + +void ColorImagesDialog::readSettings(void) +{ + // Read all settings from configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("ColorImages Settings"); + + m_Type->setCurrentItem(m_config->readNumEntry("ColorType", 8)); // Normalize per default. + m_depthValue = m_config->readEntry("DepthValue", "32"); + m_fuzzDistance = m_config->readNumEntry("FuzzDistance", 3); + m_segmentCluster = m_config->readNumEntry("SegmentCluster", 3); + m_segmentSmooth = m_config->readNumEntry("SegmentSmooth", 3); + + if (m_config->readEntry("SmallPreview", "true") == "true") + m_smallPreview->setChecked( true ); + else + m_smallPreview->setChecked( false ); + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete m_config; +} + +void ColorImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("ColorImages Settings"); + + m_config->writeEntry("ColorType", m_Type->currentItem()); + m_config->writeEntry("DepthValue", m_depthValue); + m_config->writeEntry("FuzzDistance", m_fuzzDistance); + m_config->writeEntry("SegmentCluster", m_segmentCluster); + m_config->writeEntry("SegmentSmooth", m_segmentSmooth); + + m_config->writeEntry("SmallPreview", m_smallPreview->isChecked()); + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + + m_config->sync(); + + delete m_config; +} + +QString ColorImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode) +{ + *proc << "convert"; + + if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled ! + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 "); + } + + if (m_Type->currentItem() == 0) // Decrease contrast" + { + *proc << "-contrast"; + } + + if (m_Type->currentItem() == 1) // Depth + { + *proc << "-depth" << m_depthValue; + } + + if (m_Type->currentItem() == 2) // Equalize + { + *proc << "-equalize"; + } + + if (m_Type->currentItem() == 3) // Fuzz + { + QString Temp, Temp2; + Temp2 = Temp.setNum( m_fuzzDistance ); + *proc << "-fuzz" << Temp2; + } + + if (m_Type->currentItem() == 4) // Gray scales + { + *proc << "-type"; + *proc << "Grayscale"; + } + + if (m_Type->currentItem() == 5) // Increase contrast + { + *proc << "+contrast"; + } + + if (m_Type->currentItem() == 6) // Monochrome + { + *proc << "-monochrome"; + } + + if (m_Type->currentItem() == 7) // Negate + { + *proc << "-negate"; + } + + if (m_Type->currentItem() == 8) // Normalize + { + *proc << "-normalize"; + } + + if (m_Type->currentItem() == 9) // Segment + { + *proc << "-segment"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_segmentCluster ) + "x"; + Temp2.append (Temp.setNum( m_segmentSmooth )); + *proc << Temp2; + } + + if (m_Type->currentItem() == 10) // Trim + { + *proc << "-trim"; + } + + *proc << "-verbose"; + + *proc << item->pathSrc(); + + if ( !previewMode ) // No preview mode ! + { + *proc << albumDest + "/" + item->nameDest(); + } + + return(extractArguments(proc)); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/colorimagesdialog.h b/kipi-plugins/batchprocessimages/colorimagesdialog.h new file mode 100644 index 0000000..2feeb4c --- /dev/null +++ b/kipi-plugins/batchprocessimages/colorimagesdialog.h @@ -0,0 +1,72 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + + +#ifndef COLORIMAGESDIALOG_H +#define COLORIMAGESDIALOG_H + +// Local includes + +#include "kpaboutdata.h" +#include "batchprocessimagesdialog.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class ColorImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + ColorImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~ColorImagesDialog(); + + private slots: + + void slotHelp(void); + void slotOptionsClicked(void); + void slotTypeChanged(int type); + + protected: + + QString m_depthValue; + int m_fuzzDistance; + int m_segmentCluster; + int m_segmentSmooth; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void readSettings(void); + void saveSettings(void); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // COLORIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/coloroptionsdialog.cpp b/kipi-plugins/batchprocessimages/coloroptionsdialog.cpp new file mode 100644 index 0000000..bd08870 --- /dev/null +++ b/kipi-plugins/batchprocessimages/coloroptionsdialog.cpp @@ -0,0 +1,112 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qcombobox.h> +#include <qcolor.h> + +// Include files for KDE + +#include <kdialogbase.h> +#include <klocale.h> +#include <knuminput.h> +#include <kcolorbutton.h> + +// Local includes + +#include "coloroptionsdialog.h" +#include "coloroptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +ColorOptionsDialog::ColorOptionsDialog(QWidget *parent, int ColorType) + : KDialogBase( parent, "ColorOptionsDialog", true, + i18n("Color Options"), Ok|Cancel, Ok, false) +{ + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + if (ColorType == 1) // Depth + { + QLabel *m_label_depthValue = new QLabel (i18n("Depth value:"), box); + dvlay->addWidget( m_label_depthValue ); + m_depthValue = new QComboBox( false, box ); + m_depthValue->insertItem("8"); + m_depthValue->insertItem("16"); + m_depthValue->insertItem("32"); + QWhatsThis::add( m_depthValue, i18n("<p>Select here the image depth in bits.") ); + m_label_depthValue->setBuddy( m_depthValue ); + dvlay->addWidget( m_depthValue ); + } + + if (ColorType == 3) // Fuzz + { + QLabel *m_label_fuzzDistance = new QLabel (i18n("Distance:"), box); + dvlay->addWidget( m_label_fuzzDistance ); + m_fuzzDistance = new KIntNumInput(3, box); + m_fuzzDistance->setRange(0, 20, 1, true ); + QWhatsThis::add( m_fuzzDistance, i18n("<p>Select here the fuzz distance in " + "absolute intensity units.") ); + m_label_fuzzDistance->setBuddy( m_fuzzDistance ); + dvlay->addWidget( m_fuzzDistance ); + } + + if (ColorType == 9) // Segment + { + QLabel *m_label_segmentCluster = new QLabel (i18n("Cluster threshold:"), box); + dvlay->addWidget( m_label_segmentCluster ); + m_segmentCluster = new KIntNumInput(3, box); + m_segmentCluster->setRange(0, 20, 1, true ); + QWhatsThis::add( m_segmentCluster, i18n("<p>Select here the value which represents the minimum " + "number of pixels contained in a hexahedra before it can " + "be considered valid.") ); + m_label_segmentCluster->setBuddy( m_segmentCluster ); + dvlay->addWidget( m_segmentCluster ); + + QLabel *m_label_segmentSmooth = new QLabel (i18n("Smooth threshold:"), box); + dvlay->addWidget( m_label_segmentSmooth ); + m_segmentSmooth = new KIntNumInput(3, box); + m_segmentSmooth->setRange(0, 20, 1, true ); + QWhatsThis::add( m_segmentSmooth, i18n("<p>Select here the value which eliminates noise in the " + "second derivative of the histogram. As the value is increased, " + "you can expect a smoother second derivative.") ); + m_label_segmentSmooth->setBuddy( m_segmentSmooth ); + dvlay->addWidget( m_segmentSmooth ); + } +} + +ColorOptionsDialog::~ColorOptionsDialog() +{ +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/coloroptionsdialog.h b/kipi-plugins/batchprocessimages/coloroptionsdialog.h new file mode 100644 index 0000000..7445d7f --- /dev/null +++ b/kipi-plugins/batchprocessimages/coloroptionsdialog.h @@ -0,0 +1,59 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef COLOROPTIONSDIALOG_H +#define COLOROPTIONSDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +class QComboBox; + +class KIntNumInput; + +namespace KIPIBatchProcessImagesPlugin +{ + +class ColorOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + ColorOptionsDialog(QWidget *parent=0, int ColorType = 0); + ~ColorOptionsDialog(); + + QComboBox *m_depthValue; + + KIntNumInput *m_fuzzDistance; + + KIntNumInput *m_segmentCluster; + KIntNumInput *m_segmentSmooth; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // COLOROPTIONSDIALOG_H diff --git a/kipi-plugins/batchprocessimages/convertimagesdialog.cpp b/kipi-plugins/batchprocessimages/convertimagesdialog.cpp new file mode 100644 index 0000000..6947f2f --- /dev/null +++ b/kipi-plugins/batchprocessimages/convertimagesdialog.cpp @@ -0,0 +1,376 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qfileinfo.h> +#include <qdir.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <kurlrequester.h> + +// LibKExiv2 includes. + +#include <libkexiv2/kexiv2.h> + +// Local includes + +#include "pluginsversion.h" +#include "kpaboutdata.h" +#include "convertoptionsdialog.h" +#include "outputdialog.h" +#include "convertimagesdialog.h" +#include "convertimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +ConvertImagesDialog::ConvertImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch Convert Images"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch convert images"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin for batch converting images\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Image Conversion Options") ); + + m_labelType->setText( i18n("Format:") ); + + m_Type->insertItem("JPEG"); + m_Type->insertItem("PNG"); + m_Type->insertItem("TIFF"); + m_Type->insertItem("PPM"); + m_Type->insertItem("BMP"); + m_Type->insertItem("TGA"); + m_Type->insertItem("EPS"); + m_Type->setCurrentText("JPEG"); + whatsThis = i18n("<p>Select here the target image file format.<p>"); + whatsThis = whatsThis + i18n("<b>JPEG</b>: The Joint Photographic Experts Group's file format is a " + "good Web file format but it uses lossy data compression.<p>" + "<b>PNG</b>: the Portable Network Graphics format is an extensible file " + "format for the lossless, portable, well-compressed storage of raster images. " + "PNG provides a patent-free replacement for GIF and can also replace many common " + "uses of TIFF. PNG is designed to work well in online viewing applications, such " + "as the World Wide Web, so it is fully streamable with a progressive display " + "option. Also, PNG can store gamma and chromaticity data for improved color " + "matching on heterogeneous platforms."); + whatsThis = whatsThis + i18n("<p><b>TIFF</b>: the Tag Image File Format is a rather old standard that is " + "still very popular today. It is a highly flexible and platform-independent " + "format which is supported by numerous image processing applications and " + "virtually all prepress software on the market."); + whatsThis = whatsThis + i18n("<p><b>PPM</b>: the Portable Pixel Map file format is used as an " + "intermediate format for storing color bitmap information. PPM files " + "may be either binary or ASCII and store pixel values up to 24 bits in size. " + "This format generate the largest-sized text files to encode images without " + "losing quality"); + whatsThis = whatsThis + i18n("<p><b>BMP</b>: the BitMaP file format is a popular image format from Win32 " + "environment. It efficiently stores mapped or unmapped RGB graphics data with " + "pixels 1-, 4-, 8-, or 24-bits in size. Data may be stored raw or compressed " + "using a 4-bit or 8-bit RLE data compression algorithm. BMP is an excellent " + "choice for a simple bitmap format which supports a wide range of RGB image " + "data."); + whatsThis = whatsThis + i18n("<p><b>TGA</b>: the TarGA image file format is one of the most widely used " + "bitmap file formats for storage of 24 and 32 bits truecolor images. " + "TGA supports colormaps, alpha channel, gamma value, postage stamp image, " + "textual information, and developer-definable data."); + whatsThis = whatsThis + i18n("<p><b>EPS</b>: the Adobe Encapsulated PostScript image file format " + "is a PostScript language program describing the appearance of a single page. " + "Usually, the purpose of the EPS file is to be embedded inside another PostScript " + "language page description."); + + QWhatsThis::add( m_Type, whatsThis ); + + m_previewButton->hide(); + m_smallPreview->hide(); + + //--------------------------------------------- + + readSettings(); + slotTypeChanged(m_Type->currentItem()); +} + +ConvertImagesDialog::~ConvertImagesDialog() +{ + delete m_about; +} + +void ConvertImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("convertimages", "kipi-plugins"); +} + +void ConvertImagesDialog::slotTypeChanged(int type) +{ + if ( type == 3 || type == 4 || type == 6 ) // PPM || BMP || EPS + m_optionsButton->setEnabled(false); + else + m_optionsButton->setEnabled(true); + + m_listFiles->clear(); + listImageFiles(); +} + +void ConvertImagesDialog::slotOptionsClicked(void) +{ + int Type = m_Type->currentItem(); + ConvertOptionsDialog *optionsDialog = new ConvertOptionsDialog(this, Type); + + if (Type == 0) // JPEG + { + optionsDialog->m_JPEGPNGCompression->setValue(m_JPEGPNGCompression); + optionsDialog->m_compressLossLess->setChecked(m_compressLossLess); + } + if (Type == 1) // PNG + optionsDialog->m_JPEGPNGCompression->setValue(m_JPEGPNGCompression); + if (Type == 2) // TIFF + optionsDialog->m_TIFFCompressionAlgo->setCurrentText(m_TIFFCompressionAlgo); + if (Type == 5) // TGA + optionsDialog->m_TGACompressionAlgo->setCurrentText(m_TGACompressionAlgo); + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + if (Type == 0) // JPEG + { + m_JPEGPNGCompression = optionsDialog->m_JPEGPNGCompression->value(); + m_compressLossLess = optionsDialog->m_compressLossLess->isChecked(); + } + if (Type == 1) // PNG + m_JPEGPNGCompression = optionsDialog->m_JPEGPNGCompression->value(); + if (Type == 2) // TIFF + m_TIFFCompressionAlgo = optionsDialog->m_TIFFCompressionAlgo->currentText(); + if (Type == 5) // TGA + m_TGACompressionAlgo = optionsDialog->m_TGACompressionAlgo->currentText(); + } + + delete optionsDialog; +} + +void ConvertImagesDialog::readSettings(void) +{ + // Read all settings from configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("ConvertImages Settings"); + + m_Type->setCurrentItem(m_config->readNumEntry("ImagesFormat", 0)); // JPEG per default + if ( m_config->readEntry("CompressLossLess", "false") == "true") + m_compressLossLess = true; + else + m_compressLossLess = false; + + m_JPEGPNGCompression = m_config->readNumEntry("JPEGPNGCompression", 75); + m_TIFFCompressionAlgo = m_config->readEntry("TIFFCompressionAlgo", i18n("None")); + m_TGACompressionAlgo = m_config->readEntry("TGACompressionAlgo", i18n("None")); + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete m_config; +} + +void ConvertImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("ConvertImages Settings"); + + m_config->writeEntry("ImagesFormat", m_Type->currentItem()); + m_config->writeEntry("JPEGPNGCompression", m_JPEGPNGCompression); + m_config->writeEntry("CompressLossLess", m_compressLossLess); + m_config->writeEntry("TIFFCompressionAlgo", m_TIFFCompressionAlgo); + m_config->writeEntry("TGACompressionAlgo", m_TGACompressionAlgo); + + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + m_config->sync(); + + delete m_config; +} + +QString ConvertImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode) +{ + *proc << "convert"; + + if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled ! + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 "); + } + + if (m_Type->currentItem() == 0) // JPEG + { + if (m_compressLossLess == true) + { + *proc << "-compress" << "Lossless"; + } + else + { + *proc << "-quality"; + QString Temp; + *proc << Temp.setNum( m_JPEGPNGCompression ); + } + } + + if (m_Type->currentItem() == 1) // PNG + { + *proc << "-quality"; + QString Temp; + *proc << Temp.setNum( m_JPEGPNGCompression ); + } + + if (m_Type->currentItem() == 2) // TIFF + { + *proc << "-compress"; + + if (m_TIFFCompressionAlgo == i18n("None")) + { + *proc << "None"; + } + else + { + *proc << m_TIFFCompressionAlgo; + } + } + + if (m_Type->currentItem() == 5) // TGA + { + *proc << "-compress"; + + if (m_TGACompressionAlgo == i18n("None")) + { + *proc << "None"; + } + else + { + *proc << m_TGACompressionAlgo; + } + } + + *proc << "-verbose"; + + *proc << item->pathSrc() + "[0]"; + + if ( !previewMode ) // No preview mode ! + { + *proc << albumDest + "/" + item->nameDest(); + } + + return(extractArguments(proc)); +} + +void ConvertImagesDialog::processDone() +{ + if (m_Type->currentItem() == 0) + { + // JPEG file, we remove IPTC preview. + + BatchProcessImagesItem *item = dynamic_cast<BatchProcessImagesItem*>( + m_listFile2Process_iterator->current() ); + if (item) + { + QString src = item->pathSrc(); + QString tgt = m_destinationURL->url() + "/" + item->nameDest(); + QFileInfo fi(tgt); + + kdDebug() << src << endl; + kdDebug() << tgt << fi.size()<< endl; + + KExiv2Iface::KExiv2 metaSrc(src); + + // Update Iptc preview. + // NOTE: see B.K.O #130525. a JPEG segment is limited to 64K. If the IPTC byte array is + // bigger than 64K duing of image preview tag size, the target JPEG image will be + // broken. Note that IPTC image preview tag is limited to 256K!!! + // There is no limitation with TIFF and PNG about IPTC byte array size. + + metaSrc.removeIptcTag("Iptc.Application2.Preview"); + metaSrc.removeIptcTag("Iptc.Application2.PreviewFormat"); + metaSrc.removeIptcTag("Iptc.Application2.PreviewVersion"); + + KExiv2Iface::KExiv2 metaTgt(tgt); + metaTgt.setIptc(metaSrc.getIptc()); + metaTgt.applyChanges(); + } + } + + BatchProcessImagesDialog::processDone(); +} + +QString ConvertImagesDialog::oldFileName2NewFileName(QString fileName) +{ + QString Temp; + + Temp = fileName.left( fileName.findRev('.', -1) ); // The source file name without extension. + Temp = Temp + "." + ImageFileExt(m_Type->currentText()); // Added new file extension. + + return Temp; +} + +QString ConvertImagesDialog::ImageFileExt(QString Ext) +{ + if ( Ext == "TIFF" || Ext == "tiff" ) + return ("tif"); + else if ( Ext == "JPEG" || Ext == "jpeg" || Ext == "JPE" || Ext == "jpe" ) + return ("jpg"); + else + return (Ext.lower()); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/convertimagesdialog.h b/kipi-plugins/batchprocessimages/convertimagesdialog.h new file mode 100644 index 0000000..cc96fd8 --- /dev/null +++ b/kipi-plugins/batchprocessimages/convertimagesdialog.h @@ -0,0 +1,77 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef CONVERTIMAGESDIALOG_H +#define CONVERTIMAGESDIALOG_H + +// Local includes + +#include "kpaboutdata.h" +#include "batchprocessimagesdialog.h" + + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class ConvertImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + ConvertImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~ConvertImagesDialog(); + + private slots: + + void slotHelp(void); + void slotOptionsClicked(void); + void slotTypeChanged(int type); + + protected: + + int m_JPEGPNGCompression; + bool m_compressLossLess; + QString m_TIFFCompressionAlgo; + QString m_TGACompressionAlgo; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void processDone(); + + void readSettings(void); + void saveSettings(void); + + QString oldFileName2NewFileName(QString fileName); + QString ImageFileExt(QString Ext); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // CONVERTIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/convertoptionsdialog.cpp b/kipi-plugins/batchprocessimages/convertoptionsdialog.cpp new file mode 100644 index 0000000..46ece4b --- /dev/null +++ b/kipi-plugins/batchprocessimages/convertoptionsdialog.cpp @@ -0,0 +1,121 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qcombobox.h> +#include <qcheckbox.h> + +// Include files for KDE + +#include <klocale.h> +#include <knuminput.h> + +// Local includes + +#include "convertoptionsdialog.h" +#include "convertoptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +ConvertOptionsDialog::ConvertOptionsDialog(QWidget *parent, int ImageFormatType) + : KDialogBase( parent, "ConvertOptionsDialog", true, + i18n("Image File Format Options"), Ok|Cancel, Ok, false) +{ + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + if (ImageFormatType == 0 || ImageFormatType == 1) // JPEG || PNG + { + m_label_imageCompression = new QLabel (i18n("Image compression level:"), box); + dvlay->addWidget( m_label_imageCompression ); + m_JPEGPNGCompression = new KIntNumInput(75, box); + m_JPEGPNGCompression->setRange(1, 100, 1, true ); + whatsThis = i18n("<p>The compression value for the target images:<p>"); + whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>" + "<b>25</b>: high compression<p>" + "<b>50</b>: medium compression<p>" + "<b>75</b>: low compression (default value)<p>" + "<b>100</b>: no compression"); + + QWhatsThis::add( m_JPEGPNGCompression, whatsThis); + m_label_imageCompression->setBuddy( m_JPEGPNGCompression ); + dvlay->addWidget( m_JPEGPNGCompression ); + + if (ImageFormatType == 0) // JPEG + { + m_compressLossLess = new QCheckBox( i18n("Use lossless compression"), box); + QWhatsThis::add( m_compressLossLess, i18n("<p>If this option is enabled, " + "all JPEG operations will use a lossless compression.")); + dvlay->addWidget( m_compressLossLess ); + + connect(m_compressLossLess, SIGNAL( toggled(bool) ), this, SLOT( slotCompressLossLessEnabled(bool) ) ); + } + } + + if (ImageFormatType == 2) // TIFF + { + QLabel *m_label_imageCompression = new QLabel (i18n("Image compression algorithm:"), box); + dvlay->addWidget( m_label_imageCompression ); + m_TIFFCompressionAlgo = new QComboBox( false, box ); + m_TIFFCompressionAlgo->insertItem("LZW"); + m_TIFFCompressionAlgo->insertItem("JPEG"); + m_TIFFCompressionAlgo->insertItem(i18n("None")); + QWhatsThis::add( m_TIFFCompressionAlgo, i18n("<p>Select here the compression algorithm.") ); + m_label_imageCompression->setBuddy( m_TIFFCompressionAlgo ); + dvlay->addWidget( m_TIFFCompressionAlgo ); + } + + if (ImageFormatType == 5) // TGA + { + QLabel *m_label_imageCompression = new QLabel (i18n("Image compression algorithm:"), box); + dvlay->addWidget( m_label_imageCompression ); + m_TGACompressionAlgo = new QComboBox( false, box ); + m_TGACompressionAlgo->insertItem("RLE"); + m_TGACompressionAlgo->insertItem(i18n("None")); + QWhatsThis::add( m_TGACompressionAlgo, i18n("<p>Select here the compression algorithm.") ); + m_label_imageCompression->setBuddy( m_TGACompressionAlgo ); + dvlay->addWidget( m_TGACompressionAlgo ); + } +} + +ConvertOptionsDialog::~ConvertOptionsDialog() +{ +} + +void ConvertOptionsDialog::slotCompressLossLessEnabled(bool val) +{ + m_JPEGPNGCompression->setEnabled( !val ); + m_label_imageCompression->setEnabled( !val ); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/convertoptionsdialog.h b/kipi-plugins/batchprocessimages/convertoptionsdialog.h new file mode 100644 index 0000000..e7275a2 --- /dev/null +++ b/kipi-plugins/batchprocessimages/convertoptionsdialog.h @@ -0,0 +1,63 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef CONVERTOPTIONSDIALOG_H +#define CONVERTOPTIONSDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +class QLabel; +class QCheckBox; +class QComboBox; + +class KIntNumInput; + +namespace KIPIBatchProcessImagesPlugin +{ + +class ConvertOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + ConvertOptionsDialog(QWidget *parent=0, int ImageFormatType = 0); + ~ConvertOptionsDialog(); + + QLabel *m_label_imageCompression; + KIntNumInput *m_JPEGPNGCompression; + QCheckBox *m_compressLossLess; + QComboBox *m_TIFFCompressionAlgo; + QComboBox *m_TGACompressionAlgo; + + public slots: + void slotCompressLossLessEnabled(bool val); +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // CONVERTOPTIONSDIALOG_H diff --git a/kipi-plugins/batchprocessimages/data/Makefile.am b/kipi-plugins/batchprocessimages/data/Makefile.am new file mode 100644 index 0000000..299f95a --- /dev/null +++ b/kipi-plugins/batchprocessimages/data/Makefile.am @@ -0,0 +1,2 @@ +kipibatchprocessimagespicdir = $(kde_datadir)/kipiplugin_batchprocessimages/data +kipibatchprocessimagespic_DATA = handcursor.png diff --git a/kipi-plugins/batchprocessimages/data/handcursor.png b/kipi-plugins/batchprocessimages/data/handcursor.png Binary files differnew file mode 100644 index 0000000..e19e2ef --- /dev/null +++ b/kipi-plugins/batchprocessimages/data/handcursor.png diff --git a/kipi-plugins/batchprocessimages/effectimagesdialog.cpp b/kipi-plugins/batchprocessimages/effectimagesdialog.cpp new file mode 100644 index 0000000..4c857ba --- /dev/null +++ b/kipi-plugins/batchprocessimages/effectimagesdialog.cpp @@ -0,0 +1,442 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes + +#include "kpaboutdata.h" +#include "pluginsversion.h" +#include "effectoptionsdialog.h" +#include "outputdialog.h" +#include "imagepreview.h" +#include "effectimagesdialog.h" +#include "effectimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +EffectImagesDialog::EffectImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch Image Effects"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch image effects"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin for batch image-effect transformations\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + m_nbItem = m_selectedImageFiles.count(); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Image Effect Options") ); + + m_labelType->setText( i18n("Effect:") ); + + m_Type->insertItem(i18n("Adaptive Threshold")); // 0 + m_Type->insertItem(i18n("Charcoal")); + m_Type->insertItem(i18n("Detect Edges")); + m_Type->insertItem(i18n("Emboss")); + m_Type->insertItem(i18n("Implode")); + m_Type->insertItem(i18n("Paint")); // 5 + m_Type->insertItem(i18n("Shade Light")); + m_Type->insertItem(i18n("Solarize")); + m_Type->insertItem(i18n("Spread")); + m_Type->insertItem(i18n("Swirl")); + m_Type->insertItem(i18n("Wave")); // 10 + m_Type->setCurrentText(i18n("Emboss")); + whatsThis = i18n("<p>Select here the effect type for your images:<p>" + "<b>Adaptive threshold</b>: perform local adaptive thresholding. The algorithm " + "selects an individual threshold for each pixel based on the range of intensity " + "values in its local neighborhood. This allows for thresholding of an image whose " + "global intensity histogram does not contain distinctive peaks.<p>" + "<b>Charcoal</b>: simulate a charcoal drawing.<p>" + "<b>Detect edges</b>: detect edges within an image.<p>" + "<b>Emboss</b>: returns a grayscale image with a three-dimensional effect. The " + "algorithm convolves the image with a Gaussian operator of the given radius and " + "standard deviation.<p>" + "<b>Implode</b>: implode image pixels about the center.<p>" + "<b>Paint</b>: applies a special effect filter that simulates an oil painting.<p>" + "<b>Shade light</b>: shines a distant light on an image to create a three-dimensional " + "effect.<p>" + "<b>Solarize</b>: negate all pixels above the threshold level. This algorithm produces a " + "solarization effect seen when exposing a photographic film to light during the development " + "process.<p>" + "<b>Spread</b>: this is a special-effect method that randomly displaces each pixel in a " + "block defined by the radius parameter.<p>" + "<b>Swirl</b>: swirls the pixels about the center of the image. <p>" + "<b>Wave</b>: creates a \"ripple\" effect in the image by shifting the pixels vertically " + "along a sine wave.<p>"); + + QWhatsThis::add( m_Type, whatsThis ); + + //--------------------------------------------- + + readSettings(); + listImageFiles(); +} + +EffectImagesDialog::~EffectImagesDialog() +{ + delete m_about; +} + +void EffectImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("effectimages", + "kipi-plugins"); +} + +void EffectImagesDialog::slotOptionsClicked(void) +{ + int Type = m_Type->currentItem(); + EffectOptionsDialog *optionsDialog = new EffectOptionsDialog(this, Type); + + if ( Type == 0) // Adaptive threshold + { + optionsDialog->m_latWidth->setValue(m_latWidth); + optionsDialog->m_latHeight->setValue(m_latHeight); + optionsDialog->m_latOffset->setValue(m_latOffset); + } + + if ( Type == 1) // Charcoal + { + optionsDialog->m_charcoalRadius->setValue(m_charcoalRadius); + optionsDialog->m_charcoalDeviation->setValue(m_charcoalDeviation); + } + + if ( Type == 2) // Detect edges + optionsDialog->m_edgeRadius->setValue(m_edgeRadius); + + if ( Type == 3) // Emboss + { + optionsDialog->m_embossRadius->setValue(m_embossRadius); + optionsDialog->m_embossDeviation->setValue(m_embossDeviation); + } + + if ( Type == 4) // Implode + optionsDialog->m_implodeFactor->setValue(m_implodeFactor); + + if ( Type == 5) // Paint + optionsDialog->m_paintRadius->setValue(m_paintRadius); + + if ( Type == 6) // Shade light + { + optionsDialog->m_shadeAzimuth->setValue(m_shadeAzimuth); + optionsDialog->m_shadeElevation->setValue(m_shadeElevation); + } + + if ( Type == 7) // Solarize + optionsDialog->m_solarizeFactor->setValue(m_solarizeFactor); + + if ( Type == 8) // Spread + optionsDialog->m_spreadRadius->setValue(m_spreadRadius); + + if ( Type == 9) // Swirl + optionsDialog->m_swirlDegrees->setValue(m_swirlDegrees); + + if ( Type == 10) // Wave + { + optionsDialog->m_waveAmplitude->setValue(m_waveAmplitude); + optionsDialog->m_waveLenght->setValue(m_waveLenght); + } + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + if ( Type == 0) // Adaptive threshold + { + m_latWidth = optionsDialog->m_latWidth->value(); + m_latHeight = optionsDialog->m_latHeight->value(); + m_latOffset = optionsDialog->m_latOffset->value(); + } + + if ( Type == 1) // Charcoal + { + m_charcoalRadius = optionsDialog->m_charcoalRadius->value(); + m_charcoalDeviation = optionsDialog->m_charcoalDeviation->value(); + } + + if ( Type == 2) // Detect edges + m_edgeRadius = optionsDialog->m_edgeRadius->value(); + + if ( Type == 3) // Emboss + { + m_embossRadius = optionsDialog->m_embossRadius->value(); + m_embossDeviation = optionsDialog->m_embossDeviation->value(); + } + + if ( Type == 4) // Implode + m_implodeFactor = optionsDialog->m_implodeFactor->value(); + + if ( Type == 5) // Paint + m_paintRadius = optionsDialog->m_paintRadius->value(); + + if ( Type == 6) // Shade light + { + m_shadeAzimuth = optionsDialog->m_shadeAzimuth->value(); + m_shadeElevation = optionsDialog->m_shadeElevation->value(); + } + + if ( Type == 7) // Solarize + m_solarizeFactor = optionsDialog->m_solarizeFactor->value(); + + if ( Type == 8) // Spread + m_spreadRadius = optionsDialog->m_spreadRadius->value(); + + if ( Type == 9) // Swirl + m_swirlDegrees = optionsDialog->m_swirlDegrees->value(); + + if ( Type == 10) // Wave + { + m_waveAmplitude = optionsDialog->m_waveAmplitude->value(); + m_waveLenght = optionsDialog->m_waveLenght->value(); + } + } + + delete optionsDialog; +} + +void EffectImagesDialog::readSettings(void) +{ +m_config = new KConfig("kipirc"); + m_config->setGroup("EffectImages Settings"); + + m_Type->setCurrentItem(m_config->readNumEntry("EffectType", 3)); // Emboss per default. + m_latWidth = m_config->readNumEntry("LatWidth", 50); + m_latHeight = m_config->readNumEntry("LatHeight", 50); + m_latOffset = m_config->readNumEntry("LatOffset", 1); + m_charcoalRadius = m_config->readNumEntry("CharcoalRadius", 3); + m_charcoalDeviation = m_config->readNumEntry("CharcoalDeviation", 3); + m_edgeRadius = m_config->readNumEntry("EdgeRadius", 3); + m_embossRadius = m_config->readNumEntry("EmbossRadius", 3); + m_embossDeviation = m_config->readNumEntry("EmbossDeviation", 3); + m_implodeFactor = m_config->readNumEntry("ImplodeFactor", 1); + m_paintRadius = m_config->readNumEntry("PaintRadius", 3); + m_shadeAzimuth = m_config->readNumEntry("ShadeAzimuth", 40); + m_shadeElevation = m_config->readNumEntry("ShadeElevation", 40); + m_solarizeFactor = m_config->readNumEntry("SolarizeFactor", 10); + m_spreadRadius = m_config->readNumEntry("SpreadRadius", 3); + m_swirlDegrees = m_config->readNumEntry("SwirlDegrees", 45); + m_waveAmplitude = m_config->readNumEntry("WaveAmplitude", 50); + m_waveLenght = m_config->readNumEntry("WaveLenght", 100); + + if (m_config->readEntry("SmallPreview", "true") == "true") + m_smallPreview->setChecked( true ); + else + m_smallPreview->setChecked( false ); + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete m_config; +} + +void EffectImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("EffectImages Settings"); + m_config->writeEntry("EffectType", m_Type->currentItem()); + + m_config->writeEntry("LatWidth", m_latWidth); + m_config->writeEntry("LatHeight", m_latHeight); + m_config->writeEntry("LatOffset", m_latOffset); + m_config->writeEntry("CharcoalRadius", m_charcoalRadius); + m_config->writeEntry("CharcoalDeviation", m_charcoalDeviation); + m_config->writeEntry("EdgeRadius", m_edgeRadius); + m_config->writeEntry("EmbossRadius", m_embossRadius); + m_config->writeEntry("EmbossDeviation", m_embossDeviation); + m_config->writeEntry("ImplodeFactor", m_implodeFactor); + m_config->writeEntry("PaintRadius", m_paintRadius); + m_config->writeEntry("ShadeAzimuth", m_shadeAzimuth); + m_config->writeEntry("ShadeElevation", m_shadeElevation); + m_config->writeEntry("SolarizeFactor", m_solarizeFactor); + m_config->writeEntry("SpreadRadius", m_spreadRadius); + m_config->writeEntry("SwirlDegrees", m_swirlDegrees); + m_config->writeEntry("WaveAmplitude", m_waveAmplitude); + m_config->writeEntry("WaveLenght", m_waveLenght); + + m_config->writeEntry("SmallPreview", m_smallPreview->isChecked()); + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + + m_config->sync(); + + delete m_config; +} + +QString EffectImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode) +{ + *proc << "convert"; + + if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled ! + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 "); + } + + if (m_Type->currentItem() == 0) // Adaptive threshold + { + *proc << "-lat"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_latWidth ) + "x"; + Temp2.append ( Temp.setNum( m_latHeight ) + "+" ); + Temp2.append ( Temp.setNum( m_latOffset ) ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 1) // Charcoal + { + *proc << "-charcoal"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_charcoalRadius ) + "x"; + Temp2.append ( Temp.setNum( m_charcoalDeviation ) ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 2) // Detect edges + { + *proc << "-edge"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_edgeRadius ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 3) // Emboss + { + *proc << "-emboss"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_embossRadius ) + "x"; + Temp2.append ( Temp.setNum( m_embossDeviation ) ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 4) // Implode + { + *proc << "-implode"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_implodeFactor ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 5) // Paint + { + *proc << "-paint"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_paintRadius ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 6) // Shade light + { + *proc << "-shade"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_shadeAzimuth ) + "x"; + Temp2.append ( Temp.setNum( m_shadeElevation ) ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 7) // Solarize + { + *proc << "-solarize"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_solarizeFactor ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 8) // Spread + { + *proc << "-spread"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_spreadRadius ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 9) // Swirl + { + *proc << "-swirl"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_swirlDegrees ); + *proc << Temp2; + } + + if (m_Type->currentItem() == 10) // Wave + { + *proc << "-wave"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_waveAmplitude ) + "x"; + Temp2.append ( Temp.setNum( m_waveLenght ) ); + *proc << Temp2; + } + + *proc << "-verbose"; + + *proc << item->pathSrc(); + + if ( !previewMode ) // No preview mode ! + { + *proc << albumDest + "/" + item->nameDest(); + } + + return(extractArguments(proc)); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/effectimagesdialog.h b/kipi-plugins/batchprocessimages/effectimagesdialog.h new file mode 100644 index 0000000..26ab5e9 --- /dev/null +++ b/kipi-plugins/batchprocessimages/effectimagesdialog.h @@ -0,0 +1,83 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef EFFECTIMAGESDIALOG_H +#define EFFECTIMAGESDIALOG_H + +// Local includes + +#include "kpaboutdata.h" +#include "batchprocessimagesdialog.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class EffectImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + EffectImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~EffectImagesDialog(); + + private slots: + + void slotHelp(void); + void slotOptionsClicked(void); + + protected: + + int m_latWidth; + int m_latHeight; + int m_latOffset; + int m_charcoalRadius; + int m_charcoalDeviation; + int m_edgeRadius; + int m_embossRadius; + int m_embossDeviation; + int m_implodeFactor; + int m_paintRadius; + int m_shadeAzimuth; + int m_shadeElevation; + int m_solarizeFactor; + int m_spreadRadius; + int m_swirlDegrees; + int m_waveAmplitude; + int m_waveLenght; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void readSettings(void); + void saveSettings(void); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // EFFECTIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/effectoptionsdialog.cpp b/kipi-plugins/batchprocessimages/effectoptionsdialog.cpp new file mode 100644 index 0000000..e56a740 --- /dev/null +++ b/kipi-plugins/batchprocessimages/effectoptionsdialog.cpp @@ -0,0 +1,257 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qcombobox.h> +#include <qcolor.h> + +// Include files for KDE + +#include <klocale.h> +#include <knuminput.h> +#include <kcolorbutton.h> + +// Local includes + +#include "effectoptionsdialog.h" +#include "effectoptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +EffectOptionsDialog::EffectOptionsDialog(QWidget *parent, int EffectType) + : KDialogBase( parent, "EffectOptionsDialog", true, + i18n("Effect Options"), Ok|Cancel, Ok, false) +{ + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + if (EffectType == 0) // Adaptive threshold + { + QLabel *m_label_latWidth = new QLabel (i18n("Width:"), box); + dvlay->addWidget( m_label_latWidth ); + m_latWidth = new KIntNumInput(50, box); + m_latWidth->setRange(0, 200, 1, true ); + QWhatsThis::add( m_latWidth, i18n("<p>Select here the value which represents the width " + "of the local neighborhood.") ); + m_label_latWidth->setBuddy( m_latWidth ); + dvlay->addWidget( m_latWidth ); + + QLabel *m_label_latHeight = new QLabel (i18n("Height:"), box); + dvlay->addWidget( m_label_latHeight ); + m_latHeight = new KIntNumInput(50, box); + m_latHeight->setRange(0, 200, 1, true ); + QWhatsThis::add( m_latHeight, i18n("<p>Select here the value which represents the height of " + "the local neighborhood.") ); + m_label_latHeight->setBuddy( m_latHeight ); + dvlay->addWidget( m_latHeight ); + + QLabel *m_label_latOffset = new QLabel (i18n("Offset:"), box); + dvlay->addWidget( m_label_latOffset ); + m_latOffset = new KIntNumInput(1, box); + m_latOffset->setRange(0, 200, 1, true ); + QWhatsThis::add( m_latOffset, i18n("<p>Select here the value which represents the mean offset.") ); + m_label_latOffset->setBuddy( m_latOffset ); + dvlay->addWidget( m_latOffset ); + } + + if (EffectType == 1) // Charcoal + { + QLabel *m_label_charcoalRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_charcoalRadius ); + m_charcoalRadius = new KIntNumInput(3, box); + m_charcoalRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_charcoalRadius, i18n("<p>Select here the value which represents the " + "radius of the pixel neighborhood.") ); + m_label_charcoalRadius->setBuddy( m_charcoalRadius ); + dvlay->addWidget( m_charcoalRadius ); + + QLabel *m_label_charcoalDeviation = new QLabel (i18n("Deviation:"), box); + dvlay->addWidget( m_label_charcoalDeviation ); + m_charcoalDeviation = new KIntNumInput(3, box); + m_charcoalDeviation->setRange(0, 20, 1, true ); + QWhatsThis::add( m_charcoalDeviation, i18n("<p>Select here the value which represents the " + "standard deviation of the Gaussian, in pixels.") ); + m_label_charcoalDeviation->setBuddy( m_charcoalDeviation ); + dvlay->addWidget( m_charcoalDeviation ); + } + + if (EffectType == 2) // Detect edges + { + QLabel *m_label_edgeRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_edgeRadius ); + m_edgeRadius = new KIntNumInput(3, box); + m_edgeRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_edgeRadius, i18n("<p>Select here the value which represents the radius of " + "the pixel neighborhood. Radius defines the radius of the " + "convolution filter. If you use a radius of 0 the algorithm selects " + "a suitable radius.") ); + m_label_edgeRadius->setBuddy( m_edgeRadius ); + dvlay->addWidget( m_edgeRadius ); + } + + if (EffectType == 3) // Emboss + { + QLabel *m_label_embossRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_embossRadius ); + m_embossRadius = new KIntNumInput(3, box); + m_embossRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_embossRadius, i18n("<p>Select here the value which represents the radius of the " + "pixel neighborhood. For reasonable results, radius should be " + "larger than deviation. If you use a radius of 0 the algorithm " + "selects a suitable radius.") ); + m_label_embossRadius->setBuddy( m_embossRadius ); + dvlay->addWidget( m_embossRadius ); + + QLabel *m_label_embossDeviation = new QLabel (i18n("Deviation:"), box); + dvlay->addWidget( m_label_embossDeviation ); + m_embossDeviation = new KIntNumInput(3, box); + m_embossDeviation->setRange(0, 20, 1, true ); + QWhatsThis::add( m_embossDeviation, i18n("<p>Select here the value which represents the standard " + "deviation of the Gaussian, in pixels.") ); + m_label_embossDeviation->setBuddy( m_embossDeviation ); + dvlay->addWidget( m_embossDeviation ); + } + + if (EffectType == 4) // Implode + { + QLabel *m_label_implodeFactor = new QLabel (i18n("Factor:"), box); + dvlay->addWidget( m_label_implodeFactor ); + m_implodeFactor = new KIntNumInput(1, box); + m_implodeFactor->setRange(0, 20, 1, true ); + QWhatsThis::add( m_implodeFactor, i18n("<p>Select here the value which represents the extent of " + "the implosion.") ); + m_label_implodeFactor->setBuddy( m_implodeFactor ); + dvlay->addWidget( m_implodeFactor ); + } + + if (EffectType == 5) // Paint + { + QLabel *m_label_paintRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_paintRadius ); + m_paintRadius = new KIntNumInput(3, box); + m_paintRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_paintRadius, i18n("<p>Select here the value which represents the radius of " + "the circular neighborhood. Each pixel is replaced by the " + "most frequent color occurring in a circular region defined " + "by the radius.") ); + m_label_paintRadius->setBuddy( m_paintRadius ); + dvlay->addWidget( m_paintRadius ); + } + + if (EffectType == 6) // Shade light + { + QLabel *m_label_shadeAzimuth = new QLabel (i18n("Azimuth:"), box); + dvlay->addWidget( m_label_shadeAzimuth ); + m_shadeAzimuth = new KIntNumInput(40, box); + m_shadeAzimuth->setRange(0, 360, 1, true ); + QWhatsThis::add( m_shadeAzimuth, i18n("<p>Select here the value which represents the azimuth of " + "the light source direction. The azimuth is measured in degrees " + "above the x axis.") ); + m_label_shadeAzimuth->setBuddy( m_shadeAzimuth ); + dvlay->addWidget( m_shadeAzimuth ); + + QLabel *m_label_shadeElevation = new QLabel (i18n("Elevation:"), box); + dvlay->addWidget( m_label_shadeElevation ); + m_shadeElevation = new KIntNumInput(40, box); + m_shadeElevation->setRange(0, 500, 1, true ); + QWhatsThis::add( m_shadeElevation, i18n("<p>Select here the value which represents the elevation of " + "the light source direction. The elevation is measured in " + "pixels above the Z axis.") ); + m_label_shadeElevation->setBuddy( m_shadeElevation ); + dvlay->addWidget( m_shadeElevation ); + } + + if (EffectType == 7) // Solarize + { + QLabel *m_label_solarizeFactor = new QLabel (i18n("Factor:"), box); + dvlay->addWidget( m_label_solarizeFactor ); + m_solarizeFactor = new KIntNumInput(3, box); + m_solarizeFactor->setRange(0, 99, 1, true ); + QWhatsThis::add( m_solarizeFactor, i18n("<p>Select here the value which represents the percent-" + "threshold of the solarize intensity.") ); + m_label_solarizeFactor->setBuddy( m_solarizeFactor ); + dvlay->addWidget( m_solarizeFactor ); + } + + if (EffectType == 8) // Spread + { + QLabel *m_label_spreadRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_spreadRadius ); + m_spreadRadius = new KIntNumInput(10, box); + m_spreadRadius->setRange(0, 200, 1, true ); + QWhatsThis::add( m_spreadRadius, i18n("<p>Select here the value which represents the random " + "pixel in a neighborhood of this extent.") ); + m_label_spreadRadius->setBuddy( m_spreadRadius ); + dvlay->addWidget( m_spreadRadius ); + } + + if (EffectType == 9) // Swirl + { + QLabel *m_label_swirlDegrees = new QLabel (i18n("Degrees:"), box); + dvlay->addWidget( m_label_swirlDegrees ); + m_swirlDegrees = new KIntNumInput(45, box); + m_swirlDegrees->setRange(0, 360, 1, true ); + QWhatsThis::add( m_swirlDegrees, i18n("<p>Select here the value which represents the tightness of " + "the swirling effect. You get a more dramatic effect as the " + "degrees move from 1 to 360.") ); + m_label_swirlDegrees->setBuddy( m_swirlDegrees ); + dvlay->addWidget( m_swirlDegrees ); + } + + if (EffectType == 10) // Wave + { + QLabel *m_label_waveAmplitude = new QLabel (i18n("Amplitude:"), box); + dvlay->addWidget( m_label_waveAmplitude ); + m_waveAmplitude = new KIntNumInput(50, box); + m_waveAmplitude->setRange(0, 200, 1, true ); + QWhatsThis::add( m_waveAmplitude, i18n("<p>Select here the value which represents the amplitude of " + "the sine wave.") ); + m_label_waveAmplitude->setBuddy( m_waveAmplitude ); + dvlay->addWidget( m_waveAmplitude ); + + QLabel *m_label_waveLenght = new QLabel (i18n("Length:"), box); + dvlay->addWidget( m_label_waveLenght ); + m_waveLenght = new KIntNumInput(100, box); + m_waveLenght->setRange(0, 200, 1, true ); + QWhatsThis::add( m_waveLenght, i18n("<p>Select here the value which represents the wave length " + "of the sine wave.") ); + m_label_waveLenght->setBuddy( m_waveLenght ); + dvlay->addWidget( m_waveLenght ); + } +} + +EffectOptionsDialog::~EffectOptionsDialog() +{ +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/effectoptionsdialog.h b/kipi-plugins/batchprocessimages/effectoptionsdialog.h new file mode 100644 index 0000000..673fc91 --- /dev/null +++ b/kipi-plugins/batchprocessimages/effectoptionsdialog.h @@ -0,0 +1,78 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef EFFECTOPTIONSDIALOG_H +#define EFFECTOPTIONSDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +class KIntNumInput; + +namespace KIPIBatchProcessImagesPlugin +{ + +class EffectOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + EffectOptionsDialog(QWidget *parent=0, int EffectType = 0); + ~EffectOptionsDialog(); + + KIntNumInput *m_latWidth; + KIntNumInput *m_latHeight; + KIntNumInput *m_latOffset; + + KIntNumInput *m_charcoalRadius; + KIntNumInput *m_charcoalDeviation; + + KIntNumInput *m_edgeRadius; + + KIntNumInput *m_embossRadius; + KIntNumInput *m_embossDeviation; + + KIntNumInput *m_implodeFactor; + + KIntNumInput *m_paintRadius; + + KIntNumInput *m_shadeAzimuth; + KIntNumInput *m_shadeElevation; + + KIntNumInput *m_solarizeFactor; + + KIntNumInput *m_spreadRadius; + + KIntNumInput *m_swirlDegrees; + + KIntNumInput *m_waveAmplitude; + KIntNumInput *m_waveLenght; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // EFFECTOPTIONSDIALOG_H diff --git a/kipi-plugins/batchprocessimages/filterimagesdialog.cpp b/kipi-plugins/batchprocessimages/filterimagesdialog.cpp new file mode 100644 index 0000000..220b383 --- /dev/null +++ b/kipi-plugins/batchprocessimages/filterimagesdialog.cpp @@ -0,0 +1,365 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes + +#include "kpaboutdata.h" +#include "pluginsversion.h" +#include "filteroptionsdialog.h" +#include "outputdialog.h" +#include "imagepreview.h" +#include "filterimagesdialog.h" +#include "filterimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +FilterImagesDialog::FilterImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch Image Filtering"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch image filtering"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin to batch filter images\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + m_nbItem = m_selectedImageFiles.count(); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Image Filtering Options") ); + + m_labelType->setText( i18n("Filter:") ); + + m_Type->insertItem(i18n("Add Noise")); // 0 + m_Type->insertItem(i18n("Antialias")); + m_Type->insertItem(i18n("Blur")); + m_Type->insertItem(i18n("Despeckle")); + m_Type->insertItem(i18n("Enhance")); // 4 + m_Type->insertItem(i18n("Median")); + m_Type->insertItem(i18n("Noise Reduction")); + m_Type->insertItem(i18n("Sharpen")); + m_Type->insertItem(i18n("Unsharp")); // 8 + m_Type->setCurrentText(i18n("Sharpen")); + whatsThis = i18n("<p>Select here the filter type for your images:<p>" + "<b>Add noise</b>: add artificial noise to an image.<p>" + "<b>Antialias</b>: remove pixel aliasing.<p>" + "<b>Blur</b>: blur the image with a Gaussian operator.<p>" + "<b>Despeckle</b>: reduces the speckle noise in an image while perserving the " + "edges of the original image.<p>" + "<b>Enhance</b>: apply a digital filter to enhance a noisy image.<p>" + "<b>Median</b>: apply a median filter to an image.<p>" + "<b>Noise reduction</b>: reduce noise in an image. <p>" + "<b>Sharpen</b>: sharpen the image with a Gaussian operator.<p>" + "<b>Unsharp</b>: sharpen the image with an unsharp mask operator.<p>"); + + QWhatsThis::add( m_Type, whatsThis ); + + //--------------------------------------------- + + readSettings(); + listImageFiles(); + slotTypeChanged(m_Type->currentItem()); +} + +FilterImagesDialog::~FilterImagesDialog() +{ + delete m_about; +} + +void FilterImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("filterimages", "kipi-plugins"); +} + +void FilterImagesDialog::slotTypeChanged(int type) +{ + if ( type == 1 || // Antialias + type == 3 || // Despeckle + type == 4 ) // Enhance + m_optionsButton->setEnabled(false); + else + m_optionsButton->setEnabled(true); +} + +void FilterImagesDialog::slotOptionsClicked(void) +{ + int Type = m_Type->currentItem(); + FilterOptionsDialog *optionsDialog = new FilterOptionsDialog(this, Type); + + if ( Type == 0) // Add noise + optionsDialog->m_noiseType->setCurrentText(m_noiseType); + + if ( Type == 2) // Blur + { + optionsDialog->m_blurRadius->setValue(m_blurRadius); + optionsDialog->m_blurDeviation->setValue(m_blurDeviation); + } + + if ( Type == 5) // Median + optionsDialog->m_medianRadius->setValue(m_medianRadius); + + if ( Type == 6) // Noise reduction + optionsDialog->m_noiseRadius->setValue(m_noiseRadius); + + if ( Type == 7) // Sharpen + { + optionsDialog->m_sharpenRadius->setValue(m_sharpenRadius); + optionsDialog->m_sharpenDeviation->setValue(m_sharpenDeviation); + } + + if ( Type == 8) // Unsharp + { + optionsDialog->m_unsharpenRadius->setValue(m_unsharpenRadius); + optionsDialog->m_unsharpenDeviation->setValue(m_unsharpenDeviation); + optionsDialog->m_unsharpenPercent->setValue(m_unsharpenPercent); + optionsDialog->m_unsharpenThreshold->setValue(m_unsharpenThreshold); + } + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + if ( Type == 0) // Add noise + m_noiseType = optionsDialog->m_noiseType->currentText(); + + if ( Type == 2) // Blur + { + m_blurRadius = optionsDialog->m_blurRadius->value(); + m_blurDeviation = optionsDialog->m_blurDeviation->value(); + } + + if ( Type == 5) // Median + m_medianRadius = optionsDialog->m_medianRadius->value(); + + if ( Type == 6) // Noise reduction + m_noiseRadius = optionsDialog->m_noiseRadius->value(); + + if ( Type == 7) // Sharpen + { + m_sharpenRadius = optionsDialog->m_sharpenRadius->value(); + m_sharpenDeviation = optionsDialog->m_sharpenDeviation->value(); + } + + if ( Type == 8) // Unsharp + { + m_unsharpenRadius = optionsDialog->m_unsharpenRadius->value(); + m_unsharpenDeviation = optionsDialog->m_unsharpenDeviation->value(); + m_unsharpenPercent = optionsDialog->m_unsharpenPercent->value(); + m_unsharpenThreshold = optionsDialog->m_unsharpenThreshold->value(); + } + } + + delete optionsDialog; +} + +void FilterImagesDialog::readSettings(void) +{ + // Read all settings from configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("FilterImages Settings"); + + m_Type->setCurrentItem(m_config->readNumEntry("FilterType", 7)); // Sharpen per default + m_noiseType = m_config->readEntry("NoiseType", i18n("Gaussian")); + m_blurRadius = m_config->readNumEntry("BlurRadius", 3); + m_blurDeviation = m_config->readNumEntry("BlurDeviation", 1); + m_medianRadius = m_config->readNumEntry("MedianRadius", 3); + m_noiseRadius = m_config->readNumEntry("NoiseRadius", 3); + m_sharpenRadius = m_config->readNumEntry("SharpenRadius", 3); + m_sharpenDeviation = m_config->readNumEntry("SharpenDeviation", 1); + m_unsharpenRadius = m_config->readNumEntry("UnsharpenRadius", 3); + m_unsharpenDeviation = m_config->readNumEntry("UnsharpenDeviation", 1); + m_unsharpenPercent = m_config->readNumEntry("UnsharpenPercent", 3); + m_unsharpenThreshold = m_config->readNumEntry("UnsharpenThreshold", 1); + + if (m_config->readEntry("SmallPreview", "true") == "true") + m_smallPreview->setChecked( true ); + else + m_smallPreview->setChecked( false ); + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete m_config; +} + +void FilterImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("FilterImages Settings"); + + m_config->writeEntry("FilterType", m_Type->currentItem()); + m_config->writeEntry("NoiseType", m_noiseType); + m_config->writeEntry("BlurRadius", m_blurRadius); + m_config->writeEntry("BlurDeviation", m_blurDeviation); + m_config->writeEntry("MedianRadius", m_medianRadius); + m_config->writeEntry("NoiseRadius", m_noiseRadius); + m_config->writeEntry("SharpenRadius", m_sharpenRadius); + m_config->writeEntry("SharpenDeviation", m_sharpenDeviation); + m_config->writeEntry("UnsharpenRadius", m_unsharpenRadius); + m_config->writeEntry("UnsharpenDeviation", m_unsharpenDeviation); + m_config->writeEntry("UnsharpenPercent", m_unsharpenPercent); + m_config->writeEntry("UnsharpenThreshold", m_unsharpenThreshold); + + m_config->writeEntry("SmallPreview", m_smallPreview->isChecked()); + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + + m_config->sync(); + + delete m_config; +} + +QString FilterImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode) +{ + *proc << "convert"; + + if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled ! + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 "); + } + + if (m_Type->currentItem() == 0) // Add noise + { + QString Temp; + if ( m_noiseType == i18n("Uniform") ) Temp = "Uniform"; + if ( m_noiseType == i18n("Gaussian") ) Temp = "Gaussian"; + if ( m_noiseType == i18n("Multiplicative") ) Temp = "Multiplicative"; + if ( m_noiseType == i18n("Impulse") ) Temp = "Impulse"; + if ( m_noiseType == i18n("Laplacian") ) Temp = "Laplacian"; + if ( m_noiseType == i18n("Poisson") ) Temp = "Poisson"; + *proc << "+noise" << Temp; + } + + if (m_Type->currentItem() == 1) // Antialias + { + *proc << "-antialias"; + } + + if (m_Type->currentItem() == 2) // Blur + { + *proc << "-blur"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_blurRadius ) + "x"; + Temp2.append(Temp.setNum( m_blurDeviation )); + *proc << Temp2; + } + + if (m_Type->currentItem() == 3) // Despeckle + { + *proc << "-despeckle"; + } + + if (m_Type->currentItem() == 4) // Enhance + { + *proc << "-enhance"; + } + + if (m_Type->currentItem() == 5) // Median + { + QString Temp, Temp2; + Temp2 = Temp.setNum( m_medianRadius ); + *proc << "-median" << Temp2; + } + + if (m_Type->currentItem() == 6) // Noise reduction + { + QString Temp, Temp2; + Temp2 = Temp.setNum( m_noiseRadius ); + *proc << "-noise" << Temp2; + } + + if (m_Type->currentItem() == 7) // Sharpen + { + *proc << "-sharpen"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_sharpenRadius ) + "x"; + Temp2.append(Temp.setNum( m_sharpenDeviation )); + *proc << Temp2; + } + + if (m_Type->currentItem() == 8) // Unsharp + { + *proc << "-unsharp"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_unsharpenRadius ) + "x"; + Temp2.append(Temp.setNum( m_unsharpenDeviation )); + Temp2.append( "+" + Temp.setNum( m_unsharpenPercent )); + Temp2.append( "+" + Temp.setNum( m_unsharpenThreshold )); + *proc << Temp2; + } + + *proc << "-verbose"; + + *proc << item->pathSrc(); + + if ( !previewMode ) // No preview mode ! + { + *proc << albumDest + "/" + item->nameDest(); + } + + return(extractArguments(proc)); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/filterimagesdialog.h b/kipi-plugins/batchprocessimages/filterimagesdialog.h new file mode 100644 index 0000000..7b1285e --- /dev/null +++ b/kipi-plugins/batchprocessimages/filterimagesdialog.h @@ -0,0 +1,78 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef FILTERIMAGESDIALOG_H +#define FILTERIMAGESDIALOG_H + +// Local includes + +#include "kpaboutdata.h" +#include "batchprocessimagesdialog.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class FilterImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + FilterImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~FilterImagesDialog(); + + private slots: + + void slotHelp(void); + void slotOptionsClicked(void); + void slotTypeChanged(int type); + + protected: + + QString m_noiseType; + int m_blurRadius; + int m_blurDeviation; + int m_medianRadius; + int m_noiseRadius; + int m_sharpenRadius; + int m_sharpenDeviation; + int m_unsharpenRadius; + int m_unsharpenDeviation; + int m_unsharpenPercent; + int m_unsharpenThreshold; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void readSettings(void); + void saveSettings(void); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // FILTERIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/filteroptionsdialog.cpp b/kipi-plugins/batchprocessimages/filteroptionsdialog.cpp new file mode 100644 index 0000000..f7f195c --- /dev/null +++ b/kipi-plugins/batchprocessimages/filteroptionsdialog.cpp @@ -0,0 +1,201 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qcombobox.h> +#include <qcolor.h> + +// Include files for KDE + +#include <klocale.h> +#include <knuminput.h> +#include <kcolorbutton.h> + +// Local includes + +#include "filteroptionsdialog.h" +#include "filteroptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +FilterOptionsDialog::FilterOptionsDialog(QWidget *parent, int FilterType) + : KDialogBase( parent, "FilterOptionsDialog", true, + i18n("Filter Options"), Ok|Cancel, Ok, false) +{ + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + if (FilterType == 0) // Add noise + { + QLabel *m_label_noiseType = new QLabel (i18n("Noise algorithm:"), box); + dvlay->addWidget( m_label_noiseType ); + m_noiseType = new QComboBox( false, box ); + m_noiseType->insertItem(i18n("Uniform")); + m_noiseType->insertItem(i18n("Gaussian")); + m_noiseType->insertItem(i18n("Multiplicative")); + m_noiseType->insertItem(i18n("Impulse")); + m_noiseType->insertItem(i18n("Laplacian")); + m_noiseType->insertItem(i18n("Poisson")); + QWhatsThis::add( m_noiseType, i18n("<p>Select here the algorithm method which will used " + "to add random noise to the images.") ); + m_label_noiseType->setBuddy( m_noiseType ); + dvlay->addWidget( m_noiseType ); + } + + if (FilterType == 2) // Blur + { + QLabel *m_label_blurRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_blurRadius ); + m_blurRadius = new KIntNumInput(3, box); + m_blurRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_blurRadius, i18n("<p>Select here the blur radius of the Gaussian, in pixels, " + "not counting the center pixel. For reasonable results, the " + "radius should be larger than deviation. If you use a radius of 0 " + "the blur operations selects a suitable radius.") ); + m_label_blurRadius->setBuddy( m_blurRadius ); + dvlay->addWidget( m_blurRadius ); + + QLabel *m_label_blurDeviation = new QLabel (i18n("Deviation:"), box); + dvlay->addWidget( m_label_blurDeviation ); + m_blurDeviation = new KIntNumInput(1, box); + m_blurDeviation->setRange(0, 20, 1, true ); + QWhatsThis::add( m_blurDeviation, i18n("<p>Select here the standard deviation of the blur Gaussian, " + "in pixels.") ); + m_label_blurDeviation->setBuddy( m_blurDeviation ); + dvlay->addWidget( m_blurDeviation ); + } + + if (FilterType == 5) // Median + { + QLabel *m_label_medianRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_medianRadius ); + m_medianRadius = new KIntNumInput(3, box); + m_medianRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_medianRadius, i18n("<p>Select here the median radius of the pixel neighborhood. " + "The algorithm applies a digital filter that improves the quality " + "of noisy images. Each pixel is replaced by the median in a " + "set of neighboring pixels as defined by the radius.") ); + m_label_medianRadius->setBuddy( m_medianRadius ); + dvlay->addWidget( m_medianRadius ); + } + + + if (FilterType == 6) // Noise reduction + { + QLabel *m_label_noiseRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_noiseRadius ); + m_noiseRadius = new KIntNumInput(3, box); + m_noiseRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_noiseRadius, i18n("<p>Select here the noise reduction radius value, in pixels. " + "The algorithm smooths the contours of an image while still " + "preserving edge information. The algorithm works by replacing " + "each pixel with its neighbor closest in value. A neighbor is " + "defined by the radius. If you use a radius of 0 the algorithm " + "selects a suitable radius.") ); + m_label_noiseRadius->setBuddy( m_noiseRadius ); + dvlay->addWidget( m_noiseRadius ); + } + + if (FilterType == 7) // Sharpen + { + QLabel *m_label_sharpenRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_sharpenRadius ); + m_sharpenRadius = new KIntNumInput(3, box); + m_sharpenRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_sharpenRadius, i18n("<p>Select here the radius of the sharpen Gaussian, in " + "pixels, not counting the center pixel. For reasonable " + "results, the radius should be larger than deviation. " + "if you use a radius of 0 the sharpen operation selects a " + "suitable radius.") ); + m_label_sharpenRadius->setBuddy( m_sharpenRadius ); + dvlay->addWidget( m_sharpenRadius ); + + QLabel *m_label_sharpenDeviation = new QLabel (i18n("Deviation:"), box); + dvlay->addWidget( m_label_sharpenDeviation ); + m_sharpenDeviation = new KIntNumInput(1, box); + m_sharpenDeviation->setRange(0, 20, 1, true ); + QWhatsThis::add( m_sharpenDeviation, i18n("<p>Select here the sharpen deviation value of the " + "Laplacian in pixels.") ); + m_label_sharpenDeviation->setBuddy( m_sharpenDeviation ); + dvlay->addWidget( m_sharpenDeviation ); + } + + if (FilterType == 8) // Unsharp + { + QLabel *m_label_unsharpenRadius = new QLabel (i18n("Radius:"), box); + dvlay->addWidget( m_label_unsharpenRadius ); + m_unsharpenRadius = new KIntNumInput(3, box); + m_unsharpenRadius->setRange(0, 20, 1, true ); + QWhatsThis::add( m_unsharpenRadius, i18n("<p>Select here the radius of the unsharpen Gaussian, " + "in pixels, not counting the center pixel. The algorithm " + "convolve the image with a Gaussian operator of the given " + "radius and standard deviation. For reasonable results, " + "radius should be larger than sigma. If you use a radius of 0 " + "the algorithm selects a suitable radius.") ); + m_label_unsharpenRadius->setBuddy( m_unsharpenRadius ); + dvlay->addWidget( m_unsharpenRadius ); + + QLabel *m_label_unsharpenDeviation = new QLabel (i18n("Deviation:"), box); + dvlay->addWidget( m_label_unsharpenDeviation ); + m_unsharpenDeviation = new KIntNumInput(1, box); + m_unsharpenDeviation->setRange(0, 20, 1, true ); + QWhatsThis::add( m_unsharpenDeviation, i18n("<p>Select here the unsharpen deviation value of the " + "Gaussian, in pixels.") ); + m_label_unsharpenDeviation->setBuddy( m_unsharpenDeviation ); + dvlay->addWidget( m_unsharpenDeviation ); + + QLabel *m_label_unsharpenPercent = new QLabel (i18n("Percent:"), box); + dvlay->addWidget( m_label_unsharpenPercent ); + m_unsharpenPercent = new KIntNumInput(3, box); + m_unsharpenPercent->setRange(1, 100, 1, true ); + QWhatsThis::add( m_unsharpenPercent, i18n("<p>Select here the percentage difference between original " + "and blurred image which should be added to original.") ); + m_label_unsharpenPercent->setBuddy( m_unsharpenPercent ); + dvlay->addWidget( m_unsharpenPercent ); + + QLabel *m_label_unsharpenThreshold = new QLabel (i18n("Threshold:"), box); + dvlay->addWidget( m_label_unsharpenThreshold ); + m_unsharpenThreshold = new KIntNumInput(1, box); + m_unsharpenThreshold->setRange(0, 20, 1, true ); + QWhatsThis::add( m_unsharpenThreshold, i18n("<p>Select here the unsharpen threshold value, in " + "pixels, needed to apply the diffence amount.")); + m_label_unsharpenThreshold->setBuddy( m_unsharpenThreshold ); + dvlay->addWidget( m_unsharpenThreshold ); + } +} + +FilterOptionsDialog::~FilterOptionsDialog() +{ +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/filteroptionsdialog.h b/kipi-plugins/batchprocessimages/filteroptionsdialog.h new file mode 100644 index 0000000..1446c06 --- /dev/null +++ b/kipi-plugins/batchprocessimages/filteroptionsdialog.h @@ -0,0 +1,69 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef FILTEROPTIONSDIALOG_H +#define FILTEROPTIONSDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +class QComboBox; + +class KIntNumInput; + +namespace KIPIBatchProcessImagesPlugin +{ + +class FilterOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + FilterOptionsDialog(QWidget *parent=0, int FilterType = 0); + ~FilterOptionsDialog(); + + QComboBox *m_noiseType; + + KIntNumInput *m_blurRadius; + KIntNumInput *m_blurDeviation; + + KIntNumInput *m_medianRadius; + + KIntNumInput *m_noiseRadius; + + KIntNumInput *m_sharpenRadius; + KIntNumInput *m_sharpenDeviation; + + KIntNumInput *m_unsharpenRadius; + KIntNumInput *m_unsharpenDeviation; + KIntNumInput *m_unsharpenPercent; + KIntNumInput *m_unsharpenThreshold; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // FILTEROPTIONSDIALOG_H diff --git a/kipi-plugins/batchprocessimages/hi32-action-borderimages.png b/kipi-plugins/batchprocessimages/hi32-action-borderimages.png Binary files differnew file mode 100644 index 0000000..c17d8b1 --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-borderimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-colorimages.png b/kipi-plugins/batchprocessimages/hi32-action-colorimages.png Binary files differnew file mode 100644 index 0000000..e41c17d --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-colorimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-convertimages.png b/kipi-plugins/batchprocessimages/hi32-action-convertimages.png Binary files differnew file mode 100644 index 0000000..b4007d4 --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-convertimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-effectimages.png b/kipi-plugins/batchprocessimages/hi32-action-effectimages.png Binary files differnew file mode 100644 index 0000000..238eb9c --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-effectimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-filterimages.png b/kipi-plugins/batchprocessimages/hi32-action-filterimages.png Binary files differnew file mode 100644 index 0000000..06ab0b2 --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-filterimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-recompressimages.png b/kipi-plugins/batchprocessimages/hi32-action-recompressimages.png Binary files differnew file mode 100644 index 0000000..0512188 --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-recompressimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-renameimages.png b/kipi-plugins/batchprocessimages/hi32-action-renameimages.png Binary files differnew file mode 100644 index 0000000..d82054d --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-renameimages.png diff --git a/kipi-plugins/batchprocessimages/hi32-action-resizeimages.png b/kipi-plugins/batchprocessimages/hi32-action-resizeimages.png Binary files differnew file mode 100644 index 0000000..cfc2d21 --- /dev/null +++ b/kipi-plugins/batchprocessimages/hi32-action-resizeimages.png diff --git a/kipi-plugins/batchprocessimages/imagepreview.cpp b/kipi-plugins/batchprocessimages/imagepreview.cpp new file mode 100644 index 0000000..21a2db1 --- /dev/null +++ b/kipi-plugins/batchprocessimages/imagepreview.cpp @@ -0,0 +1,386 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// C Ansi includes + +extern "C" +{ +#include <unistd.h> +} + +// C++ includes. + +#include <cstdlib> + +// Qt includes + +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qvbox.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qslider.h> +#include <qlcdnumber.h> +#include <qpainter.h> +#include <qwhatsthis.h> +#include <qapplication.h> +#include <qcursor.h> + +// KDE includes + +#include <kprocess.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kio/job.h> +#include <kio/jobclasses.h> +#include <kio/netaccess.h> +#include <kio/global.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kcursor.h> +#include <kdebug.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <kdeversion.h> + +// Local includes + +#include "kpaboutdata.h" +#include "pluginsversion.h" +#include "imagepreview.h" +#include "imagepreview.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +int INIT_ZOOM_FACTOR; + +ImagePreview::ImagePreview(const QString &fileOrig, const QString &fileDest, const QString &tmpPath, + bool cropActionOrig, bool cropActionDest, const QString &EffectName, + const QString &FileName, QWidget *parent) + : KDialogBase( parent, "PreviewDialog", true, i18n("Batch Process Preview (%1 - %2)").arg(EffectName) + .arg(FileName), Help|Ok, Ok, true) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch process images"), + 0, + KAboutData::License_GPL, + I18N_NOOP("An interface to preview the \"Batch Process Images\" " + "Kipi plugin.\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" " + "package."), + "(c) 2003-2004, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbooks"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + QWidget* box = new QWidget( this ); + setMainWidget(box); + resize(700, 400); + + if ( cropActionOrig == true || cropActionDest == true ) + INIT_ZOOM_FACTOR = 20; + else + INIT_ZOOM_FACTOR = 5; + + QVBoxLayout* ml = new QVBoxLayout( box, 10 ); + + //--------------------------------------------- + + QHBoxLayout* h1 = new QHBoxLayout( ml ); + QVBoxLayout* v1 = new QVBoxLayout( h1 ); + h1->addSpacing( 5 ); + QGridLayout* g1 = new QGridLayout( v1, 1, 2 ); + + QGroupBox * groupBoxZoomFactor = new QGroupBox( 2, Qt::Horizontal, i18n("Zoom Factor"), box ); + LCDZoomFactorValue = new QLCDNumber (4, groupBoxZoomFactor, "ZoomFactorLCDvalue"); + LCDZoomFactorValue->setSegmentStyle ( QLCDNumber::Flat ); + LCDZoomFactorValue->display( QString::number(INIT_ZOOM_FACTOR * 5) ); + QWhatsThis::add( LCDZoomFactorValue, i18n("<p>The zoom factor value, as a percentage.")); + + ZoomFactorSlider = new QSlider (1, 20, 1, INIT_ZOOM_FACTOR, Qt::Horizontal, + groupBoxZoomFactor, "ZoomFactorSlider"); + ZoomFactorSlider->setTracking ( false ); + ZoomFactorSlider->setTickInterval ( 5 ); + QWhatsThis::add( ZoomFactorSlider, i18n("<p>Moving this slider changes the zoom factor value.")); + g1->addWidget( groupBoxZoomFactor, 0, 0); + + QGridLayout* g2 = new QGridLayout( v1, 1, 2 ); + QGroupBox * groupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Original Image"), box ); + m_previewOrig = new PixmapView(cropActionOrig, groupBox1); + QWhatsThis::add( m_previewOrig, i18n("<p>This is the original image preview. You can use the mouse " + "wheel to change the zoom factor. Click in and use the mouse " + "to move the image.")); + g2->addWidget( groupBox1 , 0, 0); + + QGroupBox * groupBox2 = new QGroupBox( 1, Qt::Horizontal, i18n("Destination Image"), box ); + m_previewDest = new PixmapView(cropActionDest, groupBox2); + QWhatsThis::add( m_previewDest, i18n("<p>This is the destination image preview. You can use the " + "mouse wheel to change the zoom factor. Click in and use the " + "mouse to move the image.")); + g2->setColStretch(0,1); + g2->setColStretch(1,1); + g2->addWidget( groupBox2 , 0, 1); + + connect( ZoomFactorSlider, SIGNAL(valueChanged(int)), + this, SLOT(slotZoomFactorValueChanged(int)) ); + + connect( m_previewOrig, SIGNAL(wheelEvent(int)), + this, SLOT(slotWheelChanged(int)) ); + + connect( m_previewDest, SIGNAL(wheelEvent(int)), + this, SLOT(slotWheelChanged(int)) ); + + m_previewOrig->setImage(fileOrig, tmpPath); + m_previewDest->setImage(fileDest, tmpPath); +} + +ImagePreview::~ImagePreview() +{ + delete m_about; +} + +void ImagePreview::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("", "kipi-plugins"); +} + +void ImagePreview::slotWheelChanged( int delta ) +{ + if ( delta > 0 ) + ZoomFactorSlider->setValue ( ZoomFactorSlider->value() - 1 ); + else + ZoomFactorSlider->setValue ( ZoomFactorSlider->value() + 1 ); + + slotZoomFactorValueChanged( ZoomFactorSlider->value() ); +} + +void ImagePreview::slotZoomFactorValueChanged( int ZoomFactorValue ) +{ + LCDZoomFactorValue->display( QString::number(ZoomFactorValue * 5) ); + + m_previewOrig->resizeImage( ZoomFactorValue * 5 ); + m_previewDest->resizeImage( ZoomFactorValue * 5 ); +} + +PixmapView::PixmapView(bool cropAction, QWidget *parent, const char *name) + : QScrollView(parent, name) +{ + m_cropAction = cropAction; + m_pix = NULL; + m_validPreview = false; + setMinimumSize(QSize(300,300)); + horizontalScrollBar()->setLineStep( 1 ); + horizontalScrollBar()->setPageStep( 1 ); + verticalScrollBar()->setLineStep( 1 ); + verticalScrollBar()->setPageStep( 1 ); + KGlobal::dirs()->addResourceType("kipi_handcursor", KGlobal::dirs()->kde_default("data") + + "kipi/data"); + m_handCursor = new QCursor( KGlobal::dirs()->findResourceDir("kipi_handcursor", "handcursor.png") + + "handcursor.png" ); +} + +PixmapView::~PixmapView() +{ + if(m_pix) delete m_pix; +} + +void PixmapView::setImage(const QString &ImagePath, const QString &tmpPath) +{ + + m_previewFileName = tmpPath + "/" + QString::number(getpid()) + "-" + + QString::number(random()) + "PreviewImage.PNG"; + + if (m_cropAction == true) + PreviewCal(ImagePath, tmpPath); + else + { + if ( m_img.load(ImagePath) == false ) + PreviewCal(ImagePath, tmpPath); + else + { + if(!m_pix) m_pix = new QPixmap(m_img.width(), m_img.height()); + m_w = m_img.width(); + m_h = m_img.height(); + m_validPreview = true; + resizeImage( INIT_ZOOM_FACTOR *5 ); + horizontalScrollBar()->setLineStep(1); + verticalScrollBar()->setLineStep(1); + } + } +} + +void PixmapView::PreviewCal(const QString &ImagePath, const QString &/*tmpPath*/) +{ + m_pix = new QPixmap(300, 300); + QPainter p; + p.begin(m_pix); + p.fillRect(0, 0, m_pix->width(), m_pix->height(), Qt::white); + p.setPen(Qt::green); + p.drawText(0, 0, m_pix->width(), m_pix->height(), Qt::AlignCenter, + i18n("Preview\nimage\nprocessing\nin\nprogress...")); + p.end(); + + m_previewOutput ="convert"; + m_PreviewProc = new KProcess; + *m_PreviewProc << "convert"; + *m_PreviewProc << "-verbose"; + + if (m_cropAction == true) + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 " ); + } + + *m_PreviewProc << ImagePath; + *m_PreviewProc << m_previewFileName; + m_previewOutput.append( " -verbose " + ImagePath + " " + m_previewFileName + "\n\n"); + + connect(m_PreviewProc, SIGNAL(processExited(KProcess *)), + this, SLOT(PreviewProcessDone(KProcess*))); + + connect(m_PreviewProc, SIGNAL(receivedStdout(KProcess *, char*, int)), + this, SLOT(slotPreviewReadStd(KProcess*, char*, int))); + + connect(m_PreviewProc, SIGNAL(receivedStderr(KProcess *, char*, int)), + this, SLOT(slotPreviewReadStd(KProcess*, char*, int))); + + bool result = m_PreviewProc->start(KProcess::NotifyOnExit, KProcess::All); + if(!result) + { + KMessageBox::error(this, i18n("Cannot start 'convert' program from 'ImageMagick' package;\n" + "please check your installation.")); + return; + } +} + +void PixmapView::slotPreviewReadStd(KProcess* /*proc*/, char *buffer, int buflen) +{ + m_previewOutput.append( QString::fromLocal8Bit(buffer, buflen) ); +} + +void PixmapView::PreviewProcessDone(KProcess* proc) +{ + int ValRet = proc->exitStatus(); + kdDebug (51000) << "Convert exit (" << ValRet << ")" << endl; + + if ( ValRet == 0 ) + { + if ( m_img.load( m_previewFileName ) == true ) + { + if(!m_pix) m_pix = new QPixmap(300, 300); + m_w = m_img.width(); + m_h = m_img.height(); + m_validPreview = true; + resizeImage( INIT_ZOOM_FACTOR * 5 ); + horizontalScrollBar()->setLineStep(1); + verticalScrollBar()->setLineStep(1); + KURL deletePreviewImage( m_previewFileName ); + +#if KDE_VERSION >= 0x30200 + KIO::NetAccess::del( deletePreviewImage, kapp->activeWindow() ); +#else + KIO::NetAccess::del( deletePreviewImage ); +#endif + } + else + { + m_pix = new QPixmap(visibleWidth(), visibleHeight()); + QPainter p; + p.begin(m_pix); + p.fillRect(0, 0, m_pix->width(), m_pix->height(), Qt::white); + p.setPen(Qt::red); + p.drawText(0, 0, m_pix->width(), m_pix->height(), Qt::AlignCenter, + i18n("Cannot\nprocess\npreview\nimage.")); + p.end(); + repaintContents(); + m_validPreview = false; + } + } +} + +void PixmapView::resizeImage(int ZoomFactor) +{ + if ( m_validPreview == false) return; + + int w = m_w - (int)((float)m_w * (100-(float)ZoomFactor) / 100); + int h = m_h - (int)((float)m_h * (100-(float)ZoomFactor) / 100); + + QImage imgTmp = m_img.scale(w, h); + m_pix->convertFromImage(imgTmp); + resizeContents(w, h); + repaintContents(false); +} + +void PixmapView::drawContents(QPainter *p, int x, int y, int w, int h) +{ + if(!m_pix) return; + else p->drawPixmap(x, y, *m_pix, x, y, w, h); +} + +void PixmapView::contentsWheelEvent( QWheelEvent * e ) +{ + emit wheelEvent(e->delta()); +} + +void PixmapView::contentsMousePressEvent ( QMouseEvent * e ) +{ + if ( e->button() == Qt::LeftButton ) + { + m_xpos = e->x(); + m_ypos = e->y(); + setCursor ( *m_handCursor ); + } +} + +void PixmapView::contentsMouseReleaseEvent ( QMouseEvent * /*e*/ ) +{ + setCursor ( KCursor::arrowCursor() ); +} + +void PixmapView::contentsMouseMoveEvent( QMouseEvent * e ) +{ + if ( e->state() == Qt::LeftButton ) + { + uint newxpos = e->x(); + uint newypos = e->y(); + + scrollBy (-(newxpos - m_xpos), -(newypos - m_ypos)); + + m_xpos = newxpos - (newxpos-m_xpos); + m_ypos = newypos - (newypos-m_ypos); + } +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/imagepreview.h b/kipi-plugins/batchprocessimages/imagepreview.h new file mode 100644 index 0000000..27e7204 --- /dev/null +++ b/kipi-plugins/batchprocessimages/imagepreview.h @@ -0,0 +1,142 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef IMAGEPREVIEW_H +#define IMAGEPREVIEW_H + +// Include files for Qt + +#include <qscrollview.h> +#include <qimage.h> +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +// Local includes + +#include "kpaboutdata.h" + +class QPixmap; +class QCursor; +class QLCDNumber; +class QSlider; +class QPushButton; + +class KProcess; + +namespace KIPIBatchProcessImagesPlugin +{ + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +class PixmapView : public QScrollView +{ +Q_OBJECT + +public: + + PixmapView(bool cropAction, QWidget *parent=0, const char *name=0); + ~PixmapView(); + + void setImage(const QString &ImagePath, const QString &tmpPath); + void resizeImage(int ZoomFactor); + +private slots: + + void slotPreviewReadStd(KProcess* proc, char *buffer, int buflen); + void PreviewProcessDone(KProcess* proc); + void contentsWheelEvent( QWheelEvent * e ); + void contentsMousePressEvent ( QMouseEvent * e ); + void contentsMouseReleaseEvent ( QMouseEvent * e ); + void contentsMouseMoveEvent( QMouseEvent * e ); + +signals: + + void wheelEvent( int delta ); + +protected: + + QPixmap *m_pix; + + QImage m_img; + + int m_w; + int m_h; + int m_xpos; + int m_ypos; + + KProcess *m_PreviewProc; + + QString m_previewOutput; + QString m_previewFileName; + + bool m_validPreview; + bool m_cropAction; + + QCursor *m_handCursor; + + void drawContents(QPainter *p, int x, int y, int w, int h); + void PreviewCal(const QString &ImagePath, const QString &tmpPath); + +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +class ImagePreview : public KDialogBase +{ +Q_OBJECT + +public: + + ImagePreview(const QString &fileOrig, const QString &fileDest, const QString &tmpPath, + bool cropActionOrig, bool cropActionDest, const QString &EffectName, + const QString &FileName, QWidget *parent=0); + ~ImagePreview(); + +private slots: + + void slotZoomFactorValueChanged( int ZoomFactorValue ); + void slotWheelChanged( int delta ); + void slotHelp(void); + +protected: + + PixmapView *m_previewOrig; + PixmapView *m_previewDest; + + QLCDNumber *LCDZoomFactorValue; + + QSlider *ZoomFactorSlider; + + QPushButton *m_helpButton; + +private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // IMAGEPREVIEW_H + diff --git a/kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop b/kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop new file mode 100644 index 0000000..8c811b4 --- /dev/null +++ b/kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=BatchProcessImages +Name[ca]=Procés d'imatges per lots +Name[cs]=Dávkové zpracování obrázků +Name[da]=Behandl billeder i baggrunden +Name[de]=Bilder-Stapelverarbeitung +Name[el]=ΟμαδικήΕπεξεργασίαΕικόνων +Name[es]=Proceso de imágenes por bloques +Name[et]=Piltide pakktöötlus +Name[fi]=Eräajo +Name[gl]=Procesamento de Lotes de Imaxes +Name[is]=MagnvinnaMyndir +Name[it]=ElaborazioneNonInterattivaDelleImmagini +Name[nds]=Bild-Stapelverarbeiden +Name[nl]=AfbeeldingenVerwerken +Name[pl]=Grupowe przetwarzanie zdjęć +Name[pt]=Processamento em Lote de Imagens +Name[sr]=Пакетна обрада слика +Name[sr@Latn]=Paketna obrada slika +Name[sv]=Behandla bilder i bakgrunden +Name[tg]=ПардозишиГурӯҳиТасвирҳо +Name[tr]=ÇokluResimİşleme +Name[xx]=xxBatchProcessImagesxx +Name[zh_CN]=批处理图像 +Comment=KIPI Batch Processing Images Plugin +Comment[ca]=Connector del KIPI pel processat per lots d'imatges +Comment[cs]=KIPI modul dávkového zpracování obrázků +Comment[da]=KIPI-plugin: Behandl billeder i baggrunden +Comment[de]=Ein KIPI-Modul zum Bearbeiten von Bildern im Stapelmodus +Comment[el]=Πρόσθετο ομαδικής επεξεργασίας εικόνων KIPI +Comment[es]=Complemento de KIPI para el procesado de imágenes por lotes +Comment[et]=KIPI piltide pakktöötluse plugin +Comment[fi]=Kipi-liitännäinen usean kuvan peräkkäistä käsittelyä varten +Comment[fr]=Module externe KIPI pour traiter des images par lots +Comment[gl]=Plugin de KIPI para Procesar Imaxes por Lotes +Comment[is]=KIPI íforrit til magnvinnslu mynda +Comment[it]=Plugin di elaborazione non interattiva delle immagini di KIPI +Comment[ja]=Kipi 画像一括処理プラグイン +Comment[nds]=Kipi-Moduul för't Stapelverarbeiden vun Biller +Comment[nl]=KIPI-plugin voor het verwerken van een serie afbeeldingen +Comment[pa]=KIPI ਬੈਂਚ ਕਾਰਵਾਈ ਚਿੱਤਰ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka KIPI - Grupowe przetwarzanie zdjęć +Comment[pt]='Plugin' do KIPI de Processamento de Imagens em Lote +Comment[pt_BR]=Plugin de Processamento de Imagens em Lote do KIPI +Comment[sr]=KIPI прикључак за пакетну обраду слика +Comment[sr@Latn]=KIPI priključak za paketnu obradu slika +Comment[sv]=KIPI-insticksprogram: Behandla bilder i bakgrunden +Comment[tg]=Модули пардозиши тасвирҳои KIPI +Comment[tr]=KIPI Çoklu Resim İşleme Eklentisi +Comment[xx]=xxKIPI Batch Processing Images Pluginxx +Comment[zh_CN]=KIPI 批处理图像插件 +Icon= +ServiceTypes=KIPI/Plugin +Type=Service +X-KDE-Library=kipiplugin_batchprocessimages +author=Gilles Caulier, caulier dot gilles at gmail dot com diff --git a/kipi-plugins/batchprocessimages/outputdialog.cpp b/kipi-plugins/batchprocessimages/outputdialog.cpp new file mode 100644 index 0000000..3ba2a60 --- /dev/null +++ b/kipi-plugins/batchprocessimages/outputdialog.cpp @@ -0,0 +1,112 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Qt includes + +#include <qtextview.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qframe.h> + +// KDElib includes + +#include <klocale.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <kstandarddirs.h> + +// Local includes + +#include "pluginsversion.h" +#include "outputdialog.h" +#include "outputdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +OutputDialog::OutputDialog(QWidget* parent, QString caption, QString Messages, QString Header ) + : KDialogBase( parent, "OutputDialog", true, caption, Help|User1|Ok, Ok, false, + i18n("Copy to Clip&board")) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch processes images"), + 0, + KAboutData::License_GPL, + I18N_NOOP("An interface to show the output of the \"Batch Process " + "Images\" Kipi plugin.\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" " + "package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbooks"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + + //--------------------------------------------- + + QLabel *labelHeader = new QLabel( Header, box); + dvlay->addWidget( labelHeader ); + + debugView = new QTextView( box ); + debugView->append( Messages ); + dvlay->addWidget( debugView ); + + connect(this, SIGNAL(user1Clicked()), + this, SLOT(slotCopyToCliboard())); + + resize( 600, 400 ); +} + +OutputDialog::~OutputDialog() +{ + delete m_about; +} + +void OutputDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("", + "kipi-plugins"); +} + +void OutputDialog::slotCopyToCliboard( void ) +{ + debugView->selectAll(true); + debugView->copy(); + debugView->selectAll(false); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/outputdialog.h b/kipi-plugins/batchprocessimages/outputdialog.h new file mode 100644 index 0000000..f849439 --- /dev/null +++ b/kipi-plugins/batchprocessimages/outputdialog.h @@ -0,0 +1,71 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef OUTPUTDIALOG_H +#define OUTPUTDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +// Local includes + +#include "kpaboutdata.h" + +class QTextView; +class QPushButton; + +namespace KIPIBatchProcessImagesPlugin +{ + +class OutputDialog : public KDialogBase +{ +Q_OBJECT + +public: + + OutputDialog( QWidget* parent=0, QString caption=QString::null, + QString Messages=QString::null, QString Header=QString::null ); + ~OutputDialog(); + +private slots: + + void slotHelp(void); + void slotCopyToCliboard( void ); + +private: + + QPushButton *m_helpButton; + QTextView *debugView; + + KIPIPlugins::KPAboutData *m_about; + +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // OUTPUTDIALOG_H + diff --git a/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp new file mode 100644 index 0000000..084fb03 --- /dev/null +++ b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp @@ -0,0 +1,313 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// C Ansi includes + +extern "C" +{ +#include <unistd.h> +} + +// Qt Includes + +#include <qimage.h> + +// KDE includes + +#include <klocale.h> +#include <kapplication.h> +#include <kglobal.h> +#include <kaction.h> +#include <kgenericfactory.h> +#include <klibloader.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktempfile.h> + +// KIPI includes + +#include <libkipi/interface.h> + +// Local includes + +#include "borderimagesdialog.h" +#include "colorimagesdialog.h" +#include "convertimagesdialog.h" +#include "effectimagesdialog.h" +#include "filterimagesdialog.h" +#include "renameimagesdialog.h" +#include "recompressimagesdialog.h" +#include "resizeimagesdialog.h" +#include "plugin_batchprocessimages.h" +#include "plugin_batchprocessimages.moc" + +typedef KGenericFactory<Plugin_BatchProcessImages> Factory; + +K_EXPORT_COMPONENT_FACTORY( kipiplugin_batchprocessimages, + Factory("kipiplugin_batchprocessimages")) + +Plugin_BatchProcessImages::Plugin_BatchProcessImages(QObject *parent, const char*, const QStringList&) + : KIPI::Plugin( Factory::instance(), parent, "BatchProcessImages") +{ + kdDebug( 51001 ) << "Plugin_BatchProcessImages plugin loaded" << endl; + +} + +void Plugin_BatchProcessImages::setup( QWidget* widget ) +{ + KIPI::Plugin::setup( widget ); + + m_action_borderimages = new KAction (i18n("Border Images..."), // Menu message. + "borderimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_border_images"); + + m_action_colorimages = new KAction (i18n("Color Images..."), // Menu message. + "colorimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_color_images"); + + m_action_convertimages = new KAction (i18n("Convert Images..."), // Menu message. + "convertimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_convert_images"); + + m_action_effectimages = new KAction (i18n("Image Effects..."), // Menu message. + "effectimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_effect_images"); + + m_action_filterimages = new KAction (i18n("Filter Images..."), // Menu message. + "filterimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_filter_images"); + + m_action_renameimages = new KAction (i18n("Rename Images..."), // Menu message. + "renameimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_rename_images"); + + m_action_recompressimages = new KAction (i18n("Recompress Images..."), // Menu message. + "recompressimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_recompress_images"); + + m_action_resizeimages = new KAction (i18n("Resize Images..."), // Menu message. + "resizeimages", // Menu icon. + 0, // default shortcut. + this, + SLOT(slotActivate()), + actionCollection(), + "batch_resize_images"); + + addAction( m_action_borderimages ); + addAction( m_action_colorimages ); + addAction( m_action_convertimages ); + addAction( m_action_effectimages ); + addAction( m_action_filterimages ); + addAction( m_action_renameimages ); + addAction( m_action_recompressimages ); + addAction( m_action_resizeimages ); + + KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() ); + + if ( !interface ) + { + kdError( 51000 ) << "Kipi interface is null!" << endl; + return; + } + + KIPI::ImageCollection images = interface->currentAlbum(); + bool enable = images.isValid() && !images.images().isEmpty(); + + m_action_borderimages->setEnabled( enable ); + m_action_colorimages->setEnabled( enable ); + m_action_convertimages->setEnabled( enable ); + m_action_effectimages->setEnabled( enable ); + m_action_filterimages->setEnabled( enable ); + m_action_renameimages->setEnabled( enable ); + m_action_recompressimages->setEnabled( enable ); + m_action_resizeimages->setEnabled( enable ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_borderimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_colorimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_convertimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_effectimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_filterimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_renameimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_recompressimages, SLOT( setEnabled( bool ) ) ); + + connect( interface, SIGNAL( currentAlbumChanged( bool ) ), + m_action_resizeimages, SLOT( setEnabled( bool ) ) ); +} + +Plugin_BatchProcessImages::~Plugin_BatchProcessImages() +{ +} + +void Plugin_BatchProcessImages::slotActivate() +{ + KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() ); + + if ( !interface ) + { + kdError( 51000 ) << "Kipi interface is null!" << endl; + return; + } + + KIPI::ImageCollection images = interface->currentSelection(); + + if ( !images.isValid() ) + return; + + if ( images.images().isEmpty() ) + images = interface->currentAlbum(); + + if ( !images.isValid() ) + return; + + if ( images.images().isEmpty() ) + { + KMessageBox::sorry(kapp->activeWindow(), + i18n("Please select an album or a selection of images.")); + return; + } + + KURL::List urlList = images.images(); + + QString from(sender()->name()); + + if (from == "batch_convert_images") + { + m_ConvertImagesDialog = new KIPIBatchProcessImagesPlugin::ConvertImagesDialog( urlList, + interface, kapp->activeWindow()); + m_ConvertImagesDialog->show(); + } + else if (from == "batch_rename_images") + { + KIPIBatchProcessImagesPlugin::RenameImagesDialog + dlg(urlList, interface, kapp->activeWindow()); + dlg.exec(); + } + else if (from == "batch_border_images") + { + m_BorderImagesDialog = new KIPIBatchProcessImagesPlugin::BorderImagesDialog( urlList, + interface, kapp->activeWindow()); + m_BorderImagesDialog->show(); + } + else if (from == "batch_color_images") + { + m_ColorImagesDialog = new KIPIBatchProcessImagesPlugin::ColorImagesDialog( urlList, + interface, kapp->activeWindow()); + m_ColorImagesDialog->show(); + } + else if (from == "batch_filter_images") + { + m_FilterImagesDialog = new KIPIBatchProcessImagesPlugin::FilterImagesDialog( urlList, + interface, kapp->activeWindow()); + m_FilterImagesDialog->show(); + } + else if (from == "batch_effect_images") + { + m_EffectImagesDialog = new KIPIBatchProcessImagesPlugin::EffectImagesDialog( urlList, + interface, kapp->activeWindow()); + m_EffectImagesDialog->show(); + } + else if (from == "batch_recompress_images") + { + m_RecompressImagesDialog = new KIPIBatchProcessImagesPlugin::RecompressImagesDialog( urlList, + interface, kapp->activeWindow()); + m_RecompressImagesDialog->show(); + } + else if (from == "batch_resize_images") + { + m_ResizeImagesDialog = new KIPIBatchProcessImagesPlugin::ResizeImagesDialog( urlList, + interface, kapp->activeWindow()); + m_ResizeImagesDialog->show(); + } + else + { + kdWarning( 51000 ) << "The impossible happened... unknown batch action specified" << endl; + return; + } +} + +KIPI::Category Plugin_BatchProcessImages::category( KAction* action ) const +{ + if ( action == m_action_borderimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_colorimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_convertimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_effectimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_filterimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_renameimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_recompressimages ) + return KIPI::BATCHPLUGIN; + else if ( action == m_action_resizeimages ) + return KIPI::BATCHPLUGIN; + + kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl; + return KIPI::BATCHPLUGIN; // no warning from compiler, please +} diff --git a/kipi-plugins/batchprocessimages/plugin_batchprocessimages.h b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.h new file mode 100644 index 0000000..ff78a8f --- /dev/null +++ b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.h @@ -0,0 +1,80 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef PLUGIN_BATCHPROCESSIMAGES_H +#define PLUGIN_BATCHPROCESSIMAGES_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <libkipi/plugin.h> + +class KAction; + +class KIPIBatchProcessImagesPlugin::BorderImagesDialog; +class KIPIBatchProcessImagesPlugin::ColorImagesDialog; +class KIPIBatchProcessImagesPlugin::ConvertImagesDialog; +class KIPIBatchProcessImagesPlugin::EffectImagesDialog; +class KIPIBatchProcessImagesPlugin::FilterImagesDialog; +class KIPIBatchProcessImagesPlugin::RenameImagesDialog; +class KIPIBatchProcessImagesPlugin::RecompressImagesDialog; +class KIPIBatchProcessImagesPlugin::ResizeImagesDialog; + +class Plugin_BatchProcessImages : public KIPI::Plugin +{ +Q_OBJECT + +public: + Plugin_BatchProcessImages(QObject *parent, const char* name, const QStringList &args); + virtual ~Plugin_BatchProcessImages(); + virtual KIPI::Category category( KAction* action ) const; + virtual void setup( QWidget* ); + +public slots: + void slotActivate(); + +private: + KAction *m_action_borderimages; + KAction *m_action_colorimages; + KAction *m_action_convertimages; + KAction *m_action_effectimages; + KAction *m_action_filterimages; + KAction *m_action_renameimages; + KAction *m_action_recompressimages; + KAction *m_action_resizeimages; + + + KIPIBatchProcessImagesPlugin::BorderImagesDialog *m_BorderImagesDialog; + KIPIBatchProcessImagesPlugin::ColorImagesDialog *m_ColorImagesDialog; + KIPIBatchProcessImagesPlugin::ConvertImagesDialog *m_ConvertImagesDialog; + KIPIBatchProcessImagesPlugin::EffectImagesDialog *m_EffectImagesDialog; + KIPIBatchProcessImagesPlugin::FilterImagesDialog *m_FilterImagesDialog; + KIPIBatchProcessImagesPlugin::RenameImagesDialog *m_RenameImagesDialog; + KIPIBatchProcessImagesPlugin::RecompressImagesDialog *m_RecompressImagesDialog; + KIPIBatchProcessImagesPlugin::ResizeImagesDialog *m_ResizeImagesDialog; +}; + + +#endif /* PLUGIN_BATCHPROCESSIMAGES_H */ diff --git a/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp b/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp new file mode 100644 index 0000000..7f70474 --- /dev/null +++ b/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp @@ -0,0 +1,272 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes + +#include "kpaboutdata.h" +#include "pluginsversion.h" +#include "recompressoptionsdialog.h" +#include "outputdialog.h" +#include "recompressimagesdialog.h" +#include "recompressimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +RecompressImagesDialog::RecompressImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch Recompress Images"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch recompress images"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin to batch recompress images\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + m_nbItem = m_selectedImageFiles.count(); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Image Recompression Options") ); + + m_labelType->hide(); + m_Type->hide(); + m_previewButton->hide(); + m_smallPreview->hide(); + + //--------------------------------------------- + + readSettings(); + listImageFiles(); +} + +RecompressImagesDialog::~RecompressImagesDialog() +{ + delete m_about; +} + +void RecompressImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("recompressimages", "kipi-plugins"); +} + +void RecompressImagesDialog::slotOptionsClicked(void) +{ + RecompressOptionsDialog *optionsDialog = new RecompressOptionsDialog(this); + + optionsDialog->m_JPEGCompression->setValue(m_JPEGCompression); + optionsDialog->m_compressLossLess->setChecked(m_compressLossLess); + optionsDialog->m_PNGCompression->setValue(m_PNGCompression); + optionsDialog->m_TIFFCompressionAlgo->setCurrentText(m_TIFFCompressionAlgo); + optionsDialog->m_TGACompressionAlgo->setCurrentText(m_TGACompressionAlgo); + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + m_JPEGCompression = optionsDialog->m_JPEGCompression->value(); + m_compressLossLess = optionsDialog->m_compressLossLess->isChecked(); + m_PNGCompression = optionsDialog->m_PNGCompression->value(); + m_TIFFCompressionAlgo = optionsDialog->m_TIFFCompressionAlgo->currentText(); + m_TGACompressionAlgo = optionsDialog->m_TGACompressionAlgo->currentText(); + } + + delete optionsDialog; +} + +void RecompressImagesDialog::readSettings(void) +{ + // Read all settings from configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("RecompressImages Settings"); + + m_JPEGCompression = m_config->readNumEntry("JPEGCompression", 75); + + if ( m_config->readEntry("CompressLossLess", "false") == "true") + m_compressLossLess = true; + else + m_compressLossLess = false; + + m_PNGCompression = m_config->readNumEntry("PNGCompression", 75); + m_TIFFCompressionAlgo = m_config->readEntry("TIFFCompressionAlgo", i18n("None")); + m_TGACompressionAlgo = m_config->readEntry("TGACompressionAlgo", i18n("None")); + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete m_config; +} + +void RecompressImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("RecompressImages Settings"); + + m_config->writeEntry("JPEGCompression", m_JPEGCompression); + m_config->writeEntry("PNGCompression", m_PNGCompression); + m_config->writeEntry("CompressLossLess", m_compressLossLess); + m_config->writeEntry("TIFFCompressionAlgo", m_TIFFCompressionAlgo); + m_config->writeEntry("TGACompressionAlgo", m_TGACompressionAlgo); + + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + + m_config->sync(); + + delete m_config; +} + +QString RecompressImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode) +{ + *proc << "convert"; + + if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled ! + { + *m_PreviewProc << "-crop" << "300x300+0+0"; + m_previewOutput.append( " -crop 300x300+0+0 "); + } + + QString imageExt = item->nameSrc().section('.', -1 ); + + if (imageExt == "JPEG" || imageExt == "jpeg" || imageExt == "JPG" || imageExt == "jpg") + { + if (m_compressLossLess == true) + { + *proc << "-compress" << "Lossless"; + } + else + { + *proc << "-quality"; + QString Temp; + *proc << Temp.setNum( m_JPEGCompression ); + } + } + + else if (imageExt == "PNG" || imageExt == "png") + { + *proc << "-quality"; + QString Temp; + *proc << Temp.setNum( m_PNGCompression ); + } + + else if (imageExt == "TIFF" || imageExt == "tiff" || imageExt == "TIF" || imageExt == "tif") + { + *proc << "-compress"; + + if (m_TIFFCompressionAlgo == i18n("None")) + { + *proc << "None"; + } + else + { + *proc << m_TIFFCompressionAlgo; + } + } + + else if (imageExt == "TGA" || imageExt == "tga") + { + *proc << "-compress"; + + if (m_TGACompressionAlgo == i18n("None")) + { + *proc << "None"; + } + else + { + *proc << m_TGACompressionAlgo; + } + } + + *proc << "-verbose"; + + *proc << item->pathSrc(); + + if ( !previewMode ) // No preview mode ! + { + *proc << albumDest + "/" + item->nameDest(); + } + + return(extractArguments(proc)); +} + +bool RecompressImagesDialog::prepareStartProcess(BatchProcessImagesItem *item, + const QString& /*albumDest*/) +{ + QString imageExt = item->nameSrc().section('.', -1 ); + + if (imageExt != "JPEG" && imageExt != "jpeg" && + imageExt != "JPG" && imageExt != "jpg" && + imageExt != "JPE" && imageExt != "jpe" && + imageExt != "PNG" && imageExt != "png" && + imageExt != "TIFF" && imageExt != "tiff" && + imageExt != "TIF" && imageExt != "tif" && + imageExt != "TGA" && imageExt != "tga") + { + item->changeResult(i18n("Skipped.")); + item->changeError(i18n("image file format unsupported.")); + return false; + } + + return true; +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/recompressimagesdialog.h b/kipi-plugins/batchprocessimages/recompressimagesdialog.h new file mode 100644 index 0000000..087aa45 --- /dev/null +++ b/kipi-plugins/batchprocessimages/recompressimagesdialog.h @@ -0,0 +1,74 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef RECOMPRESSIMAGESDIALOG_H +#define RECOMPRESSIMAGESDIALOG_H + +// Local includes + +#include "kpaboutdata.h" +#include "batchprocessimagesdialog.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class RecompressImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + RecompressImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~RecompressImagesDialog(); + + private slots: + + void slotOptionsClicked(void); + void slotHelp(void); + + protected: + + int m_JPEGCompression; + int m_PNGCompression; + bool m_compressLossLess; + QString m_TIFFCompressionAlgo; + QString m_TGACompressionAlgo; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void readSettings(void); + void saveSettings(void); + + bool prepareStartProcess(BatchProcessImagesItem *item, + const QString& albumDest); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // RECOMPRESSIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp b/kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp new file mode 100644 index 0000000..fc81e26 --- /dev/null +++ b/kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp @@ -0,0 +1,140 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qcombobox.h> +#include <qcheckbox.h> + +// Include files for KDE + +#include <klocale.h> +#include <knuminput.h> + +// Local includes + +#include "recompressoptionsdialog.h" +#include "recompressoptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +RecompressOptionsDialog::RecompressOptionsDialog(QWidget *parent) + : KDialogBase( parent, "RecompressOptionsDialog", true, + i18n("Recompression Options"), Ok|Cancel, Ok, false) +{ + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + // JPEG file format. + + QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("JPEG File Format"), box ); + + m_label_JPEGimageCompression = new QLabel (i18n("Image compression level:"), groupBox1); + m_JPEGCompression = new KIntNumInput(75, groupBox1); + m_JPEGCompression->setRange(1, 100, 1, true ); + whatsThis = i18n("<p>The compression value for JPEG target images:<p>"); + whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>" + "<b>25</b>: high compression<p>" + "<b>50</b>: medium compression<p>" + "<b>75</b>: low compression (default value)<p>" + "<b>100</b>: no compression"); + + QWhatsThis::add( m_JPEGCompression, whatsThis); + m_label_JPEGimageCompression->setBuddy( m_JPEGCompression ); + + m_compressLossLess = new QCheckBox( i18n("Use lossless compression"), groupBox1); + QWhatsThis::add( m_compressLossLess, i18n("<p>If this option is enabled, " + "all JPEG operations will use lossless compression.")); + + connect(m_compressLossLess, SIGNAL( toggled(bool) ), + this, SLOT( slotCompressLossLessEnabled(bool) ) ); + + dvlay->addWidget( groupBox1 ); + + // PNG File format. + + QGroupBox * groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("PNG File Format"), box ); + + m_label_PNGimageCompression = new QLabel (i18n("Image compression level:"), groupBox2); + m_PNGCompression = new KIntNumInput(75, groupBox2); + m_PNGCompression->setRange(1, 100, 1, true ); + whatsThis = i18n("<p>The compression value for PNG target images:<p>"); + whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>" + "<b>25</b>: high compression<p>" + "<b>50</b>: medium compression<p>" + "<b>75</b>: low compression (default value)<p>" + "<b>100</b>: no compression"); + + QWhatsThis::add( m_PNGCompression, whatsThis); + m_label_PNGimageCompression->setBuddy( m_PNGCompression ); + + dvlay->addWidget( groupBox2 ); + + // TIFF File format. + + QGroupBox * groupBox3 = new QGroupBox( 2, Qt::Horizontal, i18n("TIFF File Format"), box ); + + m_label_TIFFimageCompression = new QLabel (i18n("Image compression algorithm:"), groupBox3); + m_TIFFCompressionAlgo = new QComboBox( false, groupBox3 ); + m_TIFFCompressionAlgo->insertItem("LZW"); + m_TIFFCompressionAlgo->insertItem("JPEG"); + m_TIFFCompressionAlgo->insertItem(i18n("None")); + QWhatsThis::add( m_TIFFCompressionAlgo, i18n("<p>Select here the TIFF compression algorithm.") ); + m_label_TIFFimageCompression->setBuddy( m_TIFFCompressionAlgo ); + + dvlay->addWidget( groupBox3 ); + + // TGA File format. + + QGroupBox * groupBox4 = new QGroupBox( 2, Qt::Horizontal, i18n("TGA File Format"), box ); + + m_label_TGAimageCompression = new QLabel (i18n("Image compression algorithm:"), groupBox4); + m_TGACompressionAlgo = new QComboBox( false, groupBox4 ); + m_TGACompressionAlgo->insertItem("RLE"); + m_TGACompressionAlgo->insertItem(i18n("None")); + QWhatsThis::add( m_TGACompressionAlgo, i18n("<p>Select here the TGA compression algorithm.") ); + m_label_TGAimageCompression->setBuddy( m_TGACompressionAlgo ); + + dvlay->addWidget( groupBox4 ); +} + +RecompressOptionsDialog::~RecompressOptionsDialog() +{ +} + +void RecompressOptionsDialog::slotCompressLossLessEnabled(bool val) +{ + m_JPEGCompression->setEnabled( !val ); + m_label_JPEGimageCompression->setEnabled( !val ); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/recompressoptionsdialog.h b/kipi-plugins/batchprocessimages/recompressoptionsdialog.h new file mode 100644 index 0000000..4e5828c --- /dev/null +++ b/kipi-plugins/batchprocessimages/recompressoptionsdialog.h @@ -0,0 +1,67 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef RECOMPRESSOPTIONSDIALOG_H +#define RECOMPRESSOPTIONSDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +class QLabel; +class QCheckBox; +class QComboBox; + +class KIntNumInput; + +namespace KIPIBatchProcessImagesPlugin +{ + +class RecompressOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + RecompressOptionsDialog(QWidget *parent=0); + ~RecompressOptionsDialog(); + + QLabel *m_label_JPEGimageCompression; + QLabel *m_label_PNGimageCompression; + QLabel *m_label_TIFFimageCompression; + QLabel *m_label_TGAimageCompression; + KIntNumInput *m_JPEGCompression; + KIntNumInput *m_PNGCompression; + QCheckBox *m_compressLossLess; + QComboBox *m_TIFFCompressionAlgo; + QComboBox *m_TGACompressionAlgo; + + public slots: + void slotCompressLossLessEnabled(bool val); +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // RECOMPRESSOPTIONSDIALOG_H diff --git a/kipi-plugins/batchprocessimages/renameimagesbase.ui b/kipi-plugins/batchprocessimages/renameimagesbase.ui new file mode 100644 index 0000000..a85fae5 --- /dev/null +++ b/kipi-plugins/batchprocessimages/renameimagesbase.ui @@ -0,0 +1,359 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>KIPIBatchProcessImagesPlugin::RenameImagesBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>RenameImagesBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>570</width> + <height>556</height> + </rect> + </property> + <property name="caption"> + <string>RenameImagesBase</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>m_templateGroupBox</cstring> + </property> + <property name="title"> + <string>Template for renaming files</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_seqLabel</cstring> + </property> + <property name="text"> + <string>Sequence number start value:</string> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>m_prefixEdit</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_prefixLabel</cstring> + </property> + <property name="text"> + <string>Prefix string:</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_addFileNameCheck</cstring> + </property> + <property name="text"> + <string>Add original file name</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_addFileDateCheck</cstring> + </property> + <property name="text"> + <string>Add file date</string> + </property> + </widget> + <widget class="QLineEdit" row="4" column="1"> + <property name="name"> + <cstring>m_formatDateEdit</cstring> + </property> + </widget> + <widget class="QLayoutWidget" row="4" column="0"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>12</width> + <height>14</height> + </size> + </property> + </spacer> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_formatDateCheck</cstring> + </property> + <property name="text"> + <string>Date format:</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="1" column="1"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSpinBox"> + <property name="name"> + <cstring>m_seqSpin</cstring> + </property> + <property name="maxValue"> + <number>999999</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>261</width> + <height>21</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>m_addRemoveBox</cstring> + </property> + <property name="title"> + <string></string> + </property> + <property name="alignment"> + <set>AlignTop|AlignHCenter</set> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="0" column="1"> + <property name="name"> + <cstring>m_addButton</cstring> + </property> + <property name="text"> + <string>Add</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_removeButton</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + <widget class="KListView" row="0" column="0" rowspan="10" colspan="1"> + <column> + <property name="text"> + <string>Album</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Source Image</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Target Image</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Result</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_listView</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + <property name="dragEnabled"> + <bool>true</bool> + </property> + </widget> + <spacer row="9" column="1"> + <property name="name"> + <cstring>spacer25</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>175</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="8" column="1"> + <property name="name"> + <cstring>m_reverseList</cstring> + </property> + <property name="text"> + <string>Reverse List</string> + </property> + </widget> + <spacer row="6" column="1"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>19</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="7" column="1"> + <property name="name"> + <cstring>m_sortButton</cstring> + </property> + <property name="text"> + <string>Sort List</string> + </property> + </widget> + <widget class="QPushButton" row="5" column="1"> + <property name="name"> + <cstring>m_moveDown</cstring> + </property> + <property name="text"> + <string>Move &Down</string> + </property> + </widget> + <widget class="QPushButton" row="4" column="1"> + <property name="name"> + <cstring>m_moveUp</cstring> + </property> + <property name="text"> + <string>Move &Up</string> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>m_pixLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>96</width> + <height>96</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer row="3" column="1"> + <property name="name"> + <cstring>spacer3_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>19</height> + </size> + </property> + </spacer> + </grid> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="6"/> +<includehints> + <includehint>klistview.h</includehint> +</includehints> +</UI> diff --git a/kipi-plugins/batchprocessimages/renameimagesdialog.cpp b/kipi-plugins/batchprocessimages/renameimagesdialog.cpp new file mode 100644 index 0000000..059bb4d --- /dev/null +++ b/kipi-plugins/batchprocessimages/renameimagesdialog.cpp @@ -0,0 +1,94 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2003-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.net> + * + * 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. + * + * ============================================================ */ + +// Qt includes. + +#include <qlayout.h> +#include <qpushbutton.h> + +// KDE includes. + +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes. + +#include "kpaboutdata.h" +#include "pluginsversion.h" +#include "renameimageswidget.h" +#include "renameimagesdialog.h" +#include "renameimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +RenameImagesDialog::RenameImagesDialog(const KURL::List& images, + KIPI::Interface* interface, + QWidget* parent) + : KDialogBase( KDialogBase::Plain, "Rename Images", Help|User1|Close, + Close, parent, "RenameImages", + false, false, i18n("&Start")) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch-rename images"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin to batch-rename images"), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + QPushButton* helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + helpButton->setPopup( helpMenu->menu() ); + + // gui + + QWidget* box = plainPage(); + QVBoxLayout* lay = new QVBoxLayout(box); + m_widget = new RenameImagesWidget(box, interface, images); + lay->addWidget(m_widget); + + connect(this, SIGNAL(user1Clicked()), + m_widget, SLOT(slotStart())); + + adjustSize(); +} + +RenameImagesDialog::~RenameImagesDialog() +{ + delete m_about; +} + +void RenameImagesDialog::slotHelp(void) +{ + kapp->invokeHelp("renameimages", "kipi-plugins"); +} + +} // namespace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/renameimagesdialog.h b/kipi-plugins/batchprocessimages/renameimagesdialog.h new file mode 100644 index 0000000..696dea5 --- /dev/null +++ b/kipi-plugins/batchprocessimages/renameimagesdialog.h @@ -0,0 +1,70 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2003-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.net> + * + * 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. + * + * ============================================================ */ + +#ifndef RENAMEIMAGESDLG_H +#define RENAMEIMAGESDLG_H + +// KDE includes. + +#include <kdialogbase.h> +#include <kurl.h> + +// Local includes + +#include "kpaboutdata.h" + +namespace KIPI +{ +class Interface; +} + +namespace KIPIBatchProcessImagesPlugin +{ + +class RenameImagesWidget; + +class RenameImagesDialog : public KDialogBase +{ + Q_OBJECT + +public: + + RenameImagesDialog(const KURL::List& images, + KIPI::Interface* interface, + QWidget* parent); + ~RenameImagesDialog(); + +private: + + RenameImagesWidget* m_widget; + + KIPIPlugins::KPAboutData* m_about; + +private slots: + + void slotHelp(); +}; + +} + +#endif /* RENAMEIMAGESDIALOG_H */ diff --git a/kipi-plugins/batchprocessimages/renameimageswidget.cpp b/kipi-plugins/batchprocessimages/renameimageswidget.cpp new file mode 100644 index 0000000..f295239 --- /dev/null +++ b/kipi-plugins/batchprocessimages/renameimageswidget.cpp @@ -0,0 +1,553 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2003-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.net> + * + * 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. + * + * ============================================================ */ + +// C Ansi includes. + +extern "C" +{ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +} + +// C++ includes. + +#include <cstdio> +#include <ctime> + +// Qt includes. + +#include <qlistview.h> +#include <qlineedit.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qtimer.h> +#include <qprogressdialog.h> +#include <qgroupbox.h> +#include <qpopupmenu.h> + +// KDE includes. + +#include <klocale.h> +#include <kconfig.h> +#include <kio/previewjob.h> +#include <kio/renamedlg.h> +#include <kdebug.h> +#include <kdeversion.h> + +// Libkipi includes. + +#include <libkipi/interface.h> +#include <libkipi/imageinfo.h> +#include <libkipi/imagedialog.h> + +// Local includes. + +#include "batchprocessimagesitem.h" +#include "renameimageswidget.h" +#include "renameimageswidget.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +RenameImagesWidget::RenameImagesWidget(QWidget *parent, + KIPI::Interface* interface, + const KURL::List& urlList) + : RenameImagesBase(parent), + m_interface(interface), + m_urlList(urlList) +{ + m_listView->setSorting(-1); +#if KDE_IS_VERSION(3,4,0) + // next can be done directly into designer but it seems not to compile + // under kde < 3.4.0 + m_listView->setShadeSortColumn( FALSE ); +#endif + + readSettings(); + + QPopupMenu* sortMenu = new QPopupMenu(this); + sortMenu->insertItem(i18n("Sort by Name"), BYNAME); + sortMenu->insertItem(i18n("Sort by Size"), BYSIZE); + sortMenu->insertItem(i18n("Sort by Date"), BYDATE); + m_sortButton->setPopup(sortMenu); + + connect(m_listView, SIGNAL(doubleClicked(QListViewItem*)), + SLOT(slotListViewDoubleClicked(QListViewItem*))); + connect(m_listView, SIGNAL(selectionChanged(QListViewItem*)), + SLOT(slotImageSelected(QListViewItem*))); + + connect(m_prefixEdit, SIGNAL(textChanged(const QString&)), + SLOT(slotOptionsChanged())); + connect(m_seqSpin, SIGNAL(valueChanged(int)), + SLOT(slotOptionsChanged())); + connect(m_addFileNameCheck, SIGNAL(toggled(bool)), + SLOT(slotOptionsChanged())); + connect(m_addFileDateCheck, SIGNAL(toggled(bool)), + SLOT(slotOptionsChanged())); + connect(m_formatDateCheck, SIGNAL(toggled(bool)), + SLOT(slotOptionsChanged())); + connect(m_formatDateEdit, SIGNAL(textChanged(const QString&)), + SLOT(slotOptionsChanged())); + + connect(m_addButton, SIGNAL(clicked()), + SLOT(slotAddImages())); + connect(m_removeButton, SIGNAL(clicked()), + SLOT(slotRemoveImage())); + + connect(sortMenu, SIGNAL(activated(int)), + SLOT(sortList(int)) ); + + connect(m_reverseList, SIGNAL(clicked()), + SLOT(reverseList()) ); + + connect(m_moveUp, SIGNAL(clicked()), + SLOT(moveCurrentItemUp()) ); + + connect(m_moveDown, SIGNAL(clicked()), + SLOT(moveCurrentItemDown()) ); + + m_timer = new QTimer(this); + m_progress = new QProgressDialog(this, 0, true); + connect(m_timer, SIGNAL(timeout()), + SLOT(slotNext())); + connect(m_progress, SIGNAL(canceled()), + SLOT(slotAbort())); + + for (KURL::List::iterator it = m_urlList.begin(); + it != m_urlList.end(); ++it) + { + new BatchProcessImagesItem(m_listView, + (*it).path().section('/', 0, -1), + (*it).filename(), + QString(), + QString()); + } + + updateListing(); +} + +RenameImagesWidget::~RenameImagesWidget() +{ + delete m_timer; + delete m_progress; + + saveSettings(); +} + +void RenameImagesWidget::readSettings() +{ + KConfig config("kipirc"); + config.setGroup("RenameImages Settings"); + + m_prefixEdit->setText(config.readEntry("PrefixString", "")); + m_seqSpin->setValue(config.readNumEntry("FirstRenameValue", 1)); + + m_addFileNameCheck->setChecked(config.readBoolEntry("AddOriginalFileName", false)); + m_addFileDateCheck->setChecked(config.readBoolEntry("AddImageFileDate", false)); + m_formatDateCheck->setChecked(config.readBoolEntry("FormatDate", false)); + m_formatDateEdit->setText(config.readEntry("FormatDateString", "%Y-%m-%d")); + + slotOptionsChanged(); +} + +void RenameImagesWidget::saveSettings() +{ + KConfig config("kipirc"); + config.setGroup("RenameImages Settings"); + + config.writeEntry("PrefixString", m_prefixEdit->text()); + config.writeEntry("FirstRenameValue", m_seqSpin->value()); + + config.writeEntry("AddOriginalFileName", m_addFileNameCheck->isChecked()); + config.writeEntry("AddImageFileDate", m_addFileDateCheck->isChecked()); + config.writeEntry("FormatDate", m_formatDateCheck->isChecked()); + config.writeEntry("FormatDateString", m_formatDateEdit->text()); + + config.sync(); +} + +void RenameImagesWidget::slotOptionsChanged() +{ + m_formatDateCheck->setEnabled(m_addFileDateCheck->isChecked()); + m_formatDateEdit->setEnabled(m_formatDateCheck->isEnabled() && + m_formatDateCheck->isChecked()); + + updateListing(); +} + +void RenameImagesWidget::slotListViewDoubleClicked(QListViewItem*) +{ + // TODO: Implement +} + +void RenameImagesWidget::slotImageSelected(QListViewItem* item) +{ + if (!item) + { + m_removeButton->setEnabled(false); + return; + } + + m_removeButton->setEnabled(true); + m_pixLabel->clear(); + + BatchProcessImagesItem* it = static_cast<BatchProcessImagesItem*>(item); + KIO::PreviewJob* thumbJob = KIO::filePreview(KURL(it->pathSrc()), + m_pixLabel->height() ); + + connect(thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)), + SLOT(slotGotPreview(const KFileItem*, const QPixmap&))); +} + + +void RenameImagesWidget::sortList(int intSortOrder) +{ + SortOrder sortOrder = static_cast<SortOrder>(intSortOrder); + + for (QListViewItem* it = m_listView->firstChild(); it; + it = it->nextSibling()) + { + BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it); + + switch (sortOrder) + { + case(BYNAME): + { + item->setKey(item->text(1), false); + break; + } + case(BYSIZE): + { + QFileInfo fi(item->pathSrc()); + item->setKey(QString::number(fi.size()), false); + break; + } + case(BYDATE): + { + KURL url(item->pathSrc()); + KIPI::ImageInfo info = m_interface->info(url); + item->setKey(info.time().toString(Qt::ISODate), false); + break; + } + } + }; + + // Update list order. We need to set the sorting column temporarily + // otherwise sort() won't do anything + m_listView->setSorting(1); + m_listView->sort(); + m_listView->setSorting(-1); + + updateListing(); +} + + +void RenameImagesWidget::reverseList() +{ + if (m_listView->childCount() < 2) return; + + QListViewItem* lastItem = m_listView->lastItem(); + + while (m_listView->firstChild() != lastItem) { + m_listView->firstChild()->moveItem(lastItem); + } + + updateListing(); +} + + +void RenameImagesWidget::moveCurrentItemUp() { + QListViewItem* currentItem = m_listView->currentItem(); + if (!currentItem) return; + + for (QListViewItem* previousItem = m_listView->firstChild(); previousItem; + previousItem = previousItem->nextSibling()) + { + if (previousItem->nextSibling() == currentItem) { + previousItem->moveItem(currentItem); + break; + } + } + + updateListing(); +} + + +void RenameImagesWidget::moveCurrentItemDown() { + QListViewItem* currentItem = m_listView->currentItem(); + if (!currentItem) return; + + QListViewItem* nextItem = currentItem->nextSibling(); + if (nextItem) { + currentItem->moveItem(nextItem); + } + + updateListing(); +} + + +void RenameImagesWidget::updateListing() +{ + int pos = 0; + for (QListViewItem* it = m_listView->firstChild(); it; + it = it->nextSibling()) + { + BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it); + item->changeNameDest(oldToNewName(item, pos)); + item->changeResult(QString()); + item->changeError(QString()); + item->changeOutputMess(QString()); + pos++; + } +} + +QString RenameImagesWidget::oldToNewName(BatchProcessImagesItem* item, + int itemPosition) +{ + KURL url; + url.setPath(item->pathSrc()); + + QFileInfo fi(item->pathSrc()); + + KIPI::ImageInfo info = m_interface->info(url); + + QString newName = m_prefixEdit->text(); + + if (m_addFileNameCheck->isChecked()) + { + newName += fi.baseName(); + newName += "_"; + } + + if (m_addFileDateCheck->isChecked()) + { + QString format = m_formatDateEdit->text(); + format = format.simplifyWhiteSpace(); + format.replace("%%","%"); + format.replace("%s",""); + format.replace("/", ""); + + time_t time = info.time().toTime_t(); + struct tm* time_tm = ::localtime(&time); + char s[100]; + ::strftime(s, 100, QFile::encodeName(format), time_tm); + + newName += QString::fromLatin1(s); + newName += "_"; + } + + int count = m_listView->childCount(); + int numDigits = 1; + while (count > 0) + { + numDigits++; + count = count / 10; + } + + QString format; + format.sprintf("0%dd", numDigits); + format = "%" + format; + + QString seq; + seq.sprintf(format.latin1(), itemPosition + m_seqSpin->value()); + newName += seq; + + newName += QString::fromLatin1(".") + fi.extension(); + + return newName; +} + +void RenameImagesWidget::slotGotPreview(const KFileItem*, const QPixmap& pix) +{ + m_pixLabel->setPixmap(pix); +} + +void RenameImagesWidget::slotStart() +{ + m_timer->start(0, true); + + m_listView->setSelected(m_listView->firstChild(), true); + m_listView->ensureItemVisible(m_listView->firstChild()); + + m_progress->setTotalSteps(m_listView->childCount()); + m_progress->setProgress(0); + m_progress->show(); + + m_overwriteAll = false; + m_autoSkip = false; +} + +void RenameImagesWidget::slotAbort() +{ + m_timer->stop(); + m_progress->reset(); + m_progress->hide(); +} + +void RenameImagesWidget::slotNext() +{ + QListViewItem* it = m_listView->selectedItem(); + if (!it) + { + slotAbort(); + return; + } + + BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it); + KURL src; + src.setPath(item->pathSrc()); + KURL dst = src.upURL(); + dst.addPath(item->text(2)); + + bool skip = false; + bool overwrite = false; + + if (!m_overwriteAll) + { + struct stat info; + while (::stat(QFile::encodeName(dst.path()), &info) == 0) + { + if (m_autoSkip) + { + skip = true; + break; + } + + KIO::RenameDlg dlg(this, i18n("Rename File"), src.path(), dst.path(), + KIO::RenameDlg_Mode(KIO::M_MULTI | + KIO::M_OVERWRITE | + KIO::M_SKIP)); + int result = dlg.exec(); + dst = dlg.newDestURL(); + + switch (result) + { + case KIO::R_CANCEL: + { + slotAbort(); + return; + } + case KIO::R_SKIP: + { + skip = true; + break; + } + case KIO::R_AUTO_SKIP: + { + m_autoSkip = true; + skip = true; + break; + } + case KIO::R_OVERWRITE: + { + overwrite = true; + break; + } + case KIO::R_OVERWRITE_ALL: + { + m_overwriteAll = true; + overwrite = true; + break; + } + default: + break; + } + + if (skip || overwrite) + break; + } + } + + if (skip) + { + item->changeResult(i18n("Skipped")); + } + else + { + // Get the src info + KIPI::ImageInfo srcInfo = m_interface->info(src); + + if (::rename(QFile::encodeName(src.path()), + QFile::encodeName(dst.path())) == 0) + { + srcInfo.setTitle(dst.filename()); + + item->changeResult(i18n("OK")); + } + else + { + item->changeResult(i18n("Failed")); + } + } + + m_progress->setProgress(m_progress->progress() + 1); + + if (it->nextSibling()) + { + m_listView->setSelected(it->nextSibling(), true); + m_listView->ensureItemVisible(it->nextSibling()); + m_timer->start(0, true); + } +} + +void RenameImagesWidget::slotAddImages() +{ + KURL::List urls = KIPI::ImageDialog::getImageURLs(this, m_interface); + + for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it) + { + if (m_urlList.contains(*it)) + continue; + + new BatchProcessImagesItem(m_listView, + (*it).path().section('/', 0, -1), + (*it).filename(), + QString(), + QString()); + m_urlList.append(*it); + } + + updateListing(); +} + +void RenameImagesWidget::slotRemoveImage() +{ + if (!m_listView->selectedItem()) + return; + + BatchProcessImagesItem* item = + static_cast<BatchProcessImagesItem*>(m_listView->selectedItem()); + delete item; + + m_pixLabel->clear(); + + updateListing(); +} + +} // namespace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/renameimageswidget.h b/kipi-plugins/batchprocessimages/renameimageswidget.h new file mode 100644 index 0000000..9c64013 --- /dev/null +++ b/kipi-plugins/batchprocessimages/renameimageswidget.h @@ -0,0 +1,107 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2003-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.net> + * + * 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. + * + * ============================================================ */ + +#ifndef RENAMEIMAGESWIDGET_H +#define RENAMEIMAGESWIDGET_H + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "renameimagesbase.h" + +class KFileItem; +class QTimer; +class QProgressDialog; + +namespace KIPI +{ +class Interface; +} + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class RenameImagesWidget : public RenameImagesBase +{ + Q_OBJECT + +public: + + enum SortOrder + { + BYNAME = 0, + BYSIZE, + BYDATE + }; + + RenameImagesWidget(QWidget *parent, KIPI::Interface* interface, + const KURL::List& urlList); + ~RenameImagesWidget(); + +private: + + void readSettings(); + void saveSettings(); + void reListImages(); + void updateListing(); + QString oldToNewName(BatchProcessImagesItem* item, + int itemPosition); + + KIPI::Interface* m_interface; + KURL::List m_urlList; + QTimer* m_timer; + QProgressDialog* m_progress; + bool m_overwriteAll; + bool m_autoSkip; + +public slots: + + void slotStart(); + void slotAbort(); + void slotNext(); + +private slots: + + void slotListViewDoubleClicked(QListViewItem*); + void slotImageSelected(QListViewItem*); + void slotOptionsChanged(); + void slotGotPreview(const KFileItem*, const QPixmap&); + + void slotAddImages(); + void slotRemoveImage(); + + void sortList(int); + void reverseList(); + + void moveCurrentItemUp(); + void moveCurrentItemDown(); +}; + +} + +#endif /* RENAMEIMAGESWIDGET_H */ diff --git a/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp b/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp new file mode 100644 index 0000000..36b912d --- /dev/null +++ b/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp @@ -0,0 +1,575 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qimage.h> + +// Include files for KDE + +#include <klocale.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <knuminput.h> +#include <kprocess.h> +#include <kcolorbutton.h> +#include <kapplication.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kpopupmenu.h> + +// Local includes + +#include "kpaboutdata.h" +#include "pluginsversion.h" +#include "resizeoptionsdialog.h" +#include "outputdialog.h" +#include "resizeimagesdialog.h" +#include "resizeimagesdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +ResizeImagesDialog::ResizeImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent ) + : BatchProcessImagesDialog( urlList, interface, i18n("Batch Resize Images"), parent ) +{ + // About data and help button. + + m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch resize images"), + 0, + KAboutData::License_GPL, + I18N_NOOP("A Kipi plugin to batch-resize images\n" + "This plugin uses the \"convert\" program from \"ImageMagick\" package."), + "(c) 2003-2007, Gilles Caulier"); + + m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"), + "caulier dot gilles at gmail dot com"); + + m_helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0); + m_helpButton->setPopup( helpMenu->menu() ); + + //--------------------------------------------- + + m_nbItem = m_selectedImageFiles.count(); + + //--------------------------------------------- + + groupBox1->setTitle( i18n("Image Resizing Options") ); + + m_labelType->setText( i18n("Type:") ); + + m_Type->insertItem(i18n("Proportional (1 dim.)")); // 0 + m_Type->insertItem(i18n("Proportional (2 dim.)")); // 1 + m_Type->insertItem(i18n("Non-Proportional")); // 2 + m_Type->insertItem(i18n("Prepare to Print")); // 3 + m_Type->setCurrentText(i18n("Proportional (1 dim.)")); + whatsThis = i18n("<p>Select here the image-resize type."); + whatsThis = whatsThis + i18n("<p><b>Proportional (1 dim.)</b>: standard auto-resizing using one dimension. " + "The width or the height of the images will be automatically " + "selected, depending on the images' orientations. " + "The images' aspect ratios are preserved."); + whatsThis = whatsThis + i18n("<p><b>Proportional (2 dim.)</b>: auto-resizing using two dimensions. " + "The images' aspect ratio are preserved. You can use this, for example, " + "to adapt your images' sizes to your screen size."); + whatsThis = whatsThis + i18n("<p><b>Non proportional</b>: non-proportional resizing using two dimensions. " + "The images' aspect ratios are not preserved."); + whatsThis = whatsThis + i18n("<p><b>Prepare to print</b>: prepare the image for photographic printing. " + "The user can set the print resolution and the photographic paper size. " + "The target images will be adapted to the specified dimensions " + "(included the background size, margin size, and background color)."); + + QWhatsThis::add( m_Type, whatsThis ); + + m_previewButton->hide(); + m_smallPreview->hide(); + + //--------------------------------------------- + + readSettings(); + listImageFiles(); +} + +ResizeImagesDialog::~ResizeImagesDialog() +{ + delete m_about; +} + +void ResizeImagesDialog::slotHelp( void ) +{ + KApplication::kApplication()->invokeHelp("resizeimages", "kipi-plugins"); +} + +void ResizeImagesDialog::slotOptionsClicked(void) +{ + int Type = m_Type->currentItem(); + ResizeOptionsDialog *optionsDialog = new ResizeOptionsDialog(this, Type); + + if (Type == 0) // Proportional (1 dim.) + { + optionsDialog->m_quality->setValue(m_quality); + optionsDialog->m_size->setValue(m_size); + optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter); + } + if (Type == 1) // Proportional (2 dim.) + { + optionsDialog->m_quality->setValue(m_quality); + optionsDialog->m_Width->setValue(m_Width); + optionsDialog->m_Height->setValue(m_Height); + optionsDialog->m_button_bgColor->setColor(m_bgColor); + optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter); + optionsDialog->m_Border->setValue(m_Border); + } + if (Type == 2) // Non-proportional + { + optionsDialog->m_quality->setValue(m_quality); + optionsDialog->m_fixedWidth->setValue(m_fixedWidth); + optionsDialog->m_fixedHeight->setValue(m_fixedHeight); + optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter); + } + if (Type == 3) // Prepare to print + { + optionsDialog->m_quality->setValue(m_quality); + optionsDialog->m_paperSize->setCurrentText(m_paperSize); + optionsDialog->m_printDpi->setCurrentText(m_printDpi); + optionsDialog->m_customXSize->setValue(m_customXSize); + optionsDialog->m_customYSize->setValue(m_customYSize); + optionsDialog->m_customDpi->setValue(m_customDpi); + optionsDialog->m_button_backgroundColor->setColor(m_backgroundColor); + optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter); + optionsDialog->m_marging->setValue(m_marging); + optionsDialog->m_customSettings->setChecked(m_customSettings); + } + + if ( optionsDialog->exec() == KMessageBox::Ok ) + { + if (Type == 0) // Proportional (1 dim.) + { + m_quality = optionsDialog->m_quality->value(); + m_size = optionsDialog->m_size->value(); + m_resizeFilter = optionsDialog->m_resizeFilter->currentText(); + } + if (Type == 1) // Proportional (2 dim.) + { + m_quality = optionsDialog->m_quality->value(); + m_Width = optionsDialog->m_Width->value(); + m_Height = optionsDialog->m_Height->value(); + m_bgColor = optionsDialog->m_button_bgColor->color(); + m_resizeFilter = optionsDialog->m_resizeFilter->currentText(); + m_Border = optionsDialog->m_Border->value(); + } + if (Type == 2) // Non-proportional + { + m_quality = optionsDialog->m_quality->value(); + m_fixedWidth = optionsDialog->m_fixedWidth->value(); + m_fixedHeight = optionsDialog->m_fixedHeight->value(); + m_resizeFilter = optionsDialog->m_resizeFilter->currentText(); + } + if (Type == 3) // Prepare to print + { + m_quality = optionsDialog->m_quality->value(); + m_paperSize = optionsDialog->m_paperSize->currentText(); + m_printDpi = optionsDialog->m_printDpi->currentText(); + m_customXSize = optionsDialog->m_customXSize->value(); + m_customYSize = optionsDialog->m_customYSize->value(); + m_customDpi = optionsDialog->m_customDpi->value(); + m_backgroundColor = optionsDialog->m_button_backgroundColor->color(); + m_resizeFilter = optionsDialog->m_resizeFilter->currentText(); + m_marging = optionsDialog->m_marging->value(); + m_customSettings = optionsDialog->m_customSettings->isChecked(); + } + } + + delete optionsDialog; +} + +void ResizeImagesDialog::readSettings(void) +{ + // Read all settings from configuration file. + + QColor *ColorWhite = new QColor( 255, 255, 255 ); + QColor *ColorBlack = new QColor( 0, 0, 0 ); + m_config = new KConfig("kipirc"); + m_config->setGroup("ResizeImages Settings"); + + m_Type->setCurrentItem(m_config->readNumEntry("ResiseType", 3)); // Prepare to print per default. + m_size = m_config->readNumEntry("Size", 640); + m_resizeFilter = m_config->readEntry("ResizeFilter", "Lanczos"); + + m_paperSize = m_config->readEntry("PaperSize", "10x15"); + m_printDpi = m_config->readEntry("PrintDpi", "300"); + m_customXSize = m_config->readNumEntry("CustomXSize", 10); + m_customYSize = m_config->readNumEntry("CustomYSize", 15); + m_customDpi = m_config->readNumEntry("CustomDpi", 300); + m_backgroundColor = m_config->readColorEntry("BackgroundColor", ColorWhite); + m_marging = m_config->readNumEntry("MargingSize", 10); + + + m_quality = m_config->readNumEntry("Quality", 75); + m_Width = m_config->readNumEntry("Width", 1024); + m_Height = m_config->readNumEntry("Height", 768); + m_Border = m_config->readNumEntry("Border", 100); + m_bgColor = m_config->readColorEntry("BgColor", ColorBlack); + + m_fixedWidth = m_config->readNumEntry("FixedWidth", 640); + m_fixedHeight = m_config->readNumEntry("FixedHeight", 480); + + if ( m_config->readEntry("CustomSettings", "false") == "true") + m_customSettings = true; + else + m_customSettings = false; + + m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default... + + if (m_config->readEntry("RemoveOriginal", "false") == "true") + m_removeOriginal->setChecked( true ); + else + m_removeOriginal->setChecked( false ); + + delete ColorWhite; + delete ColorBlack; + delete m_config; +} + +void ResizeImagesDialog::saveSettings(void) +{ + // Write all settings in configuration file. + + m_config = new KConfig("kipirc"); + m_config->setGroup("ResizeImages Settings"); + m_config->writeEntry("ResiseType", m_Type->currentItem()); + m_config->writeEntry("Size", m_size); + m_config->writeEntry("ResizeFilter", m_resizeFilter); + + m_config->writeEntry("PaperSize", m_paperSize); + m_config->writeEntry("PrintDpi", m_printDpi); + m_config->writeEntry("CustomXSize", m_customXSize); + m_config->writeEntry("CustomYSize", m_customYSize); + m_config->writeEntry("CustomDpi", m_customDpi); + m_config->writeEntry("BackgroundColor", m_backgroundColor); + m_config->writeEntry("MargingSize", m_marging); + m_config->writeEntry("CustomSettings", m_customSettings); + + m_config->writeEntry("Quality", m_quality); + m_config->writeEntry("Width", m_Width); + m_config->writeEntry("Height", m_Height); + m_config->writeEntry("Border", m_Border); + m_config->writeEntry("BgColor", m_bgColor); + + m_config->writeEntry("FixedWidth", m_fixedWidth); + m_config->writeEntry("FixedHeight", m_fixedHeight); + + m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem()); + m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked()); + + m_config->sync(); + + delete m_config; +} + +QString ResizeImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool ) +{ + QImage img; + + img.load( item->pathSrc() ); + + // Get image information. + + int w = img.width(); + int h = img.height(); + + int Type = m_Type->currentItem(); + bool IncDec; + int MargingSize; + + if (Type == 0) // Proportional (1 dim.) + { + *proc << "convert"; + IncDec = ResizeImage( w, h, m_size); + + *proc << "-resize"; + QString Temp, Temp2; + Temp2 = Temp.setNum( w ) + "x"; + Temp2.append(Temp.setNum( h )); + *proc << Temp2; + + *proc << "-quality"; + QString Temp3; + Temp3.setNum(m_quality); + *proc << Temp3; + + if ( IncDec == true ) // If the image is increased, enabled the filter. + { + *proc << "-filter" << m_resizeFilter; + } + + *proc << "-verbose"; + *proc << item->pathSrc() + "[0]"; + *proc << albumDest + "/" + item->nameDest(); + } + + if (Type == 1) // Proportional (2 dim.) + { + QString targetBackgroundSize; + int ResizeCoeff; + *proc << "composite"; + + // Get the target image resizing dimensions with using the target size. + + if ( m_Width < m_Height ) // Vertically resizing + { + if ( w < h ) // Original size vertically oriented. + ResizeCoeff = m_Height; + else // Original size horizontally oriented. + ResizeCoeff = m_Width; + } + else // Horizontally resizing + { + if ( w < h ) // Original size vertically oriented. + ResizeCoeff = m_Height; + else // Original size horizontally oriented. + ResizeCoeff = m_Width; + } + + IncDec = ResizeImage( w, h, ResizeCoeff - m_Border); + targetBackgroundSize = QString::number(m_Width) + "x" + QString::number(m_Height); + + *proc << "-verbose" << "-gravity" << "Center"; + + *proc << "-resize"; + QString Temp, Temp2; + Temp2 = Temp.setNum( w ) + "x"; + Temp2.append(Temp.setNum( h )); + *proc << Temp2; + + *proc << "-quality"; + QString Temp3; + Temp3.setNum(m_quality); + *proc << Temp3; + + if ( IncDec == true ) // If the image is increased, enabled the filter. + { + *proc << "-filter" << m_resizeFilter; + } + + *proc << item->pathSrc() + "[0]"; + + // ImageMagick composite program do not preserve exif data from original. + // Need to use "-profile" option for that. + + *proc << "-profile" << item->pathSrc(); + + Temp2 = "xc:rgb(" + Temp.setNum(m_bgColor.red()) + ","; + Temp2.append(Temp.setNum(m_bgColor.green()) + ","); + Temp2.append(Temp.setNum(m_bgColor.blue()) + ")"); + *proc << Temp2; + + *proc << "-resize" << targetBackgroundSize + "!"; + + *proc << albumDest + "/" + item->nameDest(); + } + + if (Type == 2) // Non-proportional + { + *proc << "convert"; + + *proc << "-resize"; + QString Temp, Temp2; + Temp2 = Temp.setNum( m_fixedWidth ) + "x"; + Temp2.append(Temp.setNum( m_fixedHeight ) + "!"); + *proc << Temp2; + + if ( m_fixedWidth > w || m_fixedHeight > h ) // If the image is increased, enabled the filter. + { + *proc << "-filter" << m_resizeFilter; + } + + *proc << "-quality"; + QString Temp3; + Temp3.setNum(m_quality); + *proc << Temp3; + + *proc << "-verbose"; + *proc << item->pathSrc() + "[0]"; + *proc << albumDest + "/" + item->nameDest(); + } + + if (Type == 3) // Prepare to print + { + if ( m_customSettings == true ) + { + MargingSize = (int)((float)(m_marging * m_customDpi) / (float)(25.4)); + + if (w < h) // (w < h) because all paper dimensions are vertically gived ! + { + m_xPixels = (int)( (float)(m_customXSize * m_customDpi) / (float)(2.54) ); + m_yPixels = (int)( (float)(m_customYSize * m_customDpi) / (float)(2.54) ); + } + else + { + m_yPixels = (int)( (float)(m_customXSize * m_customDpi) / (float)(2.54) ); + m_xPixels = (int)( (float)(m_customYSize * m_customDpi) / (float)(2.54) ); + } + } + else + { + QString Temp = m_printDpi; + int Dpi = Temp.toInt(); + MargingSize = (int)((float)(m_marging * Dpi) / (float)(25.4)); + + if (w < h) // (w < h) because all paper dimensions are vertically given ! + { + Temp = m_paperSize.left(m_paperSize.find('x')); + m_xPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) ); + Temp = m_paperSize.right(m_paperSize.find('x')); + m_yPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) ); + } + else + { + Temp = m_paperSize.left(m_paperSize.find('x')); + m_yPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) ); + Temp = m_paperSize.right(m_paperSize.find('x')); + m_xPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) ); + } + } + + QString targetBackgroundSize; + int ResizeCoeff; + float RFactor; + *proc << "composite"; + + // Get the target image resizing dimensions with using the target paper size. + + if (m_xPixels < m_yPixels) + { + RFactor = (float)m_xPixels / (float)w; + if (RFactor > 1.0) RFactor = (float)m_yPixels / (float)h; + ResizeCoeff = (int)((float)h * RFactor); + } + else + { + RFactor = (float)m_yPixels / (float)h; + if (RFactor > 1.0) RFactor = (float)m_xPixels / (float)w; + ResizeCoeff = (int)((float)w * RFactor); + } + + IncDec = ResizeImage( w, h, ResizeCoeff - MargingSize); + targetBackgroundSize = QString::number(m_xPixels) + "x" + QString::number(m_yPixels); + + *proc << "-verbose" << "-gravity" << "Center"; + + *proc << "-resize"; + QString Temp, Temp2; + Temp2 = Temp.setNum( w ) + "x"; + Temp2.append(Temp.setNum( h )); + *proc << Temp2; + + *proc << "-quality"; + QString Temp3; + Temp3.setNum(m_quality); + *proc << Temp3; + + if ( IncDec == true ) // If the image is increased, enabled the filter. + { + *proc << "-filter" << m_resizeFilter; + } + + *proc << item->pathSrc(); + + Temp2 = "xc:rgb(" + Temp.setNum(m_backgroundColor.red()) + ","; + Temp2.append(Temp.setNum(m_backgroundColor.green()) + ","); + Temp2.append(Temp.setNum(m_backgroundColor.blue()) + ")"); + *proc << Temp2; + + // ImageMagick composite program do not preserve exif data from original. + // Need to use "-profile" option for that. + + *proc << "-profile" << item->pathSrc(); + + *proc << "-resize" << targetBackgroundSize + "!"; + + *proc << "-quality"; + QString Temp4; + Temp4.setNum(m_quality); + *proc << Temp4; + + *proc << albumDest + "/" + item->nameDest(); + } + + return(extractArguments(proc)); +} + +bool ResizeImagesDialog::prepareStartProcess(BatchProcessImagesItem *item, + const QString& /*albumDest*/) +{ + QImage img; + + if ( img.load( item->pathSrc() ) == false ) + { + item->changeResult(i18n("Skipped.")); + item->changeError(i18n("image file format unsupported.")); + return false; + } + + return true; +} + +bool ResizeImagesDialog::ResizeImage( int &w, int &h, int SizeFactor) +{ + bool valRet; + + if ( w > h ) + { + h = (int)( (double)( h * SizeFactor ) / w ); + + if ( h == 0 ) h = 1; + + if ( w < SizeFactor ) valRet = true; + else valRet = false; + + w = SizeFactor; + } + else + { + w = (int)( (double)( w * SizeFactor ) / h ); + + if ( w == 0 ) w = 1; + + if ( h < SizeFactor ) valRet = true; + else valRet = false; + + h = SizeFactor; + } + + return (valRet); // Return true is image increased, else true. +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/resizeimagesdialog.h b/kipi-plugins/batchprocessimages/resizeimagesdialog.h new file mode 100644 index 0000000..93cdfd3 --- /dev/null +++ b/kipi-plugins/batchprocessimages/resizeimagesdialog.h @@ -0,0 +1,92 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef RESIZEIMAGESDIALOG_H +#define RESIZEIMAGESDIALOG_H + +// Local includes + +#include "kpaboutdata.h" +#include "batchprocessimagesdialog.h" + +namespace KIPIBatchProcessImagesPlugin +{ + +class BatchProcessImagesItem; + +class ResizeImagesDialog : public BatchProcessImagesDialog +{ +Q_OBJECT + + public: + + ResizeImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 ); + ~ResizeImagesDialog(); + + private slots: + + void slotHelp(void); + void slotOptionsClicked(void); + + protected: + + QString m_resizeFilter; + QString m_paperSize; + QString m_printDpi; + + QColor m_backgroundColor; + QColor m_bgColor; + + bool m_customSettings; + + int m_customXSize; + int m_customYSize; + int m_marging; + int m_customDpi; + int m_size; + int m_xPixels; + int m_yPixels; + int m_Width; + int m_Height; + int m_Border; + int m_fixedWidth; + int m_fixedHeight; + int m_quality; + + QString makeProcess(KProcess* proc, BatchProcessImagesItem *item, + const QString& albumDest, bool previewMode); + + void readSettings(void); + void saveSettings(void); + bool prepareStartProcess(BatchProcessImagesItem *item, + const QString& albumDest); + + bool ResizeImage( int &w, int &h, int SizeFactor); + + private: + + KIPIPlugins::KPAboutData *m_about; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // RESIZEIMAGESDIALOG_H diff --git a/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp b/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp new file mode 100644 index 0000000..031cd8e --- /dev/null +++ b/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp @@ -0,0 +1,373 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +// Include files for Qt + +#include <qvbox.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <qcolor.h> + +// Include files for KDE + +#include <klocale.h> +#include <knuminput.h> +#include <kcolorbutton.h> +#include <kmessagebox.h> + +// Local includes + +#include "resizeoptionsdialog.h" +#include "resizeoptionsdialog.moc" + +namespace KIPIBatchProcessImagesPlugin +{ + +ResizeOptionsDialog::ResizeOptionsDialog(QWidget *parent, int ResizeType) + : KDialogBase( parent, "ResizeOptionsDialog", true, + i18n("Image-Resize Options"), Ok|Cancel, Ok, false) +{ + m_Type = ResizeType; + QWidget* box = new QWidget( this ); + setMainWidget(box); + QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() ); + QString whatsThis; + + if (m_Type == 0) // Proportional (1 dim.) + { + QGroupBox * groupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Resize Options"), box ); + + m_size = new KIntNumInput(640, groupBox1); + m_size->setRange(10, 10000, 1, true ); + m_size->setLabel( i18n("New size (pixels):") ); + QWhatsThis::add( m_size, i18n("<p>The new images' size in pixels.") ); + + m_quality = new KIntNumInput(75, groupBox1); + m_quality->setRange(0, 100, 1, true); + m_quality->setLabel( i18n("Image quality (percent):") ); + QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") ); + + m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox1); + + m_resizeFilter = new QComboBox( false, groupBox1 ); + m_resizeFilter->insertItem(i18n("Filter name","Bessel")); + m_resizeFilter->insertItem(i18n("Filter name","Blackman")); + m_resizeFilter->insertItem(i18n("Filter name","Box")); + m_resizeFilter->insertItem(i18n("Filter name","Catrom")); + m_resizeFilter->insertItem(i18n("Filter name","Cubic")); + m_resizeFilter->insertItem(i18n("Filter name","Gaussian")); + m_resizeFilter->insertItem(i18n("Filter name","Hermite")); + m_resizeFilter->insertItem(i18n("Filter name","Hanning")); + m_resizeFilter->insertItem(i18n("Filter name","Hamming")); + m_resizeFilter->insertItem(i18n("Filter name","Lanczos")); + m_resizeFilter->insertItem(i18n("Filter name","Mitchell")); + m_resizeFilter->insertItem(i18n("Filter name","Point")); + m_resizeFilter->insertItem(i18n("Filter name","Quadratic")); + m_resizeFilter->insertItem(i18n("Filter name","Sinc")); + m_resizeFilter->insertItem(i18n("Filter name","Triangle")); + QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. " + "This filter will be used like a kernel convolution process " + "during the increased image size rendering. The default filter " + "is 'Lanczos'.") ); + m_label_resizeFilter->setBuddy( m_resizeFilter ); + + dvlay->addWidget( groupBox1 ); + + m_label_size = new QLabel ( i18n("Note: the images will be resized to\n" + "this size. The width or the height of the\n" + "images will be automatically\n" + "selected in depending of the images orientation.\n" + "The images' aspect ratios are preserved."), box); + dvlay->addWidget( m_label_size ); + } + + if (m_Type == 1) // Proportional (2 dim.) + { + QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("Size Settings"), box ); + + m_label_Width = new QLabel (i18n("Width (pixels):"), groupBox1); + m_Width = new KIntNumInput(1024, groupBox1); + m_Width->setRange(100, 10000, 1, true ); + QWhatsThis::add( m_Width, i18n("<p>The new images' width in pixels.")); + m_label_Width->setBuddy( m_Width ); + + m_label_Height = new QLabel (i18n("Height (pixels):"), groupBox1); + m_Height = new KIntNumInput(768, groupBox1); + m_Height->setRange(100, 10000, 1, true ); + QWhatsThis::add( m_Height, i18n("<p>The new images' height in pixels.")); + m_label_Height->setBuddy( m_Height ); + + m_label_quality = new QLabel (i18n("Image quality (percent):"), groupBox1); + m_quality = new KIntNumInput(75, groupBox1); + m_quality->setRange(0, 100, 1, true); + QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") ); + m_label_quality->setBuddy(m_quality); + + dvlay->addWidget( groupBox1 ); + + QGroupBox * groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("Rendering Settings"), box ); + + m_label_bgColor = new QLabel(i18n("Background color:"), groupBox2); + QColor bgColor = QColor( 0, 0, 0 ); // Black per default. + m_button_bgColor = new KColorButton( bgColor, groupBox2 ); + QWhatsThis::add( m_button_bgColor, i18n( "<p>You can select here the background color to " + "be used when adapting the images' sizes." )); + m_label_bgColor->setBuddy( m_button_bgColor ); + + m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox2); + m_resizeFilter = new QComboBox( false, groupBox2 ); + m_resizeFilter->insertItem(i18n("Filter name","Bessel")); + m_resizeFilter->insertItem(i18n("Filter name","Blackman")); + m_resizeFilter->insertItem(i18n("Filter name","Box")); + m_resizeFilter->insertItem(i18n("Filter name","Catrom")); + m_resizeFilter->insertItem(i18n("Filter name","Cubic")); + m_resizeFilter->insertItem(i18n("Filter name","Gaussian")); + m_resizeFilter->insertItem(i18n("Filter name","Hermite")); + m_resizeFilter->insertItem(i18n("Filter name","Hanning")); + m_resizeFilter->insertItem(i18n("Filter name","Hamming")); + m_resizeFilter->insertItem(i18n("Filter name","Lanczos")); + m_resizeFilter->insertItem(i18n("Filter name","Mitchell")); + m_resizeFilter->insertItem(i18n("Filter name","Point")); + m_resizeFilter->insertItem(i18n("Filter name","Quadratic")); + m_resizeFilter->insertItem(i18n("Filter name","Sinc")); + m_resizeFilter->insertItem(i18n("Filter name","Triangle")); + QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. " + "This filter will be used like a kernel convolution process " + "during the increased image size rendering. The default filter " + "is 'Lanczos'.") ); + m_label_resizeFilter->setBuddy( m_resizeFilter ); + + m_label_border = new QLabel (i18n("Border size (pixels):"), groupBox2); + m_Border = new KIntNumInput(100, groupBox2); + m_Border->setRange(0, 1000, 1, true ); + QWhatsThis::add( m_Border, i18n("<p>The border size around the images in pixels.")); + m_label_border->setBuddy( m_Border ); + + dvlay->addWidget( groupBox2 ); + } + + if (m_Type == 2) // Non proportional + { + QGroupBox * groupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Resize Options"), box ); + + m_fixedWidth = new KIntNumInput(640, groupBox1); + m_fixedWidth->setRange(10, 10000, 1, true ); + m_fixedWidth->setLabel( i18n("New width (pixels):") ); + QWhatsThis::add( m_fixedWidth, i18n("<p>The new images' width in pixels.") ); + + m_fixedHeight = new KIntNumInput(480, groupBox1); + m_fixedHeight->setRange(10, 10000, 1, true ); + m_fixedHeight->setLabel( i18n("New height (pixels):") ); + QWhatsThis::add( m_fixedHeight, i18n("<p>The new images' height in pixels.") ); + + m_quality = new KIntNumInput(75, groupBox1); + m_quality->setRange(0, 100, 1, true); + m_quality->setLabel( i18n("Image quality (percent):") ); + QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") ); + + m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox1); + + m_resizeFilter = new QComboBox( false, groupBox1 ); + m_resizeFilter->insertItem(i18n("Filter name","Bessel")); + m_resizeFilter->insertItem(i18n("Filter name","Blackman")); + m_resizeFilter->insertItem(i18n("Filter name","Box")); + m_resizeFilter->insertItem(i18n("Filter name","Catrom")); + m_resizeFilter->insertItem(i18n("Filter name","Cubic")); + m_resizeFilter->insertItem(i18n("Filter name","Gaussian")); + m_resizeFilter->insertItem(i18n("Filter name","Hermite")); + m_resizeFilter->insertItem(i18n("Filter name","Hanning")); + m_resizeFilter->insertItem(i18n("Filter name","Hamming")); + m_resizeFilter->insertItem(i18n("Filter name","Lanczos")); + m_resizeFilter->insertItem(i18n("Filter name","Mitchell")); + m_resizeFilter->insertItem(i18n("Filter name","Point")); + m_resizeFilter->insertItem(i18n("Filter name","Quadratic")); + m_resizeFilter->insertItem(i18n("Filter name","Sinc")); + m_resizeFilter->insertItem(i18n("Filter name","Triangle")); + QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. " + "This filter will be used like a kernel convolution process " + "during the increased image size rendering. The default filter " + "is 'Lanczos'.") ); + m_label_resizeFilter->setBuddy( m_resizeFilter ); + + dvlay->addWidget( groupBox1 ); + } + + if (m_Type == 3) // Prepare to print + { + m_customSettings = new QCheckBox( i18n("Use custom settings"), box); + QWhatsThis::add( m_customSettings, i18n("<p>If this option is enabled, " + "all printing settings can be customized.")); + dvlay->addWidget( m_customSettings ); + + QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("Printing Standard Settings"), box ); + + m_label_paperSize = new QLabel (i18n("Paper size (cm):"), groupBox1); + m_paperSize = new QComboBox( false, groupBox1 ); + m_paperSize->insertItem("9x13"); + m_paperSize->insertItem("10x15"); + m_paperSize->insertItem("13x19"); + m_paperSize->insertItem("15x21"); + m_paperSize->insertItem("18x24"); + m_paperSize->insertItem("20x30"); + m_paperSize->insertItem("21x30"); + m_paperSize->insertItem("30x40"); + m_paperSize->insertItem("30x45"); + m_paperSize->insertItem("40x50"); + m_paperSize->insertItem("50x75"); + QWhatsThis::add( m_paperSize, i18n("<p>The standard photographic paper sizes in centimeters.")); + m_label_paperSize->setBuddy( m_paperSize ); + + m_label_printDpi = new QLabel (i18n("Print resolution (dpi):"), groupBox1); + m_printDpi = new QComboBox( false, groupBox1 ); + m_printDpi->insertItem("75"); + m_printDpi->insertItem("150"); + m_printDpi->insertItem("300"); + m_printDpi->insertItem("600"); + m_printDpi->insertItem("1200"); + m_printDpi->insertItem("1400"); + m_printDpi->insertItem("2400"); + QWhatsThis::add( m_printDpi, i18n("<p>The standard print resolutions in dots per inch.")); + m_label_printDpi->setBuddy( m_printDpi ); + + dvlay->addWidget( groupBox1 ); + + QGroupBox * groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("Printing Custom Settings"), box ); + + m_label_customXSize = new QLabel (i18n("Paper width (cm):"), groupBox2); + m_customXSize = new KIntNumInput(10, groupBox2); + m_customXSize->setRange(1, 100, 1, true ); + QWhatsThis::add( m_customXSize, i18n("<p>The customized width of the photographic paper size " + "in centimeters.")); + m_label_customXSize->setBuddy( m_customXSize ); + + m_label_customYSize = new QLabel (i18n("Paper height (cm):"), groupBox2); + m_customYSize = new KIntNumInput(15, groupBox2); + m_customYSize->setRange(1, 100, 1, true ); + QWhatsThis::add( m_customYSize, i18n("<p>The customized height of the photographic paper size " + "in centimeters.")); + m_label_customYSize->setBuddy( m_customYSize ); + + m_label_customDpi = new QLabel (i18n("Print resolution (dpi):"), groupBox2); + m_customDpi = new KIntNumInput(300, groupBox2); + m_customDpi->setRange(10, 5000, 10, true ); + QWhatsThis::add( m_customDpi, i18n("<p>The customized print resolution in dots per inch.")); + m_label_customDpi->setBuddy( m_customDpi ); + + dvlay->addWidget( groupBox2 ); + + QGroupBox * groupBox3 = new QGroupBox( 2, Qt::Horizontal, i18n("Rendering Settings"), box ); + + m_label_backgroundColor = new QLabel(i18n("Background color:"), groupBox3); + QColor backgroundColor = QColor( 255, 255, 255 ); // White per default. + m_button_backgroundColor = new KColorButton( backgroundColor, groupBox3 ); + QWhatsThis::add( m_button_backgroundColor, i18n( "<p>You can select here the background color to " + "be used when adapting the images' sizes." )); + m_label_backgroundColor->setBuddy( m_button_backgroundColor ); + + m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox3); + m_resizeFilter = new QComboBox( false, groupBox3 ); + m_resizeFilter->insertItem(i18n("Filter name","Bessel")); + m_resizeFilter->insertItem(i18n("Filter name","Blackman")); + m_resizeFilter->insertItem(i18n("Filter name","Box")); + m_resizeFilter->insertItem(i18n("Filter name","Catrom")); + m_resizeFilter->insertItem(i18n("Filter name","Cubic")); + m_resizeFilter->insertItem(i18n("Filter name","Gaussian")); + m_resizeFilter->insertItem(i18n("Filter name","Hermite")); + m_resizeFilter->insertItem(i18n("Filter name","Hanning")); + m_resizeFilter->insertItem(i18n("Filter name","Hamming")); + m_resizeFilter->insertItem(i18n("Filter name","Lanczos")); + m_resizeFilter->insertItem(i18n("Filter name","Mitchell")); + m_resizeFilter->insertItem(i18n("Filter name","Point")); + m_resizeFilter->insertItem(i18n("Filter name","Quadratic")); + m_resizeFilter->insertItem(i18n("Filter name","Sinc")); + m_resizeFilter->insertItem(i18n("Filter name","Triangle")); + QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. " + "This filter will be used like a kernel convolution process " + "during the increased image size rendering. The default filter " + "is 'Lanczos'.") ); + m_label_resizeFilter->setBuddy( m_resizeFilter ); + + m_label_marging = new QLabel (i18n("Margin size (mm):"), groupBox3); + m_marging = new KIntNumInput(1, groupBox3); + m_marging->setRange(0, 80, 1, true ); + QWhatsThis::add( m_marging, i18n("<p>The margin around the images in millimeters.")); + m_label_marging->setBuddy( m_marging ); + + m_label_quality = new QLabel (i18n("Image quality (percent):"), groupBox3); + m_quality = new KIntNumInput(75, groupBox3); + m_quality->setRange(0, 100, 1, true); + QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") ); + m_label_quality->setBuddy(m_quality); + + dvlay->addWidget( groupBox3 ); + + connect(m_customSettings, SIGNAL( toggled(bool) ), + this, SLOT( slotCustomSettingsEnabled(bool) ) ); + + slotCustomSettingsEnabled(false); + } +} + +ResizeOptionsDialog::~ResizeOptionsDialog() +{ +} + +void ResizeOptionsDialog::slotCustomSettingsEnabled(bool val) +{ + m_label_paperSize->setEnabled( !val ); + m_paperSize->setEnabled( !val ); + m_label_printDpi->setEnabled( !val ); + m_printDpi->setEnabled( !val ); + + m_label_customXSize->setEnabled( val ); + m_customXSize->setEnabled( val ); + m_label_customYSize->setEnabled( val ); + m_customYSize->setEnabled( val ); + m_label_customDpi->setEnabled( val ); + m_customDpi->setEnabled( val ); +} + +void ResizeOptionsDialog::slotOk() +{ + if (m_Type == 3) // Prepare to print + { + if (m_customSettings->isChecked() == true) + { + if (m_customXSize > m_customYSize) + { + KMessageBox::sorry(this, i18n("You must enter a custom height greater than the custom width: " + "the photographic paper must be vertically orientated.")); + return; + } + } + } + + accept(); +} + +} // NameSpace KIPIBatchProcessImagesPlugin diff --git a/kipi-plugins/batchprocessimages/resizeoptionsdialog.h b/kipi-plugins/batchprocessimages/resizeoptionsdialog.h new file mode 100644 index 0000000..09a98ed --- /dev/null +++ b/kipi-plugins/batchprocessimages/resizeoptionsdialog.h @@ -0,0 +1,101 @@ +/* ============================================================ + * + * This file is a part of kipi-plugins project + * http://www.kipi-plugins.org + * + * Date : 2004-10-01 + * Description : a kipi plugin to batch process images + * + * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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. + * + * ============================================================ */ + +#ifndef RESIZEOPTIONSDIALOG_H +#define RESIZEOPTIONSDIALOG_H + +// Include files for Qt + +#include <qstring.h> + +// Include files for KDE + +#include <kdialogbase.h> + +class QLabel; +class QComboBox; +class QCheckBox; + +class KIntNumInput; +class KColorButton; + +namespace KIPIBatchProcessImagesPlugin +{ + +class ResizeOptionsDialog : public KDialogBase +{ +Q_OBJECT + + public: + + ResizeOptionsDialog(QWidget *parent=0, int ResizeType = 0); + ~ResizeOptionsDialog(); + + QLabel *m_label_size; + QLabel *m_label_resizeFilter; + QLabel *m_label_paperSize; + QLabel *m_label_printDpi; + QLabel *m_label_customXSize; + QLabel *m_label_customYSize; + QLabel *m_label_customDpi; + QLabel *m_label_backgroundColor; + QLabel *m_label_marging; + QLabel *m_label_Width; + QLabel *m_label_Height; + QLabel *m_label_bgColor; + QLabel *m_label_border; + QLabel *m_label_quality; + + KIntNumInput *m_size; + KIntNumInput *m_customXSize; + KIntNumInput *m_customYSize; + KIntNumInput *m_customDpi; + KIntNumInput *m_marging; + KIntNumInput *m_Width; + KIntNumInput *m_Height; + KIntNumInput *m_Border; + KIntNumInput *m_fixedWidth; + KIntNumInput *m_fixedHeight; + KIntNumInput *m_quality; + + QCheckBox *m_customSettings; + + KColorButton *m_button_backgroundColor; + KColorButton *m_button_bgColor; + + QComboBox *m_resizeFilter; + QComboBox *m_paperSize; + QComboBox *m_printDpi; + + protected slots: + + void slotCustomSettingsEnabled(bool val); + void slotOk(); + + protected: + + int m_Type; +}; + +} // NameSpace KIPIBatchProcessImagesPlugin + +#endif // RESIZEOPTIONSDIALOG_H |