File indexing completed on 2025-01-05 03:51:15

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2002-16-10
0007  * Description : main digiKam interface implementation - Internal setup
0008  *
0009  * SPDX-FileCopyrightText: 2002-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "digikamapp_p.h"
0016 
0017 namespace Digikam
0018 {
0019 
0020 void DigikamApp::setupView()
0021 {
0022     if (d->splashScreen)
0023     {
0024         d->splashScreen->setMessage(i18nc("@info: setup", "Initializing Main View..."));
0025     }
0026 
0027     d->view = new ItemIconView(this, d->modelCollection);
0028     setCentralWidget(d->view);
0029     d->view->applySettings();
0030 }
0031 
0032 void DigikamApp::setupViewConnections()
0033 {
0034     connect(d->view, SIGNAL(signalAlbumSelected(Album*)),
0035             this, SLOT(slotAlbumSelected(Album*)));
0036 
0037     connect(d->view, SIGNAL(signalSelectionChanged(int)),
0038             this, SLOT(slotSelectionChanged(int)));
0039 
0040     connect(d->view, SIGNAL(signalTrashSelectionChanged(QString)),
0041             this, SLOT(slotTrashSelectionChanged(QString)));
0042 
0043     connect(d->view, SIGNAL(signalImageSelected(ItemInfoList,ItemInfoList)),
0044             this, SLOT(slotImageSelected(ItemInfoList,ItemInfoList)));
0045 
0046     connect(d->view, SIGNAL(signalSwitchedToPreview()),
0047             this, SLOT(slotSwitchedToPreview()));
0048 
0049     connect(d->view, SIGNAL(signalSwitchedToIconView()),
0050             this, SLOT(slotSwitchedToIconView()));
0051 
0052     connect(d->view, SIGNAL(signalSwitchedToMapView()),
0053             this, SLOT(slotSwitchedToMapView()));
0054 
0055     connect(d->view, SIGNAL(signalSwitchedToTableView()),
0056             this, SLOT(slotSwitchedToTableView()));
0057 
0058     connect(d->view, SIGNAL(signalSwitchedToTrashView()),
0059             this, SLOT(slotSwitchedToTrashView()));
0060 }
0061 
0062 void DigikamApp::setupStatusBar()
0063 {
0064     d->statusLabel = new DAdjustableLabel(statusBar());
0065     d->statusLabel->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
0066     statusBar()->addWidget(d->statusLabel, 80);
0067 
0068     //------------------------------------------------------------------------------
0069 
0070     d->metadataStatusBar = new MetadataStatusBar(statusBar());
0071     statusBar()->addWidget(d->metadataStatusBar, 50);
0072 
0073     //------------------------------------------------------------------------------
0074 
0075     d->filterStatusBar = new FilterStatusBar(statusBar());
0076     statusBar()->addWidget(d->filterStatusBar, 50);
0077     d->view->connectIconViewFilter(d->filterStatusBar);
0078 
0079     //------------------------------------------------------------------------------
0080 
0081     ProgressView* const view = new ProgressView(statusBar(), this);
0082     view->hide();
0083 
0084     StatusbarProgressWidget* const littleProgress = new StatusbarProgressWidget(view, statusBar());
0085     littleProgress->show();
0086     statusBar()->addPermanentWidget(littleProgress);
0087 
0088     //------------------------------------------------------------------------------
0089 
0090     d->zoomBar = new DZoomBar(statusBar());
0091     d->zoomBar->setZoomToFitAction(d->zoomFitToWindowAction);
0092     d->zoomBar->setZoomTo100Action(d->zoomTo100percents);
0093     d->zoomBar->setZoomPlusAction(d->zoomPlusAction);
0094     d->zoomBar->setZoomMinusAction(d->zoomMinusAction);
0095     d->zoomBar->setBarMode(DZoomBar::ThumbsSizeCtrl);
0096     statusBar()->addPermanentWidget(d->zoomBar);
0097 
0098     //------------------------------------------------------------------------------
0099 
0100     connect(d->zoomBar, SIGNAL(signalZoomSliderChanged(int)),
0101             this, SLOT(slotZoomSliderChanged(int)));
0102 
0103     connect(this, SIGNAL(signalWindowHasMoved()),
0104             d->zoomBar, SLOT(slotUpdateTrackerPos()));
0105 
0106     connect(d->zoomBar, SIGNAL(signalZoomValueEdited(double)),
0107             d->view, SLOT(setZoomFactor(double)));
0108 
0109     connect(d->view, SIGNAL(signalZoomChanged(double)),
0110             this, SLOT(slotZoomChanged(double)));
0111 
0112     connect(d->view, SIGNAL(signalThumbSizeChanged(int)),
0113             this, SLOT(slotThumbSizeChanged(int)));
0114 }
0115 
0116 void DigikamApp::setupActions()
0117 {
0118     KActionCollection* const ac = actionCollection();
0119 
0120     d->solidCameraActionGroup   = new QActionGroup(this);
0121     connect(d->solidCameraActionGroup, SIGNAL(triggered(QAction*)),
0122             this, SLOT(slotOpenSolidCamera(QAction*)));
0123 
0124     d->solidUsmActionGroup      = new QActionGroup(this);
0125     connect(d->solidUsmActionGroup, SIGNAL(triggered(QAction*)),
0126             this, SLOT(slotOpenSolidUsmDevice(QAction*)));
0127 
0128     d->manualCameraActionGroup  = new QActionGroup(this);
0129     connect(d->manualCameraActionGroup, SIGNAL(triggered(QAction*)),
0130             this, SLOT(slotOpenManualCamera(QAction*)));
0131 
0132     // -----------------------------------------------------------------
0133 
0134     d->backwardActionMenu = new KToolBarPopupAction(QIcon::fromTheme(QLatin1String("go-previous")),
0135                                                     i18nc("@action: setup", "&Back"), this);
0136     d->backwardActionMenu->setEnabled(false);
0137     ac->addAction(QLatin1String("album_back"), d->backwardActionMenu);
0138     ac->setDefaultShortcut(d->backwardActionMenu, Qt::ALT | Qt::Key_Left);
0139 
0140 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0141 
0142     connect(d->backwardActionMenu->popupMenu(), SIGNAL(aboutToShow()),
0143             this, SLOT(slotAboutToShowBackwardMenu()));
0144 
0145 #else
0146 
0147     connect(d->backwardActionMenu->menu(), SIGNAL(aboutToShow()),
0148             this, SLOT(slotAboutToShowBackwardMenu()));
0149 
0150 #endif
0151 
0152     connect(d->backwardActionMenu, &QAction::triggered,
0153             this, [this]() { d->view->slotAlbumHistoryBack(1); });
0154 
0155     // -----------------------------------------------------------------
0156 
0157     d->forwardActionMenu = new KToolBarPopupAction(QIcon::fromTheme(QLatin1String("go-next")),
0158                                                    i18nc("@action: setup", "Forward"), this);
0159     d->forwardActionMenu->setEnabled(false);
0160     ac->addAction(QLatin1String("album_forward"), d->forwardActionMenu);
0161     ac->setDefaultShortcut(d->forwardActionMenu, Qt::ALT | Qt::Key_Right);
0162 
0163 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0164 
0165     connect(d->forwardActionMenu->popupMenu(), SIGNAL(aboutToShow()),
0166             this, SLOT(slotAboutToShowForwardMenu()));
0167 
0168 #else
0169 
0170     connect(d->forwardActionMenu->menu(), SIGNAL(aboutToShow()),
0171             this, SLOT(slotAboutToShowForwardMenu()));
0172 
0173 #endif
0174 
0175     connect(d->forwardActionMenu, &QAction::triggered,
0176             this, [this]() { d->view->slotAlbumHistoryForward(1); });
0177 
0178     // -----------------------------------------------------------------
0179 
0180     d->refreshAction = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")),
0181                                    i18nc("@action: setup", "Refresh"), this);
0182     d->refreshAction->setWhatsThis(i18nc("@info: setup", "Refresh the current contents."));
0183     connect(d->refreshAction, SIGNAL(triggered()), d->view, SLOT(slotRefresh()));
0184     ac->addAction(QLatin1String("view_refresh"), d->refreshAction);
0185     ac->setDefaultShortcuts(d->refreshAction,  QList<QKeySequence>() << Qt::Key_F5 << (Qt::CTRL | Qt::Key_F5));
0186 
0187     // -----------------------------------------------------------------
0188 
0189     Q_FOREACH (SidebarWidget* const leftWidget, d->view->leftSidebarWidgets())
0190     {
0191         QString actionName = QLatin1String("browse_") + leftWidget->objectName()
0192                                                         .remove(QLatin1Char(' '))
0193                                                         .remove(QLatin1String("Sidebar"))
0194                                                         .remove(QLatin1String("FolderView"))
0195                                                         .remove(QLatin1String("View")).toLower();
0196         qCDebug(DIGIKAM_GENERAL_LOG) << actionName;
0197 
0198         QAction* const action = new QAction(leftWidget->getIcon(), leftWidget->getCaption(), this);
0199         ac->addAction(actionName, action);
0200         ac->setDefaultShortcut(action, QKeySequence(leftWidget->property("Shortcut").toInt()));
0201 
0202         connect(action, &QAction::triggered,
0203                 this, [this, leftWidget]() { d->view->slotLeftSideBarActivate(leftWidget); });
0204     }
0205 
0206     // -----------------------------------------------------------------
0207 
0208     d->newAction = new QAction(QIcon::fromTheme(QLatin1String("folder-new")),
0209                                i18nc("@action: setup", "&New..."), this);
0210     d->newAction->setWhatsThis(i18nc("@info: setup", "Creates a new empty Album in the collection."));
0211     connect(d->newAction, SIGNAL(triggered()), d->view, SLOT(slotNewAlbum()));
0212     ac->addAction(QLatin1String("album_new"), d->newAction);
0213     ac->setDefaultShortcut(d->newAction, Qt::CTRL | Qt::Key_N);
0214 
0215     // -----------------------------------------------------------------
0216 
0217     d->moveSelectionToAlbumAction = new QAction(QIcon::fromTheme(QLatin1String("folder-new")),
0218                                                 i18nc("@action: setup", "&Move to Album..."), this);
0219     d->moveSelectionToAlbumAction->setWhatsThis(i18nc("@info: setup", "Move selected images into an album."));
0220     connect(d->moveSelectionToAlbumAction, SIGNAL(triggered()), d->view, SLOT(slotMoveSelectionToAlbum()));
0221     ac->addAction(QLatin1String("move_selection_to_album"), d->moveSelectionToAlbumAction);
0222 
0223     // -----------------------------------------------------------------
0224 
0225     d->copySelectionToAction = new QAction(QIcon::fromTheme(QLatin1String("edit-copy")),
0226                                            i18nc("@action: setup", "&Copy to..."), this);
0227     d->copySelectionToAction->setWhatsThis(i18nc("@info: setup", "Copy selected images to a target folder."));
0228     connect(d->copySelectionToAction, SIGNAL(triggered()), d->view, SLOT(slotCopySelectionTo()));
0229     ac->addAction(QLatin1String("copy_selection_to"), d->copySelectionToAction);
0230 
0231     // -----------------------------------------------------------------
0232 
0233     d->deleteAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")),
0234                                   i18nc("@action: setup", "Delete Album"), this);
0235     connect(d->deleteAction, SIGNAL(triggered()), d->view, SLOT(slotDeleteAlbum()));
0236     ac->addAction(QLatin1String("album_delete"), d->deleteAction);
0237 
0238     // -----------------------------------------------------------------
0239 
0240     d->renameAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")),
0241                                   i18nc("@action: setup", "Rename..."), this);
0242     connect(d->renameAction, SIGNAL(triggered()), d->view, SLOT(slotRenameAlbum()));
0243     ac->addAction(QLatin1String("album_rename"), d->renameAction);
0244     ac->setDefaultShortcut(d->renameAction, Qt::SHIFT | Qt::Key_F2);
0245 
0246     // -----------------------------------------------------------------
0247 
0248     d->propsEditAction = new QAction(QIcon::fromTheme(QLatin1String("configure")),
0249                                      i18nc("@action: setup", "Properties"), this);
0250     d->propsEditAction->setWhatsThis(i18nc("@info: setup", "Edit album properties and collection information."));
0251     connect(d->propsEditAction, SIGNAL(triggered()), d->view, SLOT(slotAlbumPropsEdit()));
0252     ac->addAction(QLatin1String("album_propsEdit"), d->propsEditAction);
0253     ac->setDefaultShortcut(d->propsEditAction, Qt::ALT | Qt::Key_Return);
0254 
0255     // -----------------------------------------------------------------
0256 
0257     d->writeAlbumMetadataAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")),
0258                                               i18nc("@action: setup", "Write Metadata to Files"), this);
0259     d->writeAlbumMetadataAction->setWhatsThis(i18nc("@info: setup", "Updates metadata of files in the current "
0260                                                     "album with the contents of digiKam database "
0261                                                     "(file metadata will be overwritten with data from "
0262                                                     "the database)."));
0263     connect(d->writeAlbumMetadataAction, SIGNAL(triggered()), d->view, SLOT(slotAlbumWriteMetadata()));
0264     ac->addAction(QLatin1String("album_write_metadata"), d->writeAlbumMetadataAction);
0265 
0266     // -----------------------------------------------------------------
0267 
0268     d->readAlbumMetadataAction = new QAction(QIcon::fromTheme(QLatin1String("edit-redo")),
0269                                              i18nc("@action: setup", "Reread Metadata From Files"), this);
0270     d->readAlbumMetadataAction->setWhatsThis(i18nc("@info: setup", "Updates the digiKam database from the metadata "
0271                                                    "of the files in the current album "
0272                                                    "(information in the database will be overwritten with data from "
0273                                                    "the files' metadata)."));
0274     connect(d->readAlbumMetadataAction, SIGNAL(triggered()), d->view, SLOT(slotAlbumReadMetadata()));
0275     ac->addAction(QLatin1String("album_read_metadata"), d->readAlbumMetadataAction);
0276 
0277     // -----------------------------------------------------------------
0278 
0279     d->openInFileManagerAction = new QAction(QIcon::fromTheme(QLatin1String("folder-open")),
0280                                              i18nc("@action: setup", "Open in File Manager"), this);
0281     connect(d->openInFileManagerAction, SIGNAL(triggered()), d->view, SLOT(slotAlbumOpenInFileManager()));
0282     ac->addAction(QLatin1String("album_openinfilemanager"), d->openInFileManagerAction);
0283 
0284     // -----------------------------------------------------------
0285 
0286     d->openTagMngrAction = new QAction(QIcon::fromTheme(QLatin1String("tag")),
0287                                        i18nc("@action: setup", "Tag Manager"), this);
0288     connect(d->openTagMngrAction, SIGNAL(triggered()), d->view, SLOT(slotOpenTagsManager()));
0289     ac->addAction(QLatin1String("open_tag_mngr"), d->openTagMngrAction);
0290 
0291     // -----------------------------------------------------------
0292 
0293     d->newTagAction = new QAction(QIcon::fromTheme(QLatin1String("tag-new")),
0294                                   i18nc("@action: new tag", "N&ew..."), this);
0295     connect(d->newTagAction, SIGNAL(triggered()), d->view, SLOT(slotNewTag()));
0296     ac->addAction(QLatin1String("tag_new"), d->newTagAction);
0297 
0298     // -----------------------------------------------------------
0299 
0300     d->editTagAction = new QAction(QIcon::fromTheme(QLatin1String("tag-properties")),
0301                                    i18nc("@action: setup", "Properties"), this);
0302     connect(d->editTagAction, SIGNAL(triggered()), d->view, SLOT(slotEditTag()));
0303     ac->addAction(QLatin1String("tag_edit"), d->editTagAction);
0304 
0305     // -----------------------------------------------------------
0306 
0307     d->deleteTagAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")),
0308                                      i18nc("@action: setup", "Delete"), this);
0309     connect(d->deleteTagAction, SIGNAL(triggered()), d->view, SLOT(slotDeleteTag()));
0310     ac->addAction(QLatin1String("tag_delete"), d->deleteTagAction);
0311 
0312     // -----------------------------------------------------------
0313 
0314     d->assignTagAction = new QAction(QIcon::fromTheme(QLatin1String("tag-new")),
0315                                      i18nc("@action: setup", "Assign Tag"), this);
0316     connect(d->assignTagAction, SIGNAL(triggered()), d->view, SLOT(slotAssignTag()));
0317     ac->addAction(QLatin1String("tag_assign"), d->assignTagAction);
0318     ac->setDefaultShortcut(d->assignTagAction, Qt::Key_T);
0319 
0320     // -----------------------------------------------------------
0321 
0322     d->imageViewSelectionAction = new KSelectAction(QIcon::fromTheme(QLatin1String("view-preview")),
0323                                                     i18nc("@action: setup", "Views"), this);
0324     ac->addAction(QLatin1String("view_selection"), d->imageViewSelectionAction);
0325 
0326     d->imageIconViewAction = new QAction(QIcon::fromTheme(QLatin1String("view-list-icons")),
0327                                          i18nc("@action: Go to thumbnails (icon) view", "Thumbnails"), this);
0328     d->imageIconViewAction->setCheckable(true);
0329     ac->addAction(QLatin1String("icon_view"), d->imageIconViewAction);
0330     connect(d->imageIconViewAction, SIGNAL(triggered()), d->view, SLOT(slotIconView()));
0331     d->imageViewSelectionAction->addAction(d->imageIconViewAction);
0332 
0333     d->imagePreviewAction = new QAction(QIcon::fromTheme(QLatin1String("view-preview")),
0334                                         i18nc("@action: View the selected image", "Preview"), this);
0335     d->imagePreviewAction->setCheckable(true);
0336     ac->addAction(QLatin1String("image_view"), d->imagePreviewAction);
0337     ac->setDefaultShortcut(d->imagePreviewAction, Qt::Key_F3);
0338     connect(d->imagePreviewAction, SIGNAL(triggered()), d->view, SLOT(slotImagePreview()));
0339     d->imageViewSelectionAction->addAction(d->imagePreviewAction);
0340 
0341 #ifdef HAVE_GEOLOCATION
0342 
0343     d->imageMapViewAction = new QAction(QIcon::fromTheme(QLatin1String("globe")),
0344                                         i18nc("@action: Switch to map view", "Map"), this);
0345     d->imageMapViewAction->setCheckable(true);
0346     ac->addAction(QLatin1String("map_view"), d->imageMapViewAction);
0347     connect(d->imageMapViewAction, SIGNAL(triggered()), d->view, SLOT(slotMapWidgetView()));
0348     d->imageViewSelectionAction->addAction(d->imageMapViewAction);
0349 
0350 #endif // HAVE_GEOLOCATION
0351 
0352     d->imageTableViewAction = new QAction(QIcon::fromTheme(QLatin1String("view-list-details")),
0353                                           i18nc("@action: Switch to table view", "Table"), this);
0354     d->imageTableViewAction->setCheckable(true);
0355     ac->addAction(QLatin1String("table_view"), d->imageTableViewAction);
0356     connect(d->imageTableViewAction, SIGNAL(triggered()), d->view, SLOT(slotTableView()));
0357     d->imageViewSelectionAction->addAction(d->imageTableViewAction);
0358 
0359     // -----------------------------------------------------------
0360 
0361     d->imageViewAction = new QAction(QIcon::fromTheme(QLatin1String("quickopen-file")),
0362                                      i18nc("@action: setup", "Open..."), this);
0363     d->imageViewAction->setWhatsThis(i18nc("@info: setup", "Open the selected item."));
0364     connect(d->imageViewAction, SIGNAL(triggered()), d->view, SLOT(slotImageEdit()));
0365     ac->addAction(QLatin1String("image_edit"), d->imageViewAction);
0366     ac->setDefaultShortcut(d->imageViewAction, Qt::Key_F4);
0367 
0368     d->openWithAction = new QAction(QIcon::fromTheme(QLatin1String("preferences-desktop-filetype-association")),
0369                                     i18nc("@action: setup", "Open With Default Application"), this);
0370     d->openWithAction->setWhatsThis(i18nc("@info: setup", "Open the selected item with default assigned application."));
0371     connect(d->openWithAction, SIGNAL(triggered()), d->view, SLOT(slotFileWithDefaultApplication()));
0372     ac->addAction(QLatin1String("open_with_default_application"), d->openWithAction);
0373     ac->setDefaultShortcut(d->openWithAction, Qt::CTRL | Qt::Key_F4);
0374 
0375     d->ieAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")),
0376                               i18nc("@action: setup", "Image Editor"), this);
0377     d->ieAction->setWhatsThis(i18nc("@action: setup", "Open the image editor."));
0378     connect(d->ieAction, SIGNAL(triggered()), d->view, SLOT(slotEditor()));
0379     ac->addAction(QLatin1String("imageeditor"), d->ieAction);
0380 
0381     // -----------------------------------------------------------
0382 
0383     d->ltAction = new QAction(QIcon::fromTheme(QLatin1String("lighttable")),
0384                               i18nc("@action: setup", "Light Table"), this);
0385     connect(d->ltAction, SIGNAL(triggered()), d->view, SLOT(slotLightTable()));
0386     ac->addAction(QLatin1String("light_table"), d->ltAction);
0387     ac->setDefaultShortcut(d->ltAction, Qt::SHIFT | Qt::Key_L);
0388 
0389     d->imageLightTableAction = new QAction(QIcon::fromTheme(QLatin1String("lighttable")),
0390                                            i18nc("@action: setup", "Place onto Light Table"), this);
0391     d->imageLightTableAction->setWhatsThis(i18nc("@info: setup", "Place the selected items on the light table thumbbar."));
0392     connect(d->imageLightTableAction, SIGNAL(triggered()), d->view, SLOT(slotImageLightTable()));
0393     ac->addAction(QLatin1String("image_lighttable"), d->imageLightTableAction);
0394     ac->setDefaultShortcut(d->imageLightTableAction, Qt::CTRL | Qt::Key_L);
0395 
0396     d->imageAddLightTableAction = new QAction(QIcon::fromTheme(QLatin1String("list-add")),
0397                                               i18nc("@action: setup", "Add to Light Table"), this);
0398     d->imageAddLightTableAction->setWhatsThis(i18nc("@info: setup", "Add selected items to the light table thumbbar."));
0399     connect(d->imageAddLightTableAction, SIGNAL(triggered()), d->view, SLOT(slotImageAddToLightTable()));
0400     ac->addAction(QLatin1String("image_add_to_lighttable"), d->imageAddLightTableAction);
0401     ac->setDefaultShortcut(d->imageAddLightTableAction, Qt::CTRL | Qt::SHIFT | Qt::Key_L);
0402 
0403     // -----------------------------------------------------------
0404 
0405     d->bqmAction = new QAction(QIcon::fromTheme(QLatin1String("run-build")),
0406                                i18nc("@action: setup", "Batch Queue Manager"), this);
0407     connect(d->bqmAction, SIGNAL(triggered()), d->view, SLOT(slotQueueMgr()));
0408     ac->addAction(QLatin1String("queue_manager"), d->bqmAction);
0409     ac->setDefaultShortcut(d->bqmAction, Qt::SHIFT | Qt::Key_B);
0410 
0411     d->imageAddCurrentQueueAction = new QAction(QIcon::fromTheme(QLatin1String("go-up")),
0412                                                 i18nc("@action: setup", "Add to Current Queue"), this);
0413     d->imageAddCurrentQueueAction->setWhatsThis(i18nc("@info: setup", "Add selected items to current queue from batch manager."));
0414     connect(d->imageAddCurrentQueueAction, SIGNAL(triggered()), d->view, SLOT(slotImageAddToCurrentQueue()));
0415     ac->addAction(QLatin1String("image_add_to_current_queue"), d->imageAddCurrentQueueAction);
0416     ac->setDefaultShortcut(d->imageAddCurrentQueueAction, Qt::CTRL | Qt::Key_B);
0417 
0418     d->imageAddNewQueueAction = new QAction(QIcon::fromTheme(QLatin1String("list-add")),
0419                                             i18nc("@action: setup", "Add to New Queue"), this);
0420     d->imageAddNewQueueAction->setWhatsThis(i18nc("@info: setup", "Add selected items to a new queue from batch manager."));
0421     connect(d->imageAddNewQueueAction, SIGNAL(triggered()), d->view, SLOT(slotImageAddToNewQueue()));
0422     ac->addAction(QLatin1String("image_add_to_new_queue"), d->imageAddNewQueueAction);
0423     ac->setDefaultShortcut(d->imageAddNewQueueAction, Qt::CTRL | Qt::SHIFT | Qt::Key_B);
0424 
0425     // -----------------------------------------------------------------
0426 
0427     d->quickImportMenu->setTitle(i18nc("@action: Import photos from camera", "Import"));
0428     d->quickImportMenu->setIcon(QIcon::fromTheme(QLatin1String("camera-photo")));
0429     ac->addAction(QLatin1String("import_auto"), d->quickImportMenu->menuAction());
0430 
0431     // -----------------------------------------------------------------
0432 
0433     d->imageWriteMetadataAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")),
0434                                               i18nc("@action: setup", "Write Metadata to Selected Files"), this);
0435     d->imageWriteMetadataAction->setWhatsThis(i18nc("@info: setup", "Updates metadata of files in the current "
0436                                                     "album with the contents of digiKam database "
0437                                                     "(file metadata will be overwritten with data from "
0438                                                     "the database)."));
0439     connect(d->imageWriteMetadataAction, SIGNAL(triggered()), d->view, SLOT(slotImageWriteMetadata()));
0440     ac->addAction(QLatin1String("image_write_metadata"), d->imageWriteMetadataAction);
0441 
0442     // -----------------------------------------------------------------
0443 
0444     d->imageReadMetadataAction = new QAction(QIcon::fromTheme(QLatin1String("edit-redo")),
0445                                              i18nc("@action: setup", "Reread Metadata From Selected Files"), this);
0446     d->imageReadMetadataAction->setWhatsThis(i18nc("@info: setup", "Updates the digiKam database from the metadata "
0447                                                    "of the files in the current album "
0448                                                    "(information in the database will be overwritten with data from "
0449                                                    "the files' metadata)."));
0450     connect(d->imageReadMetadataAction, SIGNAL(triggered()), d->view, SLOT(slotImageReadMetadata()));
0451     ac->addAction(QLatin1String("image_read_metadata"), d->imageReadMetadataAction);
0452 
0453     // -----------------------------------------------------------
0454 
0455     d->imageScanForFacesAction = new QAction(QIcon::fromTheme(QLatin1String("list-add-user")),
0456                                              i18nc("@action: setup", "Scan for Faces"), this);
0457     connect(d->imageScanForFacesAction, SIGNAL(triggered()), d->view, SLOT(slotImageScanForFaces()));
0458     ac->addAction(QLatin1String("image_scan_for_faces"), d->imageScanForFacesAction);
0459 
0460     d->imageRecognizeFacesAction = new QAction(QIcon::fromTheme(QLatin1String("edit-find-user")),
0461                                                i18nc("@action: setup", "Recognize Faces"), this);
0462     connect(d->imageRecognizeFacesAction, SIGNAL(triggered()), d->view, SLOT(slotImageRecognizeFaces()));
0463     ac->addAction(QLatin1String("image_recognize_faces"), d->imageRecognizeFacesAction);
0464 
0465     d->imageRemoveAllFacesAction = new QAction(QIcon::fromTheme(QLatin1String("list-remove-user")),
0466                                                i18nc("@action: setup", "Remove all Faces"), this);
0467     connect(d->imageRemoveAllFacesAction, SIGNAL(triggered()), d->view, SLOT(slotImageRemoveAllFaces()));
0468     ac->addAction(QLatin1String("image_remove_all_faces"), d->imageRemoveAllFacesAction);
0469 
0470     // -----------------------------------------------------------
0471 
0472     d->imageFindSimilarAction = new QAction(QIcon::fromTheme(QLatin1String("tools-wizard")),
0473                                             i18nc("@action: setup", "Find Similar..."), this);
0474     d->imageFindSimilarAction->setWhatsThis(i18nc("@info: setup", "Find similar images using selected item as reference."));
0475     connect(d->imageFindSimilarAction, SIGNAL(triggered()), d->view, SLOT(slotImageFindSimilar()));
0476     ac->addAction(QLatin1String("image_find_similar"), d->imageFindSimilarAction);
0477 
0478     // -----------------------------------------------------------
0479 
0480     d->imageRenameAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")),
0481                                        i18nc("@action: setup", "Rename..."), this);
0482     d->imageRenameAction->setWhatsThis(i18nc("@info: setup", "Change the filename of the currently selected item."));
0483     connect(d->imageRenameAction, SIGNAL(triggered()), d->view, SLOT(slotImageRename()));
0484     ac->addAction(QLatin1String("image_rename"), d->imageRenameAction);
0485     ac->setDefaultShortcut(d->imageRenameAction, Qt::Key_F2);
0486 
0487     // -----------------------------------------------------------
0488 
0489     // Pop up dialog to ask user whether to move to trash
0490 
0491     d->imageDeleteAction = new QAction(QIcon::fromTheme(QLatin1String("user-trash")),
0492                                        i18nc("@action: Non-pluralized", "Move to Trash"), this);
0493     connect(d->imageDeleteAction, SIGNAL(triggered()), d->view, SLOT(slotImageDelete()));
0494     ac->addAction(QLatin1String("image_delete"), d->imageDeleteAction);
0495     ac->setDefaultShortcut(d->imageDeleteAction, Qt::Key_Delete);
0496 
0497     // -----------------------------------------------------------
0498 
0499     // Pop up dialog to ask user whether to permanently delete
0500     // FIXME: This action is never used?? How can someone delete a album directly, without moving it to the trash first?
0501     //        This is especially important when deleting from a different partition or from a net source.
0502     //        Also note that we use the wrong icon for the default album delete action, which should have a trashcan icon instead
0503     //        of a red cross, it confuses users.
0504 
0505     d->imageDeletePermanentlyAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")),
0506                                                   i18nc("@action: setup", "Delete Permanently"), this);
0507     connect(d->imageDeletePermanentlyAction, SIGNAL(triggered()), d->view, SLOT(slotImageDeletePermanently()));
0508     ac->addAction(QLatin1String("image_delete_permanently"), d->imageDeletePermanentlyAction);
0509     ac->setDefaultShortcut(d->imageDeletePermanentlyAction, Qt::SHIFT | Qt::Key_Delete);
0510 
0511     // -----------------------------------------------------------
0512 
0513     // These two actions are hidden, no menu entry, no toolbar entry, no shortcut.
0514     // Power users may add them.
0515 
0516     d->imageDeletePermanentlyDirectlyAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")),
0517                                                           i18nc("@action: setup", "Delete permanently without confirmation"), this);
0518     connect(d->imageDeletePermanentlyDirectlyAction, SIGNAL(triggered()),
0519             d->view, SLOT(slotImageDeletePermanentlyDirectly()));
0520     ac->addAction(QLatin1String("image_delete_permanently_directly"), d->imageDeletePermanentlyDirectlyAction);
0521 
0522     // -----------------------------------------------------------
0523 
0524     d->imageTrashDirectlyAction = new QAction(QIcon::fromTheme(QLatin1String("user-trash")),
0525                                               i18nc("@action: setup", "Move to trash without confirmation"), this);
0526     connect(d->imageTrashDirectlyAction, SIGNAL(triggered()),
0527             d->view, SLOT(slotImageTrashDirectly()));
0528     ac->addAction(QLatin1String("image_trash_directly"), d->imageTrashDirectlyAction);
0529 
0530     // -----------------------------------------------------------------
0531 
0532     d->albumSortAction = new KSelectAction(i18nc("@action: setup", "&Sort Albums"), this);
0533     d->albumSortAction->setWhatsThis(i18nc("@info: setup", "Sort Albums in tree-view."));
0534 
0535 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0536 
0537     connect(d->albumSortAction, SIGNAL(indexTriggered(int)),
0538             d->view, SLOT(slotSortAlbums(int)));
0539 
0540 #else
0541 
0542     connect(d->albumSortAction, SIGNAL(triggered(int)),
0543             d->view, SLOT(slotSortAlbums(int)));
0544 
0545 #endif
0546 
0547     ac->addAction(QLatin1String("album_sort"), d->albumSortAction);
0548 
0549     // Use same list order as in applicationsettings enum
0550 
0551     QStringList sortActionList;
0552     sortActionList.append(i18nc("@action: setup", "By Folder"));
0553     sortActionList.append(i18nc("@action: setup", "By Category"));
0554     sortActionList.append(i18nc("@action: setup", "By Date"));
0555     d->albumSortAction->setItems(sortActionList);
0556 
0557     // -----------------------------------------------------------
0558 
0559     d->recurseAlbumsAction = new QAction(i18nc("@action: setup", "Include Album Sub-Tree"), this);
0560     d->recurseAlbumsAction->setCheckable(true);
0561     d->recurseAlbumsAction->setWhatsThis(i18nc("@info: setup", "Activate this option to show all sub-albums below "
0562                                                "the current album."));
0563     connect(d->recurseAlbumsAction, SIGNAL(toggled(bool)), this, SLOT(slotRecurseAlbums(bool)));
0564     ac->addAction(QLatin1String("albums_recursive"), d->recurseAlbumsAction);
0565 
0566     d->recurseTagsAction   = new QAction(i18nc("@action: setup", "Include Tag Sub-Tree"), this);
0567     d->recurseTagsAction->setCheckable(true);
0568     d->recurseTagsAction->setWhatsThis(i18nc("@info: setup", "Activate this option to show all images marked by the given tag "
0569                                              "and all its sub-tags."));
0570     connect(d->recurseTagsAction, SIGNAL(toggled(bool)), this, SLOT(slotRecurseTags(bool)));
0571     ac->addAction(QLatin1String("tags_recursive"), d->recurseTagsAction);
0572 
0573     d->allGroupsOpenAction = new QAction(i18nc("@action: setup", "Show All Grouped Items As Open"), this);
0574     d->allGroupsOpenAction->setCheckable(true);
0575     d->allGroupsOpenAction->setWhatsThis(i18nc("@info: setup", "Activate this option to show all grouped items as open."));
0576     connect(d->allGroupsOpenAction, SIGNAL(toggled(bool)), this, SLOT(slotAllGroupsOpen(bool)));
0577     ac->addAction(QLatin1String("all_groups_open"), d->allGroupsOpenAction);
0578 
0579     // -----------------------------------------------------------
0580 
0581     d->imageSortAction     = new KSelectAction(i18nc("@action: setup", "&Sort Items"), this);
0582     d->imageSortAction->setWhatsThis(i18nc("@info: setup", "The value by which the images in one album are sorted in the thumbnail view"));
0583     ac->addAction(QLatin1String("image_sort"), d->imageSortAction);
0584 
0585     // map to ItemSortSettings enum
0586 
0587     QAction* const sortByNameAction               = d->imageSortAction->addAction(i18nc("@action: setup", "By Name"));
0588     QAction* const sortByPathAction               = d->imageSortAction->addAction(i18nc("@action: setup", "By Path"));
0589     QAction* const sortByDateAction               = d->imageSortAction->addAction(i18nc("@action: setup", "By Creation Date"));
0590     QAction* const sortByModDateAction            = d->imageSortAction->addAction(i18nc("@action: setup", "By Modification Date"));
0591     QAction* const sortByFileSizeAction           = d->imageSortAction->addAction(i18nc("@action: setup", "By File Size"));
0592     QAction* const sortByRatingAction             = d->imageSortAction->addAction(i18nc("@action: setup", "By Rating"));
0593     QAction* const sortByImageSizeAction          = d->imageSortAction->addAction(i18nc("@action: setup", "By Image Size"));
0594     QAction* const sortByAspectRatioAction        = d->imageSortAction->addAction(i18nc("@action: setup", "By Aspect Ratio"));
0595     QAction* const sortByFacesAction              = d->imageSortAction->addAction(i18nc("@action: setup", "By Face type"));
0596     QAction* const sortBySimilarityAction         = d->imageSortAction->addAction(i18nc("@action: setup", "By Similarity"));
0597     QAction* const sortByManualOrderAndNameAction = d->imageSortAction->addAction(i18nc("@action: setup", "By Manual and Name"));
0598     QAction* const sortByManualOrderAndDateAction = d->imageSortAction->addAction(i18nc("@action: setup", "By Manual and Date"));
0599 
0600     // activate the sort by similarity if the fuzzy search sidebar is active. Deactivate at start.
0601 
0602     sortBySimilarityAction->setEnabled(false);
0603     connect(d->view, SIGNAL(signalFuzzySidebarActive(bool)), sortBySimilarityAction, SLOT(setEnabled(bool)));
0604 
0605     connect(sortByNameAction, &QAction::triggered,
0606             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByFileName); });
0607 
0608     connect(sortByPathAction, &QAction::triggered,
0609             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByFilePath); });
0610 
0611     connect(sortByDateAction, &QAction::triggered,
0612             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByCreationDate); });
0613 
0614     connect(sortByModDateAction, &QAction::triggered,
0615             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByModificationDate); });
0616 
0617     connect(sortByFileSizeAction, &QAction::triggered,
0618             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByFileSize); });
0619 
0620     connect(sortByRatingAction, &QAction::triggered,
0621             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByRating); });
0622 
0623     connect(sortByImageSizeAction, &QAction::triggered,
0624             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByImageSize); });
0625 
0626     connect(sortByAspectRatioAction, &QAction::triggered,
0627             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByAspectRatio); });
0628 
0629     connect(sortByFacesAction, &QAction::triggered,
0630             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByFaces); });
0631 
0632     connect(sortBySimilarityAction, &QAction::triggered,
0633             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortBySimilarity); });
0634 
0635     connect(sortByManualOrderAndNameAction, &QAction::triggered,
0636             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByManualOrderAndName); });
0637 
0638     connect(sortByManualOrderAndDateAction, &QAction::triggered,
0639             this, [this]() { d->view->slotSortImages((int)ItemSortSettings::SortByManualOrderAndDate); });
0640 
0641     // -----------------------------------------------------------
0642 
0643     d->imageSortOrderAction             = new KSelectAction(i18nc("@action: setup", "Item Sort &Order"), this);
0644     d->imageSortOrderAction->setWhatsThis(i18nc("@info: setup", "Defines whether images are sorted in ascending or descending manner."));
0645     ac->addAction(QLatin1String("image_sort_order"), d->imageSortOrderAction);
0646 
0647     QAction* const sortAscendingAction  = d->imageSortOrderAction->addAction(QIcon::fromTheme(QLatin1String("view-sort-ascending")),
0648                                                                              i18nc("@action: setup", "Ascending"));
0649     QAction* const sortDescendingAction = d->imageSortOrderAction->addAction(QIcon::fromTheme(QLatin1String("view-sort-descending")),
0650                                                                              i18nc("@action: setup", "Descending"));
0651 
0652     connect(sortAscendingAction, &QAction::triggered,
0653             this, [this]() { d->view->slotSortImagesOrder((int)ItemSortSettings::AscendingOrder); });
0654 
0655     connect(sortDescendingAction, &QAction::triggered,
0656             this, [this]() { d->view->slotSortImagesOrder((int)ItemSortSettings::DescendingOrder); });
0657 
0658     // -----------------------------------------------------------
0659 
0660     d->imageSeparationAction              = new KSelectAction(i18nc("@action: setup", "Separate Items"), this);
0661     d->imageSeparationAction->setWhatsThis(i18nc("@info: setup", "The categories in which the images in the thumbnail view are displayed"));
0662     ac->addAction(QLatin1String("image_separation"), d->imageSeparationAction);
0663 
0664     // map to ItemSortSettings enum
0665 
0666     QAction* const noCategoriesAction     = d->imageSeparationAction->addAction(i18nc("@action: setup", "Flat List"));
0667     QAction* const separateByAlbumAction  = d->imageSeparationAction->addAction(i18nc("@action: setup", "By Album"));
0668     QAction* const separateByFormatAction = d->imageSeparationAction->addAction(i18nc("@action: setup", "By Format"));
0669     QAction* const separateByMonthAction  = d->imageSeparationAction->addAction(i18nc("@action: setup", "By Month"));
0670     QAction* const separateByFacesAction  = d->imageSeparationAction->addAction(i18nc("@action: setup", "By Faces"));
0671 
0672     connect(noCategoriesAction, &QAction::triggered,
0673             this, [this]() { d->view->slotSeparateImages((int)ItemSortSettings::OneCategory); });
0674 
0675     connect(separateByAlbumAction, &QAction::triggered,
0676             this, [this]() { d->view->slotSeparateImages((int)ItemSortSettings::CategoryByAlbum); });
0677 
0678     connect(separateByFormatAction, &QAction::triggered,
0679             this, [this]() { d->view->slotSeparateImages((int)ItemSortSettings::CategoryByFormat); });
0680 
0681     connect(separateByMonthAction, &QAction::triggered,
0682             this, [this]() { d->view->slotSeparateImages((int)ItemSortSettings::CategoryByMonth); });
0683 
0684     connect(separateByFacesAction, &QAction::triggered,
0685             this, [this]() { d->view->slotSeparateImages((int)ItemSortSettings::CategoryByFaces); });
0686 
0687     connect(d->view, &ItemIconView::signalSeparationModeChanged,
0688             this, [this](int category)
0689         {
0690             d->imageSeparationAction->blockSignals(true);
0691             d->imageSeparationAction->setCurrentItem(category-1);
0692             d->imageSeparationAction->blockSignals(false);
0693         }
0694     );
0695 
0696     // -----------------------------------------------------------------
0697 
0698     d->imageSeparationSortOrderAction        = new KSelectAction(i18nc("@action: setup", "Item Separation Order"), this);
0699     d->imageSeparationSortOrderAction->setWhatsThis(i18nc("@info: setup", "The sort order of the groups of separated items"));
0700     ac->addAction(QLatin1String("image_separation_sort_order"), d->imageSeparationSortOrderAction);
0701 
0702     QAction* const sortSeparationsAscending  = d->imageSeparationSortOrderAction->addAction(QIcon::fromTheme(QLatin1String("view-sort-ascending")),
0703                                                                                             i18nc("@action: setup", "Ascending"));
0704     QAction* const sortSeparationsDescending = d->imageSeparationSortOrderAction->addAction(QIcon::fromTheme(QLatin1String("view-sort-descending")),
0705                                                                                             i18nc("@action: setup", "Descending"));
0706 
0707     connect(sortSeparationsAscending, &QAction::triggered,
0708             this, [this]() { d->view->slotImageSeparationSortOrder((int)ItemSortSettings::AscendingOrder); });
0709 
0710     connect(sortSeparationsDescending, &QAction::triggered,
0711             this, [this]() { d->view->slotImageSeparationSortOrder((int)ItemSortSettings::DescendingOrder); });
0712 
0713     // -----------------------------------------------------------------
0714 
0715     setupImageTransformActions();
0716     setupExifOrientationActions();
0717 
0718     // -----------------------------------------------------------------
0719 
0720     d->selectAllAction = new QAction(i18nc("@action: setup", "Select All"), this);
0721     connect(d->selectAllAction, SIGNAL(triggered()), d->view, SLOT(slotSelectAll()));
0722     ac->addAction(QLatin1String("selectAll"), d->selectAllAction);
0723     ac->setDefaultShortcut(d->selectAllAction, Qt::CTRL | Qt::Key_A);
0724 
0725     // -----------------------------------------------------------------
0726 
0727     d->selectNoneAction = new QAction(i18nc("@action: setup", "Select None"), this);
0728     connect(d->selectNoneAction, SIGNAL(triggered()), d->view, SLOT(slotSelectNone()));
0729     ac->addAction(QLatin1String("selectNone"), d->selectNoneAction);
0730     ac->setDefaultShortcut(d->selectNoneAction, Qt::CTRL | Qt::SHIFT | Qt::Key_A);
0731 
0732     // -----------------------------------------------------------------
0733 
0734     d->selectInvertAction = new QAction(i18nc("@action: setup", "Invert Selection"), this);
0735     connect(d->selectInvertAction, SIGNAL(triggered()), d->view, SLOT(slotSelectInvert()));
0736     ac->addAction(QLatin1String("selectInvert"), d->selectInvertAction);
0737     ac->setDefaultShortcut(d->selectInvertAction, Qt::CTRL | Qt::Key_I);
0738 
0739     // -----------------------------------------------------------
0740 
0741     d->showBarAction = new QAction(QIcon::fromTheme(QLatin1String("view-choose")),
0742                                    i18nc("@action: setup", "Show Thumbbar"), this);
0743     d->showBarAction->setCheckable(true);
0744     connect(d->showBarAction, SIGNAL(triggered()), this, SLOT(slotToggleShowBar()));
0745     ac->addAction(QLatin1String("showthumbs"), d->showBarAction);
0746     ac->setDefaultShortcut(d->showBarAction, Qt::CTRL | Qt::Key_T);
0747 
0748     // Provides a menu entry that allows showing/hiding the toolbar(s)
0749 
0750     setStandardToolBarMenuEnabled(true);
0751 
0752     // Provides a menu entry that allows showing/hiding the statusbar
0753 
0754     createStandardStatusBarAction();
0755 
0756     // Standard 'Configure' menu actions
0757 
0758     createSettingsActions();
0759 
0760     // -----------------------------------------------------------
0761 
0762     d->zoomPlusAction = buildStdAction(StdZoomInAction, d->view, SLOT(slotZoomIn()), this);
0763     ac->addAction(QLatin1String("album_zoomin"), d->zoomPlusAction);
0764 
0765     // -----------------------------------------------------------
0766 
0767     d->zoomMinusAction = buildStdAction(StdZoomOutAction, d->view, SLOT(slotZoomOut()), this);
0768     ac->addAction(QLatin1String("album_zoomout"), d->zoomMinusAction);
0769 
0770     // -----------------------------------------------------------
0771 
0772     d->zoomTo100percents = new QAction(QIcon::fromTheme(QLatin1String("zoom-original")),
0773                                        i18nc("@action: setup", "Zoom to 100%"), this);
0774     connect(d->zoomTo100percents, SIGNAL(triggered()), d->view, SLOT(slotZoomTo100Percents()));
0775     ac->addAction(QLatin1String("album_zoomto100percents"), d->zoomTo100percents);
0776     ac->setDefaultShortcut(d->zoomTo100percents, Qt::CTRL | Qt::Key_Period);
0777 
0778     // -----------------------------------------------------------
0779 
0780     d->zoomFitToWindowAction = new QAction(QIcon::fromTheme(QLatin1String("zoom-fit-best")),
0781                                            i18nc("@action: setup", "Fit to &Window"), this);
0782     connect(d->zoomFitToWindowAction, SIGNAL(triggered()), d->view, SLOT(slotFitToWindow()));
0783     ac->addAction(QLatin1String("album_zoomfit2window"), d->zoomFitToWindowAction);
0784     ac->setDefaultShortcut(d->zoomFitToWindowAction, Qt::CTRL | Qt::ALT | Qt::Key_E);
0785 
0786     // -----------------------------------------------------------
0787 
0788     createFullScreenAction(QLatin1String("full_screen"));
0789     createSidebarActions();
0790 
0791     // -----------------------------------------------------------
0792 
0793     d->viewCMViewAction = new QAction(QIcon::fromTheme(QLatin1String("video-display")),
0794                                       i18nc("@action: setup", "Color-Managed View"), this);
0795     d->viewCMViewAction->setCheckable(true);
0796     connect(d->viewCMViewAction, SIGNAL(triggered()), this, SLOT(slotToggleColorManagedView()));
0797     ac->addAction(QLatin1String("color_managed_view"), d->viewCMViewAction);
0798     ac->setDefaultShortcut(d->viewCMViewAction, Qt::Key_F12);
0799 
0800     // -----------------------------------------------------------
0801 
0802     d->quitAction = buildStdAction(StdQuitAction, this, SLOT(slotExit()), this);
0803     ac->addAction(QLatin1String("app_exit"), d->quitAction);
0804 
0805     // -----------------------------------------------------------
0806 
0807     createHelpActions(QLatin1String("main_window"));
0808 
0809     // -----------------------------------------------------------
0810 
0811     QAction* const findAction = new QAction(QIcon::fromTheme(QLatin1String("edit-find")),
0812                                             i18nc("@action: setup", "Search..."), this);
0813     connect(findAction, SIGNAL(triggered()), d->view, SLOT(slotNewKeywordSearch()));
0814     ac->addAction(QLatin1String("search_quick"), findAction);
0815     ac->setDefaultShortcut(findAction, Qt::CTRL | Qt::Key_F);
0816 
0817     // -----------------------------------------------------------
0818 
0819     d->advSearchAction = new QAction(QIcon::fromTheme(QLatin1String("edit-find")),
0820                                      i18nc("@action: setup", "Advanced Search..."), this);
0821     connect(d->advSearchAction, SIGNAL(triggered()), d->view, SLOT(slotNewAdvancedSearch()));
0822     ac->addAction(QLatin1String("search_advanced"), d->advSearchAction);
0823     ac->setDefaultShortcut(d->advSearchAction, Qt::CTRL | Qt::ALT | Qt::Key_F);
0824 
0825     // -----------------------------------------------------------
0826 
0827     QAction* const duplicatesAction = new QAction(QIcon::fromTheme(QLatin1String("tools-wizard")),
0828                                                   i18nc("@action: setup", "Find Duplicates..."), this);
0829     connect(duplicatesAction, SIGNAL(triggered()), d->view, SLOT(slotNewDuplicatesSearch()));
0830     ac->addAction(QLatin1String("find_duplicates"), duplicatesAction);
0831     ac->setDefaultShortcut(duplicatesAction, Qt::CTRL | Qt::Key_D);
0832 
0833     // -----------------------------------------------------------
0834 
0835 #ifdef HAVE_MYSQLSUPPORT
0836 
0837     QAction* const databaseMigrationAction = new QAction(QIcon::fromTheme(QLatin1String("network-server-database")),
0838                                                          i18nc("@action: setup", "Database Migration..."), this);
0839     connect(databaseMigrationAction, SIGNAL(triggered()), this, SLOT(slotDatabaseMigration()));
0840     ac->addAction(QLatin1String("database_migration"), databaseMigrationAction);
0841 
0842 #endif
0843 
0844     // -----------------------------------------------------------
0845 
0846     d->maintenanceAction = new QAction(QIcon::fromTheme(QLatin1String("run-build-prune")),
0847                                        i18nc("@action: setup", "Maintenance..."), this);
0848     connect(d->maintenanceAction, SIGNAL(triggered()), this, SLOT(slotMaintenance()));
0849     ac->addAction(QLatin1String("maintenance"), d->maintenanceAction);
0850 
0851     // -----------------------------------------------------------
0852 
0853     d->scanNewItemsAction = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")),
0854                                         i18nc("@action: setup", "Scan for new Items"), this);
0855     connect(d->scanNewItemsAction, SIGNAL(triggered()), this, SLOT(slotScanNewItems()));
0856     ac->addAction(QLatin1String("scan_newitems"), d->scanNewItemsAction);
0857 
0858     // -----------------------------------------------------------
0859 
0860     QAction* const cameraAction = new QAction(i18nc("@action: setup", "Add Camera Manually..."), this);
0861     connect(cameraAction, SIGNAL(triggered()), this, SLOT(slotSetupCamera()));
0862     ac->addAction(QLatin1String("camera_add"), cameraAction);
0863 
0864     // -----------------------------------------------------------
0865 
0866     // Load Cameras -- do this before the createGUI so that the cameras
0867     // are plugged into the toolbar at startup
0868 
0869     if (d->splashScreen)
0870     {
0871         d->splashScreen->setMessage(i18nc("@info: setup", "Loading cameras..."));
0872     }
0873 
0874     loadCameras();
0875 
0876     // Load Themes
0877 
0878     populateThemes();
0879 
0880     createGUI(xmlFile());
0881 
0882     registerPluginsActions();
0883 
0884     cleanupActions();
0885 
0886     // NOTE: see bug #252130 and #283281 : we need to disable these actions when BQM is running.
0887     // These connections must be done after loading color theme else theme menu cannot be plugged to Settings menu,
0888 
0889     connect(QueueMgrWindow::queueManagerWindow(), SIGNAL(signalBqmIsBusy(bool)),
0890             d->bqmAction, SLOT(setDisabled(bool)));
0891 
0892     connect(QueueMgrWindow::queueManagerWindow(), SIGNAL(signalBqmIsBusy(bool)),
0893             d->imageAddCurrentQueueAction, SLOT(setDisabled(bool)));
0894 
0895     connect(QueueMgrWindow::queueManagerWindow(), SIGNAL(signalBqmIsBusy(bool)),
0896             d->imageAddNewQueueAction, SLOT(setDisabled(bool)));
0897 }
0898 
0899 void DigikamApp::setupAccelerators()
0900 {
0901     KActionCollection* const ac = actionCollection();
0902 
0903     // Action are added by <MainWindow> tag in ui.rc XML file
0904 
0905     QAction* const escapeAction = new QAction(i18nc("@action: setup", "Exit Preview Mode"), this);
0906     ac->addAction(QLatin1String("exit_preview_mode"), escapeAction);
0907     ac->setDefaultShortcut(escapeAction, Qt::Key_Escape);
0908     connect(escapeAction, SIGNAL(triggered()), this, SIGNAL(signalEscapePressed()));
0909 
0910     QAction* const nextImageAction = new QAction(i18nc("@action: setup", "Next Image"), this);
0911     nextImageAction->setIcon(QIcon::fromTheme(QLatin1String("go-next")));
0912     ac->addAction(QLatin1String("next_image"), nextImageAction);
0913     ac->setDefaultShortcut(nextImageAction, Qt::Key_Space);
0914     connect(nextImageAction, SIGNAL(triggered()), this, SIGNAL(signalNextItem()));
0915 
0916     QAction* const previousImageAction = new QAction(i18nc("@action: setup", "Previous Image"), this);
0917     previousImageAction->setIcon(QIcon::fromTheme(QLatin1String("go-previous")));
0918     ac->addAction(QLatin1String("previous_image"), previousImageAction);
0919     ac->setDefaultShortcuts(previousImageAction, QList<QKeySequence>() << Qt::Key_Backspace << (Qt::SHIFT | Qt::Key_Space));
0920     connect(previousImageAction, SIGNAL(triggered()), this, SIGNAL(signalPrevItem()));
0921 
0922     QAction* const firstImageAction = new QAction(i18nc("@action: setup", "First Image"), this);
0923     ac->addAction(QLatin1String("first_image"), firstImageAction);
0924     ac->setDefaultShortcut(firstImageAction, Qt::CTRL | Qt::Key_Home);
0925     connect(firstImageAction, SIGNAL(triggered()), this, SIGNAL(signalFirstItem()));
0926 
0927     QAction* const lastImageAction = new QAction(i18nc("@action: setup", "Last Image"), this);
0928     ac->addAction(QLatin1String("last_image"), lastImageAction);
0929     ac->setDefaultShortcut(lastImageAction, Qt::CTRL | Qt::Key_End);
0930     connect(lastImageAction, SIGNAL(triggered()), this, SIGNAL(signalLastItem()));
0931 
0932     d->cutItemsAction = new QAction(i18nc("@action: setup", "Cu&t"), this);
0933     d->cutItemsAction->setIcon(QIcon::fromTheme(QLatin1String("edit-cut")));
0934     d->cutItemsAction->setWhatsThis(i18nc("@action: setup", "Cut selection to clipboard"));
0935     ac->addAction(QLatin1String("cut_album_selection"), d->cutItemsAction);
0936 
0937     // NOTE: shift+del keyboard shortcut must not be assigned to Cut action
0938     // else the shortcut for Delete permanently collides with secondary shortcut of Cut
0939 
0940     ac->setDefaultShortcut(d->cutItemsAction, Qt::CTRL | Qt::Key_X);
0941     connect(d->cutItemsAction, SIGNAL(triggered()), this, SIGNAL(signalCutAlbumItemsSelection()));
0942 
0943     d->copyItemsAction = buildStdAction(StdCopyAction, this, SIGNAL(signalCopyAlbumItemsSelection()), this);
0944     ac->addAction(QLatin1String("copy_album_selection"), d->copyItemsAction);
0945 
0946     d->pasteItemsAction = buildStdAction(StdPasteAction, this, SIGNAL(signalPasteAlbumItemsSelection()), this);
0947     ac->addAction(QLatin1String("paste_album_selection"), d->pasteItemsAction);
0948 
0949     // Labels shortcuts must be registered here to be saved in XML GUI files if user customize it.
0950 
0951     d->tagsActionManager->registerLabelsActions(ac);
0952 
0953     QAction* const editTitles = new QAction(i18nc("@action: setup", "Edit Titles"), this);
0954     ac->addAction(QLatin1String("edit_titles"), editTitles);
0955     ac->setDefaultShortcut(editTitles, Qt::ALT | Qt::SHIFT | Qt::Key_T);
0956     connect(editTitles, SIGNAL(triggered()), d->view, SLOT(slotRightSideBarActivateTitles()));
0957 
0958     QAction* const editComments = new QAction(i18nc("@action: setup", "Edit Comments"), this);
0959     ac->addAction(QLatin1String("edit_comments"), editComments);
0960     ac->setDefaultShortcut(editComments, Qt::ALT | Qt::SHIFT | Qt::Key_C);
0961     connect(editComments, SIGNAL(triggered()), d->view, SLOT(slotRightSideBarActivateComments()));
0962 
0963     QAction* const assignedTags = new QAction(i18nc("@action: setup", "Show Assigned Tags"), this);
0964     ac->addAction(QLatin1String("assigned_tags"), assignedTags);
0965     ac->setDefaultShortcut(assignedTags, Qt::ALT | Qt::SHIFT | Qt::Key_A);
0966     connect(assignedTags, SIGNAL(triggered()), d->view, SLOT(slotRightSideBarActivateAssignedTags()));
0967 }
0968 
0969 void DigikamApp::setupExifOrientationActions()
0970 {
0971     KActionCollection* const ac       = actionCollection();
0972     d->imageExifOrientationActionMenu = new QMenu(i18nc("@action: setup", "Adjust Exif Orientation Tag"), this);
0973     ac->addAction(QLatin1String("image_set_exif_orientation"), d->imageExifOrientationActionMenu->menuAction());
0974 
0975     d->imageSetExifOrientation1Action = new QAction(i18nc("@action: normal exif orientation", "Normal"), this);
0976     d->imageSetExifOrientation1Action->setCheckable(true);
0977     d->imageSetExifOrientation2Action = new QAction(i18nc("@action: setup", "Flipped Horizontally"),               this);
0978     d->imageSetExifOrientation2Action->setCheckable(true);
0979     d->imageSetExifOrientation3Action = new QAction(i18nc("@action: setup", "Rotated Upside Down"),                this);
0980     d->imageSetExifOrientation3Action->setCheckable(true);
0981     d->imageSetExifOrientation4Action = new QAction(i18nc("@action: setup", "Flipped Vertically"),                 this);
0982     d->imageSetExifOrientation4Action->setCheckable(true);
0983     d->imageSetExifOrientation5Action = new QAction(i18nc("@action: setup", "Rotated Right / Horiz. Flipped"),     this);
0984     d->imageSetExifOrientation5Action->setCheckable(true);
0985     d->imageSetExifOrientation6Action = new QAction(i18nc("@action: setup", "Rotated Right"),                      this);
0986     d->imageSetExifOrientation6Action->setCheckable(true);
0987     d->imageSetExifOrientation7Action = new QAction(i18nc("@action: setup", "Rotated Right / Vert. Flipped"),      this);
0988     d->imageSetExifOrientation7Action->setCheckable(true);
0989     d->imageSetExifOrientation8Action = new QAction(i18nc("@action: setup", "Rotated Left"),                       this);
0990     d->imageSetExifOrientation8Action->setCheckable(true);
0991 
0992     d->exifOrientationActionGroup = new QActionGroup(d->imageExifOrientationActionMenu);
0993     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation1Action);
0994     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation2Action);
0995     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation3Action);
0996     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation4Action);
0997     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation5Action);
0998     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation6Action);
0999     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation7Action);
1000     d->exifOrientationActionGroup->addAction(d->imageSetExifOrientation8Action);
1001     d->imageSetExifOrientation1Action->setChecked(true);
1002 
1003     ac->addAction(QLatin1String("image_set_exif_orientation_normal"),                    d->imageSetExifOrientation1Action);
1004     ac->addAction(QLatin1String("image_set_exif_orientation_flipped_horizontal"),        d->imageSetExifOrientation2Action);
1005     ac->addAction(QLatin1String("image_set_exif_orientation_rotated_upside_down"),       d->imageSetExifOrientation3Action);
1006     ac->addAction(QLatin1String("image_set_exif_orientation_flipped_vertically"),        d->imageSetExifOrientation4Action);
1007     ac->addAction(QLatin1String("image_set_exif_orientation_rotated_right_hor_flipped"), d->imageSetExifOrientation5Action);
1008     ac->addAction(QLatin1String("image_set_exif_orientation_rotated_right"),             d->imageSetExifOrientation6Action);
1009     ac->addAction(QLatin1String("image_set_exif_orientation_rotated_right_ver_flipped"), d->imageSetExifOrientation7Action);
1010     ac->addAction(QLatin1String("image_set_exif_orientation_rotated_left"),              d->imageSetExifOrientation8Action);
1011 
1012     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation1Action);
1013     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation2Action);
1014     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation3Action);
1015     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation4Action);
1016     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation5Action);
1017     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation6Action);
1018     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation7Action);
1019     d->imageExifOrientationActionMenu->addAction(d->imageSetExifOrientation8Action);
1020 
1021     connect(d->imageSetExifOrientation1Action, &QAction::triggered,
1022             this, [this]() { d->view->slotImageExifOrientation(1); });
1023 
1024     connect(d->imageSetExifOrientation2Action, &QAction::triggered,
1025             this, [this]() { d->view->slotImageExifOrientation(2); });
1026 
1027     connect(d->imageSetExifOrientation3Action, &QAction::triggered,
1028             this, [this]() { d->view->slotImageExifOrientation(3); });
1029 
1030     connect(d->imageSetExifOrientation4Action, &QAction::triggered,
1031             this, [this]() { d->view->slotImageExifOrientation(4); });
1032 
1033     connect(d->imageSetExifOrientation5Action, &QAction::triggered,
1034             this, [this]() { d->view->slotImageExifOrientation(5); });
1035 
1036     connect(d->imageSetExifOrientation6Action, &QAction::triggered,
1037             this, [this]() { d->view->slotImageExifOrientation(6); });
1038 
1039     connect(d->imageSetExifOrientation7Action, &QAction::triggered,
1040             this, [this]() { d->view->slotImageExifOrientation(7); });
1041 
1042     connect(d->imageSetExifOrientation8Action, &QAction::triggered,
1043             this, [this]() { d->view->slotImageExifOrientation(8); });
1044 }
1045 
1046 void DigikamApp::setupImageTransformActions()
1047 {
1048     KActionCollection* const ac = actionCollection();
1049 
1050     d->imageRotateActionMenu = new QMenu(i18nc("@action: setup", "Rotate"), this);
1051     d->imageRotateActionMenu->setIcon(QIcon::fromTheme(QLatin1String("object-rotate-right")));
1052 
1053     QAction* const left = ac->addAction(QLatin1String("rotate_ccw"));
1054     left->setText(i18nc("@action: rotate image left", "Left"));
1055     ac->setDefaultShortcut(left, Qt::CTRL | Qt::SHIFT | Qt::Key_Left);
1056     connect(left, SIGNAL(triggered(bool)),
1057             this, SLOT(slotTransformAction()));
1058     d->imageRotateActionMenu->addAction(left);
1059 
1060     QAction* const right = ac->addAction(QLatin1String("rotate_cw"));
1061     right->setText(i18nc("@action: rotate image right", "Right"));
1062     ac->setDefaultShortcut(right, Qt::CTRL | Qt::SHIFT | Qt::Key_Right);
1063     connect(right, SIGNAL(triggered(bool)),
1064             this, SLOT(slotTransformAction()));
1065     d->imageRotateActionMenu->addAction(right);
1066 
1067     ac->addAction(QLatin1String("image_rotate"), d->imageRotateActionMenu->menuAction());
1068 
1069     // -----------------------------------------------------------------------------------
1070 
1071     d->imageFlipActionMenu = new QMenu(i18nc("@action: setup", "Flip"), this);
1072     d->imageFlipActionMenu->setIcon(QIcon::fromTheme(QLatin1String("flip-horizontal")));
1073 
1074     QAction* const hori = ac->addAction(QLatin1String("flip_horizontal"));
1075     hori->setText(i18nc("@action: setup", "Horizontally"));
1076     ac->setDefaultShortcut(hori, Qt::CTRL | Qt::Key_Asterisk);
1077     connect(hori, SIGNAL(triggered(bool)),
1078             this, SLOT(slotTransformAction()));
1079     d->imageFlipActionMenu->addAction(hori);
1080 
1081     QAction* const verti = ac->addAction(QLatin1String("flip_vertical"));
1082     verti->setText(i18nc("@action: setup", "Vertically"));
1083     ac->setDefaultShortcut(verti, Qt::CTRL | Qt::Key_Slash);
1084     connect(verti, SIGNAL(triggered(bool)),
1085             this, SLOT(slotTransformAction()));
1086     d->imageFlipActionMenu->addAction(verti);
1087 
1088     ac->addAction(QLatin1String("image_flip"), d->imageFlipActionMenu->menuAction());
1089 
1090     // -----------------------------------------------------------------------------------
1091 
1092     d->imageAutoExifActionMenu = new QAction(i18nc("@action: setup", "Auto Rotate/Flip Using Exif Information"), this);
1093     connect(d->imageAutoExifActionMenu, SIGNAL(triggered(bool)),
1094             this, SLOT(slotTransformAction()));
1095 
1096     ac->addAction(QLatin1String("image_transform_exif"), d->imageAutoExifActionMenu);
1097 }
1098 
1099 void DigikamApp::populateThemes()
1100 {
1101     if (d->splashScreen)
1102     {
1103         d->splashScreen->setMessage(i18nc("@info: setup", "Loading themes..."));
1104     }
1105 
1106     ThemeManager::instance()->setThemeMenuAction(new QMenu(i18nc("@action: setup", "&Themes"), this));
1107     ThemeManager::instance()->registerThemeActions(this);
1108     ThemeManager::instance()->setCurrentTheme(ApplicationSettings::instance()->getCurrentTheme());
1109 
1110     connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()),
1111             this, SLOT(slotThemeChanged()));
1112 }
1113 
1114 void DigikamApp::preloadWindows()
1115 {
1116     if (d->splashScreen)
1117     {
1118         d->splashScreen->setMessage(i18nc("@info: setup", "Loading tools..."));
1119     }
1120 
1121     ImageWindow::imageWindow();
1122     QueueMgrWindow::queueManagerWindow();
1123     LightTableWindow::lightTableWindow();
1124 
1125     d->tagsActionManager->registerTagsActionCollections();
1126 }
1127 
1128 void DigikamApp::initGui()
1129 {
1130     // Initialize Actions ---------------------------------------
1131 
1132     d->deleteAction->setEnabled(false);
1133     d->renameAction->setEnabled(false);
1134     d->propsEditAction->setEnabled(false);
1135     d->openInFileManagerAction->setEnabled(false);
1136 
1137     d->imageViewAction->setEnabled(false);
1138     d->imagePreviewAction->setEnabled(false);
1139     d->imageLightTableAction->setEnabled(false);
1140     d->imageAddLightTableAction->setEnabled(false);
1141     d->imageScanForFacesAction->setEnabled(false);
1142     d->imageRemoveAllFacesAction->setEnabled(false);
1143     d->imageFindSimilarAction->setEnabled(false);
1144     d->imageRenameAction->setEnabled(false);
1145     d->imageDeleteAction->setEnabled(false);
1146     d->imageExifOrientationActionMenu->setEnabled(false);
1147     d->openWithAction->setEnabled(false);
1148     d->imageAutoExifActionMenu->setEnabled(false);
1149 
1150     Q_FOREACH (DPluginAction* const ac, DPluginLoader::instance()->pluginsActions(DPluginAction::GenericMetadata, this))
1151     {
1152         ac->setEnabled(false);
1153     }
1154 
1155     d->albumSortAction->setCurrentItem((int)ApplicationSettings::instance()->getAlbumSortRole());
1156     d->imageSortAction->setCurrentItem((int)ApplicationSettings::instance()->getImageSortOrder());
1157     d->imageSortOrderAction->setCurrentItem((int)ApplicationSettings::instance()->getImageSorting());
1158     d->imageSeparationAction->setCurrentItem((int)ApplicationSettings::instance()->getImageSeparationMode()-1); // no action for enum 0
1159     d->imageSeparationSortOrderAction->setCurrentItem((int)ApplicationSettings::instance()->getImageSeparationSortOrder());
1160     d->allGroupsOpenAction->setChecked(ApplicationSettings::instance()->getAllGroupsOpen());
1161     d->recurseAlbumsAction->setChecked(ApplicationSettings::instance()->getRecurseAlbums());
1162     d->recurseTagsAction->setChecked(ApplicationSettings::instance()->getRecurseTags());
1163     d->showBarAction->setChecked(ApplicationSettings::instance()->getShowThumbbar());
1164     showMenuBarAction()->setChecked(!menuBar()->isHidden());                                                    // NOTE: workaround for bug #171080
1165 
1166     slotSwitchedToIconView();
1167 }
1168 
1169 } // namespace Digikam