File indexing completed on 2024-05-05 17:15:09
0001 /* This file is part of the kile project 0002 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 0003 Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org> 0004 Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk> 0005 Copyright (C) 2003 Jan-Marek Glogowski <glogow@stud.fbi.fh-darmstadt.de> 0006 Copyright (C) 2005 Holger Danielsson <holger.danielsson@versanet.de> 0007 Copyright (C) 2008-2022 Michel Ludwig <michel.ludwig@kdemail.net> 0008 0009 This program is free software; you can redistribute it and/or 0010 modify it under the terms of the GNU General Public License as 0011 published by the Free Software Foundation; either version 2 of 0012 the License, or (at your option) any later version. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 0022 Original from kdebase / kate 0023 0024 changes: 2005-11-27 (dani) 0025 - add a search for all files of a Kile project 0026 (done with one grep command for each file) 0027 - dialog is now based on KDialogBase 0028 - an item of the resultbox ist opened when it's highlightened 0029 (no double click is needed anymore) 0030 - dialog is deleted after work to minimize resources 0031 - added additional search modes for environments, labels etc. 0032 - fixed some bugs (f.e. two slashes at the end of directory 0033 names, jumping to the wrong line, wrong pattern lists) 0034 - add some editable template modes to search for LaTeX commands 0035 - add some predined modes to search for environments, graphics, 0036 labels, and references, either all of them or some special ones 0037 0038 (in other words: most parts have changed to work perfectly with Kile ...) 0039 */ 0040 0041 // 2007-03-12 dani 0042 // - use KileDocument::Extensions 0043 0044 #include "dialogs/findfilesdialog.h" 0045 0046 #include <QCheckBox> 0047 #include <QCursor> 0048 #include <QDialogButtonBox> 0049 #include <QEvent> 0050 #include <QGridLayout> 0051 #include <QGroupBox> 0052 #include <QHBoxLayout> 0053 #include <QLabel> 0054 #include <QLayout> 0055 #include <QLineEdit> 0056 #include <QListWidget> 0057 #include <QObject> 0058 #include <QPushButton> 0059 #include <QRegularExpression> 0060 #include <QVBoxLayout> 0061 0062 #include <KProcess> 0063 #include <KAcceleratorManager> 0064 #include <KComboBox> 0065 #include <KLocalizedString> 0066 #include <KMessageBox> 0067 #include <KShell> 0068 #include <KUrlCompletion> 0069 #include <KUrlRequester> 0070 #include <KConfigGroup> 0071 0072 #include "kiledebug.h" 0073 #include "kileconfig.h" 0074 #include "kileproject.h" 0075 #include "kiledocmanager.h" 0076 #include "kileextensions.h" 0077 0078 namespace KileDialog { 0079 0080 FindFilesDialog::FindFilesDialog(QWidget *parent, KileInfo *ki, KileGrep::Mode mode, const char *name) 0081 : QDialog(parent) 0082 , m_ki(ki) 0083 , m_mode(mode) 0084 , m_proc(Q_NULLPTR) 0085 , m_grepJobs(0) 0086 { 0087 setObjectName(name); 0088 setWindowTitle(QString()); 0089 setModal(false); 0090 QVBoxLayout *mainLayout = new QVBoxLayout; 0091 setLayout(mainLayout); 0092 0093 // project groupbox 0094 QGroupBox *projectgroup = new QGroupBox(i18n("Project"), this); 0095 mainLayout->addWidget(projectgroup); 0096 QGridLayout *projectgrouplayout = new QGridLayout(); 0097 projectgrouplayout->setAlignment(Qt::AlignTop); 0098 projectgroup->setLayout(projectgrouplayout); 0099 0100 QLabel *project_label = new QLabel(i18n("Name:"), projectgroup); 0101 int labelwidth = project_label->sizeHint().width(); 0102 0103 QLabel *projectdir_label = new QLabel(i18n("Directory:"), projectgroup); 0104 if(projectdir_label->sizeHint().width() > labelwidth) { 0105 labelwidth = projectdir_label->sizeHint().width(); 0106 } 0107 0108 projectname_label = new QLabel(projectgroup); 0109 projectdirname_label = new QLabel(projectgroup); 0110 0111 projectgrouplayout->addWidget(project_label, 0, 0, Qt::AlignLeft | Qt::AlignVCenter); 0112 projectgrouplayout->addWidget(projectname_label, 0, 1, Qt::AlignLeft | Qt::AlignVCenter); 0113 projectgrouplayout->addWidget(projectdir_label, 1, 0, Qt::AlignLeft | Qt::AlignVCenter); 0114 projectgrouplayout->addWidget(projectdirname_label, 1, 1, Qt::AlignLeft | Qt::AlignVCenter); 0115 projectgrouplayout->setColumnStretch(1, 1); 0116 0117 // search groupbox 0118 QGroupBox *searchgroup = new QGroupBox(i18n("Search"), this); 0119 mainLayout->addWidget(searchgroup); 0120 QGridLayout *searchgrouplayout = new QGridLayout(); 0121 searchgrouplayout->setAlignment(Qt::AlignTop); 0122 searchgroup->setLayout(searchgrouplayout); 0123 0124 QLabel *pattern_label = new QLabel(i18n("Pattern:"), searchgroup); 0125 if(pattern_label->sizeHint().width() > labelwidth) { 0126 labelwidth = pattern_label->sizeHint().width(); 0127 } 0128 0129 pattern_combo = new KComboBox(true, searchgroup); 0130 pattern_combo->setInsertPolicy(KComboBox::NoInsert); 0131 pattern_combo->setFocus(); 0132 pattern_combo->setMinimumSize(pattern_combo->sizeHint()); 0133 pattern_label->setBuddy(pattern_combo); 0134 0135 QLabel *template_label = new QLabel(i18n("Template:"), searchgroup); 0136 if(template_label->sizeHint().width() > labelwidth) { 0137 labelwidth = template_label->sizeHint().width(); 0138 } 0139 0140 QStringList templatemode_list; 0141 templatemode_list << i18n("Normal") 0142 << i18n("Command") 0143 << i18n("Command[]") 0144 << i18n("Environment") 0145 << i18n("Image") 0146 << i18n("Label") 0147 << i18n("Reference") 0148 << i18n("File"); 0149 0150 QHBoxLayout *template_layout = new QHBoxLayout(); 0151 template_layout->setContentsMargins(0, 0, 0, 0); 0152 template_combo = new KComboBox(false, searchgroup); 0153 template_combo->addItems(templatemode_list); 0154 template_combo->adjustSize(); 0155 template_combo->setFixedSize(template_combo->size()); 0156 template_layout->addWidget(template_combo); 0157 m_lastTemplateIndex = 0; 0158 0159 template_edit = new QLineEdit(searchgroup); 0160 template_edit->setText("%s"); 0161 template_edit->setMinimumSize(template_edit->sizeHint()); 0162 template_label->setBuddy(template_edit); 0163 template_layout->addWidget(template_edit); 0164 0165 searchgrouplayout->addWidget(pattern_label, 0, 0, Qt::AlignLeft | Qt::AlignVCenter); 0166 searchgrouplayout->addWidget(pattern_combo, 0, 1); 0167 searchgrouplayout->addWidget(template_label, 1, 0, Qt::AlignLeft | Qt::AlignVCenter); 0168 searchgrouplayout->addLayout(template_layout, 1, 1); 0169 0170 // filter groupbox 0171 QGroupBox *filtergroup = new QGroupBox(i18n("Directory Options"), this); 0172 mainLayout->addWidget(filtergroup); 0173 QGridLayout *filtergrouplayout = new QGridLayout(); 0174 filtergrouplayout->setAlignment(Qt::AlignTop); 0175 filtergroup->setLayout(filtergrouplayout); 0176 0177 QLabel *files_label = new QLabel(i18n("Filter:"), filtergroup); 0178 if (files_label->sizeHint().width() > labelwidth) { 0179 labelwidth = files_label->sizeHint().width(); 0180 } 0181 0182 filter_combo = new KComboBox(true, filtergroup); 0183 filter_combo->setMinimumSize(filter_combo->sizeHint()); 0184 files_label->setBuddy(filter_combo->focusProxy()); 0185 0186 QLabel *dir_label = new QLabel(i18n("Directory:"), filtergroup); 0187 if (dir_label->sizeHint().width() > labelwidth) { 0188 labelwidth = dir_label->sizeHint().width(); 0189 } 0190 0191 dir_combo = new KUrlRequester(new KComboBox(true, filtergroup), filtergroup); 0192 dir_combo->setObjectName("dir combo"); 0193 dir_combo->completionObject()->setMode(KUrlCompletion::DirCompletion); 0194 dir_combo->setMode(KFile::Directory | KFile::LocalOnly | KFile::ExistingOnly); 0195 dir_label->setBuddy(dir_combo); 0196 0197 recursive_box = new QCheckBox(i18n("Scan directories recursively"), filtergroup); 0198 recursive_box->setMinimumWidth(recursive_box->sizeHint().width()); 0199 0200 filtergrouplayout->addWidget(files_label, 0, 0); 0201 filtergrouplayout->addWidget(filter_combo, 0, 1); 0202 filtergrouplayout->addWidget(dir_label, 1, 0); 0203 filtergrouplayout->addWidget(dir_combo, 1, 1); 0204 filtergrouplayout->addWidget(recursive_box, 2, 1); 0205 filtergrouplayout->setColumnStretch(1, 1); 0206 0207 // result box 0208 resultbox = new QListWidget(this); 0209 mainLayout->addWidget(resultbox); 0210 resultbox->setMinimumHeight(150); 0211 0212 // button box 0213 QDialogButtonBox *actionbox = new QDialogButtonBox(this); 0214 mainLayout->addWidget(actionbox); 0215 search_button = new QPushButton(i18n("&Search")); 0216 search_button->setDefault(true); 0217 search_button->setEnabled(false); 0218 search_button->setIcon(QIcon::fromTheme("edit-find")); 0219 connect(search_button, &QPushButton::clicked, this, &FindFilesDialog::slotSearch); 0220 actionbox->addButton(search_button, QDialogButtonBox::ActionRole); 0221 clear_button = new QPushButton(i18n("&Clear")); 0222 clear_button->setEnabled(false); 0223 clear_button->setIcon(QIcon::fromTheme("edit-clear-locationbar")); 0224 connect(clear_button, &QPushButton::clicked, this, &FindFilesDialog::slotClear); 0225 actionbox->addButton(clear_button, QDialogButtonBox::ActionRole); 0226 close_button = actionbox->addButton(QDialogButtonBox::Close); 0227 connect(close_button, &QPushButton::clicked, this, &FindFilesDialog::slotClose); 0228 0229 // adjust labels 0230 project_label->setFixedWidth(labelwidth); 0231 projectdir_label->setFixedWidth(labelwidth); 0232 pattern_label->setFixedWidth(labelwidth); 0233 template_label->setFixedWidth(labelwidth); 0234 files_label->setFixedWidth(labelwidth); 0235 dir_label->setFixedWidth(labelwidth); 0236 0237 if (m_mode == KileGrep::Project) { 0238 filtergroup->hide(); 0239 mainLayout->addWidget(projectgroup); 0240 mainLayout->addWidget(searchgroup); 0241 } 0242 else { 0243 projectgroup->hide(); 0244 mainLayout->addWidget(searchgroup); 0245 mainLayout->addWidget(filtergroup); 0246 } 0247 mainLayout->addWidget(resultbox); 0248 mainLayout->addWidget(actionbox); 0249 0250 // Produces error messages like 0251 // QListBox::property( "text" ) failed: 0252 // property invalid or does not exist 0253 // Anyone an idea? 0254 KAcceleratorManager::manage(this); 0255 0256 pattern_combo->setWhatsThis( 0257 i18n("Enter the regular expression you want to search for here.<br>" 0258 "Possible meta characters are:<br>" 0259 "<ul>" 0260 "<li> <b>.</b> - Matches any character</li>" 0261 "<li> <b>^</b> - Matches the beginning of a line</li>" 0262 "<li> <b>$</b> - Matches the end of a line</li>" 0263 "<li> <b>\\\\\\<</b> - Matches the beginning of a word</li>" 0264 "<li> <b>\\\\\\></b> - Matches the end of a word</li>" 0265 "</ul>" 0266 "The following repetition operators exist:" 0267 "<ul>" 0268 "<li> <b>?</b> - The preceding item is matched at most once</li>" 0269 "<li> <b>*</b> - The preceding item is matched zero or more times</li>" 0270 "<li> <b>+</b> - The preceding item is matched one or more times</li>" 0271 "<li> <b>{<i>n</i>}</b> - The preceding item is matched exactly <i>n</i> times</li>" 0272 "<li> <b>{<i>n</i>,}</b> - The preceding item is matched <i>n</i> or more times</li>" 0273 "<li> <b>{,<i>n</i>}</b> - The preceding item is matched at most <i>n</i> times</li>" 0274 "<li> <b>{<i>n</i>,<i>m</i>}</b> - The preceding item is matched at least <i>n</i>, " 0275 "but at most <i>m</i> times.</li>" 0276 "</ul>" 0277 "Furthermore, backreferences to bracketed subexpressions are " 0278 "available via the notation \\\\<i>n</i>." 0279 )); 0280 filter_combo->setWhatsThis( 0281 i18n("Enter the file name pattern of the files to search here. " 0282 "You may give several patterns separated by commas.")); 0283 template_combo->setWhatsThis( 0284 i18n("Choose one search mode. For the first modes, the search pattern is " 0285 "built from the editable template, where '%s' is replaced by the given pattern.<br><br>" 0286 "There are additional fixed predefined modes for environments, graphics, labels, references " 0287 "and input files. If the pattern is empty, Kile will search for all commands of this mode. " 0288 "If a pattern is given, it will be inserted as a parameter. For example, in environment mode with " 0289 "pattern 'center', Kile will search for '\\begin{center}', and in graphics mode with " 0290 "pattern '.*\\.png', Kile will search for all png files.")); 0291 template_edit->setWhatsThis( 0292 i18n("For the first three modes you can choose a template for the pattern from the combo box " 0293 "and edit it here. The string %s in the template is replaced " 0294 "by the pattern input field, resulting in the regular expression " 0295 "to search for. In all other modes this template is ignored.")); 0296 dir_combo->setWhatsThis( 0297 i18n("Enter the directory which contains the files you want to search in.")); 0298 recursive_box->setWhatsThis( 0299 i18n("Check this box to search in all subdirectories.")); 0300 resultbox->setWhatsThis( 0301 i18n("The results of the grep run are listed here. Select a " 0302 "filename/line number combination with a mouse click on the item " 0303 "or with the cursor to show the respective line in the editor.")); 0304 0305 // read config and setup dialog for both modes 0306 readConfig(); 0307 if (m_mode == KileGrep::Directory) { 0308 setWindowTitle(i18n("Find in Files")); 0309 setupDirectory(); 0310 } 0311 else { 0312 setWindowTitle(i18n("Find in Project")); 0313 setupProject(); 0314 } 0315 0316 pattern_combo->setEditText(QString()); 0317 template_edit->setText(m_TemplateList[0]); 0318 slotPatternTextChanged(QString()); 0319 0320 connect(pattern_combo->lineEdit(), &QLineEdit::textChanged, 0321 this, &FindFilesDialog::slotPatternTextChanged); 0322 connect(template_combo, static_cast<void (KComboBox::*)(int)>(&KComboBox::activated), 0323 this, &FindFilesDialog::slotTemplateActivated); 0324 connect(resultbox, &QListWidget::currentTextChanged, 0325 this, &FindFilesDialog::slotItemSelected); 0326 0327 QDialogButtonBox *buttonBox = new QDialogButtonBox(); 0328 connect(buttonBox, &QDialogButtonBox::accepted, this, &FindFilesDialog::accept); 0329 connect(buttonBox, &QDialogButtonBox::rejected, this, &FindFilesDialog::reject); 0330 mainLayout->addWidget(buttonBox); 0331 0332 connect(this, &FindFilesDialog::finished, this, &FindFilesDialog::slotClose); 0333 0334 resize(450, sizeHint().height()); 0335 KILE_DEBUG_MAIN << "==FindFilesDialog (create dialog)============================="; 0336 } 0337 0338 FindFilesDialog::~FindFilesDialog() 0339 { 0340 KILE_DEBUG_MAIN << "==FindFilesDialog (delete dialog)============================="; 0341 writeConfig(); 0342 } 0343 0344 ///////////////////// config ///////////////////// 0345 0346 void FindFilesDialog::readConfig() 0347 { 0348 pattern_combo->addItems(readList(KileGrep::SearchItems)); 0349 0350 QString labels = getCommandList(KileDocument::CmdAttrLabel); 0351 QString references = getCommandList(KileDocument::CmdAttrReference); 0352 m_TemplateList = readList(KileGrep::SearchTemplates) ; 0353 if(m_TemplateList.count() != 3) { 0354 m_TemplateList.clear(); 0355 m_TemplateList << "%s" << "\\\\%s\\{" << "\\\\%s(\\[[^]]*\\])?\\{"; 0356 } 0357 m_TemplateList << "\\\\begin\\{" // to be closed with "%s\\}" 0358 << "\\\\includegraphics(\\[[^]]*\\])?\\{" 0359 << "\\\\(label" + labels + ")\\{" 0360 << "\\\\(ref|pageref|vref|vpageref|fref|Fref|eqref" + references + ")(\\[[^]]*\\])?\\{" 0361 << "\\\\(input|include)\\{" 0362 ; 0363 0364 if (m_mode == KileGrep::Directory) { 0365 dir_combo->comboBox()->addItems(readList(KileGrep::SearchPaths)); 0366 recursive_box->setChecked(KileConfig::grepRecursive()); 0367 } 0368 } 0369 0370 void FindFilesDialog::writeConfig() 0371 { 0372 KileConfig::setLastSearchItems(getListItems(pattern_combo)); 0373 0374 QStringList list; 0375 list << m_TemplateList[0] << m_TemplateList[1] << m_TemplateList[2]; 0376 KileConfig::setLastSearchTemplates(list); 0377 0378 if(m_mode == KileGrep::Directory) { 0379 KileConfig::setLastSearchPaths(getListItems(dir_combo->comboBox())); 0380 KileConfig::setGrepRecursive(recursive_box->isChecked()); 0381 } 0382 } 0383 0384 ///////////////////// setup search modes ///////////////////// 0385 0386 void FindFilesDialog::setupDirectory() 0387 { 0388 setDirName(QDir::home().absolutePath()); 0389 // use a filter for 'find in files' dialog 0390 KileDocument::Extensions *extensions = m_ki->extensions(); 0391 QString filter = extensions->fileFilterKDEStyle(true, {KileDocument::Extensions::TEX, 0392 KileDocument::Extensions::PACKAGES, 0393 KileDocument::Extensions::BIB, 0394 KileDocument::Extensions::METAPOST 0395 }); 0396 setFilter(filter); 0397 } 0398 0399 void FindFilesDialog::setupProject() 0400 { 0401 KileProject *project = m_ki->docManager()->activeProject(); 0402 if(project) { 0403 m_projectOpened = true; 0404 m_projectdir = project->baseURL().toLocalFile(); 0405 projectname_label->setText(project->name()); 0406 projectdirname_label->setText(m_projectdir); 0407 0408 m_projectfiles.clear(); 0409 m_projectfiles = m_ki->docManager()->getProjectFiles(); 0410 } 0411 else { 0412 m_projectOpened = false; 0413 projectname_label->setText(i18n("no project opened")); 0414 projectdirname_label->setText(QString()); 0415 } 0416 } 0417 0418 ///////////////////// read entries ///////////////////// 0419 0420 QStringList FindFilesDialog::readList(KileGrep::List listtype) 0421 { 0422 QStringList strings, result; 0423 0424 bool stripSlash = false; 0425 switch (listtype) { 0426 case KileGrep::SearchItems: 0427 strings = KileConfig::lastSearchItems(); 0428 break; 0429 case KileGrep::SearchPaths: 0430 strings = KileConfig::lastSearchPaths(); 0431 stripSlash = true; 0432 break; 0433 case KileGrep::SearchTemplates: 0434 strings = KileConfig::lastSearchTemplates(); 0435 break; 0436 } 0437 0438 while (strings.count() > 0) { 0439 if(stripSlash && strings[0].right(1) == "/") { 0440 strings[0].truncate(strings[0].length() - 1); 0441 } 0442 if(!strings[0].isEmpty()) { 0443 result.append(strings[0]); 0444 } 0445 strings.removeAll(strings[0]); 0446 } 0447 return result; 0448 } 0449 0450 ///////////////////// item selected ///////////////////// 0451 0452 void FindFilesDialog::slotItemSelected(const QString& item) 0453 { 0454 KILE_DEBUG_MAIN << "\tgrep: start item selected"; 0455 int pos; 0456 0457 QString str = item; 0458 if((pos = str.indexOf(':')) != -1) { 0459 QString filename = str.left(pos); 0460 str = str.right(str.length() - 1 - pos); 0461 if((pos = str.indexOf(':')) != -1) { 0462 QString linenumber = str.left(pos); 0463 QFileInfo fileInfo(filename); 0464 if(fileInfo.isAbsolute()) { 0465 emit itemSelected(filename, linenumber.toInt()); 0466 } 0467 else if(m_mode == KileGrep::Project) { 0468 emit itemSelected(m_projectdir + QDir::separator() + filename, linenumber.toInt()); 0469 } 0470 else { 0471 emit itemSelected(dir_combo->comboBox()->itemText(0) + QDir::separator() + filename, linenumber.toInt()); 0472 } 0473 } 0474 } 0475 } 0476 0477 ///////////////////// grep ///////////////////// 0478 0479 void FindFilesDialog::startGrep() 0480 { 0481 m_proc = new KProcess(this); 0482 m_proc->setOutputChannelMode(KProcess::SeparateChannels); 0483 0484 m_buf.clear(); 0485 m_errbuf.clear(); 0486 QString command; 0487 if (m_mode == KileGrep::Project) { 0488 command = buildProjectCommand() + ' ' + KShell::quoteArg(m_projectfiles[m_grepJobs-1]); 0489 } 0490 else { 0491 command = buildFilesCommand(); 0492 } 0493 KILE_DEBUG_MAIN << "\tgrep (project): " << command; 0494 (*m_proc) << KShell::splitArgs(command); 0495 0496 m_grepJobs--; 0497 0498 connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), 0499 this, &FindFilesDialog::processExited); 0500 connect(m_proc, &KProcess::readyReadStandardOutput, 0501 this, &FindFilesDialog::processStandardOutputReady); 0502 connect(m_proc, &KProcess::readyReadStandardError, 0503 this, &FindFilesDialog::processErrorOutputReady); 0504 0505 m_proc->start(); 0506 } 0507 0508 void FindFilesDialog::processOutput(bool forceAll) 0509 { 0510 // NOTE: it isn't possible to use 'kapp->processEvents()' in this method as 0511 // this will trigger the 'readAllStandardOutput()' signal, and call this 0512 // method again. 0513 int pos; 0514 int n = 0; 0515 while((pos = m_buf.indexOf('\n')) != -1) { 0516 QString item = m_buf.left(pos); 0517 if(!item.isEmpty()) { 0518 if(m_mode == KileGrep::Project) { 0519 if (item.indexOf(m_projectdir) == 0) { 0520 new QListWidgetItem(item.mid(m_projectdir.length()), resultbox); 0521 } 0522 else { 0523 new QListWidgetItem(item, resultbox); 0524 } 0525 } 0526 else { 0527 new QListWidgetItem(item.mid(dir_combo->url().toLocalFile().length() + 1), resultbox); 0528 } 0529 } 0530 m_buf = m_buf.right(m_buf.length() - pos - 1); 0531 if(!forceAll) { 0532 ++n; 0533 if(n == 100) { 0534 break; 0535 } 0536 } 0537 } 0538 } 0539 0540 void FindFilesDialog::processStandardOutputReady() 0541 { 0542 QByteArray outputBuffer = m_proc->readAllStandardOutput(); 0543 m_buf += QString::fromLocal8Bit(outputBuffer.data(), outputBuffer.size()); 0544 processOutput(); 0545 } 0546 0547 void FindFilesDialog::processErrorOutputReady() 0548 { 0549 QByteArray outputBuffer = m_proc->readAllStandardError(); 0550 m_errbuf += QString::fromLocal8Bit(outputBuffer.data(), outputBuffer.size()); 0551 } 0552 0553 void FindFilesDialog::processExited(int /*exitCode*/, QProcess::ExitStatus /*exitStatus*/) 0554 { 0555 if(!m_errbuf.isEmpty()) { 0556 KMessageBox::information(parentWidget(), i18n("<strong>Error:</strong><p>") + m_errbuf, i18n("Grep Tool Error")); 0557 m_errbuf.clear(); 0558 } 0559 else { 0560 finish(); 0561 } 0562 } 0563 0564 void FindFilesDialog::finish() 0565 { 0566 if(m_proc) { 0567 m_proc->kill(); 0568 m_proc->disconnect(); 0569 m_proc->deleteLater(); 0570 m_proc = Q_NULLPTR; 0571 } 0572 m_buf += '\n'; 0573 // we process all the remaining output 0574 processOutput(true); 0575 0576 if (shouldRestart()) { 0577 startGrep(); 0578 } 0579 else { 0580 updateLists(); 0581 0582 resultbox->unsetCursor(); 0583 clear_button->setEnabled(resultbox->count() > 0); 0584 search_button->setText(i18n("&Search")); 0585 slotPatternTextChanged(pattern_combo->lineEdit()->text()); 0586 } 0587 } 0588 0589 void FindFilesDialog::updateLists() 0590 { 0591 updateListItems(pattern_combo); 0592 if(m_mode == KileGrep::Directory) { 0593 updateListItems(dir_combo->comboBox()); 0594 } 0595 } 0596 0597 ///////////////////// build commands ///////////////////// 0598 0599 QString FindFilesDialog::getPattern() 0600 { 0601 QString pattern; 0602 int template_mode = template_combo->currentIndex(); 0603 if (template_mode < KileGrep::tmEnv) { 0604 pattern = template_edit->text(); 0605 if (pattern.isEmpty()) { 0606 pattern = pattern_combo->currentText(); 0607 } 0608 else { 0609 pattern.replace("%s", pattern_combo->currentText()); 0610 } 0611 } 0612 else { 0613 pattern = m_TemplateList[template_mode]; 0614 if (!pattern_combo->currentText().isEmpty()) { 0615 pattern += pattern_combo->currentText() + "\\}"; 0616 } 0617 } 0618 0619 return pattern; 0620 } 0621 0622 QString FindFilesDialog::getShellPattern() 0623 { 0624 QString pattern = getPattern(); 0625 pattern.replace('\'', "'\\''"); 0626 return KShell::quoteArg(pattern); 0627 } 0628 0629 0630 QString FindFilesDialog::buildFilesCommand() 0631 { 0632 QString files, files_temp; 0633 0634 if(filter_combo->currentIndex() >= 0) { 0635 files_temp = m_filterList[filter_combo->currentIndex()]; 0636 } 0637 else { 0638 files_temp = filter_combo->currentText(); 0639 } 0640 0641 QStringList tokens = files_temp.split(' ', Qt::SkipEmptyParts); 0642 QStringList::Iterator it = tokens.begin(); 0643 if (it != tokens.end()) { 0644 files = " '" + (*it) + '\''; 0645 ++it; 0646 } 0647 0648 for(; it != tokens.end(); ++it) { 0649 files = files + " -o -name " + '\'' + (*it) + '\''; 0650 } 0651 0652 QString shell_command; 0653 shell_command += "find "; 0654 shell_command += KShell::quoteArg(dir_combo->url().path()); 0655 shell_command += " \\( -name "; 0656 shell_command += files; 0657 shell_command += " \\)"; 0658 if (!recursive_box->isChecked()) { 0659 shell_command += " -maxdepth 1"; 0660 } 0661 shell_command += " -exec grep -n -E -I -H -e " + getShellPattern() + " {} \\;"; 0662 KILE_DEBUG_MAIN << "shell command" << shell_command; 0663 return shell_command; 0664 } 0665 0666 QString FindFilesDialog::buildProjectCommand() 0667 { 0668 return "grep -n -E -I -H -e " + getShellPattern(); 0669 } 0670 0671 ///////////////////// Search ///////////////////// 0672 0673 void FindFilesDialog::slotSearch() 0674 { 0675 KILE_DEBUG_MAIN << "\tgrep: start slot search" << m_proc; 0676 0677 if (m_proc) { 0678 clearGrepJobs(); 0679 finish(); 0680 return; 0681 } 0682 0683 if (template_combo->currentIndex() < KileGrep::tmEnv && pattern_combo->currentText().isEmpty()) { 0684 return; 0685 } 0686 0687 KILE_DEBUG_MAIN << "\tgrep: start new search"; 0688 QRegularExpression re(getPattern()); 0689 if(!re.isValid()) { 0690 KMessageBox::error(m_ki->mainWindow(), i18n("Invalid regular expression: %1", re.errorString()), i18n("Grep Tool Error")); 0691 return; 0692 } 0693 0694 resultbox->setCursor(QCursor(Qt::WaitCursor)); 0695 search_button->setText(i18n("&Cancel")); 0696 if (template_combo->currentIndex() < KileGrep::tmEnv) { 0697 m_TemplateList[m_lastTemplateIndex] = template_edit->text(); 0698 } 0699 0700 // start grep command 0701 m_grepJobs = (m_mode == KileGrep::Project) ? m_projectfiles.count() : 1; 0702 startGrep(); 0703 } 0704 0705 void FindFilesDialog::slotSearchFor(const QString &pattern) 0706 { 0707 slotClear(); 0708 pattern_combo->setEditText(pattern); 0709 slotSearch(); 0710 } 0711 0712 void FindFilesDialog::slotClear() 0713 { 0714 KILE_DEBUG_MAIN << "\tgrep: slot clear"; 0715 clearGrepJobs(); 0716 finish(); 0717 resultbox->clear(); 0718 } 0719 0720 void FindFilesDialog::slotClose() 0721 { 0722 KILE_DEBUG_MAIN << "\tgrep: slot close"; 0723 clearGrepJobs(); 0724 finish(); 0725 hide(); 0726 deleteLater(); 0727 } 0728 0729 ///////////////////// templates ///////////////////// 0730 0731 void FindFilesDialog::slotPatternTextChanged(const QString &) 0732 { 0733 updateWidgets(); 0734 } 0735 0736 void FindFilesDialog::slotTemplateActivated(int index) 0737 { 0738 if (index < KileGrep::tmEnv) { 0739 m_TemplateList[m_lastTemplateIndex] = template_edit->text(); 0740 template_edit->setText(m_TemplateList[index]); 0741 } 0742 else { 0743 template_edit->setText(QString()); 0744 } 0745 m_lastTemplateIndex = index; 0746 0747 updateWidgets(); 0748 } 0749 0750 void FindFilesDialog::updateWidgets() 0751 { 0752 bool search_state = (m_mode == KileGrep::Directory) || (m_mode == KileGrep::Project && m_projectOpened); 0753 0754 if (template_combo->currentIndex() < KileGrep::tmEnv) { 0755 template_edit->setEnabled(true); 0756 search_button->setEnabled(search_state && !pattern_combo->currentText().isEmpty()); 0757 } 0758 else { 0759 template_edit->setEnabled(false); 0760 search_button->setEnabled(search_state); 0761 } 0762 } 0763 0764 ///////////////////// directory ///////////////////// 0765 0766 void FindFilesDialog::setDirName(const QString &dir) 0767 { 0768 KComboBox *combo = dir_combo->comboBox(); 0769 0770 if (findListItem(combo, dir) < 0) { 0771 combo->addItem(dir); 0772 } 0773 if (combo->itemText(0) != dir) { 0774 slotClear(); 0775 } 0776 } 0777 0778 ///////////////////// filter ///////////////////// 0779 0780 void FindFilesDialog::setFilter(const QString &filter) 0781 { 0782 m_filterList.clear(); 0783 filter_combo->clear(); 0784 if (!filter.isEmpty()) { 0785 QStringList filter_lst = filter.split('\n'); 0786 for (QStringList::Iterator it = filter_lst.begin(); it != filter_lst.end(); ++it) { 0787 QStringList filter_split = (*it).split('|'); 0788 m_filterList.append(filter_split[0]); 0789 filter_combo->addItem(filter_split[1]); 0790 } 0791 } 0792 } 0793 0794 void FindFilesDialog::appendFilter(const QString &name, const QString &filter) 0795 { 0796 filter_combo->addItem(name); 0797 m_filterList.append(filter); 0798 } 0799 0800 ///////////////////// template ///////////////////// 0801 0802 void FindFilesDialog::appendTemplate(const QString &name, const QString ®exp) 0803 { 0804 template_combo->addItem(name); 0805 m_TemplateList.append(regexp); 0806 } 0807 0808 void FindFilesDialog::clearTemplates() 0809 { 0810 template_combo->clear(); 0811 m_TemplateList.clear(); 0812 } 0813 0814 ///////////////////// KComboBox ///////////////////// 0815 0816 QStringList FindFilesDialog::getListItems(KComboBox *combo) 0817 { 0818 QStringList list; 0819 for (int i = 0; i < combo->count() && i < KILEGREP_MAX; ++i) { 0820 list.append(combo->itemText(i)); 0821 } 0822 return list; 0823 } 0824 0825 int FindFilesDialog::findListItem(KComboBox *combo, const QString &s) 0826 { 0827 for (int i = 0; i < combo->count(); ++i) { 0828 if (combo->itemText(i) == s) { 0829 return i; 0830 } 0831 } 0832 return -1; 0833 } 0834 0835 void FindFilesDialog::updateListItems(KComboBox *combo) 0836 { 0837 QString s = combo->currentText(); 0838 if (s.isEmpty()) { 0839 return; 0840 } 0841 0842 int index = findListItem(combo, s); 0843 if (index > 0) { // combo already contains s 0844 combo->removeItem(index); // remove this item 0845 } 0846 else { 0847 if (index == -1) { // combo doesn't contain s 0848 if (combo->count() >= KILEGREP_MAX) { 0849 combo->removeItem(combo->count() - 1); // remove last item 0850 } 0851 } 0852 } 0853 0854 if(index != 0) { 0855 combo->insertItem(0, s); // insert this item as first item 0856 combo->setCurrentIndex(0); // and select it 0857 } 0858 } 0859 0860 ///////////////////// template ///////////////////// 0861 0862 QString FindFilesDialog::getCommandList(KileDocument::CmdAttribute attrtype) 0863 { 0864 QStringList cmdlist; 0865 QStringList::ConstIterator it; 0866 0867 // get info about user-defined references 0868 KileDocument::LatexCommands *cmd = m_ki->latexCommands(); 0869 cmd->commandList(cmdlist, attrtype, true); 0870 0871 // build list of references 0872 QString commands; 0873 for (it = cmdlist.constBegin(); it != cmdlist.constEnd(); ++it) { 0874 commands += '|' + (*it).mid(1); 0875 } 0876 return commands; 0877 } 0878 0879 }