You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digikam/digikam/utilities/cameragui/cameraui.cpp

1735 lines
59 KiB

/* ============================================================
*
* 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 <renchi@pooh.tam.uiuc.edu>
* Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ============================================================ */
#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 <kaboutdata.h>
#include <kmessagebox.h>
#include <kprogress.h>
#include <kglobal.h>
#include <klocale.h>
#include <tdeconfig.h>
#include <kapplication.h>
#include <kiconloader.h>
#include <kpopupmenu.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("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(TQ_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, TQT_SLOT(slotSelectAll()), CTRL+Key_A, 0);
d->imageMenu->insertItem(i18n("Select N&one"), d->view, TQT_SLOT(slotSelectNone()), CTRL+Key_U, 1);
d->imageMenu->insertItem(i18n("&Invert Selection"), d->view, TQT_SLOT(slotSelectInvert()), CTRL+Key_Asterisk, 2);
d->imageMenu->insertSeparator();
d->imageMenu->insertItem(i18n("Select &New Items"), d->view, TQT_SLOT(slotSelectNew()), 0, 3);
d->imageMenu->insertSeparator();
d->imageMenu->insertItem(i18n("Increase Thumbnail Size"), this, TQT_SLOT(slotIncreaseThumbSize()), CTRL+Key_Plus, 4);
d->imageMenu->insertItem(i18n("Decrease Thumbnail Size"), this, TQT_SLOT(slotDecreaseThumbSize()), CTRL+Key_Minus, 5);
d->imageMenu->insertSeparator();
d->imageMenu->insertItem(i18n("Toggle Lock"), this, TQT_SLOT(slotToggleLock()), 0, 6);
actionButton(User3)->setPopup(d->imageMenu);
// -------------------------------------------------------------------------
d->downloadMenu = new TQPopupMenu(this);
d->downloadMenu->insertItem(i18n("Download Selected"),
this, TQT_SLOT(slotDownloadSelected()), 0, 0);
d->downloadMenu->insertItem(i18n("Download All"),
this, TQT_SLOT(slotDownloadAll()), 0, 1);
d->downloadMenu->insertSeparator();
d->downloadMenu->insertItem(i18n("Download/Delete Selected"),
this, TQT_SLOT(slotDownloadAndDeleteSelected()), 0, 2);
d->downloadMenu->insertItem(i18n("Download/Delete All"),
this, TQT_SLOT(slotDownloadAndDeleteAll()), 0, 3);
d->downloadMenu->insertSeparator();
d->downloadMenu->insertItem(i18n("Upload..."),
this, TQT_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, TQT_SLOT(slotDeleteSelected()), 0, 0);
d->deleteMenu->insertItem(i18n("Delete All"), this, TQT_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"), i18n("Camera Information"),
this, TQT_SLOT(slotInformations()), 0, CAMERA_INFO_MENU_ID, 0);
helpButton->setPopup( d->helpMenu->menu() );
// -------------------------------------------------------------------------
connect(d->autoAlbumDateCheck, TQT_SIGNAL(toggled(bool)),
d->folderDateFormat, TQT_SLOT(setEnabled(bool)));
connect(d->autoAlbumDateCheck, TQT_SIGNAL(toggled(bool)),
d->folderDateLabel, TQT_SLOT(setEnabled(bool)));
connect(d->convertJpegCheck, TQT_SIGNAL(toggled(bool)),
d->losslessFormat, TQT_SLOT(setEnabled(bool)));
connect(d->convertJpegCheck, TQT_SIGNAL(toggled(bool)),
d->formatLabel, TQT_SLOT(setEnabled(bool)));
connect(d->convertJpegCheck, TQT_SIGNAL(toggled(bool)),
d->view, TQT_SLOT(slotDownloadNameChanged()));
connect(d->fixDateTimeCheck, TQT_SIGNAL(toggled(bool)),
d->dateTimeEdit, TQT_SLOT(setEnabled(bool)));
connect(pixmapLogo, TQT_SIGNAL(leftClickedURL(const TQString&)),
this, TQT_SLOT(slotProcessURL(const TQString&)));
// -------------------------------------------------------------------------
connect(d->view, TQT_SIGNAL(signalSelected(CameraIconViewItem*, bool)),
this, TQT_SLOT(slotItemsSelected(CameraIconViewItem*, bool)));
connect(d->view, TQT_SIGNAL(signalFileView(CameraIconViewItem*)),
this, TQT_SLOT(slotFileView(CameraIconViewItem*)));
connect(d->view, TQT_SIGNAL(signalUpload(const KURL::List&)),
this, TQT_SLOT(slotUploadItems(const KURL::List&)));
connect(d->view, TQT_SIGNAL(signalDownload()),
this, TQT_SLOT(slotDownloadSelected()));
connect(d->view, TQT_SIGNAL(signalDownloadAndDelete()),
this, TQT_SLOT(slotDownloadAndDeleteSelected()));
connect(d->view, TQT_SIGNAL(signalDelete()),
this, TQT_SLOT(slotDeleteSelected()));
connect(d->view, TQT_SIGNAL(signalToggleLock()),
this, TQT_SLOT(slotToggleLock()));
connect(d->view, TQT_SIGNAL(signalNewSelection(bool)),
this, TQT_SLOT(slotNewSelection(bool)));
// -------------------------------------------------------------------------
connect(d->rightSidebar, TQT_SIGNAL(signalFirstItem()),
this, TQT_SLOT(slotFirstItem()));
connect(d->rightSidebar, TQT_SIGNAL(signalNextItem()),
this, TQT_SLOT(slotNextItem()));
connect(d->rightSidebar, TQT_SIGNAL(signalPrevItem()),
this, TQT_SLOT(slotPrevItem()));
connect(d->rightSidebar, TQT_SIGNAL(signalLastItem()),
this, TQT_SLOT(slotLastItem()));
// -------------------------------------------------------------------------
connect(d->cancelBtn, TQT_SIGNAL(clicked()),
this, TQT_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, TQT_SIGNAL(signalConnected(bool)),
this, TQT_SLOT(slotConnected(bool)));
connect(d->controller, TQT_SIGNAL(signalInfoMsg(const TQString&)),
d->status, TQT_SLOT(setText(const TQString&)));
connect(d->controller, TQT_SIGNAL(signalErrorMsg(const TQString&)),
this, TQT_SLOT(slotErrorMsg(const TQString&)));
connect(d->controller, TQT_SIGNAL(signalCameraInformations(const TQString&, const TQString&, const TQString&)),
this, TQT_SLOT(slotCameraInformations(const TQString&, const TQString&, const TQString&)));
connect(d->controller, TQT_SIGNAL(signalBusy(bool)),
this, TQT_SLOT(slotBusy(bool)));
connect(d->controller, TQT_SIGNAL(signalFolderList(const TQStringList&)),
this, TQT_SLOT(slotFolderList(const TQStringList&)));
connect(d->controller, TQT_SIGNAL(signalFileList(const GPItemInfoList&)),
this, TQT_SLOT(slotFileList(const GPItemInfoList&)));
connect(d->controller, TQT_SIGNAL(signalThumbnail(const TQString&, const TQString&, const TQImage&)),
this, TQT_SLOT(slotThumbnail(const TQString&, const TQString&, const TQImage&)));
connect(d->controller, TQT_SIGNAL(signalDownloaded(const TQString&, const TQString&, int)),
this, TQT_SLOT(slotDownloaded(const TQString&, const TQString&, int)));
connect(d->controller, TQT_SIGNAL(signalSkipped(const TQString&, const TQString&)),
this, TQT_SLOT(slotSkipped(const TQString&, const TQString&)));
connect(d->controller, TQT_SIGNAL(signalDeleted(const TQString&, const TQString&, bool)),
this, TQT_SLOT(slotDeleted(const TQString&, const TQString&, bool)));
connect(d->controller, TQT_SIGNAL(signalLocked(const TQString&, const TQString&, bool)),
this, TQT_SLOT(slotLocked(const TQString&, const TQString&, bool)));
connect(d->controller, TQT_SIGNAL(signalExifFromFile(const TQString&, const TQString&)),
this, TQT_SLOT(slotExifFromFile(const TQString&, const TQString&)));
connect(d->controller, TQT_SIGNAL(signalExifData(const TQByteArray&)),
this, TQT_SLOT(slotExifFromData(const TQByteArray&)));
connect(d->controller, TQT_SIGNAL(signalUploaded(const GPItemInfo&)),
this, TQT_SLOT(slotUploaded(const GPItemInfo&)));
// -------------------------------------------------------------------------
d->view->setFocus();
TQTimer::singleShot(0, d->controller, TQT_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, TQT_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, TQT_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(Qt::TextDate);
break;
case CameraUIPriv::LocalDateFormat:
newDirName = dateTime.date().toString(Qt::LocalDate);
break;
default: // IsoDateFormat
newDirName = dateTime.date().toString(Qt::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(Qt::TextDate);
break;
case CameraUIPriv::LocalDateFormat:
dirName = dateTime.date().toString(Qt::LocalDate);
break;
default: // IsoDateFormat
dirName = dateTime.date().toString(Qt::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