File indexing completed on 2025-01-19 03:59:23
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2004-09-16 0007 * Description : Import tool interface 0008 * 0009 * SPDX-FileCopyrightText: 2004-2005 by Renchi Raju <renchi dot raju at gmail dot com> 0010 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0012 * SPDX-FileCopyrightText: 2012 by Andi Clemens <andi dot clemens at gmail dot com> 0013 * SPDX-FileCopyrightText: 2012 by Islam Wazery <wazery at ubuntu dot com> 0014 * 0015 * SPDX-License-Identifier: GPL-2.0-or-later 0016 * 0017 * ============================================================ */ 0018 0019 #include "importui_p.h" 0020 0021 namespace Digikam 0022 { 0023 0024 ImportUI* ImportUI::m_instance = nullptr; 0025 0026 ImportUI::ImportUI(const QString& cameraTitle, const QString& model, 0027 const QString& port, const QString& path, int startIndex) 0028 : DXmlGuiWindow(nullptr), 0029 d (new Private) 0030 { 0031 setConfigGroupName(QLatin1String("Camera Settings")); 0032 0033 setXMLFile(QLatin1String("importui5.rc")); 0034 setFullScreenOptions(FS_IMPORTUI); 0035 setWindowFlags(Qt::Window); 0036 0037 m_instance = this; 0038 0039 // -------------------------------------------------------- 0040 0041 QString title = CameraNameHelper::cameraName(cameraTitle); 0042 d->cameraTitle = (title.isEmpty()) ? cameraTitle : title; 0043 setCaption(d->cameraTitle); 0044 0045 setupCameraController(model, port, path); 0046 setupUserArea(); 0047 setInitialSorting(); 0048 setupActions(); 0049 setupStatusBar(); 0050 setupAccelerators(); 0051 0052 // -- Make signals/slots connections --------------------------------- 0053 0054 setupConnections(); 0055 sidebarTabTitleStyleChanged(); 0056 slotColorManagementOptionsChanged(); 0057 0058 // -- Read settings -------------------------------------------------- 0059 0060 readSettings(); 0061 setAutoSaveSettings(configGroupName(), true); 0062 0063 // ------------------------------------------------------------------- 0064 0065 //d->historyUpdater = new CameraHistoryUpdater(this); 0066 0067 //connect (d->historyUpdater, SIGNAL(signalHistoryMap(CHUpdateItemMap)), 0068 //this, SLOT(slotRefreshIconView(CHUpdateItemMap))); 0069 0070 //connect(d->historyUpdater, SIGNAL(signalBusy(bool)), 0071 // this, SLOT(slotBusy(bool))); 0072 0073 // -------------------------------------------------------- 0074 0075 d->progressTimer = new QTimer(this); 0076 0077 connect(d->progressTimer, SIGNAL(timeout()), 0078 this, SLOT(slotProgressTimerDone())); 0079 0080 // -------------------------------------------------------- 0081 0082 d->renameCustomizer->setStartIndex(startIndex); 0083 d->view->setFocus(); 0084 0085 // -- Init icon view zoom factor -------------------------- 0086 0087 slotThumbSizeChanged(ImportSettings::instance()->getDefaultIconSize()); 0088 slotZoomSliderChanged(ImportSettings::instance()->getDefaultIconSize()); 0089 0090 // try to connect in the end, this allows us not to block the UI to show up.. 0091 QTimer::singleShot(0, d->controller, SLOT(slotConnect())); 0092 } 0093 0094 ImportUI::~ImportUI() 0095 { 0096 saveSettings(); 0097 disconnect(d->view, nullptr, this, nullptr); 0098 0099 delete d->view; 0100 delete d->rightSideBar; 0101 delete d->controller; 0102 0103 m_instance = nullptr; 0104 0105 delete d; 0106 } 0107 0108 ImportUI* ImportUI::instance() 0109 { 0110 return m_instance; 0111 } 0112 0113 void ImportUI::setupUserArea() 0114 { 0115 DHBox* const widget = new DHBox(this); 0116 d->splitter = new SidebarSplitter(widget); 0117 DVBox* const vbox = new DVBox(d->splitter); 0118 d->view = new ImportView(this, vbox); 0119 d->view->importFilterModel()->setCameraThumbsController(d->camThumbsCtrl); 0120 d->view->importFilterModel()->setStringTypeNatural(ApplicationSettings::instance()->isStringTypeNatural()); 0121 d->historyView = new DHistoryView(vbox); 0122 d->rightSideBar = new ImportItemPropertiesSideBarImport(widget, d->splitter, Qt::RightEdge, true); 0123 d->rightSideBar->setObjectName(QLatin1String("CameraGui Sidebar Right")); 0124 d->splitter->setFrameStyle(QFrame::NoFrame); 0125 d->splitter->setFrameShadow(QFrame::Plain); 0126 d->splitter->setFrameShape(QFrame::NoFrame); 0127 d->splitter->setOpaqueResize(false); 0128 d->splitter->setStretchFactor(d->splitter->indexOf(vbox), 10); // set iconview default size to max. 0129 0130 vbox->setStretchFactor(d->view, 10); 0131 vbox->setStretchFactor(d->historyView, 2); 0132 vbox->setContentsMargins(QMargins()); 0133 vbox->setSpacing(0); 0134 0135 d->errorWidget = new DNotificationWidget(vbox); 0136 d->errorWidget->setMessageType(DNotificationWidget::Error); 0137 d->errorWidget->setCloseButtonVisible(false); 0138 d->errorWidget->hide(); 0139 0140 // ------------------------------------------------------------------------- 0141 0142 d->advBox = new DExpanderBox(d->rightSideBar); 0143 d->advBox->setObjectName(QLatin1String("Camera Settings Expander")); 0144 0145 d->renameCustomizer = new RenameCustomizer(d->advBox, d->cameraTitle); 0146 d->renameCustomizer->setWhatsThis(i18nc("@info", "Set how digiKam will rename files as they are downloaded.")); 0147 d->advBox->addItem(d->renameCustomizer, QIcon::fromTheme(QLatin1String("insert-image")), i18nc("@item", "File Renaming Options"), 0148 QLatin1String("RenameCustomizer"), true); 0149 0150 // -- Albums Auto-creation options ----------------------------------------- 0151 0152 d->albumCustomizer = new AlbumCustomizer(d->advBox); 0153 d->advBox->addItem(d->albumCustomizer, QIcon::fromTheme(QLatin1String("folder-new")), i18nc("@item", "Auto-creation of Albums"), 0154 QLatin1String("AlbumBox"), false); 0155 0156 // -- On the Fly options --------------------------------------------------- 0157 0158 d->advancedSettings = new AdvancedSettings(d->advBox); 0159 d->advBox->addItem(d->advancedSettings, QIcon::fromTheme(QLatin1String("system-run")), i18nc("@item", "On the Fly Operations (JPEG only)"), 0160 QLatin1String("OnFlyBox"), true); 0161 0162 // -- DNG convert options -------------------------------------------------- 0163 0164 d->dngConvertSettings = new DNGConvertSettings(d->advBox); 0165 d->advBox->addItem(d->dngConvertSettings, QIcon::fromTheme(QLatin1String("image-x-adobe-dng")), i18nc("@item", "DNG Convert Options"), 0166 QLatin1String("DNGSettings"), false); 0167 0168 // -- Scripting options ---------------------------------------------------- 0169 0170 d->scriptingSettings = new ScriptingSettings(d->advBox); 0171 d->advBox->addItem(d->scriptingSettings, QIcon::fromTheme(QLatin1String("utilities-terminal")), i18nc("@item", "Scripting"), 0172 QLatin1String("ScriptingBox"), false); 0173 d->advBox->addStretch(); 0174 0175 d->rightSideBar->appendTab(d->advBox, QIcon::fromTheme(QLatin1String("configure")), i18nc("@title", "Settings")); 0176 d->rightSideBar->loadState(); 0177 0178 // ------------------------------------------------------------------------- 0179 0180 setCentralWidget(widget); 0181 } 0182 0183 void ImportUI::setupActions() 0184 { 0185 d->cameraActions = new QActionGroup(this); 0186 KActionCollection* const ac = actionCollection(); 0187 0188 // -- File menu ---------------------------------------------------- 0189 0190 d->cameraCancelAction = new QAction(QIcon::fromTheme(QLatin1String("process-stop")), i18nc("@action Cancel process", "Cancel"), this); 0191 connect(d->cameraCancelAction, SIGNAL(triggered()), this, SLOT(slotCancelButton())); 0192 ac->addAction(QLatin1String("importui_cancelprocess"), d->cameraCancelAction); 0193 d->cameraCancelAction->setEnabled(false); 0194 0195 // ----------------------------------------------------------------- 0196 0197 d->cameraInfoAction = new QAction(QIcon::fromTheme(QLatin1String("camera-photo")), i18nc("@action Information about camera", "Information"), this); 0198 connect(d->cameraInfoAction, SIGNAL(triggered()), this, SLOT(slotInformation())); 0199 ac->addAction(QLatin1String("importui_info"), d->cameraInfoAction); 0200 d->cameraActions->addAction(d->cameraInfoAction); 0201 0202 // ----------------------------------------------------------------- 0203 0204 d->cameraCaptureAction = new QAction(QIcon::fromTheme(QLatin1String("webcamreceive")), i18nc("@action Capture photo from camera", "Capture"), this); 0205 connect(d->cameraCaptureAction, SIGNAL(triggered()), this, SLOT(slotCapture())); 0206 ac->addAction(QLatin1String("importui_capture"), d->cameraCaptureAction); 0207 d->cameraActions->addAction(d->cameraCaptureAction); 0208 0209 // ----------------------------------------------------------------- 0210 0211 QAction* const closeAction = buildStdAction(StdCloseAction, this, SLOT(slotClose()), this); 0212 ac->addAction(QLatin1String("importui_close"), closeAction); 0213 0214 // -- Edit menu ---------------------------------------------------- 0215 0216 d->selectAllAction = new QAction(i18nc("@action:inmenu", "Select All"), this); 0217 connect(d->selectAllAction, SIGNAL(triggered()), d->view, SLOT(slotSelectAll())); 0218 ac->addAction(QLatin1String("importui_selectall"), d->selectAllAction); 0219 ac->setDefaultShortcut(d->selectAllAction, Qt::CTRL | Qt::Key_A); 0220 d->cameraActions->addAction(d->selectAllAction); 0221 0222 // ----------------------------------------------------------------- 0223 0224 d->selectNoneAction = new QAction(i18nc("@action:inmenu", "Select None"), this); 0225 connect(d->selectNoneAction, SIGNAL(triggered()), d->view, SLOT(slotSelectNone())); 0226 ac->addAction(QLatin1String("importui_selectnone"), d->selectNoneAction); 0227 ac->setDefaultShortcut(d->selectNoneAction, Qt::CTRL | Qt::SHIFT | Qt::Key_A); 0228 d->cameraActions->addAction(d->selectNoneAction); 0229 0230 // ----------------------------------------------------------------- 0231 0232 d->selectInvertAction = new QAction(i18nc("@action:inmenu", "Invert Selection"), this); 0233 connect(d->selectInvertAction, SIGNAL(triggered()), d->view, SLOT(slotSelectInvert())); 0234 ac->addAction(QLatin1String("importui_selectinvert"), d->selectInvertAction); 0235 ac->setDefaultShortcut(d->selectInvertAction, Qt::CTRL | Qt::Key_Asterisk); 0236 d->cameraActions->addAction(d->selectInvertAction); 0237 0238 // ----------------------------------------------------------- 0239 0240 d->selectNewItemsAction = new QAction(QIcon::fromTheme(QLatin1String("folder-favorites")), i18nc("@action:inmenu", "Select New Items"), this); 0241 connect(d->selectNewItemsAction, SIGNAL(triggered()), this, SLOT(slotSelectNew())); 0242 ac->addAction(QLatin1String("importui_selectnewitems"), d->selectNewItemsAction); 0243 d->cameraActions->addAction(d->selectNewItemsAction); 0244 0245 // ----------------------------------------------------------- 0246 0247 d->selectLockedItemsAction = new QAction(QIcon::fromTheme(QLatin1String("object-locked")), i18nc("@action:inmenu", "Select Locked Items"), this); 0248 connect(d->selectLockedItemsAction, SIGNAL(triggered()), this, SLOT(slotSelectLocked())); 0249 ac->addAction(QLatin1String("importui_selectlockeditems"), d->selectLockedItemsAction); 0250 ac->setDefaultShortcut(d->selectLockedItemsAction, Qt::CTRL | Qt::Key_L); 0251 d->cameraActions->addAction(d->selectLockedItemsAction); 0252 0253 // --- Download actions ---------------------------------------------------- 0254 0255 d->downloadAction = new QMenu(i18nc("@title:menu", "Download"), this); 0256 d->downloadAction->setIcon(QIcon::fromTheme(QLatin1String("document-save"))); 0257 ac->addAction(QLatin1String("importui_imagedownload"), d->downloadAction->menuAction()); 0258 d->cameraActions->addAction(d->downloadAction->menuAction()); 0259 0260 d->downloadNewAction = new QAction(QIcon::fromTheme(QLatin1String("folder-favorites")), i18nc("@action", "Download New"), this); 0261 connect(d->downloadNewAction, SIGNAL(triggered()), this, SLOT(slotDownloadNew())); 0262 ac->addAction(QLatin1String("importui_imagedownloadnew"), d->downloadNewAction); 0263 ac->setDefaultShortcut(d->downloadNewAction, Qt::CTRL | Qt::Key_N); 0264 d->downloadAction->addAction(d->downloadNewAction); 0265 d->cameraActions->addAction(d->downloadNewAction); 0266 0267 connect(d->downloadAction->menuAction(), SIGNAL(triggered()), 0268 d->downloadNewAction, SLOT(trigger())); 0269 0270 d->downloadSelectedAction = new QAction(QIcon::fromTheme(QLatin1String("document-save")), i18nc("@action", "Download Selected"), this); 0271 connect(d->downloadSelectedAction, SIGNAL(triggered()), this, SLOT(slotDownloadSelected())); 0272 ac->addAction(QLatin1String("importui_imagedownloadselected"), d->downloadSelectedAction); 0273 d->downloadSelectedAction->setEnabled(false); 0274 d->downloadAction->addAction(d->downloadSelectedAction); 0275 d->cameraActions->addAction(d->downloadSelectedAction); 0276 0277 d->downloadAllAction = new QAction(QIcon::fromTheme(QLatin1String("document-save")), i18nc("@action", "Download All"), this); 0278 connect(d->downloadAllAction, SIGNAL(triggered()), this, SLOT(slotDownloadAll())); 0279 ac->addAction(QLatin1String("importui_imagedownloadall"), d->downloadAllAction); 0280 d->downloadAction->addAction(d->downloadAllAction); 0281 d->cameraActions->addAction(d->downloadAllAction); 0282 0283 // ------------------------------------------------------------------------- 0284 0285 d->downloadDelNewAction = new QAction(i18nc("@action", "Download && Delete New"), this); 0286 connect(d->downloadDelNewAction, SIGNAL(triggered()), this, SLOT(slotDownloadAndDeleteNew())); 0287 ac->addAction(QLatin1String("importui_imagedownloaddeletenew"), d->downloadDelNewAction); 0288 ac->setDefaultShortcut(d->downloadDelNewAction, Qt::CTRL | Qt::SHIFT | Qt::Key_N); 0289 d->cameraActions->addAction(d->downloadDelNewAction); 0290 0291 // ----------------------------------------------------------------- 0292 0293 d->downloadDelSelectedAction = new QAction(i18nc("@action", "Download && Delete Selected"), this); 0294 connect(d->downloadDelSelectedAction, SIGNAL(triggered()), this, SLOT(slotDownloadAndDeleteSelected())); 0295 ac->addAction(QLatin1String("importui_imagedownloaddeleteselected"), d->downloadDelSelectedAction); 0296 d->downloadDelSelectedAction->setEnabled(false); 0297 d->cameraActions->addAction(d->downloadDelSelectedAction); 0298 0299 // ------------------------------------------------------------------------- 0300 0301 d->downloadDelAllAction = new QAction(i18nc("@action", "Download && Delete All"), this); 0302 connect(d->downloadDelAllAction, SIGNAL(triggered()), this, SLOT(slotDownloadAndDeleteAll())); 0303 ac->addAction(QLatin1String("importui_imagedownloaddeleteall"), d->downloadDelAllAction); 0304 d->cameraActions->addAction(d->downloadDelAllAction); 0305 0306 // ------------------------------------------------------------------------- 0307 0308 d->uploadAction = new QAction(QIcon::fromTheme(QLatin1String("media-flash-sd-mmc")), i18nc("@action", "Upload..."), this); 0309 connect(d->uploadAction, SIGNAL(triggered()), this, SLOT(slotUpload())); 0310 ac->addAction(QLatin1String("importui_imageupload"), d->uploadAction); 0311 ac->setDefaultShortcut(d->uploadAction, Qt::CTRL | Qt::Key_U); 0312 d->cameraActions->addAction(d->uploadAction); 0313 0314 // ------------------------------------------------------------------------- 0315 0316 d->lockAction = new QAction(QIcon::fromTheme(QLatin1String("object-locked")), i18nc("@action", "Toggle Lock"), this); 0317 connect(d->lockAction, SIGNAL(triggered()), this, SLOT(slotToggleLock())); 0318 ac->addAction(QLatin1String("importui_imagelock"), d->lockAction); 0319 ac->setDefaultShortcut(d->lockAction, Qt::CTRL | Qt::Key_G); 0320 d->cameraActions->addAction(d->lockAction); 0321 0322 // ------------------------------------------------------------------------- 0323 0324 d->markAsDownloadedAction = new QAction(QIcon::fromTheme(QLatin1String("dialog-ok-apply")), i18nc("@action", "Mark as downloaded"), this); 0325 connect(d->markAsDownloadedAction, SIGNAL(triggered()), this, SLOT(slotMarkAsDownloaded())); 0326 ac->addAction(QLatin1String("importui_imagemarkasdownloaded"), d->markAsDownloadedAction); 0327 d->cameraActions->addAction(d->markAsDownloadedAction); 0328 0329 // --- Delete actions ------------------------------------------------------ 0330 0331 d->deleteAction = new QMenu(i18nc("@title:menu", "Delete"), this); 0332 d->deleteAction->setIcon(QIcon::fromTheme(QLatin1String("edit-delete"))); 0333 ac->addAction(QLatin1String("importui_delete"), d->deleteAction->menuAction()); 0334 d->cameraActions->addAction(d->deleteAction->menuAction()); 0335 0336 d->deleteSelectedAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("@action:inmenu delete item", "Delete Selected"), this); 0337 connect(d->deleteSelectedAction, SIGNAL(triggered()), this, SLOT(slotDeleteSelected())); 0338 ac->addAction(QLatin1String("importui_imagedeleteselected"), d->deleteSelectedAction); 0339 ac->setDefaultShortcut(d->deleteSelectedAction, Qt::Key_Delete); 0340 d->deleteSelectedAction->setEnabled(false); 0341 d->deleteAction->addAction(d->deleteSelectedAction); 0342 d->cameraActions->addAction(d->deleteSelectedAction); 0343 0344 d->deleteAllAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("@action:inmenu delete item", "Delete All"), this); 0345 connect(d->deleteAllAction, SIGNAL(triggered()), this, SLOT(slotDeleteAll())); 0346 ac->addAction(QLatin1String("importui_imagedeleteall"), d->deleteAllAction); 0347 d->deleteAction->addAction(d->deleteAllAction); 0348 d->cameraActions->addAction(d->deleteAllAction); 0349 0350 d->deleteNewAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("@action:inmenu delete item", "Delete New"), this); 0351 connect(d->deleteNewAction, SIGNAL(triggered()), this, SLOT(slotDeleteNew())); 0352 ac->addAction(QLatin1String("importui_imagedeletenew"), d->deleteNewAction); 0353 d->deleteAction->addAction(d->deleteNewAction); 0354 d->cameraActions->addAction(d->deleteNewAction); 0355 0356 // --- Icon view, items preview, and map actions ------------------------------------------------------ 0357 0358 d->imageViewSelectionAction = new KSelectAction(QIcon::fromTheme(QLatin1String("view-preview")), i18nc("@title:group", "Views"), this); 0359 ac->addAction(QLatin1String("importui_view_selection"), d->imageViewSelectionAction); 0360 0361 d->iconViewAction = new QAction(QIcon::fromTheme(QLatin1String("view-list-icons")), 0362 i18nc("@action Go to thumbnails (icon) view", "Thumbnails"), this); 0363 d->iconViewAction->setCheckable(true); 0364 ac->addAction(QLatin1String("importui_icon_view"), d->iconViewAction); 0365 connect(d->iconViewAction, SIGNAL(triggered()), d->view, SLOT(slotIconView())); 0366 d->imageViewSelectionAction->addAction(d->iconViewAction); 0367 0368 d->camItemPreviewAction = new QAction(QIcon::fromTheme(QLatin1String("view-preview")), 0369 i18nc("@action View the selected image", "Preview Item"), this); 0370 d->camItemPreviewAction->setCheckable(true); 0371 ac->addAction(QLatin1String("importui_item_view"), d->camItemPreviewAction); 0372 ac->setDefaultShortcut(d->camItemPreviewAction, Qt::Key_F3); 0373 connect(d->camItemPreviewAction, SIGNAL(triggered()), d->view, SLOT(slotImagePreview())); 0374 d->imageViewSelectionAction->addAction(d->camItemPreviewAction); 0375 0376 #ifdef HAVE_GEOLOCATION 0377 d->mapViewAction = new QAction(QIcon::fromTheme(QLatin1String("globe")), 0378 i18nc("@action Switch to map view", "Map"), this); 0379 d->mapViewAction->setCheckable(true); 0380 ac->addAction(QLatin1String("importui_map_view"), d->mapViewAction); 0381 connect(d->mapViewAction, SIGNAL(triggered()), d->view, SLOT(slotMapWidgetView())); 0382 d->imageViewSelectionAction->addAction(d->mapViewAction); 0383 #endif // HAVE_GEOLOCATION 0384 0385 /// @todo Add table view stuff here 0386 0387 // -- Item Sorting ------------------------------------------------------------ 0388 0389 d->itemSortAction = new KSelectAction(i18nc("@title:menu", "&Sort Items"), this); 0390 d->itemSortAction->setWhatsThis(i18nc("@info:whatsthis", "The value by which the items are sorted in the thumbnail view")); 0391 ac->addAction(QLatin1String("item_sort"), d->itemSortAction); 0392 0393 // map to CamItemSortSettings enum 0394 QAction* const sortByNameAction = d->itemSortAction->addAction(i18nc("@item:inmenu Sort by", "By Name")); 0395 QAction* const sortByPathAction = d->itemSortAction->addAction(i18nc("@item:inmenu Sort by", "By Path")); 0396 QAction* const sortByDateAction = d->itemSortAction->addAction(i18nc("@item:inmenu Sort by", "By Date")); 0397 QAction* const sortByFileSizeAction = d->itemSortAction->addAction(i18nc("@item:inmenu Sort by", "By Size")); 0398 QAction* const sortByRatingAction = d->itemSortAction->addAction(i18nc("@item:inmenu Sort by", "By Rating")); 0399 QAction* const sortByDownloadAction = d->itemSortAction->addAction(i18nc("@item:inmenu Sort by", "By Download State")); 0400 0401 connect(sortByNameAction, &QAction::triggered, 0402 this, [this]() { d->view->slotSortImagesBy((int)CamItemSortSettings::SortByFileName); }); 0403 0404 connect(sortByPathAction, &QAction::triggered, 0405 this, [this]() { d->view->slotSortImagesBy((int)CamItemSortSettings::SortByFilePath); }); 0406 0407 connect(sortByDateAction, &QAction::triggered, 0408 this, [this]() { d->view->slotSortImagesBy((int)CamItemSortSettings::SortByCreationDate); }); 0409 0410 connect(sortByFileSizeAction, &QAction::triggered, 0411 this, [this]() { d->view->slotSortImagesBy((int)CamItemSortSettings::SortByFileSize); }); 0412 0413 connect(sortByRatingAction, &QAction::triggered, 0414 this, [this]() { d->view->slotSortImagesBy((int)CamItemSortSettings::SortByRating); }); 0415 0416 connect(sortByDownloadAction, &QAction::triggered, 0417 this, [this]() { d->view->slotSortImagesBy((int)CamItemSortSettings::SortByDownloadState); }); 0418 0419 d->itemSortAction->setCurrentItem(ImportSettings::instance()->getImageSortBy()); 0420 0421 // -- Item Sort Order ------------------------------------------------------------ 0422 0423 d->itemSortOrderAction = new KSelectAction(i18nc("@action", "Item Sorting &Order"), this); 0424 d->itemSortOrderAction->setWhatsThis(i18nc("@info:whatsthis", "Defines whether items are sorted in ascending or descending manner.")); 0425 ac->addAction(QLatin1String("item_sort_order"), d->itemSortOrderAction); 0426 0427 QAction* const sortAscendingAction = d->itemSortOrderAction->addAction(QIcon::fromTheme(QLatin1String("view-sort-ascending")), 0428 i18nc("@item:inmenu Sorting Order", "Ascending")); 0429 QAction* const sortDescendingAction = d->itemSortOrderAction->addAction(QIcon::fromTheme(QLatin1String("view-sort-descending")), 0430 i18nc("@item:inmenu Sorting Order", "Descending")); 0431 0432 connect(sortAscendingAction, &QAction::triggered, 0433 this, [this]() { d->view->slotSortImagesOrder((int)CamItemSortSettings::AscendingOrder); }); 0434 0435 connect(sortDescendingAction, &QAction::triggered, 0436 this, [this]() { d->view->slotSortImagesOrder((int)CamItemSortSettings::DescendingOrder); }); 0437 0438 d->itemSortOrderAction->setCurrentItem(ImportSettings::instance()->getImageSortOrder()); 0439 0440 // -- Item Grouping ------------------------------------------------------------ 0441 0442 d->itemsGroupAction = new KSelectAction(i18nc("@title:menu", "&Group Items"), this); 0443 d->itemsGroupAction->setWhatsThis(i18nc("@info:whatsthis", "The categories in which the items in the thumbnail view are displayed")); 0444 ac->addAction(QLatin1String("item_group"), d->itemsGroupAction); 0445 0446 // map to CamItemSortSettings enum 0447 QAction* const noCategoriesAction = d->itemsGroupAction->addAction(i18nc("@item:inmenu Group Items", "Flat List")); 0448 QAction* const groupByFolderAction = d->itemsGroupAction->addAction(i18nc("@item:inmenu Group Items", "By Folder")); 0449 QAction* const groupByFormatAction = d->itemsGroupAction->addAction(i18nc("@item:inmenu Group Items", "By Format")); 0450 QAction* const groupByDateAction = d->itemsGroupAction->addAction(i18nc("@item:inmenu Group Items", "By Date")); 0451 0452 connect(noCategoriesAction, &QAction::triggered, 0453 this, [this]() { d->view->slotSeparateImages((int)CamItemSortSettings::NoCategories); }); 0454 0455 connect(groupByFolderAction, &QAction::triggered, 0456 this, [this]() { d->view->slotSeparateImages((int)CamItemSortSettings::CategoryByFolder); }); 0457 0458 connect(groupByFormatAction, &QAction::triggered, 0459 this, [this]() { d->view->slotSeparateImages((int)CamItemSortSettings::CategoryByFormat); }); 0460 0461 connect(groupByDateAction, &QAction::triggered, 0462 this, [this]() { d->view->slotSeparateImages((int)CamItemSortSettings::CategoryByDate); }); 0463 0464 d->itemsGroupAction->setCurrentItem(ImportSettings::instance()->getImageSeparationMode()); 0465 0466 // -- Standard 'View' menu actions --------------------------------------------- 0467 0468 d->increaseThumbsAction = buildStdAction(StdZoomInAction, d->view, SLOT(slotZoomIn()), this); 0469 d->increaseThumbsAction->setEnabled(false); 0470 ac->addAction(QLatin1String("importui_zoomplus"), d->increaseThumbsAction); 0471 0472 d->decreaseThumbsAction = buildStdAction(StdZoomOutAction, d->view, SLOT(slotZoomOut()), this); 0473 d->decreaseThumbsAction->setEnabled(false); 0474 ac->addAction(QLatin1String("importui_zoomminus"), d->decreaseThumbsAction); 0475 0476 d->zoomFitToWindowAction = new QAction(QIcon::fromTheme(QLatin1String("zoom-fit-best")), i18nc("@action:inmenu", "Fit to &Window"), this); 0477 connect(d->zoomFitToWindowAction, SIGNAL(triggered()), d->view, SLOT(slotFitToWindow())); 0478 ac->addAction(QLatin1String("import_zoomfit2window"), d->zoomFitToWindowAction); 0479 ac->setDefaultShortcut(d->zoomFitToWindowAction, Qt::CTRL | Qt::ALT | Qt::Key_E); 0480 0481 d->zoomTo100percents = new QAction(QIcon::fromTheme(QLatin1String("zoom-original")), i18nc("@action:inmenu", "Zoom to 100%"), this); 0482 connect(d->zoomTo100percents, SIGNAL(triggered()), d->view, SLOT(slotZoomTo100Percents())); 0483 ac->addAction(QLatin1String("import_zoomto100percents"), d->zoomTo100percents); 0484 ac->setDefaultShortcut(d->zoomTo100percents, Qt::CTRL | Qt::Key_Period); 0485 0486 // ------------------------------------------------------------------------------------------------ 0487 0488 d->viewCMViewAction = new QAction(QIcon::fromTheme(QLatin1String("video-display")), i18nc("@action", "Color-Managed View"), this); 0489 d->viewCMViewAction->setCheckable(true); 0490 connect(d->viewCMViewAction, SIGNAL(triggered()), this, SLOT(slotToggleColorManagedView())); 0491 ac->addAction(QLatin1String("color_managed_view"), d->viewCMViewAction); 0492 ac->setDefaultShortcut(d->viewCMViewAction, Qt::Key_F12); 0493 0494 // ------------------------------------------------------------------------------------------------ 0495 0496 createFullScreenAction(QLatin1String("importui_fullscreen")); 0497 createSidebarActions(); 0498 0499 d->showLogAction = new QAction(QIcon::fromTheme(QLatin1String("edit-find")), i18nc("@option:check", "Show History"), this); 0500 d->showLogAction->setCheckable(true); 0501 connect(d->showLogAction, SIGNAL(triggered()), this, SLOT(slotShowLog())); 0502 ac->addAction(QLatin1String("importui_showlog"), d->showLogAction); 0503 ac->setDefaultShortcut(d->showLogAction, Qt::CTRL | Qt::Key_H); 0504 0505 d->showBarAction = new QAction(QIcon::fromTheme(QLatin1String("view-choose")), i18nc("@option:check", "Show Thumbbar"), this); 0506 d->showBarAction->setCheckable(true); 0507 connect(d->showBarAction, SIGNAL(triggered()), this, SLOT(slotToggleShowBar())); 0508 ac->addAction(QLatin1String("showthumbs"), d->showBarAction); 0509 ac->setDefaultShortcut(d->showBarAction, Qt::CTRL | Qt::Key_T); 0510 d->showBarAction->setEnabled(false); 0511 0512 // --------------------------------------------------------------------------------- 0513 0514 ThemeManager::instance()->registerThemeActions(this); 0515 0516 // Standard 'Help' menu actions 0517 createHelpActions(QLatin1String("camera_import")); 0518 0519 // Provides a menu entry that allows showing/hiding the toolbar(s) 0520 setStandardToolBarMenuEnabled(true); 0521 0522 // Provides a menu entry that allows showing/hiding the statusbar 0523 createStandardStatusBarAction(); 0524 0525 // Standard 'Configure' menu actions 0526 createSettingsActions(); 0527 0528 // -- Keyboard-only actions added to <MainWindow> ---------------------------------- 0529 0530 QAction* const altBackwardAction = new QAction(i18nc("@action", "Previous Image"), this); 0531 ac->addAction(QLatin1String("importui_backward_shift_space"), altBackwardAction); 0532 ac->setDefaultShortcut(altBackwardAction, Qt::SHIFT | Qt::Key_Space); 0533 connect(altBackwardAction, SIGNAL(triggered()), d->view, SLOT(slotPrevItem())); 0534 0535 // --------------------------------------------------------------------------------- 0536 0537 d->connectAction = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")), i18nc("@action Connection failed, try again?", "Retry"), this); 0538 connect(d->connectAction, SIGNAL(triggered()), d->controller, SLOT(slotConnect())); 0539 0540 createGUI(xmlFile()); 0541 cleanupActions(); 0542 0543 showMenuBarAction()->setChecked(!menuBar()->isHidden()); // NOTE: workaround for bug #171080 0544 } 0545 0546 void ImportUI::updateActions() 0547 { 0548 const CamItemInfoList& list = d->view->selectedCamItemInfos(); 0549 bool hasSelection = !list.isEmpty(); 0550 0551 d->downloadDelSelectedAction->setEnabled(hasSelection && d->controller->cameraDeleteSupport()); 0552 d->deleteSelectedAction->setEnabled(hasSelection && d->controller->cameraDeleteSupport()); 0553 d->camItemPreviewAction->setEnabled(hasSelection && cameraUseUMSDriver()); 0554 d->downloadSelectedAction->setEnabled(hasSelection); 0555 d->lockAction->setEnabled(hasSelection); 0556 0557 if (hasSelection) 0558 { 0559 // only enable "Mark as downloaded" if at least one 0560 // selected image has not been downloaded 0561 bool haveNotDownloadedItem = false; 0562 0563 Q_FOREACH (const CamItemInfo& info, list) 0564 { 0565 haveNotDownloadedItem = !(info.downloaded == CamItemInfo::DownloadedYes); 0566 0567 if (haveNotDownloadedItem) 0568 { 0569 break; 0570 } 0571 } 0572 0573 d->markAsDownloadedAction->setEnabled(haveNotDownloadedItem); 0574 } 0575 else 0576 { 0577 d->markAsDownloadedAction->setEnabled(false); 0578 } 0579 } 0580 0581 void ImportUI::setupConnections() 0582 { 0583 //TODO: Needs testing. 0584 connect(d->advancedSettings, SIGNAL(signalDownloadNameChanged()), 0585 this, SLOT(slotUpdateRenamePreview())); 0586 0587 connect(d->dngConvertSettings, SIGNAL(signalDownloadNameChanged()), 0588 this, SLOT(slotUpdateRenamePreview())); 0589 0590 connect(d->historyView, SIGNAL(signalEntryClicked(QVariant)), 0591 this, SLOT(slotHistoryEntryClicked(QVariant))); 0592 0593 connect(IccSettings::instance(), SIGNAL(signalSettingsChanged()), 0594 this, SLOT(slotColorManagementOptionsChanged())); 0595 0596 // ------------------------------------------------------------------------- 0597 0598 connect(d->view, SIGNAL(signalImageSelected(CamItemInfoList,CamItemInfoList)), 0599 this, SLOT(slotImageSelected(CamItemInfoList,CamItemInfoList))); 0600 0601 connect(d->view, SIGNAL(signalSwitchedToPreview()), 0602 this, SLOT(slotSwitchedToPreview())); 0603 0604 connect(d->view, SIGNAL(signalSwitchedToIconView()), 0605 this, SLOT(slotSwitchedToIconView())); 0606 0607 connect(d->view, SIGNAL(signalSwitchedToMapView()), 0608 this, SLOT(slotSwitchedToMapView())); 0609 0610 connect(d->view, SIGNAL(signalNewSelection(bool)), 0611 this, SLOT(slotNewSelection(bool))); 0612 0613 // ------------------------------------------------------------------------- 0614 0615 connect(d->view, SIGNAL(signalThumbSizeChanged(int)), 0616 this, SLOT(slotThumbSizeChanged(int))); 0617 0618 connect(d->view, SIGNAL(signalZoomChanged(double)), 0619 this, SLOT(slotZoomChanged(double))); 0620 0621 connect(d->zoomBar, SIGNAL(signalZoomSliderChanged(int)), 0622 this, SLOT(slotZoomSliderChanged(int))); 0623 0624 connect(d->zoomBar, SIGNAL(signalZoomValueEdited(double)), 0625 d->view, SLOT(setZoomFactor(double))); 0626 0627 connect(this, SIGNAL(signalWindowHasMoved()), 0628 d->zoomBar, SLOT(slotUpdateTrackerPos())); 0629 0630 // ------------------------------------------------------------------------- 0631 0632 connect(CollectionManager::instance(), SIGNAL(locationStatusChanged(CollectionLocation,int)), 0633 this, SLOT(slotCollectionLocationStatusChanged(CollectionLocation,int))); 0634 0635 connect(ApplicationSettings::instance(), SIGNAL(setupChanged()), 0636 this, SLOT(slotSetupChanged())); 0637 0638 connect(d->renameCustomizer, SIGNAL(signalChanged()), 0639 this, SLOT(slotUpdateRenamePreview())); 0640 } 0641 0642 void ImportUI::setupStatusBar() 0643 { 0644 d->statusProgressBar = new StatusProgressBar(statusBar()); 0645 d->statusProgressBar->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0646 d->statusProgressBar->setNotificationTitle(d->cameraTitle, QIcon::fromTheme(QLatin1String("camera-photo"))); 0647 statusBar()->addWidget(d->statusProgressBar, 100); 0648 0649 //------------------------------------------------------------------------------ 0650 0651 d->cameraFreeSpace = new FreeSpaceWidget(statusBar(), 100); 0652 0653 if (cameraUseGPhotoDriver()) 0654 { 0655 d->cameraFreeSpace->setMode(FreeSpaceWidget::GPhotoCamera); 0656 connect(d->controller, SIGNAL(signalFreeSpace(qint64,qint64)), 0657 this, SLOT(slotCameraFreeSpaceInfo(qint64,qint64))); 0658 } 0659 else 0660 { 0661 d->cameraFreeSpace->setMode(FreeSpaceWidget::UMSCamera); 0662 d->cameraFreeSpace->setPath(d->controller->cameraPath()); 0663 } 0664 0665 statusBar()->addWidget(d->cameraFreeSpace, 1); 0666 0667 //------------------------------------------------------------------------------ 0668 0669 d->albumLibraryFreeSpace = new FreeSpaceWidget(statusBar(), 100); 0670 d->albumLibraryFreeSpace->setMode(FreeSpaceWidget::AlbumLibrary); 0671 statusBar()->addWidget(d->albumLibraryFreeSpace, 1); 0672 refreshCollectionFreeSpace(); 0673 0674 //------------------------------------------------------------------------------ 0675 0676 // TODO: Replace it with FilterStatusBar after advanced filtering is implemented. 0677 0678 d->filterComboBox = new ImportFilterComboBox(statusBar()); 0679 setFilter(d->filterComboBox->currentFilter()); 0680 statusBar()->addWidget(d->filterComboBox, 1); 0681 0682 connect(d->filterComboBox, SIGNAL(signalFilterChanged(Filter*)), 0683 this, SLOT(setFilter(Filter*))); 0684 0685 //------------------------------------------------------------------------------ 0686 0687 d->zoomBar = new DZoomBar(statusBar()); 0688 d->zoomBar->setZoomToFitAction(d->zoomFitToWindowAction); 0689 d->zoomBar->setZoomTo100Action(d->zoomTo100percents); 0690 d->zoomBar->setZoomPlusAction(d->increaseThumbsAction); 0691 d->zoomBar->setZoomMinusAction(d->decreaseThumbsAction); 0692 d->zoomBar->setBarMode(DZoomBar::ThumbsSizeCtrl); 0693 statusBar()->addPermanentWidget(d->zoomBar, 1); 0694 } 0695 0696 void ImportUI::setupCameraController(const QString& model, const QString& port, const QString& path) 0697 { 0698 d->controller = new CameraController(this, d->cameraTitle, model, port, path); 0699 0700 connect(d->controller, SIGNAL(signalConnected(bool)), 0701 this, SLOT(slotConnected(bool)), 0702 Qt::QueuedConnection); 0703 0704 connect(d->controller, SIGNAL(signalLogMsg(QString,DHistoryView::EntryType,QString,QString)), 0705 this, SLOT(slotLogMsg(QString,DHistoryView::EntryType,QString,QString)), 0706 Qt::QueuedConnection); 0707 0708 connect(d->controller, SIGNAL(signalCameraInformation(QString,QString,QString)), 0709 this, SLOT(slotCameraInformation(QString,QString,QString)), 0710 Qt::QueuedConnection); 0711 0712 connect(d->controller, SIGNAL(signalBusy(bool)), 0713 this, SLOT(slotBusy(bool)), 0714 Qt::QueuedConnection); 0715 0716 connect(d->controller, SIGNAL(signalFolderList(QStringList)), 0717 this, SLOT(slotFolderList(QStringList)), 0718 Qt::QueuedConnection); 0719 0720 connect(d->controller, SIGNAL(signalDownloaded(QString,QString,QString,int)), 0721 this, SLOT(slotDownloaded(QString,QString,QString,int)), 0722 Qt::BlockingQueuedConnection); 0723 0724 connect(d->controller, SIGNAL(signalDeleted(QString,QString,bool)), 0725 this, SLOT(slotDeleted(QString,QString,bool)), 0726 Qt::QueuedConnection); 0727 0728 connect(d->controller, SIGNAL(signalLocked(QString,QString,bool)), 0729 this, SLOT(slotLocked(QString,QString,bool)), 0730 Qt::QueuedConnection); 0731 0732 connect(d->controller, SIGNAL(signalMetadata(QString,QString,MetaEngineData)), 0733 this, SLOT(slotMetadata(QString,QString,MetaEngineData)), 0734 Qt::QueuedConnection); 0735 0736 connect(d->controller, SIGNAL(signalUploaded(CamItemInfo)), 0737 this, SLOT(slotUploaded(CamItemInfo)), 0738 Qt::QueuedConnection); 0739 0740 d->controller->start(); 0741 0742 // Setup Thumbnails controller ------------------------------------------------------- 0743 0744 d->camThumbsCtrl = new CameraThumbsCtrl(d->controller, this); 0745 } 0746 0747 CameraThumbsCtrl* ImportUI::getCameraThumbsCtrl() const 0748 { 0749 return d->camThumbsCtrl; 0750 } 0751 0752 void ImportUI::setupAccelerators() 0753 { 0754 KActionCollection* const ac = actionCollection(); 0755 0756 QAction* const escapeAction = new QAction(i18nc("@action", "Exit Preview Mode"), this); 0757 ac->addAction(QLatin1String("exit_preview_mode"), escapeAction); 0758 ac->setDefaultShortcut(escapeAction, Qt::Key_Escape); 0759 connect(escapeAction, SIGNAL(triggered()), this, SIGNAL(signalEscapePressed())); 0760 0761 QAction* const nextImageAction = new QAction(i18nc("@action","Next Image"), this); 0762 nextImageAction->setIcon(QIcon::fromTheme(QLatin1String("go-next"))); 0763 ac->addAction(QLatin1String("next_image"), nextImageAction); 0764 ac->setDefaultShortcut(nextImageAction, Qt::Key_Space); 0765 connect(nextImageAction, SIGNAL(triggered()), d->view, SLOT(slotNextItem())); 0766 0767 QAction* const previousImageAction = new QAction(i18nc("@action", "Previous Image"), this); 0768 previousImageAction->setIcon(QIcon::fromTheme(QLatin1String("go-previous"))); 0769 ac->addAction(QLatin1String("previous_image"), previousImageAction); 0770 ac->setDefaultShortcuts(previousImageAction, QList<QKeySequence>() << Qt::Key_Backspace << (Qt::SHIFT | Qt::Key_Space)); 0771 connect(previousImageAction, SIGNAL(triggered()), d->view, SLOT(slotPrevItem())); 0772 0773 QAction* const firstImageAction = new QAction(i18nc("@action Go to first image", "First Image"), this); 0774 ac->addAction(QLatin1String("first_image"), firstImageAction); 0775 ac->setDefaultShortcut(firstImageAction, Qt::Key_Home); 0776 connect(firstImageAction, SIGNAL(triggered()), d->view, SLOT(slotFirstItem())); 0777 0778 QAction* const lastImageAction = new QAction(i18nc("@action Go to last image", "Last Image"), this); 0779 ac->addAction(QLatin1String("last_image"), lastImageAction); 0780 ac->setDefaultShortcut(lastImageAction, Qt::Key_End); 0781 connect(lastImageAction, SIGNAL(triggered()), d->view, SLOT(slotLastItem())); 0782 } 0783 0784 void ImportUI::readSettings() 0785 { 0786 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0787 KConfigGroup group = config->group(d->configGroupName); 0788 0789 readFullScreenSettings(group); 0790 0791 d->showBarAction->setChecked(ImportSettings::instance()->getShowThumbbar()); 0792 d->showLogAction->setChecked(group.readEntry(QLatin1String("ShowLog"), false)); 0793 d->albumCustomizer->readSettings(group); 0794 d->advancedSettings->readSettings(group); 0795 d->dngConvertSettings->readSettings(group); 0796 d->scriptingSettings->readSettings(group); 0797 0798 d->advBox->readSettings(group); 0799 0800 d->splitter->restoreState(group); 0801 0802 slotShowLog(); 0803 } 0804 0805 void ImportUI::saveSettings() 0806 { 0807 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0808 KConfigGroup group = config->group(d->configGroupName); 0809 0810 ImportSettings::instance()->setShowThumbbar(d->showBarAction->isChecked()); 0811 ImportSettings::instance()->saveSettings(); 0812 group.writeEntry(QLatin1String("ShowLog"), d->showLogAction->isChecked()); 0813 d->albumCustomizer->saveSettings(group); 0814 d->advancedSettings->saveSettings(group); 0815 d->dngConvertSettings->saveSettings(group); 0816 d->scriptingSettings->saveSettings(group); 0817 0818 d->advBox->writeSettings(group); 0819 0820 d->rightSideBar->saveState(); 0821 d->splitter->saveState(group); 0822 d->filterComboBox->saveSettings(); 0823 0824 config->sync(); 0825 } 0826 0827 bool ImportUI::isBusy() const 0828 { 0829 return d->busy; 0830 } 0831 0832 bool ImportUI::isClosed() const 0833 { 0834 return d->closed; 0835 } 0836 0837 QString ImportUI::cameraTitle() const 0838 { 0839 return d->cameraTitle; 0840 } 0841 0842 DownloadSettings ImportUI::downloadSettings() const 0843 { 0844 DownloadSettings settings = d->advancedSettings->settings(); 0845 d->dngConvertSettings->settings(&settings); 0846 d->scriptingSettings->settings(&settings); 0847 return settings; 0848 } 0849 0850 void ImportUI::setInitialSorting() 0851 { 0852 d->view->slotSeparateImages(ImportSettings::instance()->getImageSeparationMode()); 0853 d->view->slotSortImagesBy(ImportSettings::instance()->getImageSortBy()); 0854 d->view->slotSortImagesOrder(ImportSettings::instance()->getImageSortOrder()); 0855 } 0856 0857 void ImportUI::slotCancelButton() 0858 { 0859 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, 0860 i18nc("@info:status", "Canceling current operation, please wait...")); 0861 d->controller->slotCancel(); 0862 0863 d->currentlyDeleting.clear(); 0864 0865 postProcessAfterDownload(); 0866 0867 refreshFreeSpace(); 0868 } 0869 0870 void ImportUI::refreshFreeSpace() 0871 { 0872 if (cameraUseGPhotoDriver()) 0873 { 0874 d->controller->getFreeSpace(); 0875 } 0876 else 0877 { 0878 d->cameraFreeSpace->refresh(); 0879 } 0880 } 0881 0882 void ImportUI::closeEvent(QCloseEvent* e) 0883 { 0884 if (dialogClosed()) 0885 { 0886 DXmlGuiWindow::closeEvent(e); 0887 } 0888 else 0889 { 0890 e->ignore(); 0891 } 0892 } 0893 0894 void ImportUI::moveEvent(QMoveEvent* e) 0895 { 0896 Q_UNUSED(e) 0897 Q_EMIT signalWindowHasMoved(); 0898 } 0899 0900 void ImportUI::slotClose() 0901 { 0902 close(); 0903 } 0904 0905 bool ImportUI::dialogClosed() 0906 { 0907 if (d->closed) 0908 { 0909 return true; 0910 } 0911 0912 if (isBusy()) 0913 { 0914 if (QMessageBox::question(this, qApp->applicationName(), 0915 i18nc("@info", "Do you want to close the dialog " 0916 "and cancel the current operation?"), 0917 QMessageBox::Yes | QMessageBox::No 0918 ) == QMessageBox::No) 0919 { 0920 return false; 0921 } 0922 } 0923 0924 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, 0925 i18nc("@info:status", "Disconnecting from camera, please wait...")); 0926 0927 if (d->waitAutoRotate) 0928 { 0929 hide(); 0930 d->waitAutoRotate = false; 0931 0932 return false; 0933 } 0934 0935 if (isBusy()) 0936 { 0937 d->controller->slotCancel(); 0938 0939 // will be read in slotBusy later and finishDialog 0940 // will be called only when everything is finished 0941 0942 d->closed = true; 0943 } 0944 else 0945 { 0946 d->closed = true; 0947 finishDialog(); 0948 } 0949 0950 return true; 0951 } 0952 0953 void ImportUI::finishDialog() 0954 { 0955 // Look if an item have been downloaded to computer during camera GUI session. 0956 // If yes, update the starting number value used to rename camera items from camera list. 0957 0958 if (d->view->downloadedCamItemInfos() > 0) 0959 { 0960 CameraList* const clist = CameraList::defaultList(); 0961 0962 if (clist) 0963 { 0964 clist->changeCameraStartIndex(d->cameraTitle, d->renameCustomizer->startIndex()); 0965 } 0966 } 0967 0968 deleteLater(); 0969 0970 if (!d->lastDestURL.isEmpty()) 0971 { 0972 Q_EMIT signalLastDestination(d->lastDestURL); 0973 } 0974 0975 saveSettings(); 0976 } 0977 0978 void ImportUI::slotBusy(bool val) 0979 { 0980 if (!val) // Camera is available for actions. 0981 { 0982 if (!d->busy) 0983 { 0984 return; 0985 } 0986 0987 d->busy = false; 0988 d->view->setEnabled(true); 0989 d->advBox->setEnabled(true); 0990 d->cameraActions->setEnabled(true); 0991 d->cameraCancelAction->setEnabled(false); 0992 0993 // selection-dependent update of lockAction, markAsDownloadedAction, 0994 // downloadSelectedAction, downloadDelSelectedAction, deleteSelectedAction 0995 0996 updateActions(); 0997 0998 m_animLogo->stop(); 0999 d->statusProgressBar->setProgressValue(0); 1000 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, i18nc("@info:status busy state", "Ready")); 1001 1002 // like WDestructiveClose, but after camera controller operation has safely finished 1003 1004 if (d->closed) 1005 { 1006 finishDialog(); 1007 } 1008 } 1009 else // Camera is busy. 1010 { 1011 if (d->busy) 1012 { 1013 return; 1014 } 1015 1016 if (!m_animLogo->running()) 1017 { 1018 m_animLogo->start(); 1019 } 1020 1021 d->busy = true; 1022 d->cameraActions->setEnabled(false); 1023 } 1024 } 1025 1026 void ImportUI::slotZoomSliderChanged(int size) 1027 { 1028 d->view->setThumbSize(size); 1029 } 1030 1031 void ImportUI::slotZoomChanged(double zoom) 1032 { 1033 double zmin = d->view->zoomMin(); 1034 double zmax = d->view->zoomMax(); 1035 d->zoomBar->setZoom(zoom, zmin, zmax); 1036 1037 if (!fullScreenIsActive()) 1038 { 1039 d->zoomBar->triggerZoomTrackerToolTip(); 1040 } 1041 } 1042 1043 void ImportUI::slotThumbSizeChanged(int size) 1044 { 1045 d->zoomBar->setThumbsSize(size); 1046 1047 if (!fullScreenIsActive()) 1048 { 1049 d->zoomBar->triggerZoomTrackerToolTip(); 1050 } 1051 } 1052 1053 void ImportUI::slotConnected(bool val) 1054 { 1055 if (!val) 1056 { 1057 d->errorWidget->setText(i18nc("@info", "Failed to connect to the camera. " 1058 "Please make sure it is connected " 1059 "properly and turned on.")); 1060 1061 d->errorWidget->clearAllActions(); 1062 d->errorWidget->addAction(d->connectAction); 1063 d->errorWidget->addAction(d->showPreferencesAction); 1064 d->errorWidget->animatedShow(); 1065 } 1066 else 1067 { 1068 // disable unsupported actions 1069 1070 d->uploadAction->setEnabled(d->controller->cameraUploadSupport()); 1071 1072 d->cameraCaptureAction->setEnabled(d->controller->cameraCaptureImageSupport()); 1073 1074 d->errorWidget->hide(); 1075 refreshFreeSpace(); 1076 1077 // FIXME ugly c&p from slotFolderList 1078 1079 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 1080 KConfigGroup group = config->group(d->configGroupName); 1081 bool useMetadata = group.readEntry(d->configUseFileMetadata, false); 1082 d->controller->listRootFolder(useMetadata); 1083 } 1084 } 1085 1086 void ImportUI::slotFolderList(const QStringList& folderList) 1087 { 1088 if (d->closed) 1089 { 1090 return; 1091 } 1092 1093 d->statusProgressBar->setProgressValue(0); 1094 d->statusProgressBar->setProgressTotalSteps(0); 1095 1096 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 1097 KConfigGroup group = config->group(d->configGroupName); 1098 bool useMetadata = group.readEntry(d->configUseFileMetadata, false); 1099 1100 // when getting a list of subfolders, request their contents and also their subfolders 1101 1102 for (QStringList::const_iterator it = folderList.constBegin() ; 1103 it != folderList.constEnd() ; ++it) 1104 { 1105 d->controller->listFiles(*it, useMetadata); 1106 d->controller->listFolders(*it); 1107 } 1108 } 1109 1110 void ImportUI::setFilter(Filter* filter) 1111 { 1112 d->view->importFilterModel()->setFilter(filter); 1113 } 1114 1115 void ImportUI::slotCapture() 1116 { 1117 if (d->busy) 1118 { 1119 return; 1120 } 1121 1122 CaptureDlg* const captureDlg = new CaptureDlg(this, d->controller, d->cameraTitle); 1123 captureDlg->show(); 1124 } 1125 1126 void ImportUI::slotInformation() 1127 { 1128 if (d->busy) 1129 { 1130 return; 1131 } 1132 1133 d->controller->getCameraInformation(); 1134 } 1135 1136 void ImportUI::slotCameraInformation(const QString& summary, const QString& manual, const QString& about) 1137 { 1138 CameraInfoDialog* const infoDlg = new CameraInfoDialog(this, summary, manual, about); 1139 infoDlg->show(); 1140 } 1141 1142 void ImportUI::slotUpload() 1143 { 1144 if (d->busy) 1145 { 1146 return; 1147 } 1148 1149 QList<QUrl> urls = ImageDialog::getImageURLs(this, 1150 QUrl::fromLocalFile(CollectionManager::instance()->oneAlbumRootPath()), 1151 i18nc("@title:window", "Select Image to Upload")); 1152 1153 if (!urls.isEmpty()) 1154 { 1155 slotUploadItems(urls); 1156 } 1157 } 1158 1159 void ImportUI::slotUploadItems(const QList<QUrl>& urls) 1160 { 1161 if (d->busy) 1162 { 1163 return; 1164 } 1165 1166 if (urls.isEmpty()) 1167 { 1168 return; 1169 } 1170 1171 if (d->cameraFreeSpace->isValid()) 1172 { 1173 // Check if space require to upload new items in camera is enough. 1174 1175 qint64 totalBytesSize = 0; 1176 1177 for (QList<QUrl>::const_iterator it = urls.constBegin() ; it != urls.constEnd() ; ++it) 1178 { 1179 QFileInfo fi((*it).toLocalFile()); 1180 totalBytesSize += fi.size(); 1181 } 1182 1183 if (totalBytesSize >= d->cameraFreeSpace->bytesAvail()) 1184 { 1185 QMessageBox::critical(this, qApp->applicationName(), 1186 i18nc("@info", "There is not enough free space on the Camera Medium " 1187 "to upload pictures.\n\n" 1188 "Space require: %1\n" 1189 "Available free space: %2", 1190 ItemPropertiesTab::humanReadableBytesCount(totalBytesSize), 1191 ItemPropertiesTab::humanReadableBytesCount(d->cameraFreeSpace->bytesAvail()))); 1192 return; 1193 } 1194 } 1195 1196 QMap<QString, int> map = countItemsByFolders(); 1197 QPointer<CameraFolderDialog> dlg = new CameraFolderDialog(this, map, d->controller->cameraTitle(), 1198 d->controller->cameraPath()); 1199 1200 if (dlg->exec() != QDialog::Accepted) 1201 { 1202 delete dlg; 1203 return; 1204 } 1205 1206 // since we access members here, check if the pointer is still valid 1207 1208 if (!dlg) 1209 { 1210 return; 1211 } 1212 1213 QString cameraFolder = dlg->selectedFolderPath(); 1214 1215 for (QList<QUrl>::const_iterator it = urls.constBegin(); it != urls.constEnd(); ++it) 1216 { 1217 QFileInfo fi((*it).toLocalFile()); 1218 1219 if (!fi.exists()) 1220 { 1221 continue; 1222 } 1223 1224 if (fi.isDir()) 1225 { 1226 continue; 1227 } 1228 1229 QString ext = QLatin1Char('.') + fi.completeSuffix(); 1230 QString name = fi.fileName(); 1231 name.truncate(fi.fileName().length() - ext.length()); 1232 1233 bool ok; 1234 1235 CamItemInfo uploadInfo; 1236 uploadInfo.folder = cameraFolder; 1237 uploadInfo.name = name + ext; 1238 1239 while (d->view->hasImage(uploadInfo)) 1240 { 1241 QString msg(i18nc("@info", "Camera Folder \"%1\" already contains the item \"%2\".\n" 1242 "Please enter a new filename (without extension):", 1243 QDir::toNativeSeparators(cameraFolder), fi.fileName())); 1244 uploadInfo.name = QInputDialog::getText(this, 1245 i18nc("@title:window", "File Already Exists"), 1246 msg, 1247 QLineEdit::Normal, 1248 name, 1249 &ok) + ext; 1250 1251 if (!ok) 1252 { 1253 return; 1254 } 1255 } 1256 1257 d->controller->upload(fi, uploadInfo.name, cameraFolder); 1258 } 1259 1260 delete dlg; 1261 } 1262 1263 void ImportUI::slotUploaded(const CamItemInfo& /*itemInfo*/) 1264 { 1265 if (d->closed) 1266 { 1267 return; 1268 } 1269 1270 refreshFreeSpace(); 1271 } 1272 1273 void ImportUI::slotDownloadNew() 1274 { 1275 slotSelectNew(); 1276 QTimer::singleShot(0, this, SLOT(slotDownloadSelected())); 1277 } 1278 1279 void ImportUI::slotDownloadAndDeleteNew() 1280 { 1281 slotSelectNew(); 1282 QTimer::singleShot(0, this, SLOT(slotDownloadAndDeleteSelected())); 1283 } 1284 1285 void ImportUI::slotDownloadSelected() 1286 { 1287 slotDownload(true, false); 1288 } 1289 1290 void ImportUI::slotDownloadAndDeleteSelected() 1291 { 1292 slotDownload(true, true); 1293 } 1294 1295 void ImportUI::slotDownloadAll() 1296 { 1297 slotDownload(false, false); 1298 } 1299 1300 void ImportUI::slotDownloadAndDeleteAll() 1301 { 1302 slotDownload(false, true); 1303 } 1304 1305 void ImportUI::slotDownload(bool onlySelected, bool deleteAfter, Album* album) 1306 { 1307 if (d->albumCustomizer->autoAlbumDateEnabled() && 1308 (d->albumCustomizer->folderDateFormat() == AlbumCustomizer::CustomDateFormat) && 1309 !d->albumCustomizer->customDateFormatIsValid()) 1310 { 1311 QMessageBox::information(this, qApp->applicationName(), 1312 i18nc("@info", "Your custom target album date format is not valid. Please check your settings...")); 1313 return; 1314 } 1315 1316 // See bug #143934: force to select all items to prevent problem. 1317 1318 if (!onlySelected) 1319 { 1320 d->view->slotSelectAll(); 1321 } 1322 1323 // Update the download names. 1324 slotNewSelection(d->view->selectedUrls().count() > 0); 1325 1326 // -- Get the destination album from digiKam library --------------- 1327 1328 PAlbum* pAlbum = nullptr; 1329 1330 if (!album) 1331 { 1332 AlbumManager* const man = AlbumManager::instance(); 1333 1334 // Check if default target album option is enabled. 1335 1336 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 1337 KConfigGroup group = config->group(d->configGroupName); 1338 bool useDefaultTarget = group.readEntry(d->configUseDefaultTargetAlbum, false); 1339 1340 if (useDefaultTarget) 1341 { 1342 PAlbum* const pa = man->findPAlbum(group.readEntry(d->configDefaultTargetAlbumId, 0)); 1343 1344 if (pa) 1345 { 1346 CollectionLocation cl = CollectionManager::instance()->locationForAlbumRootId(pa->albumRootId()); 1347 1348 if (!cl.isAvailable() || cl.isNull()) 1349 { 1350 QMessageBox::information(this, qApp->applicationName(), 1351 i18nc("@info", "Collection which host your default target album set to process " 1352 "download from camera device is not available. Please select another one from " 1353 "camera configuration dialog.")); 1354 return; 1355 } 1356 } 1357 else 1358 { 1359 QMessageBox::information(this, qApp->applicationName(), 1360 i18nc("@info", "Your default target album set to process download " 1361 "from camera device is not available. Please select another one from " 1362 "camera configuration dialog.")); 1363 return; 1364 } 1365 1366 pAlbum = pa; 1367 } 1368 else 1369 { 1370 AlbumList list = man->currentAlbums(); 1371 int albumId = 0; 1372 1373 if (!list.isEmpty()) 1374 { 1375 albumId = group.readEntry(d->configLastTargetAlbum, list.first()->globalID()); 1376 } 1377 1378 album = man->findAlbum(albumId); 1379 1380 if (album && album->type() != Album::PHYSICAL) 1381 { 1382 album = nullptr; 1383 } 1384 1385 QString header(i18nc("@info", "Please select the destination album from the digiKam library to " 1386 "import the camera pictures into.")); 1387 1388 album = AlbumSelectDialog::selectAlbum(this, dynamic_cast<PAlbum*>(album), header); 1389 pAlbum = dynamic_cast<PAlbum*>(album); 1390 1391 if (!pAlbum) 1392 { 1393 qCDebug(DIGIKAM_IMPORTUI_LOG) << "Destination Album is null"; 1394 return; 1395 } 1396 1397 group.writeEntry(d->configLastTargetAlbum, album->globalID()); 1398 } 1399 } 1400 else 1401 { 1402 pAlbum = dynamic_cast<PAlbum*>(album); 1403 } 1404 1405 if (!pAlbum) 1406 { 1407 qCDebug(DIGIKAM_IMPORTUI_LOG) << "Destination Album is null"; 1408 return; 1409 } 1410 1411 CollectionLocation cl = CollectionManager::instance()->locationForAlbumRootId(pAlbum->albumRootId()); 1412 1413 if (!cl.isAvailable() || cl.isNull()) 1414 { 1415 QMessageBox::information(this, qApp->applicationName(), 1416 i18nc("@info", "Collection selected as the destination album to download " 1417 "from the camera device is not available. Please select another " 1418 "destination album.")); 1419 return; 1420 } 1421 1422 // -- Check disk space ------------------------ 1423 // See bug #139519: Always check free space available before to 1424 // download items selection from camera. 1425 1426 if (!checkDiskSpace(pAlbum)) 1427 { 1428 return; 1429 } 1430 1431 // -- Prepare and download camera items ------------------------ 1432 // Since we show camera items in reverse order, downloading need to be done also in reverse order. 1433 1434 downloadCameraItems(pAlbum, onlySelected, deleteAfter); 1435 } 1436 1437 void ImportUI::slotDownloaded(const QString& folder, const QString& file, const QString& temp, int status) 1438 { 1439 if (status == CamItemInfo::DownloadedYes) 1440 { 1441 QFileInfo tempInfo(temp); 1442 QUrl downloadUrl = QUrl::fromLocalFile(tempInfo.path()); 1443 QScopedPointer<DMetadata> metadata(new DMetadata(temp)); 1444 QDateTime creationDate = metadata->getItemDateTime(); 1445 1446 if (!creationDate.isValid()) 1447 { 1448 creationDate = tempInfo.birthTime(); 1449 1450 if (!creationDate.isValid()) 1451 { 1452 creationDate = tempInfo.lastModified(); 1453 } 1454 } 1455 1456 if (!createSubAlbums(downloadUrl, tempInfo.suffix(), creationDate)) 1457 { 1458 downloadUrl = QUrl::fromLocalFile(tempInfo.path()); 1459 } 1460 1461 QString dest = downloadUrl.toLocalFile() + QLatin1Char('/') + tempInfo.fileName(); 1462 1463 if (DMetadata::hasSidecar(temp)) 1464 { 1465 QString sctemp = DMetadata::sidecarPath(temp); 1466 QString scdest = DMetadata::sidecarPath(dest); 1467 1468 if (!DFileOperations::renameFile(sctemp, scdest)) 1469 { 1470 slotLogMsg(xi18n("Failed to move sidecar file for <filename>%1</filename>", tempInfo.fileName()), 1471 DHistoryView::ErrorEntry); 1472 } 1473 } 1474 1475 if (!DFileOperations::renameFile(temp, dest)) 1476 { 1477 slotLogMsg(xi18n("Failed to move file for <filename>%1</filename>", tempInfo.fileName()), 1478 DHistoryView::ErrorEntry); 1479 } 1480 1481 d->downloadedItemList << dest; 1482 d->downloadedDateHash.insert(dest, creationDate); 1483 d->downloadedInfoHash.insert(dest, qMakePair(folder, file)); 1484 1485 if (!d->foldersToScan.contains(downloadUrl.toLocalFile())) 1486 { 1487 d->foldersToScan << downloadUrl.toLocalFile(); 1488 } 1489 } 1490 1491 if ((status == CamItemInfo::DownloadedYes) || 1492 (status == CamItemInfo::DownloadFailed)) 1493 { 1494 int curr = d->statusProgressBar->progressValue(); 1495 d->statusProgressBar->setProgressValue(curr + 1); 1496 } 1497 1498 CamItemInfo& info = d->view->camItemInfoRef(folder, file); 1499 1500 if (!info.isNull()) 1501 { 1502 setDownloaded(info, status); 1503 1504 bool previewItems = ImportSettings::instance()->getPreviewItemsWhileDownload(); 1505 1506 if (status == CamItemInfo::DownloadStarted && previewItems) 1507 { 1508 Q_EMIT signalPreviewRequested(info, true); 1509 } 1510 1511 if (d->rightSideBar->url() == info.url()) 1512 { 1513 updateRightSideBar(info); 1514 } 1515 1516 if (info.downloaded == CamItemInfo::DownloadedYes) 1517 { 1518 CoreDbDownloadHistory::setDownloaded(QString::fromUtf8(d->controller->cameraMD5ID()), 1519 info.name, 1520 info.size, 1521 info.ctime); 1522 } 1523 } 1524 1525 // Download all items is complete ? 1526 1527 if (d->statusProgressBar->progressValue() == d->statusProgressBar->progressTotalSteps()) 1528 { 1529 if (d->deleteAfter) 1530 { 1531 // No need passive pop-up here, because we will ask to confirm items deletion with dialog. 1532 1533 QTimer::singleShot(0, this, SLOT(slotDeleteAfterDownload())); 1534 } 1535 1536 postProcessAfterDownload(); 1537 } 1538 } 1539 1540 void ImportUI::slotMarkAsDownloaded() 1541 { 1542 Q_FOREACH (const CamItemInfo& info, d->view->selectedCamItemInfos()) 1543 { 1544 setDownloaded(d->view->camItemInfoRef(info.folder, info.name), CamItemInfo::DownloadedYes); 1545 1546 CoreDbDownloadHistory::setDownloaded(QString::fromUtf8(d->controller->cameraMD5ID()), 1547 info.name, 1548 info.size, 1549 info.ctime); 1550 } 1551 } 1552 1553 void ImportUI::slotToggleLock() 1554 { 1555 const CamItemInfoList& list = d->view->selectedCamItemInfos(); 1556 int count = list.count(); 1557 1558 if (count > 0) 1559 { 1560 d->statusProgressBar->setProgressValue(0); 1561 d->statusProgressBar->setProgressTotalSteps(count); 1562 d->statusProgressBar->setProgressBarMode(StatusProgressBar::ProgressBarMode); 1563 } 1564 1565 Q_FOREACH (const CamItemInfo& info, list) 1566 { 1567 QString folder = info.folder; 1568 QString file = info.name; 1569 int writePerm = info.writePermissions; 1570 bool lock = true; 1571 1572 // If item is currently locked, unlock it. 1573 1574 if (writePerm == 0) 1575 { 1576 lock = false; 1577 } 1578 1579 d->controller->lockFile(folder, file, lock); 1580 } 1581 } 1582 1583 void ImportUI::slotLocked(const QString& folder, const QString& file, bool status) 1584 { 1585 if (status) 1586 { 1587 CamItemInfo& info = d->view->camItemInfoRef(folder, file); 1588 1589 if (!info.isNull()) 1590 { 1591 toggleLock(info); 1592 1593 if (d->rightSideBar->url() == info.url()) 1594 { 1595 updateRightSideBar(info); 1596 } 1597 } 1598 } 1599 1600 int curr = d->statusProgressBar->progressValue(); 1601 d->statusProgressBar->setProgressValue(curr + 1); 1602 } 1603 1604 void ImportUI::slotUpdateRenamePreview() 1605 { 1606 const CamItemInfoList& list = d->view->selectedCamItemInfos(); 1607 1608 if (list.isEmpty()) 1609 { 1610 d->renameCustomizer->setPreviewText(QString()); 1611 1612 return; 1613 } 1614 1615 const CamItemInfo& info = list.constFirst(); 1616 DownloadSettings settings = downloadSettings(); 1617 1618 if (info.isNull()) 1619 { 1620 d->renameCustomizer->setPreviewText(QString()); 1621 1622 return; 1623 } 1624 1625 QString newName = info.name; 1626 1627 if (d->renameCustomizer->useDefault()) 1628 { 1629 newName = d->renameCustomizer->newName(info.name); 1630 } 1631 else if (d->renameCustomizer->isEnabled()) 1632 { 1633 newName = d->renameCustomizer->newName(info.url().toLocalFile()); 1634 } 1635 1636 if (settings.convertJpeg && info.mime == QLatin1String("image/jpeg")) 1637 { 1638 QFileInfo fi(newName); 1639 QString ext = fi.suffix(); 1640 1641 if (!ext.isEmpty()) 1642 { 1643 if (ext[0].isUpper() && ext[ext.length()-1].isUpper()) 1644 { 1645 ext = settings.losslessFormat.toUpper(); 1646 } 1647 else if (ext[0].isUpper()) 1648 { 1649 ext = settings.losslessFormat.toLower(); 1650 ext[0] = ext[0].toUpper(); 1651 } 1652 else 1653 { 1654 ext = settings.losslessFormat.toLower(); 1655 } 1656 1657 newName = fi.completeBaseName() + QLatin1Char('.') + ext; 1658 } 1659 else 1660 { 1661 newName = newName + QLatin1Char('.') + settings.losslessFormat.toLower(); 1662 } 1663 } 1664 else if (settings.convertDng && info.mime == QLatin1String("image/x-raw")) 1665 { 1666 QFileInfo fi(newName); 1667 QString ext = fi.suffix(); 1668 1669 if (!ext.isEmpty()) 1670 { 1671 if (ext[0].isUpper() && (ext[ext.length()-1].isUpper() || ext[ext.length()-1].isDigit())) 1672 { 1673 ext = QLatin1String("DNG"); 1674 } 1675 else if (ext[0].isUpper()) 1676 { 1677 ext = QLatin1String("Dng"); 1678 } 1679 else 1680 { 1681 ext = QLatin1String("dng"); 1682 } 1683 1684 newName = fi.completeBaseName() + QLatin1Char('.') + ext; 1685 } 1686 else 1687 { 1688 newName = newName + QLatin1Char('.') + QLatin1String("dng"); 1689 } 1690 } 1691 1692 CamItemInfo& refInfo = d->view->camItemInfoRef(info.folder, info.name); 1693 1694 if (!refInfo.isNull()) 1695 { 1696 d->renameCustomizer->setPreviewText(newName); 1697 refInfo.downloadName = newName; 1698 } 1699 } 1700 1701 // FIXME: the new pictures are marked by CameraHistoryUpdater which is not working yet. 1702 1703 void ImportUI::slotSelectNew() 1704 { 1705 CamItemInfoList toBeSelected; 1706 1707 Q_FOREACH (const CamItemInfo& info, d->view->allItems()) 1708 { 1709 if (info.downloaded == CamItemInfo::DownloadedNo) 1710 { 1711 toBeSelected << info; 1712 } 1713 } 1714 1715 d->view->setSelectedCamItemInfos(toBeSelected); 1716 } 1717 1718 void ImportUI::slotSelectLocked() 1719 { 1720 CamItemInfoList toBeSelected; 1721 1722 Q_FOREACH (const CamItemInfo& info, d->view->allItems()) 1723 { 1724 if (info.writePermissions == 0) 1725 { 1726 toBeSelected << info; 1727 } 1728 } 1729 1730 d->view->setSelectedCamItemInfos(toBeSelected); 1731 } 1732 1733 void ImportUI::toggleLock(CamItemInfo& info) 1734 { 1735 if (!info.isNull()) 1736 { 1737 if (info.writePermissions == 0) 1738 { 1739 info.writePermissions = 1; 1740 } 1741 else 1742 { 1743 info.writePermissions = 0; 1744 } 1745 } 1746 } 1747 1748 // TODO is this really necessary? why not just use the folders from listfolders call? 1749 1750 QMap<QString, int> ImportUI::countItemsByFolders() const 1751 { 1752 QString path; 1753 QMap<QString, int> map; 1754 QMap<QString, int>::iterator it; 1755 1756 Q_FOREACH (const CamItemInfo& info, d->view->allItems()) 1757 { 1758 path = info.folder; 1759 1760 if (!path.isEmpty() && path.endsWith(QLatin1Char('/'))) 1761 { 1762 path.truncate(path.length() - 1); 1763 } 1764 1765 it = map.find(path); 1766 1767 if (it == map.end()) 1768 { 1769 map.insert(path, 1); 1770 } 1771 else 1772 { 1773 it.value() ++; 1774 } 1775 } 1776 1777 return map; 1778 } 1779 1780 void ImportUI::setDownloaded(CamItemInfo& itemInfo, int status) 1781 { 1782 itemInfo.downloaded = status; 1783 d->progressValue = 0; 1784 1785 if (itemInfo.downloaded == CamItemInfo::DownloadStarted) 1786 { 1787 d->progressTimer->start(500); 1788 } 1789 else 1790 { 1791 d->progressTimer->stop(); 1792 } 1793 } 1794 1795 void ImportUI::slotProgressTimerDone() 1796 { 1797 d->progressTimer->start(300); 1798 } 1799 1800 void ImportUI::itemsSelectionSizeInfo(qint64& fSizeBytes, qint64& dSizeBytes) 1801 { 1802 fSizeBytes = 0; // Files size 1803 dSizeBytes = 0; // Estimated space requires to download and process files. 1804 1805 const QList<QUrl>& selected = d->view->selectedUrls(); 1806 DownloadSettings settings = downloadSettings(); 1807 1808 Q_FOREACH (const CamItemInfo& info, d->view->allItems()) 1809 { 1810 if (selected.contains(info.url())) 1811 { 1812 qint64 size = info.size; 1813 1814 if (size < 0) // -1 if size is not provided by camera 1815 { 1816 continue; 1817 } 1818 1819 fSizeBytes += size; 1820 1821 if (info.mime == QLatin1String("image/jpeg")) 1822 { 1823 if (settings.convertJpeg) 1824 { 1825 // Estimated size is around 5 x original size when JPEG=>PNG. 1826 1827 dSizeBytes += size * 5; 1828 } 1829 else if (settings.autoRotate) 1830 { 1831 // We need a double size to perform rotation. 1832 1833 dSizeBytes += size * 2; 1834 } 1835 else 1836 { 1837 // Real file size is added. 1838 1839 dSizeBytes += size; 1840 } 1841 } 1842 else if (settings.convertDng && info.mime == QLatin1String("image/x-raw")) 1843 { 1844 // Estimated size is around 2 x original size when RAW=>DNG. 1845 1846 dSizeBytes += size * 2; 1847 } 1848 else 1849 { 1850 dSizeBytes += size; 1851 } 1852 1853 } 1854 } 1855 } 1856 1857 void ImportUI::checkItem4Deletion(const CamItemInfo& info, QStringList& folders, QStringList& files, 1858 CamItemInfoList& deleteList, CamItemInfoList& lockedList) 1859 { 1860 if (info.writePermissions != 0) // Item not locked ? 1861 { 1862 QString folder = info.folder; 1863 QString file = info.name; 1864 folders.append(folder); 1865 files.append(file); 1866 deleteList.append(info); 1867 } 1868 else 1869 { 1870 lockedList.append(info); 1871 } 1872 } 1873 1874 void ImportUI::deleteItems(bool onlySelected, bool onlyDownloaded) 1875 { 1876 QStringList folders; 1877 QStringList files; 1878 CamItemInfoList deleteList; 1879 CamItemInfoList lockedList; 1880 const CamItemInfoList& list = onlySelected ? d->view->selectedCamItemInfos() : d->view->allItems(); 1881 1882 Q_FOREACH (const CamItemInfo& info, list) 1883 { 1884 if (onlyDownloaded) 1885 { 1886 if (info.downloaded == CamItemInfo::DownloadedYes) 1887 { 1888 checkItem4Deletion(info, folders, files, deleteList, lockedList); 1889 } 1890 } 1891 else 1892 { 1893 checkItem4Deletion(info, folders, files, deleteList, lockedList); 1894 } 1895 } 1896 1897 // If we want to delete some locked files, just give a feedback to user. 1898 1899 if (!lockedList.isEmpty()) 1900 { 1901 QString infoMsg(i18nc("@info", "The items listed below are locked by camera (read-only). " 1902 "These items will not be deleted. If you really want to delete these items, " 1903 "please unlock them and try again.")); 1904 CameraMessageBox::informationList(d->camThumbsCtrl, this, i18nc("@title", "Information"), infoMsg, lockedList); 1905 } 1906 1907 if (folders.isEmpty()) 1908 { 1909 return; 1910 } 1911 1912 QString warnMsg(i18ncp("@info", "About to delete this image.\n" 1913 "Deleted file is unrecoverable.\n" 1914 "Are you sure?", 1915 "About to delete these %1 images.\n" 1916 "Deleted files are unrecoverable.\n" 1917 "Are you sure?", 1918 deleteList.count())); 1919 1920 if (CameraMessageBox::warningContinueCancelList(d->camThumbsCtrl, 1921 this, 1922 i18nc("@title: confirm delete items dialog", "Warning"), 1923 warnMsg, 1924 deleteList, 1925 QLatin1String("DontAskAgainToDeleteItemsFromCamera")) 1926 == QMessageBox::Yes) 1927 { 1928 QStringList::const_iterator itFolder = folders.constBegin(); 1929 QStringList::const_iterator itFile = files.constBegin(); 1930 1931 d->statusProgressBar->setProgressValue(0); 1932 d->statusProgressBar->setProgressTotalSteps(deleteList.count()); 1933 d->statusProgressBar->setProgressBarMode(StatusProgressBar::ProgressBarMode); 1934 1935 // enable cancel action. 1936 1937 d->cameraCancelAction->setEnabled(true); 1938 1939 for ( ; itFolder != folders.constEnd() ; ++itFolder, ++itFile) 1940 { 1941 d->controller->deleteFile(*itFolder, *itFile); 1942 1943 // the currentlyDeleting list is used to prevent loading items which 1944 // will immanently be deleted into the sidebar and wasting time 1945 1946 d->currentlyDeleting.append(*itFolder + *itFile); 1947 } 1948 } 1949 } 1950 1951 bool ImportUI::checkDiskSpace(PAlbum *pAlbum) 1952 { 1953 if (!pAlbum) 1954 { 1955 return false; 1956 } 1957 1958 qint64 fSizeBytes = 0; 1959 qint64 dSizeBytes = 0; 1960 itemsSelectionSizeInfo(fSizeBytes, dSizeBytes); 1961 QString albumRootPath = pAlbum->albumRootPath(); 1962 qint64 bytesAvail = d->albumLibraryFreeSpace->bytesAvail(albumRootPath); 1963 1964 if (dSizeBytes >= bytesAvail) 1965 { 1966 int result = QMessageBox::warning(this, i18nc("@title:window", "Insufficient Disk Space"), 1967 i18nc("@info", "There is not enough free space on the disk of the album you selected " 1968 "to download and process the selected pictures from the camera.\n\n" 1969 "Estimated space required: %1\n" 1970 "Available free space: %2\n\n" 1971 "Try Anyway?", 1972 ItemPropertiesTab::humanReadableBytesCount(dSizeBytes), 1973 ItemPropertiesTab::humanReadableBytesCount(bytesAvail)), 1974 QMessageBox::Yes | QMessageBox::No); 1975 1976 if (result == QMessageBox::No) 1977 { 1978 return false; 1979 } 1980 } 1981 1982 return true; 1983 } 1984 1985 bool ImportUI::downloadCameraItems(PAlbum* pAlbum, bool onlySelected, bool deleteAfter) 1986 { 1987 const QList<QUrl>& selected = d->view->selectedUrls(); 1988 DownloadSettings settings = downloadSettings(); 1989 QUrl url = pAlbum->fileUrl(); 1990 DownloadSettingsList allItems; 1991 1992 // -- Download camera items ------------------------------- 1993 1994 Q_FOREACH (const CamItemInfo& info, d->view->allItems()) 1995 { 1996 if (onlySelected && !selected.contains(info.url())) 1997 { 1998 continue; 1999 } 2000 2001 settings.folder = info.folder; 2002 settings.file = info.name; 2003 settings.mime = info.mime; 2004 settings.pickLabel = info.pickLabel; 2005 settings.colorLabel = info.colorLabel; 2006 settings.rating = info.rating; 2007 settings.dest = url.toLocalFile(); 2008 2009 allItems.append(settings); 2010 } 2011 2012 if (allItems.isEmpty()) 2013 { 2014 return false; 2015 } 2016 2017 d->lastDestURL = url; 2018 d->statusProgressBar->setNotify(true); 2019 d->statusProgressBar->setProgressValue(0); 2020 d->statusProgressBar->setProgressTotalSteps(allItems.count()); 2021 d->statusProgressBar->setProgressBarMode(StatusProgressBar::ProgressBarMode); 2022 2023 // enable cancel action. 2024 2025 d->cameraCancelAction->setEnabled(true); 2026 2027 // disable settings tab here instead of slotBusy: 2028 // Only needs to be disabled while downloading 2029 2030 d->advBox->setEnabled(false); 2031 d->view->setEnabled(false); 2032 2033 d->deleteAfter = deleteAfter; 2034 2035 d->downloadedItemList.clear(); 2036 d->downloadedDateHash.clear(); 2037 d->downloadedInfoHash.clear(); 2038 d->foldersToScan.clear(); 2039 2040 d->controller->download(allItems); 2041 2042 return true; 2043 } 2044 2045 bool ImportUI::createSubAlbums(QUrl& downloadUrl, const QString& suffix, const QDateTime& dateTime) 2046 { 2047 bool success = true; 2048 2049 if (d->albumCustomizer->autoAlbumDateEnabled()) 2050 { 2051 success &= createDateBasedSubAlbum(downloadUrl, dateTime); 2052 } 2053 2054 if (d->albumCustomizer->autoAlbumExtEnabled()) 2055 { 2056 success &= createExtBasedSubAlbum(downloadUrl, suffix, dateTime.date()); 2057 } 2058 2059 return success; 2060 } 2061 2062 bool ImportUI::createSubAlbum(QUrl& downloadUrl, const QString& subalbum, const QDate& date) 2063 { 2064 QString errMsg; 2065 2066 if (!createAutoAlbum(downloadUrl, subalbum, date, errMsg)) 2067 { 2068 slotLogMsg(errMsg, DHistoryView::ErrorEntry); 2069 2070 return false; 2071 } 2072 2073 downloadUrl = downloadUrl.adjusted(QUrl::StripTrailingSlash); 2074 downloadUrl.setPath(downloadUrl.path() + QLatin1Char('/') + subalbum); 2075 2076 return true; 2077 } 2078 2079 bool ImportUI::createDateBasedSubAlbum(QUrl& downloadUrl, const QDateTime& dateTime) 2080 { 2081 QString dirName; 2082 2083 switch (d->albumCustomizer->folderDateFormat()) 2084 { 2085 case AlbumCustomizer::TextDateFormat: 2086 dirName = dateTime.date().toString(Qt::TextDate); 2087 break; 2088 2089 case AlbumCustomizer::LocalDateFormat: 2090 dirName = QLocale().toString(dateTime, QLocale::ShortFormat); 2091 break; 2092 2093 case AlbumCustomizer::IsoDateFormat: 2094 dirName = dateTime.date().toString(Qt::ISODate); 2095 break; 2096 2097 default: // Custom 2098 dirName = dateTime.date().toString(d->albumCustomizer->customDateFormat()); 2099 break; 2100 } 2101 2102 return createSubAlbum(downloadUrl, dirName, dateTime.date()); 2103 } 2104 2105 bool ImportUI::createExtBasedSubAlbum(QUrl& downloadUrl, const QString& suffix, const QDate& date) 2106 { 2107 // We use the target file suffix to compute sub-albums name to take a care about 2108 // conversion on the fly option. 2109 2110 QString subAlbum = suffix.toUpper(); 2111 2112 if ( 2113 (subAlbum == QLatin1String("JPEG")) || 2114 (subAlbum == QLatin1String("JPE")) 2115 ) 2116 { 2117 subAlbum = QLatin1String("JPG"); 2118 } 2119 else if (subAlbum == QLatin1String("TIFF")) 2120 { 2121 subAlbum = QLatin1String("TIF"); 2122 } 2123 else if ( 2124 (subAlbum == QLatin1String("MPEG")) || 2125 (subAlbum == QLatin1String("MPE")) || 2126 (subAlbum == QLatin1String("MTS")) 2127 ) 2128 { 2129 subAlbum = QLatin1String("MPG"); 2130 } 2131 2132 return createSubAlbum(downloadUrl, subAlbum, date); 2133 } 2134 2135 void ImportUI::slotDeleteAfterDownload() 2136 { 2137 deleteItems(true, true); 2138 } 2139 2140 void ImportUI::slotDeleteSelected() 2141 { 2142 deleteItems(true, false); 2143 } 2144 2145 void ImportUI::slotDeleteNew() 2146 { 2147 slotSelectNew(); 2148 QTimer::singleShot(0, this, SLOT(slotDeleteSelected())); 2149 } 2150 2151 void ImportUI::slotDeleteAll() 2152 { 2153 deleteItems(false, false); 2154 } 2155 2156 void ImportUI::slotDeleted(const QString& folder, const QString& file, bool status) 2157 { 2158 if (status) 2159 { 2160 // do this after removeItem. 2161 2162 d->currentlyDeleting.removeAll(folder + file); 2163 } 2164 2165 int curr = d->statusProgressBar->progressValue(); 2166 d->statusProgressBar->setProgressValue(curr + 1); 2167 refreshFreeSpace(); 2168 } 2169 2170 void ImportUI::slotMetadata(const QString& folder, const QString& file, const MetaEngineData& data) 2171 { 2172 CamItemInfo info = d->view->camItemInfo(folder, file); 2173 2174 if (!info.isNull()) 2175 { 2176 QScopedPointer<DMetadata> meta(new DMetadata); 2177 meta.data()->setData(data); 2178 d->rightSideBar->itemChanged(info, *meta); 2179 } 2180 } 2181 2182 void ImportUI::slotNewSelection(bool hasSelection) 2183 { 2184 updateActions(); 2185 2186 const CamItemInfoList& list = d->view->selectedCamItemInfos(); 2187 2188 if (hasSelection && !list.isEmpty()) 2189 { 2190 QList<ParseSettings> renameFiles; 2191 const CamItemInfo& info = list.constFirst(); 2192 2193 ParseSettings parseSettings; 2194 2195 parseSettings.fileUrl = info.url(); 2196 parseSettings.creationTime = info.ctime; 2197 renameFiles.append(parseSettings); 2198 2199 d->renameCustomizer->renameManager()->reset(); 2200 d->renameCustomizer->renameManager()->addFiles(renameFiles); 2201 d->renameCustomizer->renameManager()->parseFiles(); 2202 2203 slotUpdateRenamePreview(); 2204 } 2205 else 2206 { 2207 d->renameCustomizer->renameManager()->reset(); 2208 d->renameCustomizer->setPreviewText(QString()); 2209 } 2210 2211 qint64 fSizeBytes = 0; 2212 qint64 dSizeBytes = 0; 2213 itemsSelectionSizeInfo(fSizeBytes, dSizeBytes); 2214 d->albumLibraryFreeSpace->setEstimatedDSizeBytes(dSizeBytes); 2215 } 2216 2217 void ImportUI::slotImageSelected(const CamItemInfoList& selection, const CamItemInfoList& listAll) 2218 { 2219 if (d->cameraCancelAction->isEnabled()) 2220 { 2221 return; 2222 } 2223 2224 int num_images = listAll.count(); 2225 2226 switch (selection.count()) 2227 { 2228 case 0: 2229 { 2230 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, 2231 i18ncp("@info:status", 2232 "No item selected (%1 item)", 2233 "No item selected (%1 items)", 2234 num_images)); 2235 2236 d->rightSideBar->slotNoCurrentItem(); 2237 break; 2238 } 2239 2240 case 1: 2241 { 2242 // if selected item is in the list of item which will be deleted, set no current item 2243 2244 if (!d->currentlyDeleting.contains(selection.first().folder + selection.first().name)) 2245 { 2246 updateRightSideBar(selection.first()); 2247 2248 int index = listAll.indexOf(selection.first()) + 1; 2249 2250 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, 2251 i18nc("@info:status Filename of first selected item of number of items", 2252 "\"%1\" (%2 of %3)", 2253 selection.first().url().fileName(), index, num_images)); 2254 } 2255 else 2256 { 2257 d->rightSideBar->slotNoCurrentItem(); 2258 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, 2259 i18ncp("@info:status", 2260 "No item selected (%1 item)", 2261 "No item selected (%1 items)", 2262 num_images)); 2263 } 2264 2265 break; 2266 } 2267 2268 default: 2269 { 2270 d->statusProgressBar->setProgressBarMode(StatusProgressBar::TextMode, 2271 i18ncp("@info:status", "%2/%1 item selected", 2272 "%2/%1 items selected", 2273 num_images, selection.count())); 2274 break; 2275 } 2276 } 2277 } 2278 2279 void ImportUI::updateRightSideBar(const CamItemInfo& info) 2280 { 2281 d->rightSideBar->itemChanged(info, DMetadata()); 2282 2283 if (!d->busy) 2284 { 2285 d->controller->getMetadata(info.folder, info.name); 2286 } 2287 } 2288 2289 QString ImportUI::identifyCategoryforMime(const QString& mime) 2290 { 2291 return mime.split(QLatin1Char('/')).at(0); 2292 } 2293 2294 void ImportUI::postProcessAfterDownload() 2295 { 2296 if (d->downloadedItemList.isEmpty()) 2297 { 2298 return; 2299 } 2300 2301 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 2302 KConfigGroup group = config->group(d->configGroupName); 2303 SetupCamera::ConflictRule conflictRule = (SetupCamera::ConflictRule)group.readEntry(d->configFileSaveConflictRule, 2304 (int)SetupCamera::DIFFNAME); 2305 2306 // Is auto-rotate option checked? 2307 2308 bool autoRotate = downloadSettings().autoRotate; 2309 QList<ParseSettings> renameFiles; 2310 QStringList renamedItemsList; 2311 2312 Q_FOREACH (const QString& srcFile, d->downloadedItemList) 2313 { 2314 ParseSettings parseSettings; 2315 2316 parseSettings.fileUrl = QUrl::fromLocalFile(srcFile); 2317 parseSettings.creationTime = d->downloadedDateHash.value(srcFile); 2318 renameFiles.append(parseSettings); 2319 } 2320 2321 d->renameCustomizer->renameManager()->reset(); 2322 d->renameCustomizer->renameManager()->setCutFileName(39); 2323 d->renameCustomizer->renameManager()->addFiles(renameFiles); 2324 d->renameCustomizer->renameManager()->parseFiles(); 2325 2326 Q_FOREACH (const QString& srcFile, d->downloadedItemList) 2327 { 2328 QFileInfo srcInfo(srcFile); 2329 2330 QString newName; 2331 QString orgName = srcInfo.fileName().mid(39); 2332 2333 if (d->renameCustomizer->useDefault()) 2334 { 2335 newName = d->renameCustomizer->newName(orgName); 2336 } 2337 else 2338 { 2339 newName = d->renameCustomizer->newName(srcFile); 2340 } 2341 2342 if (newName == srcInfo.fileName()) 2343 { 2344 newName = orgName; 2345 } 2346 2347 QString dstFile = srcInfo.path() + QLatin1Char('/') + newName; 2348 QFileInfo dstInfo(dstFile); 2349 2350 if (dstInfo.exists() && (conflictRule == SetupCamera::SKIPFILE)) 2351 { 2352 QFile::remove(srcFile); 2353 2354 slotLogMsg(xi18n("Skipped file <filename>%1</filename>", dstInfo.fileName()), 2355 DHistoryView::WarningEntry); 2356 2357 QPair<QString, QString> fPair = d->downloadedInfoHash.value(srcFile); 2358 CamItemInfo& info = d->view->camItemInfoRef(fPair.first, 2359 fPair.second); 2360 2361 if (!info.isNull()) 2362 { 2363 setDownloaded(info, CamItemInfo::DownloadedNo); 2364 } 2365 2366 continue; 2367 } 2368 else if (conflictRule != SetupCamera::OVERWRITE) 2369 { 2370 bool newurl = false; 2371 dstFile = DFileOperations::getUniqueFileUrl(QUrl::fromLocalFile(dstFile), &newurl).toLocalFile(); 2372 dstInfo = QFileInfo(dstFile); 2373 2374 if (newurl) 2375 { 2376 slotLogMsg(xi18n("Rename file to <filename>%1</filename>", dstInfo.fileName()), 2377 DHistoryView::WarningEntry); 2378 } 2379 } 2380 2381 // move the file to the destination file 2382 2383 if (DMetadata::hasSidecar(srcFile)) 2384 { 2385 QString sctemp = DMetadata::sidecarPath(srcFile); 2386 QString scdest = DMetadata::sidecarPath(dstFile); 2387 2388 qCDebug(DIGIKAM_IMPORTUI_LOG) << "File" << sctemp << " has a sidecar, renaming it to " << scdest; 2389 2390 // remove scdest file if it exist 2391 2392 if ((sctemp != scdest) && QFile::exists(sctemp) && QFile::exists(scdest)) 2393 { 2394 QFile::remove(scdest); 2395 } 2396 2397 if (!DFileOperations::renameFile(sctemp, scdest)) 2398 { 2399 slotLogMsg(xi18n("Failed to save sidecar file for <filename>%1</filename>", dstInfo.fileName()), 2400 DHistoryView::ErrorEntry); 2401 } 2402 } 2403 2404 // remove dest file if it exist 2405 2406 if ((srcFile != dstFile) && QFile::exists(srcFile) && QFile::exists(dstFile)) 2407 { 2408 QFile::remove(dstFile); 2409 } 2410 2411 if (!DFileOperations::renameFile(srcFile, dstFile)) 2412 { 2413 qCDebug(DIGIKAM_IMPORTUI_LOG) << "Renaming " << srcFile << " to " << dstFile << " failed"; 2414 2415 // rename failed. delete the temp file 2416 2417 QFile::remove(srcFile); 2418 2419 slotLogMsg(xi18n("Failed to download <filename>%1</filename>", dstInfo.fileName()), 2420 DHistoryView::ErrorEntry); 2421 } 2422 else 2423 { 2424 renamedItemsList << dstFile; 2425 } 2426 } 2427 2428 NewItemsFinder* const tool = new NewItemsFinder(NewItemsFinder::ScheduleCollectionScan, d->foldersToScan); 2429 tool->start(); 2430 2431 d->foldersToScan.clear(); 2432 d->downloadedItemList.clear(); 2433 d->downloadedDateHash.clear(); 2434 d->downloadedInfoHash.clear(); 2435 2436 // Pop-up a notification to inform user when all is done, 2437 // and inform if auto-rotation will take place. 2438 2439 if (autoRotate) 2440 { 2441 d->waitAutoRotate = true; 2442 2443 connect(tool, &NewItemsFinder::signalComplete, 2444 this, [=]() 2445 { 2446 ItemInfoList infoList; 2447 2448 Q_FOREACH (const QString& dstFile, renamedItemsList) 2449 { 2450 ItemInfo itemInfo = ItemInfo::fromLocalFile(dstFile); 2451 2452 if (itemInfo.format() == QLatin1String("JPG")) 2453 { 2454 infoList << itemInfo; 2455 } 2456 } 2457 2458 if (!infoList.isEmpty()) 2459 { 2460 FileActionMngr::instance()->transform(infoList, MetaEngineRotation::NoTransformation); 2461 } 2462 2463 if (d->waitAutoRotate) 2464 { 2465 d->waitAutoRotate = false; 2466 } 2467 else 2468 { 2469 close(); 2470 } 2471 } 2472 ); 2473 2474 DNotificationWrapper(QLatin1String("cameradownloaded"), 2475 i18nc("@info Popup notification", 2476 "Images download finished, you can now detach " 2477 "your camera while the images are auto-rotated"), 2478 this, windowTitle()); 2479 } 2480 else 2481 { 2482 DNotificationWrapper(QLatin1String("cameradownloaded"), 2483 i18nc("@info Popup notification", 2484 "Images download finished"), 2485 this, windowTitle()); 2486 } 2487 } 2488 2489 bool ImportUI::createAutoAlbum(const QUrl& parentURL, const QString& sub, 2490 const QDate& date, QString& errMsg) const 2491 { 2492 QUrl url(parentURL); 2493 url = url.adjusted(QUrl::StripTrailingSlash); 2494 url.setPath(url.path() + QLatin1Char('/') + sub); 2495 2496 // first stat to see if the album exists 2497 2498 QFileInfo info(url.toLocalFile()); 2499 2500 if (info.exists()) 2501 { 2502 // now check if its really a directory 2503 2504 if (info.isDir()) 2505 { 2506 return true; 2507 } 2508 else 2509 { 2510 errMsg = i18nc("@info", "A file with the same name (\"%1\") already exists in folder \"%2\".", 2511 sub, QDir::toNativeSeparators(parentURL.toLocalFile())); 2512 return false; 2513 } 2514 } 2515 2516 // looks like the directory does not exist, try to create it. 2517 // First we make sure that the parent exists. 2518 2519 PAlbum* parent = AlbumManager::instance()->findPAlbum(parentURL); 2520 2521 if (!parent) 2522 { 2523 errMsg = i18nc("@info", "Failed to find Album for path \"%1\".", 2524 QDir::toNativeSeparators(parentURL.toLocalFile())); 2525 return false; 2526 } 2527 2528 // Create the album, with any parent albums required for the structure 2529 2530 QUrl albumUrl(parentURL); 2531 2532 Q_FOREACH (const QString& folder, sub.split(QLatin1Char('/'), QT_SKIP_EMPTY_PARTS)) 2533 { 2534 albumUrl = albumUrl.adjusted(QUrl::StripTrailingSlash); 2535 albumUrl.setPath(albumUrl.path() + QLatin1Char('/') + folder); 2536 2537 PAlbum* album = AlbumManager::instance()->findPAlbum(albumUrl); 2538 2539 if (!album) 2540 { 2541 album = AlbumManager::instance()->createPAlbum(parent, folder, QString(), date, QString(), errMsg); 2542 2543 if (!album) 2544 { 2545 return false; 2546 } 2547 } 2548 2549 parent = album; 2550 } 2551 2552 return true; 2553 } 2554 2555 void ImportUI::slotSetup() 2556 { 2557 Setup::execDialog(this); 2558 } 2559 2560 void ImportUI::slotCameraFreeSpaceInfo(qint64 bytesSize, qint64 bytesAvail) 2561 { 2562 d->cameraFreeSpace->addInformation(bytesSize, bytesSize - bytesAvail, bytesAvail, QString()); 2563 } 2564 2565 bool ImportUI::cameraDeleteSupport() const 2566 { 2567 return d->controller->cameraDeleteSupport(); 2568 } 2569 2570 bool ImportUI::cameraUploadSupport() const 2571 { 2572 return d->controller->cameraUploadSupport(); 2573 } 2574 2575 bool ImportUI::cameraMkDirSupport() const 2576 { 2577 return d->controller->cameraMkDirSupport(); 2578 } 2579 2580 bool ImportUI::cameraDelDirSupport() const 2581 { 2582 return d->controller->cameraDelDirSupport(); 2583 } 2584 2585 bool ImportUI::cameraUseUMSDriver() const 2586 { 2587 return d->controller->cameraDriverType() == DKCamera::UMSDriver; 2588 } 2589 2590 bool ImportUI::cameraUseGPhotoDriver() const 2591 { 2592 return d->controller->cameraDriverType() == DKCamera::GPhotoDriver; 2593 } 2594 2595 void ImportUI::enableZoomPlusAction(bool val) 2596 { 2597 d->increaseThumbsAction->setEnabled(val); 2598 } 2599 2600 void ImportUI::enableZoomMinusAction(bool val) 2601 { 2602 d->decreaseThumbsAction->setEnabled(val); 2603 } 2604 2605 void ImportUI::slotComponentsInfo() 2606 { 2607 showDigikamComponentsInfo(); 2608 } 2609 2610 void ImportUI::slotDBStat() 2611 { 2612 showDigikamDatabaseStat(); 2613 } 2614 2615 void ImportUI::slotOnlineVersionCheck() 2616 { 2617 Setup::onlineVersionCheck(); 2618 } 2619 2620 void ImportUI::refreshCollectionFreeSpace() 2621 { 2622 d->albumLibraryFreeSpace->setPaths(CollectionManager::instance()->allAvailableAlbumRootPaths()); 2623 } 2624 2625 void ImportUI::slotCollectionLocationStatusChanged(const CollectionLocation&, int) 2626 { 2627 refreshCollectionFreeSpace(); 2628 } 2629 2630 void ImportUI::slotToggleShowBar() 2631 { 2632 showThumbBar(d->showBarAction->isChecked()); 2633 } 2634 2635 void ImportUI::slotLogMsg(const QString& msg, DHistoryView::EntryType type, 2636 const QString& folder, const QString& file) 2637 { 2638 d->statusProgressBar->setProgressText(msg); 2639 QStringList meta; 2640 meta << folder << file; 2641 d->historyView->addEntry(msg, type, QVariant(meta)); 2642 } 2643 2644 void ImportUI::slotShowLog() 2645 { 2646 d->showLogAction->isChecked() ? d->historyView->show() : d->historyView->hide(); 2647 } 2648 2649 void ImportUI::slotHistoryEntryClicked(const QVariant& metadata) 2650 { 2651 QStringList meta = metadata.toStringList(); 2652 QString folder = meta.at(0); 2653 QString file = meta.at(1); 2654 d->view->scrollTo(folder, file); 2655 } 2656 2657 void ImportUI::showSideBars(bool visible) 2658 { 2659 visible ? d->rightSideBar->restore() 2660 : d->rightSideBar->backup(); 2661 } 2662 2663 void ImportUI::slotToggleRightSideBar() 2664 { 2665 d->rightSideBar->isExpanded() ? d->rightSideBar->shrink() 2666 : d->rightSideBar->expand(); 2667 } 2668 2669 void ImportUI::slotPreviousRightSideBarTab() 2670 { 2671 d->rightSideBar->activePreviousTab(); 2672 } 2673 2674 void ImportUI::slotNextRightSideBarTab() 2675 { 2676 d->rightSideBar->activeNextTab(); 2677 } 2678 2679 void ImportUI::showThumbBar(bool visible) 2680 { 2681 d->view->toggleShowBar(visible); 2682 } 2683 2684 bool ImportUI::thumbbarVisibility() const 2685 { 2686 return d->showBarAction->isChecked(); 2687 } 2688 2689 void ImportUI::slotSwitchedToPreview() 2690 { 2691 d->zoomBar->setBarMode(DZoomBar::PreviewZoomCtrl); 2692 d->imageViewSelectionAction->setCurrentAction(d->camItemPreviewAction); 2693 toogleShowBar(); 2694 } 2695 2696 void ImportUI::slotSwitchedToIconView() 2697 { 2698 d->zoomBar->setBarMode(DZoomBar::ThumbsSizeCtrl); 2699 d->imageViewSelectionAction->setCurrentAction(d->iconViewAction); 2700 toogleShowBar(); 2701 } 2702 2703 void ImportUI::slotSwitchedToMapView() 2704 { 2705 d->zoomBar->setBarMode(DZoomBar::ThumbsSizeCtrl); 2706 2707 #ifdef HAVE_GEOLOCATION 2708 2709 d->imageViewSelectionAction->setCurrentAction(d->mapViewAction); 2710 2711 #endif 2712 2713 toogleShowBar(); 2714 } 2715 2716 void ImportUI::customizedFullScreenMode(bool set) 2717 { 2718 toolBarMenuAction()->setEnabled(!set); 2719 showMenuBarAction()->setEnabled(!set); 2720 showStatusBarAction()->setEnabled(!set); 2721 set ? d->showBarAction->setEnabled(false) 2722 : toogleShowBar(); 2723 2724 d->view->toggleFullScreen(set); 2725 } 2726 2727 void ImportUI::toogleShowBar() 2728 { 2729 switch (d->view->viewMode()) 2730 { 2731 case ImportStackedView::PreviewImageMode: 2732 case ImportStackedView::MediaPlayerMode: 2733 d->showBarAction->setEnabled(true); 2734 break; 2735 2736 default: 2737 d->showBarAction->setEnabled(false); 2738 break; 2739 } 2740 } 2741 2742 void ImportUI::slotSetupChanged() 2743 { 2744 d->filterComboBox->updateFilter(); 2745 setFilter(d->filterComboBox->currentFilter()); 2746 d->view->importFilterModel()->setStringTypeNatural(ApplicationSettings::instance()->isStringTypeNatural()); 2747 2748 // Load full-screen options 2749 2750 KConfigGroup group = KSharedConfig::openConfig()->group(ApplicationSettings::instance()->generalConfigGroupName()); 2751 readFullScreenSettings(group); 2752 2753 d->view->applySettings(); 2754 sidebarTabTitleStyleChanged(); 2755 } 2756 2757 void ImportUI::sidebarTabTitleStyleChanged() 2758 { 2759 d->rightSideBar->setStyle(ApplicationSettings::instance()->getSidebarTitleStyle()); 2760 d->rightSideBar->applySettings(); 2761 } 2762 2763 void ImportUI::slotToggleColorManagedView() 2764 { 2765 if (!IccSettings::instance()->isEnabled()) 2766 { 2767 return; 2768 } 2769 2770 bool cmv = !IccSettings::instance()->settings().useManagedPreviews; 2771 IccSettings::instance()->setUseManagedPreviews(cmv); 2772 d->camThumbsCtrl->clearCache(); 2773 } 2774 2775 void ImportUI::slotColorManagementOptionsChanged() 2776 { 2777 ICCSettingsContainer settings = IccSettings::instance()->settings(); 2778 2779 d->viewCMViewAction->blockSignals(true); 2780 d->viewCMViewAction->setEnabled(settings.enableCM); 2781 d->viewCMViewAction->setChecked(settings.useManagedPreviews); 2782 d->viewCMViewAction->blockSignals(false); 2783 } 2784 2785 } // namespace Digikam 2786 2787 #include "moc_importui.cpp"