Message info
 
To:kde-commits@kde.org From:Benjamin Girault Subject:[kipi-plugins] panorama: Panorama: Migration to KPActionThread (Pass 2) Date:Sun, 18 Mar 2012 17:36:15 +0100 (CET)
 

Git commit 4c9fd308b59371b9f66944c219b2f7a2e492fd63 by Benjamin Girault.
Committed on 18/03/2012 at 17:25.
Pushed by girault into branch 'master'.

Panorama: Migration to KPActionThread (Pass 2)

Segmentation of ActionThread into separate tasks

M +13 -1 panorama/CMakeLists.txt
M +2 -2 panorama/importwizard/intropage.cpp
M +2 -2 panorama/importwizard/lastpage.cpp
M +9 -5 panorama/importwizard/preprocessingpage.cpp
M +8 -12 panorama/importwizard/previewpage.cpp
M +0 -1 panorama/importwizard/previewpage.h
M +7 -0 panorama/manager/actions.h
M +206 -1288 panorama/manager/actionthread.cpp
M +15 -32 panorama/manager/actionthread.h
M +5 -14 panorama/manager/manager.cpp
M +1 -5 panorama/manager/manager.h
A +101 -0 panorama/tasks/compilemksteptask.cpp [License: GPL (v2+)]
A +71 -0 panorama/tasks/compilemksteptask.h [License: GPL (v2+)]
A +94 -0 panorama/tasks/compilemktask.cpp [License: GPL (v2+)]
A +68 -0 panorama/tasks/compilemktask.h [License: GPL (v2+)]
A +139 -0 panorama/tasks/copyfilestask.cpp [License: GPL (v2+)]
A +66 -0 panorama/tasks/copyfilestask.h [License: GPL (v2+)]
A +107 -0 panorama/tasks/cpcleantask.cpp [License: GPL (v2+)]
A +69 -0 panorama/tasks/cpcleantask.h [License: GPL (v2+)]
A +102 -0 panorama/tasks/cpfindtask.cpp [License: GPL (v2+)]
A +69 -0 panorama/tasks/cpfindtask.h [License: GPL (v2+)]
A +136 -0 panorama/tasks/createmktask.cpp [License: GPL (v2+)]
A +74 -0 panorama/tasks/createmktask.h [License: GPL (v2+)]
A +232 -0 panorama/tasks/createpreviewtask.cpp [License: GPL (v2+)]
C +26 -31 panorama/tasks/createpreviewtask.h [from: panorama/importwizard/previewpage.h - 050% similarity]
A +166 -0 panorama/tasks/createptotask.cpp [License: GPL (v2+)]
A +71 -0 panorama/tasks/createptotask.h [License: GPL (v2+)]
A +104 -0 panorama/tasks/optimisationtask.cpp [License: GPL (v2+)]
A +72 -0 panorama/tasks/optimisationtask.h [License: GPL (v2+)]
A +211 -0 panorama/tasks/preprocesstask.cpp [License: GPL (v2+)]
A +84 -0 panorama/tasks/preprocesstask.h [License: GPL (v2+)]
A +74 -0 panorama/tasks/task.cpp [License: GPL (v2+)]
C +29 -29 panorama/tasks/task.h [from: panorama/importwizard/previewpage.h - 053% similarity]
A +37 -0 panorama/tasks/tasks.h [License: GPL (v2+)]

http://commits.kde.org/kipi-plugins/4c9fd308b59371b9f66944c219b2f7a2e492fd63

diff --git a/panorama/CMakeLists.txt b/panorama/CMakeLists.txt
index a1c6139..ac9c87a 100644
--- a/panorama/CMakeLists.txt
+++ b/panorama/CMakeLists.txt
@@ -1,9 +1,10 @@
-SUBDIRS(icons)
+ADD_SUBDIRECTORY(icons)

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/importwizard
${CMAKE_CURRENT_SOURCE_DIR}/manager
${CMAKE_CURRENT_SOURCE_DIR}/plugin
${CMAKE_CURRENT_SOURCE_DIR}/ptoparser
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks
${Boost_INCLUDE_DIR}/boost # NOTICE: this is the only way for my system to compile it
# ${Boost_INCLUDE_DIRS}
)
@@ -43,6 +44,17 @@ SET(panorama_common_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/importwizard/optimizepage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/importwizard/preprocessingpage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/importwizard/previewpage.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/task.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/preprocesstask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/createptotask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/cpfindtask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/cpcleantask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/optimisationtask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/createpreviewtask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/createmktask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/compilemksteptask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/compilemktask.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tasks/copyfilestask.cpp
)

# Adjust flag for static lib and 64 bits computers using -fPIC for GCC compiler (B.K.O: #269903)
diff --git a/panorama/importwizard/intropage.cpp b/panorama/importwizard/intropage.cpp
index 5d97c8d..bce9fb7 100644
--- a/panorama/importwizard/intropage.cpp
+++ b/panorama/importwizard/intropage.cpp
@@ -153,10 +153,10 @@ IntroPage::IntroPage(Manager* const mngr, KAssistantDialog* const dlg)

switch (d->mngr->format())
{
- case ActionThread::JPEG:
+ case JPEG:
d->jpegRadioButton->setChecked(true);
break;
- case ActionThread::TIFF:
+ case TIFF:
d->tiffRadioButton->setChecked(true);
break;
}
diff --git a/panorama/importwizard/lastpage.cpp b/panorama/importwizard/lastpage.cpp
index 6df6667..2f3b0c5 100644
--- a/panorama/importwizard/lastpage.cpp
+++ b/panorama/importwizard/lastpage.cpp
@@ -238,9 +238,9 @@ QString LastPage::panoFileName(const QString& fileTemplate) const
switch (d->mngr->format())
{
default:
- case ActionThread::JPEG:
+ case JPEG:
return fileTemplate + ".jpg";
- case ActionThread::TIFF:
+ case TIFF:
return fileTemplate + ".tif";
}
}
diff --git a/panorama/importwizard/preprocessingpage.cpp b/panorama/importwizard/preprocessingpage.cpp
index f647a8d..2a2b69e 100644
--- a/panorama/importwizard/preprocessingpage.cpp
+++ b/panorama/importwizard/preprocessingpage.cpp
@@ -186,11 +186,15 @@ void PreProcessingPage::process()

// d->nbFilesProcessed = 0;

- d->mngr->thread()->setPreProcessingSettings(d->celesteCheckBox->isChecked(),
- d->mngr->hdr(),
- d->mngr->format(),
- d->mngr->rawDecodingSettings());
- d->mngr->thread()->preProcessFiles(d->mngr->itemsList(), d->mngr->cpCleanBinary().path(),
+ d->mngr->thread()->preProcessFiles(d->mngr->itemsList(),
+ d->mngr->preProcessedMap(),
+ d->mngr->cpFindUrl(),
+ d->mngr->cpFindUrlData(),
+ d->celesteCheckBox->isChecked(),
+ d->mngr->hdr(),
+ d->mngr->format(),
+ d->mngr->rawDecodingSettings(),
+ d->mngr->cpCleanBinary().path(),
d->mngr->cpFindBinary().path());
if (!d->mngr->thread()->isRunning())
d->mngr->thread()->start();
diff --git a/panorama/importwizard/previewpage.cpp b/panorama/importwizard/previewpage.cpp
index 970c1e1..b6269d1 100644
--- a/panorama/importwizard/previewpage.cpp
+++ b/panorama/importwizard/previewpage.cpp
@@ -65,7 +65,7 @@ struct PreviewPage::PreviewPagePriv
{}

QLabel* title;
- QUrl previewUrl;
+
KPPreviewManager* previewWidget;
bool previewBusy;
bool stitchingBusy;
@@ -111,9 +111,6 @@ PreviewPage::PreviewPage(Manager* const mngr, KAssistantDialog* const dlg)

connect(d->mngr->thread(), SIGNAL(finished(KIPIPanoramaPlugin::ActionData)),
this, SLOT(slotAction(KIPIPanoramaPlugin::ActionData)));
-
- connect(d->mngr->thread(), SIGNAL(previewFileReady(KUrl)),
- this, SLOT(slotGetPreviewFile(KUrl)));
}

PreviewPage::~PreviewPage()
@@ -161,6 +158,7 @@ void PreviewPage::computePreview()
d->previewBusy = true;

d->mngr->thread()->generatePanoramaPreview(d->mngr->autoOptimiseUrl(),
+ d->mngr->previewUrl(),
d->mngr->preProcessedMap(),
d->mngr->makeBinary().path(),
d->mngr->pto2MkBinary().path(),
@@ -195,6 +193,7 @@ void PreviewPage::startStitching()
d->postProcessing->show();

d->mngr->thread()->compileProject(d->mngr->autoOptimiseUrl(),
+ d->mngr->panoUrl(),
d->mngr->preProcessedMap(),
d->mngr->format(),
d->mngr->makeBinary().path(),
@@ -304,8 +303,13 @@ void PreviewPage::slotAction(const KIPIPanoramaPlugin::ActionData& ad)
{
return;
}
+
kDebug() << "Preview Stitching finished";
d->previewBusy = false;
+
+ d->previewWidget->load(d->mngr->previewUrl().toLocalFile(), true);
+ // d->previewWidget->setSelectionAreaPossible(true);
+ kDebug() << "Preview URL: " << d->mngr->previewUrl();
break;
}
case NONAFILE:
@@ -371,12 +375,4 @@ void PreviewPage::slotAction(const KIPIPanoramaPlugin::ActionData& ad)
}
}

-void PreviewPage::slotGetPreviewFile(const KUrl& previewUrl)
-{
- d->previewUrl = previewUrl;
- d->previewWidget->load(previewUrl.toLocalFile(), true);
-// d->previewWidget->setSelectionAreaPossible(true);
- kDebug() << "Preview URL: " << previewUrl;
-}
-
} // namespace KIPIPanoramaPlugin
diff --git a/panorama/importwizard/previewpage.h b/panorama/importwizard/previewpage.h
index ce7b942..7d66011 100644
--- a/panorama/importwizard/previewpage.h
+++ b/panorama/importwizard/previewpage.h
@@ -56,7 +56,6 @@ Q_SIGNALS:
private Q_SLOTS:

void slotAction(const KIPIPanoramaPlugin::ActionData&);
- void slotGetPreviewFile(const KUrl&);

private:

diff --git a/panorama/manager/actions.h b/panorama/manager/actions.h
index 09cf164..525317f 100644
--- a/panorama/manager/actions.h
+++ b/panorama/manager/actions.h
@@ -65,6 +65,13 @@ enum Action
COPY
};

+typedef enum
+{
+ JPEG,
+ TIFF
+}
+PanoramaFileType;
+
struct ItemPreprocessedUrls
{
ItemPreprocessedUrls() {}
diff --git a/panorama/manager/actionthread.cpp b/panorama/manager/actionthread.cpp
index 7034794..0c65014 100644
--- a/panorama/manager/actionthread.cpp
+++ b/panorama/manager/actionthread.cpp
@@ -7,7 +7,7 @@
* Description : a plugin to create panorama by fusion of several images.
* Acknowledge : based on the expoblending plugin
*
- * Copyright (C) 2011 by Benjamin Girault <benjamin dot girault at gmail dot com>
+ * Copyright (C) 2011-2012 by Benjamin Girault <benjamin dot girault at gmail dot com>
* Copyright (C) 2009-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2009-2011 by Johannes Wienke <languitar at semipol dot de>
*
@@ -25,18 +25,9 @@

#include "actionthread.moc"

-// C++ includes
-
-#include <iostream>
-
// Qt includes

-#include <QMutex>
-#include <QMutexLocker>
-#include <QWaitCondition>
-#include <QtDebug>
#include <QDateTime>
-#include <QFileInfo>
#include <QPointer>

// KDE includes
@@ -49,16 +40,10 @@
#include <threadweaver/JobCollection.h>
#include <threadweaver/DependencyPolicy.h>

-// LibKDcraw includes
-
-#include <libkdcraw/kdcraw.h>
-
// Local includes

-#include "kpmetadata.h"
-#include "kpwriteimage.h"
-#include "kpversion.h"
-#include "ptoparser.h"
+#include "ptotype.h"
+#include "tasks.h"

using namespace KIPIPlugins;
using namespace ThreadWeaver;
@@ -66,1061 +51,46 @@ using namespace ThreadWeaver;
namespace KIPIPanoramaPlugin
{

-class ActionThread::Task : public ThreadWeaver::Job
+struct ActionThread::ActionThreadPriv
{
-public:
-
- struct ActionPreprocessParameters
- {
- KUrl fileUrl;
- ItemPreprocessedUrls *preProcessedUrls;
- KDcrawIface::RawDecodingSettings settings;
- };
-
- struct ActionCreatePtoParameters
- {
- PanoramaFileType fileType;
- bool hdr;
- const KUrl::List *inputFiles;
- const ItemUrlsMap *itemUrlsMap;
- KUrl *ptoUrl;
- };
-
- struct ActionCPFindParameters
- {
- bool celeste;
- KUrl *ptoUrl;
- KUrl *cpFindPtoUrl;
- QString cpFindPath;
- };
-
- struct ActionCPCleanParameters
- {
- KUrl *cpFindPtoUrl;
- KUrl *cpCleanPtoUrl;
- QString cpCleanPath;
- PTOType *ptoUrlData;
- };
-
- struct ActionOptimizeParameters
- {
- KUrl *ptoUrl;
- KUrl *autoOptimiserPtoUrl;
- bool levelHorizon;
- bool optimizeProjectionAndSize;
- QString autooptimiserPath;
- };
-
- struct ActionCreatePreviewPtoParameters
- {
- KUrl ptoUrl;
- KUrl *previewPtoUrl;
- ItemUrlsMap preProcessedUrlsMap;
- };
-
- struct ActionCreateMKParameters
- {
- KUrl *ptoUrl;
- KUrl *mkUrl;
- KUrl *panoUrl;
- PanoramaFileType fileType;
- QString pto2mkPath;
- QString nonaPath;
- QString enblendPath;
- };
-
- struct ActionMakeFile
- {
- KUrl *mkUrl;
- KUrl *panoUrl;
- QString makePath;
- };
-
- struct ActionCopy
- {
- KUrl panoUrl;
- KUrl finalPanoUrl;
- KUrl ptoUrl;
- const ItemUrlsMap *urlList;
- bool savePTO;
- };
-
-public:
-
- QString errString;
-
- KUrl tmpDir;
-
- Action action;
- int id;
-
- union
- {
- ActionPreprocessParameters *preProcessingParams;
- ActionCreatePtoParameters *createPtoParams;
- ActionCPFindParameters *cpFindParams;
- ActionCPCleanParameters *cpCleanParams;
- ActionOptimizeParameters *optimizeParams;
- ActionCreatePreviewPtoParameters *createPreviewPtoParams;
- ActionCreateMKParameters *createMKParams;
- ActionMakeFile *nonaFileParams;
- ActionMakeFile *stitchParams;
- ActionCopy *copyParams;
- };
-
-private:
-
- bool successFlag;
- bool isAbortedFlag;
-
- QPointer<KDcraw> rawProcess;
- KProcess *process;
-
-public:
-
- Task(QObject* parent = 0)
- : Job(parent), id(0), successFlag(false), isAbortedFlag(false), rawProcess(0), process(0)
- {
- }
-
- ~Task()
- {
- switch (action)
- {
- case PREPROCESS_INPUT:
- {
- delete preProcessingParams;
- break;
- }
- case CREATEPTO:
- {
- delete createPtoParams->itemUrlsMap;
- delete createPtoParams;
- break;
- }
- case CPFIND:
- {
- delete cpFindParams->ptoUrl;
- delete cpFindParams;
- break;
- }
- case CPCLEAN:
- {
- delete cpCleanParams->cpFindPtoUrl;
- delete cpCleanParams->cpCleanPtoUrl;
- delete cpCleanParams;
- break;
- }
- case OPTIMIZE:
- {
- delete optimizeParams;
- break;
- }
- case CREATEPREVIEWPTO:
- {
- delete createPreviewPtoParams;
- break;
- }
- case CREATEMK:
- case CREATEMKPREVIEW:
- {
- delete createMKParams->ptoUrl;
- delete createMKParams;
- break;
- }
- case NONAFILE:
- case NONAFILEPREVIEW:
- {
- delete nonaFileParams;
- break;
- }
- case STITCH:
- case STITCHPREVIEW:
- {
- delete stitchParams->mkUrl;
- delete stitchParams->panoUrl;
- delete stitchParams;
- break;
- }
- case COPY:
- {
- delete copyParams;
- break;
- }
- case NONE:
- {
- break;
- }
- }
- }
-
- void requestAbort ()
- {
- isAbortedFlag = true;
-
- if (!rawProcess.isNull())
- {
- rawProcess->cancel();
- }
-
- if (process != 0)
- {
- process->kill();
- }
- }
-
- bool success() const
- {
- return successFlag;
- }
-
-protected:
-
- void run()
- {
- switch (action)
- {
- case PREPROCESS_INPUT:
- {
- kDebug() << "Starting Preview Generation" << id;
- successFlag = preprocessFile();
- kDebug() << "Preview Generated" << id;
- break;
- }
- case CREATEPTO:
- {
- kDebug() << "Starting Initial PTO Generation";
- successFlag = createPTO();
- kDebug() << "Initial PTO Generated";
- break;
- }
- case CPFIND:
- {
- kDebug() << "Starting CPFind";
- successFlag = startCPFind();
- kDebug() << "CPFind finished";
- break;
- }
- case CPCLEAN:
- {
- kDebug() << "Starting CPClean";
- successFlag = startCPClean();
- kDebug() << "CPClean finished";
- break;
- }
- case OPTIMIZE:
- {
- kDebug() << "Starting Optimization";
- successFlag = startOptimization();
- kDebug() << "Optimization finished";
- break;
- }
- case CREATEPREVIEWPTO:
- {
- kDebug() << "Starting Preview PTO Generation";
- successFlag = createPreviewPto();
- kDebug() << "Preview PTO Generated";
- break;
- }
- case CREATEMK:
- case CREATEMKPREVIEW:
- {
- kDebug() << "Starting Makefile Generation";
- successFlag = createMK();
- kDebug() << "Makefile Generated";
- break;
- }
- case NONAFILE:
- case NONAFILEPREVIEW:
- {
- kDebug() << "Starting Step" << id << "Of Panorama Compilation";
- successFlag = compileMKStep();
- kDebug() << "Panorama Compilation Step" << id << "Finished";
- break;
- }
- case STITCH:
- case STITCHPREVIEW:
- {
- kDebug() << "Starting Panorama Stitching";
- successFlag = compileMK();
- kDebug() << "Panorama Stitched";
- break;
- }
- case COPY:
- {
- kDebug() << "Starting Panorama Copy";
- successFlag = copyFiles();
- kDebug() << "Panorama Copied";
- break;
- }
- case NONE:
- {
- kError() << "Unknown action specified";
- }
- }
- }
-
-private:
-
- bool preprocessFile()
- {
- if (isRawFile(preProcessingParams->fileUrl.toLocalFile()))
- {
- preProcessingParams->preProcessedUrls->preprocessedUrl = tmpDir;
-
- if (!convertRaw())
- {
- return false;
- }
- }
- else
- {
- // NOTE: in this case, preprocessed Url is the original file Url.
- preProcessingParams->preProcessedUrls->preprocessedUrl = preProcessingParams->fileUrl;
- }
-
- preProcessingParams->preProcessedUrls->previewUrl = tmpDir;
-
- if (!computePreview(preProcessingParams->preProcessedUrls->preprocessedUrl))
- {
- return false;
- }
-
- return true;
- }
-
- bool computePreview(const KUrl& inUrl)
- {
- KUrl& outUrl = preProcessingParams->preProcessedUrls->previewUrl;
-
- QFileInfo fi(inUrl.toLocalFile());
- outUrl.setFileName(fi.completeBaseName().replace('.', '_') + QString("-preview.jpg"));
-
- QImage img;
- if (img.load(inUrl.toLocalFile()))
- {
- QImage preview = img.scaled(1280, 1024, Qt::KeepAspectRatio);
- bool saved = preview.save(outUrl.toLocalFile(), "JPEG");
- // save exif information also to preview image for auto rotation
- if (saved)
- {
- KPMetadata metaIn(inUrl.toLocalFile());
- KPMetadata metaOut(outUrl.toLocalFile());
- metaOut.setImageOrientation(metaIn.getImageOrientation());
- metaOut.setImageDimensions(QSize(preview.width(), preview.height()));
- metaOut.applyChanges();
- }
- kDebug() << "Preview Image url: " << outUrl << ", saved: " << saved;
- return saved;
- }
- else
- {
- errString = i18n("Input image cannot be loaded for preview generation");
- }
- return false;
- }
-
- static bool isRawFile(const KUrl& url)
- {
- QString rawFilesExt(KDcraw::rawFiles());
-
- QFileInfo fileInfo(url.toLocalFile());
- if (rawFilesExt.toUpper().contains(fileInfo.suffix().toUpper()))
- return true;
-
- return false;
- }
-
- bool convertRaw()
- {
- KUrl &inUrl = preProcessingParams->fileUrl;
- KUrl &outUrl = preProcessingParams->preProcessedUrls->preprocessedUrl;
-
- int width, height, rgbmax;
- QByteArray imageData;
-
- rawProcess = new KDcraw;
- bool decoded = rawProcess->decodeRAWImage(inUrl.toLocalFile(), preProcessingParams->settings, imageData, width, height, rgbmax);
-
-
- if (decoded)
- {
- uchar* sptr = (uchar*)imageData.data();
- float factor = 65535.0 / rgbmax;
- unsigned short tmp16[3];
-
- // Set RGB color components.
- for (int i = 0 ; !isAbortedFlag && (i < width * height) ; ++i)
- {
- // Swap Red and Blue and re-ajust color component values
- tmp16[0] = (unsigned short)((sptr[5]*256 + sptr[4]) * factor); // Blue
- tmp16[1] = (unsigned short)((sptr[3]*256 + sptr[2]) * factor); // Green
- tmp16[2] = (unsigned short)((sptr[1]*256 + sptr[0]) * factor); // Red
- memcpy(&sptr[0], &tmp16[0], 6);
- sptr += 6;
- }
-
- if (isAbortedFlag)
- {
- errString = i18n("Operation canceled.");
- return false;
- }
-
- KPMetadata metaIn, metaOut;
- metaIn.load(inUrl.toLocalFile());
- KPMetadata::MetaDataMap m = metaIn.getExifTagsDataList(QStringList("Photo"), true);
- KPMetadata::MetaDataMap::iterator it;
- for (it = m.begin(); it != m.end(); ++it)
- {
- metaIn.removeExifTag(it.key().toAscii().data(), false);
- }
- metaOut.setData(metaIn.data());
- metaOut.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
- metaOut.setImageDimensions(QSize(width, height));
- metaOut.setExifTagString("Exif.Image.DocumentName", inUrl.fileName());
- metaOut.setXmpTagString("Xmp.tiff.Make", metaOut.getExifTagString("Exif.Image.Make"));
- metaOut.setXmpTagString("Xmp.tiff.Model", metaOut.getExifTagString("Exif.Image.Model"));
- metaOut.setImageOrientation(KPMetadata::ORIENTATION_NORMAL);
-
- QByteArray prof = KPWriteImage::getICCProfilFromFile(preProcessingParams->settings.outputColorSpace);
-
- KPWriteImage wImageIface;
- wImageIface.setCancel(&isAbortedFlag);
- wImageIface.setImageData(imageData, width, height, true, false, prof, metaOut);
- QFileInfo fi(inUrl.toLocalFile());
- outUrl.setFileName(fi.completeBaseName().replace('.', '_') + QString(".tif"));
-
- if (!wImageIface.write2TIFF(outUrl.toLocalFile()))
- {
- errString = i18n("Tiff image creation failed.");
- return false;
- }
- else
- {
- metaOut.save(outUrl.toLocalFile());
- }
- }
- else
- {
- errString = i18n("Raw file conversion failed.");
- return false;
- }
-
- kDebug() << "Convert RAW output url: " << outUrl;
-
- return true;
- }
-
- bool createPTO()
- {
- (*createPtoParams->ptoUrl) = tmpDir;
- createPtoParams->ptoUrl->setFileName(QString("pano_base.pto"));
-
- QFile pto(createPtoParams->ptoUrl->toLocalFile());
- if (pto.exists())
- {
- errString = i18n("PTO file already created in the temporary directory.");
- return false;
- }
- if (!pto.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
- {
- errString = i18n("PTO file cannot be created in the temporary directory.");
- return false;
- }
-
- QTextStream pto_stream(&pto);
-
- // The pto is created following the file format described here:
- // http://hugin.sourceforge.net/docs/nona/nona.txt
-
- // 1. Project parameters
- pto_stream << "p";
- pto_stream << " f1"; // Cylindrical projection
- pto_stream << " n\"TIFF_m c:LZW\"";
- pto_stream << " R" << (createPtoParams->hdr ? '1' : '0');// HDR output
- //pto_stream << " T\"FLOAT\""; // 32bits color depth
- //pto_stream << " S," << X_left << "," << X_right << "," << X_top << "," << X_bottom; // Crop values
- pto_stream << " k0"; // Reference image
- pto_stream << endl;
-
- // 2. Images
- pto_stream << endl;
- int i = 0;
- for (i = 0; i < createPtoParams->inputFiles->size(); ++i)
- {
- KUrl inputFile(createPtoParams->inputFiles->at(i));
- KUrl preprocessedUrl(createPtoParams->itemUrlsMap->value(inputFile).preprocessedUrl);
- KPMetadata meta;
- meta.load(preprocessedUrl.toLocalFile());
- QSize size = meta.getPixelSize();
-
- pto_stream << "i";
- pto_stream << " f0"; // Lens projection type (rectilinear)
- pto_stream << " w" << size.width(); // Image width
- pto_stream << " h" << size.height(); // Image height
- if (i > 0)
- {
- // We suppose that the pictures are all taken with the same camera and lens
- pto_stream << " a=0 b=0 c=0 d=0 e=0 v=0 g=0 t=0"; // Geometry
- pto_stream << " Va=0 Vb=0 Vc=0 Vd=0 Vx=0 Vy=0"; // Vignetting
- }
- pto_stream << " n\"" << preprocessedUrl.toLocalFile() << '"';
- pto_stream << endl;
- }
-
- // 3. Variables to optimize
- pto_stream << endl;
- // Geometry optimization
- pto_stream << "v a0" << endl;
- pto_stream << "v b0" << endl;
- pto_stream << "v c0" << endl;
- pto_stream << "v d0" << endl;
- pto_stream << "v e0" << endl;
- pto_stream << "v Va0" << endl;
- pto_stream << "v Vb0" << endl;
- pto_stream << "v Vc0" << endl;
- pto_stream << "v Vd0" << endl;
- pto_stream << "v Vx0" << endl;
- pto_stream << "v Vy0" << endl;
- for (int j = 0; j < i; ++j)
- {
- // Colors optimization
- pto_stream << "v Ra" << j << endl;
- pto_stream << "v Rb" << j << endl;
- pto_stream << "v Rc" << j << endl;
- pto_stream << "v Rd" << j << endl;
- pto_stream << "v Re" << j << endl;
- pto_stream << "v Eev" << j << endl;
- pto_stream << "v Erv" << j << endl;
- pto_stream << "v Ebv" << j << endl;
- // Position optimization
- pto_stream << "v y" << j << endl;
- pto_stream << "v p" << j << endl;
- pto_stream << "v r" << j << endl;
- }
-
- switch (createPtoParams->fileType)
- {
- case TIFF:
- pto_stream << "#hugin_outputImageType tif" << endl;
- pto_stream << "#hugin_outputImageTypeCompression LZW" << endl;
- break;
- case JPEG:
- pto_stream << "#hugin_outputImageType jpg" << endl;
- pto_stream << "#hugin_outputJPEGQuality 95" << endl;
- break;
- }
-
- pto.close();
-
- return true;
- }
-
- bool startCPFind()
- {
- // Run CPFind to get control points and order the images
-
- (*cpFindParams->cpFindPtoUrl) = tmpDir;
- cpFindParams->cpFindPtoUrl->setFileName(QString("cp_pano.pto"));
-
- process = new KProcess();
- process->clearProgram();
- process->setWorkingDirectory(tmpDir.toLocalFile());
- process->setOutputChannelMode(KProcess::MergedChannels);
- process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
-
- QStringList args;
- args << cpFindParams->cpFindPath;
- if (cpFindParams->celeste)
- args << "--celeste";
- args << "-o";
- args << cpFindParams->cpFindPtoUrl->toLocalFile();
- args << cpFindParams->ptoUrl->toLocalFile();
-
- process->setProgram(args);
-
- kDebug() << "CPFind command line: " << process->program();
-
- process->start();
-
- if (!process->waitForFinished(-1) || process->exitCode() != 0)
- {
- errString = getProcessError(process);
- delete process;
- return false;
- }
-
- delete process;
-
- return true;
- }
-
- bool startCPClean()
- {
- (*cpCleanParams->cpCleanPtoUrl) = tmpDir;
- cpCleanParams->cpCleanPtoUrl->setFileName(QString("cp_pano_clean.pto"));
-
- process = new KProcess();
- process->clearProgram();
- process->setWorkingDirectory(tmpDir.toLocalFile());
- process->setOutputChannelMode(KProcess::MergedChannels);
- process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
-
- QStringList args;
- args << cpCleanParams->cpCleanPath;
- args << "-o";
- args << cpCleanParams->cpCleanPtoUrl->toLocalFile();
- args << cpCleanParams->cpFindPtoUrl->toLocalFile();
-
- process->setProgram(args);
-
- kDebug() << "CPClean command line: " << process->program();
-
- process->start();
-
- if (!process->waitForFinished(-1) || process->exitCode() != 0)
- {
- errString = getProcessError(process);
- return false;
- }
-
- cpCleanParams->ptoUrlData = new PTOType();
- if (!PTOParser::parseFile(cpCleanParams->cpCleanPtoUrl->toLocalFile(), *cpCleanParams->ptoUrlData))
- {
- kDebug() << "Parse Failed!!";
- }
-
- return true;
- }
-
- static QString getProcessError(KProcess* proc)
- {
- if (!proc)
- return QString();
-
- QString std = proc->readAll();
- return (i18n("Cannot run %1:\n\n %2", proc->program()[0], std));
- }
-
- bool startOptimization()
- {
- (*optimizeParams->autoOptimiserPtoUrl) = tmpDir;
- optimizeParams->autoOptimiserPtoUrl->setFileName(QString("auto_op_pano.pto"));
-
- process = new KProcess();
- process->clearProgram();
- process->setWorkingDirectory(tmpDir.toLocalFile());
- process->setOutputChannelMode(KProcess::MergedChannels);
- process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
-
- QStringList argsAO;
- argsAO << optimizeParams->autooptimiserPath;
- argsAO << "-am";
- if (optimizeParams->levelHorizon)
- {
- argsAO << "-l";
- }
- if (optimizeParams->optimizeProjectionAndSize)
- {
- argsAO << "-s";
- }
- argsAO << "-o";
- argsAO << optimizeParams->autoOptimiserPtoUrl->toLocalFile();
- argsAO << optimizeParams->ptoUrl->toLocalFile();
-
- process->setProgram(argsAO);
-
- kDebug() << "autooptimiser command line: " << process->program();
-
- process->start();
-
- if (!process->waitForFinished(-1) || process->exitCode() != 0)
- {
- errString = getProcessError(process);
- return false;
- }
-
- return true;
- }
-
- bool createPreviewPto()
- {
- kDebug() << "Preview Generation (" << createPreviewPtoParams->ptoUrl.toLocalFile() << ")";
- QFile input(createPreviewPtoParams->ptoUrl.toLocalFile());
- QStringList pto;
- if (!input.open(QIODevice::ReadOnly | QIODevice::Text))
- {
- errString = i18n("Cannot read project file.");
- kDebug() << "Can't read PTO File!";
- return false;
- }
- else
- {
- QTextStream in(&input);
- while (!in.atEnd())
- {
- pto.append(in.readLine());
- }
- input.close();
- }
-
- if (pto.count() == 0)
- {
- errString = i18n("Empty project file.");
- kDebug() << "Pto file empty!!";
- return false;
- }
-
- (*createPreviewPtoParams->previewPtoUrl) = tmpDir;
- createPreviewPtoParams->previewPtoUrl->setFileName("preview.pto");
- QFile output(createPreviewPtoParams->previewPtoUrl->toLocalFile());
- if (!output.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
- {
- errString = i18n("Preview project file cannot be created.");
- kDebug() << "Can't create a new PTO File!";
- return false;
- }
-
- QTextStream previewPtoStream(&output);
-
- KPMetadata metaIn(createPreviewPtoParams->preProcessedUrlsMap.begin().value().preprocessedUrl.toLocalFile());
- KPMetadata metaOut(createPreviewPtoParams->preProcessedUrlsMap.begin().value().previewUrl.toLocalFile());
- double scalingFactor = ((double) metaOut.getPixelSize().width()) / ((double) metaIn.getPixelSize().width());
-
- // TODO: change that to use boost::spirit (parser) and boost::karma (generator)
- foreach(const QString& line, pto)
- {
- if (line.isEmpty())
- {
- continue;
- }
-
- QString tmp;
- QStringList parameters = line.split(' ', QString::SkipEmptyParts);
-
- if (line[0] == 'p')
- {
- tmp.clear();
- foreach(const QString& p, parameters)
- {
- if (p[0] == 'w' || p[0] == 'h')
- {
- int size = ((double) (p.right(p.size() - 1)).toInt()) * scalingFactor;
- tmp.append(p[0]);
- tmp.append(QString::number(size));
- }
- else if (p[0] == 'n')
- {
- tmp.append("n\"JPEG q90\"");
- break; // n should be the last parameter (and the space before qXX introduce another parameter)
- }
- else
- {
- tmp.append(p);
- }
- tmp.append(" ");
- }
- }
- else if (line[0] == 'm')
- {
- tmp = line;
- }
- else if (line[0] == 'i')
- {
- tmp.clear();
- QStringList realParameters;
- bool nRead = false;
- foreach(const QString& p, parameters)
- {
- if (p[0] != 'n')
- {
- if (nRead)
- {
- realParameters[realParameters.size() - 1] += ' ' + p;
- }
- else
- {
- realParameters << p;
- }
- }
- else
- {
- nRead = true;
- realParameters << p;
- }
- }
- foreach(const QString& p, realParameters)
- {
- if (p[0] == 'w')
- {
- tmp.append("w");
- tmp.append(QString::number(metaOut.getPixelSize().width()));
- }
- else if (p[0] == 'h')
- {
- tmp.append("h");
- tmp.append(QString::number(metaOut.getPixelSize().height()));
- }
- else if (p[0] == 'n')
- {
- QString imgFileName = p.mid(2, p.size() - 3);
- KUrl imgUrl(KUrl(tmpDir), imgFileName);
- ItemUrlsMap::iterator it;
- ItemUrlsMap *ppum = &createPreviewPtoParams->preProcessedUrlsMap;
- for (it = (ItemUrlsMap::iterator) ppum->begin(); it != ppum->end() && it.value().preprocessedUrl != imgUrl; ++it);
- if (it == ppum->end())
- {
- input.close();
- errString = i18n("Unknown input file in the project file: %1", imgFileName);
- kDebug() << "Unknown input File in the PTO: " << imgFileName;
- kDebug() << "IMG: " << imgUrl.toLocalFile();
- return false;
- }
- tmp.append("n\"");
- tmp.append(it.value().previewUrl.fileName());
- tmp.append("\"");
- break;
- }
- else
- {
- tmp.append(p);
- }
- tmp.append(" ");
- }
- }
- else
- {
- continue;
- }
- previewPtoStream << tmp << endl;
- }
-
- // Add two commented line for a JPEG output
- previewPtoStream << "#hugin_outputImageType jpg" << endl;
- previewPtoStream << "#hugin_outputJPEGQuality 90" << endl;
-
- output.close();
-
- kDebug() << "Preview PTO File created: " << createPreviewPtoParams->ptoUrl.fileName();
-
- return true;
- }
-
- bool createMK()
- {
- QFileInfo fi(createMKParams->ptoUrl->toLocalFile());
- (*createMKParams->mkUrl) = tmpDir;
- createMKParams->mkUrl->setFileName(fi.completeBaseName() + QString(".mk"));
-
- (*createMKParams->panoUrl) = tmpDir;
- switch (createMKParams->fileType)
- {
- case JPEG:
- createMKParams->panoUrl->setFileName(fi.completeBaseName() + QString(".jpg"));
- break;
- case TIFF:
- createMKParams->panoUrl->setFileName(fi.completeBaseName() + QString(".tif"));
- break;
- }
-
- process = new KProcess();
- process->clearProgram();
- process->setWorkingDirectory(tmpDir.toLocalFile());
- process->setOutputChannelMode(KProcess::MergedChannels);
- process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
-
- QStringList args;
- args << createMKParams->pto2mkPath;
- args << "-o";
- args << createMKParams->mkUrl->toLocalFile();
- args << "-p";
- args << fi.completeBaseName();
- args << createMKParams->ptoUrl->toLocalFile();
-
- process->setProgram(args);
-
- kDebug() << "pto2mk command line: " << process->program();
-
- process->start();
-
- if (!process->waitForFinished(-1) || process->exitCode() != 0)
- {
- errString = getProcessError(process);
- return false;
- }
-
- /* Just replacing strings in the generated makefile to reflect the
- * location of the binaries of nona and enblend. This ensures that
- * the make process will be able to execute those binaries without
- * worring that any binary is not in the system path.
- */
- QFile mkUrlFile(createMKParams->mkUrl->toLocalFile());
- mkUrlFile.open(QIODevice::ReadWrite);
-
- QString fileData = mkUrlFile.readAll();
- fileData.replace("NONA=\"nona\"", QString("NONA=\"%1\"").arg(createMKParams->nonaPath));
- fileData.replace("ENBLEND=\"enblend\"", QString("ENBLEND=\"%1\"").arg(createMKParams->enblendPath));
-
- mkUrlFile.seek(0L);
- mkUrlFile.write(fileData.toAscii());
- mkUrlFile.close();
-
- return true;
- }
-
- bool compileMKStep()
- {
- QFileInfo fi(nonaFileParams->mkUrl->toLocalFile());
-
- process = new KProcess();
- process->clearProgram();
- process->setWorkingDirectory(tmpDir.toLocalFile());
- process->setOutputChannelMode(KProcess::MergedChannels);
- process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
-
- QString mkFile = fi.completeBaseName() + (id >= 10 ? (id >= 100 ? "0" : "00") : "000") + QString::number(id) + ".tif";
- QStringList args;
- args << nonaFileParams->makePath;
- args << "-f";
- args << nonaFileParams->mkUrl->toLocalFile();
- args << mkFile;
-
- process->setProgram(args);
- kDebug() << "make command line: " << process->program();
-
- process->start();
-
- if (!process->waitForFinished(-1) || process->exitCode() != 0)
- {
- errString = getProcessError(process);
- return false;
- }
-
- return true;
- }
-
- bool compileMK()
- {
- process = new KProcess();
- process->clearProgram();
- process->setWorkingDirectory(tmpDir.toLocalFile());
- process->setOutputChannelMode(KProcess::MergedChannels);
- process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
-
- QStringList args;
- args << stitchParams->makePath;
- args << "-f";
- args << stitchParams->mkUrl->toLocalFile();
-
- process->setProgram(args);
-
- kDebug() << "make command line: " << process->program();
-
- process->start();
-
- if (!process->waitForFinished(-1) || process->exitCode() != 0)
- {
- errString = getProcessError(process);
- return false;
- }
-
- return true;
- }
+ ActionThreadPriv()
+ : ptoUrl(0),
+ cpFindPtoUrl(0),
+ previewPtoUrl(0),
+ mkUrl(0),
+ preprocessingTmpDir(0)
+ {}

- bool copyFiles()
+ ~ActionThreadPriv()
{
- QFile panoFile(copyParams->panoUrl.toLocalFile());
- QFile finalPanoFile(copyParams->finalPanoUrl.toLocalFile());
-
- QFileInfo fi(copyParams->finalPanoUrl.toLocalFile());
- KUrl finalPTOUrl(copyParams->finalPanoUrl);
- finalPTOUrl.setFileName(fi.completeBaseName() + ".pto");
- QFile ptoFile(copyParams->ptoUrl.toLocalFile());
- QFile finalPTOFile(finalPTOUrl.toLocalFile());
+ cleanPreprocessingTmpDir();

- if (!panoFile.exists())
- {
- errString = i18n("Temporary panorama file does not exists.");
- kDebug() << "Temporary panorama file does not exists: " + copyParams->panoUrl.toLocalFile();
- return false;
- }
- if (finalPanoFile.exists())
+ if (ptoUrl)
{
- errString = i18n("A file named %1 already exists.", copyParams->finalPanoUrl.fileName());
- kDebug() << "Final panorama file already exists: " + copyParams->finalPanoUrl.toLocalFile();
- return false;
+ delete ptoUrl;
+ ptoUrl = 0;
}
- if (copyParams->savePTO && !ptoFile.exists())
+ if (cpFindPtoUrl)
{
- errString = i18n("Temporary project file does not exist.");
- kDebug() << "Temporary project file does not exists: " + copyParams->ptoUrl.toLocalFile();
- return false;
+ delete cpFindPtoUrl;
+ cpFindPtoUrl = 0;
}
- if (copyParams->savePTO && finalPTOFile.exists())
+ if (previewPtoUrl)
{
- errString = i18n("A file named %1 already exists.", finalPTOUrl.fileName());
- kDebug() << "Final project file already exists: " + finalPTOUrl.toLocalFile();
- return false;
+ delete previewPtoUrl;
+ previewPtoUrl = 0;
}
-
- kDebug() << "Copying panorama file...";
- if (!panoFile.copy(copyParams->finalPanoUrl.toLocalFile()) || !panoFile.remove())
+ if (mkUrl)
{
- errString = i18n("Cannot move panorama from %1 to %2.",
- copyParams->panoUrl.toLocalFile(),
- copyParams->finalPanoUrl.toLocalFile());
- kDebug() << "Cannot move panorama: QFile error = " + panoFile.error();
- return false;
+ delete mkUrl;
+ mkUrl = 0;
}
-
- if (copyParams->savePTO)
- {
- kDebug() << "Copying project file...";
- if (!ptoFile.copy(finalPTOUrl.toLocalFile()))
- {
- errString = i18n("Cannot move project file from %1 to %2.",
- copyParams->panoUrl.toLocalFile(),
- copyParams->finalPanoUrl.toLocalFile());
- return false;
- }
-
- kDebug() << "Copying converted RAW files...";
- for (ItemUrlsMap::iterator i = (ItemUrlsMap::iterator) copyParams->urlList->begin(); i != copyParams->urlList->end(); ++i)
- {
- if (isRawFile(i.key()))
- {
- KUrl finalImgUrl(copyParams->finalPanoUrl);
- finalImgUrl.setFileName(i->preprocessedUrl.fileName());
- QFile imgFile(i->preprocessedUrl.toLocalFile());
- if (!imgFile.copy(finalImgUrl.toLocalFile()))
- {
- errString = i18n("Cannot copy converted image file from %1 to %2.",
- i->preprocessedUrl.toLocalFile(),
- finalImgUrl.toLocalFile());
- return false;
- }
- }
- }
- }
-
- return true;
- }
-};
-
-struct ActionThread::ActionThreadPriv
-{
- ActionThreadPriv()
- : celeste(false),
- hdr(false),
- fileType(JPEG),
- preprocessingTmpDir(0)
- {
}

- bool celeste;
- bool hdr;
- PanoramaFileType fileType;
- RawDecodingSettings rawDecodingSettings;
+ KUrl* ptoUrl;
+ KUrl* cpFindPtoUrl;
+ KUrl* previewPtoUrl;
+ KUrl* mkUrl;

KTempDir* preprocessingTmpDir;

@@ -1143,22 +113,13 @@ ActionThread::ActionThread(QObject* const parent)

ActionThread::~ActionThread()
{
- d->cleanPreprocessingTmpDir();
-
delete d;
}

-void ActionThread::setPreProcessingSettings(bool celeste, bool hdr, PanoramaFileType fileType,
- const RawDecodingSettings& settings)
-{
- d->celeste = celeste;
- d->hdr = hdr;
- d->fileType = fileType;
- d->rawDecodingSettings = settings;
-}
-
-void ActionThread::preProcessFiles(const KUrl::List& urlList, const QString& cpCleanPath,
- const QString& cpFindPath)
+void ActionThread::preProcessFiles(const KUrl::List& urlList, ItemUrlsMap& preProcessedMap, KUrl& cpCleanPtoUrl,
+ PTOType& cpCleanPtoData, bool celeste, bool hdr,
+ PanoramaFileType fileType, const RawDecodingSettings& rawSettings,
+ const QString& cpCleanPath, const QString& cpFindPath)
{
d->cleanPreprocessingTmpDir();

@@ -1169,92 +130,91 @@ void ActionThread::preProcessFiles(const KUrl::List& urlList, const QString& cpC

JobCollection *jobs = new JobCollection();

- ItemUrlsMap *items = new ItemUrlsMap();
- KUrl *ptoUrl = new KUrl();
- KUrl *cpFindPtoUrl = new KUrl();
- Task *pto = new Task();
-
// TODO: try to append these jobs as a JobCollection inside a JobSequence
int id = 0;
+ QVector<PreProcessTask*> preProcessingTasks;
foreach (const KUrl& file, urlList)
{
- items->insert(file, ItemPreprocessedUrls());
+ preProcessedMap.insert(file, ItemPreprocessedUrls());

- Task *t = new Task();
- t->action = PREPROCESS_INPUT;
- t->tmpDir = d->preprocessingTmpDir->name();
- t->id = id++;
- t->preProcessingParams = new Task::ActionPreprocessParameters();
- t->preProcessingParams->fileUrl = file;
- t->preProcessingParams->settings = d->rawDecodingSettings;
- t->preProcessingParams->preProcessedUrls = &(*items)[file];
+ PreProcessTask *t = new PreProcessTask(d->preprocessingTmpDir->name(),
+ id++,
+ preProcessedMap[file],
+ file,
+ rawSettings);

connect(t, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
connect(t, SIGNAL(done(ThreadWeaver::Job*)),
this, SLOT(slotStepDone(ThreadWeaver::Job*)));

+ preProcessingTasks.append(t);
jobs->addJob(t);
- DependencyPolicy::instance().addDependency(pto, t);
}

- pto->action = CREATEPTO;
- pto->tmpDir = d->preprocessingTmpDir->name();
- pto->createPtoParams = new Task::ActionCreatePtoParameters();
- pto->createPtoParams->fileType = d->fileType;
- pto->createPtoParams->hdr = d->hdr;
- pto->createPtoParams->inputFiles = &urlList;
- pto->createPtoParams->itemUrlsMap = items;
- pto->createPtoParams->ptoUrl = ptoUrl;
+ if (d->ptoUrl)
+ {
+ // Just in case (shouldn't happen)
+ deletePtoUrl();
+ }
+ d->ptoUrl = new KUrl();
+ CreatePtoTask *pto = new CreatePtoTask(d->preprocessingTmpDir->name(),
+ fileType,
+ hdr,
+ *d->ptoUrl,
+ urlList,
+ preProcessedMap);

connect(pto, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
- connect(pto, SIGNAL(started(ThreadWeaver::Job*)),
- this, SLOT(slotExtractItemUrlMaps(ThreadWeaver::Job*)));
connect(pto, SIGNAL(done(ThreadWeaver::Job*)),
this, SLOT(slotStepDone(ThreadWeaver::Job*)));
- connect(pto, SIGNAL(done(ThreadWeaver::Job*)),
- this, SLOT(slotExtractPtoBase(ThreadWeaver::Job*)));

+ foreach (PreProcessTask *t, preProcessingTasks)
+ {
+ DependencyPolicy::instance().addDependency(pto, t);
+ }
jobs->addJob(pto);

- Task *cpFind = new Task();
- cpFind->action = CPFIND;
- cpFind->tmpDir = d->preprocessingTmpDir->name();
- cpFind->cpFindParams = new Task::ActionCPFindParameters();
- cpFind->cpFindParams->celeste = d->celeste;
- cpFind->cpFindParams->cpFindPath = cpFindPath;
- cpFind->cpFindParams->ptoUrl = ptoUrl;
- cpFind->cpFindParams->cpFindPtoUrl = cpFindPtoUrl;
+ if (d->cpFindPtoUrl)
+ {
+ // Just in case (shouldn't happen)
+ deleteCPFindPtoUrl();
+ }
+ d->cpFindPtoUrl = new KUrl();
+ CpFindTask *cpFind = new CpFindTask(d->preprocessingTmpDir->name(),
+ *d->ptoUrl,
+ *d->cpFindPtoUrl,
+ celeste,
+ cpFindPath);

connect(cpFind, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
connect(cpFind, SIGNAL(done(ThreadWeaver::Job*)),
this, SLOT(slotStepDone(ThreadWeaver::Job*)));
- connect(cpFind, SIGNAL(done(ThreadWeaver::Job*)),
- this, SLOT(slotExtractCpFindPto(ThreadWeaver::Job*)));

jobs->addJob(cpFind);
DependencyPolicy::instance().addDependency(cpFind, pto);

- Task *cpClean = new Task();
- cpClean->action = CPCLEAN;
- cpClean->tmpDir = d->preprocessingTmpDir->name();
- cpClean->cpCleanParams = new Task::ActionCPCleanParameters();
- cpClean->cpCleanParams->cpCleanPath = cpCleanPath;
- cpClean->cpCleanParams->cpFindPtoUrl = cpFindPtoUrl;
- cpClean->cpCleanParams->cpCleanPtoUrl = new KUrl();
+ CpCleanTask *cpClean = new CpCleanTask(d->preprocessingTmpDir->name(),
+ *d->cpFindPtoUrl,
+ cpCleanPtoUrl,
+ cpCleanPtoData,
+ cpCleanPath);

connect(cpClean, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
connect(cpClean, SIGNAL(done(ThreadWeaver::Job*)),
this, SLOT(slotDone(ThreadWeaver::Job*)));
- connect(cpClean, SIGNAL(done(ThreadWeaver::Job*)),
- this, SLOT(slotExtractCpCleanPto(ThreadWeaver::Job*)));

jobs->addJob(cpClean);
DependencyPolicy::instance().addDependency(cpClean, cpFind);

+ connect(jobs, SIGNAL(done(ThreadWeaver::Job*)),
+ this, SLOT(deletePtoUrl()));
+ connect(jobs, SIGNAL(done(ThreadWeaver::Job*)),
+ this, SLOT(deleteCPFindPtoUrl()));
+
appendJob(jobs);
}

@@ -1262,41 +222,40 @@ void ActionThread::optimizeProject(KUrl& ptoUrl, KUrl& optimizePtoUrl, bool leve
bool optimizeProjectionAndSize, const QString& autooptimiserPath)
{
JobCollection *jobs = new JobCollection();
- Task *t = new Task();
- t->action = OPTIMIZE;
- t->tmpDir = d->preprocessingTmpDir->name();
- t->optimizeParams = new Task::ActionOptimizeParameters();
- t->optimizeParams->autooptimiserPath = autooptimiserPath;
- t->optimizeParams->ptoUrl = &ptoUrl;
- t->optimizeParams->autoOptimiserPtoUrl = &optimizePtoUrl;
- t->optimizeParams->levelHorizon = levelHorizon;
- t->optimizeParams->optimizeProjectionAndSize = optimizeProjectionAndSize;
+
+ OptimisationTask *t = new OptimisationTask(d->preprocessingTmpDir->name(),
+ ptoUrl,
+ optimizePtoUrl,
+ levelHorizon,
+ optimizeProjectionAndSize,
+ autooptimiserPath);

connect(t, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
connect(t, SIGNAL(done(ThreadWeaver::Job*)),
this, SLOT(slotDone(ThreadWeaver::Job*)));
- connect(t, SIGNAL(done(ThreadWeaver::Job*)),
- this, SLOT(slotExtractOptimizePto(ThreadWeaver::Job*)));

jobs->addJob(t);

appendJob(jobs);
}

-void ActionThread::generatePanoramaPreview(const KUrl& ptoUrl, const ItemUrlsMap& preProcessedUrlsMap,
+void ActionThread::generatePanoramaPreview(const KUrl& ptoUrl, KUrl& previewUrl,
+ const ItemUrlsMap& preProcessedUrlsMap,
const QString& makePath, const QString& pto2mkPath,
const QString& enblendPath, const QString& nonaPath)
{
JobCollection *jobs = new JobCollection();

- Task *ptoTask = new Task();
- ptoTask->action = CREATEPREVIEWPTO;
- ptoTask->tmpDir = d->preprocessingTmpDir->name();
- ptoTask->createPreviewPtoParams = new Task::ActionCreatePreviewPtoParameters();
- ptoTask->createPreviewPtoParams->preProcessedUrlsMap = preProcessedUrlsMap;
- ptoTask->createPreviewPtoParams->ptoUrl = ptoUrl;
- ptoTask->createPreviewPtoParams->previewPtoUrl = new KUrl();
+ if (d->previewPtoUrl)
+ {
+ deletePreviewPtoUrl();
+ }
+ d->previewPtoUrl = new KUrl();
+ CreatePreviewTask *ptoTask = new CreatePreviewTask(d->preprocessingTmpDir->name(),
+ ptoUrl,
+ *d->previewPtoUrl,
+ preProcessedUrlsMap);

connect(ptoTask, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
@@ -1307,7 +266,8 @@ void ActionThread::generatePanoramaPreview(const KUrl& ptoUrl, const ItemUrlsMap

appendStitchingJobs(ptoTask,
jobs,
- ptoTask->createPreviewPtoParams->previewPtoUrl,
+ *d->previewPtoUrl,
+ previewUrl,
preProcessedUrlsMap,
JPEG,
makePath,
@@ -1316,17 +276,22 @@ void ActionThread::generatePanoramaPreview(const KUrl& ptoUrl, const ItemUrlsMap
nonaPath,
true);

+ connect(jobs, SIGNAL(done(ThreadWeaver::Job*)),
+ this, SLOT(deletePreviewPtoUrl()));
+
appendJob(jobs);
}

-void ActionThread::compileProject(const KUrl& ptoUrl, const ItemUrlsMap& preProcessedUrlsMap,
+void ActionThread::compileProject(const KUrl& ptoUrl, KUrl& panoUrl,
+ const ItemUrlsMap& preProcessedUrlsMap,
PanoramaFileType fileType, const QString& makePath, const QString& pto2mkPath,
const QString& enblendPath, const QString& nonaPath)
{
JobCollection *jobs = new JobCollection();
appendStitchingJobs(0,
jobs,
- new KUrl(ptoUrl),
+ ptoUrl,
+ panoUrl,
preProcessedUrlsMap,
fileType,
makePath,
@@ -1343,14 +308,12 @@ void ActionThread::copyFiles(const KUrl& ptoUrl, const KUrl& panoUrl, const KUrl
{
JobCollection *jobs = new JobCollection();

- Task *t = new Task();
- t->action = COPY;
- t->copyParams = new Task::ActionCopy();
- t->copyParams->ptoUrl = ptoUrl;
- t->copyParams->panoUrl = panoUrl;
- t->copyParams->finalPanoUrl = finalPanoUrl;
- t->copyParams->urlList = &preProcessedUrlsMap;
- t->copyParams->savePTO = savePTO;
+ CopyFilesTask *t = new CopyFilesTask(d->preprocessingTmpDir->name(),
+ panoUrl,
+ finalPanoUrl,
+ ptoUrl,
+ preProcessedUrlsMap,
+ savePTO);

connect(t, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
@@ -1362,162 +325,127 @@ void ActionThread::copyFiles(const KUrl& ptoUrl, const KUrl& panoUrl, const KUrl
appendJob(jobs);
}

-void ActionThread::slotExtractItemUrlMaps(Job* j)
+void ActionThread::slotStarting(Job* j)
{
Task *t = static_cast<Task*>(j);

- if (t->action != CREATEPTO)
- kError() << "Wrong task for item urls extraction!" << endl;
- else
- emit itemUrlsMapReady(*t->createPtoParams->itemUrlsMap);
-}
-
-void ActionThread::slotExtractPtoBase(Job* j)
-{
- Task *t = static_cast<Task*>(j);
+ ActionData ad;
+ ad.starting = true;
+ ad.action = t->action;
+ ad.id = -1;

- if (t->action != CREATEPTO)
+ if (t->action == NONAFILE || t->action == NONAFILE)
{
- kError() << "Wrong task for base pto url extraction!" << endl;
+ CompileMKStepTask* c = static_cast<CompileMKStepTask*>(j);
+ ad.id = c->id;
}
- if (t->success())
+ else if (t->action == PREPROCESS_INPUT)
{
- emit ptoBaseReady(*t->createPtoParams->ptoUrl);
+ PreProcessTask* p = static_cast<PreProcessTask*>(j);
+ ad.id = p->id;
}
+
+ emit starting(ad);
}

-void ActionThread::slotExtractCpFindPto(Job* j)
+void ActionThread::slotStepDone(Job* j)
{
Task *t = static_cast<Task*>(j);

- if (t->action != CPFIND)
+ ActionData ad;
+ ad.starting = false;
+ ad.action = t->action;
+ ad.id = -1;
+ ad.success = t->success();
+ ad.message = t->errString;
+
+ if (t->action == NONAFILE || t->action == NONAFILE)
{
- kError() << "Wrong task for base pto url extraction!" << endl;
+ CompileMKStepTask* c = static_cast<CompileMKStepTask*>(j);
+ ad.id = c->id;
}
- if (t->success())
+ else if (t->action == PREPROCESS_INPUT)
{
- emit cpFindPtoReady(*t->cpFindParams->cpFindPtoUrl);
+ PreProcessTask* p = static_cast<PreProcessTask*>(j);
+ ad.id = p->id;
}
-}

-void ActionThread::slotExtractCpCleanPto(Job* j)
-{
- Task *t = static_cast<Task*>(j);
+ emit stepFinished(ad);

- if (t->action != CPCLEAN)
- {
- kError() << "Wrong task for base pto url extraction!" << endl;
- }
- if (t->success())
- {
- emit cpCleanPtoReady(*t->cpCleanParams->cpCleanPtoUrl);
- }
+ ((QObject*) t)->deleteLater();
}

-void ActionThread::slotExtractOptimizePto(Job* j)
+void ActionThread::slotDone(Job* j)
{
Task *t = static_cast<Task*>(j);

- if (t->action != OPTIMIZE)
+ ActionData ad;
+ ad.starting = false;
+ ad.action = t->action;
+ ad.id = -1;
+ ad.success = t->success();
+ ad.message = t->errString;
+
+ if (t->action == NONAFILE || t->action == NONAFILE)
{
- kError() << "Wrong task for base pto url extraction!" << endl;
+ CompileMKStepTask* c = static_cast<CompileMKStepTask*>(j);
+ ad.id = c->id;
}
- if (t->success())
+ else if (t->action == PREPROCESS_INPUT)
{
- emit optimizePtoReady(*t->optimizeParams->autoOptimiserPtoUrl);
+ PreProcessTask* p = static_cast<PreProcessTask*>(j);
+ ad.id = p->id;
}
-}

-void ActionThread::slotExtractPreviewUrl(Job* j)
-{
- Task *t = static_cast<Task*>(j);
+ emit finished(ad);

- if (t->action != STITCHPREVIEW)
- {
- kError() << "Wrong task for base pto url extraction!" << endl;
- }
- if (t->success())
- {
- emit previewFileReady(*t->stitchParams->panoUrl);
- }
+ ((QObject*) t)->deleteLater();
}

-void ActionThread::slotExtractPanoUrl(Job* j)
+void ActionThread::deletePtoUrl()
{
- Task *t = static_cast<Task*>(j);
-
- if (t->action != STITCH)
- {
- kError() << "Wrong task for base pto url extraction!" << endl;
- }
- if (t->success())
- {
- emit panoFileReady(*t->stitchParams->panoUrl);
- }
+ delete d->ptoUrl;
+ d->ptoUrl = 0;
}

-void ActionThread::slotStarting(Job* j)
+void ActionThread::deleteCPFindPtoUrl()
{
- Task *t = static_cast<Task*>(j);
-
- ActionData ad;
- ad.starting = true;
- ad.id = t->id;
- ad.action = t->action;
-
- emit starting(ad);
+ delete d->cpFindPtoUrl;
+ d->cpFindPtoUrl = 0;
}

-void ActionThread::slotStepDone(Job* j)
+void ActionThread::deletePreviewPtoUrl()
{
- Task *t = static_cast<Task*>(j);
-
- ActionData ad;
- ad.starting = false;
- ad.id = t->id;
- ad.action = t->action;
- ad.success = t->success();
- ad.message = t->errString;
-
- emit stepFinished(ad);
-
- ((QObject*) t)->deleteLater();
+ delete d->previewPtoUrl;
+ d->previewPtoUrl = 0;
}

-void ActionThread::slotDone(Job* j)
+void ActionThread::deleteMkUrl()
{
- Task *t = static_cast<Task*>(j);
-
- ActionData ad;
- ad.starting = false;
- ad.id = t->id;
- ad.action = t->action;
- ad.success = t->success();
- ad.message = t->errString;
-
- emit finished(ad);
-
- ((QObject*) t)->deleteLater();
+ delete d->mkUrl;
+ d->mkUrl = 0;
}

-void ActionThread::appendStitchingJobs(Job* prevJob, JobCollection* jc, KUrl* ptoUrl, const ItemUrlsMap& preProcessedUrlsMap,
+void ActionThread::appendStitchingJobs(Job* prevJob, JobCollection* jc, const KUrl& ptoUrl,
+ KUrl& outputUrl, const ItemUrlsMap& preProcessedUrlsMap,
PanoramaFileType fileType, const QString& makePath, const QString& pto2mkPath,
const QString& enblendPath, const QString& nonaPath, bool preview)
{
- Task *createMKTask = new Task();
- if (preview)
- createMKTask->action = CREATEMKPREVIEW;
- else
- createMKTask->action = CREATEMK;
- createMKTask->tmpDir = d->preprocessingTmpDir->name();
- createMKTask->createMKParams = new Task::ActionCreateMKParameters();
- createMKTask->createMKParams->ptoUrl = ptoUrl;
- createMKTask->createMKParams->mkUrl = new KUrl();
- createMKTask->createMKParams->panoUrl = new KUrl();
- createMKTask->createMKParams->fileType = fileType;
- createMKTask->createMKParams->pto2mkPath = pto2mkPath;
- createMKTask->createMKParams->nonaPath = nonaPath;
- createMKTask->createMKParams->enblendPath = enblendPath;
+ if (d->mkUrl)
+ {
+ // Just in case (shouldn't happen)
+ deleteMkUrl();
+ }
+ d->mkUrl = new KUrl();
+ CreateMKTask *createMKTask = new CreateMKTask(d->preprocessingTmpDir->name(),
+ ptoUrl,
+ *d->mkUrl,
+ outputUrl,
+ fileType,
+ pto2mkPath,
+ nonaPath,
+ enblendPath,
+ preview);

connect(createMKTask, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
@@ -1530,19 +458,14 @@ void ActionThread::appendStitchingJobs(Job* prevJob, JobCollection* jc, KUrl* pt
}
jc->addJob(createMKTask);

- Task *compileMKTask = new Task();
+ QVector<CompileMKStepTask*> tasks;
for (int i = 0; i < preProcessedUrlsMap.size(); i++)
{
- Task *t = new Task();
- if (preview)
- t->action = NONAFILEPREVIEW;
- else
- t->action = NONAFILE;
- t->tmpDir = d->preprocessingTmpDir->name();
- t->id = i;
- t->nonaFileParams = new Task::ActionMakeFile();
- t->nonaFileParams->mkUrl = createMKTask->createMKParams->mkUrl;
- t->nonaFileParams->makePath = makePath;
+ CompileMKStepTask *t = new CompileMKStepTask(d->preprocessingTmpDir->name(),
+ i,
+ *d->mkUrl,
+ makePath,
+ preview);

connect(t, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
@@ -1550,36 +473,31 @@ void ActionThread::appendStitchingJobs(Job* prevJob, JobCollection* jc, KUrl* pt
this, SLOT(slotStepDone(ThreadWeaver::Job*)));

DependencyPolicy::instance().addDependency(t, createMKTask);
- DependencyPolicy::instance().addDependency(compileMKTask, t);
+
+ tasks.append(t);
jc->addJob(t);
}

- if (preview)
- compileMKTask->action = STITCHPREVIEW;
- else
- compileMKTask->action = STITCH;
- compileMKTask->tmpDir = d->preprocessingTmpDir->name();
- compileMKTask->stitchParams = new Task::ActionMakeFile();
- compileMKTask->stitchParams->mkUrl = createMKTask->createMKParams->mkUrl;
- compileMKTask->stitchParams->panoUrl = createMKTask->createMKParams->panoUrl;
- compileMKTask->stitchParams->makePath = makePath;
+ CompileMKTask *compileMKTask = new CompileMKTask(d->preprocessingTmpDir->name(),
+ *d->mkUrl,
+ outputUrl,
+ makePath,
+ preview);
+
+ foreach (CompileMKStepTask* t, tasks)
+ {
+ DependencyPolicy::instance().addDependency(compileMKTask, t);
+ }

connect(compileMKTask, SIGNAL(started(ThreadWeaver::Job*)),
this, SLOT(slotStarting(ThreadWeaver::Job*)));
connect(compileMKTask, SIGNAL(done(ThreadWeaver::Job*)),
this, SLOT(slotDone(ThreadWeaver::Job*)));
- if (preview)
- {
- connect(compileMKTask, SIGNAL(done(ThreadWeaver::Job*)),
- this, SLOT(slotExtractPreviewUrl(ThreadWeaver::Job*)));
- }
- else
- {
- connect(compileMKTask, SIGNAL(done(ThreadWeaver::Job*)),
- this, SLOT(slotExtractPanoUrl(ThreadWeaver::Job*)));
- }

jc->addJob(compileMKTask);
+
+ connect(jc, SIGNAL(done(ThreadWeaver::Job*)),
+ this, SLOT(deleteMkUrl()));
}

} // namespace KIPIPanoramaPlugin
diff --git a/panorama/manager/actionthread.h b/panorama/manager/actionthread.h
index eefebcd..e655c3c 100644
--- a/panorama/manager/actionthread.h
+++ b/panorama/manager/actionthread.h
@@ -7,7 +7,7 @@
* Description : a plugin to create panorama by fusion of several images.
* Acknowledge : based on the expoblending plugin
*
- * Copyright (C) 2011 by Benjamin Girault <benjamin dot girault at gmail dot com>
+ * Copyright (C) 2011-2012 by Benjamin Girault <benjamin dot girault at gmail dot com>
* Copyright (C) 2009-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2009-2011 by Johannes Wienke <languitar at semipol dot de>
*
@@ -59,32 +59,21 @@ class ActionThread : public KIPIPlugins::KPActionThreadBase

public:

- typedef enum
- {
- JPEG,
- TIFF
- }
- PanoramaFileType;
-
-private:
-
- class Task;
-
-public:
-
explicit ActionThread(QObject* const parent);
~ActionThread();

- void setPreProcessingSettings(bool celeste, bool hdr, PanoramaFileType fileType,
- const RawDecodingSettings& settings);
- void preProcessFiles(const KUrl::List& urlList, const QString& cpCleanPath,
- const QString& cpFindPath);
+ void preProcessFiles(const KUrl::List& urlList, ItemUrlsMap& preProcessedMap, KUrl& cpCleanPtoUrl,
+ PTOType& cpCleanPtoData, bool celeste, bool hdr,
+ PanoramaFileType fileType, const RawDecodingSettings& settings,
+ const QString& cpCleanPath, const QString& cpFindPath);
void optimizeProject(KUrl& ptoUrl, KUrl& optimizePtoUrl, bool levelHorizon,
bool optimizeProjectionAndSize, const QString& autooptimiserPath);
- void generatePanoramaPreview(const KUrl& ptoUrl, const ItemUrlsMap& preProcessedUrlsMap,
+ void generatePanoramaPreview(const KUrl& ptoUrl, KUrl& previewUrl,
+ const ItemUrlsMap& preProcessedUrlsMap,
const QString& makePath, const QString& pto2mkPath,
const QString& enblendPath, const QString& nonaPath);
- void compileProject(const KUrl& ptoUrl, const ItemUrlsMap& preProcessedUrlsMap,
+ void compileProject(const KUrl& ptoUrl, KUrl& panoUrl,
+ const ItemUrlsMap& preProcessedUrlsMap,
PanoramaFileType fileType, const QString& makePath, const QString& pto2mkPath,
const QString& enblendPath, const QString& nonaPath);
void copyFiles(const KUrl& ptoUrl, const KUrl& panoUrl, const KUrl& finalPanoUrl,
@@ -96,10 +85,6 @@ Q_SIGNALS:
void stepFinished(const KIPIPanoramaPlugin::ActionData& ad);
void finished(const KIPIPanoramaPlugin::ActionData& ad);

- void itemUrlsMapReady(const ItemUrlsMap& items);
- void ptoBaseReady(const KUrl& ptoUrl);
- void cpFindPtoReady(const KUrl& cpFindPtoUrl);
- void cpCleanPtoReady(const KUrl& cpCleanPtoUrl);
void optimizePtoReady(const KUrl& optimizePtoUrl);
void previewFileReady(const KUrl& previewFileUrl);
void panoFileReady(const KUrl& panoFileUrl);
@@ -110,17 +95,15 @@ private Q_SLOTS:
void slotStepDone(ThreadWeaver::Job* j);
void slotStarting(ThreadWeaver::Job* j);

- void slotExtractItemUrlMaps(ThreadWeaver::Job* j);
- void slotExtractPtoBase(ThreadWeaver::Job* j);
- void slotExtractCpFindPto(ThreadWeaver::Job* j);
- void slotExtractCpCleanPto(ThreadWeaver::Job* j);
- void slotExtractOptimizePto(ThreadWeaver::Job* j);
- void slotExtractPreviewUrl(ThreadWeaver::Job* j);
- void slotExtractPanoUrl(ThreadWeaver::Job* j);
+ void deletePtoUrl();
+ void deleteCPFindPtoUrl();
+ void deletePreviewPtoUrl();
+ void deleteMkUrl();

private:

- void appendStitchingJobs(Job* prevJob, JobCollection* jc, KUrl* ptoUrl, const ItemUrlsMap& preProcessedUrlsMap,
+ void appendStitchingJobs(Job* prevJob, JobCollection* jc, const KUrl& ptoUrl,
+ KUrl& outputUrl, const ItemUrlsMap& preProcessedUrlsMap,
PanoramaFileType fileType, const QString& makePath, const QString& pto2mkPath,
const QString& enblendPath, const QString& nonaPath, bool preview);

diff --git a/panorama/manager/manager.cpp b/panorama/manager/manager.cpp
index 9cbc0ec..1ba5240 100644
--- a/panorama/manager/manager.cpp
+++ b/panorama/manager/manager.cpp
@@ -61,7 +61,7 @@ struct Manager::ManagerPriv
group(config.group(QString("Panorama Settings")))
{
hdr = group.readEntry("HDR", false);
- fileType = (ActionThread::PanoramaFileType) group.readEntry("File Type", (int) ActionThread::JPEG);
+ fileType = (PanoramaFileType) group.readEntry("File Type", (int) JPEG);
}


@@ -80,7 +80,7 @@ struct Manager::ManagerPriv

bool hdr;

- ActionThread::PanoramaFileType fileType;
+ PanoramaFileType fileType;

ItemUrlsMap preProcessedUrlsMap;

@@ -113,15 +113,6 @@ Manager::Manager(QObject* parent)
{
d->thread = new ActionThread(this);
d->rawDecodingSettings.sixteenBitsImage = true;
-
- connect(d->thread, SIGNAL(itemUrlsMapReady(ItemUrlsMap)),
- this, SLOT(setPreProcessedMap(ItemUrlsMap)));
- connect(d->thread, SIGNAL(cpCleanPtoReady(KUrl)),
- this, SLOT(setCPFindUrl(KUrl)));
- connect(d->thread, SIGNAL(previewFileReady(KUrl)),
- this, SLOT(setPreviewUrl(KUrl)));
- connect(d->thread, SIGNAL(panoFileReady(KUrl)),
- this, SLOT(setPanoUrl(KUrl)));
}

Manager::~Manager()
@@ -156,15 +147,15 @@ bool Manager::hdr() const

void Manager::setFileFormatJPEG()
{
- d->fileType = ActionThread::JPEG;
+ d->fileType = JPEG;
}

void Manager::setFileFormatTIFF()
{
- d->fileType = ActionThread::TIFF;
+ d->fileType = TIFF;
}

-ActionThread::PanoramaFileType Manager::format() const
+PanoramaFileType Manager::format() const
{
return d->fileType;
}
diff --git a/panorama/manager/manager.h b/panorama/manager/manager.h
index 3743147..e658505 100644
--- a/panorama/manager/manager.h
+++ b/panorama/manager/manager.h
@@ -79,7 +79,7 @@ public:

void setFileFormatJPEG();
void setFileFormatTIFF();
- ActionThread::PanoramaFileType format() const;
+ PanoramaFileType format() const;

void setAbout(PanoramaAboutData* about);
PanoramaAboutData* about() const;
@@ -91,13 +91,9 @@ public:
KUrl::List& itemsList() const;

KUrl& cpFindUrl() const;
-
PTOType& cpFindUrlData() const;
-
KUrl& autoOptimiseUrl() const;
-
KUrl& previewUrl() const;
-
KUrl& panoUrl() const;

void setRawDecodingSettings(const RawDecodingSettings& settings);
diff --git a/panorama/tasks/compilemksteptask.cpp b/panorama/tasks/compilemksteptask.cpp
new file mode 100644
index 0000000..f62d529
--- /dev/null
+++ b/panorama/tasks/compilemksteptask.cpp
@@ -0,0 +1,101 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "compilemksteptask.h"
+
+// Qt includes
+
+#include <QFileInfo>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+ CompileMKStepTask::CompileMKStepTask(QObject* parent, const KUrl& workDir, int id, const KUrl& mkUrl,
+ const QString& makePath, bool preview)
+ : Task(parent, preview ? NONAFILEPREVIEW : NONAFILE, workDir),
+ id(id), mkUrl(&mkUrl), makePath(makePath), process(0)
+{}
+
+CompileMKStepTask::CompileMKStepTask(const KUrl& workDir, int id, const KUrl& mkUrl,
+ const QString& makePath, bool preview)
+ : Task(0, preview ? NONAFILEPREVIEW : NONAFILE, workDir), id(id),
+ mkUrl(&mkUrl), makePath(makePath), process(0)
+{}
+
+CompileMKStepTask::~CompileMKStepTask()
+{
+ if (process)
+ {
+ delete process;
+ process = 0;
+ }
+}
+
+void CompileMKStepTask::requestAbort()
+{
+ process->kill();
+}
+
+void CompileMKStepTask::run()
+{
+ QFileInfo fi(mkUrl->toLocalFile());
+
+ process = new KProcess();
+ process->clearProgram();
+ process->setWorkingDirectory(tmpDir.toLocalFile());
+ process->setOutputChannelMode(KProcess::MergedChannels);
+ process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
+
+ QString mkFile = fi.completeBaseName() + (id >= 10 ? (id >= 100 ? "0" : "00") : "000") + QString::number(id) + ".tif";
+ QStringList args;
+ args << makePath;
+ args << "-f";
+ args << mkUrl->toLocalFile();
+ args << mkFile;
+
+ process->setProgram(args);
+ kDebug() << "make command line: " << process->program();
+
+ process->start();
+
+ if (!process->waitForFinished(-1) || process->exitCode() != 0)
+ {
+ errString = getProcessError(*process);
+ successFlag = false;
+ }
+ else
+ {
+ successFlag = true;
+ }
+
+ delete process;
+ process = 0;
+
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/compilemksteptask.h b/panorama/tasks/compilemksteptask.h
new file mode 100644
index 0000000..df4ad43
--- /dev/null
+++ b/panorama/tasks/compilemksteptask.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 COMPILEMKSTEPTASK_H
+#define COMPILEMKSTEPTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CompileMKStepTask : public Task
+{
+
+public:
+
+ const int id;
+
+private:
+
+ const KUrl* const mkUrl;
+ const QString makePath;
+
+ KProcess* process;
+
+public:
+
+ CompileMKStepTask(QObject* parent, const KUrl& workDir, int id, const KUrl& mkUrl,
+ const QString& makePath, bool preview);
+ CompileMKStepTask(const KUrl& workDir, int id, const KUrl& mkUrl,
+ const QString& makePath, bool preview);
+ ~CompileMKStepTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* COMPILEMKSTEPTASK_H */
diff --git a/panorama/tasks/compilemktask.cpp b/panorama/tasks/compilemktask.cpp
new file mode 100644
index 0000000..d7050f5
--- /dev/null
+++ b/panorama/tasks/compilemktask.cpp
@@ -0,0 +1,94 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "compilemktask.h"
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+CompileMKTask::CompileMKTask(QObject* parent, const KUrl& workDir, const KUrl& mkUrl,
+ const KUrl& panoUrl, const QString& makePath, bool preview)
+ : Task(parent, preview ? STITCHPREVIEW : STITCH, workDir),
+ panoUrl(&panoUrl), mkUrl(&mkUrl), makePath(makePath), process(0)
+{}
+
+CompileMKTask::CompileMKTask(const KUrl& workDir, const KUrl& mkUrl,
+ const KUrl& panoUrl, const QString& makePath, bool preview)
+ : Task(0, preview ? STITCHPREVIEW : STITCH, workDir),
+ panoUrl(&panoUrl), mkUrl(&mkUrl), makePath(makePath), process(0)
+{}
+
+CompileMKTask::~CompileMKTask()
+{
+ if (process)
+ {
+ delete process;
+ process = 0;
+ }
+}
+
+void CompileMKTask::requestAbort()
+{
+ process->kill();
+}
+
+void CompileMKTask::run()
+{
+ process = new KProcess();
+ process->clearProgram();
+ process->setWorkingDirectory(tmpDir.toLocalFile());
+ process->setOutputChannelMode(KProcess::MergedChannels);
+ process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
+
+ QStringList args;
+ args << makePath;
+ args << "-f";
+ args << mkUrl->toLocalFile();
+
+ process->setProgram(args);
+
+ kDebug() << "make command line: " << process->program();
+
+ process->start();
+
+ if (!process->waitForFinished(-1) || process->exitCode() != 0)
+ {
+ errString = getProcessError(*process);
+ successFlag = false;
+ }
+ else
+ {
+ successFlag = true;
+ }
+
+ delete process;
+ process = 0;
+
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/compilemktask.h b/panorama/tasks/compilemktask.h
new file mode 100644
index 0000000..1af1048
--- /dev/null
+++ b/panorama/tasks/compilemktask.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 COMPILEMKTASK_H
+#define COMPILEMKTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CompileMKTask : public Task
+{
+
+private:
+
+ const KUrl* const panoUrl;
+ const KUrl* const mkUrl;
+ const QString makePath;
+
+ KProcess* process;
+
+public:
+
+ CompileMKTask(QObject* parent, const KUrl& workDir, const KUrl& mkUrl,
+ const KUrl& panoUrl, const QString& makePath, bool preview);
+ CompileMKTask(const KUrl& workDir, const KUrl& mkUrl,
+ const KUrl& panoUrl, const QString& makePath, bool preview);
+ ~CompileMKTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* COMPILEMKTASK_H */
diff --git a/panorama/tasks/copyfilestask.cpp b/panorama/tasks/copyfilestask.cpp
new file mode 100644
index 0000000..eaa2fd7
--- /dev/null
+++ b/panorama/tasks/copyfilestask.cpp
@@ -0,0 +1,139 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "copyfilestask.h"
+
+// Qt includes
+
+#include <QFileInfo>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+CopyFilesTask::CopyFilesTask(QObject* parent, const KUrl& workDir, const KUrl& panoUrl, const KUrl& finalPanoUrl,
+ const KUrl& ptoUrl, const ItemUrlsMap& urls, bool savePTO)
+ : Task(parent, COPY, workDir), panoUrl(panoUrl), finalPanoUrl(finalPanoUrl),
+ ptoUrl(ptoUrl), urlList(&urls), savePTO(savePTO)
+{}
+
+CopyFilesTask::CopyFilesTask(const KUrl& workDir, const KUrl& panoUrl, const KUrl& finalPanoUrl,
+ const KUrl& ptoUrl, const ItemUrlsMap& urls, bool savePTO)
+ : Task(0, COPY, workDir), panoUrl(panoUrl), finalPanoUrl(finalPanoUrl),
+ ptoUrl(ptoUrl), urlList(&urls), savePTO(savePTO)
+{}
+
+CopyFilesTask::~CopyFilesTask()
+{}
+
+void CopyFilesTask::run()
+{
+ QFile panoFile(panoUrl.toLocalFile());
+ QFile finalPanoFile(finalPanoUrl.toLocalFile());
+
+ QFileInfo fi(finalPanoUrl.toLocalFile());
+ KUrl finalPTOUrl(finalPanoUrl);
+ finalPTOUrl.setFileName(fi.completeBaseName() + ".pto");
+ QFile ptoFile(ptoUrl.toLocalFile());
+ QFile finalPTOFile(finalPTOUrl.toLocalFile());
+
+ if (!panoFile.exists())
+ {
+ errString = i18n("Temporary panorama file does not exists.");
+ kDebug() << "Temporary panorama file does not exists: " + panoUrl.toLocalFile();
+ successFlag = false;
+ return;
+ }
+ if (finalPanoFile.exists())
+ {
+ errString = i18n("A file named %1 already exists.", finalPanoUrl.fileName());
+ kDebug() << "Final panorama file already exists: " + finalPanoUrl.toLocalFile();
+ successFlag = false;
+ return;
+ }
+ if (savePTO && !ptoFile.exists())
+ {
+ errString = i18n("Temporary project file does not exist.");
+ kDebug() << "Temporary project file does not exists: " + ptoUrl.toLocalFile();
+ successFlag = false;
+ return;
+ }
+ if (savePTO && finalPTOFile.exists())
+ {
+ errString = i18n("A file named %1 already exists.", finalPTOUrl.fileName());
+ kDebug() << "Final project file already exists: " + finalPTOUrl.toLocalFile();
+ successFlag = false;
+ return;
+ }
+
+ kDebug() << "Copying panorama file...";
+ if (!panoFile.copy(finalPanoUrl.toLocalFile()) || !panoFile.remove())
+ {
+ errString = i18n("Cannot move panorama from %1 to %2.",
+ panoUrl.toLocalFile(),
+ finalPanoUrl.toLocalFile());
+ kDebug() << "Cannot move panorama: QFile error = " + panoFile.error();
+ successFlag = false;
+ return;
+ }
+
+ if (savePTO)
+ {
+ kDebug() << "Copying project file...";
+ if (!ptoFile.copy(finalPTOUrl.toLocalFile()))
+ {
+ errString = i18n("Cannot move project file from %1 to %2.",
+ panoUrl.toLocalFile(),
+ finalPanoUrl.toLocalFile());
+ successFlag = false;
+ return;
+ }
+
+ kDebug() << "Copying converted RAW files...";
+ for (ItemUrlsMap::iterator i = (ItemUrlsMap::iterator) urlList->begin(); i != urlList->end(); ++i)
+ {
+ if (isRawFile(i.key()))
+ {
+ KUrl finalImgUrl(finalPanoUrl);
+ finalImgUrl.setFileName(i->preprocessedUrl.fileName());
+ QFile imgFile(i->preprocessedUrl.toLocalFile());
+ if (!imgFile.copy(finalImgUrl.toLocalFile()))
+ {
+ errString = i18n("Cannot copy converted image file from %1 to %2.",
+ i->preprocessedUrl.toLocalFile(),
+ finalImgUrl.toLocalFile());
+ successFlag = false;
+ return;
+ }
+ }
+ }
+ }
+
+ successFlag = true;
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/copyfilestask.h b/panorama/tasks/copyfilestask.h
new file mode 100644
index 0000000..5e252a4
--- /dev/null
+++ b/panorama/tasks/copyfilestask.h
@@ -0,0 +1,66 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 COPYFILESTASK_H
+#define COPYFILESTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CopyFilesTask : public Task
+{
+
+private:
+
+ const KUrl panoUrl;
+ const KUrl finalPanoUrl;
+ const KUrl ptoUrl;
+ const ItemUrlsMap* const urlList;
+ const bool savePTO;
+
+public:
+
+ CopyFilesTask(QObject* parent, const KUrl& workDir, const KUrl& panoUrl, const KUrl& finalPanoUrl,
+ const KUrl& ptoUrl, const ItemUrlsMap& urls, bool savePTO);
+ CopyFilesTask(const KUrl& workDir, const KUrl& panoUrl, const KUrl& finalPanoUrl,
+ const KUrl& ptoUrl, const ItemUrlsMap& urls, bool savePTO);
+ ~CopyFilesTask();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* COPYFILESTASK_H */
diff --git a/panorama/tasks/cpcleantask.cpp b/panorama/tasks/cpcleantask.cpp
new file mode 100644
index 0000000..c11b88d
--- /dev/null
+++ b/panorama/tasks/cpcleantask.cpp
@@ -0,0 +1,107 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "cpcleantask.h"
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+// Local includes
+
+#include "ptoparser.h"
+
+namespace KIPIPanoramaPlugin
+{
+
+CpCleanTask::CpCleanTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& cpCleanPtoUrl, PTOType& ptoUrlData, const QString& cpCleanPath)
+ : Task(parent, CPCLEAN, workDir), cpCleanPtoUrl(&cpCleanPtoUrl), ptoUrlData(&ptoUrlData),
+ cpFindPtoUrl(&input), cpCleanPath(cpCleanPath), process(0)
+{}
+
+CpCleanTask::CpCleanTask(const KUrl& workDir, const KUrl& input,
+ KUrl& cpCleanPtoUrl, PTOType& ptoUrlData, const QString& cpCleanPath)
+ : Task(0, CPCLEAN, workDir), cpCleanPtoUrl(&cpCleanPtoUrl), ptoUrlData(&ptoUrlData),
+ cpFindPtoUrl(&input), cpCleanPath(cpCleanPath), process(0)
+{}
+
+CpCleanTask::~CpCleanTask()
+{
+ if (process)
+ {
+ delete process;
+ process = 0;
+ }
+}
+
+void CpCleanTask::requestAbort()
+{
+ process->kill();
+}
+
+void CpCleanTask::run()
+{
+ (*cpCleanPtoUrl) = tmpDir;
+ cpCleanPtoUrl->setFileName(QString("cp_pano_clean.pto"));
+
+ process = new KProcess();
+ process->clearProgram();
+ process->setWorkingDirectory(tmpDir.toLocalFile());
+ process->setOutputChannelMode(KProcess::MergedChannels);
+ process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
+
+ QStringList args;
+ args << cpCleanPath;
+ args << "-o";
+ args << cpCleanPtoUrl->toLocalFile();
+ args << cpFindPtoUrl->toLocalFile();
+
+ process->setProgram(args);
+
+ kDebug() << "CPClean command line: " << process->program();
+
+ process->start();
+
+ if (!process->waitForFinished(-1) || process->exitCode() != 0)
+ {
+ errString = getProcessError(*process);
+ successFlag = false;
+ }
+ else
+ {
+ successFlag = true;
+ }
+
+ delete process;
+ process = 0;
+
+ if (successFlag && !PTOParser::parseFile(cpCleanPtoUrl->toLocalFile(), *ptoUrlData))
+ {
+ kDebug() << "Parse Failed!!";
+ }
+
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/cpcleantask.h b/panorama/tasks/cpcleantask.h
new file mode 100644
index 0000000..d5050d8
--- /dev/null
+++ b/panorama/tasks/cpcleantask.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 CPCLEANTASK_H
+#define CPCLEANTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CpCleanTask : public Task
+{
+
+private:
+
+ KUrl* const cpCleanPtoUrl;
+ PTOType* const ptoUrlData;
+ const KUrl* const cpFindPtoUrl;
+ const QString cpCleanPath;
+
+ KProcess* process;
+
+public:
+
+ CpCleanTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& cpCleanPtoUrl, PTOType& ptoUrlData, const QString& cpCleanPath);
+ CpCleanTask(const KUrl& workDir, const KUrl& input,
+ KUrl& cpCleanPtoUrl, PTOType& ptoUrlData, const QString& cpCleanPath);
+ ~CpCleanTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* CPCLEANTASK_H */
diff --git a/panorama/tasks/cpfindtask.cpp b/panorama/tasks/cpfindtask.cpp
new file mode 100644
index 0000000..27c289c
--- /dev/null
+++ b/panorama/tasks/cpfindtask.cpp
@@ -0,0 +1,102 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "cpfindtask.h"
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+CpFindTask::CpFindTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& cpFindUrl, bool celeste, const QString& cpFindPath)
+ : Task(parent, CPFIND, workDir), cpFindPtoUrl(&cpFindUrl),
+ celeste(celeste), ptoUrl(&input), cpFindPath(cpFindPath), process(0)
+{}
+
+CpFindTask::CpFindTask(const KUrl& workDir, const KUrl& input,
+ KUrl& cpFindUrl, bool celeste, const QString& cpFindPath)
+ : Task(0, CPFIND, workDir), cpFindPtoUrl(&cpFindUrl),
+ celeste(celeste), ptoUrl(&input), cpFindPath(cpFindPath), process(0)
+{}
+
+CpFindTask::~CpFindTask()
+{
+ if (process)
+ {
+ delete process;
+ process = 0;
+ }
+}
+
+void CpFindTask::requestAbort()
+{
+ process->kill();
+}
+
+void CpFindTask::run()
+{
+ // Run CPFind to get control points and order the images
+ (*cpFindPtoUrl) = tmpDir;
+ cpFindPtoUrl->setFileName(QString("cp_pano.pto"));
+
+ process = new KProcess();
+ process->clearProgram();
+ process->setWorkingDirectory(tmpDir.toLocalFile());
+ process->setOutputChannelMode(KProcess::MergedChannels);
+ process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
+
+ QStringList args;
+ args << cpFindPath;
+ if (celeste)
+ args << "--celeste";
+ args << "-o";
+ args << cpFindPtoUrl->toLocalFile();
+ args << ptoUrl->toLocalFile();
+
+ process->setProgram(args);
+
+ kDebug() << "CPFind command line: " << process->program();
+
+ process->start();
+
+ if (!process->waitForFinished(-1) || process->exitCode() != 0)
+ {
+ errString = getProcessError(*process);
+
+ successFlag = false;
+ }
+ else
+ {
+ successFlag = true;
+ }
+
+ delete process;
+ process = 0;
+
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/cpfindtask.h b/panorama/tasks/cpfindtask.h
new file mode 100644
index 0000000..7779e74
--- /dev/null
+++ b/panorama/tasks/cpfindtask.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 CPFINDTASK_H
+#define CPFINDTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CpFindTask : public Task
+{
+
+private:
+
+ KUrl* const cpFindPtoUrl;
+ const bool celeste;
+ const KUrl* const ptoUrl;
+ const QString cpFindPath;
+
+ KProcess* process;
+
+public:
+
+ CpFindTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& cpFindUrl, bool celeste, const QString& cpFindPath);
+ CpFindTask(const KUrl& workDir, const KUrl& input,
+ KUrl& cpFindUrl, bool celeste, const QString& cpFindPath);
+ ~CpFindTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* CPFINDTASK_H */
diff --git a/panorama/tasks/createmktask.cpp b/panorama/tasks/createmktask.cpp
new file mode 100644
index 0000000..6c86f19
--- /dev/null
+++ b/panorama/tasks/createmktask.cpp
@@ -0,0 +1,136 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "createmktask.h"
+
+// Qt includes
+
+#include <QFileInfo>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+CreateMKTask::CreateMKTask(QObject* parent, const KUrl& workDir, const KUrl& input, KUrl& mkUrl,
+ KUrl& panoUrl, PanoramaFileType fileType, const QString& pto2mkPath,
+ const QString& nonaPath, const QString& enblendPath, bool preview)
+ : Task(parent, preview ? CREATEMKPREVIEW : CREATEMK, workDir), ptoUrl(&input), mkUrl(&mkUrl),
+ panoUrl(&panoUrl), fileType(fileType), pto2mkPath(pto2mkPath),
+ nonaPath(nonaPath), enblendPath(enblendPath), process(0)
+{}
+
+CreateMKTask::CreateMKTask(const KUrl& workDir, const KUrl& input, KUrl& mkUrl,
+ KUrl& panoUrl, PanoramaFileType fileType, const QString& pto2mkPath,
+ const QString& nonaPath, const QString& enblendPath, bool preview)
+ : Task(0, preview ? CREATEMKPREVIEW : CREATEMK, workDir), ptoUrl(&input), mkUrl(&mkUrl),
+ panoUrl(&panoUrl), fileType(fileType), pto2mkPath(pto2mkPath),
+ nonaPath(nonaPath), enblendPath(enblendPath), process(0)
+{}
+
+CreateMKTask::~CreateMKTask()
+{
+ if (process)
+ {
+ delete process;
+ process = 0;
+ }
+}
+
+void CreateMKTask::requestAbort()
+{
+ process->kill();
+}
+
+void CreateMKTask::run()
+{
+ QFileInfo fi(ptoUrl->toLocalFile());
+ (*mkUrl) = tmpDir;
+ mkUrl->setFileName(fi.completeBaseName() + QString(".mk"));
+
+ (*panoUrl) = tmpDir;
+ switch (fileType)
+ {
+ case JPEG:
+ panoUrl->setFileName(fi.completeBaseName() + QString(".jpg"));
+ break;
+ case TIFF:
+ panoUrl->setFileName(fi.completeBaseName() + QString(".tif"));
+ break;
+ }
+
+ process = new KProcess();
+ process->clearProgram();
+ process->setWorkingDirectory(tmpDir.toLocalFile());
+ process->setOutputChannelMode(KProcess::MergedChannels);
+ process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
+
+ QStringList args;
+ args << pto2mkPath;
+ args << "-o";
+ args << mkUrl->toLocalFile();
+ args << "-p";
+ args << fi.completeBaseName();
+ args << ptoUrl->toLocalFile();
+
+ process->setProgram(args);
+
+ kDebug() << "pto2mk command line: " << process->program();
+
+ process->start();
+
+ if (!process->waitForFinished(-1) || process->exitCode() != 0)
+ {
+ errString = getProcessError(*process);
+ successFlag = false;
+ delete process;
+ process = 0;
+ return;
+ }
+
+ delete process;
+ process = 0;
+
+ /* Just replacing strings in the generated makefile to reflect the
+ * location of the binaries of nona and enblend. This ensures that
+ * the make process will be able to execute those binaries without
+ * worring that any binary is not in the system path.
+ */
+ QFile mkUrlFile(mkUrl->toLocalFile());
+ mkUrlFile.open(QIODevice::ReadWrite);
+
+ QString fileData = mkUrlFile.readAll();
+ fileData.replace("NONA=\"nona\"", QString("NONA=\"%1\"").arg(nonaPath));
+ fileData.replace("ENBLEND=\"enblend\"", QString("ENBLEND=\"%1\"").arg(enblendPath));
+
+ mkUrlFile.seek(0L);
+ mkUrlFile.write(fileData.toAscii());
+ mkUrlFile.close();
+
+ successFlag = true;
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/createmktask.h b/panorama/tasks/createmktask.h
new file mode 100644
index 0000000..f558496
--- /dev/null
+++ b/panorama/tasks/createmktask.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 CREATEMKTASK_H
+#define CREATEMKTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CreateMKTask : public Task
+{
+
+private:
+
+ const KUrl* const ptoUrl;
+ KUrl* const mkUrl;
+ KUrl* const panoUrl;
+ const PanoramaFileType fileType;
+ const QString pto2mkPath;
+ const QString nonaPath;
+ const QString enblendPath;
+
+ KProcess* process;
+
+public:
+
+ CreateMKTask(QObject* parent, const KUrl& workDir, const KUrl& input, KUrl& mkUrl,
+ KUrl& panoUrl, PanoramaFileType fileType, const QString& pto2mkPath,
+ const QString& nonaPath, const QString& enblendPath, bool preview);
+ CreateMKTask(const KUrl& workDir, const KUrl& input, KUrl& mkUrl,
+ KUrl& panoUrl, PanoramaFileType fileType, const QString& pto2mkPath,
+ const QString& nonaPath, const QString& enblendPath, bool preview);
+ ~CreateMKTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* CREATEMKTASK_H */
diff --git a/panorama/tasks/createpreviewtask.cpp b/panorama/tasks/createpreviewtask.cpp
new file mode 100644
index 0000000..a0a85c3
--- /dev/null
+++ b/panorama/tasks/createpreviewtask.cpp
@@ -0,0 +1,232 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "createpreviewtask.h"
+
+// Qt includes
+
+#include <QFile>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+// Local includes
+
+#include "kpmetadata.h"
+
+using namespace KIPIPlugins;
+
+namespace KIPIPanoramaPlugin
+{
+
+CreatePreviewTask::CreatePreviewTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& previewPtoUrl, const ItemUrlsMap& preProcessedUrlsMap)
+ : Task(parent, CREATEMKPREVIEW, workDir), previewPtoUrl(&previewPtoUrl),
+ ptoUrl(input), preProcessedUrlsMap(preProcessedUrlsMap)
+{}
+
+CreatePreviewTask::CreatePreviewTask(const KUrl& workDir, const KUrl& input,
+ KUrl& previewPtoUrl, const ItemUrlsMap& preProcessedUrlsMap)
+ : Task(0, CREATEMKPREVIEW, workDir), previewPtoUrl(&previewPtoUrl),
+ ptoUrl(input), preProcessedUrlsMap(preProcessedUrlsMap)
+{}
+
+CreatePreviewTask::~CreatePreviewTask()
+{}
+
+void CreatePreviewTask::run()
+{
+ kDebug() << "Preview Generation (" << ptoUrl.toLocalFile() << ")";
+ QFile input(ptoUrl.toLocalFile());
+ QStringList pto;
+ if (!input.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ errString = i18n("Cannot read project file.");
+ kDebug() << "Can't read PTO File!";
+ successFlag = false;
+ return;
+ }
+ else
+ {
+ QTextStream in(&input);
+ while (!in.atEnd())
+ {
+ pto.append(in.readLine());
+ }
+ input.close();
+ }
+
+ if (pto.count() == 0)
+ {
+ errString = i18n("Empty project file.");
+ kDebug() << "Pto file empty!!";
+ successFlag = false;
+ return;
+ }
+
+ (*previewPtoUrl) = tmpDir;
+ previewPtoUrl->setFileName("preview.pto");
+ QFile output(previewPtoUrl->toLocalFile());
+ if (!output.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
+ {
+ errString = i18n("Preview project file cannot be created.");
+ kDebug() << "Can't create a new PTO File!";
+ successFlag = false;
+ return;
+ }
+
+ QTextStream previewPtoStream(&output);
+
+ KPMetadata metaIn(preProcessedUrlsMap.begin().value().preprocessedUrl.toLocalFile());
+ KPMetadata metaOut(preProcessedUrlsMap.begin().value().previewUrl.toLocalFile());
+ double scalingFactor = ((double) metaOut.getPixelSize().width()) / ((double) metaIn.getPixelSize().width());
+
+ // TODO: change that to use boost::spirit (parser) and boost::karma (generator)
+ foreach(const QString& line, pto)
+ {
+ if (line.isEmpty())
+ {
+ continue;
+ }
+
+ if (isAbortedFlag)
+ {
+ successFlag = false;
+ return;
+ }
+
+ QString tmp;
+ QStringList parameters = line.split(' ', QString::SkipEmptyParts);
+
+ if (line[0] == 'p')
+ {
+ tmp.clear();
+ foreach(const QString& p, parameters)
+ {
+ if (p[0] == 'w' || p[0] == 'h')
+ {
+ int size = ((double) (p.right(p.size() - 1)).toInt()) * scalingFactor;
+ tmp.append(p[0]);
+ tmp.append(QString::number(size));
+ }
+ else if (p[0] == 'n')
+ {
+ tmp.append("n\"JPEG q90\"");
+ break; // n should be the last parameter (and the space before qXX introduce another parameter)
+ }
+ else
+ {
+ tmp.append(p);
+ }
+ tmp.append(" ");
+ }
+ }
+ else if (line[0] == 'm')
+ {
+ tmp = line;
+ }
+ else if (line[0] == 'i')
+ {
+ tmp.clear();
+ QStringList realParameters;
+ bool nRead = false;
+ foreach(const QString& p, parameters)
+ {
+ if (p[0] != 'n')
+ {
+ if (nRead)
+ {
+ realParameters[realParameters.size() - 1] += ' ' + p;
+ }
+ else
+ {
+ realParameters << p;
+ }
+ }
+ else
+ {
+ nRead = true;
+ realParameters << p;
+ }
+ }
+ foreach(const QString& p, realParameters)
+ {
+ if (p[0] == 'w')
+ {
+ tmp.append("w");
+ tmp.append(QString::number(metaOut.getPixelSize().width()));
+ }
+ else if (p[0] == 'h')
+ {
+ tmp.append("h");
+ tmp.append(QString::number(metaOut.getPixelSize().height()));
+ }
+ else if (p[0] == 'n')
+ {
+ QString imgFileName = p.mid(2, p.size() - 3);
+ KUrl imgUrl(KUrl(tmpDir), imgFileName);
+ ItemUrlsMap::iterator it;
+ const ItemUrlsMap *ppum = &preProcessedUrlsMap;
+ for (it = (ItemUrlsMap::iterator) ppum->begin(); it != ppum->end() && it.value().preprocessedUrl != imgUrl; ++it);
+ if (it == ppum->end())
+ {
+ input.close();
+ errString = i18n("Unknown input file in the project file: %1", imgFileName);
+ kDebug() << "Unknown input File in the PTO: " << imgFileName;
+ kDebug() << "IMG: " << imgUrl.toLocalFile();
+ successFlag = false;
+ return;
+ }
+ tmp.append("n\"");
+ tmp.append(it.value().previewUrl.fileName());
+ tmp.append("\"");
+ break;
+ }
+ else
+ {
+ tmp.append(p);
+ }
+ tmp.append(" ");
+ }
+ }
+ else
+ {
+ continue;
+ }
+ previewPtoStream << tmp << endl;
+ }
+
+ // Add two commented line for a JPEG output
+ previewPtoStream << "#hugin_outputImageType jpg" << endl;
+ previewPtoStream << "#hugin_outputJPEGQuality 90" << endl;
+
+ output.close();
+
+ kDebug() << "Preview PTO File created: " << ptoUrl.fileName();
+
+ successFlag = true;
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/importwizard/previewpage.h b/panorama/tasks/createpreviewtask.h
similarity index 50%
copy from panorama/importwizard/previewpage.h
copy to panorama/tasks/createpreviewtask.h
index ce7b942..e5cc40c 100644
--- a/panorama/importwizard/previewpage.h
+++ b/panorama/tasks/createpreviewtask.h
@@ -1,12 +1,12 @@
/* ============================================================
- *
+ *
* This file is a part of kipi-plugins project
* http://www.digikam.org
*
- * Date : 2011-05-23
+ * Date : 2012-03-15
* Description : a plugin to create panorama by fusion of several images.
*
- * Copyright (C) 2011 by Benjamin Girault <benjamin dot girault at gmail dot com>
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault at gmail dot com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
@@ -20,50 +20,45 @@
*
* ============================================================ */

-#ifndef PREVIEW_PAGE_H
-#define PREVIEW_PAGE_H
+#ifndef CREATEPREVIEWTASK_H
+#define CREATEPREVIEWTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>

// Local includes

-#include "kpwizardpage.h"
-#include "actions.h"
+#include "task.h"

-using namespace KIPIPlugins;
+using namespace KDcrawIface;

namespace KIPIPanoramaPlugin
{

-class Manager;
-
-class PreviewPage : public KPWizardPage
+class CreatePreviewTask : public Task
{
- Q_OBJECT
-
-public:
-
- PreviewPage(Manager* const mngr, KAssistantDialog* const dlg);
- ~PreviewPage();

- bool cancel();
- void computePreview();
- void startStitching();
- void resetPage();
+private:

-Q_SIGNALS:
+ KUrl* const previewPtoUrl;
+ const KUrl ptoUrl;
+ const ItemUrlsMap preProcessedUrlsMap;

- void signalStitchingFinished(bool);
+public:

-private Q_SLOTS:
+ CreatePreviewTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& previewPtoUrl, const ItemUrlsMap& preProcessedUrlsMap);
+ CreatePreviewTask(const KUrl& workDir, const KUrl& input,
+ KUrl& previewPtoUrl, const ItemUrlsMap& preProcessedUrlsMap);
+ ~CreatePreviewTask();

- void slotAction(const KIPIPanoramaPlugin::ActionData&);
- void slotGetPreviewFile(const KUrl&);
+protected:

-private:
+ void run();

- struct PreviewPagePriv;
- PreviewPagePriv* const d;
};

-} // namespace KIPIPanoramaPlugin
+} // namespace KIPIPanoramaPlugin

-#endif /* PREVIEW_PAGE_H */
+#endif /* CREATEPREVIEWTASK_H */
diff --git a/panorama/tasks/createptotask.cpp b/panorama/tasks/createptotask.cpp
new file mode 100644
index 0000000..1ba47a1
--- /dev/null
+++ b/panorama/tasks/createptotask.cpp
@@ -0,0 +1,166 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "createptotask.h"
+
+// Qt includes
+
+#include <QFile>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+// Local includes
+
+#include "kpmetadata.h"
+
+using namespace KIPIPlugins;
+
+namespace KIPIPanoramaPlugin
+{
+
+CreatePtoTask::CreatePtoTask(QObject* parent, const KUrl& workDir, PanoramaFileType fileType, bool hdr,
+ KUrl& ptoUrl, const KUrl::List& inputFiles, const ItemUrlsMap& preProcessedMap)
+ : Task(parent, CREATEPTO, workDir), ptoUrl(&ptoUrl), preProcessedMap(&preProcessedMap),
+ fileType(fileType), hdr(hdr), inputFiles(&inputFiles)
+{}
+
+CreatePtoTask::CreatePtoTask(const KUrl& workDir, PanoramaFileType fileType, bool hdr,
+ KUrl& ptoUrl, const KUrl::List& inputFiles, const ItemUrlsMap& preProcessedMap)
+ : Task(0, CREATEPTO, workDir), ptoUrl(&ptoUrl), preProcessedMap(&preProcessedMap),
+ fileType(fileType), hdr(hdr), inputFiles(&inputFiles)
+{}
+
+CreatePtoTask::~CreatePtoTask()
+{}
+
+void CreatePtoTask::run()
+{
+ (*ptoUrl) = tmpDir;
+ ptoUrl->setFileName(QString("pano_base.pto"));
+
+ QFile pto(ptoUrl->toLocalFile());
+ if (pto.exists())
+ {
+ errString = i18n("PTO file already created in the temporary directory.");
+ successFlag = false;
+ return;
+ }
+ if (!pto.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
+ {
+ errString = i18n("PTO file cannot be created in the temporary directory.");
+ successFlag = false;
+ return;
+ }
+
+ QTextStream pto_stream(&pto);
+
+ // The pto is created following the file format described here:
+ // http://hugin.sourceforge.net/docs/nona/nona.txt
+
+ // 1. Project parameters
+ pto_stream << "p";
+ pto_stream << " f1"; // Cylindrical projection
+ pto_stream << " n\"TIFF_m c:LZW\"";
+ pto_stream << " R" << (hdr ? '1' : '0'); // HDR output
+ //pto_stream << " T\"FLOAT\""; // 32bits color depth
+ //pto_stream << " S," << X_left << "," << X_right << "," << X_top << "," << X_bottom; // Crop values
+ pto_stream << " k0"; // Reference image
+ pto_stream << endl;
+
+ // 2. Images
+ pto_stream << endl;
+ int i = 0;
+ for (i = 0; i < inputFiles->size(); ++i)
+ {
+ KUrl inputFile(inputFiles->at(i));
+ KUrl preprocessedUrl(preProcessedMap->value(inputFile).preprocessedUrl);
+ KPMetadata meta;
+ meta.load(preprocessedUrl.toLocalFile());
+ QSize size = meta.getPixelSize();
+
+ pto_stream << "i";
+ pto_stream << " f0"; // Lens projection type (rectilinear)
+ pto_stream << " w" << size.width(); // Image width
+ pto_stream << " h" << size.height(); // Image height
+ if (i > 0)
+ {
+ // We suppose that the pictures are all taken with the same camera and lens
+ pto_stream << " a=0 b=0 c=0 d=0 e=0 v=0 g=0 t=0"; // Geometry
+ pto_stream << " Va=0 Vb=0 Vc=0 Vd=0 Vx=0 Vy=0"; // Vignetting
+ }
+ pto_stream << " n\"" << preprocessedUrl.toLocalFile() << '"';
+ pto_stream << endl;
+ }
+
+ // 3. Variables to optimize
+ pto_stream << endl;
+ // Geometry optimization
+ pto_stream << "v a0" << endl;
+ pto_stream << "v b0" << endl;
+ pto_stream << "v c0" << endl;
+ pto_stream << "v d0" << endl;
+ pto_stream << "v e0" << endl;
+ pto_stream << "v Va0" << endl;
+ pto_stream << "v Vb0" << endl;
+ pto_stream << "v Vc0" << endl;
+ pto_stream << "v Vd0" << endl;
+ pto_stream << "v Vx0" << endl;
+ pto_stream << "v Vy0" << endl;
+ for (int j = 0; j < i; ++j)
+ {
+ // Colors optimization
+ pto_stream << "v Ra" << j << endl;
+ pto_stream << "v Rb" << j << endl;
+ pto_stream << "v Rc" << j << endl;
+ pto_stream << "v Rd" << j << endl;
+ pto_stream << "v Re" << j << endl;
+ pto_stream << "v Eev" << j << endl;
+ pto_stream << "v Erv" << j << endl;
+ pto_stream << "v Ebv" << j << endl;
+ // Position optimization
+ pto_stream << "v y" << j << endl;
+ pto_stream << "v p" << j << endl;
+ pto_stream << "v r" << j << endl;
+ }
+
+ switch (fileType)
+ {
+ case TIFF:
+ pto_stream << "#hugin_outputImageType tif" << endl;
+ pto_stream << "#hugin_outputImageTypeCompression LZW" << endl;
+ break;
+ case JPEG:
+ pto_stream << "#hugin_outputImageType jpg" << endl;
+ pto_stream << "#hugin_outputJPEGQuality 95" << endl;
+ break;
+ }
+
+ pto.close();
+
+ successFlag = true;
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/createptotask.h b/panorama/tasks/createptotask.h
new file mode 100644
index 0000000..dfc828d
--- /dev/null
+++ b/panorama/tasks/createptotask.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 CREATEPTOTASK_H
+#define CREATEPTOTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class CreatePtoTask : public Task
+{
+
+private:
+
+ KUrl* const ptoUrl;
+ const ItemUrlsMap* const preProcessedMap;
+ const PanoramaFileType fileType;
+ const bool hdr;
+ const KUrl::List* const inputFiles;
+
+public:
+
+ CreatePtoTask(QObject* parent, const KUrl& workDir, PanoramaFileType fileType, bool hdr,
+ KUrl& ptoUrl, const KUrl::List& inputFiles, const ItemUrlsMap& preProcessedMap);
+ CreatePtoTask(const KUrl& workDir, PanoramaFileType fileType, bool hdr,
+ KUrl& ptoUrl, const KUrl::List& inputFiles, const ItemUrlsMap& preProcessedMap);
+ ~CreatePtoTask();
+
+protected:
+
+ void run();
+
+private:
+
+ bool computePreview(const KUrl& inUrl);
+ bool convertRaw();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* CREATEPTOTASK_H */
diff --git a/panorama/tasks/optimisationtask.cpp b/panorama/tasks/optimisationtask.cpp
new file mode 100644
index 0000000..da350ca
--- /dev/null
+++ b/panorama/tasks/optimisationtask.cpp
@@ -0,0 +1,104 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "optimisationtask.h"
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+OptimisationTask::OptimisationTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& autoOptimiserPtoUrl, bool levelHorizon,
+ bool optimizeProjectionAndSize, const QString& autooptimiserPath)
+ : Task(parent, OPTIMIZE, workDir), autoOptimiserPtoUrl(&autoOptimiserPtoUrl), ptoUrl(&input), levelHorizon(levelHorizon),
+ optimizeProjectionAndSize(optimizeProjectionAndSize), autooptimiserPath(autooptimiserPath), process(0)
+{}
+
+OptimisationTask::OptimisationTask(const KUrl& workDir, const KUrl& input,
+ KUrl& autoOptimiserPtoUrl, bool levelHorizon,
+ bool optimizeProjectionAndSize, const QString& autooptimiserPath)
+ : Task(0, OPTIMIZE, workDir), autoOptimiserPtoUrl(&autoOptimiserPtoUrl), ptoUrl(&input), levelHorizon(levelHorizon),
+ optimizeProjectionAndSize(optimizeProjectionAndSize), autooptimiserPath(autooptimiserPath), process(0)
+{}
+
+OptimisationTask::~OptimisationTask()
+{
+ if (process)
+ {
+ delete process;
+ process = 0;
+ }
+}
+
+void OptimisationTask::requestAbort()
+{
+ process->kill();
+}
+
+void OptimisationTask::run()
+{
+ (*autoOptimiserPtoUrl) = tmpDir;
+ autoOptimiserPtoUrl->setFileName(QString("auto_op_pano.pto"));
+
+ process = new KProcess();
+ process->clearProgram();
+ process->setWorkingDirectory(tmpDir.toLocalFile());
+ process->setOutputChannelMode(KProcess::MergedChannels);
+ process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
+
+ QStringList args;
+ args << autooptimiserPath;
+ args << "-am";
+ if (levelHorizon)
+ {
+ args << "-l";
+ }
+ if (optimizeProjectionAndSize)
+ {
+ args << "-s";
+ }
+ args << "-o";
+ args << autoOptimiserPtoUrl->toLocalFile();
+ args << ptoUrl->toLocalFile();
+
+ process->setProgram(args);
+
+ kDebug() << "autooptimiser command line: " << process->program();
+
+ process->start();
+
+ if (!process->waitForFinished(-1) || process->exitCode() != 0)
+ {
+ errString = getProcessError(*process);
+ successFlag = false;
+ return;
+ }
+
+ successFlag = true;
+ return;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/optimisationtask.h b/panorama/tasks/optimisationtask.h
new file mode 100644
index 0000000..f06bb15
--- /dev/null
+++ b/panorama/tasks/optimisationtask.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 OPTIMISATIONTASK_H
+#define OPTIMISATIONTASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class OptimisationTask : public Task
+{
+
+private:
+
+ KUrl* const autoOptimiserPtoUrl;
+ const KUrl* const ptoUrl;
+ const bool levelHorizon;
+ const bool optimizeProjectionAndSize;
+ const QString autooptimiserPath;
+
+ KProcess* process;
+
+public:
+
+ OptimisationTask(QObject* parent, const KUrl& workDir, const KUrl& input,
+ KUrl& autoOptimiserPtoUrl, bool levelHorizon,
+ bool optimizeProjectionAndSize, const QString& autooptimiserPath);
+ OptimisationTask(const KUrl& workDir, const KUrl& input,
+ KUrl& autoOptimiserPtoUrl, bool levelHorizon,
+ bool optimizeProjectionAndSize, const QString& autooptimiserPath);
+ ~OptimisationTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* OPTIMISATIONTASK_H */
diff --git a/panorama/tasks/preprocesstask.cpp b/panorama/tasks/preprocesstask.cpp
new file mode 100644
index 0000000..0905d65
--- /dev/null
+++ b/panorama/tasks/preprocesstask.cpp
@@ -0,0 +1,211 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "preprocesstask.h"
+
+// Qt includes
+
+#include <QFileInfo>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kdebug.h>
+
+// Local includes
+
+#include "kpmetadata.h"
+#include "kpversion.h"
+#include "kpwriteimage.h"
+
+using namespace KIPIPlugins;
+
+namespace KIPIPanoramaPlugin
+{
+
+PreProcessTask::PreProcessTask(QObject* parent, const KUrl& workDir, int id, ItemPreprocessedUrls& targetUrls,
+ const KUrl& sourceUrl, const RawDecodingSettings& rawSettings)
+ : Task(parent, PREPROCESS_INPUT, workDir), id(id),
+ fileUrl(sourceUrl), preProcessedUrl(&targetUrls), settings(rawSettings)
+{}
+
+PreProcessTask::PreProcessTask(const KUrl& workDir, int id, ItemPreprocessedUrls& targetUrls,
+ const KUrl& sourceUrl, const RawDecodingSettings& rawSettings)
+ : Task(0, PREPROCESS_INPUT, workDir), id(id),
+ fileUrl(sourceUrl), preProcessedUrl(&targetUrls), settings(rawSettings)
+{}
+
+PreProcessTask::~PreProcessTask()
+{}
+
+void PreProcessTask::requestAbort()
+{
+ Task::requestAbort();
+
+ if (!rawProcess.isNull())
+ {
+ rawProcess->cancel();
+ }
+}
+
+void PreProcessTask::run()
+{
+ if (isRawFile(fileUrl.toLocalFile()))
+ {
+ preProcessedUrl->preprocessedUrl = tmpDir;
+
+ if (!convertRaw())
+ {
+ successFlag = false;
+ return;
+ }
+ }
+ else
+ {
+ // NOTE: in this case, preprocessed Url is the original file Url.
+ preProcessedUrl->preprocessedUrl = fileUrl;
+ }
+
+ preProcessedUrl->previewUrl = tmpDir;
+
+ if (!computePreview(preProcessedUrl->preprocessedUrl))
+ {
+ successFlag = false;
+ return;
+ }
+
+ successFlag = true;
+ return;
+}
+
+bool PreProcessTask::computePreview(const KUrl& inUrl)
+{
+ KUrl& outUrl = preProcessedUrl->previewUrl;
+
+ QFileInfo fi(inUrl.toLocalFile());
+ outUrl.setFileName(fi.completeBaseName().replace('.', '_') + QString("-preview.jpg"));
+
+ QImage img;
+ if (img.load(inUrl.toLocalFile()))
+ {
+ QImage preview = img.scaled(1280, 1024, Qt::KeepAspectRatio);
+ bool saved = preview.save(outUrl.toLocalFile(), "JPEG");
+ // save exif information also to preview image for auto rotation
+ if (saved)
+ {
+ KPMetadata metaIn(inUrl.toLocalFile());
+ KPMetadata metaOut(outUrl.toLocalFile());
+ metaOut.setImageOrientation(metaIn.getImageOrientation());
+ metaOut.setImageDimensions(QSize(preview.width(), preview.height()));
+ metaOut.applyChanges();
+ }
+ kDebug() << "Preview Image url: " << outUrl << ", saved: " << saved;
+ return saved;
+ }
+ else
+ {
+ errString = i18n("Input image cannot be loaded for preview generation");
+ }
+ return false;
+}
+
+bool PreProcessTask::convertRaw()
+{
+ const KUrl& inUrl = fileUrl;
+ KUrl &outUrl = preProcessedUrl->preprocessedUrl;
+
+ int width, height, rgbmax;
+ QByteArray imageData;
+
+ rawProcess = new KDcraw;
+ bool decoded = rawProcess->decodeRAWImage(inUrl.toLocalFile(), settings, imageData, width, height, rgbmax);
+ delete rawProcess;
+
+ if (decoded)
+ {
+ uchar* sptr = (uchar*)imageData.data();
+ float factor = 65535.0 / rgbmax;
+ unsigned short tmp16[3];
+
+ // Set RGB color components.
+ for (int i = 0 ; !isAbortedFlag && (i < width * height) ; ++i)
+ {
+ // Swap Red and Blue and re-ajust color component values
+ tmp16[0] = (unsigned short)((sptr[5]*256 + sptr[4]) * factor); // Blue
+ tmp16[1] = (unsigned short)((sptr[3]*256 + sptr[2]) * factor); // Green
+ tmp16[2] = (unsigned short)((sptr[1]*256 + sptr[0]) * factor); // Red
+ memcpy(&sptr[0], &tmp16[0], 6);
+ sptr += 6;
+ }
+
+ if (isAbortedFlag)
+ {
+ errString = i18n("Operation canceled.");
+ return false;
+ }
+
+ KPMetadata metaIn, metaOut;
+ metaIn.load(inUrl.toLocalFile());
+ KPMetadata::MetaDataMap m = metaIn.getExifTagsDataList(QStringList("Photo"), true);
+ KPMetadata::MetaDataMap::iterator it;
+ for (it = m.begin(); it != m.end(); ++it)
+ {
+ metaIn.removeExifTag(it.key().toAscii().data(), false);
+ }
+ metaOut.setData(metaIn.data());
+ metaOut.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ metaOut.setImageDimensions(QSize(width, height));
+ metaOut.setExifTagString("Exif.Image.DocumentName", inUrl.fileName());
+ metaOut.setXmpTagString("Xmp.tiff.Make", metaOut.getExifTagString("Exif.Image.Make"));
+ metaOut.setXmpTagString("Xmp.tiff.Model", metaOut.getExifTagString("Exif.Image.Model"));
+ metaOut.setImageOrientation(KPMetadata::ORIENTATION_NORMAL);
+
+ QByteArray prof = KPWriteImage::getICCProfilFromFile(settings.outputColorSpace);
+
+ KPWriteImage wImageIface;
+ wImageIface.setCancel(&isAbortedFlag);
+ wImageIface.setImageData(imageData, width, height, true, false, prof, metaOut);
+ QFileInfo fi(inUrl.toLocalFile());
+ outUrl.setFileName(fi.completeBaseName().replace('.', '_') + QString(".tif"));
+
+ if (!wImageIface.write2TIFF(outUrl.toLocalFile()))
+ {
+ errString = i18n("Tiff image creation failed.");
+ return false;
+ }
+ else
+ {
+ metaOut.save(outUrl.toLocalFile());
+ }
+ }
+ else
+ {
+ errString = i18n("Raw file conversion failed.");
+ return false;
+ }
+
+ kDebug() << "Convert RAW output url: " << outUrl;
+
+ return true;
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/tasks/preprocesstask.h b/panorama/tasks/preprocesstask.h
new file mode 100644
index 0000000..2b3c266
--- /dev/null
+++ b/panorama/tasks/preprocesstask.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 PREPROCESSTASK_H
+#define PREPROCESSTASK_H
+
+// Qt includes
+
+#include <QPointer>
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+
+// LibKDcraw includes
+
+#include <libkdcraw/kdcraw.h>
+
+// Local includes
+
+#include "task.h"
+
+using namespace KDcrawIface;
+
+namespace KIPIPanoramaPlugin
+{
+
+class PreProcessTask : public Task
+{
+
+public:
+
+ const int id;
+
+private:
+
+ const KUrl fileUrl;
+ ItemPreprocessedUrls* const preProcessedUrl;
+ const RawDecodingSettings settings;
+ QPointer<KDcraw> rawProcess;
+
+public:
+
+ PreProcessTask(QObject* parent, const KUrl& workDir, int id, ItemPreprocessedUrls& targetUrls,
+ const KUrl& sourceUrl, const RawDecodingSettings& rawSettings);
+ PreProcessTask(const KUrl& workDir, int id, ItemPreprocessedUrls& targetUrls,
+ const KUrl& sourceUrl, const RawDecodingSettings& rawSettings);
+ ~PreProcessTask();
+
+ void requestAbort();
+
+protected:
+
+ void run();
+
+private:
+
+ bool computePreview(const KUrl& inUrl);
+ bool convertRaw();
+
+};
+
+} // namespace KIPIPanoramaPlugin
+
+#endif /* PREPROCESSTASK_H */
diff --git a/panorama/tasks/task.cpp b/panorama/tasks/task.cpp
new file mode 100644
index 0000000..64fc08b
--- /dev/null
+++ b/panorama/tasks/task.cpp
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 "task.h"
+
+// Qt includes
+
+#include <QFileInfo>
+
+// KDE includes
+
+#include <klocale.h>
+
+// LibKDcraw includes
+
+#include <libkdcraw/kdcraw.h>
+
+namespace KIPIPanoramaPlugin
+{
+
+Task::Task(QObject* parent, Action action, const KUrl& workDir)
+ : Job(parent), action(action), successFlag(false), isAbortedFlag(false), tmpDir(workDir)
+{}
+
+Task::~Task()
+{}
+
+bool Task::success() const
+{
+ return successFlag;
+}
+
+void Task::requestAbort()
+{
+ isAbortedFlag = true;
+}
+
+bool Task::isRawFile(const KUrl& url)
+{
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+
+ QFileInfo fileInfo(url.toLocalFile());
+ if (rawFilesExt.toUpper().contains(fileInfo.suffix().toUpper()))
+ return true;
+
+ return false;
+}
+
+QString Task::getProcessError(KProcess& proc)
+{
+ QString std = proc.readAll();
+ return (i18n("Cannot run %1:\n\n %2", proc.program()[0], std));
+}
+
+} // namespace KIPIPanoramaPlugin
diff --git a/panorama/importwizard/previewpage.h b/panorama/tasks/task.h
similarity index 53%
copy from panorama/importwizard/previewpage.h
copy to panorama/tasks/task.h
index ce7b942..2195050 100644
--- a/panorama/importwizard/previewpage.h
+++ b/panorama/tasks/task.h
@@ -1,12 +1,12 @@
/* ============================================================
- *
+ *
* This file is a part of kipi-plugins project
* http://www.digikam.org
*
- * Date : 2011-05-23
+ * Date : 2012-03-15
* Description : a plugin to create panorama by fusion of several images.
*
- * Copyright (C) 2011 by Benjamin Girault <benjamin dot girault at gmail dot com>
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault at gmail dot com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
@@ -20,50 +20,50 @@
*
* ============================================================ */

-#ifndef PREVIEW_PAGE_H
-#define PREVIEW_PAGE_H
+#ifndef TASK_H
+#define TASK_H
+
+// KDE includes
+
+#include <threadweaver/Job.h>
+#include <kprocess.h>

// Local includes

-#include "kpwizardpage.h"
#include "actions.h"

-using namespace KIPIPlugins;
-
namespace KIPIPanoramaPlugin
{

-class Manager;
-
-class PreviewPage : public KPWizardPage
+class Task : public ThreadWeaver::Job
{
- Q_OBJECT
-
public:

- PreviewPage(Manager* const mngr, KAssistantDialog* const dlg);
- ~PreviewPage();
+ QString errString;
+ const Action action;

- bool cancel();
- void computePreview();
- void startStitching();
- void resetPage();
+protected:

-Q_SIGNALS:
+ bool successFlag;
+ bool isAbortedFlag;
+ const KUrl tmpDir;
+
+public:

- void signalStitchingFinished(bool);
+ Task(QObject* parent, Action action, const KUrl& workDir);
+ ~Task();

-private Q_SLOTS:
+ bool success() const;
+ void requestAbort();

- void slotAction(const KIPIPanoramaPlugin::ActionData&);
- void slotGetPreviewFile(const KUrl&);
+protected:

-private:
+ virtual void run() = 0;

- struct PreviewPagePriv;
- PreviewPagePriv* const d;
+ static bool isRawFile(const KUrl& url);
+ static QString getProcessError(KProcess& proc);
};

-} // namespace KIPIPanoramaPlugin
+} // namespace KIPIPanoramaPlugin

-#endif /* PREVIEW_PAGE_H */
+#endif /* TASK_H */
diff --git a/panorama/tasks/tasks.h b/panorama/tasks/tasks.h
new file mode 100644
index 0000000..e227387
--- /dev/null
+++ b/panorama/tasks/tasks.h
@@ -0,0 +1,37 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.digikam.org
+ *
+ * Date : 2012-03-15
+ * Description : a plugin to create panorama by fusion of several images.
+ *
+ * Copyright (C) 2012 by Benjamin Girault <benjamin dot girault 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 TASKS_H
+#define TASKS_H
+
+#include "preprocesstask.h"
+#include "createptotask.h"
+#include "cpfindtask.h"
+#include "cpcleantask.h"
+#include "optimisationtask.h"
+#include "createpreviewtask.h"
+#include "createmktask.h"
+#include "compilemksteptask.h"
+#include "compilemktask.h"
+#include "copyfilestask.h"
+
+#endif /* TASKS_H */
\ No newline at end of file