|
|
|
/* ============================================================
|
|
|
|
*
|
|
|
|
* 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 <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("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
|