Warning, file /utilities/kfind/src/kfindtreeview.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 kfindtreeview.cpp 0003 SPDX-FileCopyrightText: 2009 Dario Andres Rodriguez <andresbajotierra@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 0007 */ 0008 0009 #include "kfindtreeview.h" 0010 #include "kfinddlg.h" 0011 0012 #include <QApplication> 0013 #include <QClipboard> 0014 #include <QFileDialog> 0015 #include <QFileInfo> 0016 #include <QHeaderView> 0017 #include <QMenu> 0018 #include <QMimeData> 0019 #include <QScrollBar> 0020 #include <QTextCodec> 0021 #include <QTextStream> 0022 0023 #include <KActionCollection> 0024 #include <KFileItemActions> 0025 #include <KFileItemListProperties> 0026 #include <KJobWidgets> 0027 #include <KLocalizedString> 0028 #include <KMessageBox> 0029 #include <KPropertiesDialog> 0030 0031 #include <KIO/CopyJob> 0032 #include <KIO/DeleteJob> 0033 #include <kio_version.h> 0034 #include <KIO/JobUiDelegateFactory> 0035 #include <KIO/JobUiDelegate> 0036 #include <KIO/OpenFileManagerWindowJob> 0037 #include <KIO/OpenUrlJob> 0038 #include <KIO/DeleteOrTrashJob> 0039 0040 // Permission strings 0041 #include <ki18n_version.h> 0042 #include <KLazyLocalizedString> 0043 0044 const KLazyLocalizedString perm[4] = { 0045 kli18n("Read-write"), 0046 kli18n("Read-only"), 0047 kli18n("Write-only"), 0048 kli18n("Inaccessible") 0049 }; 0050 #define RW 0 0051 #define RO 1 0052 #define WO 2 0053 #define NA 3 0054 0055 //BEGIN KFindItemModel 0056 0057 KFindItemModel::KFindItemModel(KFindTreeView *parentView) 0058 : QAbstractTableModel(parentView) 0059 { 0060 m_view = parentView; 0061 } 0062 0063 QVariant KFindItemModel::headerData(int section, Qt::Orientation orientation, int role) const 0064 { 0065 if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { 0066 switch (section) { 0067 case 0: 0068 return i18nc("file name column", "Name"); 0069 case 1: 0070 return i18nc("name of the containing folder", "In Subfolder"); 0071 case 2: 0072 return i18nc("file size column", "Size"); 0073 case 3: 0074 return i18nc("modified date column", "Modified"); 0075 case 4: 0076 return i18nc("file permissions column", "Permissions"); 0077 case 5: 0078 return i18nc("first matching line of the query string in this file", "First Matching Line"); 0079 default: 0080 return QVariant(); 0081 } 0082 } 0083 return QVariant(); 0084 } 0085 0086 void KFindItemModel::insertFileItems(const QList<QPair<KFileItem, QString>> &pairs) 0087 { 0088 if (!pairs.isEmpty()) { 0089 beginInsertRows(QModelIndex(), m_itemList.size(), m_itemList.size()+pairs.size()-1); 0090 0091 for (const auto &[item, dir] : pairs) { 0092 const QString subDir = m_view->reducedDir(item.url().adjusted(QUrl::RemoveFilename).path()); 0093 m_itemList.append(KFindItem(item, subDir, dir)); 0094 } 0095 0096 endInsertRows(); 0097 } 0098 } 0099 0100 int KFindItemModel::rowCount(const QModelIndex &parent) const 0101 { 0102 if (!parent.isValid()) { 0103 return m_itemList.count(); //Return itemcount for toplevel 0104 } else { 0105 return 0; 0106 } 0107 } 0108 0109 KFindItem KFindItemModel::itemAtIndex(const QModelIndex &index) const 0110 { 0111 if (index.isValid() && m_itemList.size() >= index.row()) { 0112 return m_itemList.at(index.row()); 0113 } 0114 0115 return KFindItem(); 0116 } 0117 0118 QList<KFindItem> KFindItemModel::getItemList() const 0119 { 0120 return m_itemList; 0121 } 0122 0123 QVariant KFindItemModel::data(const QModelIndex &index, int role) const 0124 { 0125 if (!index.isValid()) { 0126 return QVariant(); 0127 } 0128 0129 if (index.column() > 6 || index.row() >= m_itemList.count()) { 0130 return QVariant(); 0131 } 0132 0133 switch (role) { 0134 case Qt::DisplayRole: 0135 case Qt::DecorationRole: 0136 case Qt::UserRole: 0137 return m_itemList.at(index.row()).data(index.column(), role); 0138 default: 0139 return QVariant(); 0140 } 0141 return QVariant(); 0142 } 0143 0144 void KFindItemModel::removeItem(const QUrl &url) 0145 { 0146 const int itemCount = m_itemList.size(); 0147 for (int i = 0; i < itemCount; i++) { 0148 KFindItem item = m_itemList.at(i); 0149 if (item.getFileItem().url() == url) { 0150 beginRemoveRows(QModelIndex(), i, i); 0151 m_itemList.removeAt(i); 0152 endRemoveRows(); 0153 return; 0154 } 0155 } 0156 } 0157 0158 bool KFindItemModel::isInserted(const QUrl &url) 0159 { 0160 const int itemCount = m_itemList.size(); 0161 for (int i = 0; i < itemCount; i++) { 0162 KFindItem item = m_itemList.at(i); 0163 if (item.getFileItem().url() == url) { 0164 return true; 0165 } 0166 } 0167 return false; 0168 } 0169 0170 void KFindItemModel::clear() 0171 { 0172 if (!m_itemList.isEmpty()) { 0173 beginRemoveRows(QModelIndex(), 0, m_itemList.size()); 0174 m_itemList.clear(); 0175 endRemoveRows(); 0176 } 0177 } 0178 0179 Qt::DropActions KFindItemModel::supportedDropActions() const 0180 { 0181 return Qt::CopyAction | Qt::MoveAction; 0182 } 0183 0184 Qt::ItemFlags KFindItemModel::flags(const QModelIndex &index) const 0185 { 0186 const Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; 0187 if (index.isValid()) { 0188 return Qt::ItemIsDragEnabled | defaultFlags; 0189 } 0190 return defaultFlags; 0191 } 0192 0193 QMimeData *KFindItemModel::mimeData(const QModelIndexList &indexes) const 0194 { 0195 QList<QUrl> uris; 0196 0197 for (const QModelIndex &index : indexes) { 0198 if (index.isValid()) { 0199 if (index.column() == 0) { //Only use the first column item 0200 uris.append(m_itemList.at(index.row()).getFileItem().url()); 0201 } 0202 } 0203 } 0204 0205 if (uris.isEmpty()) { 0206 return nullptr; 0207 } 0208 0209 QMimeData *mimeData = new QMimeData(); 0210 mimeData->setUrls(uris); 0211 0212 return mimeData; 0213 } 0214 0215 int KFindItemModel::columnCount(const QModelIndex &parent) const 0216 { 0217 Q_UNUSED(parent); 0218 return 6; 0219 } 0220 0221 //END KFindItemModel 0222 0223 //BEGIN KFindItem 0224 0225 KFindItem::KFindItem(const KFileItem &_fileItem, const QString &subDir, const QString &matchingLine) 0226 { 0227 m_fileItem = _fileItem; 0228 m_subDir = subDir; 0229 m_matchingLine = matchingLine; 0230 0231 //TODO more caching ? 0232 if (!m_fileItem.isNull() && m_fileItem.isLocalFile()) { 0233 QFileInfo fileInfo(m_fileItem.url().toLocalFile()); 0234 0235 int perm_index; 0236 if (fileInfo.isReadable()) { 0237 perm_index = fileInfo.isWritable() ? RW : RO; 0238 } else { 0239 perm_index = fileInfo.isWritable() ? WO : NA; 0240 } 0241 m_permission = KLocalizedString(perm[perm_index]).toString(); 0242 0243 m_icon = QIcon::fromTheme(m_fileItem.iconName()); 0244 } 0245 } 0246 0247 QVariant KFindItem::data(int column, int role) const 0248 { 0249 if (m_fileItem.isNull()) { 0250 return QVariant(); 0251 } 0252 0253 if (role == Qt::DecorationRole) { 0254 if (column == 0) { 0255 return m_icon; 0256 } else { 0257 return QVariant(); 0258 } 0259 } 0260 0261 if (role == Qt::DisplayRole) { 0262 switch (column) { 0263 case 0: 0264 return m_fileItem.url().fileName(); 0265 case 1: 0266 return m_subDir; 0267 case 2: 0268 return KIO::convertSize(m_fileItem.size()); 0269 case 3: 0270 return m_fileItem.timeString(KFileItem::ModificationTime); 0271 case 4: 0272 return m_permission; 0273 case 5: 0274 return m_matchingLine; 0275 default: 0276 return QVariant(); 0277 } 0278 } 0279 0280 if (role == Qt::UserRole) { 0281 switch (column) { 0282 case 2: 0283 return m_fileItem.size(); 0284 case 3: 0285 return m_fileItem.time(KFileItem::ModificationTime).toSecsSinceEpoch(); 0286 default: 0287 return QVariant(); 0288 } 0289 } 0290 0291 return QVariant(); 0292 } 0293 0294 KFileItem KFindItem::getFileItem() const 0295 { 0296 return m_fileItem; 0297 } 0298 0299 bool KFindItem::isValid() const 0300 { 0301 return !m_fileItem.isNull(); 0302 } 0303 0304 //END KFindItem 0305 0306 //BEGIN KFindSortFilterProxyModel 0307 0308 bool KFindSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const 0309 { 0310 //Order by UserData size in bytes or unix date 0311 if (left.column() == 2 || left.column() == 3) { 0312 qulonglong leftData = sourceModel()->data(left, Qt::UserRole).toULongLong(); 0313 qulonglong rightData = sourceModel()->data(right, Qt::UserRole).toULongLong(); 0314 return leftData < rightData; 0315 } 0316 // Default sorting rules for string values 0317 else { 0318 return QSortFilterProxyModel::lessThan(left, right); 0319 } 0320 } 0321 0322 //END KFindSortFilterProxyModel 0323 0324 //BEGIN KFindTreeView 0325 0326 KFindTreeView::KFindTreeView(QWidget *parent, KfindDlg *findDialog) 0327 : QTreeView(parent) 0328 , m_model(new KFindItemModel(this)) 0329 , m_proxyModel(new KFindSortFilterProxyModel(this)) 0330 , m_kfindDialog(findDialog) 0331 { 0332 m_proxyModel->setSourceModel(m_model); 0333 setModel(m_proxyModel); 0334 0335 //Configure QTreeView 0336 setRootIsDecorated(false); 0337 setSelectionMode(QAbstractItemView::ExtendedSelection); 0338 setSortingEnabled(true); 0339 setDragEnabled(true); 0340 setContextMenuPolicy(Qt::CustomContextMenu); 0341 0342 connect(this, &KFindTreeView::customContextMenuRequested, this, &KFindTreeView::contextMenuRequested); 0343 0344 //Mouse single/double click settings 0345 reconfigureMouseSettings(); 0346 0347 // TODO: this is a workaround until Qt-issue 176832 has been fixed (from Dolphin) 0348 connect(this, &KFindTreeView::pressed, this, &KFindTreeView::updateMouseButtons); 0349 0350 //Generate popup menu actions 0351 m_actionCollection = new KActionCollection(this); 0352 m_actionCollection->addAssociatedWidget(this); 0353 0354 QAction *open = KStandardAction::open(this, SLOT(slotExecuteSelected()), this); 0355 m_actionCollection->addAction(QStringLiteral("file_open"), open); 0356 0357 QAction *copy = KStandardAction::copy(this, SLOT(copySelection()), this); 0358 m_actionCollection->addAction(QStringLiteral("edit_copy"), copy); 0359 0360 QAction *copyPathAction = m_actionCollection->addAction(QStringLiteral("copy_location")); 0361 copyPathAction->setText(i18nc("@action:incontextmenu", "Copy Location")); 0362 copyPathAction->setWhatsThis(i18nc("@info:whatsthis copy_location", "This will copy the path of the first selected item into the clipboard.")); 0363 copyPathAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy-path"))); 0364 m_actionCollection->setDefaultShortcuts(copyPathAction, {Qt::CTRL | Qt::ALT | Qt::Key_C}); 0365 connect(copyPathAction, &QAction::triggered, this, &KFindTreeView::copySelectionPath); 0366 0367 QAction *openFolder = new QAction(QIcon::fromTheme(QStringLiteral("window-new")), i18n("&Open containing folder(s)"), this); 0368 connect(openFolder, &QAction::triggered, this, &KFindTreeView::openContainingFolder); 0369 m_actionCollection->addAction(QStringLiteral("openfolder"), openFolder); 0370 0371 QAction *del = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("&Delete"), this); 0372 connect(del, &QAction::triggered, this, &KFindTreeView::deleteSelectedFiles); 0373 m_actionCollection->setDefaultShortcut(del, Qt::SHIFT | Qt::Key_Delete); 0374 0375 QAction *trash = new QAction(QIcon::fromTheme(QStringLiteral("user-trash")), i18n("&Move to Trash"), this); 0376 connect(trash, &QAction::triggered, this, &KFindTreeView::moveToTrashSelectedFiles); 0377 m_actionCollection->setDefaultShortcut(trash, Qt::Key_Delete); 0378 m_actionCollection->addAction(QStringLiteral("trash"), trash); 0379 0380 header()->setStretchLastSection(true); 0381 0382 sortByColumn(0, Qt::AscendingOrder); 0383 } 0384 0385 KFindTreeView::~KFindTreeView() 0386 { 0387 delete m_model; 0388 delete m_proxyModel; 0389 delete m_actionCollection; 0390 } 0391 0392 void KFindTreeView::resizeToContents() 0393 { 0394 resizeColumnToContents(0); 0395 resizeColumnToContents(1); 0396 resizeColumnToContents(2); 0397 resizeColumnToContents(3); 0398 } 0399 0400 QString KFindTreeView::reducedDir(const QString &fullDir) 0401 { 0402 QString relDir = m_baseDir.relativeFilePath(fullDir); 0403 if (!relDir.startsWith(QLatin1String(".."))) { 0404 return relDir; 0405 } 0406 return fullDir; 0407 } 0408 0409 int KFindTreeView::itemCount() const 0410 { 0411 return m_model->rowCount(); 0412 } 0413 0414 void KFindTreeView::beginSearch(const QUrl &baseUrl) 0415 { 0416 m_baseDir = QDir(baseUrl.toLocalFile()); 0417 m_model->clear(); 0418 } 0419 0420 void KFindTreeView::endSearch() 0421 { 0422 resizeToContents(); 0423 } 0424 0425 QList<QPersistentModelIndex> KFindTreeView::selectedVisibleIndexes() { 0426 QModelIndexList selected = selectedIndexes(); 0427 if (selected.empty()) { 0428 return QList<QPersistentModelIndex>(); 0429 } 0430 QModelIndex index = indexAt(QPoint(0, 0)); 0431 QModelIndex bottomIndex = indexAt(viewport()->rect().bottomLeft()); 0432 QList<QPersistentModelIndex> result; 0433 while (index.isValid()) { 0434 if (selected.contains(index)) { 0435 result.append(QPersistentModelIndex(index)); 0436 } 0437 if (index == bottomIndex) { 0438 break; 0439 } 0440 index = indexBelow(index); 0441 } 0442 return result; 0443 } 0444 0445 void KFindTreeView::insertItems(const QList< QPair<KFileItem, QString> > &pairs) 0446 { 0447 auto hScroll = horizontalScrollBar()->value(); 0448 QPersistentModelIndex topIndex(indexAt(rect().topLeft())); 0449 QList<QPersistentModelIndex> selectedVisible = selectedVisibleIndexes(); 0450 0451 m_model->insertFileItems(pairs); 0452 0453 if (topIndex.isValid()) { 0454 if (verticalScrollBar()->value() > 0) { 0455 scrollTo(topIndex, QAbstractItemView::PositionAtTop); 0456 } 0457 } 0458 if (!selectedVisible.empty()) { 0459 scrollTo(selectedVisible.last()); 0460 } 0461 horizontalScrollBar()->setValue(hScroll); 0462 } 0463 0464 void KFindTreeView::removeItem(const QUrl &url) 0465 { 0466 QList<QUrl> list = selectedUrls(); 0467 if (list.contains(url)) { 0468 //Close menu 0469 delete m_contextMenu; 0470 m_contextMenu = nullptr; 0471 } 0472 m_model->removeItem(url); 0473 } 0474 0475 bool KFindTreeView::isInserted(const QUrl &url) const 0476 { 0477 return m_model->isInserted(url); 0478 } 0479 0480 // copy to clipboard 0481 void KFindTreeView::copySelection() 0482 { 0483 QMimeData *mime = m_model->mimeData(m_proxyModel->mapSelectionToSource(selectionModel()->selection()).indexes()); 0484 if (mime) { 0485 QClipboard *cb = qApp->clipboard(); 0486 cb->setMimeData(mime); 0487 } 0488 } 0489 0490 void KFindTreeView::copySelectionPath() 0491 { 0492 const auto selectedIndexes = m_proxyModel->mapSelectionToSource(selectionModel()->selection()).indexes(); 0493 if (selectedIndexes.isEmpty()) { 0494 return; 0495 } 0496 0497 const auto item = m_model->itemAtIndex(selectedIndexes.at(0)).getFileItem(); 0498 0499 QString path = item.localPath(); 0500 if (path.isEmpty()) { 0501 path = item.url().toDisplayString(); 0502 } 0503 0504 QClipboard *clipboard = QApplication::clipboard(); 0505 if (!clipboard) { 0506 return; 0507 } 0508 clipboard->setText(path); 0509 } 0510 0511 void KFindTreeView::saveResults() 0512 { 0513 QFileDialog dialog; 0514 dialog.setAcceptMode(QFileDialog::AcceptSave); 0515 dialog.setWindowTitle(i18nc("@title:window", "Save Results As")); 0516 dialog.setMimeTypeFilters({ 0517 QStringLiteral("text/html"), 0518 QStringLiteral("text/plain") 0519 }); 0520 0521 if (!dialog.exec()) { 0522 return; 0523 } 0524 0525 if (dialog.selectedUrls().isEmpty()) { 0526 return; 0527 } 0528 0529 const QUrl u = dialog.selectedUrls().constFirst(); 0530 if (!u.isValid() || !u.isLocalFile()) { 0531 return; 0532 } 0533 0534 QString filename = u.toLocalFile(); 0535 0536 QFile file(filename); 0537 0538 if (!file.open(QIODevice::WriteOnly)) { 0539 KMessageBox::error(parentWidget(), 0540 i18n("Unable to save results.")); 0541 } else { 0542 QTextStream stream(&file); 0543 stream.setEncoding(QStringConverter::System); 0544 0545 const QList<KFindItem> itemList = m_model->getItemList(); 0546 if (dialog.selectedMimeTypeFilter() == QLatin1String("text/html")) { 0547 stream << QString::fromLatin1("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" 0548 "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\">\n" 0549 "<head>\n" 0550 "<title>%2</title></head>\n" 0551 "<meta charset=\"%1\">\n" 0552 "<body>\n<h1>%2</h1>\n" 0553 "<dl>\n") 0554 .arg(QString::fromLatin1(QTextCodec::codecForLocale()->name()), i18n("KFind Results File")); 0555 0556 for (const KFindItem &item : itemList) { 0557 const KFileItem fileItem = item.getFileItem(); 0558 stream << QStringLiteral("<dt><a href=\"%1\">%2</a></dt>\n").arg( 0559 fileItem.url().url(), fileItem.url().toDisplayString()); 0560 } 0561 stream << QStringLiteral("</dl>\n</body>\n</html>\n"); 0562 } else { 0563 for (const KFindItem &item : itemList) { 0564 stream << item.getFileItem().url().url() << Qt::endl; 0565 } 0566 } 0567 0568 file.close(); 0569 m_kfindDialog->setStatusMsg(i18nc("%1=filename", "Results were saved to: %1", filename)); 0570 } 0571 } 0572 0573 void KFindTreeView::openContainingFolder() 0574 { 0575 KIO::highlightInFileManager(selectedUrls()); 0576 } 0577 0578 void KFindTreeView::slotExecuteSelected() 0579 { 0580 const QModelIndexList selected = m_proxyModel->mapSelectionToSource(selectionModel()->selection()).indexes(); 0581 if (selected.isEmpty()) { 0582 return; 0583 } 0584 0585 //TODO if >X add a warn ? 0586 for (const QModelIndex &index : selected) { 0587 if (index.column() == 0) { 0588 KFindItem item = m_model->itemAtIndex(index); 0589 if (item.isValid()) { 0590 auto *job = new KIO::OpenUrlJob(item.getFileItem().targetUrl()); 0591 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0592 job->start(); 0593 } 0594 } 0595 } 0596 } 0597 0598 void KFindTreeView::slotExecute(const QModelIndex &index) 0599 { 0600 if ((m_mouseButtons & Qt::LeftButton) && QApplication::keyboardModifiers() == Qt::NoModifier) { 0601 if (!index.isValid()) { 0602 return; 0603 } 0604 0605 QModelIndex realIndex = m_proxyModel->mapToSource(index); 0606 if (!realIndex.isValid()) { 0607 return; 0608 } 0609 0610 const KFindItem item = m_model->itemAtIndex(realIndex); 0611 if (item.isValid()) { 0612 auto *job = new KIO::OpenUrlJob(item.getFileItem().targetUrl()); 0613 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0614 job->start(); 0615 } 0616 } 0617 } 0618 0619 void KFindTreeView::contextMenuRequested(const QPoint &p) 0620 { 0621 KFileItemList fileList; 0622 0623 const QModelIndexList selected = m_proxyModel->mapSelectionToSource(selectionModel()->selection()).indexes(); 0624 if (selected.isEmpty()) { 0625 return; 0626 } 0627 0628 for (const QModelIndex &index : selected) { 0629 if (index.column() == 0) { 0630 const KFindItem item = m_model->itemAtIndex(index); 0631 if (item.isValid()) { 0632 fileList.append(item.getFileItem()); 0633 } 0634 } 0635 } 0636 0637 delete m_contextMenu; 0638 m_contextMenu = new QMenu(this); 0639 m_contextMenu->addAction(m_actionCollection->action(QStringLiteral("file_open"))); 0640 m_contextMenu->addAction(m_actionCollection->action(QStringLiteral("openfolder"))); 0641 m_contextMenu->addAction(m_actionCollection->action(QStringLiteral("edit_copy"))); 0642 0643 QAction *copyLocationAction = m_actionCollection->action(QStringLiteral("copy_location")); 0644 // It's not worth it to track the selection and update the action live. 0645 copyLocationAction->setEnabled(fileList.count() == 1); 0646 m_contextMenu->addAction(copyLocationAction); 0647 0648 //m_contextMenu->addAction(m_actionCollection->action(QLatin1String("del"))); 0649 m_contextMenu->addAction(m_actionCollection->action(QStringLiteral("trash"))); 0650 m_contextMenu->addSeparator(); 0651 0652 // Open With... 0653 KFileItemActions menuActions; 0654 KFileItemListProperties fileProperties(fileList); 0655 menuActions.setItemListProperties(fileProperties); 0656 menuActions.insertOpenWithActionsTo(nullptr, m_contextMenu, QStringList()); 0657 // 'Actions' submenu 0658 menuActions.addActionsTo(m_contextMenu); 0659 0660 m_contextMenu->addSeparator(); 0661 0662 // Properties 0663 if (KPropertiesDialog::canDisplay(fileList)) { 0664 QAction *act = new QAction(m_contextMenu); 0665 act->setText(i18n("&Properties")); 0666 QObject::connect(act, &QAction::triggered, [this, fileList]() { 0667 KPropertiesDialog::showDialog(fileList, this, false /*non modal*/); 0668 }); 0669 m_contextMenu->addAction(act); 0670 } 0671 0672 m_contextMenu->exec(this->mapToGlobal(p)); 0673 } 0674 0675 QList<QUrl> KFindTreeView::selectedUrls() const 0676 { 0677 QList<QUrl> uris; 0678 0679 const QModelIndexList indexes = m_proxyModel->mapSelectionToSource(selectionModel()->selection()).indexes(); 0680 for (const QModelIndex &index : indexes) { 0681 if (index.column() == 0 && index.isValid()) { 0682 KFindItem item = m_model->itemAtIndex(index); 0683 if (item.isValid()) { 0684 uris.append(item.getFileItem().url()); 0685 } 0686 } 0687 } 0688 0689 return uris; 0690 } 0691 0692 void KFindTreeView::deleteSelectedFiles() 0693 { 0694 QList<QUrl> uris = selectedUrls(); 0695 if (uris.isEmpty()) { 0696 return; 0697 } 0698 0699 using Iface = KIO::AskUserActionInterface; 0700 auto *trashJob = new KIO::DeleteOrTrashJob(uris, Iface::Delete, Iface::ForceConfirmation, this); 0701 trashJob->start(); 0702 } 0703 0704 void KFindTreeView::moveToTrashSelectedFiles() 0705 { 0706 QList<QUrl> uris = selectedUrls(); 0707 if (uris.isEmpty()) { 0708 return; 0709 } 0710 0711 using Iface = KIO::AskUserActionInterface; 0712 auto *trashJob = new KIO::DeleteOrTrashJob(uris, Iface::Trash, Iface::ForceConfirmation, this); 0713 trashJob->start(); 0714 } 0715 0716 void KFindTreeView::reconfigureMouseSettings() 0717 { 0718 disconnect(this, &KFindTreeView::clicked, this, &KFindTreeView::slotExecute); 0719 disconnect(this, &KFindTreeView::doubleClicked, this, &KFindTreeView::slotExecute); 0720 0721 if (m_kfindDialog->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) { 0722 connect(this, &KFindTreeView::clicked, this, &KFindTreeView::slotExecute); 0723 } else { 0724 connect(this, &KFindTreeView::doubleClicked, this, &KFindTreeView::slotExecute); 0725 } 0726 } 0727 0728 void KFindTreeView::updateMouseButtons() 0729 { 0730 m_mouseButtons = QApplication::mouseButtons(); 0731 } 0732 0733 void KFindTreeView::dragMoveEvent(QDragMoveEvent *e) 0734 { 0735 e->accept(); 0736 } 0737 0738 //END KFindTreeView 0739 0740 #include "moc_kfindtreeview.cpp"