• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • app
kategrepdialog.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
3  Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
4  Copyright (C) 2001, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2 as published by the Free Software Foundation.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kategrepdialog.h"
22 #include "katemainwindow.h"
23 
24 #include <tqobject.h>
25 #include <tqlayout.h>
26 #include <tqlabel.h>
27 #include <tqcheckbox.h>
28 #include <tqevent.h>
29 #include <tqlistbox.h>
30 #include <tqregexp.h>
31 #include <tqwhatsthis.h>
32 #include <tqcursor.h>
33 
34 #include <tdeapplication.h>
35 #include <tdeaccelmanager.h>
36 #include <kbuttonbox.h>
37 #include <tdefiledialog.h>
38 #include <kprocess.h>
39 #include <tdeapplication.h>
40 #include <tdelocale.h>
41 #include <kiconloader.h>
42 #include <tdemessagebox.h>
43 #include <kpushbutton.h>
44 #include <kurlrequester.h>
45 #include <kurlcompletion.h>
46 #include <kcombobox.h>
47 #include <klineedit.h>
48 
49 const char *template_desc[] = {
50  "normal",
51  "assignment",
52  "->MEMBER(",
53  "class::MEMBER(",
54  "OBJECT->member(",
55  0
56 };
57 
58 const char *strTemplate[] = {
59  "%s",
60  "\\<%s\\>[\t ]*=[^=]",
61  "\\->[\\t ]*\\<%s\\>[\\t ]*(",
62  "[a-z0-9_$]\\+[\\t ]*::[\\t ]*\\<%s\\>[\\t ]*(",
63  "\\<%s\\>[\\t ]*\\->[\\t ]*[a-z0-9_$]\\+[\\t ]*(",
64  0
65 };
66 
67 
68 GrepTool::GrepTool(TQWidget *parent, const char *name)
69  : TQWidget(parent, name/*, false*/), m_fixFocus(true), childproc(0)
70 {
71  setCaption(i18n("Find in Files"));
72  config = TDEGlobal::config();
73  config->setGroup("GrepTool");
74  lastSearchItems = config->readListEntry("LastSearchItems");
75  lastSearchPaths = config->readListEntry("LastSearchPaths");
76  lastSearchFiles = config->readListEntry("LastSearchFiles");
77 
78  if( lastSearchFiles.isEmpty() )
79  {
80  // if there are no entries, most probably the first Kate start.
81  // Initialize with default values.
82  lastSearchFiles << "*.h,*.hxx,*.cpp,*.cc,*.C,*.cxx,*.idl,*.c"
83  << "*.cpp,*.cc,*.C,*.cxx,*.c"
84  << "*.h,*.hxx,*.idl"
85  << "*";
86  }
87 
88  TQGridLayout *layout = new TQGridLayout(this, 6, 3, 4, 4);
89  layout->setColStretch(0, 10);
90  layout->addColSpacing(1, 10);
91  layout->setColStretch(1, 0);
92  layout->setColStretch(2, 1);
93  layout->setRowStretch(1, 0);
94  layout->setRowStretch(2, 10);
95  layout->setRowStretch(4, 0);
96 
97  TQGridLayout *loInput = new TQGridLayout(4, 2, 4);
98  layout->addLayout(loInput, 0, 0);
99  loInput->setColStretch(0, 0);
100  loInput->setColStretch(1, 20);
101 
102  TQLabel *lPattern = new TQLabel(i18n("Pattern:"), this);
103  lPattern->setFixedSize(lPattern->sizeHint());
104  loInput->addWidget(lPattern, 0, 0, TQt::AlignRight | TQt::AlignVCenter);
105 
106  TQBoxLayout *loPattern = new TQHBoxLayout( 4 );
107  loInput->addLayout( loPattern, 0, 1 );
108  cmbPattern = new KComboBox(true, this);
109  cmbPattern->setDuplicatesEnabled(false);
110  cmbPattern->insertStringList(lastSearchItems);
111  cmbPattern->setEditText(TQString::null);
112  cmbPattern->setInsertionPolicy(TQComboBox::NoInsertion);
113  lPattern->setBuddy(cmbPattern);
114  cmbPattern->setFocus();
115  cmbPattern->setMinimumSize(cmbPattern->sizeHint());
116  loPattern->addWidget( cmbPattern );
117 
118  cbCasesensitive = new TQCheckBox(i18n("Case sensitive"), this);
119  cbCasesensitive->setMinimumWidth(cbCasesensitive->sizeHint().width());
120  cbCasesensitive->setChecked(config->readBoolEntry("CaseSensitive", true));
121  loPattern->addWidget(cbCasesensitive);
122 
123  cbRegex = new TQCheckBox( i18n("Regular expression"), this );
124  cbRegex->setMinimumWidth( cbRegex->sizeHint().width() );
125  cbRegex->setChecked( config->readBoolEntry( "Regex", true ) );
126  loPattern->addWidget( cbRegex );
127  loPattern->setStretchFactor( cmbPattern, 100 );
128 
129  TQLabel *lTemplate = new TQLabel(i18n("Template:"), this);
130  lTemplate->setFixedSize(lTemplate->sizeHint());
131  loInput->addWidget(lTemplate, 1, 0, TQt::AlignRight | TQt::AlignVCenter);
132 
133  TQBoxLayout *loTemplate = new TQHBoxLayout(4);
134  loInput->addLayout(loTemplate, 1, 1);
135 
136  leTemplate = new KLineEdit(this);
137  lTemplate->setBuddy(leTemplate);
138  leTemplate->setText(strTemplate[0]);
139  leTemplate->setMinimumSize(leTemplate->sizeHint());
140  loTemplate->addWidget(leTemplate);
141 
142  KComboBox *cmbTemplate = new KComboBox(false, this);
143  cmbTemplate->insertStrList(template_desc);
144  cmbTemplate->adjustSize();
145  cmbTemplate->setFixedSize(cmbTemplate->size());
146  loTemplate->addWidget(cmbTemplate);
147 
148  TQLabel *lFiles = new TQLabel(i18n("Files:"), this);
149  lFiles->setFixedSize(lFiles->sizeHint());
150  loInput->addWidget(lFiles, 2, 0, TQt::AlignRight | TQt::AlignVCenter);
151 
152  TQBoxLayout *loFiles = new TQHBoxLayout( 2 );
153  loInput->addLayout( loFiles, 2, 1 );
154 
155  cmbFiles = new KComboBox(true, this);
156  lFiles->setBuddy(cmbFiles->focusProxy());
157  cmbFiles->setMinimumSize(cmbFiles->sizeHint());
158  cmbFiles->setInsertionPolicy(TQComboBox::NoInsertion);
159  cmbFiles->setDuplicatesEnabled(false);
160  cmbFiles->insertStringList(lastSearchFiles);
161  loFiles->addWidget(cmbFiles);
162 
163  cbHideErrors = new TQCheckBox( i18n("Hide errors"), this );
164  cbHideErrors->setMinimumWidth( cbHideErrors->sizeHint().width() );
165  cbHideErrors->setChecked( config->readBoolEntry( "HideErrors", false ) );
166  loFiles->addWidget(cbHideErrors);
167  loFiles->setStretchFactor(cmbFiles, 100);
168 
169  TQLabel *lDir = new TQLabel(i18n("Folder:"), this);
170  lDir->setFixedSize(lDir->sizeHint());
171  loInput->addWidget(lDir, 3, 0, TQt::AlignRight | TQt::AlignVCenter);
172 
173  TQBoxLayout *loDir = new TQHBoxLayout(3);
174  loInput->addLayout(loDir, 3, 1);
175 
176  KComboBox* cmbUrl = new KComboBox(true, this);
177  cmbUrl->setMinimumWidth(80); // make sure that 800x600 res works
178  cmbUrl->setDuplicatesEnabled(false);
179  cmbUrl->setInsertionPolicy(TQComboBox::NoInsertion);
180  cmbDir = new KURLRequester( cmbUrl, this, "dir combo" );
181  cmbDir->completionObject()->setMode(KURLCompletion::DirCompletion);
182  cmbDir->comboBox()->insertStringList(lastSearchPaths);
183  cmbDir->setMode( KFile::Directory|KFile::LocalOnly );
184  loDir->addWidget(cmbDir, 1);
185  lDir->setBuddy(cmbDir);
186 
187  cbRecursive = new TQCheckBox(i18n("Recursive"), this);
188  cbRecursive->setMinimumWidth(cbRecursive->sizeHint().width());
189  cbRecursive->setChecked(config->readBoolEntry("Recursive", true));
190  loDir->addWidget(cbRecursive);
191 
192  KButtonBox *actionbox = new KButtonBox(this, TQt::Vertical);
193  layout->addWidget(actionbox, 0, 2);
194  actionbox->addStretch();
195  btnSearch = static_cast<KPushButton*>(actionbox->addButton(KGuiItem(i18n("Find"),"edit-find")));
196  btnSearch->setDefault(true);
197  btnClear = static_cast<KPushButton*>(actionbox->addButton( KStdGuiItem::clear() ));
198  actionbox->addStretch();
199  actionbox->layout();
200 
201  lbResult = new TQListBox(this);
202  TQFontMetrics rb_fm(lbResult->fontMetrics());
203  layout->addMultiCellWidget(lbResult, 2, 2, 0, 2);
204 
205  layout->activate();
206 
207  TDEAcceleratorManager::manage( this );
208 
209  TQWhatsThis::add(lPattern,
210  i18n("<p>Enter the expression you want to search for here."
211  "<p>If 'regular expression' is unchecked, all characters that are not "
212  "letters in your expression will be escaped with a backslash character."
213  "<p>Possible meta characters are:<br>"
214  "<b>.</b> - Matches any character<br>"
215  "<b>^</b> - Matches the beginning of a line<br>"
216  "<b>$</b> - Matches the end of a line<br>"
217  "<b>\\&lt;</b> - Matches the beginning of a word<br>"
218  "<b>\\&gt;</b> - Matches the end of a word"
219  "<p>The following repetition operators exist:<br>"
220  "<b>?</b> - The preceding item is matched at most once<br>"
221  "<b>*</b> - The preceding item is matched zero or more times<br>"
222  "<b>+</b> - The preceding item is matched one or more times<br>"
223  "<b>{<i>n</i>}</b> - The preceding item is matched exactly <i>n</i> times<br>"
224  "<b>{<i>n</i>,}</b> - The preceding item is matched <i>n</i> or more times<br>"
225  "<b>{,<i>n</i>}</b> - The preceding item is matched at most <i>n</i> times<br>"
226  "<b>{<i>n</i>,<i>m</i>}</b> - The preceding item is matched at least <i>n</i>, "
227  "but at most <i>m</i> times."
228  "<p>Furthermore, backreferences to bracketed subexpressions are available "
229  "via the notation <code>\\#</code>."
230  "<p>See the grep(1) documentation for the full documentation."
231  ));
232  TQWhatsThis::add(lFiles,
233  i18n("Enter the file name pattern of the files to search here.\n"
234  "You may give several patterns separated by commas."));
235  TQWhatsThis::add(lTemplate,
236  i18n("You can choose a template for the pattern from the combo box\n"
237  "and edit it here. The string %s in the template is replaced\n"
238  "by the pattern input field, resulting in the regular expression\n"
239  "to search for."));
240  TQWhatsThis::add(lDir,
241  i18n("Enter the folder which contains the files in which you want to search."));
242  TQWhatsThis::add(cbRecursive,
243  i18n("Check this box to search in all subfolders."));
244  TQWhatsThis::add(cbCasesensitive,
245  i18n("If this option is enabled (the default), the search will be case sensitive."));
246  TQWhatsThis::add( cbRegex, i18n(
247  "<p>If this is enabled, your pattern will be passed unmodified to "
248  "<em>grep(1)</em>. Otherwise, all characters that are not letters will be "
249  "escaped using a backslash character to prevent grep from interpreting "
250  "them as part of the expression.") );
251  TQWhatsThis::add(lbResult,
252  i18n("The results of the grep run are listed here. Select a\n"
253  "filename/line number combination and press Enter or doubleclick\n"
254  "on the item to show the respective line in the editor."));
255  TQWhatsThis::add( cbHideErrors, i18n(
256  "<p>If this is checked, the dialog window showing the search errors "
257  "will not be displayed at the end of the search.") );
258 
259  // event filter, do something relevant for RETURN
260  cmbPattern->installEventFilter( this );
261  leTemplate->installEventFilter( this );
262  cmbFiles->installEventFilter( this );
263  cmbDir->comboBox()->installEventFilter( this );
264 
265  connect( cmbTemplate, TQ_SIGNAL(activated(int)),
266  TQ_SLOT(templateActivated(int)) );
267  connect( lbResult, TQ_SIGNAL(selected(const TQString&)),
268  TQ_SLOT(itemSelected(const TQString&)) );
269  connect( btnSearch, TQ_SIGNAL(clicked()),
270  TQ_SLOT(slotSearch()) );
271  connect( btnClear, TQ_SIGNAL(clicked()),
272  TQ_SLOT(slotClear()) );
273  connect( cmbPattern->lineEdit(), TQ_SIGNAL(textChanged ( const TQString & )),
274  TQ_SLOT( patternTextChanged( const TQString & )));
275 
276  patternTextChanged( cmbPattern->lineEdit()->text());
277 }
278 
279 
280 GrepTool::~GrepTool()
281 {
282  delete childproc;
283 }
284 
285 void GrepTool::patternTextChanged( const TQString & _text)
286 {
287  btnSearch->setEnabled( !_text.isEmpty() );
288 }
289 
290 void GrepTool::templateActivated(int index)
291 {
292  leTemplate->setText(strTemplate[index]);
293 }
294 
295 void GrepTool::itemSelected(const TQString& item)
296 {
297  int pos;
298  TQString filename, linenumber;
299 
300  TQString str = item;
301  if ( (pos = str.find(':')) != -1)
302  {
303  filename = str.left(pos);
304  str = str.mid(pos+1);
305  if ( (pos = str.find(':')) != -1)
306  {
307  filename = m_workingDir + TQDir::separator() + filename;
308  linenumber = str.left(pos);
309  emit itemSelected(filename,linenumber.toInt()-1);
310  }
311  }
312 }
313 
314 void GrepTool::processOutput()
315 {
316  int pos;
317  while ( (pos = buf.find('\n')) != -1)
318  {
319  TQString item = buf.mid(2,pos-2);
320  if (!item.isEmpty())
321  lbResult->insertItem(item);
322  buf = buf.mid(pos+1);
323  }
324  kapp->processEvents();
325 }
326 
327 void GrepTool::slotSearch()
328 {
329  if ( cmbPattern->currentText().isEmpty() )
330  {
331  cmbPattern->setFocus();
332  return;
333  }
334 
335  if ( cmbDir->url().isEmpty() || ! TQDir(cmbDir->url()).exists() )
336  {
337  cmbDir->setFocus();
338  KMessageBox::information( this, i18n(
339  "You must enter an existing local folder in the 'Folder' entry."),
340  i18n("Invalid Folder"), "Kate grep tool: invalid folder" );
341  return;
342  }
343 
344  if ( ! leTemplate->text().contains("%s") )
345  {
346  leTemplate->setFocus();
347  return;
348  }
349 
350  if ( childproc && childproc->isRunning() )
351  {
352  childproc->kill();
353  return;
354  }
355 
356  slotClear ();
357 
358  m_workingDir = cmbDir->url();
359 
360  TQString s = cmbPattern->currentText();
361  if ( ! cbRegex->isChecked() )
362  s.replace( TQRegExp( "([^\\w'()<>])" ), "\\\\1" );
363  TQString pattern = leTemplate->text();
364  pattern.replace( "%s", s );
365 
366  childproc = new TDEProcess();
367  childproc->setWorkingDirectory( m_workingDir );
368  *childproc << "find" << ".";
369  if (!cbRecursive->isChecked())
370  *childproc << "-maxdepth" << "1";
371  if (!cmbFiles->currentText().isEmpty() )
372  {
373  TQStringList files = TQStringList::split ( ",", cmbFiles->currentText(), FALSE );
374  *childproc << "(";
375  bool first = true;
376  for ( TQStringList::Iterator it = files.begin(); it != files.end(); ++it )
377  {
378  if (!first)
379  *childproc << "-o";
380  *childproc << "-name" << (*it);
381  first = false;
382  }
383  *childproc << ")";
384  }
385  *childproc << "-exec" << "grep";
386  if (!cbCasesensitive->isChecked())
387  *childproc << "-i";
388  *childproc << "-n" << "-e" << pattern << "{}";
389  *childproc << "/dev/null"; //trick to have grep always display the filename
390  *childproc << ";";
391 
392  connect( childproc, TQ_SIGNAL(processExited(TDEProcess *)),
393  TQ_SLOT(childExited()) );
394  connect( childproc, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)),
395  TQ_SLOT(receivedOutput(TDEProcess *, char *, int)) );
396  connect( childproc, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int)),
397  TQ_SLOT(receivedErrOutput(TDEProcess *, char *, int)) );
398 
399  // actually it should be checked whether the process was started successfully
400  lbResult->setCursor( TQCursor(TQt::WaitCursor) );
401  btnClear->setEnabled( false );
402  btnSearch->setGuiItem( KGuiItem(i18n("Cancel"), "button_cancel"));
403  childproc->start(TDEProcess::NotifyOnExit, TDEProcess::AllOutput);
404 }
405 
406 void GrepTool::slotSearchFor(const TQString &pattern)
407 {
408  slotClear();
409  cmbPattern->setEditText(pattern);
410  slotSearch();
411 }
412 
413 void GrepTool::finish()
414 {
415  btnSearch->setEnabled( !cmbPattern->lineEdit()->text().isEmpty() );
416 
417  buf += '\n';
418  processOutput();
419  delete childproc;
420  childproc = 0;
421 
422  config->setGroup("GrepTool");
423 
424  TQString cmbText = cmbPattern->currentText();
425  bool itemsRemoved = lastSearchItems.remove(cmbText) > 0;
426  lastSearchItems.prepend(cmbText);
427  if (itemsRemoved)
428  {
429  cmbPattern->removeItem(cmbPattern->currentItem());
430  }
431  cmbPattern->insertItem(cmbText, 0);
432  cmbPattern->setCurrentItem(0);
433  if (lastSearchItems.count() > 10) {
434  lastSearchItems.pop_back();
435  cmbPattern->removeItem(cmbPattern->count() - 1);
436  }
437  config->writeEntry("LastSearchItems", lastSearchItems);
438 
439 
440  cmbText = cmbDir->url();
441  itemsRemoved = lastSearchPaths.remove(cmbText) > 0;
442  lastSearchPaths.prepend(cmbText);
443  if (itemsRemoved)
444  {
445  cmbDir->comboBox()->removeItem(cmbDir->comboBox()->currentItem());
446  }
447  cmbDir->comboBox()->insertItem(cmbText, 0);
448  cmbDir->comboBox()->setCurrentItem(0);
449  if (lastSearchPaths.count() > 10)
450  {
451  lastSearchPaths.pop_back();
452  cmbDir->comboBox()->removeItem(cmbDir->comboBox()->count() - 1);
453  }
454  config->writeEntry("LastSearchPaths", lastSearchPaths);
455 
456 
457  cmbText = cmbFiles->currentText();
458  itemsRemoved = lastSearchFiles.remove(cmbText) > 0;
459  lastSearchFiles.prepend(cmbText);
460  if (itemsRemoved)
461  {
462  cmbFiles->removeItem(cmbFiles->currentItem());
463  }
464  cmbFiles->insertItem(cmbText, 0);
465  cmbFiles->setCurrentItem(0);
466  if (lastSearchFiles.count() > 10) {
467  lastSearchFiles.pop_back();
468  cmbFiles->removeItem(cmbFiles->count() - 1);
469  }
470  config->writeEntry("LastSearchFiles", lastSearchFiles);
471 
472  config->writeEntry("Recursive", cbRecursive->isChecked());
473  config->writeEntry("CaseSensitive", cbCasesensitive->isChecked());
474  config->writeEntry("Regex", cbRegex->isChecked());
475  config->writeEntry("HideErrors", cbHideErrors->isChecked());
476 }
477 
478 void GrepTool::slotCancel()
479 {
480  finish();
481 }
482 
483 void GrepTool::childExited()
484 {
485 // int status = childproc->exitStatus();
486  lbResult->unsetCursor();
487  btnClear->setEnabled( true );
488  btnSearch->setGuiItem( KGuiItem(i18n("Find"), "edit-find") );
489 
490  if ( !errbuf.isEmpty())
491  {
492  if (!cbHideErrors->isChecked())
493  {
494  KMessageBox::information( parentWidget(), i18n("<strong>Error:</strong><p>") + errbuf, i18n("Grep Tool Error") );
495  }
496  errbuf.truncate(0);
497  }
498  else
499  finish();
500 }
501 
502 void GrepTool::receivedOutput(TDEProcess */*proc*/, char *buffer, int buflen)
503 {
504  buf += TQCString(buffer, buflen+1);
505  processOutput();
506 }
507 
508 void GrepTool::receivedErrOutput(TDEProcess */*proc*/, char *buffer, int buflen)
509 {
510  errbuf += TQCString( buffer, buflen + 1 );
511 }
512 
513 void GrepTool::slotClear()
514 {
515  finish();
516  lbResult->clear();
517 }
518 
519 void GrepTool::updateDirName(const TQString &dir)
520 {
521  if (m_lastUpdatedDir != dir)
522  {
523  setDirName (dir);
524  m_lastUpdatedDir = dir;
525  }
526 }
527 
528 void GrepTool::setDirName(const TQString &dir){
529  cmbDir->setURL(dir);
530 }
531 
532 bool GrepTool::eventFilter( TQObject *o, TQEvent *e )
533 {
534  if ( e->type() == TQEvent::KeyPress && (
535  ((TQKeyEvent*)e)->key() == TQt::Key_Return ||
536  ((TQKeyEvent*)e)->key() == TQt::Key_Enter ) )
537  {
538  slotSearch();
539  return true;
540  }
541 
542  return TQWidget::eventFilter( o, e );
543 }
544 
545 void GrepTool::focusInEvent ( TQFocusEvent * ev )
546 {
547  TQWidget::focusInEvent(ev);
548  if (m_fixFocus) {
549  m_fixFocus = false;
550  cmbPattern->setFocus();
551  }
552 }
553 
554 void GrepTool::showEvent( TQShowEvent * ev )
555 {
556  TQWidget::showEvent(ev);
557  m_fixFocus = true;
558 }
559 
560 #include "kategrepdialog.moc"

kate

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

kate

Skip menu "kate"
  • kate
  • libkonq
  • twin
  •   lib
Generated for kate by doxygen 1.9.1
This website is maintained by Timothy Pearson.