You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1093 lines
36 KiB
1093 lines
36 KiB
/* ============================================================
|
|
*
|
|
* 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 TQt
|
|
|
|
#include <tqvbox.h>
|
|
#include <tqlayout.h>
|
|
#include <tqdir.h>
|
|
#include <tqwidget.h>
|
|
#include <tqlabel.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqwhatsthis.h>
|
|
#include <tqcombobox.h>
|
|
#include <tqcheckbox.h>
|
|
#include <tqprocess.h>
|
|
#include <tqcolor.h>
|
|
#include <tqpainter.h>
|
|
#include <tqpalette.h>
|
|
#include <tqimage.h>
|
|
#include <tqevent.h>
|
|
#include <tqdragobject.h>
|
|
#include <tqfileinfo.h>
|
|
#include <tqhgroupbox.h>
|
|
#include <tqvgroupbox.h>
|
|
#include <tqframe.h>
|
|
#include <tqwmatrix.h>
|
|
|
|
// Include files for KDE
|
|
|
|
#include <kstandarddirs.h>
|
|
#include <kcolorbutton.h>
|
|
#include <tdelocale.h>
|
|
#include <kprogress.h>
|
|
#include <tdefiledialog.h>
|
|
#include <kiconloader.h>
|
|
#include <tdemessagebox.h>
|
|
#include <knuminput.h>
|
|
#include <kinstance.h>
|
|
#include <tdeconfig.h>
|
|
#include <tdeapplication.h>
|
|
#include <kdebug.h>
|
|
#include <kdialogbase.h>
|
|
#include <tdelistview.h>
|
|
#include <kimageio.h>
|
|
#include <kprocess.h>
|
|
#include <klineeditdlg.h>
|
|
#include <tdeio/jobclasses.h>
|
|
#include <tdeio/netaccess.h>
|
|
#include <tdeio/global.h>
|
|
#include <tdeio/previewjob.h>
|
|
#include <kbuttonbox.h>
|
|
#include <tdediroperator.h>
|
|
#include <tdeversion.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,
|
|
TQString caption, TQWidget *parent )
|
|
: KDialogBase( KDialogBase::Plain, caption, Help|User1|Cancel,
|
|
Cancel, parent, "BatchProcessImagesDialog", false, false, i18n("&Start")),
|
|
m_selectedImageFiles( urlList), m_interface( interface )
|
|
{
|
|
// Init. Tmp folder
|
|
|
|
TDEStandardDirs dir;
|
|
m_tmpFolder = dir.saveLocation("tmp", "kipi-batchprocessimagesplugin-" +
|
|
TQString::number(getpid()) );
|
|
|
|
m_convertStatus = NO_PROCESS;
|
|
m_progressStatus = 0;
|
|
m_ProcessusProc = 0;
|
|
m_PreviewProc = 0;
|
|
|
|
KImageIO::registerFormats();
|
|
|
|
TQWidget* box = plainPage();
|
|
TQVBoxLayout *dvlay = new TQVBoxLayout(box, 0, KDialog::spacingHint());
|
|
|
|
//---------------------------------------------
|
|
|
|
TQHBoxLayout *hlay = new TQHBoxLayout( dvlay );
|
|
groupBox1 = new TQGroupBox( 0, TQt::Vertical, box );
|
|
groupBox1->layout()->setSpacing(KDialog::spacingHint());
|
|
groupBox1->layout()->setMargin(KDialog::marginHint());
|
|
TQGridLayout* grid = new TQGridLayout( groupBox1->layout(), 2, 3);
|
|
m_labelType = new TQLabel( groupBox1 );
|
|
grid->addMultiCellWidget(m_labelType, 0, 0, 0, 0);
|
|
|
|
m_Type = new TQComboBox(false, groupBox1);
|
|
grid->addMultiCellWidget(m_Type, 0, 0, 1, 1);
|
|
|
|
m_optionsButton = new TQPushButton (groupBox1, "OptionButton");
|
|
m_optionsButton->setText(i18n("Options"));
|
|
TQWhatsThis::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 TQCheckBox(i18n("Small preview"), groupBox1);
|
|
TQWhatsThis::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 TQPushButton (groupBox1, "PreviewButton");
|
|
m_previewButton->setText(i18n("&Preview"));
|
|
TQWhatsThis::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 TQGroupBox( 2, TQt::Horizontal, i18n("File Operations"), box );
|
|
|
|
m_labelOverWrite = new TQLabel (i18n("Overwrite mode:"), groupBox2);
|
|
m_overWriteMode = new TQComboBox( 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"));
|
|
TQWhatsThis::add( m_overWriteMode, i18n("<p>Select here the overwrite mode used if your target's image "
|
|
"files already exist.") );
|
|
|
|
m_removeOriginal = new TQCheckBox(i18n("Remove original"), groupBox2);
|
|
TQWhatsThis::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 TQHGroupBox( i18n("Target Folder"), box );
|
|
|
|
m_destinationURL = new KURLRequester(groupBox3);
|
|
m_destinationURL->setMode(KFile::Directory | KFile::LocalOnly);
|
|
KIPI::ImageCollection album = interface->currentAlbum();
|
|
if (album.isValid())
|
|
{
|
|
TQString url;
|
|
if (album.isDirectory())
|
|
{
|
|
url = album.uploadPath().path();
|
|
}
|
|
else
|
|
{
|
|
url = TQDir::homeDirPath();
|
|
}
|
|
m_destinationURL->lineEdit()->setText(url);
|
|
}
|
|
TQWhatsThis::add( m_destinationURL, i18n("<p>Here you can select the target folder which "
|
|
"will used by the process."));
|
|
|
|
dvlay->addWidget( groupBox3 );
|
|
|
|
//---------------------------------------------
|
|
|
|
groupBox4 = new TQHGroupBox( box );
|
|
TQWidget* box41 = new TQWidget( groupBox4 );
|
|
TQHBoxLayout* lay2 = new TQHBoxLayout( box41, 0, spacingHint() );
|
|
m_listFiles = new BatchProcessImagesList( box41 );
|
|
lay2->addWidget( m_listFiles );
|
|
|
|
m_listFiles->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::MinimumExpanding);
|
|
|
|
TQVBoxLayout* lay3 = new TQVBoxLayout( lay2 );
|
|
m_addImagesButton = new TQPushButton ( i18n( "&Add..." ), box41 );
|
|
lay3->addWidget( m_addImagesButton );
|
|
TQWhatsThis::add( m_addImagesButton, i18n("<p>Add images to the list.") );
|
|
|
|
m_remImagesButton = new TQPushButton ( i18n( "&Remove" ), box41 );
|
|
lay3->addWidget( m_remImagesButton );
|
|
TQWhatsThis::add( m_remImagesButton, i18n("<p>Remove selected image from the list.") );
|
|
|
|
m_imageLabel = new TQLabel( box41 );
|
|
m_imageLabel->setFixedHeight( 80 );
|
|
m_imageLabel->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter );
|
|
m_imageLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) );
|
|
lay3->addWidget( m_imageLabel );
|
|
TQWhatsThis::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);
|
|
TQWhatsThis::add( m_progress, i18n("<p>This is the current percentage of the task completed.") );
|
|
|
|
dvlay->addWidget( m_progress );
|
|
|
|
//---------------------------------------------
|
|
|
|
connect(m_listFiles, TQT_SIGNAL(doubleClicked(TQListViewItem *)),
|
|
this, TQT_SLOT(slotListDoubleClicked(TQListViewItem *)));
|
|
|
|
connect(this, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotProcessStart()));
|
|
|
|
connect(m_optionsButton, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(slotOptionsClicked()));
|
|
|
|
connect(m_previewButton, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(slotPreview()));
|
|
|
|
connect(m_Type, TQT_SIGNAL(activated(int)),
|
|
this, TQT_SLOT(slotTypeChanged(int)));
|
|
|
|
connect(m_listFiles, TQT_SIGNAL( addedDropItems(TQStringList) ),
|
|
this, TQT_SLOT( slotAddDropItems(TQStringList)));
|
|
|
|
connect(m_listFiles, TQT_SIGNAL( currentChanged( TQListViewItem * ) ),
|
|
this, TQT_SLOT( slotImageSelected( TQListViewItem * )));
|
|
|
|
connect(m_addImagesButton, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(slotImagesFilesButtonAdd()));
|
|
|
|
connect(m_remImagesButton, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(slotImagesFilesButtonRem()));
|
|
|
|
// Get the image files filters from the hosts app.
|
|
|
|
m_ImagesFilesSort = m_interface->fileExtensions();
|
|
|
|
dvlay->activate();
|
|
}
|
|
|
|
BatchProcessImagesDialog::~BatchProcessImagesDialog()
|
|
{
|
|
}
|
|
|
|
void BatchProcessImagesDialog::slotImagesFilesButtonAdd( void )
|
|
{
|
|
TQStringList 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( TQListViewItem * item )
|
|
{
|
|
if ( !item || m_listFiles->childCount() == 0 )
|
|
{
|
|
m_imageLabel->clear();
|
|
return;
|
|
}
|
|
|
|
BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>( item );
|
|
if ( !pitem ) return;
|
|
|
|
m_imageLabel->clear();
|
|
|
|
TQString IdemIndexed = "file:" + pitem->pathSrc();
|
|
|
|
KURL url(IdemIndexed);
|
|
|
|
TDEIO::PreviewJob* m_thumbJob = TDEIO::filePreview( url, m_imageLabel->height() );
|
|
|
|
connect(m_thumbJob, TQT_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)),
|
|
this, TQT_SLOT(slotGotPreview(const KFileItem*, const TQPixmap&)));
|
|
}
|
|
|
|
void BatchProcessImagesDialog::slotGotPreview(const KFileItem* url, const TQPixmap &pixmap)
|
|
{
|
|
TQPixmap 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 )
|
|
{
|
|
TQImage img = pix.convertToImage();
|
|
TQWMatrix matrix;
|
|
|
|
matrix.rotate( info.angle() );
|
|
img = img.xForm( matrix );
|
|
pix.convertFromImage( img );
|
|
}
|
|
|
|
m_imageLabel->setPixmap(pix);
|
|
}
|
|
|
|
void BatchProcessImagesDialog::slotAddDropItems(TQStringList filesPath)
|
|
{
|
|
if (filesPath.isEmpty()) return;
|
|
|
|
for ( TQStringList::Iterator it = filesPath.begin() ; it != filesPath.end() ; ++it )
|
|
{
|
|
TQString 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 )
|
|
{
|
|
TQString currentFile = (*it2).path(); // PENDING(blackie) Handle URL's
|
|
|
|
if ( currentFile == currentDropFile )
|
|
findItem = true;
|
|
}
|
|
|
|
if (findItem == false)
|
|
m_selectedImageFiles.append(currentDropFile);
|
|
}
|
|
|
|
listImageFiles();
|
|
}
|
|
|
|
void BatchProcessImagesDialog::closeEvent ( TQCloseEvent *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, TQT_SIGNAL(user1Clicked()), this, TQT_SLOT(slotProcessStart()));
|
|
showButtonCancel( false );
|
|
setButtonText( User1, i18n("&Stop") );
|
|
connect(this, TQT_SIGNAL(user1Clicked()), this, TQT_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 TQListViewItemIterator( m_listFiles );
|
|
startProcess();
|
|
}
|
|
|
|
bool BatchProcessImagesDialog::startProcess(void)
|
|
{
|
|
if ( m_convertStatus == STOP_PROCESS )
|
|
{
|
|
endProcess();
|
|
return true;
|
|
}
|
|
|
|
TQString targetAlbum = m_destinationURL->url();
|
|
|
|
//TODO check if it is valid also for remote URL's
|
|
// this is a workarond for bug 117397
|
|
TQFileInfo 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 TDE_VERSION >= 0x30200
|
|
if ( TDEIO::NetAccess::exists( desturl, false, TQT_TQWIDGET(kapp->activeWindow()) ) == true )
|
|
#else
|
|
if ( TDEIO::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:
|
|
{
|
|
TQFileInfo *Target = new TQFileInfo(targetAlbum + "/" + item->nameDest());
|
|
TQString 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
|
|
{
|
|
TQFileInfo *newTarget = new TQFileInfo(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 = TQString();
|
|
m_ProcessusProc = new TDEProcess;
|
|
m_commandLine.append(makeProcess(m_ProcessusProc, item, targetAlbum));
|
|
|
|
item->changeOutputMess(m_commandLine + "\n\n");
|
|
|
|
connect(m_ProcessusProc, TQT_SIGNAL(processExited(TDEProcess *)),
|
|
this, TQT_SLOT(slotProcessDone(TDEProcess*)));
|
|
|
|
connect(m_ProcessusProc, TQT_SIGNAL(receivedStdout(TDEProcess *, char*, int)),
|
|
this, TQT_SLOT(slotReadStd(TDEProcess*, char*, int)));
|
|
|
|
connect(m_ProcessusProc, TQT_SIGNAL(receivedStderr(TDEProcess *, char*, int)),
|
|
this, TQT_SLOT(slotReadStd(TDEProcess*, char*, int)));
|
|
|
|
bool result = m_ProcessusProc->start(TDEProcess::NotifyOnExit, TDEProcess::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(TDEProcess* /*proc*/, char *buffer, int buflen)
|
|
{
|
|
BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() );
|
|
item->changeOutputMess( TQString::fromLocal8Bit(buffer, buflen) );
|
|
}
|
|
|
|
void BatchProcessImagesDialog::slotProcessDone(TDEProcess* 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() );
|
|
TQString 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 TDE_VERSION >= 0x30200
|
|
if ( TDEIO::NetAccess::del( deleteImage, TQT_TQWIDGET(kapp->activeWindow()) ) == false )
|
|
#else
|
|
if ( TDEIO::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(TQListViewItem *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, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotProcessStart()));
|
|
|
|
showButtonCancel( false );
|
|
setButtonText( User1, i18n("&Stop") );
|
|
|
|
connect(this, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotPreviewStop()));
|
|
|
|
m_previewOutput = "";
|
|
m_PreviewProc = new TDEProcess;
|
|
|
|
m_previewOutput.append(makeProcess(m_PreviewProc, item, TQString(), true));
|
|
|
|
*m_PreviewProc << m_tmpFolder + "/" + TQString::number(getpid()) + "preview.PNG";
|
|
m_previewOutput.append( " " + m_tmpFolder + "/" + TQString::number(getpid()) + "preview.PNG\n\n");
|
|
|
|
connect(m_PreviewProc, TQT_SIGNAL(processExited(TDEProcess *)),
|
|
this, TQT_SLOT(slotPreviewProcessDone(TDEProcess*)));
|
|
|
|
connect(m_PreviewProc, TQT_SIGNAL(receivedStdout(TDEProcess *, char*, int)),
|
|
this, TQT_SLOT(slotPreviewReadStd(TDEProcess*, char*, int)));
|
|
|
|
connect(m_PreviewProc, TQT_SIGNAL(receivedStderr(TDEProcess *, char*, int)),
|
|
this, TQT_SLOT(slotPreviewReadStd(TDEProcess*, char*, int)));
|
|
|
|
bool result = m_PreviewProc->start(TDEProcess::NotifyOnExit, TDEProcess::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(TDEProcess* /*proc*/, char *buffer, int buflen)
|
|
{
|
|
m_previewOutput.append( TQString::fromLocal8Bit(buffer, buflen) );
|
|
}
|
|
|
|
void BatchProcessImagesDialog::slotPreviewProcessDone(TDEProcess* 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 )
|
|
{
|
|
TQString cropTitle = "";
|
|
|
|
if ( m_smallPreview->isChecked() )
|
|
cropTitle = i18n(" - small preview");
|
|
|
|
ImagePreview *previewDialog = new ImagePreview(
|
|
item->pathSrc(),
|
|
m_tmpFolder + "/" + TQString::number(getpid()) + "preview.PNG",
|
|
m_tmpFolder,
|
|
m_smallPreview->isChecked(),
|
|
false,
|
|
m_Type->currentText() + cropTitle,
|
|
item->nameSrc(),
|
|
this);
|
|
previewDialog->exec();
|
|
|
|
KURL deletePreviewImage(m_tmpFolder + "/" + TQString::number(getpid()) + "preview.PNG");
|
|
|
|
#if TDE_VERSION >= 0x30200
|
|
TDEIO::NetAccess::del( deletePreviewImage, TQT_TQWIDGET(kapp->activeWindow()) );
|
|
#else
|
|
TDEIO::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 )
|
|
{
|
|
TQString currentFile = (*it).path(); // PENDING(blackie) Handle URLS
|
|
TQFileInfo *fi = new TQFileInfo(currentFile);
|
|
|
|
// Check if the new item already exist in the list.
|
|
|
|
bool findItem = false;
|
|
|
|
TQListViewItemIterator 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)
|
|
{
|
|
TQString oldFileName = fi->fileName();
|
|
TQString 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, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotPreviewStop()));
|
|
|
|
connect(this, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotProcessStart()));
|
|
}
|
|
|
|
int BatchProcessImagesDialog::overwriteMode(void)
|
|
{
|
|
TQString 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 TDE_VERSION >= 0x30200
|
|
if ( TDEIO::NetAccess::exists( deleteImage, false, TQT_TQWIDGET(kapp->activeWindow()) ) == true )
|
|
TDEIO::NetAccess::del( deleteImage, TQT_TQWIDGET(kapp->activeWindow()) );
|
|
#else
|
|
if ( TDEIO::NetAccess::exists( deleteImage ) == true )
|
|
TDEIO::NetAccess::del( deleteImage );
|
|
#endif
|
|
}
|
|
|
|
endProcess();
|
|
}
|
|
|
|
void BatchProcessImagesDialog::endProcess(void)
|
|
{
|
|
m_convertStatus = PROCESS_DONE;
|
|
setButtonText( User1, i18n("&Close") );
|
|
|
|
disconnect(this, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotProcessStop()));
|
|
|
|
connect(this, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotOk()));
|
|
}
|
|
|
|
TQString BatchProcessImagesDialog::RenameTargetImageFile(TQFileInfo *fi)
|
|
{
|
|
TQString 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 TDE_VERSION >= 0x30200
|
|
TDEIO::NetAccess::exists( NewDestUrl, true, TQT_TQWIDGET(kapp->activeWindow()) )
|
|
#else
|
|
TDEIO::NetAccess::exists( NewDestUrl )
|
|
#endif
|
|
== true );
|
|
|
|
if (Enumerator == 100) return TQString();
|
|
|
|
return (NewDestUrl.path());
|
|
}
|
|
|
|
TQString BatchProcessImagesDialog::extractArguments(TDEProcess *proc)
|
|
{
|
|
TQString retArguments;
|
|
TQValueList<TQCString> argumentsList = proc->args();
|
|
|
|
for ( TQValueList<TQCString>::iterator it = argumentsList.begin() ; it != argumentsList.end() ; ++it )
|
|
retArguments.append(*it + " ");
|
|
|
|
return (retArguments);
|
|
}
|
|
|
|
} // NameSpace KIPIBatchProcessImagesPlugin
|