1
/* ============================================================
2
* Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
6
* Copyright 2004 by Renchi Raju
8
* This program is free software; you can redistribute it
9
* and/or modify it under the terms of the GNU General
10
* Public License as published by the Free Software Foundation;
11
* either version 2, or (at your option)
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* ============================================================ */
23
#include <qwaitcondition.h>
25
#include <qapplication.h>
26
#include <qdeepcopy.h>
29
#include <qdatastream.h>
35
#include <kmessagebox.h>
36
#include <kio/renamedlg.h>
38
#include <kstandarddirs.h>
41
#include <libkexif/kexifdialog.h>
45
#include <sys/types.h>
51
#include <imagewindow.h>
53
#include "umscamera.h"
54
#include "exifrotate.h"
56
#include "cameracontroller.h"
80
QMap<QString,QVariant> map;
83
class CameraEvent : public QCustomEvent
106
CameraEvent(State state) :
107
QCustomEvent(QEvent::User+state)
112
QMap<QString,QVariant> map;
115
class CameraControllerPriv
120
CameraThread* thread;
122
MTQueue<CameraCommand> cmdQueue;
131
class CameraThread : public QThread
135
CameraThread(CameraController* controller);
138
void sendBusy(bool busy);
139
void sendError(const QString& msg);
140
void sendInfo(const QString& msg);
148
CameraControllerPriv* d;
152
CameraThread::CameraThread(CameraController* controller)
153
: d(controller->d), parent(controller)
157
CameraThread::~CameraThread()
161
void CameraThread::run()
169
CameraCommand* cmd = d->cmdQueue.dequeue();
175
case(CameraCommand::gp_connect):
177
sendInfo(i18n("Connecting to camera..."));
179
bool result = d->camera->connect();
181
CameraEvent* event = new CameraEvent(CameraEvent::gp_connected);
182
event->result = result;
183
QApplication::postEvent(parent, event);
186
sendInfo(i18n("Connection established"));
188
sendInfo(i18n("Connection failed"));
192
case(CameraCommand::gp_listfolders):
194
sendInfo(i18n("Listing folders..."));
196
QStringList folderList;
197
folderList.append(d->camera->path());
198
d->camera->getAllFolders(d->camera->path(), folderList);
200
/* TODO: ugly hack since qt <= 3.1.2 does not define
201
QStringList with QDeepCopy as a friend. */
202
QValueList<QString> flist(folderList);
204
CameraEvent* event = new CameraEvent(CameraEvent::gp_listedfolders);
205
event->map.insert("folders", QVariant(flist));
206
QApplication::postEvent(parent, event);
208
sendInfo(i18n("Finished listing folders..."));
212
case(CameraCommand::gp_listfiles):
214
QString folder = cmd->map["folder"].asString();
216
sendInfo(i18n("Listing files in %1...")
219
GPItemInfoList itemsList;
220
if (!d->camera->getItemsInfoList(folder, itemsList))
222
sendError(i18n("Failed to list files in %1")
226
if (!itemsList.isEmpty())
228
CameraEvent* event = new CameraEvent(CameraEvent::gp_listedfiles);
229
event->map.insert("folder", QVariant(folder));
232
QDataStream ds(ba, IO_WriteOnly);
235
event->map.insert("files", QVariant(ba));
236
QApplication::postEvent(parent, event);
239
sendInfo(i18n("Finished listing files in %1")
244
case(CameraCommand::gp_thumbnail):
246
QString folder = cmd->map["folder"].asString();
247
QString file = cmd->map["file"].asString();
249
sendInfo(i18n("Getting thumbnail for %1/%2...")
254
d->camera->getThumbnail(folder, file,
257
if (!thumbnail.isNull())
259
thumbnail = thumbnail.smoothScale(128,128,QImage::ScaleMin);
261
CameraEvent* event = new CameraEvent(CameraEvent::gp_thumbnailed);
262
event->map.insert("folder", QVariant(folder));
263
event->map.insert("file", QVariant(file));
264
event->map.insert("thumbnail", QVariant(thumbnail));
265
QApplication::postEvent(parent, event);
270
case(CameraCommand::gp_exif):
272
QString folder = cmd->map["folder"].asString();
273
QString file = cmd->map["file"].asString();
275
sendInfo(i18n("Getting EXIF information for %1/%2...")
281
d->camera->getExif(folder, file, &edata, esize);
283
if (!edata || !esize)
285
sendError(i18n("Failed to retrieve EXIF information for %1")
291
QDataStream ds(ba, IO_WriteOnly);
292
ds.writeRawBytes(edata, esize);
295
CameraEvent* event = new CameraEvent(CameraEvent::gp_exif);
296
event->map.insert("folder", QVariant(folder));
297
event->map.insert("file", QVariant(file));
298
event->map.insert("exifSize", QVariant(esize));
299
event->map.insert("exifData", QVariant(ba));
300
QApplication::postEvent(parent, event);
304
case(CameraCommand::gp_download):
306
QString folder = cmd->map["folder"].asString();
307
QString file = cmd->map["file"].asString();
308
QString dest = cmd->map["dest"].asString();
309
bool autoRotate = cmd->map["autoRotate"].asBool();
311
sendInfo(i18n("Downloading file %1...")
314
// download to a temp file
316
tempURL = tempURL.upURL();
317
tempURL.addPath( QString(".digikam-camera-%1")
320
bool result = d->camera->downloadItem(folder, file,
327
sendInfo(i18n("EXIF rotating file %1...")
329
Digikam::exifRotate(tempURL.path());
332
// move the file to the destination file
333
if (rename(QFile::encodeName(tempURL.path()),
334
QFile::encodeName(dest)) != 0)
336
// rename failed. delete the temp file
337
unlink(QFile::encodeName(tempURL.path()));
345
CameraEvent* event = new CameraEvent(CameraEvent::gp_downloaded);
346
event->map.insert("folder", QVariant(folder));
347
event->map.insert("file", QVariant(file));
348
event->map.insert("dest", QVariant(dest));
349
QApplication::postEvent(parent, event);
353
CameraEvent* event = new CameraEvent(CameraEvent::gp_downloadFailed);
354
event->map.insert("folder", QVariant(folder));
355
event->map.insert("file", QVariant(file));
356
event->map.insert("dest", QVariant(dest));
357
QApplication::postEvent(parent, event);
361
case(CameraCommand::gp_open):
363
QString folder = cmd->map["folder"].asString();
364
QString file = cmd->map["file"].asString();
365
QString dest = cmd->map["dest"].asString();
367
sendInfo(i18n("Retrieving file %1 from camera...")
370
bool result = d->camera->downloadItem(folder, file, dest);
374
CameraEvent* event = new CameraEvent(CameraEvent::gp_opened);
375
event->map.insert("folder", QVariant(folder));
376
event->map.insert("file", QVariant(file));
377
event->map.insert("dest", QVariant(dest));
378
QApplication::postEvent(parent, event);
382
sendError(i18n("Failed to retrieve file %1 from camera")
387
case(CameraCommand::gp_upload):
389
QString folder = cmd->map["folder"].asString();
390
QString file = cmd->map["file"].asString();
391
QString src = cmd->map["src"].asString();
393
sendInfo(i18n("Uploading file %1...")
396
bool result = d->camera->uploadItem(folder, file, src);
400
CameraEvent* event = new CameraEvent(CameraEvent::gp_uploaded);
401
event->map.insert("folder", QVariant(folder));
402
event->map.insert("file", QVariant(file));
403
event->map.insert("src", QVariant(src));
404
QApplication::postEvent(parent, event);
408
CameraEvent* event = new CameraEvent(CameraEvent::gp_uploadFailed);
409
event->map.insert("folder", QVariant(folder));
410
event->map.insert("file", QVariant(file));
411
event->map.insert("src", QVariant(src));
412
QApplication::postEvent(parent, event);
416
case(CameraCommand::gp_delete):
418
QString folder = cmd->map["folder"].asString();
419
QString file = cmd->map["file"].asString();
421
sendInfo(i18n("Deleting file %1...")
424
bool result = d->camera->deleteItem(folder, file);
428
CameraEvent* event = new CameraEvent(CameraEvent::gp_deleted);
429
event->map.insert("folder", QVariant(folder));
430
event->map.insert("file", QVariant(file));
431
QApplication::postEvent(parent, event);
435
CameraEvent* event = new CameraEvent(CameraEvent::gp_deleteFailed);
436
event->map.insert("folder", QVariant(folder));
437
event->map.insert("file", QVariant(file));
438
QApplication::postEvent(parent, event);
443
kdWarning() << k_funcinfo << " unknown action specified" << endl;
453
void CameraThread::sendBusy(bool val)
455
CameraEvent* event = new CameraEvent(CameraEvent::gp_busy);
457
QApplication::postEvent(parent, event);
460
void CameraThread::sendError(const QString& msg)
462
CameraEvent* event = new CameraEvent(CameraEvent::gp_errormsg);
464
QApplication::postEvent(parent, event);
468
void CameraThread::sendInfo(const QString& msg)
470
CameraEvent* event = new CameraEvent(CameraEvent::gp_infomsg);
472
QApplication::postEvent(parent, event);
475
// -- Camera Controller ------------------------------------------------------
477
CameraController::CameraController(QWidget* parent, const QString& model,
482
d = new CameraControllerPriv;
486
d->overwriteAll = false;
488
d->downloadTotal = 0;
490
if (model.lower() == "directory browse")
491
d->camera = new UMSCamera(model, port, path);
493
d->camera = new GPCamera(model, port, path);
495
d->thread = new CameraThread(this);
496
d->timer = new QTimer();
498
connect(d->timer, SIGNAL(timeout()),
499
SLOT(slotProcessNext()));
501
d->timer->start(50, false);
504
CameraController::~CameraController()
511
while (d->thread->running())
518
void CameraController::slotConnect()
520
CameraCommand *cmd = new CameraCommand;
521
cmd->action = CameraCommand::gp_connect;
522
d->cmdQueue.enqueue(cmd);
525
void CameraController::listFolders()
527
CameraCommand *cmd = new CameraCommand;
528
cmd->action = CameraCommand::gp_listfolders;
529
d->cmdQueue.enqueue(cmd);
532
void CameraController::listFiles(const QString& folder)
534
CameraCommand *cmd = new CameraCommand;
535
cmd->action = CameraCommand::gp_listfiles;
536
cmd->map.insert("folder", QVariant(folder));
537
d->cmdQueue.enqueue(cmd);
540
void CameraController::getThumbnail(const QString& folder, const QString& file)
542
CameraCommand *cmd = new CameraCommand;
543
cmd->action = CameraCommand::gp_thumbnail;
544
cmd->map.insert("folder", QVariant(folder));
545
cmd->map.insert("file", QVariant(file));
546
d->cmdQueue.enqueue(cmd);
549
void CameraController::getExif(const QString& folder, const QString& file)
551
CameraCommand *cmd = new CameraCommand;
552
cmd->action = CameraCommand::gp_exif;
553
cmd->map.insert("folder", QVariant(folder));
554
cmd->map.insert("file", QVariant(file));
555
d->cmdQueue.enqueue(cmd);
558
void CameraController::downloadPrep()
560
d->overwriteAll = false;
562
d->downloadTotal = 0;
565
void CameraController::download(const QString& folder, const QString& file,
566
const QString& dest, bool autoRotate)
568
CameraCommand *cmd = new CameraCommand;
569
cmd->action = CameraCommand::gp_download;
570
cmd->map.insert("folder", QVariant(folder));
571
cmd->map.insert("file", QVariant(file));
572
cmd->map.insert("dest", QVariant(dest));
573
cmd->map.insert("autoRotate", QVariant(autoRotate, 0));
574
d->cmdQueue.enqueue(cmd);
577
void CameraController::deleteFile(const QString& folder, const QString& file)
579
CameraCommand *cmd = new CameraCommand;
580
cmd->action = CameraCommand::gp_delete;
581
cmd->map.insert("folder", QVariant(folder));
582
cmd->map.insert("file", QVariant(file));
583
d->cmdQueue.enqueue(cmd);
586
void CameraController::openFile(const QString& folder, const QString& file)
588
CameraCommand *cmd = new CameraCommand;
589
cmd->action = CameraCommand::gp_open;
590
cmd->map.insert("folder", QVariant(folder));
591
cmd->map.insert("file", QVariant(file));
592
cmd->map.insert("dest", QVariant(locateLocal("tmp", file)));
593
d->cmdQueue.enqueue(cmd);
596
void CameraController::slotCancel()
602
void CameraController::customEvent(QCustomEvent* e)
604
CameraEvent* event = dynamic_cast<CameraEvent*>(e);
610
switch(event->type()-QEvent::User)
612
case (CameraEvent::gp_connected) :
614
emit signalConnected(event->result);
617
case (CameraEvent::gp_errormsg) :
619
emit signalErrorMsg(QDeepCopy<QString>(event->msg));
622
case (CameraEvent::gp_busy) :
625
emit signalBusy(true);
628
case (CameraEvent::gp_infomsg) :
630
emit signalInfoMsg(QDeepCopy<QString>(event->msg));
633
case (CameraEvent::gp_listedfolders) :
635
/* TODO: ugly hack since qt <= 3.1.2 does not define
636
QStringList with QDeepCopy as a friend. */
637
QValueList<QVariant> flist =
638
QDeepCopy< QValueList<QVariant> >(event->map["folders"].toList());
640
QStringList folderList;
641
QValueList<QVariant>::Iterator it;
642
for (it = flist.begin(); it != flist.end(); ++it )
644
folderList.append(QDeepCopy<QString>((*it).asString()));
647
emit signalFolderList(folderList);
650
case (CameraEvent::gp_listedfiles) :
652
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
653
QByteArray ba = QDeepCopy<QByteArray>(event->map["files"].asByteArray());
654
QDataStream ds(ba, IO_ReadOnly);
655
GPItemInfoList items;
657
emit signalFileList(items);
660
case (CameraEvent::gp_thumbnailed) :
662
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
663
QString file = QDeepCopy<QString>(event->map["file"].asString());
664
QImage thumb = QDeepCopy<QImage>(event->map["thumbnail"].asImage());
665
emit signalThumbnail(folder, file, thumb);
668
case (CameraEvent::gp_exif) :
670
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
671
QString file = QDeepCopy<QString>(event->map["file"].asString());
672
QByteArray ba = QDeepCopy<QByteArray>(event->map["exifData"].asByteArray());
674
KExifDialog exif(d->parent);
675
if (exif.loadData(file, ba.data(), ba.size()))
681
KMessageBox::sorry(0, i18n("Failed to retrieve EXIF information for %1")
687
case (CameraEvent::gp_downloaded) :
689
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
690
QString file = QDeepCopy<QString>(event->map["file"].asString());
691
emit signalDownloaded(folder, file);
694
case (CameraEvent::gp_downloadFailed) :
696
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
697
QString file = QDeepCopy<QString>(event->map["file"].asString());
701
QString msg = i18n("Failed to download file %1.")
704
if (d->cmdQueue.isEmpty())
706
KMessageBox::error(d->parent, msg);
710
msg += i18n(" Do you want to continue?");
711
int result = KMessageBox::warningContinueCancel(d->parent, msg);
712
if (result != KMessageBox::Continue)
717
emit signalDownloaded(folder, file);
720
case (CameraEvent::gp_deleted) :
722
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
723
QString file = QDeepCopy<QString>(event->map["file"].asString());
724
emit signalDeleted(folder, file);
727
case (CameraEvent::gp_deleteFailed) :
729
QString folder = QDeepCopy<QString>(event->map["folder"].asString());
730
QString file = QDeepCopy<QString>(event->map["file"].asString());
734
QString msg = i18n("Failed to delete file %1.")
737
if (d->cmdQueue.isEmpty())
739
KMessageBox::error(d->parent, msg);
743
msg += i18n(" Do you want to continue?");
744
int result = KMessageBox::warningContinueCancel(d->parent, msg);
745
if (result != KMessageBox::Continue)
752
case (CameraEvent::gp_opened) :
754
QString file = QDeepCopy<QString>(event->map["file"].asString());
755
QString dest = QDeepCopy<QString>(event->map["dest"].asString());
761
ImageWindow *im = ImageWindow::imagewindow();
762
im->loadURL(urlList, url, file, false);
771
kdWarning() << k_funcinfo << "Unknown event" << endl;
775
void CameraController::slotProcessNext()
777
if (d->thread->running())
780
if (d->cmdQueue.isEmpty())
782
emit signalBusy(false);
787
emit signalBusy(true);
789
CameraCommand* cmd = d->cmdQueue.head();
793
bool overwrite = false;
799
if ((cmd->action == CameraCommand::gp_exif) &&
800
(typeid(*(d->camera)) == typeid(UMSCamera)))
802
folder = QDeepCopy<QString>(cmd->map["folder"].asString());
803
file = QDeepCopy<QString>(cmd->map["file"].asString());
805
KExifDialog exif(d->parent);
806
exif.loadFile(folder + "/" + file);
809
d->cmdQueue.dequeue();
810
d->timer->start(50, false);
814
if (cmd->action == CameraCommand::gp_download)
816
folder = QDeepCopy<QString>(cmd->map["folder"].asString());
817
file = QDeepCopy<QString>(cmd->map["file"].asString());
818
dest = QDeepCopy<QString>(cmd->map["dest"].asString());
820
if (!d->overwriteAll)
823
while (::stat(QFile::encodeName(dest), &info) == 0)
831
KIO::RenameDlg dlg(d->parent, i18n("Rename File"), file, dest,
832
KIO::RenameDlg_Mode(KIO::M_MULTI |
836
int result = dlg.exec();
837
dest = dlg.newDestURL().path();
851
case KIO::R_AUTO_SKIP:
857
case KIO::R_OVERWRITE:
862
case KIO::R_OVERWRITE_ALL:
864
d->overwriteAll = true;
872
if (cancel || skip || overwrite)
877
cmd->map["dest"] = QVariant(QDeepCopy<QString>(dest));
884
d->timer->start(50, false);
889
d->cmdQueue.dequeue();
890
emit signalInfoMsg(i18n("Skipped file %1")
892
emit signalSkipped(folder, file);
893
d->timer->start(50, false);
898
d->timer->start(50, false);
901
#include "cameracontroller.moc"