File indexing completed on 2024-12-01 05:18:25
0001 /* 0002 kfinddlg.cpp 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 */ 0007 0008 #include "kfinddlg.h" 0009 0010 #include <QDialogButtonBox> 0011 #include <QHBoxLayout> 0012 #include <QPushButton> 0013 #include <QStatusBar> 0014 0015 #include <KAboutApplicationDialog> 0016 #include <KAboutData> 0017 #include <KGuiItem> 0018 #include <KHelpMenu> 0019 #include <KLocalizedString> 0020 #include <KMessageBox> 0021 0022 #include "kftabdlg.h" 0023 #include "kquery.h" 0024 #include "kfindtreeview.h" 0025 0026 KfindDlg::KfindDlg(const QUrl &url, QWidget *parent) 0027 : QDialog(parent) 0028 { 0029 QHBoxLayout *mainLayout = new QHBoxLayout(this); 0030 setModal(true); 0031 QWidget::setWindowTitle(i18nc("@title:window", "Find Files/Folders")); 0032 0033 QFrame *frame = new QFrame; 0034 mainLayout->addWidget(frame); 0035 0036 // create tabwidget 0037 tabWidget = new KfindTabWidget(frame); 0038 mainLayout->addWidget(tabWidget); 0039 tabWidget->setURL(url); 0040 0041 // prepare window for find results 0042 win = new KFindTreeView(frame, this); 0043 0044 mStatusBar = new QStatusBar(frame); 0045 0046 m_labelStatus = new QLabel(mStatusBar); 0047 m_labelStatus->setAlignment (Qt::AlignLeft | Qt::AlignVCenter); 0048 m_labelStatus->setText(i18nc("the application is currently idle, there is no active search", "Idle.")); 0049 0050 m_labelProgress = new QLabel(mStatusBar); 0051 m_labelProgress->setAlignment (Qt::AlignRight | Qt::AlignVCenter); 0052 m_labelProgress->setText(QString()); 0053 0054 mStatusBar->addWidget(m_labelStatus, 1); 0055 mStatusBar->addWidget(m_labelProgress, 0); 0056 0057 QVBoxLayout *vBox = new QVBoxLayout(frame); 0058 vBox->addWidget(tabWidget, 0); 0059 vBox->addWidget(win, 1); 0060 vBox->addWidget(mStatusBar, 0); 0061 0062 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close, this); 0063 m_findButton = new QPushButton; 0064 buttonBox->addButton(m_findButton, QDialogButtonBox::ActionRole); 0065 m_stopButton = new QPushButton; 0066 buttonBox->addButton(m_stopButton, QDialogButtonBox::ActionRole); 0067 m_saveAsButton = new QPushButton; 0068 buttonBox->addButton(m_saveAsButton, QDialogButtonBox::ActionRole); 0069 buttonBox->setOrientation(Qt::Vertical); 0070 m_findButton->setDefault(true); 0071 0072 KGuiItem::assign(m_findButton, KStandardGuiItem::find()); 0073 KGuiItem::assign(m_stopButton, KStandardGuiItem::stop()); 0074 KGuiItem::assign(m_saveAsButton, KStandardGuiItem::saveAs()); 0075 0076 m_findButton->setEnabled(true); // Enable "Find" 0077 m_stopButton->setEnabled(false); // Disable "Stop" 0078 m_saveAsButton->setEnabled(false); // Disable "Save As..." 0079 0080 mainLayout->addWidget(buttonBox); 0081 0082 connect(tabWidget, &KfindTabWidget::startSearch, this, &KfindDlg::startSearch); 0083 connect(m_findButton, &QPushButton::clicked, this, &KfindDlg::startSearch); 0084 connect(m_stopButton, &QPushButton::clicked, this, &KfindDlg::stopSearch); 0085 connect(m_saveAsButton, &QPushButton::clicked, win, &KFindTreeView::saveResults); 0086 0087 connect(buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &KfindDlg::finishAndClose); 0088 0089 connect(win, &KFindTreeView::resultSelected, this, &KfindDlg::resultSelected); 0090 0091 query = new KQuery(frame); 0092 connect(query, &KQuery::result, this, &KfindDlg::slotResult); 0093 connect(query, &KQuery::foundFileList, this, &KfindDlg::addFiles); 0094 0095 KHelpMenu *helpMenu = new KHelpMenu(this, KAboutData::applicationData(), true); 0096 buttonBox->button(QDialogButtonBox::Help)->setMenu(helpMenu->menu()); 0097 dirwatch = nullptr; 0098 0099 setFocus(); 0100 } 0101 0102 KfindDlg::~KfindDlg() 0103 { 0104 stopSearch(); 0105 0106 delete dirwatch; 0107 } 0108 0109 void KfindDlg::finishAndClose() 0110 { 0111 //Stop the current search and closes the dialog 0112 stopSearch(); 0113 close(); 0114 } 0115 0116 void KfindDlg::setProgressMsg(const QString &msg) 0117 { 0118 m_labelProgress->setText(msg); 0119 } 0120 0121 void KfindDlg::setStatusMsg(const QString &msg) 0122 { 0123 m_labelStatus->setText(msg); 0124 } 0125 0126 void KfindDlg::startSearch() 0127 { 0128 tabWidget->setQuery(query); 0129 0130 isResultReported = false; 0131 0132 // Reset count - use the same i18n as below 0133 setProgressMsg(i18n("0 items found")); 0134 0135 Q_EMIT resultSelected(false); 0136 Q_EMIT haveResults(false); 0137 0138 m_findButton->setEnabled(false); // Disable "Find" 0139 m_stopButton->setEnabled(true); // Enable "Stop" 0140 m_saveAsButton->setEnabled(false); // Disable "Save As..." 0141 0142 delete dirwatch; 0143 dirwatch = new KDirWatch(); 0144 connect(dirwatch, &KDirWatch::created, this, &KfindDlg::slotNewItems); 0145 connect(dirwatch, &KDirWatch::deleted, this, &KfindDlg::slotDeleteItem); 0146 dirwatch->addDir(query->url().toLocalFile(), KDirWatch::WatchFiles); 0147 0148 #if 0 0149 // waba: Watching for updates is disabled for now because even with FAM it causes too 0150 // much problems. See BR68220, BR77854, BR77846, BR79512 and BR85802 0151 // There are 3 problems: 0152 // 1) addDir() keeps looping on recursive symlinks 0153 // 2) addDir() scans all subdirectories, so it basically does the same as the process that 0154 // is started by KQuery but in-process, undoing the advantages of using a separate find process 0155 // A solution could be to let KQuery Q_EMIT all the directories it has searched in. 0156 // Either way, putting dirwatchers on a whole file system is probably just too much. 0157 // 3) FAM has a tendency to deadlock with so many files (See BR77854) This has hopefully 0158 // been fixed in KDirWatch, but that has not yet been confirmed. 0159 0160 //Getting a list of all subdirs 0161 if (tabWidget->isSearchRecursive() && (dirwatch->internalMethod() == KDirWatch::FAM)) { 0162 const QStringList subdirs = getAllSubdirs(query->url().path()); 0163 for (QStringList::const_iterator it = subdirs.constBegin(); it != subdirs.constEnd(); ++it) { 0164 dirwatch->addDir(*it, true); 0165 } 0166 } 0167 #endif 0168 0169 win->beginSearch(query->url()); 0170 tabWidget->beginSearch(); 0171 0172 setStatusMsg(i18n("Searching...")); 0173 query->start(); 0174 } 0175 0176 void KfindDlg::stopSearch() 0177 { 0178 query->kill(); 0179 } 0180 0181 void KfindDlg::newSearch() 0182 { 0183 // WABA: Not used any longer? 0184 stopSearch(); 0185 0186 tabWidget->setDefaults(); 0187 0188 Q_EMIT haveResults(false); 0189 Q_EMIT resultSelected(false); 0190 0191 setFocus(); 0192 } 0193 0194 void KfindDlg::slotResult(int errorCode) 0195 { 0196 if (errorCode == 0) { 0197 setStatusMsg(i18nc("the application is currently idle, there is no active search", "Idle.")); 0198 } else if (errorCode == KIO::ERR_USER_CANCELED) { 0199 setStatusMsg(i18n("Canceled.")); 0200 } else if (errorCode == KIO::ERR_MALFORMED_URL) { 0201 setStatusMsg(i18n("Error.")); 0202 KMessageBox::error(this, i18n("Please specify an absolute path in the \"Look in\" box.")); 0203 } else if (errorCode == KIO::ERR_DOES_NOT_EXIST) { 0204 setStatusMsg(i18n("Error.")); 0205 KMessageBox::error(this, i18n("Could not find the specified folder.")); 0206 } else { 0207 setStatusMsg(i18n("Error.")); 0208 } 0209 0210 m_findButton->setEnabled(true); // Enable "Find" 0211 m_stopButton->setEnabled(false); // Disable "Stop" 0212 m_saveAsButton->setEnabled(true); // Enable "Save As..." 0213 0214 win->endSearch(); 0215 tabWidget->endSearch(); 0216 setFocus(); 0217 } 0218 0219 void KfindDlg::addFiles(const QList< QPair<KFileItem, QString> > &pairs) 0220 { 0221 win->insertItems(pairs); 0222 0223 if (!isResultReported) { 0224 Q_EMIT haveResults(true); 0225 isResultReported = true; 0226 } 0227 0228 const QString str = i18np("one item found", "%1 items found", win->itemCount()); 0229 setProgressMsg(str); 0230 } 0231 0232 void KfindDlg::setFocus() 0233 { 0234 tabWidget->setFocus(); 0235 } 0236 0237 void KfindDlg::copySelection() 0238 { 0239 win->copySelection(); 0240 } 0241 0242 void KfindDlg::about() 0243 { 0244 KAboutApplicationDialog dlg(KAboutData::applicationData(), KAboutApplicationDialog::NoOptions, this); 0245 dlg.exec(); 0246 } 0247 0248 void KfindDlg::slotDeleteItem(const QString &file) 0249 { 0250 win->removeItem(QUrl::fromLocalFile(file)); 0251 0252 const QString str = i18np("one item found", "%1 items found", win->itemCount()); 0253 setProgressMsg(str); 0254 } 0255 0256 void KfindDlg::slotNewItems(const QString &file) 0257 { 0258 const QUrl url = QUrl::fromLocalFile(file); 0259 0260 if (query->url().isParentOf(url)) { 0261 if (!win->isInserted(url)) { 0262 query->slotListEntries(QStringList() << file); 0263 } 0264 } 0265 } 0266 0267 QStringList KfindDlg::getAllSubdirs(QDir d) 0268 { 0269 d.setFilter(QDir::Dirs); 0270 const QStringList dirs = d.entryList(QDir::NoDotAndDotDot); 0271 QStringList subdirs; 0272 subdirs.reserve(dirs.size()); 0273 0274 for (const auto &dir : dirs) { 0275 subdirs.append(d.path() + QLatin1Char('/') + dir); 0276 subdirs += getAllSubdirs(QDir(d.path() + QLatin1Char('/') + dir)); 0277 } 0278 return subdirs; 0279 } 0280 0281 #include "moc_kfinddlg.cpp"