File indexing completed on 2024-05-05 17:57:23
0001 /* 0002 SPDX-FileCopyrightText: 2001 Shie Erlich <krusader@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2001 Rafi Yanai <krusader@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "krsearchdialog.h" 0010 0011 // QtCore 0012 #include <QMimeData> 0013 #include <QRegExp> 0014 // QtGui 0015 #include <QClipboard> 0016 #include <QCloseEvent> 0017 #include <QCursor> 0018 #include <QDrag> 0019 #include <QKeyEvent> 0020 #include <QResizeEvent> 0021 // QtWidgets 0022 #include <QApplication> 0023 #include <QGridLayout> 0024 #include <QHBoxLayout> 0025 #include <QInputDialog> 0026 #include <QMenu> 0027 0028 #include <KConfigCore/KConfig> 0029 #include <KConfigWidgets/KStandardAction> 0030 #include <KI18n/KLocalizedString> 0031 #include <KWidgetsAddons/KMessageBox> 0032 0033 #include "../Dialogs/krdialogs.h" 0034 #include "../Dialogs/krspecialwidgets.h" 0035 #include "../Dialogs/krsqueezedtextlabel.h" 0036 #include "../FileSystem/fileitem.h" 0037 #include "../FileSystem/krquery.h" 0038 #include "../FileSystem/virtualfilesystem.h" 0039 #include "../Filter/filtertabs.h" 0040 #include "../Filter/generalfilter.h" 0041 #include "../KViewer/krviewer.h" 0042 #include "../Panel/PanelView/krview.h" 0043 #include "../Panel/PanelView/krviewfactory.h" 0044 #include "../Panel/PanelView/krviewitem.h" 0045 #include "../Panel/krpanel.h" 0046 #include "../Panel/krsearchbar.h" 0047 #include "../Panel/panelfunc.h" 0048 #include "../defaults.h" 0049 #include "../filelisticon.h" 0050 #include "../kractions.h" 0051 #include "../krglobal.h" 0052 #include "../krservices.h" 0053 #include "../krslots.h" 0054 #include "../krusaderview.h" 0055 #include "../panelmanager.h" 0056 #include "krsearchmod.h" 0057 0058 #define RESULTVIEW_TYPE 0 0059 0060 class SearchResultContainer : public DirListerInterface 0061 { 0062 public: 0063 explicit SearchResultContainer(QObject *parent) 0064 : DirListerInterface(parent) 0065 { 0066 } 0067 ~SearchResultContainer() override 0068 { 0069 clear(); 0070 } 0071 0072 QList<FileItem *> fileItems() const override 0073 { 0074 return _fileItems; 0075 } 0076 unsigned long numFileItems() const override 0077 { 0078 return _fileItems.count(); 0079 } 0080 bool isRoot() const override 0081 { 0082 return true; 0083 } 0084 0085 void clear() 0086 { 0087 emit cleared(); 0088 foreach (FileItem *fileitem, _fileItems) 0089 delete fileitem; 0090 _fileItems.clear(); 0091 _foundText.clear(); 0092 } 0093 0094 void addItem(const FileItem &file, const QString &foundText) 0095 { 0096 const QString path = file.getUrl().toDisplayString(QUrl::PreferLocalFile); 0097 FileItem *fileitem = FileItem::createCopy(file, path); 0098 _fileItems << fileitem; 0099 if (!foundText.isEmpty()) 0100 _foundText[fileitem] = foundText; 0101 emit addedFileItem(fileitem); 0102 } 0103 0104 QString foundText(const FileItem *fileitem) 0105 { 0106 return _foundText[fileitem]; 0107 } 0108 0109 private: 0110 QList<FileItem *> _fileItems; 0111 QHash<const FileItem *, QString> _foundText; 0112 }; 0113 0114 KrSearchDialog *KrSearchDialog::SearchDialog = nullptr; 0115 0116 QString KrSearchDialog::lastSearchText = QString('*'); 0117 int KrSearchDialog::lastSearchType = 0; 0118 bool KrSearchDialog::lastSearchForCase = false; 0119 bool KrSearchDialog::lastContainsWholeWord = false; 0120 bool KrSearchDialog::lastContainsWithCase = false; 0121 bool KrSearchDialog::lastSearchInSubDirs = true; 0122 bool KrSearchDialog::lastSearchInArchives = false; 0123 bool KrSearchDialog::lastFollowSymLinks = false; 0124 bool KrSearchDialog::lastContainsRegExp = false; 0125 0126 // class starts here ///////////////////////////////////////// 0127 KrSearchDialog::KrSearchDialog(const QString &profile, QWidget *parent) 0128 : QDialog(parent) 0129 , query(nullptr) 0130 , searcher(nullptr) 0131 , isBusy(false) 0132 , closed(false) 0133 { 0134 KConfigGroup group(krConfig, "Search"); 0135 0136 setWindowTitle(i18n("Krusader::Search")); 0137 setWindowIcon(Icon("system-search")); 0138 0139 auto *searchBaseLayout = new QGridLayout(this); 0140 searchBaseLayout->setSpacing(6); 0141 searchBaseLayout->setContentsMargins(11, 11, 11, 11); 0142 0143 // creating the dialog buttons ( Search, Stop, Close ) 0144 0145 auto *buttonsLayout = new QHBoxLayout(); 0146 buttonsLayout->setSpacing(6); 0147 buttonsLayout->setContentsMargins(0, 0, 0, 0); 0148 0149 profileManager = new ProfileManager("SearcherProfile", this); 0150 buttonsLayout->addWidget(profileManager); 0151 0152 searchTextToClipboard = new QCheckBox(this); 0153 searchTextToClipboard->setText(i18n("Query to clipboard")); 0154 searchTextToClipboard->setToolTip(i18n("Place search text to clipboard when a found file is opened.")); 0155 searchTextToClipboard->setCheckState(static_cast<Qt::CheckState>(group.readEntry("QueryToClipboard", 0))); 0156 connect(searchTextToClipboard, &QCheckBox::stateChanged, this, [=](int state) { 0157 KConfigGroup group(krConfig, "Search"); 0158 group.writeEntry("QueryToClipboard", state); 0159 }); 0160 buttonsLayout->addWidget(searchTextToClipboard); 0161 0162 auto *spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0163 buttonsLayout->addItem(spacer); 0164 0165 mainSearchBtn = new QPushButton(this); 0166 mainSearchBtn->setText(i18n("Search")); 0167 mainSearchBtn->setIcon(Icon("edit-find")); 0168 mainSearchBtn->setDefault(true); 0169 buttonsLayout->addWidget(mainSearchBtn); 0170 0171 mainStopBtn = new QPushButton(this); 0172 mainStopBtn->setEnabled(false); 0173 mainStopBtn->setText(i18n("Stop")); 0174 mainStopBtn->setIcon(Icon("process-stop")); 0175 buttonsLayout->addWidget(mainStopBtn); 0176 0177 mainCloseBtn = new QPushButton(this); 0178 mainCloseBtn->setText(i18n("Close")); 0179 mainCloseBtn->setIcon(Icon("dialog-close")); 0180 buttonsLayout->addWidget(mainCloseBtn); 0181 0182 searchBaseLayout->addLayout(buttonsLayout, 1, 0); 0183 0184 // creating the searcher tabs 0185 0186 searcherTabs = new QTabWidget(this); 0187 0188 filterTabs = FilterTabs::addTo(searcherTabs, FilterTabs::Default); 0189 generalFilter = dynamic_cast<GeneralFilter *>(filterTabs->get("GeneralFilter")); 0190 0191 // creating the result tab 0192 0193 QWidget *resultTab = new QWidget(searcherTabs); 0194 auto *resultLayout = new QGridLayout(resultTab); 0195 resultLayout->setSpacing(6); 0196 resultLayout->setContentsMargins(6, 6, 6, 6); 0197 0198 // actions 0199 viewAction = new QAction(Icon("document-edit-preview"), i18n("View File"), this); 0200 viewAction->setShortcut(Qt::Key_F3); 0201 connect(viewAction, &QAction::triggered, this, &KrSearchDialog::viewCurrent); 0202 addAction(viewAction); 0203 0204 editAction = new QAction(Icon("document-edit-sign"), i18n("Edit File"), this); 0205 editAction->setShortcut(Qt::Key_F4); 0206 connect(editAction, &QAction::triggered, this, &KrSearchDialog::editCurrent); 0207 addAction(editAction); 0208 0209 compareAction = new QAction(i18n("Compare by content"), this); 0210 compareAction->setShortcut(Qt::Key_F10); 0211 connect(compareAction, &QAction::triggered, this, &KrSearchDialog::compareByContent); 0212 addAction(compareAction); 0213 0214 copyAction = KStandardAction::create(KStandardAction::Copy, this, SLOT(copyToClipBoard()), this); 0215 copyAction->setText(i18n("Copy to Clipboard")); 0216 addAction(copyAction); 0217 0218 connect(searcherTabs, &QTabWidget::currentChanged, this, [=](int index) { 0219 bool resultTabShown = index == searcherTabs->indexOf(resultTab); 0220 viewAction->setEnabled(resultTabShown); 0221 editAction->setEnabled(resultTabShown); 0222 compareAction->setEnabled(resultTabShown); 0223 copyAction->setEnabled(resultTabShown); 0224 }); 0225 0226 // creating the result list view 0227 result = new SearchResultContainer(this); 0228 // the view 0229 resultView = KrViewFactory::createView(RESULTVIEW_TYPE, resultTab, krConfig); 0230 resultView->init(false); 0231 resultView->restoreSettings(KConfigGroup(&group, "ResultView")); 0232 resultView->setMainWindow(this); 0233 resultView->prepareForActive(); 0234 resultView->refreshColors(); 0235 resultView->setFiles(result); 0236 resultView->refresh(); 0237 resultLayout->addWidget(resultView->widget(), 0, 0); 0238 // search bar - hidden by default 0239 searchBar = new KrSearchBar(resultView, this); 0240 searchBar->hide(); 0241 resultLayout->addWidget(searchBar, 1, 0); 0242 0243 // text found row 0244 foundTextFrame = new QFrame(resultTab); 0245 foundTextFrame->setFrameShape(QLabel::StyledPanel); 0246 foundTextFrame->setFrameShadow(QLabel::Sunken); 0247 0248 auto *foundTextLayout = new QHBoxLayout(); 0249 foundTextLayout->setSpacing(6); 0250 0251 QLabel *textFoundLabel = new QLabel(i18n("Text found:"), resultTab); 0252 foundTextLayout->addWidget(textFoundLabel); 0253 foundTextLabel = new KrSqueezedTextLabel(resultTab); 0254 foundTextLayout->addWidget(foundTextLabel); 0255 0256 foundTextFrame->setLayout(foundTextLayout); 0257 foundTextFrame->hide(); 0258 0259 resultLayout->addWidget(foundTextFrame, 2, 0); 0260 0261 // result info row 0262 auto *resultLabelLayout = new QHBoxLayout(); 0263 resultLabelLayout->setSpacing(6); 0264 resultLabelLayout->setContentsMargins(0, 0, 0, 0); 0265 0266 searchingLabel = new KSqueezedTextLabel(i18n("Idle"), resultTab); 0267 resultLabelLayout->addWidget(searchingLabel); 0268 0269 foundLabel = new QLabel("", resultTab); 0270 resultLabelLayout->addWidget(foundLabel); 0271 0272 mainFeedToListBoxBtn = new QPushButton(QIcon::fromTheme("list-add"), i18n("Feed to listbox"), this); 0273 mainFeedToListBoxBtn->setEnabled(false); 0274 resultLabelLayout->addWidget(mainFeedToListBoxBtn); 0275 0276 resultLayout->addLayout(resultLabelLayout, 3, 0); 0277 0278 searcherTabs->addTab(resultTab, i18n("&Results")); 0279 0280 searchBaseLayout->addWidget(searcherTabs, 0, 0); 0281 0282 // signals and slots connections 0283 0284 connect(mainSearchBtn, &QPushButton::clicked, this, &KrSearchDialog::startSearch); 0285 connect(mainStopBtn, &QPushButton::clicked, this, &KrSearchDialog::stopSearch); 0286 connect(mainCloseBtn, &QPushButton::clicked, this, &KrSearchDialog::closeDialog); 0287 connect(mainFeedToListBoxBtn, &QPushButton::clicked, this, &KrSearchDialog::feedToListBox); 0288 0289 connect(profileManager, &ProfileManager::loadFromProfile, filterTabs, &FilterTabs::loadFromProfile); 0290 connect(profileManager, &ProfileManager::saveToProfile, filterTabs, &FilterTabs::saveToProfile); 0291 0292 connect(resultView->op(), &KrViewOperator::currentChanged, this, &KrSearchDialog::currentChanged); 0293 connect(resultView->op(), &KrViewOperator::executed, this, &KrSearchDialog::executed); 0294 connect(resultView->op(), &KrViewOperator::contextMenu, this, &KrSearchDialog::contextMenu); 0295 0296 // tab order 0297 0298 setTabOrder(mainSearchBtn, mainCloseBtn); 0299 setTabOrder(mainCloseBtn, mainStopBtn); 0300 setTabOrder(mainStopBtn, searcherTabs); 0301 setTabOrder(searcherTabs, resultView->widget()); 0302 0303 sizeX = group.readEntry("Window Width", -1); 0304 sizeY = group.readEntry("Window Height", -1); 0305 0306 if (sizeX != -1 && sizeY != -1) 0307 resize(sizeX, sizeY); 0308 0309 if (group.readEntry("Window Maximized", false)) 0310 showMaximized(); 0311 else 0312 show(); 0313 0314 generalFilter->searchFor->setFocus(); 0315 0316 // finally, load a profile of apply defaults: 0317 0318 if (profile.isEmpty()) { 0319 // load the last used values 0320 generalFilter->searchFor->setEditText(lastSearchText); 0321 generalFilter->searchFor->lineEdit()->selectAll(); 0322 generalFilter->ofType->setCurrentIndex(lastSearchType); 0323 generalFilter->searchForCase->setChecked(lastSearchForCase); 0324 generalFilter->containsWholeWord->setChecked(lastContainsWholeWord); 0325 generalFilter->containsTextCase->setChecked(lastContainsWithCase); 0326 generalFilter->containsRegExp->setChecked(lastContainsRegExp); 0327 generalFilter->searchInDirs->setChecked(lastSearchInSubDirs); 0328 generalFilter->searchInArchives->setChecked(lastSearchInArchives); 0329 generalFilter->followLinks->setChecked(lastFollowSymLinks); 0330 // the path in the active panel should be the default search location 0331 generalFilter->searchIn->lineEdit()->setText(ACTIVE_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)); 0332 } else 0333 profileManager->loadProfile(profile); // important: call this _after_ you've connected profileManager ot the loadFromProfile!! 0334 } 0335 0336 KrSearchDialog::~KrSearchDialog() 0337 { 0338 delete query; 0339 query = nullptr; 0340 delete resultView; 0341 resultView = nullptr; 0342 } 0343 0344 void KrSearchDialog::closeDialog(bool isAccept) 0345 { 0346 if (isBusy) { 0347 closed = true; 0348 return; 0349 } 0350 0351 // stop the search if it's on-going 0352 if (searcher != nullptr) { 0353 delete searcher; 0354 searcher = nullptr; 0355 } 0356 0357 // saving the searcher state 0358 0359 KConfigGroup group(krConfig, "Search"); 0360 0361 group.writeEntry("Window Width", sizeX); 0362 group.writeEntry("Window Height", sizeY); 0363 group.writeEntry("Window Maximized", isMaximized()); 0364 0365 resultView->saveSettings(KConfigGroup(&group, "ResultView")); 0366 0367 lastSearchText = generalFilter->searchFor->currentText(); 0368 lastSearchType = generalFilter->ofType->currentIndex(); 0369 lastSearchForCase = generalFilter->searchForCase->isChecked(); 0370 lastContainsWholeWord = generalFilter->containsWholeWord->isChecked(); 0371 lastContainsWithCase = generalFilter->containsTextCase->isChecked(); 0372 lastContainsRegExp = generalFilter->containsRegExp->isChecked(); 0373 lastSearchInSubDirs = generalFilter->searchInDirs->isChecked(); 0374 lastSearchInArchives = generalFilter->searchInArchives->isChecked(); 0375 lastFollowSymLinks = generalFilter->followLinks->isChecked(); 0376 hide(); 0377 0378 SearchDialog = nullptr; 0379 if (isAccept) 0380 QDialog::accept(); 0381 else 0382 QDialog::reject(); 0383 0384 this->deleteLater(); 0385 } 0386 0387 void KrSearchDialog::reject() 0388 { 0389 closeDialog(false); 0390 } 0391 0392 void KrSearchDialog::resizeEvent(QResizeEvent *e) 0393 { 0394 if (!isMaximized()) { 0395 sizeX = e->size().width(); 0396 sizeY = e->size().height(); 0397 } 0398 } 0399 0400 void KrSearchDialog::slotFound(const FileItem &file, const QString &foundText) 0401 { 0402 result->addItem(file, foundText); 0403 foundLabel->setText(i18np("Found %1 match.", "Found %1 matches.", result->numFileItems())); 0404 } 0405 0406 bool KrSearchDialog::gui2query() 0407 { 0408 // prepare the query ... 0409 /////////////////// names, locations and greps 0410 if (query != nullptr) { 0411 delete query; 0412 query = nullptr; 0413 } 0414 query = new KrQuery(); 0415 0416 return filterTabs->fillQuery(query); 0417 } 0418 0419 void KrSearchDialog::startSearch() 0420 { 0421 if (isBusy) 0422 return; 0423 0424 // prepare the query ///////////////////////////////////////////// 0425 if (!gui2query()) 0426 return; 0427 0428 // first, informative messages 0429 if (query->searchInArchives()) { 0430 KMessageBox::information(this, 0431 i18n("Since you chose to also search in archives, " 0432 "note the following limitations:\n" 0433 "You cannot search for text (grep) while doing" 0434 " a search that includes archives."), 0435 nullptr, 0436 "searchInArchives"); 0437 } 0438 0439 // prepare the gui /////////////////////////////////////////////// 0440 result->clear(); 0441 resultView->setSortMode(KrViewProperties::NoColumn, 0); 0442 0443 foundTextFrame->setVisible(!query->content().isEmpty()); 0444 foundTextLabel->setText(""); 0445 0446 searchingLabel->setText(""); 0447 foundLabel->setText(i18n("Found 0 matches.")); 0448 mainFeedToListBoxBtn->setEnabled(false); 0449 0450 mainSearchBtn->setEnabled(false); 0451 mainStopBtn->setEnabled(true); 0452 mainCloseBtn->setEnabled(false); 0453 0454 searcherTabs->setCurrentIndex(2); // show the results page 0455 0456 isBusy = true; 0457 0458 qApp->processEvents(); 0459 0460 // start the search. 0461 if (searcher != nullptr) 0462 abort(); 0463 searcher = new KrSearchMod(query); 0464 connect(searcher, &KrSearchMod::searching, searchingLabel, &KSqueezedTextLabel::setText); 0465 connect(searcher, &KrSearchMod::found, this, &KrSearchDialog::slotFound); 0466 connect(searcher, &KrSearchMod::finished, this, &KrSearchDialog::stopSearch); 0467 0468 searcher->start(); 0469 0470 isBusy = false; 0471 0472 delete searcher; 0473 searcher = nullptr; 0474 0475 // gui stuff 0476 mainSearchBtn->setEnabled(true); 0477 mainCloseBtn->setEnabled(true); 0478 mainStopBtn->setEnabled(false); 0479 if (result->numFileItems()) 0480 mainFeedToListBoxBtn->setEnabled(true); 0481 searchingLabel->setText(i18n("Finished searching.")); 0482 0483 // go to the first result. Note: `getFirst()` doesn't cause problems 0484 // if the results list is empty 0485 resultView->setCurrentKrViewItem(resultView->getFirst()); 0486 0487 if (closed) 0488 closeDialog(); 0489 } 0490 0491 void KrSearchDialog::stopSearch() 0492 { 0493 if (searcher != nullptr) { 0494 searcher->stop(); 0495 disconnect(searcher, nullptr, nullptr, nullptr); 0496 } 0497 } 0498 0499 void KrSearchDialog::executed(const QString &name) 0500 { 0501 // 'name' is (local) file path or complete URL 0502 QString path = name; 0503 QString fileName; 0504 if (!name.endsWith('/')) { 0505 // not a directory, split filename and path 0506 int idx = name.lastIndexOf("/"); 0507 fileName = name.mid(idx + 1); 0508 path = name.left(idx); 0509 } 0510 QUrl url(path); 0511 if (url.scheme().isEmpty()) { 0512 url = QUrl::fromLocalFile(path); 0513 } 0514 ACTIVE_FUNC->openUrl(url, fileName); 0515 showMinimized(); 0516 } 0517 0518 void KrSearchDialog::currentChanged(KrViewItem *item) 0519 { 0520 if (!item) 0521 return; 0522 QString text = result->foundText(item->getFileItem()); 0523 if (!text.isEmpty()) { 0524 // ugly hack: find the <b> and </b> in the text, then 0525 // use it to set the are which we don't want squeezed 0526 int idx = text.indexOf("<b>") - 4; // take "<qt>" into account 0527 int length = text.indexOf("</b>") - idx + 4; 0528 foundTextLabel->setText(text, idx, length); 0529 } 0530 } 0531 0532 void KrSearchDialog::closeEvent(QCloseEvent *e) 0533 { /* if searching is in progress we must not close the window */ 0534 if (isBusy) /* because qApp->processEvents() is called by the searcher and */ 0535 { /* at window destruction, the searcher object will be deleted */ 0536 stopSearch(); /* instead we stop searching */ 0537 closed = true; /* and after stopping: startSearch can close the window */ 0538 e->ignore(); /* ignoring the close event */ 0539 } else 0540 QDialog::closeEvent(e); /* if no searching, let QDialog handle the event */ 0541 } 0542 0543 void KrSearchDialog::keyPressEvent(QKeyEvent *e) 0544 { 0545 // TODO: don't use hardcoded shortcuts 0546 0547 if (isBusy && e->key() == Qt::Key_Escape) { /* at searching we must not close the window */ 0548 stopSearch(); /* so we simply stop searching */ 0549 return; 0550 } 0551 if (resultView->widget()->hasFocus()) { 0552 if ((e->key() | e->modifiers()) == (Qt::CTRL | Qt::Key_I)) { 0553 searchBar->showBar(KrSearchBar::MODE_FILTER); 0554 } 0555 if (e->key() == Qt::Key_Menu) { 0556 contextMenu(QCursor::pos()); 0557 } 0558 } 0559 QDialog::keyPressEvent(e); 0560 } 0561 0562 void KrSearchDialog::editCurrent() 0563 { 0564 tryPlaceSearchQueryToClipboard(); 0565 KrViewItem *current = resultView->getCurrentKrViewItem(); 0566 if (current) 0567 KrViewer::edit(current->getFileItem()->getUrl(), this); 0568 } 0569 0570 void KrSearchDialog::viewCurrent() 0571 { 0572 tryPlaceSearchQueryToClipboard(); 0573 KrViewItem *current = resultView->getCurrentKrViewItem(); 0574 if (current) 0575 KrViewer::view(current->getFileItem()->getUrl(), this); 0576 } 0577 0578 void KrSearchDialog::compareByContent() 0579 { 0580 const KrViewItemList list = resultView->getSelectedKrViewItems(); 0581 if (list.count() != 2) 0582 return; 0583 0584 SLOTS->compareContent(list[0]->getFileItem()->getUrl(), list[1]->getFileItem()->getUrl()); 0585 } 0586 0587 void KrSearchDialog::contextMenu(const QPoint &pos) 0588 { 0589 // create the menu 0590 QMenu popup; 0591 popup.setTitle(i18n("Krusader Search")); 0592 0593 popup.addAction(viewAction); 0594 popup.addAction(editAction); 0595 popup.addAction(compareAction); 0596 compareAction->setEnabled(resultView->numSelected() == 2); 0597 popup.addSeparator(); 0598 popup.addAction(copyAction); 0599 0600 popup.exec(pos); 0601 } 0602 0603 void KrSearchDialog::feedToListBox() 0604 { 0605 VirtualFileSystem virtFilesystem; 0606 virtFilesystem.scanDir(QUrl::fromLocalFile("/")); 0607 0608 KConfigGroup group(krConfig, "Search"); 0609 int listBoxNum = group.readEntry("Feed To Listbox Counter", 1); 0610 QString queryName; 0611 if (query) { 0612 const QString where = KrServices::toStringList(query->searchInDirs()).join(", "); 0613 queryName = query->content().isEmpty() ? i18n("Search results for \"%1\" in %2", query->nameFilter(), where) 0614 : i18n("Search results for \"%1\" containing \"%2\" in %3", query->nameFilter(), query->content(), where); 0615 } 0616 QString fileSystemName; 0617 do { 0618 fileSystemName = i18n("Search results") + QString(" %1").arg(listBoxNum++); 0619 } while (virtFilesystem.getFileItem(fileSystemName) != nullptr); 0620 group.writeEntry("Feed To Listbox Counter", listBoxNum); 0621 0622 KConfigGroup ga(krConfig, "Advanced"); 0623 if (ga.readEntry("Confirm Feed to Listbox", _ConfirmFeedToListbox)) { 0624 bool ok; 0625 fileSystemName = QInputDialog::getText(this, i18n("Query name"), i18n("Here you can name the file collection"), QLineEdit::Normal, fileSystemName, &ok); 0626 if (!ok) 0627 return; 0628 } 0629 0630 QList<QUrl> urlList; 0631 foreach (FileItem *fileitem, result->fileItems()) 0632 urlList.push_back(fileitem->getUrl()); 0633 0634 mainSearchBtn->setEnabled(false); 0635 mainCloseBtn->setEnabled(false); 0636 mainFeedToListBoxBtn->setEnabled(false); 0637 0638 isBusy = true; 0639 0640 const QUrl url = QUrl(QString("virt:/") + fileSystemName); 0641 virtFilesystem.scanDir(url); 0642 virtFilesystem.addFiles(urlList); 0643 virtFilesystem.setMetaInformation(queryName); 0644 // ACTIVE_FUNC->openUrl(url); 0645 ACTIVE_MNG->slotNewTab(url); 0646 0647 isBusy = false; 0648 0649 closeDialog(); 0650 } 0651 0652 void KrSearchDialog::copyToClipBoard() 0653 { 0654 const KrViewItemList selectedItems = resultView->getSelectedKrViewItems(); 0655 QList<QUrl> urls; 0656 for (KrViewItem *item : selectedItems) { 0657 urls.append(item->getFileItem()->getUrl()); 0658 } 0659 0660 if (urls.count() == 0) 0661 return; 0662 0663 auto *mimeData = new QMimeData; 0664 mimeData->setImageData(FileListIcon("file").pixmap()); 0665 mimeData->setUrls(urls); 0666 0667 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); 0668 } 0669 0670 void KrSearchDialog::tryPlaceSearchQueryToClipboard() 0671 { 0672 if (searchTextToClipboard->isChecked() && !generalFilter->containsText->currentText().isEmpty() 0673 && QApplication::clipboard()->text() != generalFilter->containsText->currentText()) { 0674 QApplication::clipboard()->setText(generalFilter->containsText->currentText()); 0675 } 0676 }