summaryrefslogtreecommitdiffstats
path: root/src/utilities/cameragui
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/cameragui')
-rw-r--r--src/utilities/cameragui/Makefile.am30
-rw-r--r--src/utilities/cameragui/albumselectdialog.cpp417
-rw-r--r--src/utilities/cameragui/albumselectdialog.h80
-rw-r--r--src/utilities/cameragui/animwidget.cpp131
-rw-r--r--src/utilities/cameragui/animwidget.h66
-rw-r--r--src/utilities/cameragui/cameracontroller.cpp1227
-rw-r--r--src/utilities/cameragui/cameracontroller.h111
-rw-r--r--src/utilities/cameragui/camerafolderdialog.cpp138
-rw-r--r--src/utilities/cameragui/camerafolderdialog.h68
-rw-r--r--src/utilities/cameragui/camerafolderitem.cpp108
-rw-r--r--src/utilities/cameragui/camerafolderitem.h69
-rw-r--r--src/utilities/cameragui/camerafolderview.cpp169
-rw-r--r--src/utilities/cameragui/camerafolderview.h83
-rw-r--r--src/utilities/cameragui/cameraiconitem.cpp302
-rw-r--r--src/utilities/cameragui/cameraiconitem.h81
-rw-r--r--src/utilities/cameragui/cameraiconview.cpp900
-rw-r--r--src/utilities/cameragui/cameraiconview.h141
-rw-r--r--src/utilities/cameragui/camerainfodialog.cpp85
-rw-r--r--src/utilities/cameragui/camerainfodialog.h50
-rw-r--r--src/utilities/cameragui/cameraui.cpp1734
-rw-r--r--src/utilities/cameragui/cameraui.h155
-rw-r--r--src/utilities/cameragui/dkcamera.cpp113
-rw-r--r--src/utilities/cameragui/dkcamera.h97
-rw-r--r--src/utilities/cameragui/downloadsettingscontainer.h79
-rw-r--r--src/utilities/cameragui/freespacewidget.cpp252
-rw-r--r--src/utilities/cameragui/freespacewidget.h75
-rw-r--r--src/utilities/cameragui/gpcamera.cpp1223
-rw-r--r--src/utilities/cameragui/gpcamera.h107
-rw-r--r--src/utilities/cameragui/gpiteminfo.cpp68
-rw-r--r--src/utilities/cameragui/gpiteminfo.h80
-rw-r--r--src/utilities/cameragui/mtqueue.h116
-rw-r--r--src/utilities/cameragui/renamecustomizer.cpp532
-rw-r--r--src/utilities/cameragui/renamecustomizer.h91
-rw-r--r--src/utilities/cameragui/umscamera.cpp519
-rw-r--r--src/utilities/cameragui/umscamera.h78
35 files changed, 9575 insertions, 0 deletions
diff --git a/src/utilities/cameragui/Makefile.am b/src/utilities/cameragui/Makefile.am
new file mode 100644
index 00000000..83f810f4
--- /dev/null
+++ b/src/utilities/cameragui/Makefile.am
@@ -0,0 +1,30 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libcameragui.la
+
+# NOTE from Gilles (06-12-06): gpcamera.cpp must be placed on the top of source file list
+# to unbreak compilation with './configure -enable-final' option. I suspect a problem with
+# Gphoto2 C Ansi header.
+libcameragui_la_SOURCES = gpcamera.cpp cameraui.cpp cameraiconview.cpp \
+ cameraiconitem.cpp cameracontroller.cpp \
+ camerafolderview.cpp camerafolderitem.cpp \
+ animwidget.cpp renamecustomizer.cpp \
+ dkcamera.cpp umscamera.cpp gpiteminfo.cpp \
+ camerainfodialog.cpp albumselectdialog.cpp \
+ camerafolderdialog.cpp freespacewidget.cpp
+
+libcameragui_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+libcameragui_la_LIBADD = $(top_builddir)/src/libs/imageproperties/libimagepropertiescamgui.la \
+ $(LIB_GPHOTO) $(LIBJPEG)
+
+INCLUDES = -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/libs/jpegutils \
+ -I$(top_srcdir)/src/libs/themeengine \
+ -I$(top_srcdir)/src/libs/imageproperties \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ $(LIBKEXIV2_CFLAGS) \
+ $(GPHOTO_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
diff --git a/src/utilities/cameragui/albumselectdialog.cpp b/src/utilities/cameragui/albumselectdialog.cpp
new file mode 100644
index 00000000..486c4711
--- /dev/null
+++ b/src/utilities/cameragui/albumselectdialog.cpp
@@ -0,0 +1,417 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-06-16
+ * Description : a dialog to select a target album to download
+ * pictures from camera
+ *
+ * Copyright (C) 2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqframe.h>
+#include <tqlayout.h>
+#include <tqpopupmenu.h>
+#include <tqcursor.h>
+#include <tqdatetime.h>
+#include <tqmap.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdeaction.h>
+#include <kinputdialog.h>
+#include <tdemessagebox.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "folderview.h"
+#include "folderitem.h"
+#include "album.h"
+#include "albummanager.h"
+#include "albumsettings.h"
+#include "searchtextbar.h"
+#include "albumselectdialog.h"
+#include "albumselectdialog.moc"
+
+namespace Digikam
+{
+
+class AlbumSelectDialogPrivate
+{
+
+public:
+
+ AlbumSelectDialogPrivate()
+ {
+ allowRootSelection = false;
+ folderView = 0;
+ searchBar = 0;
+ }
+
+ bool allowRootSelection;
+
+ TQString newAlbumString;
+
+ TQMap<FolderItem*, PAlbum*> albumMap;
+
+ FolderView *folderView;
+
+ SearchTextBar *searchBar;
+};
+
+AlbumSelectDialog::AlbumSelectDialog(TQWidget* parent, PAlbum* albumToSelect,
+ const TQString& header,
+ const TQString& newAlbumString,
+ bool allowRootSelection )
+ : KDialogBase(Plain, i18n("Select Album"),
+ Help|User1|Ok|Cancel, Ok,
+ parent, 0, true, true,
+ i18n("&New Album"))
+{
+ d = new AlbumSelectDialogPrivate;
+ setHelp("targetalbumdialog.anchor", "digikam");
+ enableButtonOK(false);
+
+ d->allowRootSelection = allowRootSelection;
+ d->newAlbumString = newAlbumString;
+
+ // -------------------------------------------------------------
+
+ TQGridLayout* grid = new TQGridLayout(plainPage(), 2, 1, 0, spacingHint());
+
+ TQLabel *logo = new TQLabel(plainPage());
+ TDEIconLoader* iconLoader = TDEApplication::kApplication()->iconLoader();
+ logo->setPixmap(iconLoader->loadIcon("digikam", TDEIcon::NoGroup, 128, TDEIcon::DefaultState, 0, true));
+
+ TQLabel *message = new TQLabel(plainPage());
+ if (!header.isEmpty())
+ message->setText(header);
+
+ d->folderView = new FolderView(plainPage());
+ d->folderView->addColumn(i18n("My Albums"));
+ d->folderView->setColumnWidthMode( 0, TQListView::Maximum );
+ d->folderView->setResizeMode( TQListView::AllColumns );
+ d->folderView->setRootIsDecorated(true);
+
+ d->searchBar = new SearchTextBar(plainPage(), "AlbumSelectDialogSearchBar");
+
+ // -------------------------------------------------------------
+
+ TQPixmap icon = iconLoader->loadIcon("folder", TDEIcon::NoGroup,
+ AlbumSettings::instance()->getDefaultTreeIconSize(), TDEIcon::DefaultState, 0, true);
+
+ AlbumList aList = AlbumManager::instance()->allPAlbums();
+
+ for (AlbumList::const_iterator it = aList.begin(); it != aList.end(); ++it)
+ {
+ PAlbum* album = (PAlbum*)(*it);
+
+ FolderItem* viewItem = 0;
+
+ if (album->isRoot())
+ {
+ viewItem = new FolderItem(d->folderView, album->title());
+ viewItem->setOpen(true);
+ }
+ else
+ {
+ FolderItem* parentItem = (FolderItem*)(album->parent()->extraData(d->folderView));
+
+ if (!parentItem)
+ {
+ DWarning() << "Failed to find parent for Album "
+ << album->title() << endl;
+ continue;
+ }
+
+ viewItem = new FolderItem(parentItem, album->title());
+ }
+
+ if (viewItem)
+ {
+ viewItem->setPixmap(0, icon);
+ album->setExtraData(d->folderView, viewItem);
+ d->albumMap.insert(viewItem, album);
+
+ if (album == albumToSelect)
+ {
+ viewItem->setOpen(true);
+ d->folderView->setSelected(viewItem, true);
+ d->folderView->ensureItemVisible(viewItem);
+ }
+ }
+ }
+
+ // -------------------------------------------------------------
+
+ grid->addMultiCellWidget(logo, 0, 0, 0, 0);
+ grid->addMultiCellWidget(message, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->folderView, 0, 2, 1, 1);
+ grid->addMultiCellWidget(d->searchBar, 3, 3, 1, 1);
+ grid->setRowStretch(2, 10);
+
+ // -------------------------------------------------------------
+
+ connect(AlbumManager::instance(), TQ_SIGNAL(signalAlbumAdded(Album*)),
+ this, TQ_SLOT(slotAlbumAdded(Album*)));
+
+ connect(AlbumManager::instance(), TQ_SIGNAL(signalAlbumDeleted(Album*)),
+ this, TQ_SLOT(slotAlbumDeleted(Album*)));
+
+ connect(AlbumManager::instance(), TQ_SIGNAL(signalAlbumsCleared()),
+ this, TQ_SLOT(slotAlbumsCleared()));
+
+ connect(d->folderView, TQ_SIGNAL(selectionChanged()),
+ this, TQ_SLOT(slotSelectionChanged()));
+
+ connect(d->folderView, TQ_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
+ this, TQ_SLOT(slotContextMenu(TQListViewItem*, const TQPoint&, int)));
+
+ connect(d->searchBar, TQ_SIGNAL(signalTextChanged(const TQString&)),
+ this, TQ_SLOT(slotSearchTextChanged(const TQString&)));
+
+ // -------------------------------------------------------------
+
+ resize(650, 650);
+ slotSelectionChanged();
+}
+
+AlbumSelectDialog::~AlbumSelectDialog()
+{
+ delete d;
+}
+
+void AlbumSelectDialog::slotAlbumAdded(Album* album)
+{
+ if (!album || album->type() != Album::PHYSICAL)
+ return;
+
+ FolderItem* parentItem = (FolderItem*)(album->parent()->extraData(d->folderView));
+
+ if (!parentItem)
+ {
+ DWarning() << "Failed to find parent for Album "
+ << album->title() << endl;
+ return;
+ }
+
+ TDEIconLoader *iconLoader = TDEApplication::kApplication()->iconLoader();
+ TQPixmap icon = iconLoader->loadIcon("folder", TDEIcon::NoGroup,
+ AlbumSettings::instance()->getDefaultTreeIconSize(),
+ TDEIcon::DefaultState, 0, true);
+
+ FolderItem* viewItem = new FolderItem(parentItem, album->title());
+ viewItem->setPixmap(0, icon);
+ album->setExtraData(d->folderView, viewItem);
+ d->albumMap.insert(viewItem, (PAlbum*)album);
+}
+
+void AlbumSelectDialog::slotAlbumDeleted(Album* album)
+{
+ if (!album || album->type() != Album::PHYSICAL)
+ return;
+
+ FolderItem* viewItem = (FolderItem*)(album->extraData(d->folderView));
+
+ if (viewItem)
+ {
+ delete viewItem;
+ album->removeExtraData(d->folderView);
+ d->albumMap.remove(viewItem);
+ }
+}
+
+void AlbumSelectDialog::slotAlbumsCleared()
+{
+ d->folderView->clear();
+}
+
+void AlbumSelectDialog::slotSelectionChanged()
+{
+ TQListViewItem* selItem = 0;
+ TQListViewItemIterator it(d->folderView);
+
+ while (it.current())
+ {
+ if (it.current()->isSelected())
+ {
+ selItem = it.current();
+ break;
+ }
+ ++it;
+ }
+
+ if (!selItem || (selItem == d->folderView->firstChild()) &&
+ !d->allowRootSelection)
+ {
+ enableButtonOK(false);
+ return;
+ }
+
+ enableButtonOK(true);
+}
+
+void AlbumSelectDialog::slotContextMenu(TQListViewItem *, const TQPoint &, int)
+{
+ TQPopupMenu popmenu(d->folderView);
+ TDEAction *action = new TDEAction(i18n( "Create New Album" ),
+ "albumfolder-new", 0, this,
+ TQ_SLOT( slotUser1() ),
+ &popmenu);
+ action->plug(&popmenu);
+ popmenu.exec(TQCursor::pos());
+}
+
+void AlbumSelectDialog::slotUser1()
+{
+ TQListViewItem* item = d->folderView->currentItem();
+ if (!item)
+ item = d->folderView->firstChild();
+
+ if (!item)
+ return;
+
+ PAlbum* album = d->albumMap[(FolderItem*)item];
+ if (!album)
+ return;
+
+ bool ok;
+ TQString newAlbumName = KInputDialog::getText(i18n("New Album Name"),
+ i18n("Creating new album in '%1'\n"
+ "Enter album name:")
+ .arg(album->prettyURL()),
+ d->newAlbumString, &ok, this);
+ if (!ok)
+ return;
+
+ TQString errMsg;
+ PAlbum* newAlbum = AlbumManager::instance()->createPAlbum(album, newAlbumName,
+ TQString(), TQDate::currentDate(),
+ TQString(), errMsg);
+ if (!newAlbum)
+ {
+ KMessageBox::error(this, errMsg);
+ return;
+ }
+
+ FolderItem* newItem = (FolderItem*)newAlbum->extraData(d->folderView);
+ if (newItem)
+ {
+ d->folderView->ensureItemVisible(newItem);
+ d->folderView->setSelected(newItem, true);
+ }
+}
+
+PAlbum* AlbumSelectDialog::selectAlbum(TQWidget* parent,
+ PAlbum* albumToSelect,
+ const TQString& header,
+ const TQString& newAlbumString,
+ bool allowRootSelection )
+{
+ AlbumSelectDialog dlg(parent, albumToSelect,
+ header, newAlbumString,
+ allowRootSelection);
+
+ if (dlg.exec() != KDialogBase::Accepted)
+ return 0;
+
+ FolderItem* item = (FolderItem*) dlg.d->folderView->currentItem();
+ if (!item || (item == dlg.d->folderView->firstChild()) &&
+ !allowRootSelection)
+ {
+ return 0;
+ }
+
+ return dlg.d->albumMap[item];
+}
+
+void AlbumSelectDialog::slotSearchTextChanged(const TQString& filter)
+{
+ TQString search = filter.lower();
+
+ bool atleastOneMatch = false;
+
+ AlbumList pList = AlbumManager::instance()->allPAlbums();
+ for (AlbumList::iterator it = pList.begin(); it != pList.end(); ++it)
+ {
+ PAlbum* palbum = (PAlbum*)(*it);
+
+ // don't touch the root Album
+ if (palbum->isRoot())
+ continue;
+
+ bool match = palbum->title().lower().contains(search);
+ if (!match)
+ {
+ // check if any of the parents match the search
+ Album* parent = palbum->parent();
+ while (parent && !parent->isRoot())
+ {
+ if (parent->title().lower().contains(search))
+ {
+ match = true;
+ break;
+ }
+
+ parent = parent->parent();
+ }
+ }
+
+ if (!match)
+ {
+ // check if any of the children match the search
+ AlbumIterator it(palbum);
+ while (it.current())
+ {
+ if ((*it)->title().lower().contains(search))
+ {
+ match = true;
+ break;
+ }
+ ++it;
+ }
+ }
+
+ FolderItem* viewItem = (FolderItem*) palbum->extraData(d->folderView);
+
+ if (match)
+ {
+ atleastOneMatch = true;
+
+ if (viewItem)
+ viewItem->setVisible(true);
+ }
+ else
+ {
+ if (viewItem)
+ {
+ viewItem->setVisible(false);
+ }
+ }
+ }
+
+ d->searchBar->slotSearchResult(atleastOneMatch);
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/albumselectdialog.h b/src/utilities/cameragui/albumselectdialog.h
new file mode 100644
index 00000000..aea53319
--- /dev/null
+++ b/src/utilities/cameragui/albumselectdialog.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-06-16
+ * Description : a dialog to select a target album to download
+ * pictures from camera
+ *
+ * Copyright (C) 2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ALBUMSELECTDIALOG_H
+#define ALBUMSELECTDIALOG_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+namespace Digikam
+{
+
+class PAlbum;
+class AlbumSelectDialogPrivate;
+
+class AlbumSelectDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ AlbumSelectDialog(TQWidget* parent, PAlbum* albumToSelect,
+ const TQString& header=TQString(),
+ const TQString& newAlbumString=TQString(),
+ bool allowRootSelection=false);
+ ~AlbumSelectDialog();
+
+
+ static PAlbum* selectAlbum(TQWidget* parent,
+ PAlbum* albumToSelect,
+ const TQString& header=TQString(),
+ const TQString& newAlbumString=TQString(),
+ bool allowRootSelection=false);
+
+private slots:
+
+ void slotAlbumAdded(Album*);
+ void slotAlbumDeleted(Album*);
+ void slotAlbumsCleared();
+ void slotSelectionChanged();
+ void slotContextMenu(TQListViewItem *item, const TQPoint&, int);
+ void slotUser1();
+ void slotSearchTextChanged(const TQString&);
+
+private:
+
+ AlbumSelectDialogPrivate *d;
+};
+
+} // namespace Digikam
+
+#endif /* ALBUMSELECTDIALOG_H */
diff --git a/src/utilities/cameragui/animwidget.cpp b/src/utilities/cameragui/animwidget.cpp
new file mode 100644
index 00000000..1d869cd9
--- /dev/null
+++ b/src/utilities/cameragui/animwidget.cpp
@@ -0,0 +1,131 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-21
+ * Description : an animated busy widget
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqpalette.h>
+#include <tqcolor.h>
+#include <tqtimer.h>
+
+// Local includes.
+
+#include "animwidget.h"
+#include "animwidget.moc"
+
+namespace Digikam
+{
+
+class AnimWidgetPriv
+{
+public:
+
+ AnimWidgetPriv()
+ {
+ timer = 0;
+ pos = 0;
+ }
+
+ int pos;
+ int size;
+
+ TQTimer *timer;
+
+ TQPixmap pix;
+};
+
+AnimWidget::AnimWidget(TQWidget* parent, int size)
+ : TQWidget(parent, 0, WResizeNoErase|WRepaintNoErase)
+{
+ d = new AnimWidgetPriv;
+ setBackgroundMode(TQt::NoBackground);
+
+ d->size = size;
+ d->pix = TQPixmap(d->size, d->size);
+ setFixedSize(d->size, d->size);
+
+ d->timer = new TQTimer(this);
+
+ connect(d->timer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotTimeout()));
+}
+
+AnimWidget::~AnimWidget()
+{
+ delete d;
+}
+
+void AnimWidget::start()
+{
+ d->pos = 0;
+ d->timer->start(100);
+}
+
+void AnimWidget::stop()
+{
+ d->pos = 0;
+ d->timer->stop();
+ repaint();
+}
+
+void AnimWidget::paintEvent(TQPaintEvent*)
+{
+ d->pix.fill(colorGroup().background());
+ TQPainter p(&d->pix);
+
+ p.translate(d->size/2, d->size/2);
+
+ if (d->timer->isActive())
+ {
+ p.setPen(TQPen(colorGroup().text()));
+ p.rotate( d->pos );
+ }
+ else
+ {
+ p.setPen(TQPen(colorGroup().dark()));
+ }
+
+ for ( int i=0 ; i<12 ; i++ )
+ {
+ p.drawLine(d->size/2-4, 0, d->size/2-2, 0);
+ p.rotate(30);
+ }
+
+ p.end();
+ bitBlt(this, 0, 0, &d->pix);
+}
+
+void AnimWidget::slotTimeout()
+{
+ d->pos = (d->pos + 10) % 360;
+ repaint();
+}
+
+bool AnimWidget::running() const
+{
+ return d->timer->isActive();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/animwidget.h b/src/utilities/cameragui/animwidget.h
new file mode 100644
index 00000000..6a93f410
--- /dev/null
+++ b/src/utilities/cameragui/animwidget.h
@@ -0,0 +1,66 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-21
+ * Description : an animated busy widget
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef ANIMWIDGET_H
+#define ANIMWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+
+namespace Digikam
+{
+
+class AnimWidgetPriv;
+
+class AnimWidget : public TQWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ AnimWidget(TQWidget* parent, int size=28);
+ ~AnimWidget();
+
+ void start();
+ void stop();
+ bool running() const;
+
+protected:
+
+ void paintEvent(TQPaintEvent*);
+
+private slots:
+
+ void slotTimeout();
+
+private:
+
+ AnimWidgetPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* ANIMWIDGET_H */
diff --git a/src/utilities/cameragui/cameracontroller.cpp b/src/utilities/cameragui/cameracontroller.cpp
new file mode 100644
index 00000000..34afa8ab
--- /dev/null
+++ b/src/utilities/cameragui/cameracontroller.cpp
@@ -0,0 +1,1227 @@
+/* ============================================================
+ *
+ * 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 <[email protected]>
+ * 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 <tdelocale.h>
+#include <kurl.h>
+#include <tdemessagebox.h>
+#include <tdeio/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;
+ TQStringVariantMap 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;
+ TQStringVariantMap 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, TQImage::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, TQ_SIGNAL(timeout()),
+ this, TQ_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));
+ cmd->map.insert("fixDateTime", TQVariant(downloadSettings.fixDateTime));
+ cmd->map.insert("newDateTime", TQVariant(downloadSettings.newDateTime));
+ cmd->map.insert("setPhotographerId", TQVariant(downloadSettings.setPhotographerId));
+ cmd->map.insert("author", TQVariant(downloadSettings.author));
+ cmd->map.insert("authorTitle", TQVariant(downloadSettings.authorTitle));
+ cmd->map.insert("setCredits", TQVariant(downloadSettings.setCredits));
+ 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));
+ 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));
+ 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
diff --git a/src/utilities/cameragui/cameracontroller.h b/src/utilities/cameragui/cameracontroller.h
new file mode 100644
index 00000000..45e7fede
--- /dev/null
+++ b/src/utilities/cameragui/cameracontroller.h
@@ -0,0 +1,111 @@
+/* ============================================================
+ *
+ * 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 <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef CAMERACONTROLLER_H
+#define CAMERACONTROLLER_H
+
+// TQt includes.
+
+#include <tqobject.h>
+#include <tqstring.h>
+#include <tqfileinfo.h>
+
+// Local includes.
+
+#include "downloadsettingscontainer.h"
+#include "gpiteminfo.h"
+
+namespace Digikam
+{
+
+class CameraControllerPriv;
+
+class CameraController : public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ CameraController(TQWidget* parent, const TQString& title, const TQString& model,
+ const TQString& port, const TQString& path);
+ ~CameraController();
+
+ void listFolders();
+ void listFiles(const TQString& folder);
+ void getThumbnail(const TQString& folder, const TQString& file);
+ void getExif(const TQString& folder, const TQString& file);
+ void getCameraInformations();
+ TQString getCameraPath();
+ TQString getCameraTitle();
+
+ void downloadPrep();
+ void download(DownloadSettingsContainer downloadSettings);
+ void upload(const TQFileInfo& srcFileInfo, const TQString& destFile, const TQString& destFolder);
+ void deleteFile(const TQString& folder, const TQString& file);
+ void lockFile(const TQString& folder, const TQString& file, bool lock);
+ void openFile(const TQString& folder, const TQString& file);
+
+signals:
+
+ void signalBusy(bool val);
+ void signalInfoMsg(const TQString& msg);
+ void signalErrorMsg(const TQString& msg);
+ void signalCameraInformations(const TQString& summary, const TQString& manual, const TQString& about);
+
+ void signalConnected(bool val);
+ void signalFolderList(const TQStringList& folderList);
+ void signalFileList(const GPItemInfoList& infoList);
+ void signalUploaded(const GPItemInfo& itemInfo);
+ void signalDownloaded(const TQString& folder, const TQString& file, int status);
+ void signalSkipped(const TQString& folder, const TQString& file);
+ void signalDeleted(const TQString& folder, const TQString& file, bool status);
+ void signalLocked(const TQString& folder, const TQString& file, bool status);
+ void signalThumbnail(const TQString& folder, const TQString& file, const TQImage& thumb);
+ void signalExifFromFile(const TQString& folder, const TQString& file);
+ void signalExifData(const TQByteArray& exifData);
+
+protected:
+
+ void customEvent(TQCustomEvent* e);
+
+public slots:
+
+ void slotCancel();
+ void slotConnect();
+
+private slots:
+
+ void slotProcessNext();
+
+private:
+
+ CameraControllerPriv *d;
+
+ friend class CameraThread;
+};
+
+} // namespace Digikam
+
+#endif /* CAMERACONTROLLER_H */
diff --git a/src/utilities/cameragui/camerafolderdialog.cpp b/src/utilities/cameragui/camerafolderdialog.cpp
new file mode 100644
index 00000000..93feb0ab
--- /dev/null
+++ b/src/utilities/cameragui/camerafolderdialog.cpp
@@ -0,0 +1,138 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-07-24
+ * Description : a dialog to select a camera folders.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "cameraiconview.h"
+#include "camerafolderitem.h"
+#include "camerafolderview.h"
+#include "camerafolderdialog.h"
+#include "camerafolderdialog.moc"
+
+namespace Digikam
+{
+
+CameraFolderDialog::CameraFolderDialog(TQWidget *parent, CameraIconView *cameraView,
+ const TQStringList& cameraFolderList,
+ const TQString& cameraName, const TQString& rootPath)
+ : KDialogBase(parent, 0, true,
+ i18n("%1 - Select Camera Folder").arg(cameraName),
+ Help|Ok|Cancel, Ok, true)
+{
+ setHelp("camerainterface.anchor", "digikam");
+ enableButtonOK(false);
+
+ m_rootPath = rootPath;
+
+ TQFrame *page = makeMainWidget();
+ TQGridLayout* grid = new TQGridLayout(page, 2, 1, 0, spacingHint());
+
+ m_folderView = new CameraFolderView(page);
+ TQLabel *logo = new TQLabel(page);
+ TQLabel *message = new TQLabel(page);
+
+ TDEIconLoader* iconLoader = TDEApplication::kApplication()->iconLoader();
+ logo->setPixmap(iconLoader->loadIcon("digikam", TDEIcon::NoGroup, 128, TDEIcon::DefaultState, 0, true));
+ message->setText(i18n("<p>Please select the camera folder "
+ "where you want to upload the images.</p>"));
+
+ grid->addMultiCellWidget(logo, 0, 0, 0, 0);
+ grid->addMultiCellWidget(message, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_folderView, 0, 2, 1, 1);
+ grid->setRowStretch(2, 10);
+
+ m_folderView->addVirtualFolder(cameraName);
+ m_folderView->addRootFolder("/", cameraView->countItemsByFolder(rootPath));
+
+ for (TQStringList::const_iterator it = cameraFolderList.begin();
+ it != cameraFolderList.end(); ++it)
+ {
+ TQString folder(*it);
+ if (folder.startsWith(rootPath) && rootPath != TQString("/"))
+ folder.remove(0, rootPath.length());
+
+ if (folder != TQString("/") && !folder.isEmpty())
+ {
+ TQString root = folder.section( '/', 0, -2 );
+ if (root.isEmpty()) root = TQString("/");
+
+ TQString sub = folder.section( '/', -1 );
+ m_folderView->addFolder(root, sub, cameraView->countItemsByFolder(*it));
+ DDebug() << "Camera folder: '" << folder << "' (root='" << root << "', sub='" <<sub <<"')" << endl;
+ }
+ }
+
+ connect(m_folderView, TQ_SIGNAL(signalFolderChanged(CameraFolderItem*)),
+ this, TQ_SLOT(slotFolderPathSelectionChanged(CameraFolderItem*)));
+
+ resize(500, 500);
+}
+
+CameraFolderDialog::~CameraFolderDialog()
+{
+}
+
+TQString CameraFolderDialog::selectedFolderPath()
+{
+ TQListViewItem *item = m_folderView->currentItem();
+ if (!item) return TQString();
+
+ CameraFolderItem *folderItem = static_cast<CameraFolderItem *>(item);
+ if (folderItem->isVirtualFolder())
+ return TQString(m_rootPath);
+
+ // Case of Gphoto2 cameras. No need to duplicate root '/'.
+ if (m_rootPath == TQString("/"))
+ return(folderItem->folderPath());
+
+ return(m_rootPath + folderItem->folderPath());
+}
+
+void CameraFolderDialog::slotFolderPathSelectionChanged(CameraFolderItem* item)
+{
+ if (item)
+ {
+ enableButtonOK(true);
+ DDebug() << "Camera folder path: " << selectedFolderPath() << endl;
+ }
+ else
+ {
+ enableButtonOK(false);
+ }
+}
+
+} // namespace Digikam
+
diff --git a/src/utilities/cameragui/camerafolderdialog.h b/src/utilities/cameragui/camerafolderdialog.h
new file mode 100644
index 00000000..efc7586a
--- /dev/null
+++ b/src/utilities/cameragui/camerafolderdialog.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-07-24
+ * Description : a dialog to select a camera folders.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CAMERAFOLDERDIALOG_H
+#define CAMERAFOLDERDIALOG_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+namespace Digikam
+{
+
+class CameraIconView;
+class CameraFolderView;
+class CameraFolderItem;
+
+class CameraFolderDialog : public KDialogBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ CameraFolderDialog(TQWidget *parent, CameraIconView *cameraView, const TQStringList& cameraFolderList,
+ const TQString& cameraName, const TQString& rootPath);
+ ~CameraFolderDialog();
+
+ TQString selectedFolderPath();
+
+private slots:
+
+ void slotFolderPathSelectionChanged(CameraFolderItem* item);
+
+private:
+
+ TQString m_rootPath;
+
+ CameraFolderView *m_folderView;
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAFOLDERDIALOG_H */
diff --git a/src/utilities/cameragui/camerafolderitem.cpp b/src/utilities/cameragui/camerafolderitem.cpp
new file mode 100644
index 00000000..f53508a6
--- /dev/null
+++ b/src/utilities/cameragui/camerafolderitem.cpp
@@ -0,0 +1,108 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-23
+ * Description : A widget to display a camera folder.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "camerafolderitem.h"
+
+namespace Digikam
+{
+
+class CameraFolderItemPriv
+{
+public:
+
+ CameraFolderItemPriv()
+ {
+ count = 0;
+ }
+
+ bool virtualFolder;
+
+ int count;
+
+ TQString folderName;
+ TQString folderPath;
+ TQString name;
+};
+
+CameraFolderItem::CameraFolderItem(TQListView* parent, const TQString& name, const TQPixmap& pixmap)
+ : TQListViewItem(parent, name)
+{
+ d = new CameraFolderItemPriv;
+ d->virtualFolder = true;
+ d->name = name;
+ setPixmap(0, pixmap);
+}
+
+CameraFolderItem::CameraFolderItem(TQListViewItem* parent, const TQString& folderName,
+ const TQString& folderPath, const TQPixmap& pixmap)
+ : TQListViewItem(parent, folderName)
+{
+ d = new CameraFolderItemPriv;
+ d->folderName = folderName;
+ d->folderPath = folderPath;
+ d->virtualFolder = false;
+ d->name = folderName;
+ setPixmap(0, pixmap);
+}
+
+CameraFolderItem::~CameraFolderItem()
+{
+ delete d;
+}
+
+bool CameraFolderItem::isVirtualFolder()
+{
+ return d->virtualFolder;
+}
+
+TQString CameraFolderItem::folderName()
+{
+ return d->folderName;
+}
+
+TQString CameraFolderItem::folderPath()
+{
+ return d->folderPath;
+}
+
+void CameraFolderItem::changeCount(int val)
+{
+ d->count += val;
+ setText(0, TQString("%1 (%2)").arg(d->name).arg(TQString::number(d->count)));
+}
+
+void CameraFolderItem::setCount(int val)
+{
+ d->count = val;
+ setText(0, TQString("%1 (%2)").arg(d->name).arg(TQString::number(d->count)));
+}
+
+int CameraFolderItem::count()
+{
+ return d->count;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/camerafolderitem.h b/src/utilities/cameragui/camerafolderitem.h
new file mode 100644
index 00000000..dde2c5c6
--- /dev/null
+++ b/src/utilities/cameragui/camerafolderitem.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-23
+ * Description : A widget to display a camera folder.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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 CAMERAFOLDERITEM_H
+#define CAMERAFOLDERITEM_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqlistview.h>
+
+// KDE includes.
+
+#include <kiconloader.h>
+
+namespace Digikam
+{
+
+class CameraFolderItemPriv;
+
+class CameraFolderItem : public TQListViewItem
+{
+
+public:
+
+ CameraFolderItem(TQListView* parent, const TQString& name,
+ const TQPixmap& pixmap=SmallIcon("folder"));
+
+ CameraFolderItem(TQListViewItem* parent, const TQString& folderName, const TQString& folderPath,
+ const TQPixmap& pixmap=SmallIcon("folder"));
+
+ ~CameraFolderItem();
+
+ TQString folderName();
+ TQString folderPath();
+ bool isVirtualFolder();
+ void changeCount(int val);
+ void setCount(int val);
+ int count();
+
+private:
+
+ CameraFolderItemPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAFOLDERITEM_H */
diff --git a/src/utilities/cameragui/camerafolderview.cpp b/src/utilities/cameragui/camerafolderview.cpp
new file mode 100644
index 00000000..877c4b51
--- /dev/null
+++ b/src/utilities/cameragui/camerafolderview.cpp
@@ -0,0 +1,169 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-23
+ * Description : A widget to display a list of camera folders.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "camerafolderitem.h"
+#include "camerafolderview.h"
+#include "camerafolderview.moc"
+
+namespace Digikam
+{
+
+class CameraFolderViewPriv
+{
+public:
+
+ CameraFolderViewPriv()
+ {
+ virtualFolder = 0;
+ rootFolder = 0;
+ cameraName = TQString("Camera");
+ }
+
+ TQString cameraName;
+
+ CameraFolderItem *virtualFolder;
+ CameraFolderItem *rootFolder;
+};
+
+CameraFolderView::CameraFolderView(TQWidget* parent)
+ : TQListView(parent)
+{
+ d = new CameraFolderViewPriv;
+
+ addColumn(i18n("Camera Folders"));
+ setColumnWidthMode( 0, TQListView::Maximum );
+ setResizeMode( TQListView::AllColumns );
+ setSelectionMode(TQListView::Single);
+
+ connect(this, TQ_SIGNAL(currentChanged(TQListViewItem*)),
+ this, TQ_SLOT(slotCurrentChanged(TQListViewItem*)));
+
+ connect(this, TQ_SIGNAL(clicked(TQListViewItem*)),
+ this, TQ_SLOT(slotCurrentChanged(TQListViewItem*)));
+}
+
+CameraFolderView::~CameraFolderView()
+{
+ delete d;
+}
+
+void CameraFolderView::addVirtualFolder(const TQString& name, const TQPixmap& pixmap)
+{
+ d->cameraName = name;
+ d->virtualFolder = new CameraFolderItem(this, d->cameraName, pixmap);
+ d->virtualFolder->setOpen(true);
+ d->virtualFolder->setSelected(false);
+ d->virtualFolder->setSelectable(false);
+}
+
+void CameraFolderView::addRootFolder(const TQString& folder, int nbItems, const TQPixmap& pixmap)
+{
+ d->rootFolder = new CameraFolderItem(d->virtualFolder, folder, folder, pixmap);
+ d->rootFolder->setOpen(true);
+ d->rootFolder->setCount(nbItems);
+}
+
+CameraFolderItem* CameraFolderView::addFolder(const TQString& folder, const TQString& subFolder,
+ int nbItems, const TQPixmap& pixmap)
+{
+ CameraFolderItem *parentItem = findFolder(folder);
+
+ DDebug() << "CameraFolderView: Adding Subfolder " << subFolder
+ << " of folder " << folder << endl;
+
+ if (parentItem)
+ {
+ TQString path(folder);
+
+ if (!folder.endsWith("/"))
+ path += '/';
+
+ path += subFolder;
+ CameraFolderItem* item = new CameraFolderItem(parentItem, subFolder, path, pixmap);
+
+ DDebug() << "CameraFolderView: Added ViewItem with path "
+ << item->folderPath() << endl;
+
+ item->setCount(nbItems);
+ item->setOpen(true);
+ return item;
+ }
+ else
+ {
+ DWarning() << "CameraFolderView: Couldn't find parent for subFolder "
+ << subFolder << " of folder " << folder << endl;
+ return 0;
+ }
+}
+
+CameraFolderItem* CameraFolderView::findFolder(const TQString& folderPath)
+{
+
+ TQListViewItemIterator it(this);
+ for ( ; it.current(); ++it)
+ {
+ CameraFolderItem* item = static_cast<CameraFolderItem*>(it.current());
+
+ if (item->folderPath() == folderPath)
+ return item;
+ }
+
+ return 0;
+}
+
+void CameraFolderView::slotCurrentChanged(TQListViewItem* item)
+{
+ if (!item)
+ emit signalFolderChanged(0);
+ else
+ emit signalFolderChanged(static_cast<CameraFolderItem *>(item));
+}
+
+CameraFolderItem* CameraFolderView::virtualFolder()
+{
+ return d->virtualFolder;
+}
+
+CameraFolderItem* CameraFolderView::rootFolder()
+{
+ return d->rootFolder;
+}
+
+void CameraFolderView::clear()
+{
+ TQListView::clear();
+ d->virtualFolder = 0;
+ d->rootFolder = 0;
+ emit signalCleared();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/camerafolderview.h b/src/utilities/cameragui/camerafolderview.h
new file mode 100644
index 00000000..1b02fc9c
--- /dev/null
+++ b/src/utilities/cameragui/camerafolderview.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-23
+ * Description : A widget to display a list of camera folders.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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 CAMERAFOLDERVIEW_H
+#define CAMERAFOLDERVIEW_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqlistview.h>
+
+// KDE includes.
+
+#include <kiconloader.h>
+
+namespace Digikam
+{
+
+class CameraFolderItem;
+class CameraFolderViewPriv;
+
+class CameraFolderView : public TQListView
+{
+ TQ_OBJECT
+
+
+public:
+
+ CameraFolderView(TQWidget* parent);
+ ~CameraFolderView();
+
+ void addVirtualFolder(const TQString& name, const TQPixmap& pixmap=SmallIcon("camera-photo"));
+ void addRootFolder(const TQString& folder, int nbItems, const TQPixmap& pixmap=SmallIcon("folder"));
+
+ CameraFolderItem* addFolder(const TQString& folder, const TQString& subFolder, int nbItems,
+ const TQPixmap& pixmap=SmallIcon("folder"));
+
+ CameraFolderItem* findFolder(const TQString& folderPath);
+
+ CameraFolderItem* virtualFolder();
+ CameraFolderItem* rootFolder();
+
+ virtual void clear();
+
+signals:
+
+ void signalFolderChanged(CameraFolderItem*);
+ void signalCleared();
+
+private slots:
+
+ void slotCurrentChanged(TQListViewItem*);
+
+private:
+
+ CameraFolderViewPriv* d;
+
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAFOLDERVIEW_H */
diff --git a/src/utilities/cameragui/cameraiconitem.cpp b/src/utilities/cameragui/cameraiconitem.cpp
new file mode 100644
index 00000000..c68f7855
--- /dev/null
+++ b/src/utilities/cameragui/cameraiconitem.cpp
@@ -0,0 +1,302 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-21
+ * Description : camera icon view item
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "iconview.h"
+#include "thumbnailsize.h"
+#include "albumiconitem.h"
+#include "gpiteminfo.h"
+#include "themeengine.h"
+#include "cameraiconview.h"
+#include "cameraiconitem.h"
+
+namespace Digikam
+{
+
+class CameraIconViewItemPriv
+{
+
+public:
+
+ CameraIconViewItemPriv()
+ {
+ itemInfo = 0;
+ }
+
+ TQString downloadName;
+
+ TQPixmap pixmap;
+ TQPixmap thumbnail;
+
+ TQRect pixRect;
+ TQRect textRect;
+ TQRect extraRect;
+
+ GPItemInfo *itemInfo;
+};
+
+CameraIconViewItem::CameraIconViewItem(IconGroupItem* parent, const GPItemInfo& itemInfo,
+ const TQImage& thumbnail, const TQString& downloadName)
+ : IconItem(parent)
+{
+ d = new CameraIconViewItemPriv;
+ d->itemInfo = new GPItemInfo(itemInfo);
+ d->downloadName = downloadName;
+ setThumbnail(thumbnail);
+}
+
+CameraIconViewItem::~CameraIconViewItem()
+{
+ delete d->itemInfo;
+ delete d;
+}
+
+void CameraIconViewItem::setThumbnail(const TQImage& thumbnail)
+{
+ d->thumbnail = TQPixmap(thumbnail);
+}
+
+GPItemInfo* CameraIconViewItem::itemInfo() const
+{
+ return d->itemInfo;
+}
+
+void CameraIconViewItem::paintItem()
+{
+ CameraIconView* view = (CameraIconView*)iconView();
+ TQFont fn(view->font());
+
+ TQPixmap pix;
+ TQRect r(rect());
+
+ if (isSelected())
+ pix = *(view->itemBaseSelPixmap());
+ else
+ pix = *(view->itemBaseRegPixmap());
+
+ ThemeEngine* te = ThemeEngine::instance();
+
+ TQPainter p(&pix);
+
+ TQString itemName = AlbumIconItem::squeezedText(&p, r.width()-5, d->itemInfo->name);
+ TQString downloadName = AlbumIconItem::squeezedText(&p, r.width()-5, d->downloadName);
+ calcRect(itemName, downloadName);
+
+ p.setPen(isSelected() ? te->textSelColor() : te->textRegColor());
+
+ p.drawPixmap(d->pixRect.x() + (d->pixRect.width() - d->pixmap.width()) /2,
+ d->pixRect.y() + (d->pixRect.height() - d->pixmap.height()) /2,
+ d->pixmap);
+
+ p.drawText(d->textRect, TQt::AlignHCenter|TQt::AlignTop, itemName);
+
+ if (!d->downloadName.isEmpty())
+ {
+ if (fn.pointSize() > 0)
+ fn.setPointSize(TQMAX(fn.pointSize()-2, 6));
+
+ p.setFont(fn);
+ p.setPen(isSelected() ? te->textSpecialSelColor() : te->textSpecialRegColor());
+ p.drawText(d->extraRect, TQt::AlignHCenter|TQt::AlignTop, downloadName);
+ }
+
+ if (this == iconView()->currentItem())
+ {
+ p.setPen(TQPen(isSelected() ? TQt::white : TQt::black, 1, TQt::DotLine));
+ p.drawRect(0, 0, r.width(), r.height());
+ }
+
+ // Draw download status icon.
+ TQPixmap downloaded;
+
+ switch (d->itemInfo->downloaded)
+ {
+ case GPItemInfo::NewPicture:
+ {
+ downloaded = TQPixmap(view->newPicturePixmap());
+ break;
+ }
+ case GPItemInfo::DownloadedYes:
+ {
+ downloaded = SmallIcon( "button_ok" );
+ break;
+ }
+ case GPItemInfo::DownloadStarted:
+ {
+ downloaded = SmallIcon( "system-run" );
+ break;
+ }
+ case GPItemInfo::DownloadFailed:
+ {
+ downloaded = SmallIcon( "button_cancel" );
+ break;
+ }
+ /* TODO: see B.K.O #107316 : disable temporally the unknow download status until
+ a new method to identify the already downloaded pictures from camera is
+ implemented.
+
+ case GPItemInfo::DownloadUnknow:
+ {
+ downloaded = view->unknowPicturePixmap();
+ break;
+ }
+ */
+ }
+
+ if (!downloaded.isNull())
+ p.drawPixmap(rect().width() - downloaded.width() - 5, 5, downloaded);
+
+ // If camera item is locked (read only), draw a "Lock" icon.
+ if (d->itemInfo->writePermissions == 0)
+ p.drawPixmap(5, 5, SmallIcon( "encrypted" ));
+
+ p.end();
+
+ r = TQRect(view->contentsToViewport(TQPoint(r.x(), r.y())),
+ TQSize(r.width(), r.height()));
+
+ bitBlt(view->viewport(), r.x(), r.y(), &pix);
+}
+
+void CameraIconViewItem::setDownloadName(const TQString& downloadName)
+{
+ d->downloadName = downloadName;
+ repaint();
+}
+
+TQString CameraIconViewItem::getDownloadName() const
+{
+ return d->downloadName;
+}
+
+void CameraIconViewItem::setDownloaded(int status)
+{
+ d->itemInfo->downloaded = status;
+ repaint();
+}
+
+bool CameraIconViewItem::isDownloaded() const
+{
+ return (d->itemInfo->downloaded == GPItemInfo::DownloadedYes);
+}
+
+void CameraIconViewItem::toggleLock()
+{
+ if (d->itemInfo->writePermissions == 0)
+ d->itemInfo->writePermissions = 1;
+ else
+ d->itemInfo->writePermissions = 0;
+
+ repaint();
+}
+
+void CameraIconViewItem::calcRect(const TQString& itemName, const TQString& downloadName)
+{
+ CameraIconView* view = (CameraIconView*)iconView();
+ int thumbSize = view->thumbnailSize().size();
+ d->pixmap = TQPixmap(d->thumbnail.convertToImage().smoothScale(thumbSize, thumbSize, TQImage::ScaleMin));
+ d->pixRect = TQRect(0,0,0,0);
+ d->textRect = TQRect(0,0,0,0);
+ d->extraRect = TQRect(0,0,0,0);
+ TQRect itemRect = rect();
+ itemRect.moveTopLeft(TQPoint(0, 0));
+
+ d->pixRect.setWidth(thumbSize);
+ d->pixRect.setHeight(thumbSize);
+
+ TQFontMetrics fm(iconView()->font());
+ TQRect r = TQRect(fm.boundingRect(0, 0, thumbSize, 0xFFFFFFFF,
+ TQt::AlignHCenter | TQt::AlignTop,
+ itemName));
+ d->textRect.setWidth(r.width());
+ d->textRect.setHeight(r.height());
+
+ if (!d->downloadName.isEmpty())
+ {
+ TQFont fn(iconView()->font());
+ if (fn.pointSize() > 0)
+ {
+ fn.setPointSize(TQMAX(fn.pointSize()-2, 6));
+ }
+
+ fm = TQFontMetrics(fn);
+ r = TQRect(fm.boundingRect(0, 0, thumbSize, 0xFFFFFFFF,
+ TQt::AlignHCenter | TQt::WordBreak,
+ downloadName));
+ d->extraRect.setWidth(r.width());
+ d->extraRect.setHeight(r.height());
+
+ d->textRect.setWidth(TQMAX(d->textRect.width(), d->extraRect.width()));
+ d->textRect.setHeight(d->textRect.height() + d->extraRect.height());
+ }
+
+ int w = TQMAX(d->textRect.width(), d->pixRect.width() );
+ int h = d->textRect.height() + d->pixRect.height() ;
+
+ itemRect.setWidth(w+4);
+ itemRect.setHeight(h+4);
+
+ // Center the pix and text rect
+ d->pixRect = TQRect(2, 2, d->pixRect.width(), d->pixRect.height());
+ d->textRect = TQRect((itemRect.width() - d->textRect.width())/2,
+ itemRect.height() - d->textRect.height(),
+ d->textRect.width(), d->textRect.height());
+
+ if (!d->extraRect.isEmpty())
+ {
+ d->extraRect = TQRect((itemRect.width() - d->extraRect.width())/2,
+ itemRect.height() - d->extraRect.height(),
+ d->extraRect.width(), d->extraRect.height());
+ }
+}
+
+TQRect CameraIconViewItem::clickToOpenRect()
+{
+ TQRect r(rect());
+
+ if (d->pixmap.isNull())
+ {
+ TQRect pixRect(d->pixRect);
+ pixRect.moveBy(r.x(), r.y());
+ return pixRect;
+ }
+
+ TQRect pixRect(d->pixRect.x() + (d->pixRect.width() - d->pixmap.width())/2,
+ d->pixRect.y() + (d->pixRect.height() - d->pixmap.height())/2,
+ d->pixmap.width(), d->pixmap.height());
+ pixRect.moveBy(r.x(), r.y());
+ return pixRect;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/cameraiconitem.h b/src/utilities/cameragui/cameraiconitem.h
new file mode 100644
index 00000000..961bc1a3
--- /dev/null
+++ b/src/utilities/cameragui/cameraiconitem.h
@@ -0,0 +1,81 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-21
+ * Description : camera icon view item
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef CAMERAICONITEM_H
+#define CAMERAICONITEM_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqimage.h>
+
+// Local includes.
+
+#include "iconitem.h"
+
+namespace Digikam
+{
+
+class GPItemInfo;
+class CameraIconViewItemPriv;
+
+class CameraIconViewItem : public IconItem
+{
+
+public:
+
+ CameraIconViewItem(IconGroupItem* parent, const GPItemInfo& itemInfo,
+ const TQImage& thumbnail, const TQString& downloadName=TQString());
+ ~CameraIconViewItem();
+
+ void setThumbnail(const TQImage& thumbnail);
+
+ void setDownloadName(const TQString& downloadName);
+ TQString getDownloadName() const;
+ void setDownloaded(int status);
+ bool isDownloaded() const;
+
+ void toggleLock();
+
+ GPItemInfo* itemInfo() const;
+
+ // reimplemented from IconItem
+ virtual TQRect clickToOpenRect();
+
+protected:
+
+ virtual void paintItem();
+
+private:
+
+ void calcRect(const TQString& itemName, const TQString& downloadName);
+
+private:
+
+ CameraIconViewItemPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAICONITEM_H */
diff --git a/src/utilities/cameragui/cameraiconview.cpp b/src/utilities/cameragui/cameraiconview.cpp
new file mode 100644
index 00000000..ba496217
--- /dev/null
+++ b/src/utilities/cameragui/cameraiconview.cpp
@@ -0,0 +1,900 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-18
+ * Description : camera icon view
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqtimer.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqcursor.h>
+#include <tqfontmetrics.h>
+#include <tqfont.h>
+#include <tqdragobject.h>
+#include <tqclipboard.h>
+
+// KDE includes.
+
+#include <kurldrag.h>
+#include <kmimetype.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tdeaction.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "themeengine.h"
+#include "thumbnailsize.h"
+#include "gpiteminfo.h"
+#include "renamecustomizer.h"
+#include "icongroupitem.h"
+#include "dpopupmenu.h"
+#include "dragobjects.h"
+#include "cameraui.h"
+#include "cameraiconitem.h"
+#include "cameraiconview.h"
+#include "cameraiconview.moc"
+
+namespace Digikam
+{
+
+class CameraIconViewPriv
+{
+public:
+
+ CameraIconViewPriv()
+ {
+ renamer = 0;
+ groupItem = 0;
+ cameraUI = 0;
+ thumbSize = ThumbnailSize::Large;
+ pixmapNewPicture = TQPixmap(newPicture_xpm);
+ pixmapUnknowPicture = TQPixmap(unknowPicture_xpm);
+ }
+
+ static const char *newPicture_xpm[];
+ static const char *unknowPicture_xpm[];
+
+ TQDict<CameraIconViewItem> itemDict;
+
+ TQRect itemRect;
+
+ TQPixmap itemRegPixmap;
+ TQPixmap itemSelPixmap;
+ TQPixmap pixmapNewPicture;
+ TQPixmap pixmapUnknowPicture;
+
+ RenameCustomizer *renamer;
+
+ IconGroupItem *groupItem;
+
+ ThumbnailSize thumbSize;
+
+ CameraUI *cameraUI;
+};
+
+const char *CameraIconViewPriv::newPicture_xpm[] =
+{
+ "13 13 8 1",
+ " c None",
+ ". c #232300",
+ "+ c #F6F611",
+ "@ c #000000",
+ "# c #DBDA4D",
+ "$ c #FFFF00",
+ "% c #AAA538",
+ "& c #E8E540",
+ " . ",
+ " . .+. . ",
+ " @#@ .$. .#. ",
+ " @$@#$#@$. ",
+ " @$%&%$@ ",
+ " ..#%&&&%#.. ",
+ ".+$$&&&&&$$+@",
+ " ..#%&&&%#@@ ",
+ " @$%&%$@ ",
+ " .$@#$#@$. ",
+ " @#. @$@ @#. ",
+ " . @+@ . ",
+ " @ "
+};
+
+const char *CameraIconViewPriv::unknowPicture_xpm[] =
+{
+ "16 16 78 1",
+ " g None",
+ ". g #777777",
+ "+ g #7A7A7A",
+ "@ g #8C8C8C",
+ "# g #787878",
+ "$ g #707070",
+ "% g #878787",
+ "& g #C3C3C3",
+ "* g #EAEAEA",
+ "= g #E4E4E4",
+ "- g #E2E2E2",
+ "; g #E6E6E6",
+ "> g #CECECE",
+ ", g #888888",
+ "' g #6B6B6B",
+ ") g #969696",
+ "! g #DEDEDE",
+ "~ g #D8D8D8",
+ "{ g #FFFFFF",
+ "] g #F2F2F2",
+ "^ g #DFDFDF",
+ "/ g #9D9D9D",
+ "( g #686868",
+ "_ g #848484",
+ ": g #D0D0D0",
+ "< g #F1F1F1",
+ "[ g #F0F0F0",
+ "} g #EBEBEB",
+ "| g #FDFDFD",
+ "1 g #DDDDDD",
+ "2 g #D4D4D4",
+ "3 g #838383",
+ "4 g #ABABAB",
+ "5 g #C8C8C8",
+ "6 g #CCCCCC",
+ "7 g #F4F4F4",
+ "8 g #D6D6D6",
+ "9 g #E8E8E8",
+ "0 g #C4C4C4",
+ "a g #A4A4A4",
+ "b g #656565",
+ "c g #B4B4B4",
+ "d g #B9B9B9",
+ "e g #BDBDBD",
+ "f g #B7B7B7",
+ "g g #898989",
+ "h g #6D6D6D",
+ "i g #808080",
+ "j g #AAAAAA",
+ "k g #A9A9A9",
+ "l g #737373",
+ "m g #7F7F7F",
+ "n g #9A9A9A",
+ "o g #D3D3D3",
+ "p g #909090",
+ "q g #727272",
+ "r g #8F8F8F",
+ "s g #8E8E8E",
+ "t g #8D8D8D",
+ "u g #EEEEEE",
+ "v g #FAFAFA",
+ "w g #929292",
+ "x g #C5C5C5",
+ "y g #5F5F5F",
+ "z g #989898",
+ "A g #CFCFCF",
+ "B g #9C9C9C",
+ "C g #A0A0A0",
+ "D g #FEFEFE",
+ "E g #ACACAC",
+ "F g #5E5E5E",
+ "G g #868686",
+ "H g #AFAFAF",
+ "I g #C1C1C1",
+ "J g #818181",
+ "K g #7E7E7E",
+ "L g #7B7B7B",
+ "M g #636363",
+ " ",
+ " .+@@#$ ",
+ " .%&*=-;>,' ",
+ " .)!~={{]^-/( ",
+ " _::<{[}|{123 ",
+ " .456{7558{90ab ",
+ " +cde96df={&g,h ",
+ " ijjjjjk;{=@,,l ",
+ " mnnnnno{-pgggq ",
+ " #rprstuvwtttt' ",
+ " $tpppp6xpppp@y ",
+ " mnnnzA~Bnnn. ",
+ " 'taaCD{Eaa,F ",
+ " (GjHI0HjJF ",
+ " (K,,LM ",
+ " "
+};
+
+CameraIconView::CameraIconView(CameraUI* ui, TQWidget* parent)
+ : IconView(parent)
+{
+ d = new CameraIconViewPriv;
+ d->cameraUI = ui;
+ d->groupItem = new IconGroupItem(this);
+
+ setHScrollBarMode(TQScrollView::AlwaysOff);
+ setMinimumSize(400, 300);
+
+ setAcceptDrops(true);
+ viewport()->setAcceptDrops(true);
+
+ // ----------------------------------------------------------------
+
+ connect(this, TQ_SIGNAL(signalSelectionChanged()),
+ this, TQ_SLOT(slotSelectionChanged()));
+
+ connect(this, TQ_SIGNAL(signalNewSelection(bool)),
+ this, TQ_SLOT(slotUpdateDownloadNames(bool)));
+
+ connect(this, TQ_SIGNAL(signalRightButtonClicked(IconItem*, const TQPoint&)),
+ this, TQ_SLOT(slotContextMenu(IconItem*, const TQPoint&)));
+
+ connect(this, TQ_SIGNAL(signalRightButtonClicked(const TQPoint &)),
+ this, TQ_SLOT(slotRightButtonClicked(const TQPoint &)));
+
+ connect(this, TQ_SIGNAL(signalDoubleClicked(IconItem*)),
+ this, TQ_SLOT(slotDoubleClicked(IconItem*)));
+
+ connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
+ this, TQ_SLOT(slotThemeChanged()));
+
+ // ----------------------------------------------------------------
+
+ updateItemRectsPixmap();
+ slotThemeChanged();
+}
+
+CameraIconView::~CameraIconView()
+{
+ clear();
+ delete d;
+}
+
+TQPixmap* CameraIconView::itemBaseRegPixmap() const
+{
+ return &d->itemRegPixmap;
+}
+
+TQPixmap* CameraIconView::itemBaseSelPixmap() const
+{
+ return &d->itemSelPixmap;
+}
+
+TQPixmap CameraIconView::newPicturePixmap() const
+{
+ return d->pixmapNewPicture;
+}
+
+TQPixmap CameraIconView::unknowPicturePixmap() const
+{
+ return d->pixmapUnknowPicture;
+}
+
+void CameraIconView::setRenameCustomizer(RenameCustomizer* renamer)
+{
+ d->renamer = renamer;
+
+ connect(d->renamer, TQ_SIGNAL(signalChanged()),
+ this, TQ_SLOT(slotDownloadNameChanged()));
+}
+
+void CameraIconView::addItem(const GPItemInfo& info)
+{
+ TQImage thumb;
+ // Just to have a generic image thumb from desktop with KDE < 3.5.0
+ KMimeType::Ptr mime = KMimeType::mimeType(info.mime == TQString("image/x-raw") ?
+ TQString("image/tiff") : info.mime);
+
+ if (mime)
+ {
+ thumb = TQImage(mime->pixmap(TDEIcon::Desktop, ThumbnailSize::Huge, TDEIcon::DefaultState)
+ .convertToImage());
+ }
+ else
+ {
+ TDEIconLoader *iconLoader = TDEApplication::kApplication()->iconLoader();
+ thumb = iconLoader->loadIcon("application-x-zerosize", TDEIcon::Desktop,
+ ThumbnailSize::Huge, TDEIcon::DefaultState, 0, true)
+ .convertToImage();
+ }
+
+ TQString downloadName;
+
+ if (d->renamer)
+ {
+ if (!d->renamer->useDefault())
+ {
+ downloadName = getTemplatedName( &info, d->itemDict.count() );
+ }
+ else
+ {
+ downloadName = getCasedName( d->renamer->changeCase(), &info);
+ }
+ }
+
+ CameraIconViewItem* item = new CameraIconViewItem(d->groupItem, info, thumb, downloadName);
+ d->itemDict.insert(info.folder+info.name, item);
+}
+
+void CameraIconView::removeItem(const TQString& folder, const TQString& file)
+{
+ CameraIconViewItem* item = d->itemDict.find(folder+file);
+ if (!item)
+ return;
+ d->itemDict.remove(folder+file);
+
+ setDelayedRearrangement(true);
+ delete item;
+ setDelayedRearrangement(false);
+}
+
+CameraIconViewItem* CameraIconView::findItem(const TQString& folder, const TQString& file)
+{
+ return d->itemDict.find(folder+file);
+}
+
+int CameraIconView::countItemsByFolder(TQString folder)
+{
+ int count = 0;
+ if (folder.endsWith("/")) folder.truncate(folder.length()-1);
+
+ for (IconItem* item = firstItem(); item; item = item->nextItem())
+ {
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(item);
+ TQString itemFolder = iconItem->itemInfo()->folder;
+ if (itemFolder.endsWith("/")) itemFolder.truncate(itemFolder.length()-1);
+
+ if (folder == itemFolder)
+ count++;
+ }
+
+ return count;
+}
+
+void CameraIconView::setThumbnail(const TQString& folder, const TQString& filename, const TQImage& image)
+{
+ CameraIconViewItem* item = d->itemDict.find(folder+filename);
+ if (!item)
+ return;
+
+ item->setThumbnail(image);
+ item->repaint();
+}
+
+void CameraIconView::ensureItemVisible(CameraIconViewItem *item)
+{
+ IconView::ensureItemVisible(item);
+}
+
+void CameraIconView::ensureItemVisible(const GPItemInfo& itemInfo)
+{
+ ensureItemVisible(itemInfo.folder, itemInfo.name);
+}
+
+void CameraIconView::ensureItemVisible(const TQString& folder, const TQString& file)
+{
+ CameraIconViewItem* item = d->itemDict.find(folder+file);
+ if (!item)
+ return;
+
+ ensureItemVisible(item);
+}
+
+void CameraIconView::slotDownloadNameChanged()
+{
+ bool hasSelection = false;
+ for (IconItem* item = firstItem(); item; item = item->nextItem())
+ {
+ if (item->isSelected())
+ {
+ hasSelection = true;
+ break;
+ }
+ }
+
+ // connected to slotUpdateDownloadNames, and used externally
+ emit signalNewSelection(hasSelection);
+}
+
+void CameraIconView::slotUpdateDownloadNames(bool hasSelection)
+{
+ bool useDefault = true;
+ int startIndex = 0;
+
+ if (d->renamer)
+ {
+ useDefault = d->renamer->useDefault();
+ startIndex = d->renamer->startIndex() -1;
+ }
+
+ bool convertLossLessJpeg = d->cameraUI->convertLosslessJpegFiles();
+ TQString losslessFormat = d->cameraUI->losslessFormat();
+
+ viewport()->setUpdatesEnabled(false);
+
+ // NOTE: see B.K.O #182352: ordering of item count must be adapted sort of icon view,
+ // since items are ordered from the most rescent to the older one.
+
+ if (hasSelection)
+ {
+ // Camera items selection.
+
+ for (IconItem* item = lastItem(); item; item = item->prevItem())
+ {
+ TQString downloadName;
+ CameraIconViewItem* viewItem = static_cast<CameraIconViewItem*>(item);
+
+ if (item->isSelected())
+ {
+ if (!useDefault)
+ downloadName = getTemplatedName( viewItem->itemInfo(), startIndex );
+ else
+ downloadName = getCasedName( d->renamer->changeCase(), viewItem->itemInfo() );
+
+ startIndex++;
+ }
+
+ if (convertLossLessJpeg && !downloadName.isEmpty())
+ {
+ TQFileInfo fi(downloadName);
+ TQString ext = fi.extension(false).upper();
+ if (ext == TQString("JPEG") || ext == TQString("JPG") || ext == TQString("JPE"))
+ {
+ downloadName.truncate(downloadName.length() - ext.length());
+ downloadName.append(losslessFormat.lower());
+ }
+ }
+
+ viewItem->setDownloadName( downloadName );
+ }
+ }
+ else
+ {
+ // No camera item selection.
+
+ for (IconItem* item = lastItem(); item; item = item->prevItem())
+ {
+ TQString downloadName;
+ CameraIconViewItem* viewItem = static_cast<CameraIconViewItem*>(item);
+
+ if (!useDefault)
+ downloadName = getTemplatedName( viewItem->itemInfo(), startIndex );
+ else
+ downloadName = getCasedName( d->renamer->changeCase(), viewItem->itemInfo() );
+
+ if (convertLossLessJpeg)
+ {
+ TQFileInfo fi(downloadName);
+ TQString ext = fi.extension(false).upper();
+ if (ext == TQString("JPEG") || ext == TQString("JPG") || ext == TQString("JPE"))
+ {
+ downloadName.truncate(downloadName.length() - ext.length());
+ downloadName.append(losslessFormat.lower());
+ }
+ }
+
+ viewItem->setDownloadName( downloadName );
+ startIndex++;
+ }
+ }
+
+ viewport()->setUpdatesEnabled(true);
+ viewport()->update();
+}
+
+TQString CameraIconView::defaultDownloadName(CameraIconViewItem *viewItem)
+{
+ RenameCustomizer::Case renamecase = RenameCustomizer::NONE;
+ if (d->renamer)
+ renamecase = d->renamer->changeCase();
+
+ return getCasedName( renamecase, viewItem->itemInfo() );
+}
+
+TQString CameraIconView::getTemplatedName(const GPItemInfo* itemInfo, int position)
+{
+ TQString ext = itemInfo->name;
+ int pos = ext.findRev('.');
+ if (pos < 0)
+ ext = "";
+ else
+ ext = ext.right( ext.length() - pos );
+
+ TQDateTime mtime;
+ mtime.setTime_t(itemInfo->mtime);
+
+ return d->renamer->newName(mtime, position+1, ext);
+}
+
+TQString CameraIconView::getCasedName(const RenameCustomizer::Case ccase,
+ const GPItemInfo* itemInfo)
+{
+ TQString dname;
+
+ switch (ccase)
+ {
+ case(RenameCustomizer::UPPER):
+ {
+ dname = itemInfo->name.upper();
+ break;
+ }
+ case(RenameCustomizer::LOWER):
+ {
+ dname = itemInfo->name.lower();
+ break;
+ }
+ default:
+ {
+ dname = itemInfo->name;
+ break;
+ }
+ };
+
+ return dname;
+}
+
+void CameraIconView::slotSelectionChanged()
+{
+ bool selected = false;
+ CameraIconViewItem* camItem = 0;
+
+ for (IconItem* item = firstItem(); item; item = item->nextItem())
+ {
+ if (item->isSelected())
+ {
+ camItem = static_cast<CameraIconViewItem*>(item);
+ selected = true;
+ break;
+ }
+ }
+
+ emit signalNewSelection(selected);
+ emit signalSelected(camItem, selected);
+
+ viewport()->update();
+}
+
+void CameraIconView::slotContextMenu(IconItem * item, const TQPoint&)
+{
+ if (!item)
+ return;
+
+ // don't popup context menu if the camera is busy
+ if (d->cameraUI->isBusy())
+ return;
+
+ CameraIconViewItem* camItem = static_cast<CameraIconViewItem*>(item);
+
+ DPopupMenu menu(this);
+ menu.insertItem(SmallIcon("editimage"), i18n("&View"), 0);
+ menu.insertSeparator(-1);
+ menu.insertItem(SmallIcon("go-down"),i18n("Download"), 1);
+ menu.insertItem(SmallIcon("go-down"),i18n("Download && Delete"), 4);
+ menu.insertItem(SmallIcon("encrypted"), i18n("Toggle lock"), 3);
+ menu.insertSeparator(-1);
+ menu.insertItem(SmallIcon("edit-delete"), i18n("Delete"), 2);
+
+ int result = menu.exec(TQCursor::pos());
+
+ switch (result)
+ {
+ case(0):
+ {
+ emit signalFileView(camItem);
+ break;
+ }
+ case(1):
+ {
+ emit signalDownload();
+ break;
+ }
+ case(2):
+ {
+ emit signalDelete();
+ break;
+ }
+ case(3):
+ {
+ emit signalToggleLock();
+ break;
+ }
+ case(4):
+ {
+ emit signalDownloadAndDelete();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void CameraIconView::slotDoubleClicked(IconItem* item)
+{
+ if (!item)
+ return;
+
+ if (d->cameraUI->isBusy())
+ return;
+
+ emit signalFileView(static_cast<CameraIconViewItem*>(item));
+}
+
+void CameraIconView::slotSelectAll()
+{
+ selectAll();
+}
+
+void CameraIconView::slotSelectNone()
+{
+ clearSelection();
+}
+
+void CameraIconView::slotSelectInvert()
+{
+ invertSelection();
+}
+
+void CameraIconView::slotSelectNew()
+{
+ blockSignals(true);
+ clearSelection();
+
+ for (IconItem* item = firstItem(); item;
+ item = item->nextItem())
+ {
+ CameraIconViewItem* viewItem = static_cast<CameraIconViewItem*>(item);
+ if (viewItem->itemInfo()->downloaded == GPItemInfo::NewPicture)
+ {
+ viewItem->setSelected(true, false);
+ }
+ }
+
+ blockSignals(false);
+ emit signalSelectionChanged();
+}
+
+void CameraIconView::startDrag()
+{
+ TQStringList lst;
+
+ for (IconItem* item = firstItem(); item; item = item->nextItem())
+ {
+ if (!item->isSelected())
+ continue;
+
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(item);
+ TQString itemPath = iconItem->itemInfo()->folder + iconItem->itemInfo()->name;
+ lst.append(itemPath);
+ }
+
+ TQDragObject * drag = new CameraItemListDrag(lst, d->cameraUI);
+ if (drag)
+ {
+ TQPixmap icon(DesktopIcon("image-x-generic", 48));
+ int w = icon.width();
+ int h = icon.height();
+
+ TQPixmap pix(w+4,h+4);
+ TQString text(TQString::number(lst.count()));
+
+ TQPainter p(&pix);
+ p.fillRect(0, 0, w+4, h+4, TQColor(TQt::white));
+ p.setPen(TQPen(TQt::black, 1));
+ p.drawRect(0, 0, w+4, h+4);
+ p.drawPixmap(2, 2, icon);
+ TQRect r = p.boundingRect(2,2,w,h,TQt::AlignLeft|TQt::AlignTop,text);
+ r.setWidth(TQMAX(r.width(),r.height()));
+ r.setHeight(TQMAX(r.width(),r.height()));
+ p.fillRect(r, TQColor(0,80,0));
+ p.setPen(TQt::white);
+ TQFont f(font());
+ f.setBold(true);
+ p.setFont(f);
+ p.drawText(r, TQt::AlignCenter, text);
+ p.end();
+
+ drag->setPixmap(pix);
+ drag->drag();
+ }
+}
+
+void CameraIconView::contentsDropEvent(TQDropEvent *event)
+{
+ // don't popup context menu if the camera is busy
+ if (d->cameraUI->isBusy())
+ return;
+
+ if ( (!TQUriDrag::canDecode(event) && !CameraDragObject::canDecode(event) )
+ || event->source() == this)
+ {
+ event->ignore();
+ return;
+ }
+
+ KURL::List srcURLs;
+ KURLDrag::decode(event, srcURLs);
+ uploadItemPopupMenu(srcURLs);
+}
+
+void CameraIconView::slotRightButtonClicked(const TQPoint&)
+{
+ // don't popup context menu if the camera is busy
+ if (d->cameraUI->isBusy())
+ return;
+
+ TQMimeSource *data = kapp->clipboard()->data(TQClipboard::Clipboard);
+ if(!data || !TQUriDrag::canDecode(data))
+ return;
+
+ KURL::List srcURLs;
+ KURLDrag::decode(data, srcURLs);
+ uploadItemPopupMenu(srcURLs);
+}
+
+void CameraIconView::uploadItemPopupMenu(const KURL::List& srcURLs)
+{
+ TDEPopupMenu popMenu(this);
+ popMenu.insertTitle(SmallIcon("digikam"), d->cameraUI->cameraTitle());
+ popMenu.insertItem( SmallIcon("goto"), i18n("&Upload to camera"), 10 );
+ popMenu.insertSeparator(-1);
+ popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") );
+
+ popMenu.setMouseTracking(true);
+ int id = popMenu.exec(TQCursor::pos());
+ switch(id)
+ {
+ case 10:
+ {
+ emit signalUpload(srcURLs);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+TQRect CameraIconView::itemRect() const
+{
+ return d->itemRect;
+}
+
+void CameraIconView::setThumbnailSize(const ThumbnailSize& thumbSize)
+{
+ if ( d->thumbSize != thumbSize)
+ {
+ d->thumbSize = thumbSize;
+ updateItemRectsPixmap();
+ triggerRearrangement();
+ }
+}
+
+ThumbnailSize CameraIconView::thumbnailSize() const
+{
+ return d->thumbSize;
+}
+
+void CameraIconView::updateItemRectsPixmap()
+{
+ int thumbSize = d->thumbSize.size();
+
+ TQRect pixRect;
+ TQRect textRect;
+ TQRect extraRect;
+
+ pixRect.setWidth(thumbSize);
+ pixRect.setHeight(thumbSize);
+
+ TQFontMetrics fm(font());
+ TQRect r = TQRect(fm.boundingRect(0, 0, thumbSize, 0xFFFFFFFF,
+ TQt::AlignHCenter | TQt::AlignTop,
+ "XXXXXXXXX"));
+ textRect.setWidth(r.width());
+ textRect.setHeight(r.height());
+
+ TQFont fn(font());
+ if (fn.pointSize() > 0)
+ {
+ fn.setPointSize(TQMAX(fn.pointSize()-2, 6));
+ }
+
+ fm = TQFontMetrics(fn);
+ r = TQRect(fm.boundingRect(0, 0, thumbSize, 0xFFFFFFFF,
+ TQt::AlignHCenter | TQt::AlignTop,
+ "XXXXXXXXX"));
+ extraRect.setWidth(r.width());
+ extraRect.setHeight(r.height());
+
+ r = TQRect();
+ r.setWidth(TQMAX(TQMAX(pixRect.width(), textRect.width()), extraRect.width()) + 4);
+ r.setHeight(pixRect.height() + textRect.height() + extraRect.height() + 4);
+
+ d->itemRect = r;
+
+ d->itemRegPixmap = ThemeEngine::instance()->thumbRegPixmap(d->itemRect.width(),
+ d->itemRect.height());
+
+ d->itemSelPixmap = ThemeEngine::instance()->thumbSelPixmap(d->itemRect.width(),
+ d->itemRect.height());
+}
+
+void CameraIconView::slotThemeChanged()
+{
+ updateItemRectsPixmap();
+ viewport()->update();
+}
+
+int CameraIconView::itemsDownloaded()
+{
+ int downloaded = 0;
+
+ for (IconItem* item = firstItem(); item; item = item->nextItem())
+ {
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(item);
+
+ if (iconItem->itemInfo()->downloaded == GPItemInfo::DownloadedYes)
+ downloaded++;
+ }
+
+ return downloaded;
+}
+
+void CameraIconView::itemsSelectionSizeInfo(unsigned long& fSizeKB, unsigned long& dSizeKB)
+{
+ long long fSize = 0; // Files size
+ long long dSize = 0; // Estimated space requires to download and process files.
+ for (IconItem* item = firstItem(); item; item = item->nextItem())
+ {
+ if (item->isSelected())
+ {
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(item);
+ long long size = iconItem->itemInfo()->size;
+ if (size < 0) // -1 if size is not provided by camera
+ continue;
+ fSize += size;
+
+ if (iconItem->itemInfo()->mime == TQString("image/jpeg"))
+ {
+ if (d->cameraUI->convertLosslessJpegFiles())
+ {
+ // Estimated size is aroud 5 x original size when JPEG=>PNG.
+ dSize += size*5;
+ }
+ else if (d->cameraUI->autoRotateJpegFiles())
+ {
+ // We need a double size to perform rotation.
+ dSize += size*2;
+ }
+ else
+ {
+ // Real file size is added.
+ dSize += size;
+ }
+ }
+ else
+ dSize += size;
+
+ }
+ }
+
+ fSizeKB = fSize / 1024;
+ dSizeKB = dSize / 1024;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/cameraiconview.h b/src/utilities/cameragui/cameraiconview.h
new file mode 100644
index 00000000..f621fedf
--- /dev/null
+++ b/src/utilities/cameragui/cameraiconview.h
@@ -0,0 +1,141 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-18
+ * Description : camera icon view
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef CAMERAICONVIEW_H
+#define CAMERAICONVIEW_H
+
+// TQt includes.
+
+#include <tqdict.h>
+#include <tqrect.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "iconview.h"
+#include "renamecustomizer.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+
+class ThumbnailSize;
+class GPItemInfo;
+class RenameCustomizer;
+class CameraUI;
+class CameraIconViewItem;
+class CameraIconViewPriv;
+
+class CameraIconView : public IconView
+{
+ TQ_OBJECT
+
+
+public:
+
+ CameraIconView(CameraUI* ui, TQWidget* parent);
+ ~CameraIconView();
+
+ void setRenameCustomizer(RenameCustomizer* renamer);
+
+ void addItem(const GPItemInfo& itemInfo);
+ void removeItem(const TQString& folder, const TQString& file);
+ void setThumbnail(const TQString& folder, const TQString& filename, const TQImage& image);
+
+ void ensureItemVisible(CameraIconViewItem *item);
+ void ensureItemVisible(const GPItemInfo& itemInfo);
+ void ensureItemVisible(const TQString& folder, const TQString& file);
+
+ void setThumbnailSize(const ThumbnailSize& thumbSize);
+ ThumbnailSize thumbnailSize() const;
+
+ CameraIconViewItem* findItem(const TQString& folder, const TQString& file);
+
+ int countItemsByFolder(TQString folder);
+ int itemsDownloaded();
+
+ TQPixmap* itemBaseRegPixmap() const;
+ TQPixmap* itemBaseSelPixmap() const;
+ TQPixmap newPicturePixmap() const;
+ TQPixmap unknowPicturePixmap() const;
+
+ virtual TQRect itemRect() const;
+
+ TQString defaultDownloadName(CameraIconViewItem *item);
+
+ void itemsSelectionSizeInfo(unsigned long& fSize, unsigned long& dSize);
+
+signals:
+
+ void signalSelected(CameraIconViewItem*, bool);
+ void signalFileView(CameraIconViewItem*);
+
+ void signalUpload(const KURL::List&);
+ void signalDownload();
+ void signalDownloadAndDelete();
+ void signalDelete();
+ void signalToggleLock();
+ void signalNewSelection(bool);
+
+public slots:
+
+ void slotDownloadNameChanged();
+ void slotSelectionChanged();
+ void slotSelectAll();
+ void slotSelectNone();
+ void slotSelectInvert();
+ void slotSelectNew();
+
+private slots:
+
+ void slotRightButtonClicked(const TQPoint& pos);
+ void slotContextMenu(IconItem* item, const TQPoint& pos);
+ void slotDoubleClicked(IconItem* item);
+ void slotThemeChanged();
+ void slotUpdateDownloadNames(bool hasSelection);
+
+protected:
+
+ void startDrag();
+ void contentsDropEvent(TQDropEvent *event);
+ void updateItemRectsPixmap();
+
+private:
+
+ TQString getTemplatedName(const GPItemInfo* itemInfo, int position);
+ TQString getCasedName(const RenameCustomizer::Case ccase, const GPItemInfo* itemInfo);
+ void uploadItemPopupMenu(const KURL::List& srcURLs);
+
+private:
+
+ CameraIconViewPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAICONVIEW_H */
diff --git a/src/utilities/cameragui/camerainfodialog.cpp b/src/utilities/cameragui/camerainfodialog.cpp
new file mode 100644
index 00000000..ba565a59
--- /dev/null
+++ b/src/utilities/cameragui/camerainfodialog.cpp
@@ -0,0 +1,85 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-28
+ * Description : a dialog to display camera information.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqtextedit.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "camerainfodialog.h"
+
+namespace Digikam
+{
+
+CameraInfoDialog::CameraInfoDialog(TQWidget *parent, const TQString& summary, const TQString& manual,
+ const TQString& about)
+ : KDialogBase(IconList, i18n("Camera Information"), Help|Ok, Ok, parent, 0, true, true)
+{
+ setHelp("digitalstillcamera.anchor", "digikam");
+ resize(500, 400);
+
+ // ----------------------------------------------------------
+
+ TQFrame *p1 = addPage( i18n("Summary"), i18n("Camera Summary"), BarIcon("contents2", TDEIcon::SizeMedium) );
+ TQVBoxLayout *p1layout = new TQVBoxLayout( p1, 0, 6 );
+
+ TQTextEdit *summaryView = new TQTextEdit(summary, TQString(), p1);
+ summaryView->setWordWrap(TQTextEdit::WidgetWidth);
+ summaryView->setReadOnly(true);
+ p1layout->addWidget(summaryView);
+
+ // ----------------------------------------------------------
+
+ TQFrame *p2 = addPage( i18n("Manual"), i18n("Camera Manual"), BarIcon("contents", TDEIcon::SizeMedium) );
+ TQVBoxLayout *p2layout = new TQVBoxLayout( p2, 0, 6 );
+
+ TQTextEdit *manualView = new TQTextEdit(manual, TQString(), p2);
+ manualView->setWordWrap(TQTextEdit::WidgetWidth);
+ manualView->setReadOnly(true);
+ p2layout->addWidget(manualView);
+
+ // ----------------------------------------------------------
+
+ TQFrame *p3 = addPage( i18n("About"), i18n("About Driver"), BarIcon("camera-photo", TDEIcon::SizeMedium) );
+ TQVBoxLayout *p3layout = new TQVBoxLayout( p3, 0, 6 );
+
+ TQTextEdit *aboutView = new TQTextEdit(about, TQString(), p3);
+ aboutView->setWordWrap(TQTextEdit::WidgetWidth);
+ aboutView->setReadOnly(true);
+ p3layout->addWidget(aboutView);
+}
+
+CameraInfoDialog::~CameraInfoDialog()
+{
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/camerainfodialog.h b/src/utilities/cameragui/camerainfodialog.h
new file mode 100644
index 00000000..7ec3120f
--- /dev/null
+++ b/src/utilities/cameragui/camerainfodialog.h
@@ -0,0 +1,50 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-28
+ * Description : a dialog to display camera information.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CAMERAINFODIALOG_H
+#define CAMERAINFODIALOG_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+namespace Digikam
+{
+
+class CameraInfoDialog : public KDialogBase
+{
+public:
+
+ CameraInfoDialog(TQWidget *parent, const TQString& summary, const TQString& manual,
+ const TQString& about);
+ ~CameraInfoDialog();
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAINFODIALOG_H */
diff --git a/src/utilities/cameragui/cameraui.cpp b/src/utilities/cameragui/cameraui.cpp
new file mode 100644
index 00000000..8b531ea2
--- /dev/null
+++ b/src/utilities/cameragui/cameraui.cpp
@@ -0,0 +1,1734 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-16
+ * Description : Camera interface dialog
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#define CAMERA_INFO_MENU_ID 255
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqtoolbutton.h>
+#include <tqiconview.h>
+#include <tqvbox.h>
+#include <tqhbox.h>
+#include <tqpopupmenu.h>
+#include <tqsplitter.h>
+#include <tqpixmap.h>
+#include <tqcombobox.h>
+#include <tqtoolbox.h>
+#include <tqframe.h>
+#include <tqvbuttongroup.h>
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqlineedit.h>
+#include <tqtooltip.h>
+#include <tqtimer.h>
+#include <tqwhatsthis.h>
+#include <tqfile.h>
+#include <tqfileinfo.h>
+
+// KDE includes.
+
+#include <tdefiledialog.h>
+#include <kimageio.h>
+#include <tdeaboutdata.h>
+#include <tdemessagebox.h>
+#include <kprogress.h>
+#include <tdeglobal.h>
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <khelpmenu.h>
+#include <kcalendarsystem.h>
+#include <kurllabel.h>
+#include <ksqueezedtextlabel.h>
+
+#if KDE_IS_VERSION(3,2,0)
+#include <kinputdialog.h>
+#else
+#include <klineeditdlg.h>
+#endif
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "thumbnailsize.h"
+#include "kdatetimeedit.h"
+#include "sidebar.h"
+#include "scanlib.h"
+#include "downloadsettingscontainer.h"
+#include "imagepropertiessidebarcamgui.h"
+#include "albummanager.h"
+#include "albumsettings.h"
+#include "album.h"
+#include "albumselectdialog.h"
+#include "renamecustomizer.h"
+#include "animwidget.h"
+#include "freespacewidget.h"
+#include "camerafolderdialog.h"
+#include "camerainfodialog.h"
+#include "cameraiconview.h"
+#include "cameraiconitem.h"
+#include "cameracontroller.h"
+#include "cameralist.h"
+#include "cameratype.h"
+#include "cameraui.h"
+#include "cameraui.moc"
+
+namespace Digikam
+{
+
+class CameraUIPriv
+{
+public:
+
+ enum SettingsTab
+ {
+ RENAMEFILEPAGE=0,
+ AUTOALBUMPAGE,
+ ONFLYPAGE
+ };
+
+ enum DateFormatOptions
+ {
+ IsoDateFormat=0,
+ TextDateFormat,
+ LocalDateFormat
+ };
+
+ CameraUIPriv()
+ {
+ deleteAfter = false;
+ busy = false;
+ closed = false;
+ helpMenu = 0;
+ advBox = 0;
+ downloadMenu = 0;
+ deleteMenu = 0;
+ imageMenu = 0;
+ cancelBtn = 0;
+ splitter = 0;
+ rightSidebar = 0;
+ fixDateTimeCheck = 0;
+ autoRotateCheck = 0;
+ autoAlbumDateCheck = 0;
+ autoAlbumExtCheck = 0;
+ status = 0;
+ progress = 0;
+ controller = 0;
+ view = 0;
+ renameCustomizer = 0;
+ anim = 0;
+ dateTimeEdit = 0;
+ setPhotographerId = 0;
+ setCredits = 0;
+ losslessFormat = 0;
+ convertJpegCheck = 0;
+ formatLabel = 0;
+ folderDateLabel = 0;
+ folderDateFormat = 0;
+ freeSpaceWidget = 0;
+ }
+
+ bool deleteAfter;
+ bool busy;
+ bool closed;
+
+ TQString cameraTitle;
+
+ TQStringList currentlyDeleting;
+ TQStringList foldersToScan;
+ TQStringList cameraFolderList;
+
+ TQPopupMenu *downloadMenu;
+ TQPopupMenu *deleteMenu;
+ TQPopupMenu *imageMenu;
+
+ TQToolButton *cancelBtn;
+
+ TQToolBox *advBox;
+
+ TQCheckBox *autoRotateCheck;
+ TQCheckBox *autoAlbumDateCheck;
+ TQCheckBox *autoAlbumExtCheck;
+ TQCheckBox *fixDateTimeCheck;
+ TQCheckBox *setPhotographerId;
+ TQCheckBox *setCredits;
+ TQCheckBox *convertJpegCheck;
+
+ TQLabel *formatLabel;
+ TQLabel *folderDateLabel;
+
+ TQComboBox *losslessFormat;
+ TQComboBox *folderDateFormat;
+
+ TQSplitter *splitter;
+
+ TQDateTime lastAccess;
+
+ KProgress *progress;
+
+ KSqueezedTextLabel *status;
+
+ KURL lastDestURL;
+
+ KHelpMenu *helpMenu;
+
+ KDateTimeEdit *dateTimeEdit;
+
+ CameraController *controller;
+
+ CameraIconView *view;
+
+ RenameCustomizer *renameCustomizer;
+
+ AnimWidget *anim;
+
+ ImagePropertiesSideBarCamGui *rightSidebar;
+
+ FreeSpaceWidget *freeSpaceWidget;
+};
+
+CameraUI::CameraUI(TQWidget* /*parent*/, const TQString& cameraTitle,
+ const TQString& model, const TQString& port,
+ const TQString& path, const TQDateTime lastAccess)
+ : KDialogBase(Plain, cameraTitle,
+ Help|User1|User2|User3|Close, Close,
+ 0, // B.K.O # 116485: no parent for this modal dialog.
+ 0, false, true,
+ i18n("D&elete"),
+ i18n("&Download"),
+ i18n("&Images"))
+{
+ d = new CameraUIPriv;
+ d->lastAccess = lastAccess;
+ d->cameraTitle = cameraTitle;
+ setHelp("camerainterface.anchor", "digikam");
+
+ // -------------------------------------------------------------------------
+
+ TQGridLayout* viewBoxLayout = new TQGridLayout(plainPage(), 2, 7);
+
+ TQHBox* widget = new TQHBox(plainPage());
+ d->splitter = new TQSplitter(widget);
+ d->view = new CameraIconView(this, d->splitter);
+
+ TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
+ d->view->setSizePolicy(rightSzPolicy);
+
+ d->rightSidebar = new ImagePropertiesSideBarCamGui(widget, "CameraGui Sidebar Right", d->splitter,
+ Sidebar::Right, true);
+ d->splitter->setFrameStyle( TQFrame::NoFrame );
+ d->splitter->setFrameShadow( TQFrame::Plain );
+ d->splitter->setFrameShape( TQFrame::NoFrame );
+ d->splitter->setOpaqueResize(false);
+
+ // -------------------------------------------------------------------------
+
+ d->advBox = new TQToolBox(d->rightSidebar);
+ d->renameCustomizer = new RenameCustomizer(d->advBox, d->cameraTitle);
+ d->view->setRenameCustomizer(d->renameCustomizer);
+
+ TQWhatsThis::add( d->advBox, i18n("<p>Set how digiKam will rename files as they are downloaded."));
+
+ d->advBox->insertItem(CameraUIPriv::RENAMEFILEPAGE, d->renameCustomizer,
+ SmallIconSet("fileimport"), i18n("File Renaming Options"));
+
+ // -- Albums Auto-creation options -----------------------------------------
+
+ TQWidget* albumBox = new TQWidget(d->advBox);
+ TQVBoxLayout* albumVlay = new TQVBoxLayout(albumBox, marginHint(), spacingHint());
+ d->autoAlbumExtCheck = new TQCheckBox(i18n("Extension-based sub-albums"), albumBox);
+ d->autoAlbumDateCheck = new TQCheckBox(i18n("Date-based sub-albums"), albumBox);
+ TQHBox *hbox1 = new TQHBox(albumBox);
+ d->folderDateLabel = new TQLabel(i18n("Date format:"), hbox1);
+ d->folderDateFormat = new TQComboBox(hbox1);
+ d->folderDateFormat->insertItem(i18n("ISO"), CameraUIPriv::IsoDateFormat);
+ d->folderDateFormat->insertItem(i18n("Full Text"), CameraUIPriv::TextDateFormat);
+ d->folderDateFormat->insertItem(i18n("Local Settings"), CameraUIPriv::LocalDateFormat);
+ albumVlay->addWidget(d->autoAlbumExtCheck);
+ albumVlay->addWidget(d->autoAlbumDateCheck);
+ albumVlay->addWidget(hbox1);
+ albumVlay->addStretch();
+
+ TQWhatsThis::add( albumBox, i18n("<p>Set how digiKam creates albums automatically when downloading."));
+ TQWhatsThis::add( d->autoAlbumExtCheck, i18n("<p>Enable this option if you want to download your "
+ "pictures into automatically created file extension-based sub-albums of the destination "
+ "album. This way, you can separate JPEG and RAW files as they are downloaded from your camera."));
+ TQWhatsThis::add( d->autoAlbumDateCheck, i18n("<p>Enable this option if you want to "
+ "download your pictures into automatically created file date-based sub-albums "
+ "of the destination album."));
+ TQWhatsThis::add( d->folderDateFormat, i18n("<p>Select your preferred date format used to "
+ "create new albums. The options available are:<p>"
+ "<b>ISO</b>: the date format is in accordance with ISO 8601 "
+ "(YYYY-MM-DD). E.g.: <i>2006-08-24</i><p>"
+ "<b>Full Text</b>: the date format is in a user-readable string. "
+ "E.g.: <i>Thu Aug 24 2006</i><p>"
+ "<b>Local Settings</b>: the date format depending on TDE control panel settings.<p>"));
+
+ d->advBox->insertItem(CameraUIPriv::AUTOALBUMPAGE, albumBox, SmallIconSet("folder-new"),
+ i18n("Auto-creation of Albums"));
+
+ // -- On the Fly options ---------------------------------------------------
+
+ TQWidget* onFlyBox = new TQWidget(d->advBox);
+ TQVBoxLayout* onFlyVlay = new TQVBoxLayout(onFlyBox, marginHint(), spacingHint());
+ d->setPhotographerId = new TQCheckBox(i18n("Set default photographer identity"), onFlyBox);
+ d->setCredits = new TQCheckBox(i18n("Set default credit and copyright"), onFlyBox);
+ d->fixDateTimeCheck = new TQCheckBox(i18n("Fix internal date && time"), onFlyBox);
+ d->dateTimeEdit = new KDateTimeEdit(onFlyBox, "datepicker");
+ d->autoRotateCheck = new TQCheckBox(i18n("Auto-rotate/flip image"), onFlyBox);
+ d->convertJpegCheck = new TQCheckBox(i18n("Convert to lossless file format"), onFlyBox);
+ TQHBox *hbox2 = new TQHBox(onFlyBox);
+ d->formatLabel = new TQLabel(i18n("New image format:"), hbox2);
+ d->losslessFormat = new TQComboBox(hbox2);
+ d->losslessFormat->insertItem("PNG", 0);
+ onFlyVlay->addWidget(d->setPhotographerId);
+ onFlyVlay->addWidget(d->setCredits);
+ onFlyVlay->addWidget(d->fixDateTimeCheck);
+ onFlyVlay->addWidget(d->dateTimeEdit);
+ onFlyVlay->addWidget(d->autoRotateCheck);
+ onFlyVlay->addWidget(d->convertJpegCheck);
+ onFlyVlay->addWidget(hbox2);
+ onFlyVlay->addStretch();
+
+ TQWhatsThis::add( onFlyBox, i18n("<p>Set here all options to fix/transform JPEG files automatically "
+ "as they are downloaded."));
+ TQWhatsThis::add( d->autoRotateCheck, i18n("<p>Enable this option if you want images automatically "
+ "rotated or flipped using EXIF information provided by the camera."));
+ TQWhatsThis::add( d->setPhotographerId, i18n("<p>Enable this option to store the default "
+ "photographer identity in the IPTC tags using digiKam's metadata settings."));
+ TQWhatsThis::add( d->setCredits, i18n("<p>Enable this option to store the default credit "
+ "and copyright information in the IPTC tags using digiKam's metadata settings."));
+ TQWhatsThis::add( d->fixDateTimeCheck, i18n("<p>Enable this option to set date and time metadata "
+ "tags to the right values if your camera does not set "
+ "these tags correctly when pictures are taken. The values will "
+ "be saved in the DateTimeDigitized and DateTimeCreated EXIF/IPTC fields."));
+ TQWhatsThis::add( d->convertJpegCheck, i18n("<p>Enable this option to automatically convert "
+ "all JPEG files to a lossless image format. <b>Note:</b> Image conversion can take a "
+ "while on a slow computer."));
+ TQWhatsThis::add( d->losslessFormat, i18n("<p>Select your preferred lossless image file format to "
+ "convert to. <b>Note:</b> All metadata will be preserved during the conversion."));
+
+ d->advBox->insertItem(CameraUIPriv::ONFLYPAGE, onFlyBox, SmallIconSet("system-run"),
+ i18n("On the Fly Operations (JPEG only)"));
+
+ d->rightSidebar->appendTab(d->advBox, SmallIcon("configure"), i18n("Settings"));
+ d->rightSidebar->loadViewState();
+
+ // -------------------------------------------------------------------------
+
+ d->cancelBtn = new TQToolButton(plainPage());
+ d->cancelBtn->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) );
+ d->cancelBtn->setPixmap( SmallIcon( "cancel" ) );
+ d->cancelBtn->setEnabled(false);
+
+ d->status = new KSqueezedTextLabel(plainPage());
+ d->progress = new KProgress(plainPage());
+ d->progress->setMaximumHeight( fontMetrics().height()+4 );
+ d->progress->hide();
+
+ TQWidget *frame = new TQWidget(plainPage());
+ TQHBoxLayout* layout = new TQHBoxLayout(frame);
+ frame->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
+
+ KURLLabel *pixmapLogo = new KURLLabel( Digikam::webProjectUrl(), TQString(), frame );
+ pixmapLogo->setMargin(0);
+ pixmapLogo->setScaledContents( false );
+ pixmapLogo->setSizePolicy(TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum));
+ TQToolTip::add(pixmapLogo, i18n("Visit digiKam project website"));
+ TDEGlobal::dirs()->addResourceType("logo-digikam", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("logo-digikam", "logo-digikam.png");
+ pixmapLogo->setPixmap( TQPixmap( directory + "logo-digikam.png" ) );
+ pixmapLogo->setFocusPolicy(TQWidget::NoFocus);
+
+ d->anim = new AnimWidget(frame, pixmapLogo->height()-2);
+
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ layout->addWidget( pixmapLogo );
+ layout->addWidget( d->anim );
+
+ d->freeSpaceWidget = new FreeSpaceWidget(plainPage(), 100);
+
+ viewBoxLayout->addMultiCellWidget(widget, 0, 0, 0, 7);
+ viewBoxLayout->addMultiCellWidget(d->cancelBtn, 2, 2, 0, 0);
+ viewBoxLayout->addMultiCellWidget(d->status, 2, 2, 2, 2);
+ viewBoxLayout->addMultiCellWidget(d->progress, 2, 2, 3, 3);
+ viewBoxLayout->addMultiCellWidget(d->freeSpaceWidget, 2, 2, 5, 5);
+ viewBoxLayout->addMultiCellWidget(frame, 2, 2, 7, 7);
+ viewBoxLayout->setRowSpacing(1, spacingHint());
+ viewBoxLayout->setColSpacing(1, spacingHint());
+ viewBoxLayout->setColSpacing(4, spacingHint());
+ viewBoxLayout->setColSpacing(6, spacingHint());
+ viewBoxLayout->setColStretch( 0, 0 );
+ viewBoxLayout->setColStretch( 1, 0 );
+ viewBoxLayout->setColStretch( 2, 3 );
+ viewBoxLayout->setColStretch( 3, 1 );
+ viewBoxLayout->setColStretch( 4, 0 );
+ viewBoxLayout->setColStretch( 5, 0 );
+ viewBoxLayout->setColStretch( 6, 0 );
+ viewBoxLayout->setColStretch( 7, 0 );
+
+ // -------------------------------------------------------------------------
+
+ d->imageMenu = new TQPopupMenu(this);
+ d->imageMenu->insertItem(i18n("Select &All"), d->view, TQ_SLOT(slotSelectAll()), CTRL+Key_A, 0);
+ d->imageMenu->insertItem(i18n("Select N&one"), d->view, TQ_SLOT(slotSelectNone()), CTRL+Key_U, 1);
+ d->imageMenu->insertItem(i18n("&Invert Selection"), d->view, TQ_SLOT(slotSelectInvert()), CTRL+Key_Asterisk, 2);
+ d->imageMenu->insertSeparator();
+ d->imageMenu->insertItem(i18n("Select &New Items"), d->view, TQ_SLOT(slotSelectNew()), 0, 3);
+ d->imageMenu->insertSeparator();
+ d->imageMenu->insertItem(i18n("Increase Thumbnail Size"), this, TQ_SLOT(slotIncreaseThumbSize()), CTRL+Key_Plus, 4);
+ d->imageMenu->insertItem(i18n("Decrease Thumbnail Size"), this, TQ_SLOT(slotDecreaseThumbSize()), CTRL+Key_Minus, 5);
+ d->imageMenu->insertSeparator();
+ d->imageMenu->insertItem(i18n("Toggle Lock"), this, TQ_SLOT(slotToggleLock()), 0, 6);
+ actionButton(User3)->setPopup(d->imageMenu);
+
+ // -------------------------------------------------------------------------
+
+ d->downloadMenu = new TQPopupMenu(this);
+ d->downloadMenu->insertItem(i18n("Download Selected"),
+ this, TQ_SLOT(slotDownloadSelected()), 0, 0);
+ d->downloadMenu->insertItem(i18n("Download All"),
+ this, TQ_SLOT(slotDownloadAll()), 0, 1);
+ d->downloadMenu->insertSeparator();
+ d->downloadMenu->insertItem(i18n("Download/Delete Selected"),
+ this, TQ_SLOT(slotDownloadAndDeleteSelected()), 0, 2);
+ d->downloadMenu->insertItem(i18n("Download/Delete All"),
+ this, TQ_SLOT(slotDownloadAndDeleteAll()), 0, 3);
+ d->downloadMenu->insertSeparator();
+ d->downloadMenu->insertItem(i18n("Upload..."),
+ this, TQ_SLOT(slotUpload()), 0, 4);
+ d->downloadMenu->setItemEnabled(0, false);
+ d->downloadMenu->setItemEnabled(2, false);
+ actionButton(User2)->setPopup(d->downloadMenu);
+
+ // -------------------------------------------------------------------------
+
+ d->deleteMenu = new TQPopupMenu(this);
+ d->deleteMenu->insertItem(i18n("Delete Selected"), this, TQ_SLOT(slotDeleteSelected()), 0, 0);
+ d->deleteMenu->insertItem(i18n("Delete All"), this, TQ_SLOT(slotDeleteAll()), 0, 1);
+ d->deleteMenu->setItemEnabled(0, false);
+ actionButton(User1)->setPopup(d->deleteMenu);
+
+ // -------------------------------------------------------------------------
+
+ TQPushButton *helpButton = actionButton( Help );
+ d->helpMenu = new KHelpMenu(this, kapp->aboutData(), false);
+ d->helpMenu->menu()->insertItem(SmallIcon("camera-photo"), i18n("Camera Information"),
+ this, TQ_SLOT(slotInformations()), 0, CAMERA_INFO_MENU_ID, 0);
+ helpButton->setPopup( d->helpMenu->menu() );
+
+ // -------------------------------------------------------------------------
+
+ connect(d->autoAlbumDateCheck, TQ_SIGNAL(toggled(bool)),
+ d->folderDateFormat, TQ_SLOT(setEnabled(bool)));
+
+ connect(d->autoAlbumDateCheck, TQ_SIGNAL(toggled(bool)),
+ d->folderDateLabel, TQ_SLOT(setEnabled(bool)));
+
+ connect(d->convertJpegCheck, TQ_SIGNAL(toggled(bool)),
+ d->losslessFormat, TQ_SLOT(setEnabled(bool)));
+
+ connect(d->convertJpegCheck, TQ_SIGNAL(toggled(bool)),
+ d->formatLabel, TQ_SLOT(setEnabled(bool)));
+
+ connect(d->convertJpegCheck, TQ_SIGNAL(toggled(bool)),
+ d->view, TQ_SLOT(slotDownloadNameChanged()));
+
+ connect(d->fixDateTimeCheck, TQ_SIGNAL(toggled(bool)),
+ d->dateTimeEdit, TQ_SLOT(setEnabled(bool)));
+
+ connect(pixmapLogo, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(slotProcessURL(const TQString&)));
+
+ // -------------------------------------------------------------------------
+
+ connect(d->view, TQ_SIGNAL(signalSelected(CameraIconViewItem*, bool)),
+ this, TQ_SLOT(slotItemsSelected(CameraIconViewItem*, bool)));
+
+ connect(d->view, TQ_SIGNAL(signalFileView(CameraIconViewItem*)),
+ this, TQ_SLOT(slotFileView(CameraIconViewItem*)));
+
+ connect(d->view, TQ_SIGNAL(signalUpload(const KURL::List&)),
+ this, TQ_SLOT(slotUploadItems(const KURL::List&)));
+
+ connect(d->view, TQ_SIGNAL(signalDownload()),
+ this, TQ_SLOT(slotDownloadSelected()));
+
+ connect(d->view, TQ_SIGNAL(signalDownloadAndDelete()),
+ this, TQ_SLOT(slotDownloadAndDeleteSelected()));
+
+ connect(d->view, TQ_SIGNAL(signalDelete()),
+ this, TQ_SLOT(slotDeleteSelected()));
+
+ connect(d->view, TQ_SIGNAL(signalToggleLock()),
+ this, TQ_SLOT(slotToggleLock()));
+
+ connect(d->view, TQ_SIGNAL(signalNewSelection(bool)),
+ this, TQ_SLOT(slotNewSelection(bool)));
+
+ // -------------------------------------------------------------------------
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalFirstItem()),
+ this, TQ_SLOT(slotFirstItem()));
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalNextItem()),
+ this, TQ_SLOT(slotNextItem()));
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalPrevItem()),
+ this, TQ_SLOT(slotPrevItem()));
+
+ connect(d->rightSidebar, TQ_SIGNAL(signalLastItem()),
+ this, TQ_SLOT(slotLastItem()));
+
+ // -------------------------------------------------------------------------
+
+ connect(d->cancelBtn, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCancelButton()));
+
+ // -- Read settings & Check free space availability on album root path -----
+
+ readSettings();
+
+ // -- camera controller ----------------------------------------------------
+
+ d->controller = new CameraController(this, d->cameraTitle, model, port, path);
+
+ connect(d->controller, TQ_SIGNAL(signalConnected(bool)),
+ this, TQ_SLOT(slotConnected(bool)));
+
+ connect(d->controller, TQ_SIGNAL(signalInfoMsg(const TQString&)),
+ d->status, TQ_SLOT(setText(const TQString&)));
+
+ connect(d->controller, TQ_SIGNAL(signalErrorMsg(const TQString&)),
+ this, TQ_SLOT(slotErrorMsg(const TQString&)));
+
+ connect(d->controller, TQ_SIGNAL(signalCameraInformations(const TQString&, const TQString&, const TQString&)),
+ this, TQ_SLOT(slotCameraInformations(const TQString&, const TQString&, const TQString&)));
+
+ connect(d->controller, TQ_SIGNAL(signalBusy(bool)),
+ this, TQ_SLOT(slotBusy(bool)));
+
+ connect(d->controller, TQ_SIGNAL(signalFolderList(const TQStringList&)),
+ this, TQ_SLOT(slotFolderList(const TQStringList&)));
+
+ connect(d->controller, TQ_SIGNAL(signalFileList(const GPItemInfoList&)),
+ this, TQ_SLOT(slotFileList(const GPItemInfoList&)));
+
+ connect(d->controller, TQ_SIGNAL(signalThumbnail(const TQString&, const TQString&, const TQImage&)),
+ this, TQ_SLOT(slotThumbnail(const TQString&, const TQString&, const TQImage&)));
+
+ connect(d->controller, TQ_SIGNAL(signalDownloaded(const TQString&, const TQString&, int)),
+ this, TQ_SLOT(slotDownloaded(const TQString&, const TQString&, int)));
+
+ connect(d->controller, TQ_SIGNAL(signalSkipped(const TQString&, const TQString&)),
+ this, TQ_SLOT(slotSkipped(const TQString&, const TQString&)));
+
+ connect(d->controller, TQ_SIGNAL(signalDeleted(const TQString&, const TQString&, bool)),
+ this, TQ_SLOT(slotDeleted(const TQString&, const TQString&, bool)));
+
+ connect(d->controller, TQ_SIGNAL(signalLocked(const TQString&, const TQString&, bool)),
+ this, TQ_SLOT(slotLocked(const TQString&, const TQString&, bool)));
+
+ connect(d->controller, TQ_SIGNAL(signalExifFromFile(const TQString&, const TQString&)),
+ this, TQ_SLOT(slotExifFromFile(const TQString&, const TQString&)));
+
+ connect(d->controller, TQ_SIGNAL(signalExifData(const TQByteArray&)),
+ this, TQ_SLOT(slotExifFromData(const TQByteArray&)));
+
+ connect(d->controller, TQ_SIGNAL(signalUploaded(const GPItemInfo&)),
+ this, TQ_SLOT(slotUploaded(const GPItemInfo&)));
+
+ // -------------------------------------------------------------------------
+
+ d->view->setFocus();
+ TQTimer::singleShot(0, d->controller, TQ_SLOT(slotConnect()));
+}
+
+CameraUI::~CameraUI()
+{
+ delete d->rightSidebar;
+ delete d->controller;
+ delete d;
+}
+
+void CameraUI::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("Camera Settings");
+ d->advBox->setCurrentIndex(config->readNumEntry("Settings Tab", CameraUIPriv::RENAMEFILEPAGE));
+ d->autoRotateCheck->setChecked(config->readBoolEntry("AutoRotate", true));
+ d->autoAlbumDateCheck->setChecked(config->readBoolEntry("AutoAlbumDate", false));
+ d->autoAlbumExtCheck->setChecked(config->readBoolEntry("AutoAlbumExt", false));
+ d->fixDateTimeCheck->setChecked(config->readBoolEntry("FixDateTime", false));
+ d->setPhotographerId->setChecked(config->readBoolEntry("SetPhotographerId", false));
+ d->setCredits->setChecked(config->readBoolEntry("SetCredits", false));
+ d->convertJpegCheck->setChecked(config->readBoolEntry("ConvertJpeg", false));
+ d->losslessFormat->setCurrentItem(config->readNumEntry("LossLessFormat", 0)); // PNG by default
+ d->folderDateFormat->setCurrentItem(config->readNumEntry("FolderDateFormat", CameraUIPriv::IsoDateFormat));
+
+ d->view->setThumbnailSize(ThumbnailSize((ThumbnailSize::Size)config->readNumEntry("ThumbnailSize",
+ ThumbnailSize::Large)));
+
+ if(config->hasKey("Splitter Sizes"))
+ d->splitter->setSizes(config->readIntListEntry("Splitter Sizes"));
+
+ d->dateTimeEdit->setEnabled(d->fixDateTimeCheck->isChecked());
+ d->losslessFormat->setEnabled(convertLosslessJpegFiles());
+ d->formatLabel->setEnabled(convertLosslessJpegFiles());
+ d->folderDateFormat->setEnabled(d->autoAlbumDateCheck->isChecked());
+ d->folderDateLabel->setEnabled(d->autoAlbumDateCheck->isChecked());
+
+ resize(configDialogSize("Camera Settings"));
+}
+
+void CameraUI::saveSettings()
+{
+ saveDialogSize("Camera Settings");
+
+ TDEConfig* config = kapp->config();
+ config->setGroup("Camera Settings");
+ config->writeEntry("Settings Tab", d->advBox->currentIndex());
+ config->writeEntry("AutoRotate", d->autoRotateCheck->isChecked());
+ config->writeEntry("AutoAlbumDate", d->autoAlbumDateCheck->isChecked());
+ config->writeEntry("AutoAlbumExt", d->autoAlbumExtCheck->isChecked());
+ config->writeEntry("FixDateTime", d->fixDateTimeCheck->isChecked());
+ config->writeEntry("SetPhotographerId", d->setPhotographerId->isChecked());
+ config->writeEntry("SetCredits", d->setCredits->isChecked());
+ config->writeEntry("ConvertJpeg", convertLosslessJpegFiles());
+ config->writeEntry("LossLessFormat", d->losslessFormat->currentItem());
+ config->writeEntry("ThumbnailSize", d->view->thumbnailSize().size());
+ config->writeEntry("Splitter Sizes", d->splitter->sizes());
+ config->writeEntry("FolderDateFormat", d->folderDateFormat->currentItem());
+ config->sync();
+}
+
+void CameraUI::slotProcessURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+bool CameraUI::isBusy() const
+{
+ return d->busy;
+}
+
+bool CameraUI::isClosed() const
+{
+ return d->closed;
+}
+
+bool CameraUI::convertLosslessJpegFiles() const
+{
+ return d->convertJpegCheck->isChecked();
+}
+
+bool CameraUI::autoRotateJpegFiles() const
+{
+ return d->autoRotateCheck->isChecked();
+}
+
+TQString CameraUI::losslessFormat()
+{
+ return d->losslessFormat->currentText();
+}
+
+TQString CameraUI::cameraTitle() const
+{
+ return d->cameraTitle;
+}
+
+void CameraUI::slotCancelButton()
+{
+ d->status->setText(i18n("Cancelling current operation, please wait..."));
+ d->progress->hide();
+ TQTimer::singleShot(0, d->controller, TQ_SLOT(slotCancel()));
+ d->currentlyDeleting.clear();
+}
+
+void CameraUI::closeEvent(TQCloseEvent* e)
+{
+ if (dialogClosed())
+ e->accept();
+ else
+ e->ignore();
+}
+
+void CameraUI::slotClose()
+{
+ if (dialogClosed())
+ reject();
+}
+
+bool CameraUI::dialogClosed()
+{
+ if (d->closed)
+ return true;
+
+ if (isBusy())
+ {
+ if (KMessageBox::questionYesNo(this,
+ i18n("Do you want to close the dialog "
+ "and cancel the current operation?"))
+ == KMessageBox::No)
+ return false;
+ }
+
+ d->status->setText(i18n("Disconnecting from camera, please wait..."));
+ d->progress->hide();
+
+ if (isBusy())
+ {
+ d->controller->slotCancel();
+ // will be read in slotBusy later and finishDialog
+ // will be called only when everything is finished
+ d->closed = true;
+ }
+ else
+ {
+ d->closed = true;
+ finishDialog();
+ }
+
+ return true;
+}
+
+void CameraUI::finishDialog()
+{
+ // Look if an item have been downloaded to computer during camera gui session.
+ // If yes, update the lastAccess date property of camera in digiKam camera list.
+
+ if (d->view->itemsDownloaded() > 0)
+ {
+ CameraList* clist = CameraList::instance();
+ if (clist)
+ clist->changeCameraAccessTime(d->cameraTitle, TQDateTime::TQDateTime::currentDateTime());
+ }
+
+ // When a directory is created, a watch is put on it to spot new files
+ // but it can occur that the file is copied there before the watch is
+ // completely setup. That is why as an extra safeguard run scanlib
+ // over the folders we used. Bug: 119201
+
+ d->status->setText(i18n("Scanning for new files, please wait..."));
+ ScanLib sLib;
+ for (TQStringList::iterator it = d->foldersToScan.begin();
+ it != d->foldersToScan.end(); ++it)
+ {
+ //DDebug() << "Scanning " << (*it) << endl;
+ sLib.findMissingItems( (*it) );
+ }
+
+ // Never call finalScan after deleteLater() - ScanLib will call processEvent(),
+ // and the delete event may be executed!
+ deleteLater();
+
+ if(!d->lastDestURL.isEmpty())
+ emit signalLastDestination(d->lastDestURL);
+
+ saveSettings();
+}
+
+void CameraUI::slotBusy(bool val)
+{
+ if (!val)
+ {
+ if (!d->busy)
+ return;
+
+ d->busy = false;
+ d->cancelBtn->setEnabled(false);
+ d->view->viewport()->setEnabled(true);
+
+ d->advBox->setEnabled(true);
+ // B.K.O #127614: The Focus need to be restored in custom prefix widget.
+ //commenting this out again: If we do not disable, no need to restore focus
+ //d->renameCustomizer->restoreFocus();
+
+ enableButton(User3, true);
+ enableButton(User2, true);
+ enableButton(User1, true);
+ d->helpMenu->menu()->setItemEnabled(CAMERA_INFO_MENU_ID, true);
+
+ d->anim->stop();
+ d->status->setText(i18n("Ready"));
+ d->progress->hide();
+
+ // like WDestructiveClose, but after camera controller operation has safely finished
+ if (d->closed)
+ {
+ finishDialog();
+ }
+ }
+ else
+ {
+ if (d->busy)
+ return;
+
+ if (!d->anim->running())
+ d->anim->start();
+
+ d->busy = true;
+ d->cancelBtn->setEnabled(true);
+
+ // Has camera icon view item selection is used to control download post processing,
+ // all selection actions are disable when camera interface is busy.
+ d->view->viewport()->setEnabled(false);
+
+ // Settings tab is disabled in slotDownload, selectively when downloading
+ // Fast dis/enabling would create the impression of flicker, e.g. when retrieving EXIF from camera
+ //d->advBox->setEnabled(false);
+
+ enableButton(User3, false);
+ enableButton(User2, false);
+ enableButton(User1, false);
+ d->helpMenu->menu()->setItemEnabled(CAMERA_INFO_MENU_ID, false);
+ }
+}
+
+void CameraUI::slotIncreaseThumbSize()
+{
+ int thumbSize = d->view->thumbnailSize().size();
+ if (thumbSize >= ThumbnailSize::Huge) return;
+
+ thumbSize += ThumbnailSize::Step;
+
+ if (thumbSize >= ThumbnailSize::Huge)
+ {
+ d->imageMenu->setItemEnabled(4, false);
+ }
+ d->imageMenu->setItemEnabled(5, true);
+
+ d->view->setThumbnailSize(thumbSize);
+}
+
+void CameraUI::slotDecreaseThumbSize()
+{
+ int thumbSize = d->view->thumbnailSize().size();
+ if (thumbSize <= ThumbnailSize::Small) return;
+
+ thumbSize -= ThumbnailSize::Step;
+
+ if (thumbSize <= ThumbnailSize::Small)
+ {
+ d->imageMenu->setItemEnabled(5, false);
+ }
+ d->imageMenu->setItemEnabled(4, true);
+
+ d->view->setThumbnailSize(thumbSize);
+}
+
+void CameraUI::slotConnected(bool val)
+{
+ if (!val)
+ {
+ if (KMessageBox::warningYesNo(this,
+ i18n("Failed to connect to the camera. "
+ "Please make sure it is connected "
+ "properly and turned on. "
+ "Would you like to try again?"),
+ i18n("Connection Failed"),
+ i18n("Retry"),
+ i18n("Abort"))
+ == KMessageBox::Yes)
+ TQTimer::singleShot(0, d->controller, TQ_SLOT(slotConnect()));
+ else
+ close();
+ }
+ else
+ {
+ d->controller->listFolders();
+ }
+}
+
+void CameraUI::slotFolderList(const TQStringList& folderList)
+{
+ if (d->closed)
+ return;
+
+ d->progress->setProgress(0);
+ d->progress->setTotalSteps(0);
+ d->progress->show();
+
+ d->cameraFolderList = folderList;
+ for (TQStringList::const_iterator it = folderList.begin();
+ it != folderList.end(); ++it)
+ {
+ d->controller->listFiles(*it);
+ }
+}
+
+void CameraUI::slotFileList(const GPItemInfoList& fileList)
+{
+ if (d->closed)
+ return;
+
+ if (fileList.empty())
+ return;
+
+ kdDebug() << fileList.count() << endl;
+
+ // We sort the map by time stamp
+ // and we remove internal camera files which are not image/video/sounds.
+ TQStringList fileNames, fileExts;
+ TQFileInfo info;
+
+ // JVC camera (see B.K.O #133185).
+ fileNames.append("mgr_data");
+ fileNames.append("pgr_mgr");
+
+ // HP Photosmart camera (see B.K.O #156338).
+ fileExts.append("dsp");
+
+ // Minolta camera in PTP mode
+ fileExts.append("dps");
+
+ // We sort the map by time stamp.
+ GPItemInfoList sfileList;
+ GPItemInfoList::const_iterator it;
+ GPItemInfoList::iterator it2;
+
+ for(it = fileList.begin() ; it != fileList.end() ; ++it)
+ {
+ info.setFile((*it).name);
+ if (!fileNames.contains(info.fileName().lower()) &&
+ !fileExts.contains(info.extension(false).lower()))
+ {
+ kdDebug() << info.fileName() << " : " << (*it).mtime << endl;
+
+ for(it2 = sfileList.begin() ; it2 != sfileList.end() ; ++it2)
+ if ((*it2).mtime <= (*it).mtime) break;
+
+ sfileList.insert(it2, *it);
+ }
+ }
+
+ if (sfileList.empty())
+ return;
+
+ kdDebug() << sfileList.count() << endl;
+
+ GPItemInfoList::const_iterator it3 = sfileList.begin();
+
+ do
+ {
+ GPItemInfo item = *it3;
+
+ if (item.mtime > (time_t)d->lastAccess.toTime_t() && item.downloaded == GPItemInfo::DownloadUnknow)
+ item.downloaded = GPItemInfo::NewPicture;
+
+ d->view->addItem(item);
+ d->controller->getThumbnail(item.folder, item.name);
+ ++it3;
+ }
+ while(it3 != sfileList.end());
+
+ d->progress->setTotalSteps(d->progress->totalSteps() + fileList.count());
+}
+
+void CameraUI::slotThumbnail(const TQString& folder, const TQString& file,
+ const TQImage& thumbnail)
+{
+ d->view->setThumbnail(folder, file, thumbnail);
+ int curr = d->progress->progress();
+ d->progress->setProgress(curr+1);
+}
+
+void CameraUI::slotInformations()
+{
+ if (d->busy)
+ return;
+
+ d->controller->getCameraInformations();
+}
+
+void CameraUI::slotCameraInformations(const TQString& summary, const TQString& manual, const TQString& about)
+{
+ CameraInfoDialog *infoDlg = new CameraInfoDialog(this, summary, manual, about);
+ infoDlg->show();
+}
+
+void CameraUI::slotErrorMsg(const TQString& msg)
+{
+ KMessageBox::error(this, msg);
+}
+
+void CameraUI::slotUpload()
+{
+ if (d->busy)
+ return;
+
+ TQString fileformats;
+
+ TQStringList patternList = TQStringList::split('\n', KImageIO::pattern(KImageIO::Reading));
+
+ // All Images from list must been always the first entry given by KDE API
+ TQString allPictures = patternList[0];
+
+ // Add RAW file format to All Images" type mime and remplace current.
+#if KDCRAW_VERSION < 0x000106
+ allPictures.insert(allPictures.find("|"), TQString(KDcrawIface::DcrawBinary::instance()->rawFiles()));
+#else
+ allPictures.insert(allPictures.find("|"), TQString(KDcrawIface::KDcraw::rawFiles()));
+#endif
+ patternList.remove(patternList[0]);
+ patternList.prepend(allPictures);
+
+ // Added RAW file formats supported by dcraw program like a type mime.
+ // Nota: we cannot use here "image/x-raw" type mime from KDE because it uncomplete
+ // or unavailable(dcraw_0)(see file #121242 in B.K.O).
+#if KDCRAW_VERSION < 0x000106
+ patternList.append(TQString("\n%1|Camera RAW files").arg(TQString(KDcrawIface::DcrawBinary::instance()->rawFiles())));
+#else
+ patternList.append(TQString("\n%1|Camera RAW files").arg(TQString(KDcrawIface::KDcraw::rawFiles())));
+#endif
+
+ fileformats = patternList.join("\n");
+
+ DDebug () << "fileformats=" << fileformats << endl;
+
+ KURL::List urls = KFileDialog::getOpenURLs(AlbumManager::instance()->getLibraryPath(),
+ fileformats, this, i18n("Select Image to Upload"));
+ if (!urls.isEmpty())
+ slotUploadItems(urls);
+}
+
+void CameraUI::slotUploadItems(const KURL::List& urls)
+{
+ if (d->busy)
+ return;
+
+ if (urls.isEmpty())
+ return;
+
+ CameraFolderDialog dlg(this, d->view, d->cameraFolderList, d->controller->getCameraTitle(),
+ d->controller->getCameraPath());
+
+ if (dlg.exec() != TQDialog::Accepted)
+ return;
+
+ TQString cameraFolder = dlg.selectedFolderPath();
+
+ for (KURL::List::const_iterator it = urls.begin() ; it != urls.end() ; ++it)
+ {
+ TQFileInfo fi((*it).path());
+ if (!fi.exists()) continue;
+ if (fi.isDir()) continue;
+
+ TQString ext = TQString(".") + fi.extension();
+ TQString name = fi.fileName();
+ name.truncate(fi.fileName().length() - ext.length());
+
+ bool ok;
+
+ while (d->view->findItem(cameraFolder, name + ext))
+ {
+ TQString msg(i18n("Camera Folder <b>%1</b> already contains item <b>%2</b><br>"
+ "Please enter a new file name (without extension):")
+ .arg(cameraFolder).arg(fi.fileName()));
+#if KDE_IS_VERSION(3,2,0)
+ name = KInputDialog::getText(i18n("File already exists"), msg, name, &ok, this);
+
+#else
+ name = KLineEditDlg::getText(i18n("File already exists"), msg, name, &ok, this);
+#endif
+ if (!ok)
+ return;
+ }
+
+ d->controller->upload(fi, name + ext, cameraFolder);
+ }
+}
+
+void CameraUI::slotUploaded(const GPItemInfo& itemInfo)
+{
+ if (d->closed)
+ return;
+
+ d->view->addItem(itemInfo);
+ d->controller->getThumbnail(itemInfo.folder, itemInfo.name);
+}
+
+void CameraUI::slotDownloadSelected()
+{
+ slotDownload(true, false);
+}
+
+void CameraUI::slotDownloadAndDeleteSelected()
+{
+ slotDownload(true, true);
+}
+
+void CameraUI::slotDownloadAll()
+{
+ slotDownload(false, false);
+}
+
+void CameraUI::slotDownloadAndDeleteAll()
+{
+ slotDownload(false, true);
+}
+
+void CameraUI::slotDownload(bool onlySelected, bool deleteAfter, Album *album)
+{
+ // See B.K.O #143934: force to select all items to prevent problem
+ // when !renameCustomizer->useDefault() ==> iconItem->getDownloadName()
+ // can return an empty string in this case because it depends on selection.
+ if (!onlySelected)
+ d->view->slotSelectAll();
+
+ // See B.K.O #139519: Always check free space available before to
+ // download items selection from camera.
+ unsigned long fSize = 0;
+ unsigned long dSize = 0;
+ d->view->itemsSelectionSizeInfo(fSize, dSize);
+ if (d->freeSpaceWidget->isValid() && (dSize >= d->freeSpaceWidget->kBAvail()))
+ {
+ KMessageBox::error(this, i18n("There is no enough free space on Album Library Path "
+ "to download and process selected pictures from camera.\n\n"
+ "Estimated space require: %1\n"
+ "Available free space: %2")
+ .arg(TDEIO::convertSizeFromKB(dSize))
+ .arg(TDEIO::convertSizeFromKB(d->freeSpaceWidget->kBAvail())));
+ return;
+ }
+
+ TQString newDirName;
+ IconItem* firstItem = d->view->firstItem();
+ if (firstItem)
+ {
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(firstItem);
+
+ TQDateTime dateTime;
+ dateTime.setTime_t(iconItem->itemInfo()->mtime);
+
+ switch(d->folderDateFormat->currentItem())
+ {
+ case CameraUIPriv::TextDateFormat:
+ newDirName = dateTime.date().toString(TQt::TextDate);
+ break;
+ case CameraUIPriv::LocalDateFormat:
+ newDirName = dateTime.date().toString(TQt::LocalDate);
+ break;
+ default: // IsoDateFormat
+ newDirName = dateTime.date().toString(TQt::ISODate);
+ break;
+ }
+ }
+
+ // -- Get the destination album from digiKam library if necessary ---------------
+
+ if (!album)
+ {
+ AlbumManager* man = AlbumManager::instance();
+ album = man->currentAlbum();
+
+ if (album && album->type() != Album::PHYSICAL)
+ album = 0;
+
+ TQString header(i18n("<p>Please select the destination album from the digiKam library to "
+ "import the camera pictures into.</p>"));
+
+ album = AlbumSelectDialog::selectAlbum(this, (PAlbum*)album, header, newDirName,
+ d->autoAlbumDateCheck->isChecked());
+
+ if (!album) return;
+ }
+
+ PAlbum *pAlbum = dynamic_cast<PAlbum*>(album);
+ if (!pAlbum) return;
+
+ // -- Prepare downloading of camera items ------------------------
+
+ KURL url;
+ url.setPath(pAlbum->folderPath());
+
+ d->controller->downloadPrep();
+
+ DownloadSettingsContainer downloadSettings;
+ TQString downloadName;
+ time_t mtime;
+ int total = 0;
+
+ downloadSettings.autoRotate = d->autoRotateCheck->isChecked();
+ downloadSettings.fixDateTime = d->fixDateTimeCheck->isChecked();
+ downloadSettings.newDateTime = d->dateTimeEdit->dateTime();
+ downloadSettings.setPhotographerId = d->setPhotographerId->isChecked();
+ downloadSettings.setCredits = d->setCredits->isChecked();
+ downloadSettings.convertJpeg = convertLosslessJpegFiles();
+ downloadSettings.losslessFormat = losslessFormat();
+
+ AlbumSettings* settings = AlbumSettings::instance();
+ if (settings)
+ {
+ downloadSettings.author = settings->getIptcAuthor();
+ downloadSettings.authorTitle = settings->getIptcAuthorTitle();
+ downloadSettings.credit = settings->getIptcCredit();
+ downloadSettings.source = settings->getIptcSource();
+ downloadSettings.copyright = settings->getIptcCopyright();
+ }
+
+ // -- Download camera items -------------------------------
+ // Since we show camera items in reverse order, downloading need to be done also in reverse order.
+
+ for (IconItem* item = d->view->lastItem(); item;
+ item = item->prevItem())
+ {
+ if (onlySelected && !(item->isSelected()))
+ continue;
+
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(item);
+ downloadSettings.folder = iconItem->itemInfo()->folder;
+ downloadSettings.file = iconItem->itemInfo()->name;
+ downloadName = iconItem->getDownloadName();
+ mtime = iconItem->itemInfo()->mtime;
+
+ KURL u(url);
+ TQString errMsg;
+ TQDateTime dateTime;
+ dateTime.setTime_t(mtime);
+
+ // Auto sub-albums creation based on file date.
+
+ if (d->autoAlbumDateCheck->isChecked())
+ {
+ TQString dirName;
+
+ switch(d->folderDateFormat->currentItem())
+ {
+ case CameraUIPriv::TextDateFormat:
+ dirName = dateTime.date().toString(TQt::TextDate);
+ break;
+ case CameraUIPriv::LocalDateFormat:
+ dirName = dateTime.date().toString(TQt::LocalDate);
+ break;
+ default: // IsoDateFormat
+ dirName = dateTime.date().toString(TQt::ISODate);
+ break;
+ }
+ // See B.K.O #136927 : we need to support file system which do not
+ // handle upper case properly.
+ dirName = dirName.lower();
+ if (!createAutoAlbum(url, dirName, dateTime.date(), errMsg))
+ {
+ KMessageBox::error(this, errMsg);
+ return;
+ }
+
+ u.addPath(dirName);
+ }
+
+ // Auto sub-albums creation based on file extensions.
+
+ if (d->autoAlbumExtCheck->isChecked())
+ {
+ // We use the target file name to compute sub-albums name to take a care about
+ // convertion on the fly option.
+ TQFileInfo fi(downloadName);
+
+ TQString subAlbum = fi.extension(false).upper();
+ if (fi.extension(false).upper() == TQString("JPEG") ||
+ fi.extension(false).upper() == TQString("JPE"))
+ subAlbum = TQString("JPG");
+ if (fi.extension(false).upper() == TQString("TIFF"))
+ subAlbum = TQString("TIF");
+ if (fi.extension(false).upper() == TQString("MPEG") ||
+ fi.extension(false).upper() == TQString("MPE") ||
+ fi.extension(false).upper() == TQString("MPO"))
+ subAlbum = TQString("MPG");
+
+ // See B.K.O #136927 : we need to support file system which do not
+ // handle upper case properly.
+ subAlbum = subAlbum.lower();
+ if (!createAutoAlbum(u, subAlbum, dateTime.date(), errMsg))
+ {
+ KMessageBox::error(this, errMsg);
+ return;
+ }
+
+ u.addPath(subAlbum);
+ }
+
+ d->foldersToScan.append(u.path());
+ u.addPath(downloadName.isEmpty() ? downloadSettings.file : downloadName);
+
+ downloadSettings.dest = u.path();
+
+ d->controller->download(downloadSettings);
+ addFileExtension(TQFileInfo(u.path()).extension(false));
+ total++;
+ }
+
+ if (total <= 0)
+ return;
+
+ d->lastDestURL = url;
+ d->progress->setProgress(0);
+ d->progress->setTotalSteps(total);
+ d->progress->show();
+
+ // disable settings tab here instead of slotBusy:
+ // Only needs to be disabled while downloading
+ d->advBox->setEnabled(false);
+
+ d->deleteAfter = deleteAfter;
+}
+
+void CameraUI::slotDownloaded(const TQString& folder, const TQString& file, int status)
+{
+ CameraIconViewItem* iconItem = d->view->findItem(folder, file);
+ if (iconItem)
+ iconItem->setDownloaded(status);
+
+ if (status == GPItemInfo::DownloadedYes || status == GPItemInfo::DownloadFailed)
+ {
+ int curr = d->progress->progress();
+ d->progress->setProgress(curr+1);
+ }
+
+ // Download all items is complete.
+ if (d->progress->progress() == d->progress->totalSteps())
+ {
+ if (d->deleteAfter)
+ deleteItems(true, true);
+ }
+}
+
+void CameraUI::slotSkipped(const TQString& folder, const TQString& file)
+{
+ CameraIconViewItem* iconItem = d->view->findItem(folder, file);
+ if (iconItem)
+ iconItem->setDownloaded(GPItemInfo::DownloadedNo);
+
+ int curr = d->progress->progress();
+ d->progress->setProgress(curr+1);
+}
+
+void CameraUI::slotToggleLock()
+{
+ int count = 0;
+ for (IconItem* item = d->view->firstItem(); item;
+ item = item->nextItem())
+ {
+ CameraIconViewItem* iconItem = static_cast<CameraIconViewItem*>(item);
+ if (iconItem->isSelected())
+ {
+ TQString folder = iconItem->itemInfo()->folder;
+ TQString file = iconItem->itemInfo()->name;
+ int writePerm = iconItem->itemInfo()->writePermissions;
+ bool lock = true;
+
+ // If item is currently locked, unlock it.
+ if (writePerm == 0)
+ lock = false;
+
+ d->controller->lockFile(folder, file, lock);
+ count++;
+ }
+ }
+
+ if (count > 0)
+ {
+ d->progress->setProgress(0);
+ d->progress->setTotalSteps(count);
+ d->progress->show();
+ }
+}
+
+void CameraUI::slotLocked(const TQString& folder, const TQString& file, bool status)
+{
+ if (status)
+ {
+ CameraIconViewItem* iconItem = d->view->findItem(folder, file);
+ if (iconItem)
+ {
+ iconItem->toggleLock();
+ //if (iconItem->isSelected())
+ // slotItemsSelected(iconItem, true);
+ }
+ }
+
+ int curr = d->progress->progress();
+ d->progress->setProgress(curr+1);
+}
+
+void CameraUI::checkItem4Deletion(CameraIconViewItem* iconItem, TQStringList& folders, TQStringList& files,
+ TQStringList& deleteList, TQStringList& lockedList)
+{
+ if (iconItem->itemInfo()->writePermissions != 0) // Item not locked ?
+ {
+ TQString folder = iconItem->itemInfo()->folder;
+ TQString file = iconItem->itemInfo()->name;
+ folders.append(folder);
+ files.append(file);
+ deleteList.append(folder + TQString("/") + file);
+ }
+ else
+ {
+ lockedList.append(iconItem->itemInfo()->name);
+ }
+}
+
+void CameraUI::deleteItems(bool onlySelected, bool onlyDownloaded)
+{
+ TQStringList folders;
+ TQStringList files;
+ TQStringList deleteList;
+ TQStringList lockedList;
+
+ for (IconItem* item = d->view->firstItem(); item; item = item->nextItem())
+ {
+ CameraIconViewItem* iconItem = dynamic_cast<CameraIconViewItem*>(item);
+ if (iconItem)
+ {
+ if (onlySelected)
+ {
+ if (iconItem->isSelected())
+ {
+ if (onlyDownloaded)
+ {
+ if (iconItem->isDownloaded())
+ checkItem4Deletion(iconItem, folders, files, deleteList, lockedList);
+ }
+ else
+ {
+ checkItem4Deletion(iconItem, folders, files, deleteList, lockedList);
+ }
+ }
+ }
+ else // All items
+ {
+ if (onlyDownloaded)
+ {
+ if (iconItem->isDownloaded())
+ checkItem4Deletion(iconItem, folders, files, deleteList, lockedList);
+ }
+ else
+ {
+ checkItem4Deletion(iconItem, folders, files, deleteList, lockedList);
+ }
+ }
+ }
+ }
+
+ // If we want to delete some locked files, just give a feedback to user.
+ if (!lockedList.isEmpty())
+ {
+ TQString infoMsg(i18n("The items listed below are locked by camera (read-only). "
+ "These items will not be deleted. If you really want to delete these items, "
+ "please unlock them and try again."));
+ KMessageBox::informationList(this, infoMsg, lockedList, i18n("Information"));
+ }
+
+ if (folders.isEmpty())
+ return;
+
+ TQString warnMsg(i18n("About to delete this image. "
+ "Deleted files are unrecoverable. "
+ "Are you sure?",
+ "About to delete these %n images. "
+ "Deleted files are unrecoverable. "
+ "Are you sure?",
+ deleteList.count()));
+ if (KMessageBox::warningContinueCancelList(this, warnMsg,
+ deleteList,
+ i18n("Warning"),
+ i18n("Delete"))
+ == KMessageBox::Continue)
+ {
+ TQStringList::iterator itFolder = folders.begin();
+ TQStringList::iterator itFile = files.begin();
+
+ d->progress->setProgress(0);
+ d->progress->setTotalSteps(deleteList.count());
+ d->progress->show();
+
+ for ( ; itFolder != folders.end(); ++itFolder, ++itFile)
+ {
+ d->controller->deleteFile(*itFolder, *itFile);
+ // the currentlyDeleting list is used to prevent loading items which
+ // will immenently be deleted into the sidebar and wasting time
+ d->currentlyDeleting.append(*itFolder + *itFile);
+ }
+ }
+}
+
+void CameraUI::slotDeleteSelected()
+{
+ deleteItems(true, false);
+}
+
+void CameraUI::slotDeleteAll()
+{
+ deleteItems(false, false);
+}
+
+void CameraUI::slotDeleted(const TQString& folder, const TQString& file, bool status)
+{
+ if (status)
+ {
+ d->view->removeItem(folder, file);
+ // do this after removeItem, which will signal to slotItemsSelected, which checks for the list
+ d->currentlyDeleting.remove(folder + file);
+ }
+
+ int curr = d->progress->progress();
+ d->progress->setProgress(curr+1);
+}
+
+void CameraUI::slotFileView(CameraIconViewItem* item)
+{
+ d->controller->openFile(item->itemInfo()->folder, item->itemInfo()->name);
+}
+
+void CameraUI::slotExifFromFile(const TQString& folder, const TQString& file)
+{
+ CameraIconViewItem* item = d->view->findItem(folder, file);
+ if (!item)
+ return;
+
+ d->rightSidebar->itemChanged(item->itemInfo(), folder + TQString("/") + file,
+ TQByteArray(), d->view, item);
+}
+
+void CameraUI::slotExifFromData(const TQByteArray& exifData)
+{
+ CameraIconViewItem* item = dynamic_cast<CameraIconViewItem*>(d->view->currentItem());
+
+ if (!item)
+ return;
+
+ KURL url(item->itemInfo()->folder + '/' + item->itemInfo()->name);
+
+ // Sometimes, GPhoto2 drivers return complete APP1 JFIF section. Exiv2 cannot
+ // decode (yet) exif metadata from APP1. We will find Exif header to get data at this place
+ // to please with Exiv2...
+
+ DDebug() << "Size of Exif metadata from camera = " << exifData.size() << endl;
+ char exifHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
+
+ if (!exifData.isEmpty())
+ {
+ int i = exifData.find(*exifHeader);
+ if (i != -1)
+ {
+ DDebug() << "Exif header found at position " << i << endl;
+ i = i + sizeof(exifHeader);
+ TQByteArray data(exifData.size()-i);
+ memcpy(data.data(), exifData.data()+i, data.size());
+ d->rightSidebar->itemChanged(item->itemInfo(), url, data, d->view, item);
+ return;
+ }
+ }
+
+ d->rightSidebar->itemChanged(item->itemInfo(), url, exifData, d->view, item);
+}
+
+void CameraUI::slotNewSelection(bool hasSelection)
+{
+ if (!d->renameCustomizer->useDefault())
+ {
+ d->downloadMenu->setItemEnabled(0, hasSelection);
+ d->downloadMenu->setItemEnabled(2, hasSelection);
+ }
+ else
+ {
+ d->downloadMenu->setItemEnabled(0, hasSelection);
+ d->downloadMenu->setItemEnabled(2, hasSelection);
+ }
+
+ unsigned long fSize = 0;
+ unsigned long dSize = 0;
+ d->view->itemsSelectionSizeInfo(fSize, dSize);
+ d->freeSpaceWidget->setEstimatedDSizeKb(dSize);
+}
+
+void CameraUI::slotItemsSelected(CameraIconViewItem* item, bool selected)
+{
+ d->downloadMenu->setItemEnabled(0, selected);
+ d->downloadMenu->setItemEnabled(2, selected);
+ d->deleteMenu->setItemEnabled(0, selected);
+
+ if (selected)
+ {
+ // if selected item is in the list of item which will be deleted, set no current item
+ if (d->currentlyDeleting.find(item->itemInfo()->folder + item->itemInfo()->name)
+ == d->currentlyDeleting.end())
+ {
+ KURL url(item->itemInfo()->folder + '/' + item->itemInfo()->name);
+ d->rightSidebar->itemChanged(item->itemInfo(), url, TQByteArray(), d->view, item);
+ d->controller->getExif(item->itemInfo()->folder, item->itemInfo()->name);
+ }
+ else
+ {
+ d->rightSidebar->slotNoCurrentItem();
+ }
+ }
+ else
+ d->rightSidebar->slotNoCurrentItem();
+}
+
+bool CameraUI::createAutoAlbum(const KURL& parentURL, const TQString& sub,
+ const TQDate& date, TQString& errMsg)
+{
+ KURL u(parentURL);
+ u.addPath(sub);
+
+ // first stat to see if the album exists
+ TQFileInfo info(u.path());
+ if (info.exists())
+ {
+ // now check if its really a directory
+ if (info.isDir())
+ return true;
+ else
+ {
+ errMsg = i18n("A file with same name (%1) exists in folder %2")
+ .arg(sub)
+ .arg(parentURL.path());
+ return false;
+ }
+ }
+
+ // looks like the directory does not exist, try to create it
+
+ AlbumManager* aman = AlbumManager::instance();
+ PAlbum* parent = aman->findPAlbum(parentURL);
+ if (!parent)
+ {
+ errMsg = i18n("Failed to find Album for path '%1'")
+ .arg(parentURL.path());
+ return false;
+ }
+
+ return aman->createPAlbum(parent, sub, TQString(""), date, TQString(""), errMsg);
+}
+
+void CameraUI::addFileExtension(const TQString& ext)
+{
+ AlbumSettings* settings = AlbumSettings::instance();
+ if (!settings)
+ return;
+
+ if (settings->getImageFileFilter().upper().contains(ext.upper()) ||
+ settings->getMovieFileFilter().upper().contains(ext.upper()) ||
+ settings->getAudioFileFilter().upper().contains(ext.upper()) ||
+ settings->getRawFileFilter().upper().contains(ext.upper()))
+ return;
+
+ settings->setImageFileFilter(settings->getImageFileFilter() + TQString(" *.") + ext);
+ emit signalAlbumSettingsChanged();
+}
+
+void CameraUI::slotFirstItem()
+{
+ CameraIconViewItem *currItem = dynamic_cast<CameraIconViewItem*>(d->view->firstItem());
+ d->view->clearSelection();
+ d->view->updateContents();
+ if (currItem)
+ d->view->setCurrentItem(currItem);
+}
+
+void CameraUI::slotPrevItem()
+{
+ CameraIconViewItem *currItem = dynamic_cast<CameraIconViewItem*>(d->view->currentItem());
+ d->view->clearSelection();
+ d->view->updateContents();
+ if (currItem)
+ d->view->setCurrentItem(currItem->prevItem());
+}
+
+void CameraUI::slotNextItem()
+{
+ CameraIconViewItem *currItem = dynamic_cast<CameraIconViewItem*>(d->view->currentItem());
+ d->view->clearSelection();
+ d->view->updateContents();
+ if (currItem)
+ d->view->setCurrentItem(currItem->nextItem());
+}
+
+void CameraUI::slotLastItem(void)
+{
+ CameraIconViewItem *currItem = dynamic_cast<CameraIconViewItem*>(d->view->lastItem());
+ d->view->clearSelection();
+ d->view->updateContents();
+ if (currItem)
+ d->view->setCurrentItem(currItem);
+}
+
+// Backport KDialog::keyPressEvent() implementation from KDELibs to ignore Enter/Return Key events
+// to prevent any conflicts between dialog keys events and SpinBox keys events.
+
+void CameraUI::keyPressEvent(TQKeyEvent *e)
+{
+ if ( e->state() == 0 )
+ {
+ switch ( e->key() )
+ {
+ case Key_Escape:
+ e->accept();
+ reject();
+ break;
+ case Key_Enter:
+ case Key_Return:
+ e->ignore();
+ break;
+ default:
+ e->ignore();
+ return;
+ }
+ }
+ else
+ {
+ // accept the dialog when Ctrl-Return is pressed
+ if ( e->state() == ControlButton &&
+ (e->key() == Key_Return || e->key() == Key_Enter) )
+ {
+ e->accept();
+ accept();
+ }
+ else
+ {
+ e->ignore();
+ }
+ }
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/cameraui.h b/src/utilities/cameragui/cameraui.h
new file mode 100644
index 00000000..df9c7885
--- /dev/null
+++ b/src/utilities/cameragui/cameraui.h
@@ -0,0 +1,155 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-16
+ * Description : Camera interface dialog
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef CAMERAUI_H
+#define CAMERAUI_H
+
+// TQt includes.
+
+#include <tqdatetime.h>
+#include <tqstring.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "gpiteminfo.h"
+
+namespace Digikam
+{
+
+class Album;
+class CameraIconViewItem;
+class CameraUIPriv;
+
+class CameraUI : public KDialogBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ CameraUI(TQWidget* parent, const TQString& cameraTitle,
+ const TQString& model, const TQString& port,
+ const TQString& path, const TQDateTime lastAccess);
+ ~CameraUI();
+
+ bool isBusy() const;
+ bool isClosed() const;
+
+ bool autoRotateJpegFiles() const;
+
+ /** Get status of JPEG conversion files to lossless format during download.*/
+ bool convertLosslessJpegFiles() const;
+ TQString losslessFormat();
+
+ TQString cameraTitle() const;
+
+signals:
+
+ void signalLastDestination(const KURL&);
+ void signalAlbumSettingsChanged();
+
+public slots:
+
+ void slotDownload(bool onlySelected, bool deleteAfter, Album *album=0);
+
+protected:
+
+ void closeEvent(TQCloseEvent* e);
+ void keyPressEvent(TQKeyEvent *e);
+
+private:
+
+ void readSettings();
+ void saveSettings();
+ bool dialogClosed();
+ bool createAutoAlbum(const KURL& parentURL, const TQString& sub,
+ const TQDate& date, TQString& errMsg);
+ void addFileExtension(const TQString& ext);
+ void finishDialog();
+ void deleteItems(bool onlySelected, bool onlyDownloaded);
+ void checkItem4Deletion(CameraIconViewItem* iconItem, TQStringList& folders, TQStringList& files,
+ TQStringList& deleteList, TQStringList& lockedList);
+
+private slots:
+
+ void slotClose();
+ void slotCancelButton();
+ void slotProcessURL(const TQString& url);
+
+ void slotConnected(bool val);
+ void slotBusy(bool val);
+ void slotErrorMsg(const TQString& msg);
+ void slotInformations();
+ void slotCameraInformations(const TQString&, const TQString&, const TQString&);
+
+ void slotFolderList(const TQStringList& folderList);
+ void slotFileList(const GPItemInfoList& fileList);
+ void slotThumbnail(const TQString&, const TQString&, const TQImage&);
+
+ void slotIncreaseThumbSize();
+ void slotDecreaseThumbSize();
+
+ void slotUpload();
+ void slotUploadItems(const KURL::List&);
+ void slotDownloadSelected();
+ void slotDownloadAll();
+ void slotDeleteSelected();
+ void slotDownloadAndDeleteSelected();
+ void slotDeleteAll();
+ void slotDownloadAndDeleteAll();
+ void slotToggleLock();
+
+ void slotFileView(CameraIconViewItem* item);
+
+ void slotUploaded(const GPItemInfo&);
+ void slotDownloaded(const TQString&, const TQString&, int);
+ void slotSkipped(const TQString&, const TQString&);
+ void slotDeleted(const TQString&, const TQString&, bool);
+ void slotLocked(const TQString&, const TQString&, bool);
+
+ void slotNewSelection(bool);
+ void slotItemsSelected(CameraIconViewItem* item, bool selected);
+
+ void slotExifFromFile(const TQString& folder, const TQString& file);
+ void slotExifFromData(const TQByteArray& exifData);
+
+ void slotFirstItem(void);
+ void slotPrevItem(void);
+ void slotNextItem(void);
+ void slotLastItem(void);
+
+private:
+
+ CameraUIPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* CAMERAUI_H */
diff --git a/src/utilities/cameragui/dkcamera.cpp b/src/utilities/cameragui/dkcamera.cpp
new file mode 100644
index 00000000..8f318855
--- /dev/null
+++ b/src/utilities/cameragui/dkcamera.cpp
@@ -0,0 +1,113 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-21
+ * Description : abstract camera interface class
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqdeepcopy.h>
+
+// Local includes.
+
+#include "albumsettings.h"
+#include "dkcamera.h"
+
+namespace Digikam
+{
+
+DKCamera::DKCamera(const TQString& title, const TQString& model, const TQString& port, const TQString& path)
+{
+ m_title = title;
+ m_model = model;
+ m_port = port;
+ m_path = path;
+
+ AlbumSettings* settings = AlbumSettings::instance();
+ m_imageFilter = TQDeepCopy<TQString>(settings->getImageFileFilter());
+ m_movieFilter = TQDeepCopy<TQString>(settings->getMovieFileFilter());
+ m_audioFilter = TQDeepCopy<TQString>(settings->getAudioFileFilter());
+ m_rawFilter = TQDeepCopy<TQString>(settings->getRawFileFilter());
+
+ m_imageFilter = m_imageFilter.lower();
+ m_movieFilter = m_movieFilter.lower();
+ m_audioFilter = m_audioFilter.lower();
+ m_rawFilter = m_rawFilter.lower();
+}
+
+DKCamera::~DKCamera()
+{
+}
+
+TQString DKCamera::title() const
+{
+ return m_title;
+}
+
+TQString DKCamera::model() const
+{
+ return m_model;
+}
+
+TQString DKCamera::port() const
+{
+ return m_port;
+}
+
+TQString DKCamera::path() const
+{
+ return m_path;
+}
+
+TQString DKCamera::mimeType(const TQString& fileext) const
+{
+ if (fileext.isEmpty()) return TQString();
+
+ TQString ext = fileext;
+ TQString mime;
+
+ // Massage known variations of known mimetypes into KDE specific ones
+ if (ext == "jpg" || ext == "jpe")
+ ext = "jpeg";
+ else if (ext == "tif")
+ ext = "tiff";
+
+ if (m_rawFilter.contains(ext))
+ {
+ mime = TQString("image/x-raw");
+ }
+ else if (m_imageFilter.contains(ext))
+ {
+ mime = TQString("image/") + ext;
+ }
+ else if (m_movieFilter.contains(ext))
+ {
+ mime = TQString("video/") + ext;
+ }
+ else if (m_audioFilter.contains(ext))
+ {
+ mime = TQString("audio/") + ext;
+ }
+
+ return mime;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/dkcamera.h b/src/utilities/cameragui/dkcamera.h
new file mode 100644
index 00000000..2ef76723
--- /dev/null
+++ b/src/utilities/cameragui/dkcamera.h
@@ -0,0 +1,97 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-21
+ * Description : abstract camera interface class
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * 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.
+ *
+ * ============================================================ */
+
+#ifndef DKCAMERA_H
+#define DKCAMERA_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Local includes.
+
+#include "gpiteminfo.h"
+
+class TQStringList;
+class TQImage;
+
+namespace Digikam
+{
+
+class DKCamera
+{
+public:
+
+ DKCamera(const TQString& title, const TQString& model, const TQString& port, const TQString& path);
+ virtual ~DKCamera();
+
+ virtual bool doConnect() = 0;
+ virtual void cancel() = 0;
+
+ virtual void getAllFolders(const TQString& folder, TQStringList& subFolderList) = 0;
+
+ /// If getImageDimensions is false, the camera shall set width and height to -1
+ /// if the values are not immediately available
+ virtual bool getItemsInfoList(const TQString& folder, GPItemInfoList& infoList, bool getImageDimensions = true) = 0;
+
+ virtual bool getThumbnail(const TQString& folder, const TQString& itemName, TQImage& thumbnail) = 0;
+ virtual bool getExif(const TQString& folder, const TQString& itemName, char **edata, int& esize) = 0;
+
+ virtual bool downloadItem(const TQString& folder, const TQString& itemName, const TQString& saveFile) = 0;
+ virtual bool deleteItem(const TQString& folder, const TQString& itemName) = 0;
+ virtual bool uploadItem(const TQString& folder, const TQString& itemName, const TQString& localFile,
+ GPItemInfo& itemInfo, bool getImageDimensions=true) = 0;
+ virtual bool cameraSummary(TQString& summary) = 0;
+ virtual bool cameraManual(TQString& manual) = 0;
+ virtual bool cameraAbout(TQString& about) = 0;
+
+ virtual bool setLockItem(const TQString& folder, const TQString& itemName, bool lock) = 0;
+
+ TQString title() const;
+ TQString model() const;
+ TQString port() const;
+ TQString path() const;
+
+protected:
+
+ TQString mimeType(const TQString& fileext) const;
+
+protected:
+
+ TQString m_imageFilter;
+ TQString m_movieFilter;
+ TQString m_audioFilter;
+ TQString m_rawFilter;
+
+private:
+
+ TQString m_title;
+ TQString m_model;
+ TQString m_port;
+ TQString m_path;
+};
+
+} // namespace Digikam
+
+#endif /* DKCAMERA_H */
diff --git a/src/utilities/cameragui/downloadsettingscontainer.h b/src/utilities/cameragui/downloadsettingscontainer.h
new file mode 100644
index 00000000..b3e59501
--- /dev/null
+++ b/src/utilities/cameragui/downloadsettingscontainer.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-21-07
+ * Description : Camera item download settings container.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef DOWNLOADSETTINGSCONTAINER_H
+#define DOWNLOADSETTINGSCONTAINER_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqdatetime.h>
+
+namespace Digikam
+{
+
+class DownloadSettingsContainer
+{
+
+public:
+
+ DownloadSettingsContainer()
+ {
+ autoRotate = true;
+ fixDateTime = false;
+ setPhotographerId = false;
+ setCredits = false;
+ convertJpeg = false;
+ };
+
+ ~DownloadSettingsContainer(){};
+
+public:
+
+ bool autoRotate;
+ bool fixDateTime;
+ bool setPhotographerId;
+ bool setCredits;
+ bool convertJpeg;
+
+ TQDateTime newDateTime;
+
+ // File path to download.
+ TQString folder;
+ TQString file;
+ TQString dest;
+
+ // New format to convert Jpeg files.
+ TQString losslessFormat;
+
+ // IPTC settings
+ TQString author;
+ TQString authorTitle;
+ TQString credit;
+ TQString source;
+ TQString copyright;
+};
+
+} // namespace Digikam
+
+#endif // DOWNLOADSETTINGSCONTAINER_H
diff --git a/src/utilities/cameragui/freespacewidget.cpp b/src/utilities/cameragui/freespacewidget.cpp
new file mode 100644
index 00000000..0d7a26b1
--- /dev/null
+++ b/src/utilities/cameragui/freespacewidget.cpp
@@ -0,0 +1,252 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-08-31
+ * Description : a widget to display free space for a mount-point.
+ *
+ * Copyright (C) 2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqpalette.h>
+#include <tqcolor.h>
+#include <tqtimer.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <tdelocale.h>
+#include <kdiskfreesp.h>
+#include <tdeio/global.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "albumsettings.h"
+#include "freespacewidget.h"
+#include "freespacewidget.moc"
+
+namespace Digikam
+{
+
+class FreeSpaceWidgetPriv
+{
+public:
+
+ FreeSpaceWidgetPriv()
+ {
+ timer = 0;
+ isValid = false;
+ kBSize = 0;
+ kBUsed = 0;
+ kBAvail = 0;
+ dSizeKb = 0;
+ percentUsed = 0;
+ }
+
+ bool isValid;
+
+ int percentUsed;
+
+ unsigned long dSizeKb;
+ unsigned long kBSize;
+ unsigned long kBUsed;
+ unsigned long kBAvail;
+
+ TQString mountPoint;
+
+ TQTimer *timer;
+
+ TQPixmap pix;
+};
+
+FreeSpaceWidget::FreeSpaceWidget(TQWidget* parent, int width)
+ : TQWidget(parent, 0, WResizeNoErase|WRepaintNoErase)
+{
+ d = new FreeSpaceWidgetPriv;
+ setBackgroundMode(TQt::NoBackground);
+ setFixedWidth(width);
+ setMaximumHeight(fontMetrics().height()+4);
+ slotTimeout();
+
+ d->timer = new TQTimer(this);
+
+ connect(d->timer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotTimeout()));
+
+ d->timer->start(10000);
+}
+
+FreeSpaceWidget::~FreeSpaceWidget()
+{
+ d->timer->stop();
+ delete d->timer;
+ delete d;
+}
+
+void FreeSpaceWidget::setEstimatedDSizeKb(unsigned long dSize)
+{
+ d->dSizeKb = dSize;
+ updatePixmap();
+ repaint();
+}
+
+unsigned long FreeSpaceWidget::estimatedDSizeKb()
+{
+ return d->dSizeKb;
+}
+
+bool FreeSpaceWidget::isValid()
+{
+ return d->isValid;
+}
+
+int FreeSpaceWidget::percentUsed()
+{
+ return d->percentUsed;
+}
+
+unsigned long FreeSpaceWidget::kBSize()
+{
+ return d->kBSize;
+}
+
+unsigned long FreeSpaceWidget::kBUsed()
+{
+ return d->kBUsed;
+}
+
+unsigned long FreeSpaceWidget::kBAvail()
+{
+ return d->kBAvail;
+}
+
+TQString FreeSpaceWidget::mountPoint()
+{
+ return d->mountPoint;
+}
+
+void FreeSpaceWidget::updatePixmap()
+{
+ TQPixmap fimgPix = SmallIcon("folder_image");
+ d->pix = TQPixmap(size());
+ d->pix.fill(colorGroup().background());
+
+ TQPainter p(&d->pix);
+ p.setPen(colorGroup().mid());
+ p.drawRect(0, 0, d->pix.width(), d->pix.height());
+ p.drawPixmap(2, d->pix.height()/2-fimgPix.height()/2,
+ fimgPix, 0, 0, fimgPix.width(), fimgPix.height());
+
+ if (isValid())
+ {
+ // We will compute the estimated % of space size used to download and process.
+ unsigned long eUsedKb = d->dSizeKb + d->kBUsed;
+ int peUsed = (int)(100.0*((double)eUsedKb/(double)d->kBSize));
+ int pClamp = peUsed > 100 ? 100 : peUsed;
+ p.setBrush(peUsed > 95 ? TQt::red : TQt::darkGreen);
+ p.setPen(TQt::white);
+ TQRect gRect(fimgPix.height()+2, 1,
+ (int)(((double)d->pix.width()-2.0-fimgPix.width()-2.0)*(pClamp/100.0)),
+ d->pix.height()-2);
+ p.drawRect(gRect);
+
+ TQRect tRect(fimgPix.height()+2, 1, d->pix.width()-2-fimgPix.width()-2, d->pix.height()-2);
+ TQString text = TQString("%1%").arg(peUsed);
+ p.setPen(colorGroup().text());
+ TQFontMetrics fontMt = p.fontMetrics();
+ TQRect fontRect = fontMt.boundingRect(tRect.x(), tRect.y(),
+ tRect.width(), tRect.height(), 0, text);
+ p.drawText(tRect, TQt::AlignCenter, text);
+
+ TQString tipText, value;
+ TQString header = i18n("Album Library");
+ TQString headBeg("<tr bgcolor=\"orange\"><td colspan=\"2\">"
+ "<nobr><font size=\"-1\" color=\"black\"><b>");
+ TQString headEnd("</b></font></nobr></td></tr>");
+ TQString cellBeg("<tr><td><nobr><font size=-1>");
+ TQString cellMid("</font></nobr></td><td><nobr><font size=-1>");
+ TQString cellEnd("</font></nobr></td></tr>");
+ tipText = "<table cellspacing=0 cellpadding=0>";
+ tipText += headBeg + header + headEnd;
+
+ if (d->dSizeKb > 0)
+ {
+ tipText += cellBeg + i18n("Capacity:") + cellMid;
+ tipText += TDEIO::convertSizeFromKB(d->kBSize) + cellEnd;
+
+ tipText += cellBeg + i18n("Available:") + cellMid;
+ tipText += TDEIO::convertSizeFromKB(d->kBAvail) + cellEnd;
+
+ tipText += cellBeg + i18n("Require:") + cellMid;
+ tipText += TDEIO::convertSizeFromKB(d->dSizeKb) + cellEnd;
+ }
+ else
+ {
+ tipText += cellBeg + i18n("Capacity:") + cellMid;
+ tipText += TDEIO::convertSizeFromKB(d->kBSize) + cellEnd;
+
+ tipText += cellBeg + i18n("Available:") + cellMid;
+ tipText += TDEIO::convertSizeFromKB(d->kBAvail) + cellEnd;
+ }
+
+ tipText += "</table>";
+
+ TQWhatsThis::add(this, tipText);
+ TQToolTip::add(this, tipText);
+ }
+
+ p.end();
+}
+
+void FreeSpaceWidget::paintEvent(TQPaintEvent*)
+{
+ bitBlt(this, 0, 0, &d->pix);
+}
+
+void FreeSpaceWidget::slotTimeout()
+{
+ TQString mountPoint = TDEIO::findPathMountPoint(AlbumSettings::instance()->getAlbumLibraryPath());
+ KDiskFreeSp *job = new KDiskFreeSp;
+ connect(job, TQ_SIGNAL(foundMountPoint(const unsigned long&, const unsigned long&,
+ const unsigned long&, const TQString&)),
+ this, TQ_SLOT(slotAvailableFreeSpace(const unsigned long&, const unsigned long&,
+ const unsigned long&, const TQString&)));
+ job->readDF(mountPoint);
+}
+
+void FreeSpaceWidget::slotAvailableFreeSpace(const unsigned long& kBSize, const unsigned long& kBUsed,
+ const unsigned long& kBAvail, const TQString& mountPoint)
+{
+ d->mountPoint = mountPoint;
+ d->kBSize = kBSize;
+ d->kBUsed = kBUsed;
+ d->kBAvail = kBAvail;
+ d->percentUsed = 100 - (int)(100.0*kBAvail/kBSize);
+ d->isValid = true;
+ updatePixmap();
+ repaint();
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/freespacewidget.h b/src/utilities/cameragui/freespacewidget.h
new file mode 100644
index 00000000..2111791a
--- /dev/null
+++ b/src/utilities/cameragui/freespacewidget.h
@@ -0,0 +1,75 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-08-31
+ * Description : a widget to display free space for a mount-point.
+ *
+ * Copyright (C) 2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef FREESPACEWIDGET_H
+#define FREESPACEWIDGET_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqwidget.h>
+
+namespace Digikam
+{
+
+class FreeSpaceWidgetPriv;
+
+class FreeSpaceWidget : public TQWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ FreeSpaceWidget(TQWidget* parent, int width);
+ ~FreeSpaceWidget();
+
+ void setEstimatedDSizeKb(unsigned long dSize);
+ unsigned long estimatedDSizeKb();
+
+ bool isValid() ;
+ int percentUsed();
+ unsigned long kBSize();
+ unsigned long kBUsed();
+ unsigned long kBAvail();
+ TQString mountPoint();
+
+protected:
+
+ void paintEvent(TQPaintEvent*);
+ void updatePixmap();
+
+private slots:
+
+ void slotTimeout();
+ void slotAvailableFreeSpace(const unsigned long& kBSize, const unsigned long& kBUsed,
+ const unsigned long& kBAvail, const TQString& mountPoint);
+
+private:
+
+ FreeSpaceWidgetPriv* d;
+};
+
+} // namespace Digikam
+
+#endif /* FREESPACEWIDGET_H */
diff --git a/src/utilities/cameragui/gpcamera.cpp b/src/utilities/cameragui/gpcamera.cpp
new file mode 100644
index 00000000..e03d92d0
--- /dev/null
+++ b/src/utilities/cameragui/gpcamera.cpp
@@ -0,0 +1,1223 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-21
+ * Description : Gphoto2 camera interface
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <iostream>
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqdom.h>
+#include <tqfile.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// C Ansi includes.
+extern "C"
+{
+#include <gphoto2.h>
+}
+
+// Local includes.
+
+#include "ddebug.h"
+#include "gpcamera.h"
+
+namespace Digikam
+{
+
+class GPCameraPrivate
+{
+
+public:
+
+ GPCameraPrivate()
+ {
+ camera = 0;
+ }
+
+ bool cameraInitialized;
+
+ bool thumbnailSupport;
+ bool deleteSupport;
+ bool uploadSupport;
+ bool mkDirSupport;
+ bool delDirSupport;
+
+ TQString model;
+ TQString port;
+ TQString globalPath;
+
+ Camera *camera;
+ CameraAbilities cameraAbilities;
+};
+
+class GPStatus
+{
+
+public:
+
+ GPStatus()
+ {
+ context = gp_context_new();
+ cancel = false;
+ gp_context_set_cancel_func(context, cancel_func, 0);
+ }
+
+ ~GPStatus()
+ {
+ gp_context_unref(context);
+ cancel = false;
+ }
+
+ GPContext *context;
+ static bool cancel;
+
+ static GPContextFeedback cancel_func(GPContext *, void *)
+ {
+ return (cancel ? GP_CONTEXT_FEEDBACK_CANCEL :
+ GP_CONTEXT_FEEDBACK_OK);
+ }
+};
+
+bool GPStatus::cancel = false;
+
+GPCamera::GPCamera(const TQString& title, const TQString& model, const TQString& port, const TQString& path)
+ : DKCamera(title, model, port, path)
+{
+ m_status = 0;
+
+ d = new GPCameraPrivate;
+ d->camera = 0;
+ d->model = model;
+ d->port = port;
+ d->globalPath = path;
+ d->cameraInitialized = false;
+ d->thumbnailSupport = false;
+ d->deleteSupport = false;
+ d->uploadSupport = false;
+ d->mkDirSupport = false;
+ d->delDirSupport = false;
+}
+
+GPCamera::~GPCamera()
+{
+ if (d->camera)
+ {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ }
+
+ delete d;
+}
+
+TQString GPCamera::model() const
+{
+ return d->model;
+}
+
+TQString GPCamera::port() const
+{
+ return d->port;
+}
+
+TQString GPCamera::path() const
+{
+ return d->globalPath;
+}
+
+bool GPCamera::thumbnailSupport()
+{
+ return d->thumbnailSupport;
+}
+
+bool GPCamera::deleteSupport()
+{
+ return d->deleteSupport;
+}
+
+bool GPCamera::uploadSupport()
+{
+ return d->uploadSupport;
+}
+
+bool GPCamera::mkDirSupport()
+{
+ return d->mkDirSupport;
+}
+
+bool GPCamera::delDirSupport()
+{
+ return d->delDirSupport;
+}
+
+bool GPCamera::doConnect()
+{
+ int errorCode;
+ // -- first step - setup the camera --------------------
+
+ if (d->camera)
+ {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ }
+
+ CameraAbilitiesList *abilList;
+ GPPortInfoList *infoList;
+ GPPortInfo info;
+
+ gp_camera_new(&d->camera);
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus();
+
+ gp_abilities_list_new(&abilList);
+ gp_abilities_list_load(abilList, m_status->context);
+ gp_port_info_list_new(&infoList);
+ gp_port_info_list_load(infoList);
+
+ delete m_status;
+ m_status = 0;
+
+ int modelNum = -1, portNum = -1;
+ modelNum = gp_abilities_list_lookup_model(abilList, d->model.latin1());
+ portNum = gp_port_info_list_lookup_path (infoList, d->port.latin1());
+
+ gp_abilities_list_get_abilities(abilList, modelNum, &d->cameraAbilities);
+
+ errorCode = gp_camera_set_abilities(d->camera, d->cameraAbilities);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to set camera Abilities!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ gp_abilities_list_free(abilList);
+ gp_port_info_list_free(infoList);
+ return false;
+ }
+
+ if (d->model != "Directory Browse")
+ {
+ gp_port_info_list_get_info(infoList, portNum, &info);
+ errorCode = gp_camera_set_port_info(d->camera, info);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to set camera port!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ gp_abilities_list_free (abilList);
+ gp_port_info_list_free (infoList);
+ return false;
+ }
+ }
+
+ gp_abilities_list_free (abilList);
+ gp_port_info_list_free (infoList);
+
+ if (d->cameraAbilities.file_operations &
+ GP_FILE_OPERATION_PREVIEW)
+ d->thumbnailSupport = true;
+
+ if (d->cameraAbilities.file_operations &
+ GP_FILE_OPERATION_DELETE)
+ d->deleteSupport = true;
+
+ if (d->cameraAbilities.folder_operations &
+ GP_FOLDER_OPERATION_PUT_FILE)
+ d->uploadSupport = true;
+
+ if (d->cameraAbilities.folder_operations &
+ GP_FOLDER_OPERATION_MAKE_DIR)
+ d->mkDirSupport = true;
+
+ if (d->cameraAbilities.folder_operations &
+ GP_FOLDER_OPERATION_REMOVE_DIR)
+ d->delDirSupport = true;
+
+ // -- Now try to initialize the camera -----------------
+
+ m_status = new GPStatus();
+
+ // Try and initialize the camera to see if its connected
+ errorCode = gp_camera_init(d->camera, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to initialize camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ d->cameraInitialized = true;
+ return true;
+}
+
+void GPCamera::cancel()
+{
+ if (!m_status)
+ return;
+ m_status->cancel = true;
+}
+
+void GPCamera::getAllFolders(const TQString& rootFolder,
+ TQStringList& folderList)
+{
+ TQStringList subfolders;
+ getSubFolders(rootFolder, subfolders);
+
+ for (TQStringList::iterator it = subfolders.begin();
+ it != subfolders.end(); ++it)
+ {
+ *it = rootFolder + TQString(rootFolder.endsWith("/") ? "" : "/") + (*it);
+ folderList.append(*it);
+ }
+
+ for (TQStringList::iterator it = subfolders.begin();
+ it != subfolders.end(); ++it)
+ {
+ getAllFolders(*it, folderList);
+ }
+}
+
+bool GPCamera::getSubFolders(const TQString& folder, TQStringList& subFolderList)
+{
+ int errorCode;
+ CameraList *clist;
+ gp_list_new(&clist);
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+ m_status = new GPStatus();
+
+ errorCode = gp_camera_folder_list_folders(d->camera, TQFile::encodeName(folder), clist, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get folders list from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_list_unref(clist);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ int count = gp_list_count(clist);
+ for (int i = 0 ; i < count ; i++)
+ {
+ const char* subFolder;
+ errorCode = gp_list_get_name(clist, i, &subFolder);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get folder name from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_list_unref(clist);
+ return false;
+ }
+
+ subFolderList.append(TQFile::decodeName(subFolder));
+ }
+
+ gp_list_unref(clist);
+ return true;
+}
+
+bool GPCamera::getItemsList(const TQString& folder, TQStringList& itemsList)
+{
+ int errorCode;
+ CameraList *clist;
+ const char *cname;
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+ m_status = new GPStatus;
+
+ gp_list_new(&clist);
+
+ errorCode = gp_camera_folder_list_files(d->camera, TQFile::encodeName(folder), clist, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get folder files list from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_list_unref(clist);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ int count = gp_list_count(clist);
+ for (int i = 0 ; i < count ; i++)
+ {
+ errorCode = gp_list_get_name(clist, i, &cname);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get file name from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_list_unref(clist);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ itemsList.append(TQFile::decodeName(cname));
+ }
+
+ gp_list_unref(clist);
+
+ delete m_status;
+ m_status = 0;
+
+ return true;
+}
+
+bool GPCamera::getItemsInfoList(const TQString& folder, GPItemInfoList& items, bool /*getImageDimensions*/)
+{
+ int errorCode;
+ CameraList *clist;
+ const char *cname;
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+ m_status = new GPStatus;
+
+ gp_list_new(&clist);
+
+ errorCode = gp_camera_folder_list_files(d->camera, TQFile::encodeName(folder), clist, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get folder files list from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_list_unref(clist);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ int count = gp_list_count(clist);
+ for (int i = 0 ; i < count ; i++)
+ {
+ errorCode = gp_list_get_name(clist, i, &cname);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get file name from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_list_unref(clist);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ GPItemInfo itemInfo;
+
+ itemInfo.name = TQFile::decodeName(cname);
+ itemInfo.folder = folder;
+
+ CameraFileInfo info;
+ gp_camera_file_get_info(d->camera, TQFile::encodeName(folder),
+ cname, &info, m_status->context);
+
+ itemInfo.mtime = -1;
+ itemInfo.mime = "";
+ itemInfo.size = -1;
+ itemInfo.width = -1;
+ itemInfo.height = -1;
+ itemInfo.downloaded = GPItemInfo::DownloadUnknow;
+ itemInfo.readPermissions = -1;
+ itemInfo.writePermissions = -1;
+
+ /* The mime type returned by Gphoto2 is dummy with all RAW files.
+ if (info.file.fields & GP_FILE_INFO_TYPE)
+ itemInfo.mime = info.file.type;*/
+
+ itemInfo.mime = mimeType(TQString(itemInfo.name.section('.', -1)).lower());
+
+ if (info.file.fields & GP_FILE_INFO_MTIME)
+ itemInfo.mtime = info.file.mtime;
+
+ if (info.file.fields & GP_FILE_INFO_SIZE)
+ itemInfo.size = info.file.size;
+
+ if (info.file.fields & GP_FILE_INFO_WIDTH)
+ itemInfo.width = info.file.width;
+
+ if (info.file.fields & GP_FILE_INFO_HEIGHT)
+ itemInfo.height = info.file.height;
+
+ if (info.file.fields & GP_FILE_INFO_STATUS)
+ {
+ if (info.file.status == GP_FILE_STATUS_DOWNLOADED)
+ itemInfo.downloaded = GPItemInfo::DownloadedYes;
+ }
+
+ if (info.file.fields & GP_FILE_INFO_PERMISSIONS)
+ {
+ if (info.file.permissions & GP_FILE_PERM_READ)
+ itemInfo.readPermissions = 1;
+ else
+ itemInfo.readPermissions = 0;
+ if (info.file.permissions & GP_FILE_PERM_DELETE)
+ itemInfo.writePermissions = 1;
+ else
+ itemInfo.writePermissions = 0;
+ }
+
+ items.append(itemInfo);
+ }
+
+ gp_list_unref(clist);
+
+ delete m_status;
+ m_status = 0;
+
+ return true;
+}
+
+bool GPCamera::getThumbnail(const TQString& folder, const TQString& itemName, TQImage& thumbnail)
+{
+ int errorCode;
+ CameraFile *cfile;
+ const char *data;
+ unsigned long int size;
+
+ gp_file_new(&cfile);
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_file_get(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName),
+ GP_FILE_TYPE_PREVIEW,
+ cfile, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ errorCode = gp_file_get_data_and_size(cfile, &data, &size);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get thumbnail from camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ return false;
+ }
+
+ thumbnail.loadFromData((const uchar*) data, (uint) size);
+
+ gp_file_unref(cfile);
+ return true;
+}
+
+bool GPCamera::getExif(const TQString& folder, const TQString& itemName,
+ char **edata, int& esize)
+{
+ int errorCode;
+ CameraFile *cfile;
+ const char *data;
+ unsigned long int size;
+
+ gp_file_new(&cfile);
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_file_get(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName),
+ GP_FILE_TYPE_EXIF,
+ cfile, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ errorCode = gp_file_get_data_and_size(cfile, &data, &size);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get Exif data from camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ return false;
+ }
+
+ *edata = new char[size];
+ esize = size;
+ memcpy(*edata, data, size);
+
+ gp_file_unref(cfile);
+ return true;
+}
+
+bool GPCamera::downloadItem(const TQString& folder, const TQString& itemName,
+ const TQString& saveFile)
+{
+ int errorCode;
+ CameraFile *cfile;
+
+ gp_file_new(&cfile);
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_file_get(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName),
+ GP_FILE_TYPE_NORMAL, cfile,
+ m_status->context);
+ if ( errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ errorCode = gp_file_save(cfile, TQFile::encodeName(saveFile));
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to save camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ return false;
+ }
+
+ gp_file_unref(cfile);
+ return true;
+}
+
+bool GPCamera::setLockItem(const TQString& folder, const TQString& itemName, bool lock)
+{
+ int errorCode;
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ CameraFileInfo info;
+ errorCode = gp_camera_file_get_info(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName), &info, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera item properties!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ if (info.file.fields & GP_FILE_INFO_PERMISSIONS)
+ {
+ if (lock)
+ {
+ // Lock the file to set read only flag
+ info.file.permissions = (CameraFilePermissions)GP_FILE_PERM_READ;
+ }
+ else
+ {
+ // Unlock the file to set read/write flag
+ info.file.permissions = (CameraFilePermissions)(GP_FILE_PERM_READ | GP_FILE_PERM_DELETE);
+ }
+ }
+
+ // Some gphoto2 drivers need to have only the right flag at on to process properties update in camera.
+ info.file.fields = GP_FILE_INFO_PERMISSIONS;
+ info.preview.fields = GP_FILE_INFO_NONE;
+ info.audio.fields = GP_FILE_INFO_NONE;
+
+ errorCode = gp_camera_file_set_info(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName), info, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to set camera item lock properties!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+ return true;
+}
+
+bool GPCamera::deleteItem(const TQString& folder, const TQString& itemName)
+{
+ int errorCode;
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_file_delete(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName),
+ m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to delete camera item!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ return true;
+}
+
+// recursively delete all items
+bool GPCamera::deleteAllItems(const TQString& folder)
+{
+ int errorCode;
+ TQStringList folderList;
+
+ // Get all subfolders in this folder
+ getSubFolders(folder, folderList);
+
+ if (folderList.count() > 0)
+ {
+ for (unsigned int i = 0 ; i < folderList.count() ; i++)
+ {
+ TQString subFolder(folder);
+
+ if (!subFolder.endsWith("/"))
+ subFolder += '/';
+
+ subFolder += folderList[i];
+ deleteAllItems(subFolder);
+ }
+ }
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_folder_delete_all(d->camera, TQFile::encodeName(folder),
+ m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to delete camera folder!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ delete m_status;
+ m_status = 0;
+
+ return true;
+}
+
+bool GPCamera::uploadItem(const TQString& folder, const TQString& itemName, const TQString& localFile,
+ GPItemInfo& itemInfo, bool /*getImageDimensions*/)
+{
+ int errorCode;
+ CameraFile *cfile;
+
+ errorCode = gp_file_new(&cfile);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to init new camera file instance!" << endl;
+ printGphotoErrorDescription(errorCode);
+ return false;
+ }
+
+ errorCode = gp_file_open(cfile, TQFile::encodeName(localFile));
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to open file!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ return false;
+ }
+
+ errorCode = gp_file_set_name(cfile, TQFile::encodeName(itemName));
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to rename item from camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ return false;
+ }
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+#ifdef HAVE_GPHOTO25
+ errorCode = gp_camera_folder_put_file(d->camera,
+ TQFile::encodeName(folder),
+ TQFile::encodeName(itemName),
+ GP_FILE_TYPE_NORMAL,
+ cfile,
+ m_status->context);
+#else
+ errorCode = gp_camera_folder_put_file(d->camera,
+ TQFile::encodeName(folder),
+ cfile,
+ m_status->context);
+#endif
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to upload item to camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ // Get new camera item information.
+
+ itemInfo.name = itemName;
+ itemInfo.folder = folder;
+
+ CameraFileInfo info;
+ errorCode = gp_camera_file_get_info(d->camera, TQFile::encodeName(folder),
+ TQFile::encodeName(itemName), &info, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera item information!" << endl;
+ printGphotoErrorDescription(errorCode);
+ gp_file_unref(cfile);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ itemInfo.mtime = -1;
+ itemInfo.mime = "";
+ itemInfo.size = -1;
+ itemInfo.width = -1;
+ itemInfo.height = -1;
+ itemInfo.downloaded = GPItemInfo::DownloadUnknow;
+ itemInfo.readPermissions = -1;
+ itemInfo.writePermissions = -1;
+
+ /* The mime type returned by Gphoto2 is dummy with all RAW files.
+ if (info.file.fields & GP_FILE_INFO_TYPE)
+ itemInfo.mime = info.file.type;*/
+
+ itemInfo.mime = mimeType(TQString(itemInfo.name.section('.', -1)).lower());
+
+ if (info.file.fields & GP_FILE_INFO_MTIME)
+ itemInfo.mtime = info.file.mtime;
+
+ if (info.file.fields & GP_FILE_INFO_SIZE)
+ itemInfo.size = info.file.size;
+
+ if (info.file.fields & GP_FILE_INFO_WIDTH)
+ itemInfo.width = info.file.width;
+
+ if (info.file.fields & GP_FILE_INFO_HEIGHT)
+ itemInfo.height = info.file.height;
+
+ if (info.file.fields & GP_FILE_INFO_STATUS)
+ {
+ if (info.file.status == GP_FILE_STATUS_DOWNLOADED)
+ itemInfo.downloaded = GPItemInfo::DownloadedYes;
+ else
+ itemInfo.downloaded = GPItemInfo::DownloadedNo;
+ }
+
+ if (info.file.fields & GP_FILE_INFO_PERMISSIONS)
+ {
+ if (info.file.permissions & GP_FILE_PERM_READ)
+ itemInfo.readPermissions = 1;
+ else
+ itemInfo.readPermissions = 0;
+ if (info.file.permissions & GP_FILE_PERM_DELETE)
+ itemInfo.writePermissions = 1;
+ else
+ itemInfo.writePermissions = 0;
+ }
+
+ gp_file_unref(cfile);
+ delete m_status;
+ m_status = 0;
+ return true;
+}
+
+bool GPCamera::cameraSummary(TQString& summary)
+{
+ int errorCode;
+ CameraText sum;
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_get_summary(d->camera, &sum, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera summary!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ summary = i18n("Title: %1\n"
+ "Model: %2\n"
+ "Port: %3\n"
+ "Path: %4\n\n"
+ "Thumbnails: %5\n"
+ "Delete items: %6\n"
+ "Upload items: %7\n"
+ "Create directories: %8\n"
+ "Delete directories: %9\n\n")
+ .arg(title())
+ .arg(model())
+ .arg(port())
+ .arg(path())
+ .arg(thumbnailSupport() ? i18n("yes") : i18n("no"))
+ .arg(deleteSupport() ? i18n("yes") : i18n("no"))
+ .arg(uploadSupport() ? i18n("yes") : i18n("no"))
+ .arg(mkDirSupport() ? i18n("yes") : i18n("no"))
+ .arg(delDirSupport() ? i18n("yes") : i18n("no"));
+
+ summary.append(TQString(sum.text));
+
+ delete m_status;
+ m_status = 0;
+ return true;
+}
+
+bool GPCamera::cameraManual(TQString& manual)
+{
+ int errorCode;
+ CameraText man;
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_get_manual(d->camera, &man, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get camera manual!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ manual = TQString(man.text);
+
+ delete m_status;
+ m_status = 0;
+ return true;
+}
+
+bool GPCamera::cameraAbout(TQString& about)
+{
+ int errorCode;
+ CameraText abt;
+
+ if (m_status)
+ {
+ delete m_status;
+ m_status = 0;
+ }
+
+ m_status = new GPStatus;
+
+ errorCode = gp_camera_get_about(d->camera, &abt, m_status->context);
+ if (errorCode != GP_OK)
+ {
+ DDebug() << "Failed to get information about camera!" << endl;
+ printGphotoErrorDescription(errorCode);
+ delete m_status;
+ m_status = 0;
+ return false;
+ }
+
+ about = TQString(abt.text);
+ about.append(i18n("\n\nTo report problems about this driver, please contact "
+ "the gphoto2 team at:\n\nhttp://gphoto.org/bugs"));
+
+ delete m_status;
+ m_status = 0;
+ return true;
+}
+
+// -- Static methods ---------------------------------------------------------------------
+
+void GPCamera::printGphotoErrorDescription(int errorCode)
+{
+ DDebug() << "Libgphoto2 error: " << gp_result_as_string(errorCode)
+ << " (" << errorCode << ")" << endl;
+}
+
+void GPCamera::getSupportedCameras(int& count, TQStringList& clist)
+{
+ clist.clear();
+ count = 0;
+
+ CameraAbilitiesList *abilList;
+ CameraAbilities abil;
+ GPContext *context;
+
+ context = gp_context_new();
+
+ gp_abilities_list_new( &abilList );
+ gp_abilities_list_load( abilList, context );
+
+ count = gp_abilities_list_count( abilList );
+ if ( count < 0 )
+ {
+ DDebug() << "Failed to get list of cameras!" << endl;
+ printGphotoErrorDescription(count);
+ gp_context_unref( context );
+ return;
+ }
+ else
+ {
+ for (int i = 0 ; i < count ; i++)
+ {
+ gp_abilities_list_get_abilities( abilList, i, &abil );
+ const char *cname = abil.model;
+ clist.append( TQString( cname ) );
+ }
+ }
+
+ gp_abilities_list_free( abilList );
+ gp_context_unref( context );
+}
+
+void GPCamera::getSupportedPorts(TQStringList& plist)
+{
+ GPPortInfoList *list;
+ GPPortInfo info;
+
+ plist.clear();
+
+ gp_port_info_list_new( &list );
+ gp_port_info_list_load( list );
+
+ int numPorts = gp_port_info_list_count( list );
+ if ( numPorts < 0)
+ {
+ DDebug() << "Failed to get list of port!" << endl;
+ printGphotoErrorDescription(numPorts);
+ gp_port_info_list_free( list );
+ return;
+ }
+ else
+ {
+ for (int i = 0 ; i < numPorts ; i++)
+ {
+ gp_port_info_list_get_info( list, i, &info );
+#ifdef HAVE_GPHOTO25
+ char *xpath;
+ gp_port_info_get_name( info, &xpath );
+ plist.append( xpath );
+#else
+ plist.append( info.path );
+#endif
+ }
+ }
+
+ gp_port_info_list_free( list );
+}
+
+void GPCamera::getCameraSupportedPorts(const TQString& model, TQStringList& plist)
+{
+ int i = 0;
+ plist.clear();
+
+ CameraAbilities abilities;
+ CameraAbilitiesList *abilList;
+ GPContext *context;
+
+ context = gp_context_new();
+
+ gp_abilities_list_new (&abilList);
+ gp_abilities_list_load (abilList, context);
+ i = gp_abilities_list_lookup_model (abilList, model.local8Bit().data());
+ gp_abilities_list_get_abilities (abilList, i, &abilities);
+ gp_abilities_list_free (abilList);
+
+ if (abilities.port & GP_PORT_SERIAL)
+ plist.append("serial");
+
+ if (abilities.port & GP_PORT_USB)
+ plist.append("usb");
+
+ gp_context_unref( context );
+}
+
+int GPCamera::autoDetect(TQString& model, TQString& port)
+{
+ CameraList *camList;
+ CameraAbilitiesList *abilList;
+ GPPortInfoList *infoList;
+ const char *camModel_, *camPort_;
+ GPContext *context;
+
+ context = gp_context_new();
+ gp_list_new(&camList);
+
+ gp_abilities_list_new(&abilList);
+ gp_abilities_list_load(abilList, context);
+ gp_port_info_list_new(&infoList);
+ gp_port_info_list_load(infoList);
+ gp_abilities_list_detect(abilList, infoList, camList, context);
+ gp_abilities_list_free(abilList);
+ gp_port_info_list_free(infoList);
+
+ gp_context_unref(context);
+
+ int count = gp_list_count(camList);
+
+ if (count <= 0)
+ {
+ DDebug() << "Failed to autodetect camera!" << endl;
+ printGphotoErrorDescription(count);
+ gp_list_free(camList);
+ return -1;
+ }
+
+ camModel_ = 0;
+ camPort_ = 0;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (gp_list_get_name(camList, i, &camModel_) != GP_OK)
+ {
+ DDebug() << "Failed to autodetect camera!" << endl;
+ gp_list_free(camList);
+ return -1;
+ }
+
+ if (gp_list_get_value(camList, i, &camPort_) != GP_OK)
+ {
+ DDebug() << "Failed to autodetect camera!" << endl;
+ gp_list_free(camList);
+ return -1;
+ }
+
+ if (camModel_ && camPort_)
+ {
+ model = TQString::fromLatin1(camModel_);
+ port = TQString::fromLatin1(camPort_);
+ gp_list_free(camList);
+ return 0;
+ }
+ }
+
+ DDebug() << "Failed to autodetect camera!" << endl;
+ gp_list_free(camList);
+ return -1;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/gpcamera.h b/src/utilities/cameragui/gpcamera.h
new file mode 100644
index 00000000..7071e972
--- /dev/null
+++ b/src/utilities/cameragui/gpcamera.h
@@ -0,0 +1,107 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2003-01-21
+ * Description : Gphoto2 camera interface
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef GPCAMERA_H
+#define GPCAMERA_H
+
+// Local includes.
+
+#include "dkcamera.h"
+
+class TQImage;
+
+namespace Digikam
+{
+
+class GPCameraPrivate;
+class GPStatus;
+
+// Gphoto2 camera Implementation of abstract type DKCamera
+
+class GPCamera : public DKCamera
+{
+
+public:
+
+ GPCamera(const TQString& title, const TQString& model,
+ const TQString& port, const TQString& path);
+ ~GPCamera();
+
+ bool thumbnailSupport();
+ bool deleteSupport();
+ bool uploadSupport();
+ bool mkDirSupport();
+ bool delDirSupport();
+
+ bool doConnect();
+
+ void cancel();
+
+ void getAllFolders(const TQString& folder, TQStringList& subFolderList);
+ bool getSubFolders(const TQString& folder, TQStringList& subFolderList);
+ bool getItemsList(const TQString& folder, TQStringList& itemsList);
+ bool getItemsInfoList(const TQString& folder, GPItemInfoList& items, bool getImageDimensions = true);
+ bool getThumbnail(const TQString& folder, const TQString& itemName, TQImage& thumbnail);
+ bool getExif(const TQString& folder, const TQString& itemName, char **edata, int& esize);
+
+ bool setLockItem(const TQString& folder, const TQString& itemName, bool lock);
+
+ bool downloadItem(const TQString& folder, const TQString& itemName, const TQString& saveFile);
+ bool deleteItem(const TQString& folder, const TQString& itemName);
+
+ // recursively delete all items
+ bool deleteAllItems(const TQString& folder);
+
+ bool uploadItem(const TQString& folder, const TQString& itemName, const TQString& localFile,
+ GPItemInfo& itemInfo, bool getImageDimensions=true);
+
+ bool cameraSummary(TQString& summary);
+ bool cameraManual(TQString& manual);
+ bool cameraAbout(TQString& about);
+
+ TQString model() const;
+ TQString port() const;
+ TQString path() const;
+
+ // Public static methods shared with Camera Setup
+
+ static int autoDetect(TQString& model, TQString& port);
+ static void getSupportedCameras(int& count, TQStringList& clist);
+ static void getSupportedPorts(TQStringList& plist);
+ static void getCameraSupportedPorts(const TQString& model, TQStringList& plist);
+
+private:
+
+ int setup();
+ static void printGphotoErrorDescription(int errorCode);
+
+private:
+
+ GPCameraPrivate *d;
+ GPStatus *m_status;
+};
+
+} // namespace Digikam
+
+#endif /* GPCAMERA_H */
diff --git a/src/utilities/cameragui/gpiteminfo.cpp b/src/utilities/cameragui/gpiteminfo.cpp
new file mode 100644
index 00000000..3a1d53e1
--- /dev/null
+++ b/src/utilities/cameragui/gpiteminfo.cpp
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-19
+ * Description : camera item info container
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqdatastream.h>
+
+// Local includes.
+
+#include "gpiteminfo.h"
+
+namespace Digikam
+{
+
+TQDataStream& operator<<( TQDataStream& ds, const GPItemInfo& info)
+{
+ ds << info.name;
+ ds << info.folder;
+ ds << info.mtime;
+ ds << info.mime;
+ ds << info.size;
+ ds << info.width;
+ ds << info.height;
+ ds << info.downloaded;
+ ds << info.readPermissions;
+ ds << info.writePermissions;
+
+ return ds;
+}
+
+TQDataStream& operator>>(TQDataStream& ds, GPItemInfo& info)
+{
+ ds >> info.name;
+ ds >> info.folder;
+ ds >> info.mtime;
+ ds >> info.mime;
+ ds >> info.size;
+ ds >> info.width;
+ ds >> info.height;
+ ds >> info.downloaded;
+ ds >> info.readPermissions;
+ ds >> info.writePermissions;
+
+ return ds;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/gpiteminfo.h b/src/utilities/cameragui/gpiteminfo.h
new file mode 100644
index 00000000..02b28693
--- /dev/null
+++ b/src/utilities/cameragui/gpiteminfo.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-18
+ * Description : camera item info container
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef GPITEMINFO_H
+#define GPITEMINFO_H
+
+// C++ includes.
+
+#include <ctime>
+
+// TQt includes.
+
+#include <tqvaluelist.h>
+#include <tqcstring.h>
+
+class TQDataStream;
+
+namespace Digikam
+{
+
+class GPItemInfo
+{
+
+public:
+
+ enum DownloadStatus
+ {
+ DownloadUnknow = -1,
+ DownloadedNo = 0,
+ DownloadedYes = 1,
+ DownloadFailed = 2,
+ DownloadStarted = 3,
+ NewPicture = 4
+ };
+
+public:
+
+ long size;
+ int width;
+ int height;
+ int downloaded; // See DownloadStatus enum.
+ int readPermissions;
+ int writePermissions;
+
+ TQString name;
+ TQString folder;
+ TQString mime;
+
+ time_t mtime;
+};
+
+TQDataStream& operator<<( TQDataStream &, const GPItemInfo & );
+TQDataStream& operator>>( TQDataStream &, GPItemInfo & );
+
+typedef TQValueList<GPItemInfo> GPItemInfoList;
+
+} // namespace Digikam
+
+#endif /* GPITEMINFO_H */
diff --git a/src/utilities/cameragui/mtqueue.h b/src/utilities/cameragui/mtqueue.h
new file mode 100644
index 00000000..0fb80e5c
--- /dev/null
+++ b/src/utilities/cameragui/mtqueue.h
@@ -0,0 +1,116 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : camera download multi-threading handler.
+ *
+ * Copyright (C) 2004 by Renchi Raju <[email protected]>
+
+ * 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 COMMAND_QUEUE_H
+#define COMMAND_QUEUE_H
+
+// TQt includes.
+
+#include <tqptrqueue.h>
+#include <tqmutex.h>
+
+namespace Digikam
+{
+
+template<class Type> class MTQueue
+{
+
+public:
+
+ MTQueue()
+ {
+ queue_.setAutoDelete(true);
+ }
+
+ ~MTQueue()
+ {
+ flush();
+ }
+
+ bool isEmpty()
+ {
+ mutex_.lock();
+ bool empty = queue_.isEmpty();
+ mutex_.unlock();
+ return empty;
+ }
+
+ void flush()
+ {
+ mutex_.lock();
+ queue_.clear();
+ mutex_.unlock();
+ }
+
+ void enqueue(Type * t)
+ {
+ mutex_.lock();
+ queue_.enqueue(t);
+ mutex_.unlock();
+ }
+
+ Type * dequeue()
+ {
+ mutex_.lock();
+ Type * i = queue_.dequeue();
+ mutex_.unlock();
+ return i;
+ }
+
+ Type * head(bool lock=true)
+ {
+ if (lock)
+ mutex_.lock();
+ Type * i = queue_.head();
+ if (lock)
+ mutex_.unlock();
+ return i;
+ }
+
+ int count()
+ {
+ mutex_.lock();
+ int c = queue_.count();
+ mutex_.unlock();
+ return c;
+ }
+
+ void lock()
+ {
+ mutex_.lock();
+ }
+
+ void unlock()
+ {
+ mutex_.unlock();
+ }
+
+private:
+
+ TQPtrQueue<Type> queue_;
+ TQMutex mutex_;
+};
+
+} // namespace Digikam
+
+#endif // COMMAND_QUEUE_H
diff --git a/src/utilities/cameragui/renamecustomizer.cpp b/src/utilities/cameragui/renamecustomizer.cpp
new file mode 100644
index 00000000..a906ccb1
--- /dev/null
+++ b/src/utilities/cameragui/renamecustomizer.cpp
@@ -0,0 +1,532 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-19
+ * Description : a options group to set renaming files
+ * operations during camera downloading
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqdatetime.h>
+#include <tqlayout.h>
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqhbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqtimer.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <tdeapplication.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <knuminput.h>
+#include <kdialogbase.h>
+#if KDE_IS_VERSION(3,2,0)
+#include <kinputdialog.h>
+#else
+#include <klineeditdlg.h>
+#endif
+
+// Local includes.
+
+#include "renamecustomizer.h"
+#include "renamecustomizer.moc"
+
+namespace Digikam
+{
+
+class RenameCustomizerPriv
+{
+public:
+
+ enum DateFormatOptions
+ {
+ DigikamStandard = 0,
+ IsoDateFormat,
+ TextDateFormat,
+ LocalDateFormat,
+ Advanced
+ };
+
+ RenameCustomizerPriv()
+ {
+ renameDefault = 0;
+ renameCustom = 0;
+ renameDefaultBox = 0;
+ renameCustomBox = 0;
+ renameDefaultCase = 0;
+ renameDefaultCaseType = 0;
+ addDateTimeBox = 0;
+ addCameraNameBox = 0;
+ addSeqNumberBox = 0;
+ changedTimer = 0;
+ renameCustomPrefix = 0;
+ renameCustomSuffix = 0;
+ startIndexLabel = 0;
+ startIndexInput = 0;
+ focusedWidget = 0;
+ dateTimeButton = 0;
+ dateTimeLabel = 0;
+ dateTimeFormat = 0;
+}
+
+ TQWidget *focusedWidget;
+
+ TQString cameraTitle;
+
+ TQRadioButton *renameDefault;
+ TQRadioButton *renameCustom;
+
+ TQGroupBox *renameDefaultBox;
+ TQGroupBox *renameCustomBox;
+
+ TQLabel *renameDefaultCase;
+ TQLabel *startIndexLabel;
+ TQLabel *dateTimeLabel;
+
+ TQComboBox *renameDefaultCaseType;
+ TQComboBox *dateTimeFormat;
+
+ TQCheckBox *addDateTimeBox;
+ TQCheckBox *addCameraNameBox;
+ TQCheckBox *addSeqNumberBox;
+
+ TQPushButton *dateTimeButton;
+ TQString dateTimeFormatString;
+
+ TQTimer *changedTimer;
+
+ KLineEdit *renameCustomPrefix;
+ KLineEdit *renameCustomSuffix;
+
+ KIntNumInput *startIndexInput;
+};
+
+RenameCustomizer::RenameCustomizer(TQWidget* parent, const TQString& cameraTitle)
+ : TQButtonGroup(parent)
+{
+ d = new RenameCustomizerPriv;
+ d->changedTimer = new TQTimer(this);
+ d->cameraTitle = cameraTitle;
+
+ setFrameStyle( TQFrame::NoFrame );
+ setRadioButtonExclusive(true);
+ setColumnLayout(0, TQt::Vertical);
+ TQGridLayout* mainLayout = new TQGridLayout(layout(), 4, 1);
+
+ // ----------------------------------------------------------------
+
+ d->renameDefault = new TQRadioButton(i18n("Camera filenames"), this);
+ TQWhatsThis::add( d->renameDefault, i18n("<p>Turn on this option to use camera "
+ "provided image filenames without modifications."));
+ mainLayout->addMultiCellWidget(d->renameDefault, 0, 0, 0, 1);
+
+ d->renameDefaultBox = new TQGroupBox( this );
+ d->renameDefaultBox->setFrameStyle(TQFrame::NoFrame|TQFrame::Plain);
+ d->renameDefaultBox->setInsideMargin(0);
+ d->renameDefaultBox->setColumnLayout(0, TQt::Vertical);
+
+ d->renameDefaultCase = new TQLabel( i18n("Change case to:"), d->renameDefaultBox );
+ d->renameDefaultCase->setSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Preferred );
+
+ d->renameDefaultCaseType = new TQComboBox( d->renameDefaultBox );
+ d->renameDefaultCaseType->insertItem(i18n("Leave as Is"), 0);
+ d->renameDefaultCaseType->insertItem(i18n("Upper"), 1);
+ d->renameDefaultCaseType->insertItem(i18n("Lower"), 2);
+ d->renameDefaultCaseType->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Preferred);
+ TQWhatsThis::add( d->renameDefaultCaseType, i18n("<p>Set the method to use to change the case "
+ "of image filenames."));
+
+ TQHBoxLayout* boxLayout1 = new TQHBoxLayout( d->renameDefaultBox->layout() );
+ boxLayout1->addSpacing( 10 );
+ boxLayout1->addWidget( d->renameDefaultCase );
+ boxLayout1->addWidget( d->renameDefaultCaseType );
+
+ mainLayout->addMultiCellWidget(d->renameDefaultBox, 1, 1, 0, 1);
+
+ // -------------------------------------------------------------
+
+ d->renameCustom = new TQRadioButton(i18n("Customize"), this);
+ mainLayout->addMultiCellWidget(d->renameCustom, 2, 2, 0, 1);
+ TQWhatsThis::add( d->renameCustom, i18n("<p>Turn on this option to customize image filenames "
+ "during download."));
+
+ d->renameCustomBox = new TQGroupBox(this);
+ d->renameCustomBox->setFrameStyle(TQFrame::NoFrame|TQFrame::Plain);
+ d->renameCustomBox->setInsideMargin(0);
+ d->renameCustomBox->setColumnLayout(0, TQt::Vertical);
+
+ TQGridLayout* renameCustomBoxLayout = new TQGridLayout(d->renameCustomBox->layout(),
+ 6, 2, KDialogBase::spacingHint());
+ renameCustomBoxLayout->setColSpacing( 0, 10 );
+
+ TQLabel* prefixLabel = new TQLabel(i18n("Prefix:"), d->renameCustomBox);
+ renameCustomBoxLayout->addMultiCellWidget(prefixLabel, 0, 0, 1, 1);
+ d->renameCustomPrefix = new KLineEdit(d->renameCustomBox);
+ d->focusedWidget = d->renameCustomPrefix;
+ renameCustomBoxLayout->addMultiCellWidget(d->renameCustomPrefix, 0, 0, 2, 2);
+ TQWhatsThis::add( d->renameCustomPrefix, i18n("<p>Set the prefix which will be added to "
+ "image filenames."));
+
+ TQLabel* suffixLabel = new TQLabel(i18n("Suffix:"), d->renameCustomBox);
+ renameCustomBoxLayout->addMultiCellWidget(suffixLabel, 1, 1, 1, 1);
+ d->renameCustomSuffix = new KLineEdit(d->renameCustomBox);
+ renameCustomBoxLayout->addMultiCellWidget(d->renameCustomSuffix, 1, 1, 2, 2);
+ TQWhatsThis::add( d->renameCustomSuffix, i18n("<p>Set the suffix which will be added to "
+ "image filenames."));
+
+ d->addDateTimeBox = new TQCheckBox( i18n("Add Date && Time"), d->renameCustomBox );
+ renameCustomBoxLayout->addMultiCellWidget(d->addDateTimeBox, 2, 2, 1, 2);
+ TQWhatsThis::add( d->addDateTimeBox, i18n("<p>Set this option to add the camera provided date and time."));
+
+ TQWidget *dateTimeWidget = new TQWidget(d->renameCustomBox);
+ d->dateTimeLabel = new TQLabel(i18n("Date format:"), dateTimeWidget);
+ d->dateTimeFormat = new TQComboBox(dateTimeWidget);
+ d->dateTimeFormat->insertItem(i18n("Standard"), RenameCustomizerPriv::DigikamStandard);
+ d->dateTimeFormat->insertItem(i18n("ISO"), RenameCustomizerPriv::IsoDateFormat);
+ d->dateTimeFormat->insertItem(i18n("Full Text"), RenameCustomizerPriv::TextDateFormat);
+ d->dateTimeFormat->insertItem(i18n("Local Settings"), RenameCustomizerPriv::LocalDateFormat);
+ d->dateTimeFormat->insertItem(i18n("Advanced..."), RenameCustomizerPriv::Advanced);
+ TQWhatsThis::add( d->dateTimeFormat, i18n("<p>Select your preferred date format for "
+ "creating new albums. The options available are:</p>"
+ "<p><b>Standard</b>: the date format that has been used as a standard by digiKam. "
+ "E.g.: <i>20060824T142618</i></p>"
+ "<p/><b>ISO</b>: the date format according to ISO 8601 "
+ "(YYYY-MM-DD). E.g.: <i>2006-08-24T14:26:18</i></p>"
+ "<p><b>Full Text</b>: the date format is a user-readable string. "
+ "E.g.: <i>Thu Aug 24 14:26:18 2006</i></p>"
+ "<p><b>Local Settings</b>: the date format depending on TDE control panel settings.</p>"
+ "<p><b>Advanced:</b> allows the user to specify a custom date format.</p>"));
+ d->dateTimeButton = new TQPushButton(SmallIcon("configure"), TQString(), dateTimeWidget);
+ TQSizePolicy policy = d->dateTimeButton->sizePolicy();
+ policy.setHorData(TQSizePolicy::Maximum);
+ d->dateTimeButton->setSizePolicy(policy);
+ TQHBoxLayout *boxLayout2 = new TQHBoxLayout(dateTimeWidget);
+ boxLayout2->addWidget(d->dateTimeLabel);
+ boxLayout2->addWidget(d->dateTimeFormat);
+ boxLayout2->addWidget(d->dateTimeButton);
+ renameCustomBoxLayout->addMultiCellWidget(dateTimeWidget, 3, 3, 1, 2);
+
+ d->addCameraNameBox = new TQCheckBox( i18n("Add Camera Name"), d->renameCustomBox );
+ renameCustomBoxLayout->addMultiCellWidget(d->addCameraNameBox, 4, 4, 1, 2);
+ TQWhatsThis::add( d->addCameraNameBox, i18n("<p>Set this option to add the camera name."));
+
+ d->addSeqNumberBox = new TQCheckBox( i18n("Add Sequence Number"), d->renameCustomBox );
+ renameCustomBoxLayout->addMultiCellWidget(d->addSeqNumberBox, 5, 5, 1, 2);
+ TQWhatsThis::add( d->addSeqNumberBox, i18n("<p>Set this option to add a sequence number "
+ "starting with the index set below."));
+
+ d->startIndexLabel = new TQLabel( i18n("Start Index:"), d->renameCustomBox );
+ d->startIndexInput = new KIntNumInput(1, d->renameCustomBox);
+ d->startIndexInput->setRange(1, 900000, 1, false);
+ TQWhatsThis::add( d->startIndexInput, i18n("<p>Set the starting index value used to rename "
+ "files with a sequence number."));
+
+ renameCustomBoxLayout->addMultiCellWidget(d->startIndexLabel, 6, 6, 1, 1);
+ renameCustomBoxLayout->addMultiCellWidget(d->startIndexInput, 6, 6, 2, 2);
+
+ mainLayout->addMultiCellWidget(d->renameCustomBox, 3, 3, 0, 1);
+ mainLayout->setRowStretch(4, 10);
+
+ // -- setup connections -------------------------------------------------
+
+ connect(this, TQ_SIGNAL(clicked(int)),
+ this, TQ_SLOT(slotRadioButtonClicked(int)));
+
+ connect(d->renameCustomPrefix, TQ_SIGNAL(textChanged(const TQString&)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->renameCustomSuffix, TQ_SIGNAL(textChanged(const TQString&)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->addDateTimeBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->addCameraNameBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->addSeqNumberBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->renameDefaultCaseType, TQ_SIGNAL(activated(const TQString&)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->startIndexInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotRenameOptionsChanged()));
+
+ connect(d->changedTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SIGNAL(signalChanged()));
+
+ connect(d->dateTimeButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotDateTimeButtonClicked()));
+
+ connect(d->dateTimeFormat, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotDateTimeFormatChanged(int)));
+
+ connect(d->addDateTimeBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotDateTimeBoxToggled(bool)));
+
+ // -- initial values ---------------------------------------------------
+
+ readSettings();
+
+ // signal to this not yet connected when readSettings is called? Don't know
+ slotDateTimeBoxToggled(d->addDateTimeBox->isChecked());
+}
+
+RenameCustomizer::~RenameCustomizer()
+{
+ delete d->changedTimer;
+ saveSettings();
+ delete d;
+}
+
+bool RenameCustomizer::useDefault() const
+{
+ return d->renameDefault->isChecked();
+}
+
+int RenameCustomizer::startIndex() const
+{
+ return d->startIndexInput->value();
+}
+
+TQString RenameCustomizer::newName(const TQDateTime &dateTime, int index, const TQString &extension) const
+{
+ if (d->renameDefault->isChecked())
+ return TQString();
+ else
+ {
+ TQString name(d->renameCustomPrefix->text());
+
+ // use the "T" as a delimiter between date and time
+ TQString date;
+ switch (d->dateTimeFormat->currentItem())
+ {
+ case RenameCustomizerPriv::DigikamStandard:
+ date = dateTime.toString("yyyyMMddThhmmss");
+ break;
+ case RenameCustomizerPriv::TextDateFormat:
+ date = dateTime.toString(TQt::TextDate);
+ break;
+ case RenameCustomizerPriv::LocalDateFormat:
+ date = dateTime.toString(TQt::LocalDate);
+ break;
+ case RenameCustomizerPriv::IsoDateFormat:
+ date = dateTime.toString(TQt::ISODate);
+ break;
+ case RenameCustomizerPriv::Advanced:
+ date = dateTime.toString(d->dateTimeFormatString);
+ break;
+ }
+
+ // it seems that TQString::number does not support padding with zeros
+ TQString seq;
+ seq.sprintf("-%06d", index);
+
+ if (d->addDateTimeBox->isChecked())
+ name += date;
+
+ if (d->addSeqNumberBox->isChecked())
+ name += seq;
+
+ if (d->addCameraNameBox->isChecked())
+ name += TQString("-%1").arg(d->cameraTitle.simplifyWhiteSpace().replace(" ", ""));
+
+ name += d->renameCustomSuffix->text();
+ name += extension;
+
+ return name;
+ }
+}
+
+RenameCustomizer::Case RenameCustomizer::changeCase() const
+{
+ RenameCustomizer::Case type = NONE;
+
+ if (d->renameDefaultCaseType->currentItem() == 1)
+ type=UPPER;
+ if (d->renameDefaultCaseType->currentItem() == 2)
+ type=LOWER;
+
+ return type;
+}
+
+void RenameCustomizer::slotRadioButtonClicked(int)
+{
+ TQRadioButton* btn = dynamic_cast<TQRadioButton*>(selected());
+ if (!btn)
+ return;
+
+ d->renameCustomBox->setEnabled( btn != d->renameDefault );
+ d->renameDefaultBox->setEnabled( btn == d->renameDefault );
+ slotRenameOptionsChanged();
+}
+
+void RenameCustomizer::slotRenameOptionsChanged()
+{
+ d->focusedWidget = focusWidget();
+
+ if (d->addSeqNumberBox->isChecked())
+ {
+ d->startIndexInput->setEnabled(true);
+ d->startIndexLabel->setEnabled(true);
+ }
+ else
+ {
+ d->startIndexInput->setEnabled(false);
+ d->startIndexLabel->setEnabled(false);
+ }
+
+ d->changedTimer->start(500, true);
+}
+
+void RenameCustomizer::slotDateTimeBoxToggled(bool on)
+{
+ d->dateTimeLabel->setEnabled(on);
+ d->dateTimeFormat->setEnabled(on);
+ d->dateTimeButton->setEnabled(on
+ && d->dateTimeFormat->currentItem() == RenameCustomizerPriv::Advanced);
+ slotRenameOptionsChanged();
+}
+
+void RenameCustomizer::slotDateTimeFormatChanged(int index)
+{
+ if (index == RenameCustomizerPriv::Advanced)
+ {
+ d->dateTimeButton->setEnabled(true);
+ //d->dateTimeButton->show();
+ //slotDateTimeButtonClicked();
+ }
+ else
+ {
+ d->dateTimeButton->setEnabled(false);
+ //d->dateTimeButton->hide();
+ }
+ slotRenameOptionsChanged();
+}
+
+void RenameCustomizer::slotDateTimeButtonClicked()
+{
+ bool ok;
+ TQString message = i18n("<qt><p>Enter the format for date and time.</p>"
+ "<p>Use <i>dd</i> for the day, "
+ "<i>MM</i> for the month, "
+ "<i>yyyy</i> for the year, "
+ "<i>hh</i> for the hour, "
+ "<i>mm</i> for the minute, "
+ "<i>ss</i> for the second.</p>"
+ "<p>Examples: <i>yyyyMMddThhmmss</i> "
+ "for 20060824T142418,<br>"
+ "<i>yyyy-MM-dd hh:mm:ss</i> "
+ "for 2006-08-24 14:24:18.</p></qt>");
+
+#if KDE_IS_VERSION(3,2,0)
+ TQString newFormat = KInputDialog::getText(i18n("Change Date and Time Format"),
+ message,
+ d->dateTimeFormatString, &ok, this);
+#else
+ TQString newFormat = KLineEditDlg::getText(i18n("Change Date and Time Format"),
+ message,
+ d->dateTimeFormatString, &ok, this);
+#endif
+
+ if (!ok)
+ return;
+
+ d->dateTimeFormatString = newFormat;
+ slotRenameOptionsChanged();
+}
+
+void RenameCustomizer::readSettings()
+{
+ TDEConfig* config = kapp->config();
+
+ config->setGroup("Camera Settings");
+ bool def = config->readBoolEntry("Rename Use Default", true);
+ bool addSeqNumb = config->readBoolEntry("Add Sequence Number", true);
+ bool adddateTime = config->readBoolEntry("Add Date Time", false);
+ bool addCamName = config->readBoolEntry("Add Camera Name", false);
+ int chcaseT = config->readNumEntry("Case Type", NONE);
+ TQString prefix = config->readEntry("Rename Prefix", i18n("photo"));
+ TQString suffix = config->readEntry("Rename Postfix", TQString());
+ int startIndex = config->readNumEntry("Rename Start Index", 1);
+ int dateTime = config->readNumEntry("Date Time Format", RenameCustomizerPriv::IsoDateFormat);
+ TQString format = config->readEntry("Date Time Format String", "yyyyMMddThhmmss");
+
+ if (def)
+ {
+ d->renameDefault->setChecked(true);
+ d->renameCustom->setChecked(false);
+ d->renameCustomBox->setEnabled(false);
+ d->renameDefaultBox->setEnabled(true);
+ }
+ else
+ {
+ d->renameDefault->setChecked(false);
+ d->renameCustom->setChecked(true);
+ d->renameCustomBox->setEnabled(true);
+ d->renameDefaultBox->setEnabled(false);
+ }
+
+ d->addDateTimeBox->setChecked(adddateTime);
+ d->addCameraNameBox->setChecked(addCamName);
+ d->addSeqNumberBox->setChecked(addSeqNumb);
+ d->renameDefaultCaseType->setCurrentItem(chcaseT);
+ d->renameCustomPrefix->setText(prefix);
+ d->renameCustomSuffix->setText(suffix);
+ d->startIndexInput->setValue(startIndex);
+ d->dateTimeFormat->setCurrentItem(dateTime);
+ d->dateTimeFormatString = format;
+ slotRenameOptionsChanged();
+}
+
+void RenameCustomizer::saveSettings()
+{
+ TDEConfig* config = kapp->config();
+
+ config->setGroup("Camera Settings");
+ config->writeEntry("Rename Use Default", d->renameDefault->isChecked());
+ config->writeEntry("Add Camera Name", d->addCameraNameBox->isChecked());
+ config->writeEntry("Add Date Time", d->addDateTimeBox->isChecked());
+ config->writeEntry("Add Sequence Number", d->addSeqNumberBox->isChecked());
+ config->writeEntry("Case Type", d->renameDefaultCaseType->currentItem());
+ config->writeEntry("Rename Prefix", d->renameCustomPrefix->text());
+ config->writeEntry("Rename Suffix", d->renameCustomSuffix->text());
+ config->writeEntry("Rename Start Index", d->startIndexInput->value());
+ config->writeEntry("Date Time Format", d->dateTimeFormat->currentItem());
+ config->writeEntry("Date Time Format String", d->dateTimeFormatString);
+ config->sync();
+}
+
+void RenameCustomizer::restoreFocus()
+{
+ d->focusedWidget->setFocus();
+}
+
+} // namespace Digikam
+
diff --git a/src/utilities/cameragui/renamecustomizer.h b/src/utilities/cameragui/renamecustomizer.h
new file mode 100644
index 00000000..47ad925b
--- /dev/null
+++ b/src/utilities/cameragui/renamecustomizer.h
@@ -0,0 +1,91 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-19
+ * Description : a options group to set renaming files
+ * operations during camera downloading
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef RENAMECUSTOMIZER_H
+#define RENAMECUSTOMIZER_H
+
+// TQt includes.
+
+#include <tqbuttongroup.h>
+
+class TQDateTime;
+
+namespace Digikam
+{
+
+class RenameCustomizerPriv;
+
+class RenameCustomizer : public TQButtonGroup
+{
+ TQ_OBJECT
+
+
+public:
+
+ enum Case
+ {
+ NONE = 0,
+ UPPER,
+ LOWER
+ };
+
+ RenameCustomizer(TQWidget* parent, const TQString& cameraTitle);
+ ~RenameCustomizer();
+
+ void setUseDefault(bool val);
+ bool useDefault() const;
+ TQString newName(const TQDateTime &date, int index, const TQString &extension) const;
+ Case changeCase() const;
+ int startIndex() const;
+
+signals:
+
+ void signalChanged();
+
+public slots:
+
+ void restoreFocus();
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+private slots:
+
+ void slotRadioButtonClicked(int);
+ void slotRenameOptionsChanged();
+ void slotDateTimeBoxToggled(bool);
+ void slotDateTimeFormatChanged(int);
+ void slotDateTimeButtonClicked();
+
+private:
+
+ RenameCustomizerPriv *d;
+};
+
+} // namespace Digikam
+
+#endif /* RENAMECUSTOMIZER_H */
diff --git a/src/utilities/cameragui/umscamera.cpp b/src/utilities/cameragui/umscamera.cpp
new file mode 100644
index 00000000..537c29ba
--- /dev/null
+++ b/src/utilities/cameragui/umscamera.cpp
@@ -0,0 +1,519 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-21
+ * Description : USB Mass Storage camera interface
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utime.h>
+}
+
+// TQt includes.
+
+#include <tqdir.h>
+#include <tqfileinfo.h>
+#include <tqfile.h>
+#include <tqstringlist.h>
+#include <tqdeepcopy.h>
+#include <tqwmatrix.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdefilemetainfo.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/kdcraw.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dmetadata.h"
+#include "umscamera.h"
+
+namespace Digikam
+{
+
+UMSCamera::UMSCamera(const TQString& title, const TQString& model, const TQString& port, const TQString& path)
+ : DKCamera(title, model, port, path)
+{
+ m_cancel = false;
+}
+
+UMSCamera::~UMSCamera()
+{
+}
+
+bool UMSCamera::doConnect()
+{
+ return true;
+}
+
+void UMSCamera::cancel()
+{
+ // set the cancel flag
+ m_cancel = true;
+}
+
+void UMSCamera::getAllFolders(const TQString& folder, TQStringList& subFolderList)
+{
+ m_cancel = false;
+ subFolderList.clear();
+ subFolderList.append(folder);
+ listFolders(folder, subFolderList);
+}
+
+bool UMSCamera::getItemsInfoList(const TQString& folder, GPItemInfoList& infoList, bool getImageDimensions)
+{
+ m_cancel = false;
+ infoList.clear();
+
+ TQDir dir(folder);
+ dir.setFilter(TQDir::Files);
+
+ const TQFileInfoList *list = dir.entryInfoList();
+ if (!list)
+ return false;
+
+ TQFileInfoListIterator it(*list);
+ TQFileInfo *fi;
+ TQFileInfo thmlo, thmup;
+ DMetadata meta;
+
+ while ((fi = it.current()) != 0 && !m_cancel)
+ {
+ ++it;
+
+ TQString mime = mimeType(fi->extension(false).lower());
+
+ if (!mime.isEmpty())
+ {
+ TQSize dims;
+ TQDateTime dt;
+ GPItemInfo info;
+ thmlo.setFile(folder + TQString("/") + fi->baseName() + TQString(".thm"));
+ thmup.setFile(folder + TQString("/") + fi->baseName() + TQString(".THM"));
+
+ if (thmlo.exists())
+ {
+ // Try thumbnail sidecar files with lowercase extension.
+ meta.load(thmlo.filePath());
+ dt = meta.getImageDateTime();
+ dims = meta.getImageDimensions();
+ }
+ else if (thmup.exists())
+ {
+ // Try thumbnail sidecar files with uppercase extension.
+ meta.load(thmup.filePath());
+ dt = meta.getImageDateTime();
+ dims = meta.getImageDimensions();
+ }
+ else if (mime == TQString("image/x-raw"))
+ {
+ // If no thumbnail sidecar file available , try to load image metadata with Raw files.
+ meta.load(fi->filePath());
+ dt = meta.getImageDateTime();
+ dims = meta.getImageDimensions();
+ }
+ else
+ {
+ meta.load(fi->filePath());
+ dt = meta.getImageDateTime();
+ dims = meta.getImageDimensions();
+
+ if (dims.isNull())
+ {
+ // In all others case, try KFileMetaInfo.
+ KFileMetaInfo kmeta(fi->filePath());
+ if (kmeta.isValid())
+ {
+ if (kmeta.containsGroup("Jpeg EXIF Data"))
+ dims = kmeta.group("Jpeg EXIF Data").item("Dimensions").value().toSize();
+ else if (kmeta.containsGroup("General"))
+ dims = kmeta.group("General").item("Dimensions").value().toSize();
+ else if (kmeta.containsGroup("Technical"))
+ dims = kmeta.group("Technical").item("Dimensions").value().toSize();
+ }
+ }
+ }
+
+ if (dt.isNull())
+ {
+ // If date is not found in metadata, use file time stamp
+ dt = fi->created();
+ }
+
+ info.name = fi->fileName();
+ info.folder = !folder.endsWith("/") ? folder + TQString("/") : folder;
+ info.mime = mime;
+ info.mtime = dt.toTime_t();
+ info.size = fi->size();
+ info.width = getImageDimensions ? dims.width() : -1;
+ info.height = getImageDimensions ? dims.height() : -1;
+ info.downloaded = GPItemInfo::DownloadUnknow;
+ info.readPermissions = fi->isReadable();
+ info.writePermissions = fi->isWritable();
+
+ infoList.append(info);
+ }
+ }
+
+ return true;
+}
+
+bool UMSCamera::getThumbnail(const TQString& folder, const TQString& itemName, TQImage& thumbnail)
+{
+ m_cancel = false;
+
+ // JPEG files: try to get thumbnail from Exif data.
+
+ DMetadata metadata(TQFile::encodeName(folder + TQString("/") + itemName));
+ thumbnail = metadata.getExifThumbnail(true);
+ if (!thumbnail.isNull())
+ return true;
+
+ // RAW files : try to extract embedded thumbnail using dcraw
+
+ KDcrawIface::KDcraw::loadDcrawPreview(thumbnail, TQString(folder + TQString("/") + itemName));
+ if (!thumbnail.isNull())
+ return true;
+
+ // THM files: try to get thumbnail from '.thm' files if we didn't manage to get
+ // thumbnail from Exif. Any cameras provides *.thm files like JPEG files with RAW/video files.
+ // Using this way speed up thumbnailization and limit data transfered between camera and computer.
+ // NOTE: the thumbnail extracted with this method can provide a poor quality preview.
+
+ TQFileInfo fi(folder + TQString("/") + itemName);
+
+ if (thumbnail.load(folder + TQString("/") + fi.baseName() + TQString(".thm"))) // Lowercase
+ {
+ if (!thumbnail.isNull())
+ return true;
+ }
+ else if (thumbnail.load(folder + TQString("/") + fi.baseName() + TQString(".THM"))) // Uppercase
+ {
+ if (!thumbnail.isNull())
+ return true;
+ }
+
+ // Finaly, we trying to get thumbnail using DImg API (slow).
+
+ DImg dimgThumb(TQCString(TQFile::encodeName(folder + TQString("/") + itemName)));
+
+ if (!dimgThumb.isNull())
+ {
+ thumbnail = dimgThumb.copyTQImage();
+ return true;
+ }
+
+ return false;
+}
+
+bool UMSCamera::getExif(const TQString&, const TQString&, char **, int&)
+{
+ // not necessary to implement this. read it directly from the file
+ // (done in camera controller)
+ DWarning() << "exif implemented yet in camera controller" << endl;
+ return false;
+}
+
+bool UMSCamera::downloadItem(const TQString& folder, const TQString& itemName, const TQString& saveFile)
+{
+ m_cancel = false;
+ TQString src = folder + TQString("/") + itemName;
+ TQString dest = saveFile;
+
+ TQFile sFile(src);
+ TQFile dFile(dest);
+
+ if ( !sFile.open(IO_ReadOnly) )
+ {
+ DWarning() << "Failed to open source file for reading: "
+ << src << endl;
+ return false;
+ }
+
+ if ( !dFile.open(IO_WriteOnly) )
+ {
+ sFile.close();
+ DWarning() << "Failed to open dest file for writing: "
+ << dest << endl;
+ return false;
+ }
+
+ const int MAX_IPC_SIZE = (1024*32);
+ char buffer[MAX_IPC_SIZE];
+
+ TQ_LONG len;
+ while ((len = sFile.readBlock(buffer, MAX_IPC_SIZE)) != 0 && !m_cancel)
+ {
+ if (len == -1 || dFile.writeBlock(buffer, (TQ_ULONG)len) != len)
+ {
+ sFile.close();
+ dFile.close();
+ return false;
+ }
+ }
+
+ sFile.close();
+ dFile.close();
+
+ // set the file modification time of the downloaded file to that
+ // of the original file
+ struct stat st;
+ ::stat(TQFile::encodeName(src), &st);
+
+ struct utimbuf ut;
+ ut.modtime = st.st_mtime;
+ ut.actime = st.st_atime;
+
+ ::utime(TQFile::encodeName(dest), &ut);
+
+ return true;
+}
+
+bool UMSCamera::setLockItem(const TQString& folder, const TQString& itemName, bool lock)
+{
+ TQString src = folder + TQString("/") + itemName;
+
+ if (lock)
+ {
+ // Lock the file to set read only flag
+ if (::chmod(TQFile::encodeName(src), S_IREAD) == -1)
+ return false;
+ }
+ else
+ {
+ // Unlock the file to set read/write flag
+ if (::chmod(TQFile::encodeName(src), S_IREAD | S_IWRITE) == -1)
+ return false;
+ }
+
+ return true;
+}
+
+bool UMSCamera::deleteItem(const TQString& folder, const TQString& itemName)
+{
+ m_cancel = false;
+
+ // Any camera provide THM (thumbnail) file with real image. We need to remove it also.
+
+ TQFileInfo fi(folder + TQString("/") + itemName);
+
+ TQFileInfo thmLo(folder + TQString("/") + fi.baseName() + ".thm"); // Lowercase
+
+ if (thmLo.exists())
+ ::unlink(TQFile::encodeName(thmLo.filePath()));
+
+ TQFileInfo thmUp(folder + TQString("/") + fi.baseName() + ".THM"); // Uppercase
+
+ if (thmUp.exists())
+ ::unlink(TQFile::encodeName(thmUp.filePath()));
+
+ // Remove the real image.
+ return (::unlink(TQFile::encodeName(folder + TQString("/") + itemName)) == 0);
+}
+
+bool UMSCamera::uploadItem(const TQString& folder, const TQString& itemName, const TQString& localFile,
+ GPItemInfo& info, bool getImageDimensions)
+{
+ m_cancel = false;
+ TQString dest = folder + TQString("/") + itemName;
+ TQString src = localFile;
+
+ TQFile sFile(src);
+ TQFile dFile(dest);
+
+ if ( !sFile.open(IO_ReadOnly) )
+ {
+ DWarning() << "Failed to open source file for reading: "
+ << src << endl;
+ return false;
+ }
+
+ if ( !dFile.open(IO_WriteOnly) )
+ {
+ sFile.close();
+ DWarning() << "Failed to open dest file for writing: "
+ << dest << endl;
+ return false;
+ }
+
+ const int MAX_IPC_SIZE = (1024*32);
+ char buffer[MAX_IPC_SIZE];
+
+ TQ_LONG len;
+ while ((len = sFile.readBlock(buffer, MAX_IPC_SIZE)) != 0 && !m_cancel)
+ {
+ if (len == -1 || dFile.writeBlock(buffer, (TQ_ULONG)len) == -1)
+ {
+ sFile.close();
+ dFile.close();
+ return false;
+ }
+ }
+
+ sFile.close();
+ dFile.close();
+
+ // set the file modification time of the uploaded file to that
+ // of the original file
+ struct stat st;
+ ::stat(TQFile::encodeName(src), &st);
+
+ struct utimbuf ut;
+ ut.modtime = st.st_mtime;
+ ut.actime = st.st_atime;
+
+ ::utime(TQFile::encodeName(dest), &ut);
+
+ // Get new camera item information.
+
+ DMetadata meta;
+ TQFileInfo fi(dest);
+ TQString mime = mimeType(fi.extension(false).lower());
+
+ if (!mime.isEmpty())
+ {
+ TQSize dims;
+ TQDateTime dt;
+
+ if (mime == TQString("image/x-raw"))
+ {
+ // Try to load image metadata with Raw files.
+ meta.load(fi.filePath());
+ dt = meta.getImageDateTime();
+ dims = meta.getImageDimensions();
+ }
+ else
+ {
+ meta.load(fi.filePath());
+ dt = meta.getImageDateTime();
+ dims = meta.getImageDimensions();
+
+ if (dims.isNull())
+ {
+ // In all others case, try KFileMetaInfo.
+ KFileMetaInfo kmeta(fi.filePath());
+ if (kmeta.isValid())
+ {
+ if (kmeta.containsGroup("Jpeg EXIF Data"))
+ dims = kmeta.group("Jpeg EXIF Data").item("Dimensions").value().toSize();
+ else if (kmeta.containsGroup("General"))
+ dims = kmeta.group("General").item("Dimensions").value().toSize();
+ else if (kmeta.containsGroup("Technical"))
+ dims = kmeta.group("Technical").item("Dimensions").value().toSize();
+ }
+ }
+ }
+
+ if (dt.isNull())
+ {
+ // If date is not found in metadata, use file time stamp
+ dt = fi.created();
+ }
+
+ info.name = fi.fileName();
+ info.folder = !folder.endsWith("/") ? folder + TQString("/") : folder;
+ info.mime = mime;
+ info.mtime = dt.toTime_t();
+ info.size = fi.size();
+ info.width = getImageDimensions ? dims.width() : -1;
+ info.height = getImageDimensions ? dims.height() : -1;
+ info.downloaded = GPItemInfo::DownloadUnknow;
+ info.readPermissions = fi.isReadable();
+ info.writePermissions = fi.isWritable();
+ }
+
+ return true;
+}
+
+void UMSCamera::listFolders(const TQString& folder, TQStringList& subFolderList)
+{
+ if (m_cancel)
+ return;
+
+ TQDir dir(folder);
+ dir.setFilter(TQDir::Dirs|TQDir::Executable);
+
+ const TQFileInfoList *list = dir.entryInfoList();
+ if (!list)
+ return;
+
+ TQFileInfoListIterator it( *list );
+ TQFileInfo *fi;
+
+ while ((fi = it.current()) != 0 && !m_cancel)
+ {
+ ++it;
+
+ if (fi->fileName() == "." || fi->fileName() == "..")
+ continue;
+
+ TQString subfolder = folder + TQString(folder.endsWith("/") ? "" : "/") + fi->fileName();
+ subFolderList.append(subfolder);
+ listFolders(subfolder, subFolderList);
+ }
+}
+
+bool UMSCamera::cameraSummary(TQString& summary)
+{
+ summary = TQString(i18n("<b>Mounted Camera</b> driver for USB/IEEE1394 mass storage cameras and "
+ "Flash disk card readers.<br><br>"));
+
+ summary.append(i18n("Title: %1<br>"
+ "Model: %2<br>"
+ "Port: %3<br>"
+ "Path: %4<br>")
+ .arg(title())
+ .arg(model())
+ .arg(port())
+ .arg(path()));
+ return true;
+}
+
+bool UMSCamera::cameraManual(TQString& manual)
+{
+ manual = TQString(i18n("For more information about the <b>Mounted Camera</b> driver, "
+ "please read <b>Supported Digital Still "
+ "Cameras</b> section in the digiKam manual."));
+ return true;
+}
+
+bool UMSCamera::cameraAbout(TQString& about)
+{
+ about = TQString(i18n("The <b>Mounted Camera</b> driver is a simple interface to a camera disk "
+ "mounted locally on your system.<br><br>"
+ "It doesn't use libgphoto2 drivers.<br><br>"
+ "To report any problems with this driver, please contact the digiKam team at:<br><br>"
+ "http://www.digikam.org/?q=contact"));
+ return true;
+}
+
+} // namespace Digikam
diff --git a/src/utilities/cameragui/umscamera.h b/src/utilities/cameragui/umscamera.h
new file mode 100644
index 00000000..697ef615
--- /dev/null
+++ b/src/utilities/cameragui/umscamera.h
@@ -0,0 +1,78 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-21
+ * Description : USB Mass Storage camera interface
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef UMSCAMERA_H
+#define UMSCAMERA_H
+
+// TQt includes.
+
+#include <tqstringlist.h>
+
+// Local includes.
+
+#include "dkcamera.h"
+
+namespace Digikam
+{
+
+class UMSCameraPriv;
+
+class UMSCamera : public DKCamera
+{
+public:
+
+ UMSCamera(const TQString& title, const TQString& model, const TQString& port, const TQString& path);
+ ~UMSCamera();
+
+ bool doConnect();
+ void cancel();
+
+ void getAllFolders(const TQString& folder, TQStringList& subFolderList);
+ bool getItemsInfoList(const TQString& folder, GPItemInfoList& infoList, bool getImageDimensions=true);
+ bool getThumbnail(const TQString& folder, const TQString& itemName, TQImage& thumbnail);
+ bool getExif(const TQString& folder, const TQString& itemName, char **edata, int& esize);
+
+ bool setLockItem(const TQString& folder, const TQString& itemName, bool lock);
+
+ bool downloadItem(const TQString& folder, const TQString& itemName, const TQString& saveFile);
+ bool deleteItem(const TQString& folder, const TQString& itemName);
+ bool uploadItem(const TQString& folder, const TQString& itemName, const TQString& localFile,
+ GPItemInfo& info, bool getImageDimensions=true);
+
+ bool cameraSummary(TQString& summary);
+ bool cameraManual(TQString& manual);
+ bool cameraAbout(TQString& about);
+
+private:
+
+ void listFolders(const TQString& folder, TQStringList& subFolderList);
+
+private:
+
+ bool m_cancel;
+};
+
+} // namespace Digikam
+
+#endif /* UMSCAMERA_H */