• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kate

kategrepdialog.cpp

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

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kate
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal