kate Library API Documentation

kategrepdialog.cpp

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00003 Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org> 00004 Copyright (C) 2001, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include "kategrepdialog.h" 00022 #include "katemainwindow.h" 00023 00024 #include <qobject.h> 00025 #include <qlayout.h> 00026 #include <qlineedit.h> 00027 #include <qlabel.h> 00028 #include <qcombobox.h> 00029 #include <qcheckbox.h> 00030 #include <qevent.h> 00031 #include <qlistbox.h> 00032 #include <qregexp.h> 00033 #include <qwhatsthis.h> 00034 #include <qcursor.h> 00035 00036 #include <kapplication.h> 00037 #include <kaccelmanager.h> 00038 #include <kbuttonbox.h> 00039 #include <kfiledialog.h> 00040 #include <kprocess.h> 00041 #include <kapplication.h> 00042 #include <klocale.h> 00043 #include <kiconloader.h> 00044 #include <kmessagebox.h> 00045 #include <kpushbutton.h> 00046 #include <kurlrequester.h> 00047 #include <kurlcompletion.h> 00048 #include <kcombobox.h> 00049 #include <klineedit.h> 00050 00051 const char *template_desc[] = { 00052 "normal", 00053 "assignment", 00054 "->MEMBER(", 00055 "class::MEMBER(", 00056 "OBJECT->member(", 00057 0 00058 }; 00059 00060 const char *strTemplate[] = { 00061 "%s", 00062 "\\<%s\\>[\t ]*=[^=]", 00063 "\\->[\\t ]*\\<%s\\>[\\t ]*(", 00064 "[a-z0-9_$]\\+[\\t ]*::[\\t ]*\\<%s\\>[\\t ]*(", 00065 "\\<%s\\>[\\t ]*\\->[\\t ]*[a-z0-9_$]\\+[\\t ]*(", 00066 0 00067 }; 00068 00069 00070 GrepTool::GrepTool(KateMainWindow *parent, const char *name) 00071 : QWidget(parent, name/*, false*/), childproc(0) 00072 { 00073 setCaption(i18n("Find in Files")); 00074 config = KGlobal::config(); 00075 config->setGroup("GrepTool"); 00076 lastSearchItems = config->readListEntry("LastSearchItems"); 00077 lastSearchPaths = config->readListEntry("LastSearchPaths"); 00078 00079 QGridLayout *layout = new QGridLayout(this, 6, 3, 4, 4); 00080 layout->setColStretch(0, 10); 00081 layout->addColSpacing(1, 10); 00082 layout->setColStretch(1, 0); 00083 layout->setColStretch(2, 1); 00084 layout->setRowStretch(1, 0); 00085 layout->setRowStretch(2, 10); 00086 layout->setRowStretch(4, 0); 00087 00088 QGridLayout *loInput = new QGridLayout(4, 2, 4); 00089 layout->addLayout(loInput, 0, 0); 00090 loInput->setColStretch(0, 0); 00091 loInput->setColStretch(1, 20); 00092 00093 QLabel *lPattern = new QLabel(i18n("Pattern:"), this); 00094 lPattern->setFixedSize(lPattern->sizeHint()); 00095 loInput->addWidget(lPattern, 0, 0, AlignRight | AlignVCenter); 00096 00097 QBoxLayout *loPattern = new QHBoxLayout( 4 ); 00098 loInput->addLayout( loPattern, 0, 1 ); 00099 cmbPattern = new QComboBox(true, this); 00100 cmbPattern->insertStringList(lastSearchItems); 00101 cmbPattern->setEditText(QString::null); 00102 cmbPattern->setInsertionPolicy(QComboBox::NoInsertion); 00103 lPattern->setBuddy(cmbPattern); 00104 cmbPattern->setFocus(); 00105 cmbPattern->setMinimumSize(cmbPattern->sizeHint()); 00106 loPattern->addWidget( cmbPattern ); 00107 00108 cbCasesensitive = new QCheckBox(i18n("Case sensitive"), this); 00109 cbCasesensitive->setMinimumWidth(cbCasesensitive->sizeHint().width()); 00110 cbCasesensitive->setChecked(config->readBoolEntry("CaseSensitive", true)); 00111 loPattern->addWidget(cbCasesensitive); 00112 00113 cbRegex = new QCheckBox( i18n("Regular expression"), this ); 00114 cbRegex->setMinimumWidth( cbRegex->sizeHint().width() ); 00115 cbRegex->setChecked( config->readBoolEntry( "Regex", true ) ); 00116 loPattern->addWidget( cbRegex ); 00117 loPattern->setStretchFactor( cmbPattern, 100 ); 00118 00119 QLabel *lTemplate = new QLabel(i18n("Template:"), this); 00120 lTemplate->setFixedSize(lTemplate->sizeHint()); 00121 loInput->addWidget(lTemplate, 1, 0, AlignRight | AlignVCenter); 00122 00123 QBoxLayout *loTemplate = new QHBoxLayout(4); 00124 loInput->addLayout(loTemplate, 1, 1); 00125 00126 leTemplate = new QLineEdit(this); 00127 lTemplate->setBuddy(leTemplate); 00128 leTemplate->setText(strTemplate[0]); 00129 leTemplate->setMinimumSize(leTemplate->sizeHint()); 00130 loTemplate->addWidget(leTemplate); 00131 00132 QComboBox *cmbTemplate = new QComboBox(false, this); 00133 cmbTemplate->insertStrList(template_desc); 00134 cmbTemplate->adjustSize(); 00135 cmbTemplate->setFixedSize(cmbTemplate->size()); 00136 loTemplate->addWidget(cmbTemplate); 00137 00138 QLabel *lFiles = new QLabel(i18n("Files:"), this); 00139 lFiles->setFixedSize(lFiles->sizeHint()); 00140 loInput->addWidget(lFiles, 2, 0, AlignRight | AlignVCenter); 00141 00142 cmbFiles = new QComboBox(true, this); 00143 lFiles->setBuddy(cmbFiles->focusProxy()); 00144 cmbFiles->setMinimumSize(cmbFiles->sizeHint()); 00145 cmbFiles->insertItem("*.h,*.hxx,*.cpp,*.cc,*.C,*.cxx,*.idl,*.c"); 00146 cmbFiles->insertItem("*.cpp,*.cc,*.C,*.cxx,*.c"); 00147 cmbFiles->insertItem("*.h,*.hxx,*.idl"); 00148 cmbFiles->insertItem("*"); 00149 loInput->addWidget(cmbFiles, 2, 1); 00150 00151 QLabel *lDir = new QLabel(i18n("Directory:"), this); 00152 lDir->setFixedSize(lDir->sizeHint()); 00153 loInput->addWidget(lDir, 3, 0, AlignRight | AlignVCenter); 00154 00155 QBoxLayout *loDir = new QHBoxLayout(3); 00156 loInput->addLayout(loDir, 3, 1); 00157 00158 KComboBox* cmbUrl = new KComboBox(true, this); 00159 cmbUrl->setMinimumWidth(80); // make sure that 800x600 res works 00160 cmbDir = new KURLRequester( cmbUrl, this, "dir combo" ); 00161 cmbDir->completionObject()->setMode(KURLCompletion::DirCompletion); 00162 cmbDir->comboBox()->insertStringList(lastSearchPaths); 00163 cmbDir->setMode( KFile::Directory|KFile::LocalOnly ); 00164 loDir->addWidget(cmbDir, 1); 00165 lDir->setBuddy(cmbDir); 00166 00167 cbRecursive = new QCheckBox(i18n("Recursive"), this); 00168 cbRecursive->setMinimumWidth(cbRecursive->sizeHint().width()); 00169 cbRecursive->setChecked(config->readBoolEntry("Recursive", true)); 00170 loDir->addWidget(cbRecursive); 00171 00172 KButtonBox *actionbox = new KButtonBox(this, Qt::Vertical); 00173 layout->addWidget(actionbox, 0, 2); 00174 actionbox->addStretch(); 00175 btnSearch = static_cast<KPushButton*>(actionbox->addButton(KGuiItem(i18n("Find"),"find"))); 00176 btnSearch->setDefault(true); 00177 btnClear = static_cast<KPushButton*>(actionbox->addButton( KStdGuiItem::clear() )); 00178 actionbox->addStretch(); 00179 actionbox->layout(); 00180 00181 lbResult = new QListBox(this); 00182 QFontMetrics rb_fm(lbResult->fontMetrics()); 00183 layout->addMultiCellWidget(lbResult, 2, 2, 0, 2); 00184 00185 layout->activate(); 00186 00187 KAcceleratorManager::manage( this ); 00188 00189 QWhatsThis::add(cmbPattern, 00190 i18n("<p>Enter the expression you want to search for here." 00191 "<p>If 'regular expression' is unchecked, any non-space letters in your " 00192 "expression will be escaped with a backslash character." 00193 "<p>Possible meta characters are:<br>" 00194 "<b>.</b> - Matches any character<br>" 00195 "<b>^</b> - Matches the beginning of a line<br>" 00196 "<b>$</b> - Matches the end of a line<br>" 00197 "<b>\\&lt;</b> - Matches the beginning of a word<br>" 00198 "<b>\\&gt;</b> - Matches the end of a word" 00199 "<p>The following repetition operators exist:<br>" 00200 "<b>?</b> - The preceding item is matched at most once<br>" 00201 "<b>*</b> - The preceding item is matched zero or more times<br>" 00202 "<b>+</b> - The preceding item is matched one or more times<br>" 00203 "<b>{<i>n</i>}</b> - The preceding item is matched exactly <i>n</i> times<br>" 00204 "<b>{<i>n</i>,}</b> - The preceding item is matched <i>n</i> or more times<br>" 00205 "<b>{,<i>n</i>}</b> - The preceding item is matched at most <i>n</i> times<br>" 00206 "<b>{<i>n</i>,<i>m</i>}</b> - The preceding item is matched at least <i>n</i>, " 00207 "but at most <i>m</i> times." 00208 "<p>Furthermore, backreferences to bracketed subexpressions are available " 00209 "via the notation <code>\\#</code>." 00210 "<p>See the grep(1) documentation for the full documentation." 00211 )); 00212 QWhatsThis::add(cmbFiles, 00213 i18n("Enter the file name pattern of the files to search here.\n" 00214 "You may give several patterns separated by commas.")); 00215 QWhatsThis::add(leTemplate, 00216 i18n("You can choose a template for the pattern from the combo box\n" 00217 "and edit it here. The string %s in the template is replaced\n" 00218 "by the pattern input field, resulting in the regular expression\n" 00219 "to search for.")); 00220 QWhatsThis::add(cmbDir, 00221 i18n("Enter the directory which contains the files you want to search in.")); 00222 QWhatsThis::add(cbRecursive, 00223 i18n("Check this box to search in all subdirectories.")); 00224 QWhatsThis::add(cbCasesensitive, 00225 i18n("If this option is enabled (the default), the search will be case sensitive.")); 00226 QWhatsThis::add( cbRegex, i18n( 00227 "<p>If this is enabled, your pattern will be passed unmodified to " 00228 "<em>grep(1)</em>. Otherwise, all characters that are not letters will be " 00229 "escaped using a backslash character to prevent grep from interpreting " 00230 "them as part of the expression.") ); 00231 QWhatsThis::add(lbResult, 00232 i18n("The results of the grep run are listed here. Select a\n" 00233 "filename/line number combination and press Enter or doubleclick\n" 00234 "on the item to show the respective line in the editor.")); 00235 00236 // event filter, do something relevant for RETURN 00237 cmbPattern->installEventFilter( this ); 00238 leTemplate->installEventFilter( this ); 00239 cmbPattern->installEventFilter( this ); 00240 cmbFiles->installEventFilter( this ); 00241 cmbDir->comboBox()->installEventFilter( this ); 00242 00243 connect( cmbTemplate, SIGNAL(activated(int)), 00244 SLOT(templateActivated(int)) ); 00245 connect( lbResult, SIGNAL(selected(const QString&)), 00246 SLOT(itemSelected(const QString&)) ); 00247 connect( btnSearch, SIGNAL(clicked()), 00248 SLOT(slotSearch()) ); 00249 connect( btnClear, SIGNAL(clicked()), 00250 SLOT(slotClear()) ); 00251 connect( cmbPattern->lineEdit(), SIGNAL(textChanged ( const QString & )), 00252 SLOT( patternTextChanged( const QString & ))); 00253 00254 patternTextChanged( cmbPattern->lineEdit()->text()); 00255 } 00256 00257 00258 GrepTool::~GrepTool() 00259 { 00260 delete childproc; 00261 } 00262 00263 void GrepTool::patternTextChanged( const QString & _text) 00264 { 00265 btnSearch->setEnabled( !_text.isEmpty() ); 00266 } 00267 00268 void GrepTool::templateActivated(int index) 00269 { 00270 leTemplate->setText(strTemplate[index]); 00271 } 00272 00273 void GrepTool::itemSelected(const QString& item) 00274 { 00275 int pos; 00276 QString filename, linenumber; 00277 00278 QString str = item; 00279 if ( (pos = str.find(':')) != -1) 00280 { 00281 filename = str.left(pos); 00282 str = str.mid(pos+1); 00283 if ( (pos = str.find(':')) != -1) 00284 { 00285 filename = m_workingDir + QDir::separator() + filename; 00286 linenumber = str.left(pos); 00287 emit itemSelected(filename,linenumber.toInt()-1); 00288 } 00289 } 00290 } 00291 00292 void GrepTool::processOutput() 00293 { 00294 int pos; 00295 while ( (pos = buf.find('\n')) != -1) 00296 { 00297 QString item = buf.mid(2,pos-2); 00298 if (!item.isEmpty()) 00299 lbResult->insertItem(item); 00300 buf = buf.mid(pos+1); 00301 } 00302 kapp->processEvents(); 00303 } 00304 00305 void GrepTool::slotSearch() 00306 { 00307 if ( cmbPattern->currentText().isEmpty() ) 00308 { 00309 cmbPattern->setFocus(); 00310 return; 00311 } 00312 00313 if ( cmbDir->url().isEmpty() || ! QDir(cmbDir->url()).exists() ) 00314 { 00315 cmbDir->setFocus(); 00316 return; 00317 } 00318 00319 if ( ! leTemplate->text().contains("%s") ) 00320 { 00321 leTemplate->setFocus(); 00322 return; 00323 } 00324 00325 if ( childproc && childproc->isRunning() ) 00326 { 00327 childproc->kill(); 00328 return; 00329 } 00330 00331 slotClear (); 00332 00333 m_workingDir = cmbDir->url(); 00334 00335 QString s = cmbPattern->currentText(); 00336 if ( ! cbRegex->isChecked() ) 00337 s.replace( QRegExp( "([^\\w'])" ), "\\\\1" ); 00338 QString pattern = leTemplate->text(); 00339 pattern.replace( "%s", s ); 00340 00341 childproc = new KProcess(); 00342 childproc->setWorkingDirectory( m_workingDir ); 00343 *childproc << "find" << "."; 00344 if (!cbRecursive->isChecked()) 00345 *childproc << "-maxdepth" << "1"; 00346 if (!cmbFiles->currentText().isEmpty() ) 00347 { 00348 QStringList files = QStringList::split ( ",", cmbFiles->currentText(), FALSE ); 00349 *childproc << "(" << "-false"; 00350 for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it ) 00351 *childproc << "-o" << "-name" << (*it); 00352 *childproc << ")"; 00353 } 00354 *childproc << "-exec" << "grep"; 00355 if (!cbCasesensitive->isChecked()) 00356 *childproc << "-i"; 00357 *childproc << "-n" << "-e" << pattern << "{}"; 00358 *childproc << "/dev/null"; //trick to have grep always display the filename 00359 *childproc << ";"; 00360 00361 connect( childproc, SIGNAL(processExited(KProcess *)), 00362 SLOT(childExited()) ); 00363 connect( childproc, SIGNAL(receivedStdout(KProcess *, char *, int)), 00364 SLOT(receivedOutput(KProcess *, char *, int)) ); 00365 connect( childproc, SIGNAL(receivedStderr(KProcess *, char *, int)), 00366 SLOT(receivedErrOutput(KProcess *, char *, int)) ); 00367 00368 // actually it should be checked whether the process was started successfully 00369 lbResult->setCursor( QCursor(Qt::WaitCursor) ); 00370 btnClear->setEnabled( false ); 00371 btnSearch->setGuiItem( KGuiItem(i18n("Cancel"), "button_cancel")); 00372 childproc->start(KProcess::NotifyOnExit, KProcess::AllOutput); 00373 } 00374 00375 void GrepTool::slotSearchFor(const QString &pattern) 00376 { 00377 slotClear(); 00378 cmbPattern->setEditText(pattern); 00379 slotSearch(); 00380 } 00381 00382 void GrepTool::finish() 00383 { 00384 btnSearch->setEnabled( !cmbPattern->lineEdit()->text().isEmpty() ); 00385 00386 buf += '\n'; 00387 processOutput(); 00388 delete childproc; 00389 childproc = 0; 00390 00391 config->setGroup("GrepTool"); 00392 00393 if (lastSearchItems.contains(cmbPattern->currentText()) == 0) 00394 { 00395 cmbPattern->insertItem(cmbPattern->currentText(), 0); 00396 lastSearchItems.prepend(cmbPattern->currentText()); 00397 if (lastSearchItems.count() > 10) { 00398 lastSearchItems.remove(lastSearchItems.fromLast()); 00399 cmbPattern->removeItem(cmbPattern->count() - 1); 00400 } 00401 config->writeEntry("LastSearchItems", lastSearchItems); 00402 } 00403 00404 if (lastSearchPaths.contains(cmbDir->url()) == 0) 00405 { 00406 cmbDir->comboBox()->insertItem(cmbDir->url(), 0); 00407 lastSearchPaths.prepend(cmbDir->url()); 00408 if (lastSearchPaths.count() > 10) 00409 { 00410 lastSearchPaths.remove(lastSearchPaths.fromLast()); 00411 cmbDir->comboBox()->removeItem(cmbDir->comboBox()->count() - 1); 00412 } 00413 config->writeEntry("LastSearchPaths", lastSearchPaths); 00414 } 00415 config->writeEntry("Recursive", cbRecursive->isChecked()); 00416 config->writeEntry("CaseSensitive", cbCasesensitive->isChecked()); 00417 config->writeEntry( "Regex", cbRegex->isChecked() ); 00418 } 00419 00420 void GrepTool::slotCancel() 00421 { 00422 finish(); 00423 } 00424 00425 void GrepTool::childExited() 00426 { 00427 // int status = childproc->exitStatus(); 00428 lbResult->unsetCursor(); 00429 btnClear->setEnabled( true ); 00430 btnSearch->setGuiItem( KGuiItem(i18n("Find"), "find") ); 00431 00432 if ( ! errbuf.isEmpty() ) 00433 { 00434 KMessageBox::information( parentWidget(), i18n("<strong>Error:</strong><p>") + errbuf, i18n("Grep Tool Error") ); 00435 errbuf.truncate(0); 00436 } 00437 else 00438 finish(); 00439 } 00440 00441 void GrepTool::receivedOutput(KProcess */*proc*/, char *buffer, int buflen) 00442 { 00443 buf += QCString(buffer, buflen+1); 00444 processOutput(); 00445 } 00446 00447 void GrepTool::receivedErrOutput(KProcess */*proc*/, char *buffer, int buflen) 00448 { 00449 errbuf += QCString( buffer, buflen + 1 ); 00450 } 00451 00452 void GrepTool::slotClear() 00453 { 00454 finish(); 00455 lbResult->clear(); 00456 } 00457 00458 void GrepTool::updateDirName(const QString &dir) 00459 { 00460 if (m_lastUpdatedDir != dir) 00461 { 00462 setDirName (dir); 00463 m_lastUpdatedDir = dir; 00464 } 00465 } 00466 00467 void GrepTool::setDirName(const QString &dir){ 00468 cmbDir->setURL(dir); 00469 } 00470 00471 bool GrepTool::eventFilter( QObject *o, QEvent *e ) 00472 { 00473 if ( e->type() == QEvent::KeyPress && ( 00474 ((QKeyEvent*)e)->key() == Qt::Key_Return || 00475 ((QKeyEvent*)e)->key() == Qt::Key_Enter ) ) 00476 { 00477 slotSearch(); 00478 return true; 00479 } 00480 00481 return QWidget::eventFilter( o, e ); 00482 } 00483 00484 #include "kategrepdialog.moc"
KDE Logo
This file is part of the documentation for kate Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 13 21:47:01 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003