You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1228 lines
41 KiB
1228 lines
41 KiB
/* ============================================================
|
|
*
|
|
* This file is a part of digiKam project
|
|
* http://www.digikam.org
|
|
*
|
|
* Date : 2004-09-17
|
|
* Description : digital camera controller
|
|
*
|
|
* Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
|
|
* Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
|
|
*
|
|
* This program is free software; you can redistribute it
|
|
* and/or modify it under the terms of the GNU General
|
|
* Public License as published by the Free Software Foundation;
|
|
* either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* ============================================================ */
|
|
|
|
extern "C"
|
|
{
|
|
#include <unistd.h>
|
|
}
|
|
|
|
// C++ includes.
|
|
|
|
#include <typeinfo>
|
|
#include <cstdio>
|
|
|
|
// TQt includes.
|
|
|
|
#include <tqthread.h>
|
|
#include <tqmutex.h>
|
|
#include <tqwaitcondition.h>
|
|
#include <tqevent.h>
|
|
#include <tqapplication.h>
|
|
#include <tqdeepcopy.h>
|
|
#include <tqvariant.h>
|
|
#include <tqimage.h>
|
|
#include <tqdatastream.h>
|
|
#include <tqfile.h>
|
|
#include <tqtimer.h>
|
|
#include <tqregexp.h>
|
|
|
|
// KDE includes.
|
|
|
|
#include <klocale.h>
|
|
#include <kurl.h>
|
|
#include <kmessagebox.h>
|
|
#include <kio/renamedlg.h>
|
|
#include <kstandarddirs.h>
|
|
|
|
// Local includes.
|
|
|
|
#include "ddebug.h"
|
|
#include "thumbnailsize.h"
|
|
#include "imagewindow.h"
|
|
#include "gpcamera.h"
|
|
#include "umscamera.h"
|
|
#include "dmetadata.h"
|
|
#include "jpegutils.h"
|
|
#include "mtqueue.h"
|
|
#include "cameracontroller.h"
|
|
#include "cameracontroller.moc"
|
|
|
|
namespace Digikam
|
|
{
|
|
|
|
class CameraThread;
|
|
|
|
class CameraCommand
|
|
{
|
|
public:
|
|
|
|
enum Action
|
|
{
|
|
gp_none = 0,
|
|
gp_connect,
|
|
gp_cancel,
|
|
gp_cameraInformations,
|
|
gp_listfolders,
|
|
gp_listfiles,
|
|
gp_download,
|
|
gp_upload,
|
|
gp_delete,
|
|
gp_lock,
|
|
gp_thumbnail,
|
|
gp_exif,
|
|
gp_open
|
|
};
|
|
|
|
Action action;
|
|
TQMap<TQString,TQVariant> map;
|
|
};
|
|
|
|
class CameraEvent : public TQCustomEvent
|
|
{
|
|
public:
|
|
|
|
enum State
|
|
{
|
|
gp_connected = 0,
|
|
gp_busy,
|
|
gp_listedfolders,
|
|
gp_listedfiles,
|
|
gp_downloadstarted,
|
|
gp_downloaded,
|
|
gp_downloadFailed,
|
|
gp_opened,
|
|
gp_uploaded,
|
|
gp_uploadFailed,
|
|
gp_deleted,
|
|
gp_deleteFailed,
|
|
gp_locked,
|
|
gp_lockFailed,
|
|
gp_thumbnailed,
|
|
gp_exif,
|
|
gp_cameraInformations,
|
|
gp_infomsg,
|
|
gp_errormsg
|
|
};
|
|
|
|
CameraEvent(State state) :
|
|
TQCustomEvent(TQEvent::User+state)
|
|
{}
|
|
|
|
bool result;
|
|
TQString msg;
|
|
TQMap<TQString,TQVariant> map;
|
|
};
|
|
|
|
class CameraControllerPriv
|
|
{
|
|
public:
|
|
|
|
CameraControllerPriv()
|
|
{
|
|
close = false;
|
|
overwriteAll = false;
|
|
skipAll = false;
|
|
canceled = false;
|
|
downloadTotal = 0;
|
|
parent = 0;
|
|
timer = 0;
|
|
camera = 0;
|
|
thread = 0;
|
|
}
|
|
|
|
bool close;
|
|
bool overwriteAll;
|
|
bool skipAll;
|
|
bool canceled;
|
|
|
|
int downloadTotal;
|
|
|
|
TQWidget *parent;
|
|
|
|
TQTimer *timer;
|
|
|
|
CameraThread *thread;
|
|
|
|
DKCamera *camera;
|
|
|
|
MTQueue<CameraCommand> cmdQueue;
|
|
};
|
|
|
|
class CameraThread : public TQThread
|
|
{
|
|
public:
|
|
|
|
CameraThread(CameraController* controller);
|
|
~CameraThread();
|
|
|
|
void sendBusy(bool busy);
|
|
void sendError(const TQString& msg);
|
|
void sendInfo(const TQString& msg);
|
|
|
|
protected:
|
|
|
|
void run();
|
|
|
|
private:
|
|
|
|
CameraControllerPriv *d;
|
|
|
|
TQObject *parent;
|
|
};
|
|
|
|
CameraThread::CameraThread(CameraController* controller)
|
|
: d(controller->d), parent(controller)
|
|
{
|
|
}
|
|
|
|
CameraThread::~CameraThread()
|
|
{
|
|
}
|
|
|
|
void CameraThread::run()
|
|
{
|
|
if (d->close)
|
|
return;
|
|
|
|
sendBusy(true);
|
|
|
|
CameraCommand* cmd = d->cmdQueue.dequeue();
|
|
if (cmd)
|
|
{
|
|
switch (cmd->action)
|
|
{
|
|
case(CameraCommand::gp_connect):
|
|
{
|
|
sendInfo(i18n("Connecting to camera..."));
|
|
|
|
bool result = d->camera->doConnect();
|
|
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_connected);
|
|
event->result = result;
|
|
TQApplication::postEvent(parent, event);
|
|
|
|
if (result)
|
|
sendInfo(i18n("Connection established"));
|
|
else
|
|
sendInfo(i18n("Connection failed"));
|
|
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_cameraInformations):
|
|
{
|
|
sendInfo(i18n("Getting camera information..."));
|
|
|
|
TQString summary, manual, about;
|
|
|
|
d->camera->cameraSummary(summary);
|
|
d->camera->cameraManual(manual);
|
|
d->camera->cameraAbout(about);
|
|
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_cameraInformations);
|
|
event->map.insert("summary", TQVariant(summary));
|
|
event->map.insert("manual", TQVariant(manual));
|
|
event->map.insert("about", TQVariant(about));
|
|
TQApplication::postEvent(parent, event);
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_listfolders):
|
|
{
|
|
sendInfo(i18n("Listing folders..."));
|
|
|
|
TQStringList folderList;
|
|
folderList.append(d->camera->path());
|
|
d->camera->getAllFolders(d->camera->path(), folderList);
|
|
|
|
/* TODO: ugly hack since qt <= 3.1.2 does not define
|
|
TQStringList with TQDeepCopy as a friend. */
|
|
TQValueList<TQString> flist(folderList);
|
|
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_listedfolders);
|
|
event->map.insert("folders", TQVariant(flist));
|
|
TQApplication::postEvent(parent, event);
|
|
|
|
sendInfo(i18n("The folders have been listed."));
|
|
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_listfiles):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
|
|
sendInfo(i18n("The files in %1 have been listed.").arg(folder));
|
|
|
|
GPItemInfoList itemsList;
|
|
// setting getImageDimensions to false is a huge speedup for UMSCamera
|
|
if (!d->camera->getItemsInfoList(folder, itemsList, false))
|
|
{
|
|
sendError(i18n("Failed to list files in %1").arg(folder));
|
|
}
|
|
|
|
if (!itemsList.isEmpty())
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_listedfiles);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
|
|
TQByteArray ba;
|
|
TQDataStream ds(ba, IO_WriteOnly);
|
|
ds << itemsList;
|
|
|
|
event->map.insert("files", TQVariant(ba));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
|
|
sendInfo(i18n("Listing files in %1 is complete").arg(folder));
|
|
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_thumbnail):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
TQString file = cmd->map["file"].asString();
|
|
|
|
sendInfo(i18n("Getting thumbnails..."));
|
|
|
|
TQImage thumbnail;
|
|
d->camera->getThumbnail(folder, file, thumbnail);
|
|
|
|
if (!thumbnail.isNull())
|
|
{
|
|
thumbnail = thumbnail.smoothScale(ThumbnailSize::Huge, ThumbnailSize::Huge, TQ_ScaleMin);
|
|
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_thumbnailed);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("thumbnail", TQVariant(thumbnail));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_exif):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
TQString file = cmd->map["file"].asString();
|
|
|
|
sendInfo(i18n("Getting EXIF information for %1/%2...").arg(folder).arg(file));
|
|
|
|
char* edata = 0;
|
|
int esize = 0;
|
|
d->camera->getExif(folder, file, &edata, esize);
|
|
|
|
if (edata || esize)
|
|
{
|
|
TQByteArray ba;
|
|
TQDataStream ds(ba, IO_WriteOnly);
|
|
ds.writeRawBytes(edata, esize);
|
|
delete [] edata;
|
|
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_exif);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("exifSize", TQVariant(esize));
|
|
event->map.insert("exifData", TQVariant(ba));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_download):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
TQString file = cmd->map["file"].asString();
|
|
TQString dest = cmd->map["dest"].asString();
|
|
bool autoRotate = cmd->map["autoRotate"].asBool();
|
|
bool fixDateTime = cmd->map["fixDateTime"].asBool();
|
|
TQDateTime newDateTime = cmd->map["newDateTime"].asDateTime();
|
|
bool setPhotographerId = cmd->map["setPhotographerId"].asBool();
|
|
TQString author = cmd->map["author"].asString();
|
|
TQString authorTitle = cmd->map["authorTitle"].asString();
|
|
bool setCredits = cmd->map["setCredits"].asBool();
|
|
TQString credit = cmd->map["credit"].asString();
|
|
TQString source = cmd->map["source"].asString();
|
|
TQString copyright = cmd->map["copyright"].asString();
|
|
bool convertJpeg = cmd->map["convertJpeg"].asBool();
|
|
TQString losslessFormat = cmd->map["losslessFormat"].asString();
|
|
sendInfo(i18n("Downloading file %1...").arg(file));
|
|
|
|
// download to a temp file
|
|
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_downloadstarted);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("dest", TQVariant(dest));
|
|
TQApplication::postEvent(parent, event);
|
|
|
|
KURL tempURL(dest);
|
|
tempURL = tempURL.upURL();
|
|
tempURL.addPath( TQString(".digikam-camera-tmp1-%1").arg(getpid()).append(file));
|
|
DDebug() << "Downloading: " << file << " using (" << tempURL.path() << ")" << endl;
|
|
TQString temp = tempURL.path();
|
|
|
|
bool result = d->camera->downloadItem(folder, file, tempURL.path());
|
|
|
|
if (result && isJpegImage(tempURL.path()))
|
|
{
|
|
if (autoRotate)
|
|
{
|
|
DDebug() << "Exif autorotate: " << file << " using (" << tempURL.path() << ")" << endl;
|
|
sendInfo(i18n("EXIF rotating file %1...").arg(file));
|
|
exifRotate(tempURL.path(), file);
|
|
}
|
|
|
|
if (fixDateTime || setPhotographerId || setCredits)
|
|
{
|
|
DDebug() << "Set Metadata from: " << file << " using (" << tempURL.path() << ")" << endl;
|
|
sendInfo(i18n("Setting Metadata tags to file %1...").arg(file));
|
|
DMetadata metadata(tempURL.path());
|
|
|
|
if (fixDateTime)
|
|
metadata.setImageDateTime(newDateTime, true);
|
|
|
|
if (setPhotographerId)
|
|
metadata.setImagePhotographerId(author, authorTitle);
|
|
|
|
if (setCredits)
|
|
metadata.setImageCredits(credit, source, copyright);
|
|
|
|
metadata.applyChanges();
|
|
}
|
|
|
|
// Convert Jpeg file to lossless format if necessary,
|
|
// and move converted image to destination.
|
|
|
|
if (convertJpeg)
|
|
{
|
|
DDebug() << "Convert to LossLess: " << file << " using (" << tempURL.path() << ")" << endl;
|
|
sendInfo(i18n("Converting %1 to lossless file format...").arg(file));
|
|
|
|
KURL tempURL2(dest);
|
|
tempURL2 = tempURL2.upURL();
|
|
tempURL2.addPath( TQString(".digikam-camera-tmp2-%1").arg(getpid()).append(file));
|
|
temp = tempURL2.path();
|
|
|
|
if (!jpegConvert(tempURL.path(), tempURL2.path(), file, losslessFormat))
|
|
{
|
|
// convert failed. delete the temp file
|
|
unlink(TQFile::encodeName(tempURL.path()));
|
|
unlink(TQFile::encodeName(tempURL2.path()));
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
// Else remove only the first temp file.
|
|
unlink(TQFile::encodeName(tempURL.path()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_downloaded);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("dest", TQVariant(dest));
|
|
event->map.insert("temp", TQVariant(temp));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
else
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_downloadFailed);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("dest", TQVariant(dest));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_open):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
TQString file = cmd->map["file"].asString();
|
|
TQString dest = cmd->map["dest"].asString();
|
|
|
|
sendInfo(i18n("Retrieving file %1 from camera...").arg(file));
|
|
|
|
bool result = d->camera->downloadItem(folder, file, dest);
|
|
|
|
if (result)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_opened);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("dest", TQVariant(dest));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
else
|
|
{
|
|
sendError(i18n("Failed to retrieve file %1 from camera").arg(file));
|
|
}
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_upload):
|
|
{
|
|
TQString folder = cmd->map["destFolder"].asString();
|
|
|
|
// We will using the same source file name to create the dest file
|
|
// name in camera.
|
|
TQString file = cmd->map["destFile"].asString();
|
|
|
|
// The source file path to download in camera.
|
|
TQString src = cmd->map["srcFilePath"].asString();
|
|
|
|
sendInfo(i18n("Uploading file %1 to camera...").arg(file));
|
|
|
|
GPItemInfo itemsInfo;
|
|
|
|
bool result = d->camera->uploadItem(folder, file, src, itemsInfo);
|
|
|
|
if (result)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_uploaded);
|
|
TQByteArray ba;
|
|
TQDataStream ds(ba, IO_WriteOnly);
|
|
ds << itemsInfo;
|
|
event->map.insert("info", TQVariant(ba));
|
|
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
else
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_uploadFailed);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
event->map.insert("src", TQVariant(src));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_delete):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
TQString file = cmd->map["file"].asString();
|
|
|
|
sendInfo(i18n("Deleting file %1...").arg(file));
|
|
|
|
bool result = d->camera->deleteItem(folder, file);
|
|
|
|
if (result)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_deleted);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
else
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_deleteFailed);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
break;
|
|
}
|
|
case(CameraCommand::gp_lock):
|
|
{
|
|
TQString folder = cmd->map["folder"].asString();
|
|
TQString file = cmd->map["file"].asString();
|
|
bool lock = cmd->map["lock"].asBool();
|
|
|
|
sendInfo(i18n("Toggle lock file %1...").arg(file));
|
|
|
|
bool result = d->camera->setLockItem(folder, file, lock);
|
|
|
|
if (result)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_locked);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
else
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_lockFailed);
|
|
event->map.insert("folder", TQVariant(folder));
|
|
event->map.insert("file", TQVariant(file));
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
DWarning() << k_funcinfo << " unknown action specified" << endl;
|
|
}
|
|
|
|
delete cmd;
|
|
}
|
|
|
|
sendBusy(false);
|
|
}
|
|
|
|
void CameraThread::sendBusy(bool val)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_busy);
|
|
event->result = val;
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
|
|
void CameraThread::sendError(const TQString& msg)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_errormsg);
|
|
event->msg = msg;
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
|
|
void CameraThread::sendInfo(const TQString& msg)
|
|
{
|
|
CameraEvent* event = new CameraEvent(CameraEvent::gp_infomsg);
|
|
event->msg = msg;
|
|
TQApplication::postEvent(parent, event);
|
|
}
|
|
|
|
|
|
//-- Camera Controller ------------------------------------------------------
|
|
|
|
|
|
CameraController::CameraController(TQWidget* parent, const TQString& title, const TQString& model,
|
|
const TQString& port, const TQString& path)
|
|
: TQObject(parent)
|
|
{
|
|
d = new CameraControllerPriv;
|
|
d->parent = parent;
|
|
d->canceled = false;
|
|
d->close = false;
|
|
d->overwriteAll = false;
|
|
d->skipAll = false;
|
|
d->downloadTotal = 0;
|
|
d->camera = 0;
|
|
|
|
// URL parsing (c) Stephan Kulow
|
|
if (path.startsWith("camera:/"))
|
|
{
|
|
KURL url(path);
|
|
DDebug() << "path " << path << " " << url << " " << url.host() << endl;
|
|
TQString xport = url.host();
|
|
if (xport.startsWith("usb:"))
|
|
{
|
|
DDebug() << "xport " << xport << endl;
|
|
TQRegExp x = TQRegExp("(usb:[0-9,]*)");
|
|
|
|
if (x.search(xport) != -1)
|
|
{
|
|
TQString usbport = x.cap(1);
|
|
DDebug() << "USB " << xport << " " << usbport << endl;
|
|
// if ((xport == usbport) || ((count == 1) && (xport == "usb:"))) {
|
|
// model = xmodel;
|
|
d->camera = new GPCamera(title, url.user(), "usb:", "/");
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!d->camera)
|
|
{
|
|
if (model.lower() == "directory browse")
|
|
d->camera = new UMSCamera(title, model, port, path);
|
|
else
|
|
d->camera = new GPCamera(title, model, port, path);
|
|
}
|
|
|
|
d->thread = new CameraThread(this);
|
|
d->timer = new TQTimer(this);
|
|
|
|
connect(d->timer, TQT_SIGNAL(timeout()),
|
|
this, TQT_SLOT(slotProcessNext()));
|
|
|
|
d->timer->start(50, false);
|
|
}
|
|
|
|
CameraController::~CameraController()
|
|
{
|
|
if (d->timer->isActive())
|
|
{
|
|
d->timer->stop();
|
|
delete d->timer;
|
|
}
|
|
|
|
d->camera->cancel();
|
|
d->canceled = true;
|
|
d->close = true;
|
|
|
|
while (d->thread->running())
|
|
d->thread->wait();
|
|
|
|
delete d->thread;
|
|
delete d->camera;
|
|
delete d;
|
|
}
|
|
|
|
TQString CameraController::getCameraPath()
|
|
{
|
|
if (!d->camera) return TQString();
|
|
return d->camera->path();
|
|
}
|
|
|
|
TQString CameraController::getCameraTitle()
|
|
{
|
|
if (!d->camera) return TQString();
|
|
return d->camera->title();
|
|
}
|
|
|
|
void CameraController::slotConnect()
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_connect;
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::listFolders()
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_listfolders;
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::listFiles(const TQString& folder)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_listfiles;
|
|
cmd->map.insert("folder", TQVariant(folder));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::getThumbnail(const TQString& folder, const TQString& file)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_thumbnail;
|
|
cmd->map.insert("folder", TQVariant(folder));
|
|
cmd->map.insert("file", TQVariant(file));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::getExif(const TQString& folder, const TQString& file)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_exif;
|
|
cmd->map.insert("folder", TQVariant(folder));
|
|
cmd->map.insert("file", TQVariant(file));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::getCameraInformations()
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_cameraInformations;
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::upload(const TQFileInfo& srcFileInfo, const TQString& destFile, const TQString& destFolder)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_upload;
|
|
cmd->map.insert("srcFilePath", TQVariant(srcFileInfo.filePath()));
|
|
cmd->map.insert("destFile", TQVariant(destFile));
|
|
cmd->map.insert("destFolder", TQVariant(destFolder));
|
|
d->cmdQueue.enqueue(cmd);
|
|
DDebug() << "Uploading '" << srcFileInfo.filePath() << "' into camera : '" << destFolder <<
|
|
"' (" << destFile << ")" << endl;
|
|
}
|
|
|
|
void CameraController::downloadPrep()
|
|
{
|
|
d->overwriteAll = false;
|
|
d->skipAll = false;
|
|
d->downloadTotal = 0;
|
|
}
|
|
|
|
void CameraController::download(DownloadSettingsContainer downloadSettings)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_download;
|
|
cmd->map.insert("folder", TQVariant(downloadSettings.folder));
|
|
cmd->map.insert("file", TQVariant(downloadSettings.file));
|
|
cmd->map.insert("dest", TQVariant(downloadSettings.dest));
|
|
cmd->map.insert("autoRotate", TQVariant(downloadSettings.autoRotate, 0));
|
|
cmd->map.insert("fixDateTime", TQVariant(downloadSettings.fixDateTime, 0));
|
|
cmd->map.insert("newDateTime", TQVariant(downloadSettings.newDateTime));
|
|
cmd->map.insert("setPhotographerId", TQVariant(downloadSettings.setPhotographerId, 0));
|
|
cmd->map.insert("author", TQVariant(downloadSettings.author));
|
|
cmd->map.insert("authorTitle", TQVariant(downloadSettings.authorTitle));
|
|
cmd->map.insert("setCredits", TQVariant(downloadSettings.setCredits, 0));
|
|
cmd->map.insert("credit", TQVariant(downloadSettings.credit));
|
|
cmd->map.insert("source", TQVariant(downloadSettings.source));
|
|
cmd->map.insert("copyright", TQVariant(downloadSettings.copyright));
|
|
cmd->map.insert("convertJpeg", TQVariant(downloadSettings.convertJpeg, 0));
|
|
cmd->map.insert("losslessFormat", TQVariant(downloadSettings.losslessFormat));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::deleteFile(const TQString& folder, const TQString& file)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_delete;
|
|
cmd->map.insert("folder", TQVariant(folder));
|
|
cmd->map.insert("file", TQVariant(file));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::lockFile(const TQString& folder, const TQString& file, bool lock)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_lock;
|
|
cmd->map.insert("folder", TQVariant(folder));
|
|
cmd->map.insert("file", TQVariant(file));
|
|
cmd->map.insert("lock", TQVariant(lock, 0));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::openFile(const TQString& folder, const TQString& file)
|
|
{
|
|
d->canceled = false;
|
|
CameraCommand *cmd = new CameraCommand;
|
|
cmd->action = CameraCommand::gp_open;
|
|
cmd->map.insert("folder", TQVariant(folder));
|
|
cmd->map.insert("file", TQVariant(file));
|
|
cmd->map.insert("dest", TQVariant(locateLocal("tmp", file)));
|
|
d->cmdQueue.enqueue(cmd);
|
|
}
|
|
|
|
void CameraController::slotCancel()
|
|
{
|
|
d->canceled = true;
|
|
d->cmdQueue.flush();
|
|
d->camera->cancel();
|
|
}
|
|
|
|
void CameraController::customEvent(TQCustomEvent* e)
|
|
{
|
|
CameraEvent* event = dynamic_cast<CameraEvent*>(e);
|
|
if (!event)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch(event->type()-TQEvent::User)
|
|
{
|
|
case (CameraEvent::gp_connected) :
|
|
{
|
|
emit signalConnected(event->result);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_cameraInformations) :
|
|
{
|
|
TQString summary = TQDeepCopy<TQString>(event->map["summary"].asString());
|
|
TQString manual = TQDeepCopy<TQString>(event->map["manual"].asString());
|
|
TQString about = TQDeepCopy<TQString>(event->map["about"].asString());
|
|
emit signalCameraInformations(summary, manual, about);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_errormsg) :
|
|
{
|
|
emit signalErrorMsg(TQDeepCopy<TQString>(event->msg));
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_busy) :
|
|
{
|
|
if (event->result)
|
|
emit signalBusy(true);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_infomsg) :
|
|
{
|
|
if (!d->canceled)
|
|
emit signalInfoMsg(TQDeepCopy<TQString>(event->msg));
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_listedfolders) :
|
|
{
|
|
/* TODO: ugly hack since qt <= 3.1.2 does not define
|
|
TQStringList with TQDeepCopy as a friend. */
|
|
TQValueList<TQVariant> flist = TQDeepCopy< TQValueList<TQVariant> >(event->map["folders"].toList());
|
|
|
|
TQStringList folderList;
|
|
TQValueList<TQVariant>::Iterator it;
|
|
for (it = flist.begin(); it != flist.end(); ++it )
|
|
{
|
|
folderList.append(TQDeepCopy<TQString>((*it).asString()));
|
|
}
|
|
|
|
emit signalFolderList(folderList);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_listedfiles) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQByteArray ba = TQDeepCopy<TQByteArray>(event->map["files"].asByteArray());
|
|
TQDataStream ds(ba, IO_ReadOnly);
|
|
GPItemInfoList items;
|
|
ds >> items;
|
|
emit signalFileList(items);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_thumbnailed) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
TQImage thumb = TQDeepCopy<TQImage>(event->map["thumbnail"].asImage());
|
|
emit signalThumbnail(folder, file, thumb);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_exif) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
TQByteArray ba = TQDeepCopy<TQByteArray>(event->map["exifData"].asByteArray());
|
|
emit signalExifData(ba);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_downloadstarted) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
emit signalDownloaded(folder, file, GPItemInfo::DownloadStarted);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_downloaded) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
TQString dest = TQDeepCopy<TQString>(event->map["dest"].asString());
|
|
TQString temp = TQDeepCopy<TQString>(event->map["temp"].asString());
|
|
|
|
d->timer->stop();
|
|
|
|
bool skip = false;
|
|
bool cancel = false;
|
|
bool overwrite = false;
|
|
|
|
// Check if dest file already exist.
|
|
|
|
if (!d->overwriteAll)
|
|
{
|
|
TQFileInfo info(dest);
|
|
|
|
while (info.exists())
|
|
{
|
|
if (d->skipAll)
|
|
{
|
|
skip = true;
|
|
break;
|
|
}
|
|
|
|
TDEIO::RenameDlg dlg(d->parent, i18n("Rename File"),
|
|
folder + TQString("/") + file, dest,
|
|
TDEIO::RenameDlg_Mode(TDEIO::M_MULTI | TDEIO::M_OVERWRITE | TDEIO::M_SKIP));
|
|
|
|
int result = dlg.exec();
|
|
dest = dlg.newDestURL().path();
|
|
info = TQFileInfo(dest);
|
|
|
|
switch (result)
|
|
{
|
|
case TDEIO::R_CANCEL:
|
|
{
|
|
cancel = true;
|
|
break;
|
|
}
|
|
case TDEIO::R_SKIP:
|
|
{
|
|
skip = true;
|
|
break;
|
|
}
|
|
case TDEIO::R_AUTO_SKIP:
|
|
{
|
|
d->skipAll = true;
|
|
skip = true;
|
|
break;
|
|
}
|
|
case TDEIO::R_OVERWRITE:
|
|
{
|
|
overwrite = true;
|
|
break;
|
|
}
|
|
case TDEIO::R_OVERWRITE_ALL:
|
|
{
|
|
d->overwriteAll = true;
|
|
overwrite = true;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (cancel || skip || overwrite)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cancel)
|
|
{
|
|
unlink(TQFile::encodeName(temp));
|
|
slotCancel();
|
|
d->timer->start(50);
|
|
emit signalSkipped(folder, file);
|
|
return;
|
|
}
|
|
else if (skip)
|
|
{
|
|
unlink(TQFile::encodeName(temp));
|
|
d->timer->start(50);
|
|
emit signalInfoMsg(i18n("Skipped file %1").arg(file));
|
|
emit signalSkipped(folder, file);
|
|
return;
|
|
}
|
|
|
|
// move the file to the destination file
|
|
if (rename(TQFile::encodeName(temp), TQFile::encodeName(dest)) != 0)
|
|
{
|
|
// rename failed. delete the temp file
|
|
unlink(TQFile::encodeName(temp));
|
|
d->timer->start(50);
|
|
emit signalDownloaded(folder, file, GPItemInfo::DownloadFailed);
|
|
}
|
|
else
|
|
{
|
|
d->timer->start(50);
|
|
emit signalDownloaded(folder, file, GPItemInfo::DownloadedYes);
|
|
}
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_downloadFailed) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
|
|
d->timer->stop();
|
|
|
|
TQString msg = i18n("Failed to download file \"%1\".").arg(file);
|
|
|
|
if (!d->canceled)
|
|
{
|
|
if (d->cmdQueue.isEmpty())
|
|
{
|
|
KMessageBox::error(d->parent, msg);
|
|
}
|
|
else
|
|
{
|
|
msg += i18n(" Do you want to continue?");
|
|
int result = KMessageBox::warningContinueCancel(d->parent, msg);
|
|
if (result != KMessageBox::Continue)
|
|
slotCancel();
|
|
}
|
|
}
|
|
|
|
d->timer->start(50);
|
|
emit signalDownloaded(folder, file, GPItemInfo::DownloadFailed);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_uploaded) :
|
|
{
|
|
TQByteArray ba = TQDeepCopy<TQByteArray>(event->map["info"].asByteArray());
|
|
TQDataStream ds(ba, IO_ReadOnly);
|
|
GPItemInfo itemInfo;
|
|
ds >> itemInfo;
|
|
|
|
emit signalUploaded(itemInfo);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_uploadFailed) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
TQString src = TQDeepCopy<TQString>(event->map["src"].asString());
|
|
|
|
d->timer->stop();
|
|
|
|
TQString msg = i18n("Failed to upload file \"%1\".").arg(file);
|
|
|
|
if (!d->canceled)
|
|
{
|
|
if (d->cmdQueue.isEmpty())
|
|
{
|
|
KMessageBox::error(d->parent, msg);
|
|
}
|
|
else
|
|
{
|
|
msg += i18n(" Do you want to continue?");
|
|
int result = KMessageBox::warningContinueCancel(d->parent, msg);
|
|
if (result != KMessageBox::Continue)
|
|
slotCancel();
|
|
}
|
|
}
|
|
|
|
d->timer->start(50);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_deleted) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
emit signalDeleted(folder, file, true);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_deleteFailed) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
|
|
d->timer->stop();
|
|
emit signalDeleted(folder, file, false);
|
|
|
|
TQString msg = i18n("Failed to delete file \"%1\".").arg(file);
|
|
|
|
if (!d->canceled)
|
|
{
|
|
if (d->cmdQueue.isEmpty())
|
|
{
|
|
KMessageBox::error(d->parent, msg);
|
|
}
|
|
else
|
|
{
|
|
msg += i18n(" Do you want to continue?");
|
|
int result = KMessageBox::warningContinueCancel(d->parent, msg);
|
|
if (result != KMessageBox::Continue)
|
|
slotCancel();
|
|
}
|
|
}
|
|
|
|
d->timer->start(50);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_locked) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
emit signalLocked(folder, file, true);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_lockFailed) :
|
|
{
|
|
TQString folder = TQDeepCopy<TQString>(event->map["folder"].asString());
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
|
|
d->timer->stop();
|
|
emit signalLocked(folder, file, false);
|
|
|
|
TQString msg = i18n("Failed to toggle lock file \"%1\".").arg(file);
|
|
|
|
if (!d->canceled)
|
|
{
|
|
if (d->cmdQueue.isEmpty())
|
|
{
|
|
KMessageBox::error(d->parent, msg);
|
|
}
|
|
else
|
|
{
|
|
msg += i18n(" Do you want to continue?");
|
|
int result = KMessageBox::warningContinueCancel(d->parent, msg);
|
|
if (result != KMessageBox::Continue)
|
|
slotCancel();
|
|
}
|
|
}
|
|
|
|
d->timer->start(50);
|
|
break;
|
|
}
|
|
case (CameraEvent::gp_opened) :
|
|
{
|
|
TQString file = TQDeepCopy<TQString>(event->map["file"].asString());
|
|
TQString dest = TQDeepCopy<TQString>(event->map["dest"].asString());
|
|
|
|
KURL url(dest);
|
|
KURL::List urlList;
|
|
urlList << url;
|
|
|
|
ImageWindow *im = ImageWindow::imagewindow();
|
|
im->loadURL(urlList, url, i18n("Camera \"%1\"").arg(d->camera->model()), false);
|
|
|
|
if (im->isHidden())
|
|
im->show();
|
|
else
|
|
im->raise();
|
|
|
|
im->setFocus();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DWarning() << k_funcinfo << "Unknown event" << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CameraController::slotProcessNext()
|
|
{
|
|
if (d->thread->running())
|
|
return;
|
|
|
|
if (d->cmdQueue.isEmpty())
|
|
{
|
|
emit signalBusy(false);
|
|
return;
|
|
}
|
|
|
|
d->timer->stop();
|
|
emit signalBusy(true);
|
|
|
|
CameraCommand* cmd = d->cmdQueue.head();
|
|
|
|
TQString folder;
|
|
TQString file;
|
|
TQString dest;
|
|
|
|
if ((cmd->action == CameraCommand::gp_exif) &&
|
|
(typeid(*(d->camera)) == typeid(UMSCamera)))
|
|
{
|
|
folder = TQDeepCopy<TQString>(cmd->map["folder"].asString());
|
|
file = TQDeepCopy<TQString>(cmd->map["file"].asString());
|
|
|
|
emit signalExifFromFile(folder, file);
|
|
|
|
d->cmdQueue.dequeue();
|
|
d->timer->start(50, false);
|
|
return;
|
|
}
|
|
|
|
if (cmd->action == CameraCommand::gp_download)
|
|
{
|
|
folder = TQDeepCopy<TQString>(cmd->map["folder"].asString());
|
|
file = TQDeepCopy<TQString>(cmd->map["file"].asString());
|
|
dest = TQDeepCopy<TQString>(cmd->map["dest"].asString());
|
|
cmd->map["dest"] = TQVariant(TQDeepCopy<TQString>(dest));
|
|
}
|
|
|
|
d->thread->start();
|
|
d->timer->start(50, false);
|
|
}
|
|
|
|
} // namespace Digikam
|