File indexing completed on 2025-03-09 03:58:42
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2012-22-07 0007 * Description : Icon view for import tool items 0008 * 0009 * SPDX-FileCopyrightText: 2012 by Islam Wazery <wazery at ubuntu dot com> 0010 * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "importiconview_p.h" 0017 0018 // Qt includes 0019 0020 #include <QDesktopServices> 0021 #include <QPointer> 0022 #include <QAction> 0023 #include <QMenu> 0024 0025 // Local includes 0026 0027 #include "importoverlays.h" 0028 #include "importsettings.h" 0029 #include "camitemsortsettings.h" 0030 #include "fileactionmngr.h" 0031 #include "importdelegate.h" 0032 #include "advancedrenamedialog.h" 0033 #include "advancedrenameprocessdialog.h" 0034 #include "itemviewutilities.h" 0035 #include "importcontextmenu.h" 0036 #include "importdragdrop.h" 0037 0038 namespace Digikam 0039 { 0040 0041 ImportIconView::ImportIconView(QWidget* const parent) 0042 : ImportCategorizedView(parent), 0043 d(new Private(this)) 0044 { 0045 ImportThumbnailModel* const model = new ImportThumbnailModel(this); 0046 ImportFilterModel* const filterModel = new ImportFilterModel(this); 0047 0048 filterModel->setSourceImportModel(model); 0049 filterModel->sort(0); // an initial sorting is necessary 0050 0051 setModels(model, filterModel); 0052 0053 d->normalDelegate = new ImportNormalDelegate(this); 0054 0055 setItemDelegate(d->normalDelegate); 0056 setSpacing(10); 0057 0058 ImportSettings* const settings = ImportSettings::instance(); 0059 0060 // Virtual method: use Dynamic binding. 0061 this->setThumbnailSize(ThumbnailSize(settings->getDefaultIconSize())); 0062 0063 importItemModel()->setDragDropHandler(new ImportDragDropHandler(importItemModel())); 0064 setDragEnabled(true); 0065 setAcceptDrops(true); 0066 setDropIndicatorShown(false); 0067 0068 setToolTipEnabled(settings->showToolTipsIsValid()); 0069 0070 // selection overlay 0071 0072 addSelectionOverlay(d->normalDelegate); 0073 0074 /* TODO 0075 addSelectionOverlay(d->faceDelegate); 0076 */ 0077 // rotation overlays 0078 0079 d->rotateLeftOverlay = ImportRotateOverlay::left(this); 0080 d->rotateRightOverlay = ImportRotateOverlay::right(this); 0081 0082 addOverlay(new ImportDownloadOverlay(this)); 0083 addOverlay(new ImportLockOverlay(this)); 0084 addOverlay(new ImportCoordinatesOverlay(this)); 0085 0086 d->updateOverlays(); 0087 0088 // rating overlay 0089 0090 ImportRatingOverlay* const ratingOverlay = new ImportRatingOverlay(this); 0091 addOverlay(ratingOverlay); 0092 0093 /* TODO 0094 GroupIndicatorOverlay* groupOverlay = new GroupIndicatorOverlay(this); 0095 addOverlay(groupOverlay); 0096 */ 0097 connect(ratingOverlay, SIGNAL(ratingEdited(QList<QModelIndex>,int)), 0098 this, SLOT(assignRating(QList<QModelIndex>,int))); 0099 0100 /* TODO 0101 0102 connect(groupOverlay, SIGNAL(toggleGroupOpen(QModelIndex)), 0103 this, SLOT(groupIndicatorClicked(QModelIndex))); 0104 0105 connect(groupOverlay, SIGNAL(showButtonContextMenu(QModelIndex,QContextMenuEvent*)), 0106 this, SLOT(showGroupContextMenu(QModelIndex,QContextMenuEvent*))); 0107 0108 connect(importItemModel()->dragDropHandler(), SIGNAL(assignTags(QList<CamItemInfo>,QList<int>)), 0109 FileActionMngr::instance(), SLOT(assignTags(QList<CamItemInfo>,QList<int>))); 0110 0111 connect(importItemModel()->dragDropHandler(), SIGNAL(addToGroup(CamItemInfo,QList<CamItemInfo>)), 0112 FileActionMngr::instance(), SLOT(addToGroup(CamItemInfo,QList<CamItemInfo>))); 0113 */ 0114 // --- NOTE: use dynamic binding as slotSetupChanged() is a virtual method which can be re-implemented in derived classes. 0115 0116 connect(settings, &ImportSettings::setupChanged, 0117 this, &ImportIconView::slotSetupChanged); 0118 0119 this->slotSetupChanged(); 0120 } 0121 0122 ImportIconView::~ImportIconView() 0123 { 0124 delete d; 0125 } 0126 0127 ItemViewUtilities* ImportIconView::utilities() const 0128 { 0129 return d->utilities; 0130 } 0131 0132 void ImportIconView::setThumbnailSize(const ThumbnailSize& size) 0133 { 0134 ImportCategorizedView::setThumbnailSize(size); 0135 } 0136 0137 int ImportIconView::fitToWidthIcons() 0138 { 0139 return delegate()->calculatethumbSizeToFit(viewport()->size().width()); 0140 } 0141 0142 CamItemInfo ImportIconView::camItemInfo(const QString& folder, const QString& file) 0143 { 0144 QUrl url = QUrl::fromLocalFile(folder); 0145 url = url.adjusted(QUrl::StripTrailingSlash); 0146 url.setPath(url.path() + QLatin1Char('/') + file); 0147 QModelIndex indexForCamItemInfo = importFilterModel()->indexForPath(url.toLocalFile()); 0148 0149 if (indexForCamItemInfo.isValid()) 0150 { 0151 return importFilterModel()->camItemInfo(indexForCamItemInfo); 0152 } 0153 0154 return CamItemInfo(); 0155 } 0156 0157 CamItemInfo& ImportIconView::camItemInfoRef(const QString& folder, const QString& file) 0158 { 0159 QUrl url = QUrl::fromLocalFile(folder); 0160 url = url.adjusted(QUrl::StripTrailingSlash); 0161 url.setPath(url.path() + QLatin1Char('/') + file); 0162 QModelIndex indexForCamItemInfo = importFilterModel()->indexForPath(url.toLocalFile()); 0163 QModelIndex mappedIndex = importFilterModel()->mapToSource(indexForCamItemInfo); 0164 0165 return importItemModel()->camItemInfoRef(mappedIndex); 0166 } 0167 0168 void ImportIconView::slotSetupChanged() 0169 { 0170 setToolTipEnabled(ImportSettings::instance()->showToolTipsIsValid()); 0171 setFont(ImportSettings::instance()->getIconViewFont()); 0172 0173 d->updateOverlays(); 0174 0175 ImportCategorizedView::slotSetupChanged(); 0176 } 0177 0178 void ImportIconView::rename() 0179 { 0180 QList<QUrl> urls = selectedUrls(); 0181 NewNamesList newNamesList; 0182 0183 QPointer<AdvancedRenameDialog> dlg = new AdvancedRenameDialog(this); 0184 dlg->slotAddImages(urls); 0185 0186 if (dlg->exec() == QDialog::Accepted) 0187 { 0188 newNamesList = dlg->newNames(); 0189 } 0190 0191 delete dlg; 0192 0193 if (!newNamesList.isEmpty()) 0194 { 0195 QPointer<AdvancedRenameProcessDialog> dlg2 = new AdvancedRenameProcessDialog(newNamesList); 0196 dlg2->exec(); 0197 delete dlg2; 0198 } 0199 } 0200 0201 void ImportIconView::deleteSelected(bool /*permanently*/) 0202 { 0203 CamItemInfoList camItemInfoList = selectedCamItemInfos(); 0204 0205 // FIXME: This way of deletion may not working with camera items. 0206 /* 0207 if (d->utilities->deleteImages(camItemInfoList, permanently)) 0208 { 0209 awayFromSelection(); 0210 } 0211 */ 0212 } 0213 0214 void ImportIconView::deleteSelectedDirectly(bool /*permanently*/) 0215 { 0216 CamItemInfoList camItemInfoList = selectedCamItemInfos(); 0217 0218 // FIXME: This way of deletion may not working with camera items. 0219 /* 0220 d->utilities->deleteImagesDirectly(camItemInfoList, permanently); 0221 */ 0222 awayFromSelection(); 0223 } 0224 0225 void ImportIconView::createGroupFromSelection() 0226 { 0227 // TODO: Implement grouping in import tool. 0228 /* 0229 QList<CamItemInfo> selectedInfos = selectedCamItemInfosCurrentFirst(); 0230 CamItemInfo groupLeader = selectedInfos.takeFirst(); 0231 FileActionMngr::instance()->addToGroup(groupLeader, selectedInfos); 0232 */ 0233 } 0234 0235 void ImportIconView::createGroupByTimeFromSelection() 0236 { 0237 // TODO: Implement grouping in import tool. 0238 /* 0239 QList<CamItemInfo> selectedInfos = selectedCamItemInfosCurrentFirst(); 0240 0241 while (selectedInfos.size() > 0) 0242 { 0243 QList<CamItemInfo> group; 0244 CamItemInfo groupLeader = selectedInfos.takeFirst(); 0245 QDateTime dateTime = groupLeader.dateTime(); 0246 0247 while (selectedInfos.size() > 0 && abs(dateTime.secsTo(selectedInfos.first().dateTime())) < 2) 0248 { 0249 group.push_back(selectedInfos.takeFirst()); 0250 } 0251 0252 FileActionMngr::instance()->addToGroup(groupLeader, group); 0253 } 0254 */ 0255 } 0256 0257 void ImportIconView::ungroupSelected() 0258 { 0259 // TODO: Implement grouping in import tool. 0260 /* 0261 FileActionMngr::instance()->ungroup(selectedCamItemInfos()); 0262 */ 0263 } 0264 0265 void ImportIconView::removeSelectedFromGroup() 0266 { 0267 // TODO: Implement grouping in import tool. 0268 /* 0269 FileActionMngr::instance()->removeFromGroup(selectedCamItemInfos()); 0270 */ 0271 } 0272 0273 void ImportIconView::slotRotateLeft(const QList<QModelIndex>& /*indexes*/) 0274 { 0275 /* 0276 QList<ItemInfo> imageInfos; 0277 0278 Q_FOREACH (const QModelIndex& index, indexes) 0279 { 0280 ItemInfo imageInfo(importFilterModel()->camItemInfo(index).url()); 0281 imageInfos << imageInfo; 0282 } 0283 0284 FileActionMngr::instance()->transform(imageInfos, MetaEngineRotation::Rotate270); 0285 */ 0286 } 0287 0288 void ImportIconView::slotRotateRight(const QList<QModelIndex>& /*indexes*/) 0289 { 0290 /* 0291 QList<ItemInfo> imageInfos; 0292 0293 Q_FOREACH (const QModelIndex& index, indexes) 0294 { 0295 ItemInfo imageInfo(importFilterModel()->camItemInfo(index).url()); 0296 imageInfos << imageInfo; 0297 } 0298 0299 FileActionMngr::instance()->transform(imageInfos, MetaEngineRotation::Rotate90); 0300 */ 0301 } 0302 0303 void ImportIconView::activated(const CamItemInfo& info, Qt::KeyboardModifiers) 0304 { 0305 if (info.isNull()) 0306 { 0307 return; 0308 } 0309 0310 int leftClickAction = ImportSettings::instance()->getItemLeftClickAction(); 0311 0312 if (leftClickAction == ImportSettings::ShowPreview) 0313 { 0314 Q_EMIT previewRequested(info, false); 0315 } 0316 else if (leftClickAction == ImportSettings::StartEditor) 0317 { 0318 /* TODO 0319 openFile(info); 0320 */ 0321 } 0322 else 0323 { 0324 QDesktopServices::openUrl(info.url()); 0325 } 0326 } 0327 0328 void ImportIconView::showContextMenuOnInfo(QContextMenuEvent* event, const CamItemInfo& /*info*/) 0329 { 0330 QList<CamItemInfo> selectedInfos = selectedCamItemInfosCurrentFirst(); 0331 QList<qlonglong> selectedItemIDs; 0332 0333 Q_FOREACH (const CamItemInfo& info, selectedInfos) 0334 { 0335 selectedItemIDs << info.id; 0336 } 0337 0338 // -------------------------------------------------------- 0339 0340 QMenu popmenu(this); 0341 ImportContextMenuHelper cmhelper(&popmenu); 0342 0343 cmhelper.addAction(QLatin1String("importui_fullscreen")); 0344 cmhelper.addAction(QLatin1String("options_show_menubar")); 0345 cmhelper.addAction(QLatin1String("import_zoomfit2window")); 0346 cmhelper.addSeparator(); 0347 0348 // -------------------------------------------------------- 0349 0350 cmhelper.addAction(QLatin1String("importui_imagedownload")); 0351 cmhelper.addAction(QLatin1String("importui_imagemarkasdownloaded")); 0352 cmhelper.addAction(QLatin1String("importui_imagelock")); 0353 cmhelper.addAction(QLatin1String("importui_delete")); 0354 cmhelper.addSeparator(); 0355 cmhelper.addAction(QLatin1String("importui_item_view")); 0356 cmhelper.addServicesMenu(selectedUrls()); 0357 0358 /* TODO 0359 cmhelper.addRotateMenu(selectedItemIDs); 0360 */ 0361 0362 cmhelper.addSeparator(); 0363 0364 // -------------------------------------------------------- 0365 0366 cmhelper.addAction(QLatin1String("importui_selectall")); 0367 cmhelper.addAction(QLatin1String("importui_selectnone")); 0368 cmhelper.addAction(QLatin1String("importui_selectinvert")); 0369 cmhelper.addSeparator(); 0370 0371 // -------------------------------------------------------- 0372 /* 0373 cmhelper.addAssignTagsMenu(selectedItemIDs); 0374 cmhelper.addRemoveTagsMenu(selectedItemIDs); 0375 cmhelper.addSeparator(); 0376 */ 0377 // -------------------------------------------------------- 0378 0379 cmhelper.addLabelsAction(); 0380 /* 0381 if (!d->faceMode) 0382 { 0383 cmhelper.addGroupMenu(selectedItemIDs); 0384 } 0385 0386 // special action handling -------------------------------- 0387 0388 connect(&cmhelper, SIGNAL(signalAssignTag(int)), 0389 this, SLOT(assignTagToSelected(int))); 0390 0391 TODO: Implement tag view for import tool. 0392 0393 connect(&cmhelper, SIGNAL(signalPopupTagsView()), 0394 this, SIGNAL(signalPopupTagsView())); 0395 0396 connect(&cmhelper, SIGNAL(signalRemoveTag(int)), 0397 this, SLOT(removeTagFromSelected(int))); 0398 0399 connect(&cmhelper, SIGNAL(signalGotoTag(int)), 0400 this, SIGNAL(gotoTagAndImageRequested(int))); 0401 */ 0402 connect(&cmhelper, SIGNAL(signalAssignPickLabel(int)), 0403 this, SLOT(assignPickLabelToSelected(int))); 0404 0405 connect(&cmhelper, SIGNAL(signalAssignColorLabel(int)), 0406 this, SLOT(assignColorLabelToSelected(int))); 0407 0408 connect(&cmhelper, SIGNAL(signalAssignRating(int)), 0409 this, SLOT(assignRatingToSelected(int))); 0410 /* 0411 connect(&cmhelper, SIGNAL(signalAddToExistingQueue(int)), 0412 this, SLOT(insertSelectedToExistingQueue(int))); 0413 0414 connect(&cmhelper, SIGNAL(signalCreateGroup()), 0415 this, SLOT(createGroupFromSelection())); 0416 0417 connect(&cmhelper, SIGNAL(signalUngroup()), 0418 this, SLOT(ungroupSelected())); 0419 0420 connect(&cmhelper, SIGNAL(signalRemoveFromGroup()), 0421 this, SLOT(removeSelectedFromGroup())); 0422 */ 0423 // -------------------------------------------------------- 0424 0425 cmhelper.exec(event->globalPos()); 0426 } 0427 0428 void ImportIconView::showContextMenu(QContextMenuEvent* event) 0429 { 0430 QMenu popmenu(this); 0431 ImportContextMenuHelper cmhelper(&popmenu); 0432 0433 cmhelper.addAction(QLatin1String("importui_fullscreen")); 0434 cmhelper.addAction(QLatin1String("options_show_menubar")); 0435 cmhelper.addSeparator(); 0436 cmhelper.addAction(QLatin1String("importui_close")); 0437 0438 // -------------------------------------------------------- 0439 0440 cmhelper.exec(event->globalPos()); 0441 } 0442 0443 void ImportIconView::assignTagToSelected(int tagID) 0444 { 0445 CamItemInfoList infos = selectedCamItemInfos(); 0446 0447 Q_FOREACH (const CamItemInfo& info, infos) 0448 { 0449 importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).tagIds.append(tagID); 0450 } 0451 } 0452 0453 void ImportIconView::removeTagFromSelected(int tagID) 0454 { 0455 CamItemInfoList infos = selectedCamItemInfos(); 0456 0457 Q_FOREACH (const CamItemInfo& info, infos) 0458 { 0459 importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).tagIds.removeAll(tagID); 0460 } 0461 } 0462 0463 void ImportIconView::assignPickLabel(const QModelIndex& index, int pickId) 0464 { 0465 importItemModel()->camItemInfoRef(index).pickLabel = pickId; 0466 } 0467 0468 void ImportIconView::assignPickLabelToSelected(int pickId) 0469 { 0470 CamItemInfoList infos = selectedCamItemInfos(); 0471 0472 Q_FOREACH (const CamItemInfo& info, infos) 0473 { 0474 importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).pickLabel = pickId; 0475 } 0476 } 0477 0478 void ImportIconView::assignColorLabel(const QModelIndex& index, int colorId) 0479 { 0480 importItemModel()->camItemInfoRef(index).colorLabel = colorId; 0481 } 0482 0483 void ImportIconView::assignColorLabelToSelected(int colorId) 0484 { 0485 CamItemInfoList infos = selectedCamItemInfos(); 0486 0487 Q_FOREACH (const CamItemInfo& info, infos) 0488 { 0489 importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).colorLabel = colorId; 0490 } 0491 } 0492 0493 void ImportIconView::assignRating(const QList<QModelIndex>& indexes, int rating) 0494 { 0495 Q_FOREACH (const QModelIndex& index, indexes) 0496 { 0497 if (index.isValid()) 0498 { 0499 importItemModel()->camItemInfoRef(index).rating = rating; 0500 } 0501 } 0502 } 0503 0504 void ImportIconView::assignRatingToSelected(int rating) 0505 { 0506 CamItemInfoList infos = selectedCamItemInfos(); 0507 0508 Q_FOREACH (const CamItemInfo& info, infos) 0509 { 0510 importItemModel()->camItemInfoRef(importItemModel()->indexForCamItemInfo(info)).rating = rating; 0511 } 0512 } 0513 0514 } // namespace Digikam 0515 0516 #include "moc_importiconview.cpp"