/* ============================================================ * * 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 * Copyright (C) 2006-2009 by Gilles Caulier * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // KDE includes. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if KDE_IS_VERSION(3,2,0) #include #else #include #endif // LibKDcraw includes. #include #include #if KDCRAW_VERSION < 0x000106 #include #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("

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("

Set how digiKam creates albums automatically when downloading.")); TQWhatsThis::add( d->autoAlbumExtCheck, i18n("

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("

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("

Select your preferred date format used to " "create new albums. The options available are:

" "ISO: the date format is in accordance with ISO 8601 " "(YYYY-MM-DD). E.g.: 2006-08-24

" "Full Text: the date format is in a user-readable string. " "E.g.: Thu Aug 24 2006

" "Local Settings: the date format depending on TDE control panel settings.

")); 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("

Set here all options to fix/transform JPEG files automatically " "as they are downloaded.")); TQWhatsThis::add( d->autoRotateCheck, i18n("

Enable this option if you want images automatically " "rotated or flipped using EXIF information provided by the camera.")); TQWhatsThis::add( d->setPhotographerId, i18n("

Enable this option to store the default " "photographer identity in the IPTC tags using digiKam's metadata settings.")); TQWhatsThis::add( d->setCredits, i18n("

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("

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("

Enable this option to automatically convert " "all JPEG files to a lossless image format. Note: Image conversion can take a " "while on a slow computer.")); TQWhatsThis::add( d->losslessFormat, i18n("

Select your preferred lossless image file format to " "convert to. Note: All metadata will be preserved during the conversion.")); d->advBox->insertItem(CameraUIPriv::ONFLYPAGE, onFlyBox, SmallIconSet("system-run"), i18n("On the Fly Operations (JPEG only)")); d->rightSidebar->appendTab(d->advBox, SmallIcon("configure"), i18n("Settings")); d->rightSidebar->loadViewState(); // ------------------------------------------------------------------------- d->cancelBtn = new TQToolButton(plainPage()); d->cancelBtn->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) ); d->cancelBtn->setPixmap( SmallIcon( "cancel" ) ); d->cancelBtn->setEnabled(false); d->status = new KSqueezedTextLabel(plainPage()); d->progress = new KProgress(plainPage()); d->progress->setMaximumHeight( fontMetrics().height()+4 ); d->progress->hide(); TQWidget *frame = new TQWidget(plainPage()); TQHBoxLayout* layout = new TQHBoxLayout(frame); frame->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); KURLLabel *pixmapLogo = new KURLLabel( Digikam::webProjectUrl(), TQString(), frame ); pixmapLogo->setMargin(0); pixmapLogo->setScaledContents( false ); pixmapLogo->setSizePolicy(TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum)); TQToolTip::add(pixmapLogo, i18n("Visit digiKam project website")); TDEGlobal::dirs()->addResourceType("logo-digikam", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); TQString directory = TDEGlobal::dirs()->findResourceDir("logo-digikam", "logo-digikam.png"); pixmapLogo->setPixmap( TQPixmap( directory + "logo-digikam.png" ) ); pixmapLogo->setFocusPolicy(TQWidget::NoFocus); d->anim = new AnimWidget(frame, pixmapLogo->height()-2); layout->setMargin(0); layout->setSpacing(0); layout->addWidget( pixmapLogo ); layout->addWidget( d->anim ); d->freeSpaceWidget = new FreeSpaceWidget(plainPage(), 100); viewBoxLayout->addMultiCellWidget(widget, 0, 0, 0, 7); viewBoxLayout->addMultiCellWidget(d->cancelBtn, 2, 2, 0, 0); viewBoxLayout->addMultiCellWidget(d->status, 2, 2, 2, 2); viewBoxLayout->addMultiCellWidget(d->progress, 2, 2, 3, 3); viewBoxLayout->addMultiCellWidget(d->freeSpaceWidget, 2, 2, 5, 5); viewBoxLayout->addMultiCellWidget(frame, 2, 2, 7, 7); viewBoxLayout->setRowSpacing(1, spacingHint()); viewBoxLayout->setColSpacing(1, spacingHint()); viewBoxLayout->setColSpacing(4, spacingHint()); viewBoxLayout->setColSpacing(6, spacingHint()); viewBoxLayout->setColStretch( 0, 0 ); viewBoxLayout->setColStretch( 1, 0 ); viewBoxLayout->setColStretch( 2, 3 ); viewBoxLayout->setColStretch( 3, 1 ); viewBoxLayout->setColStretch( 4, 0 ); viewBoxLayout->setColStretch( 5, 0 ); viewBoxLayout->setColStretch( 6, 0 ); viewBoxLayout->setColStretch( 7, 0 ); // ------------------------------------------------------------------------- d->imageMenu = new TQPopupMenu(this); d->imageMenu->insertItem(i18n("Select &All"), d->view, TQ_SLOT(slotSelectAll()), CTRL+Key_A, 0); d->imageMenu->insertItem(i18n("Select N&one"), d->view, TQ_SLOT(slotSelectNone()), CTRL+Key_U, 1); d->imageMenu->insertItem(i18n("&Invert Selection"), d->view, TQ_SLOT(slotSelectInvert()), CTRL+Key_Asterisk, 2); d->imageMenu->insertSeparator(); d->imageMenu->insertItem(i18n("Select &New Items"), d->view, TQ_SLOT(slotSelectNew()), 0, 3); d->imageMenu->insertSeparator(); d->imageMenu->insertItem(i18n("Increase Thumbnail Size"), this, TQ_SLOT(slotIncreaseThumbSize()), CTRL+Key_Plus, 4); d->imageMenu->insertItem(i18n("Decrease Thumbnail Size"), this, TQ_SLOT(slotDecreaseThumbSize()), CTRL+Key_Minus, 5); d->imageMenu->insertSeparator(); d->imageMenu->insertItem(i18n("Toggle Lock"), this, TQ_SLOT(slotToggleLock()), 0, 6); actionButton(User3)->setPopup(d->imageMenu); // ------------------------------------------------------------------------- d->downloadMenu = new TQPopupMenu(this); d->downloadMenu->insertItem(i18n("Download Selected"), this, TQ_SLOT(slotDownloadSelected()), 0, 0); d->downloadMenu->insertItem(i18n("Download All"), this, TQ_SLOT(slotDownloadAll()), 0, 1); d->downloadMenu->insertSeparator(); d->downloadMenu->insertItem(i18n("Download/Delete Selected"), this, TQ_SLOT(slotDownloadAndDeleteSelected()), 0, 2); d->downloadMenu->insertItem(i18n("Download/Delete All"), this, TQ_SLOT(slotDownloadAndDeleteAll()), 0, 3); d->downloadMenu->insertSeparator(); d->downloadMenu->insertItem(i18n("Upload..."), this, TQ_SLOT(slotUpload()), 0, 4); d->downloadMenu->setItemEnabled(0, false); d->downloadMenu->setItemEnabled(2, false); actionButton(User2)->setPopup(d->downloadMenu); // ------------------------------------------------------------------------- d->deleteMenu = new TQPopupMenu(this); d->deleteMenu->insertItem(i18n("Delete Selected"), this, TQ_SLOT(slotDeleteSelected()), 0, 0); d->deleteMenu->insertItem(i18n("Delete All"), this, TQ_SLOT(slotDeleteAll()), 0, 1); d->deleteMenu->setItemEnabled(0, false); actionButton(User1)->setPopup(d->deleteMenu); // ------------------------------------------------------------------------- TQPushButton *helpButton = actionButton( Help ); d->helpMenu = new KHelpMenu(this, kapp->aboutData(), false); d->helpMenu->menu()->insertItem(SmallIcon("camera-photo"), i18n("Camera Information"), this, TQ_SLOT(slotInformations()), 0, CAMERA_INFO_MENU_ID, 0); helpButton->setPopup( d->helpMenu->menu() ); // ------------------------------------------------------------------------- connect(d->autoAlbumDateCheck, TQ_SIGNAL(toggled(bool)), d->folderDateFormat, TQ_SLOT(setEnabled(bool))); connect(d->autoAlbumDateCheck, TQ_SIGNAL(toggled(bool)), d->folderDateLabel, TQ_SLOT(setEnabled(bool))); connect(d->convertJpegCheck, TQ_SIGNAL(toggled(bool)), d->losslessFormat, TQ_SLOT(setEnabled(bool))); connect(d->convertJpegCheck, TQ_SIGNAL(toggled(bool)), d->formatLabel, TQ_SLOT(setEnabled(bool))); connect(d->convertJpegCheck, TQ_SIGNAL(toggled(bool)), d->view, TQ_SLOT(slotDownloadNameChanged())); connect(d->fixDateTimeCheck, TQ_SIGNAL(toggled(bool)), d->dateTimeEdit, TQ_SLOT(setEnabled(bool))); connect(pixmapLogo, TQ_SIGNAL(leftClickedURL(const TQString&)), this, TQ_SLOT(slotProcessURL(const TQString&))); // ------------------------------------------------------------------------- connect(d->view, TQ_SIGNAL(signalSelected(CameraIconViewItem*, bool)), this, TQ_SLOT(slotItemsSelected(CameraIconViewItem*, bool))); connect(d->view, TQ_SIGNAL(signalFileView(CameraIconViewItem*)), this, TQ_SLOT(slotFileView(CameraIconViewItem*))); connect(d->view, TQ_SIGNAL(signalUpload(const KURL::List&)), this, TQ_SLOT(slotUploadItems(const KURL::List&))); connect(d->view, TQ_SIGNAL(signalDownload()), this, TQ_SLOT(slotDownloadSelected())); connect(d->view, TQ_SIGNAL(signalDownloadAndDelete()), this, TQ_SLOT(slotDownloadAndDeleteSelected())); connect(d->view, TQ_SIGNAL(signalDelete()), this, TQ_SLOT(slotDeleteSelected())); connect(d->view, TQ_SIGNAL(signalToggleLock()), this, TQ_SLOT(slotToggleLock())); connect(d->view, TQ_SIGNAL(signalNewSelection(bool)), this, TQ_SLOT(slotNewSelection(bool))); // ------------------------------------------------------------------------- connect(d->rightSidebar, TQ_SIGNAL(signalFirstItem()), this, TQ_SLOT(slotFirstItem())); connect(d->rightSidebar, TQ_SIGNAL(signalNextItem()), this, TQ_SLOT(slotNextItem())); connect(d->rightSidebar, TQ_SIGNAL(signalPrevItem()), this, TQ_SLOT(slotPrevItem())); connect(d->rightSidebar, TQ_SIGNAL(signalLastItem()), this, TQ_SLOT(slotLastItem())); // ------------------------------------------------------------------------- connect(d->cancelBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotCancelButton())); // -- Read settings & Check free space availability on album root path ----- readSettings(); // -- camera controller ---------------------------------------------------- d->controller = new CameraController(this, d->cameraTitle, model, port, path); connect(d->controller, TQ_SIGNAL(signalConnected(bool)), this, TQ_SLOT(slotConnected(bool))); connect(d->controller, TQ_SIGNAL(signalInfoMsg(const TQString&)), d->status, TQ_SLOT(setText(const TQString&))); connect(d->controller, TQ_SIGNAL(signalErrorMsg(const TQString&)), this, TQ_SLOT(slotErrorMsg(const TQString&))); connect(d->controller, TQ_SIGNAL(signalCameraInformations(const TQString&, const TQString&, const TQString&)), this, TQ_SLOT(slotCameraInformations(const TQString&, const TQString&, const TQString&))); connect(d->controller, TQ_SIGNAL(signalBusy(bool)), this, TQ_SLOT(slotBusy(bool))); connect(d->controller, TQ_SIGNAL(signalFolderList(const TQStringList&)), this, TQ_SLOT(slotFolderList(const TQStringList&))); connect(d->controller, TQ_SIGNAL(signalFileList(const GPItemInfoList&)), this, TQ_SLOT(slotFileList(const GPItemInfoList&))); connect(d->controller, TQ_SIGNAL(signalThumbnail(const TQString&, const TQString&, const TQImage&)), this, TQ_SLOT(slotThumbnail(const TQString&, const TQString&, const TQImage&))); connect(d->controller, TQ_SIGNAL(signalDownloaded(const TQString&, const TQString&, int)), this, TQ_SLOT(slotDownloaded(const TQString&, const TQString&, int))); connect(d->controller, TQ_SIGNAL(signalSkipped(const TQString&, const TQString&)), this, TQ_SLOT(slotSkipped(const TQString&, const TQString&))); connect(d->controller, TQ_SIGNAL(signalDeleted(const TQString&, const TQString&, bool)), this, TQ_SLOT(slotDeleted(const TQString&, const TQString&, bool))); connect(d->controller, TQ_SIGNAL(signalLocked(const TQString&, const TQString&, bool)), this, TQ_SLOT(slotLocked(const TQString&, const TQString&, bool))); connect(d->controller, TQ_SIGNAL(signalExifFromFile(const TQString&, const TQString&)), this, TQ_SLOT(slotExifFromFile(const TQString&, const TQString&))); connect(d->controller, TQ_SIGNAL(signalExifData(const TQByteArray&)), this, TQ_SLOT(slotExifFromData(const TQByteArray&))); connect(d->controller, TQ_SIGNAL(signalUploaded(const GPItemInfo&)), this, TQ_SLOT(slotUploaded(const GPItemInfo&))); // ------------------------------------------------------------------------- d->view->setFocus(); TQTimer::singleShot(0, d->controller, TQ_SLOT(slotConnect())); } CameraUI::~CameraUI() { delete d->rightSidebar; delete d->controller; delete d; } void CameraUI::readSettings() { TDEConfig* config = kapp->config(); config->setGroup("Camera Settings"); d->advBox->setCurrentIndex(config->readNumEntry("Settings Tab", CameraUIPriv::RENAMEFILEPAGE)); d->autoRotateCheck->setChecked(config->readBoolEntry("AutoRotate", true)); d->autoAlbumDateCheck->setChecked(config->readBoolEntry("AutoAlbumDate", false)); d->autoAlbumExtCheck->setChecked(config->readBoolEntry("AutoAlbumExt", false)); d->fixDateTimeCheck->setChecked(config->readBoolEntry("FixDateTime", false)); d->setPhotographerId->setChecked(config->readBoolEntry("SetPhotographerId", false)); d->setCredits->setChecked(config->readBoolEntry("SetCredits", false)); d->convertJpegCheck->setChecked(config->readBoolEntry("ConvertJpeg", false)); d->losslessFormat->setCurrentItem(config->readNumEntry("LossLessFormat", 0)); // PNG by default d->folderDateFormat->setCurrentItem(config->readNumEntry("FolderDateFormat", CameraUIPriv::IsoDateFormat)); d->view->setThumbnailSize(ThumbnailSize((ThumbnailSize::Size)config->readNumEntry("ThumbnailSize", ThumbnailSize::Large))); if(config->hasKey("Splitter Sizes")) d->splitter->setSizes(config->readIntListEntry("Splitter Sizes")); d->dateTimeEdit->setEnabled(d->fixDateTimeCheck->isChecked()); d->losslessFormat->setEnabled(convertLosslessJpegFiles()); d->formatLabel->setEnabled(convertLosslessJpegFiles()); d->folderDateFormat->setEnabled(d->autoAlbumDateCheck->isChecked()); d->folderDateLabel->setEnabled(d->autoAlbumDateCheck->isChecked()); resize(configDialogSize("Camera Settings")); } void CameraUI::saveSettings() { saveDialogSize("Camera Settings"); TDEConfig* config = kapp->config(); config->setGroup("Camera Settings"); config->writeEntry("Settings Tab", d->advBox->currentIndex()); config->writeEntry("AutoRotate", d->autoRotateCheck->isChecked()); config->writeEntry("AutoAlbumDate", d->autoAlbumDateCheck->isChecked()); config->writeEntry("AutoAlbumExt", d->autoAlbumExtCheck->isChecked()); config->writeEntry("FixDateTime", d->fixDateTimeCheck->isChecked()); config->writeEntry("SetPhotographerId", d->setPhotographerId->isChecked()); config->writeEntry("SetCredits", d->setCredits->isChecked()); config->writeEntry("ConvertJpeg", convertLosslessJpegFiles()); config->writeEntry("LossLessFormat", d->losslessFormat->currentItem()); config->writeEntry("ThumbnailSize", d->view->thumbnailSize().size()); config->writeEntry("Splitter Sizes", d->splitter->sizes()); config->writeEntry("FolderDateFormat", d->folderDateFormat->currentItem()); config->sync(); } void CameraUI::slotProcessURL(const TQString& url) { TDEApplication::kApplication()->invokeBrowser(url); } bool CameraUI::isBusy() const { return d->busy; } bool CameraUI::isClosed() const { return d->closed; } bool CameraUI::convertLosslessJpegFiles() const { return d->convertJpegCheck->isChecked(); } bool CameraUI::autoRotateJpegFiles() const { return d->autoRotateCheck->isChecked(); } TQString CameraUI::losslessFormat() { return d->losslessFormat->currentText(); } TQString CameraUI::cameraTitle() const { return d->cameraTitle; } void CameraUI::slotCancelButton() { d->status->setText(i18n("Cancelling current operation, please wait...")); d->progress->hide(); TQTimer::singleShot(0, d->controller, TQ_SLOT(slotCancel())); d->currentlyDeleting.clear(); } void CameraUI::closeEvent(TQCloseEvent* e) { if (dialogClosed()) e->accept(); else e->ignore(); } void CameraUI::slotClose() { if (dialogClosed()) reject(); } bool CameraUI::dialogClosed() { if (d->closed) return true; if (isBusy()) { if (KMessageBox::questionYesNo(this, i18n("Do you want to close the dialog " "and cancel the current operation?")) == KMessageBox::No) return false; } d->status->setText(i18n("Disconnecting from camera, please wait...")); d->progress->hide(); if (isBusy()) { d->controller->slotCancel(); // will be read in slotBusy later and finishDialog // will be called only when everything is finished d->closed = true; } else { d->closed = true; finishDialog(); } return true; } void CameraUI::finishDialog() { // Look if an item have been downloaded to computer during camera gui session. // If yes, update the lastAccess date property of camera in digiKam camera list. if (d->view->itemsDownloaded() > 0) { CameraList* clist = CameraList::instance(); if (clist) clist->changeCameraAccessTime(d->cameraTitle, TQDateTime::TQDateTime::currentDateTime()); } // When a directory is created, a watch is put on it to spot new files // but it can occur that the file is copied there before the watch is // completely setup. That is why as an extra safeguard run scanlib // over the folders we used. Bug: 119201 d->status->setText(i18n("Scanning for new files, please wait...")); ScanLib sLib; for (TQStringList::iterator it = d->foldersToScan.begin(); it != d->foldersToScan.end(); ++it) { //DDebug() << "Scanning " << (*it) << endl; sLib.findMissingItems( (*it) ); } // Never call finalScan after deleteLater() - ScanLib will call processEvent(), // and the delete event may be executed! deleteLater(); if(!d->lastDestURL.isEmpty()) emit signalLastDestination(d->lastDestURL); saveSettings(); } void CameraUI::slotBusy(bool val) { if (!val) { if (!d->busy) return; d->busy = false; d->cancelBtn->setEnabled(false); d->view->viewport()->setEnabled(true); d->advBox->setEnabled(true); // B.K.O #127614: The Focus need to be restored in custom prefix widget. //commenting this out again: If we do not disable, no need to restore focus //d->renameCustomizer->restoreFocus(); enableButton(User3, true); enableButton(User2, true); enableButton(User1, true); d->helpMenu->menu()->setItemEnabled(CAMERA_INFO_MENU_ID, true); d->anim->stop(); d->status->setText(i18n("Ready")); d->progress->hide(); // like WDestructiveClose, but after camera controller operation has safely finished if (d->closed) { finishDialog(); } } else { if (d->busy) return; if (!d->anim->running()) d->anim->start(); d->busy = true; d->cancelBtn->setEnabled(true); // Has camera icon view item selection is used to control download post processing, // all selection actions are disable when camera interface is busy. d->view->viewport()->setEnabled(false); // Settings tab is disabled in slotDownload, selectively when downloading // Fast dis/enabling would create the impression of flicker, e.g. when retrieving EXIF from camera //d->advBox->setEnabled(false); enableButton(User3, false); enableButton(User2, false); enableButton(User1, false); d->helpMenu->menu()->setItemEnabled(CAMERA_INFO_MENU_ID, false); } } void CameraUI::slotIncreaseThumbSize() { int thumbSize = d->view->thumbnailSize().size(); if (thumbSize >= ThumbnailSize::Huge) return; thumbSize += ThumbnailSize::Step; if (thumbSize >= ThumbnailSize::Huge) { d->imageMenu->setItemEnabled(4, false); } d->imageMenu->setItemEnabled(5, true); d->view->setThumbnailSize(thumbSize); } void CameraUI::slotDecreaseThumbSize() { int thumbSize = d->view->thumbnailSize().size(); if (thumbSize <= ThumbnailSize::Small) return; thumbSize -= ThumbnailSize::Step; if (thumbSize <= ThumbnailSize::Small) { d->imageMenu->setItemEnabled(5, false); } d->imageMenu->setItemEnabled(4, true); d->view->setThumbnailSize(thumbSize); } void CameraUI::slotConnected(bool val) { if (!val) { if (KMessageBox::warningYesNo(this, i18n("Failed to connect to the camera. " "Please make sure it is connected " "properly and turned on. " "Would you like to try again?"), i18n("Connection Failed"), i18n("Retry"), i18n("Abort")) == KMessageBox::Yes) TQTimer::singleShot(0, d->controller, TQ_SLOT(slotConnect())); else close(); } else { d->controller->listFolders(); } } void CameraUI::slotFolderList(const TQStringList& folderList) { if (d->closed) return; d->progress->setProgress(0); d->progress->setTotalSteps(0); d->progress->show(); d->cameraFolderList = folderList; for (TQStringList::const_iterator it = folderList.begin(); it != folderList.end(); ++it) { d->controller->listFiles(*it); } } void CameraUI::slotFileList(const GPItemInfoList& fileList) { if (d->closed) return; if (fileList.empty()) return; kdDebug() << fileList.count() << endl; // We sort the map by time stamp // and we remove internal camera files which are not image/video/sounds. TQStringList fileNames, fileExts; TQFileInfo info; // JVC camera (see B.K.O #133185). fileNames.append("mgr_data"); fileNames.append("pgr_mgr"); // HP Photosmart camera (see B.K.O #156338). fileExts.append("dsp"); // Minolta camera in PTP mode fileExts.append("dps"); // We sort the map by time stamp. GPItemInfoList sfileList; GPItemInfoList::const_iterator it; GPItemInfoList::iterator it2; for(it = fileList.begin() ; it != fileList.end() ; ++it) { info.setFile((*it).name); if (!fileNames.contains(info.fileName().lower()) && !fileExts.contains(info.extension(false).lower())) { kdDebug() << info.fileName() << " : " << (*it).mtime << endl; for(it2 = sfileList.begin() ; it2 != sfileList.end() ; ++it2) if ((*it2).mtime <= (*it).mtime) break; sfileList.insert(it2, *it); } } if (sfileList.empty()) return; kdDebug() << sfileList.count() << endl; GPItemInfoList::const_iterator it3 = sfileList.begin(); do { GPItemInfo item = *it3; if (item.mtime > (time_t)d->lastAccess.toTime_t() && item.downloaded == GPItemInfo::DownloadUnknow) item.downloaded = GPItemInfo::NewPicture; d->view->addItem(item); d->controller->getThumbnail(item.folder, item.name); ++it3; } while(it3 != sfileList.end()); d->progress->setTotalSteps(d->progress->totalSteps() + fileList.count()); } void CameraUI::slotThumbnail(const TQString& folder, const TQString& file, const TQImage& thumbnail) { d->view->setThumbnail(folder, file, thumbnail); int curr = d->progress->progress(); d->progress->setProgress(curr+1); } void CameraUI::slotInformations() { if (d->busy) return; d->controller->getCameraInformations(); } void CameraUI::slotCameraInformations(const TQString& summary, const TQString& manual, const TQString& about) { CameraInfoDialog *infoDlg = new CameraInfoDialog(this, summary, manual, about); infoDlg->show(); } void CameraUI::slotErrorMsg(const TQString& msg) { KMessageBox::error(this, msg); } void CameraUI::slotUpload() { if (d->busy) return; TQString fileformats; TQStringList patternList = TQStringList::split('\n', KImageIO::pattern(KImageIO::Reading)); // All Images from list must been always the first entry given by KDE API TQString allPictures = patternList[0]; // Add RAW file format to All Images" type mime and remplace current. #if KDCRAW_VERSION < 0x000106 allPictures.insert(allPictures.find("|"), TQString(KDcrawIface::DcrawBinary::instance()->rawFiles())); #else allPictures.insert(allPictures.find("|"), TQString(KDcrawIface::KDcraw::rawFiles())); #endif patternList.remove(patternList[0]); patternList.prepend(allPictures); // Added RAW file formats supported by dcraw program like a type mime. // Nota: we cannot use here "image/x-raw" type mime from KDE because it uncomplete // or unavailable(dcraw_0)(see file #121242 in B.K.O). #if KDCRAW_VERSION < 0x000106 patternList.append(TQString("\n%1|Camera RAW files").arg(TQString(KDcrawIface::DcrawBinary::instance()->rawFiles()))); #else patternList.append(TQString("\n%1|Camera RAW files").arg(TQString(KDcrawIface::KDcraw::rawFiles()))); #endif fileformats = patternList.join("\n"); DDebug () << "fileformats=" << fileformats << endl; KURL::List urls = KFileDialog::getOpenURLs(AlbumManager::instance()->getLibraryPath(), fileformats, this, i18n("Select Image to Upload")); if (!urls.isEmpty()) slotUploadItems(urls); } void CameraUI::slotUploadItems(const KURL::List& urls) { if (d->busy) return; if (urls.isEmpty()) return; CameraFolderDialog dlg(this, d->view, d->cameraFolderList, d->controller->getCameraTitle(), d->controller->getCameraPath()); if (dlg.exec() != TQDialog::Accepted) return; TQString cameraFolder = dlg.selectedFolderPath(); for (KURL::List::const_iterator it = urls.begin() ; it != urls.end() ; ++it) { TQFileInfo fi((*it).path()); if (!fi.exists()) continue; if (fi.isDir()) continue; TQString ext = TQString(".") + fi.extension(); TQString name = fi.fileName(); name.truncate(fi.fileName().length() - ext.length()); bool ok; while (d->view->findItem(cameraFolder, name + ext)) { TQString msg(i18n("Camera Folder %1 already contains item %2
" "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(firstItem); TQDateTime dateTime; dateTime.setTime_t(iconItem->itemInfo()->mtime); switch(d->folderDateFormat->currentItem()) { case CameraUIPriv::TextDateFormat: newDirName = dateTime.date().toString(TQt::TextDate); break; case CameraUIPriv::LocalDateFormat: newDirName = dateTime.date().toString(TQt::LocalDate); break; default: // IsoDateFormat newDirName = dateTime.date().toString(TQt::ISODate); break; } } // -- Get the destination album from digiKam library if necessary --------------- if (!album) { AlbumManager* man = AlbumManager::instance(); album = man->currentAlbum(); if (album && album->type() != Album::PHYSICAL) album = 0; TQString header(i18n("

Please select the destination album from the digiKam library to " "import the camera pictures into.

")); album = AlbumSelectDialog::selectAlbum(this, (PAlbum*)album, header, newDirName, d->autoAlbumDateCheck->isChecked()); if (!album) return; } PAlbum *pAlbum = dynamic_cast(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(item); downloadSettings.folder = iconItem->itemInfo()->folder; downloadSettings.file = iconItem->itemInfo()->name; downloadName = iconItem->getDownloadName(); mtime = iconItem->itemInfo()->mtime; KURL u(url); TQString errMsg; TQDateTime dateTime; dateTime.setTime_t(mtime); // Auto sub-albums creation based on file date. if (d->autoAlbumDateCheck->isChecked()) { TQString dirName; switch(d->folderDateFormat->currentItem()) { case CameraUIPriv::TextDateFormat: dirName = dateTime.date().toString(TQt::TextDate); break; case CameraUIPriv::LocalDateFormat: dirName = dateTime.date().toString(TQt::LocalDate); break; default: // IsoDateFormat dirName = dateTime.date().toString(TQt::ISODate); break; } // See B.K.O #136927 : we need to support file system which do not // handle upper case properly. dirName = dirName.lower(); if (!createAutoAlbum(url, dirName, dateTime.date(), errMsg)) { KMessageBox::error(this, errMsg); return; } u.addPath(dirName); } // Auto sub-albums creation based on file extensions. if (d->autoAlbumExtCheck->isChecked()) { // We use the target file name to compute sub-albums name to take a care about // convertion on the fly option. TQFileInfo fi(downloadName); TQString subAlbum = fi.extension(false).upper(); if (fi.extension(false).upper() == TQString("JPEG") || fi.extension(false).upper() == TQString("JPE")) subAlbum = TQString("JPG"); if (fi.extension(false).upper() == TQString("TIFF")) subAlbum = TQString("TIF"); if (fi.extension(false).upper() == TQString("MPEG") || fi.extension(false).upper() == TQString("MPE") || fi.extension(false).upper() == TQString("MPO")) subAlbum = TQString("MPG"); // See B.K.O #136927 : we need to support file system which do not // handle upper case properly. subAlbum = subAlbum.lower(); if (!createAutoAlbum(u, subAlbum, dateTime.date(), errMsg)) { KMessageBox::error(this, errMsg); return; } u.addPath(subAlbum); } d->foldersToScan.append(u.path()); u.addPath(downloadName.isEmpty() ? downloadSettings.file : downloadName); downloadSettings.dest = u.path(); d->controller->download(downloadSettings); addFileExtension(TQFileInfo(u.path()).extension(false)); total++; } if (total <= 0) return; d->lastDestURL = url; d->progress->setProgress(0); d->progress->setTotalSteps(total); d->progress->show(); // disable settings tab here instead of slotBusy: // Only needs to be disabled while downloading d->advBox->setEnabled(false); d->deleteAfter = deleteAfter; } void CameraUI::slotDownloaded(const TQString& folder, const TQString& file, int status) { CameraIconViewItem* iconItem = d->view->findItem(folder, file); if (iconItem) iconItem->setDownloaded(status); if (status == GPItemInfo::DownloadedYes || status == GPItemInfo::DownloadFailed) { int curr = d->progress->progress(); d->progress->setProgress(curr+1); } // Download all items is complete. if (d->progress->progress() == d->progress->totalSteps()) { if (d->deleteAfter) deleteItems(true, true); } } void CameraUI::slotSkipped(const TQString& folder, const TQString& file) { CameraIconViewItem* iconItem = d->view->findItem(folder, file); if (iconItem) iconItem->setDownloaded(GPItemInfo::DownloadedNo); int curr = d->progress->progress(); d->progress->setProgress(curr+1); } void CameraUI::slotToggleLock() { int count = 0; for (IconItem* item = d->view->firstItem(); item; item = item->nextItem()) { CameraIconViewItem* iconItem = static_cast(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(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(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(d->view->firstItem()); d->view->clearSelection(); d->view->updateContents(); if (currItem) d->view->setCurrentItem(currItem); } void CameraUI::slotPrevItem() { CameraIconViewItem *currItem = dynamic_cast(d->view->currentItem()); d->view->clearSelection(); d->view->updateContents(); if (currItem) d->view->setCurrentItem(currItem->prevItem()); } void CameraUI::slotNextItem() { CameraIconViewItem *currItem = dynamic_cast(d->view->currentItem()); d->view->clearSelection(); d->view->updateContents(); if (currItem) d->view->setCurrentItem(currItem->nextItem()); } void CameraUI::slotLastItem(void) { CameraIconViewItem *currItem = dynamic_cast(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