File indexing completed on 2025-01-19 03:50:47
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2013-02-11 0007 * Description : Table view 0008 * 0009 * SPDX-FileCopyrightText: 2013 by Michael G. Hansen <mike at mghansen dot de> 0010 * SPDX-FileCopyrightText: 2017 by Simon Frei <freisim93 at gmail dot com> 0011 * SPDX-FileCopyrightText: 2017-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "tableview.h" 0018 0019 // Qt includes 0020 0021 #include <QContextMenuEvent> 0022 #include <QHeaderView> 0023 #include <QItemSelectionModel> 0024 #include <QVBoxLayout> 0025 #include <QMenu> 0026 #include <QAction> 0027 #include <QIcon> 0028 #include <QApplication> 0029 #include <QPointer> 0030 0031 // KDE includes 0032 0033 #include <kconfiggroup.h> 0034 #include <klocalizedstring.h> 0035 0036 // Local includes 0037 0038 #include "advancedrenamedialog.h" 0039 #include "advancedrenameprocessdialog.h" 0040 #include "contextmenuhelper.h" 0041 #include "digikam_debug.h" 0042 #include "fileactionmngr.h" 0043 #include "album.h" 0044 #include "tableview_columnfactory.h" 0045 #include "tableview_model.h" 0046 #include "tableview_selection_model_syncer.h" 0047 #include "tableview_shared.h" 0048 #include "tableview_treeview.h" 0049 0050 namespace Digikam 0051 { 0052 0053 class ItemAlbumModel; 0054 class ItemFilterModel; 0055 0056 class Q_DECL_HIDDEN TableView::Private 0057 { 0058 public: 0059 0060 explicit Private() 0061 : columnProfiles (), 0062 thumbnailSize (), 0063 imageViewUtilities(nullptr) 0064 { 0065 } 0066 0067 QList<TableViewColumnProfile> columnProfiles; 0068 ThumbnailSize thumbnailSize; 0069 ItemViewUtilities* imageViewUtilities; 0070 }; 0071 0072 TableView::TableView(QItemSelectionModel* const selectionModel, 0073 DCategorizedSortFilterProxyModel* const imageFilterModel, 0074 QWidget* const parent) 0075 : QWidget(parent), 0076 StateSavingObject(this), 0077 d (new Private()), 0078 s (new TableViewShared()) 0079 { 0080 s->isActive = false; 0081 s->tableView = this; 0082 s->thumbnailLoadThread = new ThumbnailLoadThread(this); 0083 s->imageFilterModel = dynamic_cast<ItemFilterModel*>(imageFilterModel); 0084 s->imageModel = dynamic_cast<ItemModel*>(imageFilterModel->sourceModel()); 0085 s->imageFilterSelectionModel = selectionModel; 0086 s->columnFactory = new TableViewColumnFactory(s.data(), this); 0087 0088 QVBoxLayout* const vbox1 = new QVBoxLayout(); 0089 s->tableViewModel = new TableViewModel(s.data(), this); 0090 s->tableViewSelectionModel = new QItemSelectionModel(s->tableViewModel); 0091 s->tableViewSelectionModelSyncer = new TableViewSelectionModelSyncer(s.data(), this); 0092 s->treeView = new TableViewTreeView(s.data(), this); 0093 s->treeView->installEventFilter(this); 0094 0095 d->imageViewUtilities = new ItemViewUtilities(this); 0096 0097 connect(s->treeView, SIGNAL(activated(QModelIndex)), 0098 this, SLOT(slotItemActivated(QModelIndex))); 0099 0100 connect(s->treeView, SIGNAL(signalZoomInStep()), 0101 this, SIGNAL(signalZoomInStep())); 0102 0103 connect(s->treeView, SIGNAL(signalZoomOutStep()), 0104 this, SIGNAL(signalZoomOutStep())); 0105 0106 connect(s->tableViewSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), 0107 this, SIGNAL(signalItemsChanged())); 0108 0109 connect(s->treeView, SIGNAL(collapsed(QModelIndex)), 0110 this, SIGNAL(signalItemsChanged())); 0111 0112 connect(s->treeView, SIGNAL(expanded(QModelIndex)), 0113 this, SIGNAL(signalItemsChanged())); 0114 0115 connect(s->tableViewModel, SIGNAL(rowsInserted(QModelIndex,int,int)), 0116 this, SIGNAL(signalItemsChanged())); 0117 0118 connect(s->tableViewModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), 0119 this, SIGNAL(signalItemsChanged())); 0120 0121 connect(s->tableViewModel, SIGNAL(layoutChanged()), 0122 this, SIGNAL(signalItemsChanged())); 0123 0124 connect(s->tableViewModel, SIGNAL(modelReset()), 0125 this, SIGNAL(signalItemsChanged())); 0126 0127 vbox1->addWidget(s->treeView); 0128 vbox1->setContentsMargins(QMargins()); 0129 0130 setLayout(vbox1); 0131 } 0132 0133 TableView::~TableView() 0134 { 0135 } 0136 0137 void TableView::doLoadState() 0138 { 0139 const KConfigGroup group = getConfigGroup(); 0140 0141 TableViewColumnProfile profile; 0142 const KConfigGroup groupCurrentProfile = group.group(QLatin1String("Current Profile")); 0143 profile.loadSettings(groupCurrentProfile); 0144 s->tableViewModel->loadColumnProfile(profile); 0145 0146 const TableViewModel::GroupingMode groupingMode = TableViewModel::GroupingMode(group.readEntry<int>("Grouping mode", 0147 int(TableViewModel::GroupingShowSubItems))); 0148 s->tableViewModel->setGroupingMode(groupingMode); 0149 0150 if (!profile.headerState.isEmpty()) 0151 { 0152 s->treeView->header()->restoreState(profile.headerState); 0153 } 0154 } 0155 0156 void TableView::doSaveState() 0157 { 0158 KConfigGroup group = getConfigGroup(); 0159 0160 TableViewColumnProfile profile = s->tableViewModel->getColumnProfile(); 0161 profile.headerState = s->treeView->header()->saveState(); 0162 KConfigGroup groupCurrentProfile = group.group(QLatin1String("Current Profile")); 0163 profile.saveSettings(groupCurrentProfile); 0164 group.writeEntry("Grouping mode", int(s->tableViewModel->groupingMode())); 0165 } 0166 0167 void TableView::slotItemActivated(const QModelIndex& tableViewIndex) 0168 { 0169 const ItemInfo info = s->tableViewModel->imageInfo(tableViewIndex); 0170 0171 if (info.isNull()) 0172 { 0173 return; 0174 } 0175 0176 Qt::KeyboardModifiers modifiers = qApp->queryKeyboardModifiers(); 0177 0178 if (modifiers == Qt::NoModifier) 0179 { 0180 int leftClickAction = ApplicationSettings::instance()->getItemLeftClickAction(); 0181 0182 if (leftClickAction == ApplicationSettings::ShowPreview) 0183 { 0184 Q_EMIT signalPreviewRequested(info); 0185 } 0186 else if (leftClickAction == ApplicationSettings::StartEditor) 0187 { 0188 d->imageViewUtilities->openInfos(info, allItemInfos(), currentAlbum()); 0189 } 0190 else if (leftClickAction == ApplicationSettings::ShowOnTable) 0191 { 0192 d->imageViewUtilities->insertToLightTable(allItemInfos(), info, false); 0193 } 0194 else 0195 { 0196 d->imageViewUtilities->openInfosWithDefaultApplication(QList<ItemInfo>() << info); 0197 } 0198 } 0199 else if (modifiers == Qt::AltModifier) 0200 { 0201 d->imageViewUtilities->openInfosWithDefaultApplication(QList<ItemInfo>() << info); 0202 } 0203 } 0204 0205 bool TableView::eventFilter(QObject* watched, QEvent* event) 0206 { 0207 // we are looking for context menu events for the table view 0208 0209 if ((watched == s->treeView) && (event->type() == QEvent::ContextMenu)) 0210 { 0211 QContextMenuEvent* const e = static_cast<QContextMenuEvent*>(event); 0212 e->accept(); 0213 0214 const QModelIndex contextMenuIndex = s->treeView->indexAt(e->pos()); 0215 0216 if (contextMenuIndex.isValid()) 0217 { 0218 Q_EMIT signalShowContextMenuOnInfo(e, 0219 s->tableViewModel->imageInfo(contextMenuIndex), 0220 getExtraGroupingActions()); 0221 } 0222 else 0223 { 0224 Q_EMIT signalShowContextMenu(e, getExtraGroupingActions()); 0225 } 0226 0227 // event has been filtered by us 0228 0229 return true; 0230 } 0231 0232 return QObject::eventFilter(watched, event); 0233 } 0234 0235 void TableView::setThumbnailSize(const ThumbnailSize& size) 0236 { 0237 d->thumbnailSize = size; 0238 const QList<TableViewColumn*> columnObjects = s->tableViewModel->getColumnObjects(); 0239 0240 Q_FOREACH (TableViewColumn* const iColumn, columnObjects) 0241 { 0242 iColumn->updateThumbnailSize(); 0243 } 0244 } 0245 0246 ThumbnailSize TableView::getThumbnailSize() const 0247 { 0248 return d->thumbnailSize; 0249 } 0250 0251 Album* TableView::currentAlbum() const 0252 { 0253 ItemAlbumModel* const albumModel = qobject_cast<ItemAlbumModel*>(s->imageModel); 0254 0255 if (!albumModel) 0256 { 0257 return nullptr; 0258 } 0259 0260 if (albumModel->currentAlbums().isEmpty()) 0261 { 0262 return nullptr; 0263 } 0264 0265 return albumModel->currentAlbums().constFirst(); 0266 } 0267 0268 void TableView::slotPaste() 0269 { 0270 DragDropViewImplementation* const dragDropViewImplementation = s->treeView; 0271 dragDropViewImplementation->paste(); 0272 } 0273 0274 ItemInfo TableView::currentInfo() const 0275 { 0276 return s->tableViewModel->imageInfo(s->tableViewSelectionModel->currentIndex()); 0277 } 0278 0279 ItemInfoList TableView::allItemInfos(bool grouping) const 0280 { 0281 if (grouping) 0282 { 0283 return s->treeView->resolveGrouping(ItemInfoList(s->tableViewModel->allItemInfo())); 0284 } 0285 0286 return ItemInfoList(s->tableViewModel->allItemInfo()); 0287 } 0288 0289 bool TableView::allNeedGroupResolving(const ApplicationSettings::OperationType type) const 0290 { 0291 return s->treeView->needGroupResolving(type, allItemInfos()); 0292 } 0293 0294 bool TableView::selectedNeedGroupResolving(const ApplicationSettings::OperationType type) const 0295 { 0296 return s->treeView->needGroupResolving(type, selectedItemInfos()); 0297 } 0298 0299 void TableView::slotDeleteSelected(const ItemViewUtilities::DeleteMode deleteMode) 0300 { 0301 const bool allGroupsOpen = ApplicationSettings::instance()->getAllGroupsOpen(); 0302 const ItemInfoList& infoList = selectedItemInfos(!allGroupsOpen); 0303 0304 /// @todo Update parameter naming for deleteImages 0305 0306 if (d->imageViewUtilities->deleteImages(infoList, deleteMode)) 0307 { 0308 slotAwayFromSelection(); 0309 } 0310 } 0311 0312 void TableView::slotDeleteSelectedWithoutConfirmation(const ItemViewUtilities::DeleteMode deleteMode) 0313 { 0314 const bool allGroupsOpen = ApplicationSettings::instance()->getAllGroupsOpen(); 0315 const ItemInfoList& infoList = selectedItemInfos(!allGroupsOpen); 0316 0317 d->imageViewUtilities->deleteImagesDirectly(infoList, deleteMode); 0318 slotAwayFromSelection(); 0319 } 0320 0321 QList<QAction*> TableView::getExtraGroupingActions() 0322 { 0323 QList<QAction*> actionList; 0324 0325 const TableViewModel::GroupingMode currentGroupingMode = s->tableViewModel->groupingMode(); 0326 0327 QAction* const actionHideGrouped = new QAction(i18n("Hide grouped items"), this); 0328 actionHideGrouped->setCheckable(true); 0329 actionHideGrouped->setChecked(currentGroupingMode == TableViewModel::GroupingHideGrouped); 0330 actionHideGrouped->setData(QVariant::fromValue<TableViewModel::GroupingMode>(TableViewModel::GroupingHideGrouped)); 0331 0332 connect(actionHideGrouped, SIGNAL(triggered(bool)), 0333 this, SLOT(slotGroupingModeActionTriggered())); 0334 0335 actionList << actionHideGrouped; 0336 0337 QAction* const actionIgnoreGrouping = new QAction(i18n("Ignore grouping"), this); 0338 actionIgnoreGrouping->setCheckable(true); 0339 actionIgnoreGrouping->setChecked(currentGroupingMode == TableViewModel::GroupingIgnoreGrouping); 0340 actionIgnoreGrouping->setData(QVariant::fromValue<TableViewModel::GroupingMode>(TableViewModel::GroupingIgnoreGrouping)); 0341 0342 connect(actionIgnoreGrouping, SIGNAL(triggered(bool)), 0343 this, SLOT(slotGroupingModeActionTriggered())); 0344 0345 actionList << actionIgnoreGrouping; 0346 0347 QAction* const actionShowSubItems = new QAction(i18n("Show grouping in tree"), this); 0348 actionShowSubItems->setCheckable(true); 0349 actionShowSubItems->setChecked(currentGroupingMode == TableViewModel::GroupingShowSubItems); 0350 actionShowSubItems->setData(QVariant::fromValue<TableViewModel::GroupingMode>(TableViewModel::GroupingShowSubItems)); 0351 0352 connect(actionShowSubItems, SIGNAL(triggered(bool)), 0353 this, SLOT(slotGroupingModeActionTriggered())); 0354 0355 actionList << actionShowSubItems; 0356 0357 return actionList; 0358 } 0359 0360 void TableView::slotGroupingModeActionTriggered() 0361 { 0362 const QAction* const senderAction = qobject_cast<QAction*>(sender()); 0363 0364 if (!senderAction) 0365 { 0366 return; 0367 } 0368 0369 const TableViewModel::GroupingMode newGroupingMode = senderAction->data().value<TableViewModel::GroupingMode>(); 0370 s->tableViewModel->setGroupingMode(newGroupingMode); 0371 } 0372 0373 int TableView::numberOfSelectedItems() const 0374 { 0375 return s->tableViewSelectionModel->selectedRows().count(); 0376 } 0377 0378 void TableView::slotGoToRow(const int rowNumber, const bool relativeMove) 0379 { 0380 int nextDeepRowNumber = rowNumber; 0381 0382 if (relativeMove) 0383 { 0384 const QModelIndex currentTableViewIndex = s->tableViewSelectionModel->currentIndex(); 0385 const int currentDeepRowNumber = s->tableViewModel->indexToDeepRowNumber(currentTableViewIndex); 0386 nextDeepRowNumber += currentDeepRowNumber; 0387 } 0388 0389 const QModelIndex nextIndex = s->tableViewModel->deepRowIndex(nextDeepRowNumber); 0390 0391 if (nextIndex.isValid()) 0392 { 0393 const QItemSelection rowSelection = s->tableViewSelectionModelSyncer->targetIndexToRowItemSelection(nextIndex); 0394 s->tableViewSelectionModel->select(rowSelection, QItemSelectionModel::ClearAndSelect); 0395 s->tableViewSelectionModel->setCurrentIndex(nextIndex, QItemSelectionModel::Select); 0396 } 0397 } 0398 0399 ItemInfo TableView::deepRowItemInfo(const int rowNumber, const bool relative) const 0400 { 0401 int targetRowNumber = rowNumber; 0402 0403 if (relative) 0404 { 0405 const QModelIndex& currentTableViewIndex = s->tableViewSelectionModel->currentIndex(); 0406 0407 if (!currentTableViewIndex.isValid()) 0408 { 0409 return ItemInfo(); 0410 } 0411 0412 const int currentDeepRowNumber = s->tableViewModel->indexToDeepRowNumber(currentTableViewIndex); 0413 targetRowNumber += currentDeepRowNumber; 0414 } 0415 0416 const QModelIndex targetIndex = s->tableViewModel->deepRowIndex(targetRowNumber); 0417 0418 return s->tableViewModel->imageInfo(targetIndex); 0419 } 0420 0421 ItemInfo TableView::nextInfo() const 0422 { 0423 const QModelIndex cIndex = s->tableViewSelectionModel->currentIndex(); 0424 const int currentDeepRowNumber = s->tableViewModel->indexToDeepRowNumber(cIndex); 0425 const int nextDeepRowNumber = currentDeepRowNumber + 1; 0426 0427 if (nextDeepRowNumber>=s->tableViewModel->deepRowCount()) 0428 { 0429 return ItemInfo(); 0430 } 0431 0432 const QModelIndex nextDeepRowIndex = s->tableViewModel->deepRowIndex(nextDeepRowNumber); 0433 0434 return s->tableViewModel->imageInfo(nextDeepRowIndex); 0435 } 0436 0437 ItemInfo TableView::previousInfo() const 0438 { 0439 const QModelIndex cIndex = s->tableViewSelectionModel->currentIndex(); 0440 const int currentDeepRowNumber = s->tableViewModel->indexToDeepRowNumber(cIndex); 0441 const int previousDeepRowNumber = currentDeepRowNumber - 1; 0442 0443 if (previousDeepRowNumber < 0) 0444 { 0445 return ItemInfo(); 0446 } 0447 0448 const QModelIndex previousDeepRowIndex = s->tableViewModel->deepRowIndex(previousDeepRowNumber); 0449 0450 return s->tableViewModel->imageInfo(previousDeepRowIndex); 0451 } 0452 0453 void TableView::slotSetCurrentUrlWhenAvailable(const QUrl& url) 0454 { 0455 Q_FOREACH (const ItemInfo& info, allItemInfos()) 0456 { 0457 if (info.fileUrl() == url) 0458 { // cppcheck-suppress useStlAlgorithm 0459 slotSetCurrentWhenAvailable(info.id()); 0460 break; 0461 } 0462 } 0463 } 0464 0465 void TableView::slotSetCurrentWhenAvailable(const qlonglong id) 0466 { 0467 const QModelIndex idx = s->tableViewModel->indexFromImageId(id, 0); 0468 0469 if (!idx.isValid()) 0470 { 0471 /// @todo Actually buffer this request until the model is fully populated 0472 0473 return; 0474 } 0475 0476 s->tableViewSelectionModel->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect); 0477 } 0478 0479 /** 0480 * @brief Unselects the current selection and changes the current item 0481 * 0482 * @todo This may not work correctly if grouped items are deleted, but are not selected 0483 */ 0484 void TableView::slotAwayFromSelection() 0485 { 0486 QModelIndexList selection = s->tableViewSelectionModel->selectedRows(0); 0487 0488 if (selection.isEmpty()) 0489 { 0490 return; 0491 } 0492 0493 const QModelIndex firstIndex = s->tableViewModel->deepRowIndex(0); 0494 const QModelIndex lastIndex = s->tableViewModel->deepRowIndex(-1); 0495 0496 if (selection.contains(firstIndex) && selection.contains(lastIndex)) 0497 { 0498 // both the first and the last index are selected, we have to 0499 // select an index inbetween 0500 0501 const int nextFreeDeepRow = s->tableViewModel->firstDeepRowNotInList(selection); 0502 0503 if (nextFreeDeepRow < 0) 0504 { 0505 s->tableViewSelectionModel->clearSelection(); 0506 s->tableViewSelectionModel->setCurrentIndex(QModelIndex(), QItemSelectionModel::ClearAndSelect); 0507 } 0508 else 0509 { 0510 const QModelIndex nextFreeIndex = s->tableViewModel->deepRowIndex(nextFreeDeepRow); 0511 s->tableViewSelectionModel->setCurrentIndex(nextFreeIndex, QItemSelectionModel::ClearAndSelect); 0512 const QItemSelection nextFreeIndexAsRow = s->tableViewSelectionModelSyncer->targetIndexToRowItemSelection(nextFreeIndex); 0513 s->tableViewSelectionModel->select(nextFreeIndexAsRow, QItemSelectionModel::ClearAndSelect); 0514 } 0515 } 0516 else if (selection.contains(lastIndex)) 0517 { 0518 const int firstSelectedRowNumber = s->tableViewModel->indexToDeepRowNumber(selection.first()); 0519 const QModelIndex newIndex = s->tableViewModel->deepRowIndex(firstSelectedRowNumber-1); 0520 s->tableViewSelectionModel->setCurrentIndex(newIndex, QItemSelectionModel::ClearAndSelect); 0521 const QItemSelection newIndexAsRow = s->tableViewSelectionModelSyncer->targetIndexToRowItemSelection(newIndex); 0522 s->tableViewSelectionModel->select(newIndexAsRow, QItemSelectionModel::ClearAndSelect); 0523 } 0524 else 0525 { 0526 const int lastSelectedRowNumber = s->tableViewModel->indexToDeepRowNumber(selection.last()); 0527 const QModelIndex newIndex = s->tableViewModel->deepRowIndex(lastSelectedRowNumber+1); 0528 s->tableViewSelectionModel->setCurrentIndex(newIndex, QItemSelectionModel::ClearAndSelect); 0529 const QItemSelection newIndexAsRow = s->tableViewSelectionModelSyncer->targetIndexToRowItemSelection(newIndex); 0530 s->tableViewSelectionModel->select(newIndexAsRow, QItemSelectionModel::ClearAndSelect); 0531 } 0532 } 0533 0534 void TableView::clearSelection() 0535 { 0536 s->tableViewSelectionModel->clearSelection(); 0537 } 0538 0539 void TableView::invertSelection() 0540 { 0541 const int deepRowCount = s->tableViewModel->deepRowCount(); 0542 QList<int> rowsToSelect; 0543 int lastSelectedRow = -1; 0544 0545 /// @todo Create a DeepRowIterator because there is a lot of overhead here 0546 0547 for (int i = 0 ; i < deepRowCount ; ++i) 0548 { 0549 const QModelIndex iIndex = s->tableViewModel->deepRowIndex(i); 0550 0551 if (s->tableViewSelectionModel->isSelected(iIndex)) 0552 { 0553 if ((i - 1) > lastSelectedRow) 0554 { 0555 for (int j = lastSelectedRow + 1 ; j < i ; ++j) 0556 { 0557 rowsToSelect << j; 0558 } 0559 } 0560 0561 lastSelectedRow = i; 0562 } 0563 } 0564 0565 if (lastSelectedRow + 1 < deepRowCount) 0566 { 0567 for (int j = lastSelectedRow + 1 ; j < deepRowCount ; ++j) 0568 { 0569 rowsToSelect << j; 0570 } 0571 } 0572 0573 s->tableViewSelectionModel->clearSelection(); 0574 0575 Q_FOREACH (const int i, rowsToSelect) 0576 { 0577 const QModelIndex iIndex = s->tableViewModel->deepRowIndex(i); 0578 const QItemSelection is = s->tableViewSelectionModelSyncer->targetIndexToRowItemSelection(iIndex); 0579 s->tableViewSelectionModel->select(is, QItemSelectionModel::Select); 0580 } 0581 } 0582 0583 void TableView::selectAll() 0584 { 0585 /// @todo This only selects expanded items. 0586 0587 s->treeView->selectAll(); 0588 } 0589 0590 void TableView::slotSetActive(const bool isActive) 0591 { 0592 if (s->isActive != isActive) 0593 { 0594 s->isActive = isActive; 0595 s->tableViewModel->slotSetActive(isActive); 0596 s->tableViewSelectionModelSyncer->slotSetActive(isActive); 0597 } 0598 } 0599 0600 ItemInfoList TableView::selectedItemInfos(bool grouping) const 0601 { 0602 ItemInfoList infos = ItemInfoList(s->tableViewModel->imageInfos(s->tableViewSelectionModel->selectedRows())); 0603 0604 if (grouping) 0605 { 0606 return s->treeView->resolveGrouping(infos); 0607 } 0608 0609 return infos; 0610 } 0611 0612 ItemInfoList TableView::selectedItemInfosCurrentFirst(bool grouping) const 0613 { 0614 QModelIndexList indexes = s->tableViewSelectionModel->selectedRows(); 0615 const QModelIndex current = s->tableViewModel->toCol0(s->tableViewSelectionModel->currentIndex()); 0616 0617 if (!indexes.isEmpty()) 0618 { 0619 if (indexes.first() != current) 0620 { 0621 if (indexes.removeOne(current)) 0622 { 0623 indexes.prepend(current); 0624 } 0625 } 0626 } 0627 0628 if (grouping) 0629 { 0630 return s->treeView->resolveGrouping(ItemInfoList(s->tableViewModel->imageInfos(indexes))); 0631 } 0632 0633 return ItemInfoList(s->tableViewModel->imageInfos(indexes)); 0634 } 0635 0636 void TableView::rename() 0637 { 0638 ItemInfoList infos = selectedItemInfos(); 0639 0640 if (s->treeView->needGroupResolving(ApplicationSettings::Rename, infos)) 0641 { 0642 infos = s->treeView->resolveGrouping(infos); 0643 } 0644 0645 QList<QUrl> urls = infos.toImageUrlList(); 0646 bool loop = false; 0647 NewNamesList newNamesList; 0648 0649 do 0650 { 0651 qCDebug(DIGIKAM_GENERAL_LOG) << "Selected URLs to rename: " << urls; 0652 0653 QPointer<AdvancedRenameDialog> dlg = new AdvancedRenameDialog(this); 0654 dlg->slotAddImages(urls); 0655 0656 if (dlg->exec() != QDialog::Accepted) 0657 { 0658 delete dlg; 0659 break; 0660 } 0661 0662 if (!loop) 0663 { 0664 slotAwayFromSelection(); 0665 loop = true; 0666 } 0667 0668 newNamesList = dlg->newNames(); 0669 delete dlg; 0670 0671 setFocus(); 0672 qApp->processEvents(); 0673 0674 if (!newNamesList.isEmpty()) 0675 { 0676 QPointer<AdvancedRenameProcessDialog> dlg2 = new AdvancedRenameProcessDialog(newNamesList, this); 0677 dlg2->exec(); 0678 0679 s->tableViewModel->scheduleResort(); 0680 urls = dlg2->failedUrls(); 0681 delete dlg2; 0682 } 0683 } 0684 while (!urls.isEmpty() && !newNamesList.isEmpty()); 0685 } 0686 0687 } // namespace Digikam 0688 0689 #include "moc_tableview.cpp"