summaryrefslogtreecommitdiffstats
path: root/parts/grepview
diff options
context:
space:
mode:
Diffstat (limited to 'parts/grepview')
-rw-r--r--parts/grepview/Makefile.am19
-rw-r--r--parts/grepview/README.dox12
-rw-r--r--parts/grepview/grepdlg.cpp381
-rw-r--r--parts/grepview/grepdlg.h104
-rw-r--r--parts/grepview/grepviewpart.cpp150
-rw-r--r--parts/grepview/grepviewpart.h50
-rw-r--r--parts/grepview/grepviewwidget.cpp535
-rw-r--r--parts/grepview/grepviewwidget.h111
-rw-r--r--parts/grepview/kdevgrepview.desktop86
-rw-r--r--parts/grepview/kdevgrepview.rc9
10 files changed, 1457 insertions, 0 deletions
diff --git a/parts/grepview/Makefile.am b/parts/grepview/Makefile.am
new file mode 100644
index 00000000..49f3c202
--- /dev/null
+++ b/parts/grepview/Makefile.am
@@ -0,0 +1,19 @@
+# Here resides the grep view part.
+
+INCLUDES = -I$(top_srcdir)/lib/interfaces -I$(top_srcdir)/lib/util \
+ -I$(top_srcdir)/lib/widgets $(all_includes)
+
+kde_module_LTLIBRARIES = libkdevgrepview.la
+libkdevgrepview_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN)
+libkdevgrepview_la_LIBADD = $(top_builddir)/lib/libkdevelop.la \
+ $(top_builddir)/lib/widgets/libkdevwidgets.la $(LIB_KHTML)
+
+libkdevgrepview_la_SOURCES = grepviewpart.cpp grepviewwidget.cpp grepdlg.cpp
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = kdevgrepview.desktop
+
+rcdir = $(kde_datadir)/kdevgrepview
+rc_DATA = kdevgrepview.rc
diff --git a/parts/grepview/README.dox b/parts/grepview/README.dox
new file mode 100644
index 00000000..d5e9130a
--- /dev/null
+++ b/parts/grepview/README.dox
@@ -0,0 +1,12 @@
+/** \class GrepViewPart
+Integrates "find|grep" in KDevelop - allows fast searching of multiple files using patterns or regular expressions.
+
+\authors <a href="mailto:bernd AT kdevelop.org">Bernd Gehrmann</a>
+
+\maintainer <a href="mailto:jens.dagerbo AT swipnet.se">Jens Dagerbo</a> aka teatime
+
+\feature grep works on editor context menu
+
+\bug bugs in <a href="http://bugs.kde.org/buglist.cgi?product=kdevelop&component=grep%20frontend&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=Bug+Number">Grep Frontend component at Bugzilla database</a>
+
+*/
diff --git a/parts/grepview/grepdlg.cpp b/parts/grepview/grepdlg.cpp
new file mode 100644
index 00000000..9c62510e
--- /dev/null
+++ b/parts/grepview/grepdlg.cpp
@@ -0,0 +1,381 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann and the KDevelop Team *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "grepdlg.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+#include <qhbox.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+#include <qstringlist.h>
+#include <kfiledialog.h>
+#include <kbuttonbox.h>
+#include <kpushbutton.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <qlabel.h>
+#include <kcombobox.h>
+#include <kurlcompletion.h>
+#include <kurlrequester.h>
+#include <kstdguiitem.h>
+#include <kparts/part.h>
+#include <kdevpartcontroller.h>
+#include <klineedit.h>
+
+#include "grepviewpart.h"
+
+
+const char *template_desc[] = {
+ "verbatim",
+ "assignment",
+ "->MEMBER(",
+ "class::MEMBER(",
+ "OBJECT->member(",
+ 0
+};
+
+const char *template_str[] = {
+ "%s",
+ "\\<%s\\>[\\t ]*=[^=]",
+ "\\->[\\t ]*\\<%s\\>[\\t ]*\\(",
+ "[a-z0-9_$]+[\\t ]*::[\\t ]*\\<%s\\>[\\t ]*\\(",
+ "\\<%s\\>[\\t ]*\\->[\\t ]*[a-z0-9_$]+[\\t ]*\\(",
+ 0
+};
+
+const char *filepatterns[] = {
+ "*.h,*.hxx,*.hpp,*.hh,*.h++,*.H,*.tlh,*.cpp,*.cc,*.C,*.c++,*.cxx,*.ocl,*.inl,*.idl,*.c,*.m,*.mm,*.M",
+ "*.cpp,*.cc,*.C,*.c++,*.cxx,*.ocl,*.inl,*.c,*.m,*.mm,*.M",
+ "*.h,*.hxx,*.hpp,*.hh,*.h++,*.H,*.tlh,*.idl",
+ "*.adb",
+ "*.cs",
+ "*.f",
+ "*.html,*.htm",
+ "*.hs",
+ "*.java",
+ "*.js",
+ "*.php,*.php3,*.php4",
+ "*.pl",
+ "*.pp,*.pas",
+ "*.py",
+ "*.js,*.css,*.yml,*.rb,*.rhtml,*.html.erb,*.rjs,*.js.rjs,*.rxml,*.xml.builder",
+ "CMakeLists.txt,*.cmake",
+ "*",
+ 0
+};
+
+
+GrepDialog::GrepDialog( GrepViewPart * part, QWidget *parent, const char *name )
+ : QDialog(parent, name, false), m_part( part )
+{
+ setCaption(i18n("Find in Files"));
+
+ config = GrepViewFactory::instance()->config();
+ config->setGroup("GrepDialog");
+
+ QGridLayout *layout = new QGridLayout(this, 9, 2, 10, 4);
+ layout->setColStretch(0, 0);
+ layout->setColStretch(1, 20);
+
+ QLabel *pattern_label = new QLabel(i18n("&Pattern:"), this);
+ layout->addWidget(pattern_label, 0, 0, AlignRight | AlignVCenter);
+
+ pattern_combo = new KHistoryCombo(true, this);
+ pattern_label->setBuddy(pattern_combo);
+ pattern_combo->setFocus();
+ pattern_combo->setHistoryItems(config->readListEntry("LastSearchItems"), true);
+ pattern_combo->setInsertionPolicy(QComboBox::NoInsertion);
+ layout->addWidget(pattern_combo, 0, 1);
+
+ QLabel *template_label = new QLabel(i18n("&Template:"), this);
+ layout->addWidget(template_label, 1, 0, AlignRight | AlignVCenter);
+
+ QBoxLayout *template_layout = new QHBoxLayout(4);
+ layout->addLayout(template_layout, 1, 1);
+
+ template_edit = new KLineEdit(this);
+ template_label->setBuddy(template_edit);
+ template_edit->setText(template_str[0]);
+ template_layout->addWidget(template_edit, 1);
+
+ KComboBox *template_combo = new KComboBox(false, this);
+ template_combo->insertStrList(template_desc);
+ template_layout->addWidget(template_combo, 0);
+
+ QBoxLayout *search_opts_layout = new QHBoxLayout(15);
+ layout->addLayout(search_opts_layout, 2, 1);
+
+ regexp_box = new QCheckBox(i18n("&Regular Expression"), this);
+ regexp_box->setChecked(config->readBoolEntry("regexp", false ));
+ search_opts_layout->addWidget(regexp_box);
+
+ case_sens_box = new QCheckBox(i18n("C&ase sensitive"), this);
+ case_sens_box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ case_sens_box->setChecked(config->readBoolEntry("case_sens", true));
+ search_opts_layout->addWidget(case_sens_box);
+
+ QLabel *dir_label = new QLabel(i18n("&Directory:"), this);
+ layout->addWidget(dir_label, 3, 0, AlignRight | AlignVCenter);
+
+ QBoxLayout *dir_layout = new QHBoxLayout(4);
+ layout->addLayout(dir_layout, 3, 1);
+
+ dir_combo = new KComboBox( true, this );
+ dir_combo->insertStringList(config->readPathListEntry("LastSearchPaths"));
+ dir_combo->setInsertionPolicy(QComboBox::NoInsertion);
+ dir_combo->setEditText(QDir::homeDirPath());
+
+ url_requester = new KURLRequester( dir_combo, this );
+ url_requester->completionObject()->setMode(KURLCompletion::DirCompletion);
+ url_requester->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+
+ dir_label->setBuddy( url_requester );
+ dir_combo->setMinimumWidth(dir_combo->fontMetrics().maxWidth()*25);
+ dir_layout->addWidget( url_requester, 10 );
+
+ synch_button = new KPushButton( this );
+ QIconSet set = SmallIconSet( "dirsynch" );
+ QPixmap pix = set.pixmap( QIconSet::Small, QIconSet::Normal );
+ synch_button->setFixedSize( pix.width()+8, pix.height()+8 );
+ synch_button->setIconSet( set );
+ synch_button->setAccel( QKeySequence( "Alt+y") );
+ QToolTip::add( synch_button, i18n("Set directory to that of the current file (Alt+Y)") );
+ dir_layout->addWidget( synch_button );
+
+ QBoxLayout *dir_opts_layout = new QHBoxLayout(15);
+ layout->addLayout(dir_opts_layout, 4, 1);
+
+ recursive_box = new QCheckBox(i18n("Rec&ursive"), this);
+ recursive_box->setChecked(config->readBoolEntry("recursive", true));
+ dir_opts_layout->addWidget(recursive_box);
+
+ use_project_box = new QCheckBox(i18n("Limit search to &project files"), this);
+ use_project_box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ use_project_box->setChecked(config->readBoolEntry("search_project_files", true));
+ dir_opts_layout->addWidget(use_project_box);
+
+ QLabel *files_label = new QLabel(i18n("&Files:"), this);
+ layout->addWidget(files_label, 5, 0, AlignRight | AlignVCenter);
+
+ files_combo = new KComboBox(true, this);
+ files_label->setBuddy(files_combo->focusProxy());
+ files_combo->insertStrList(filepatterns);
+ layout->addWidget(files_combo, 5, 1);
+
+ QLabel *exclude_label = new QLabel(i18n("&Exclude:"), this);
+ layout->addWidget(exclude_label, 6, 0, AlignRight | AlignVCenter);
+
+ QStringList exclude_list = config->readListEntry("exclude_patterns");
+ exclude_combo = new KComboBox(true, this);
+ exclude_label->setBuddy(files_combo->focusProxy());
+ if (exclude_list.count()) {
+ exclude_combo->insertStringList(exclude_list);
+ }
+ else
+ {
+ exclude_combo->insertItem("/CVS/,/SCCS/,/\\.svn/,/_darcs/");
+ exclude_combo->insertItem("");
+ }
+ layout->addWidget(exclude_combo, 6, 1);
+
+ QBoxLayout *other_opts_layout = new QHBoxLayout(15);
+ layout->addLayout(other_opts_layout, 7, 1);
+
+ keep_output_box = new QCheckBox(i18n("New view"), this);
+ keep_output_box->setChecked(config->readBoolEntry("new_view", true));
+ other_opts_layout->addWidget(keep_output_box);
+
+ no_find_err_box = new QCheckBox(i18n("&Suppress find errors"), this);
+ no_find_err_box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ no_find_err_box->setChecked(config->readBoolEntry("no_find_errs", true));
+ other_opts_layout->addWidget(no_find_err_box);
+
+ QBoxLayout *button_layout = new QHBoxLayout(4);
+ layout->addLayout(button_layout, 8, 1);
+ search_button = new KPushButton(KGuiItem(i18n("Sea&rch"),"grep"), this);
+ search_button->setDefault(true);
+ KPushButton *done_button = new KPushButton(KStdGuiItem::cancel(), this);
+ button_layout->addStretch();
+ button_layout->addWidget(search_button);
+ button_layout->addWidget(done_button);
+
+ resize(sizeHint());
+
+ QWhatsThis::add(pattern_combo,
+ i18n("<qt>Enter the regular expression you want to search for here.<p>"
+ "Possible meta characters are:"
+ "<ul>"
+ "<li><b>.</b> - Matches any character"
+ "<li><b>^</b> - Matches the beginning of a line"
+ "<li><b>$</b> - Matches the end of a line"
+ "<li><b>\\&lt;</b> - Matches the beginning of a word"
+ "<li><b>\\&gt;</b> - Matches the end of a word"
+ "</ul>"
+ "The following repetition operators exist:"
+ "<ul>"
+ "<li><b>?</b> - The preceding item is matched at most once"
+ "<li><b>*</b> - The preceding item is matched zero or more times"
+ "<li><b>+</b> - The preceding item is matched one or more times"
+ "<li><b>{<i>n</i>}</b> - The preceding item is matched exactly <i>n</i> times"
+ "<li><b>{<i>n</i>,}</b> - The preceding item is matched <i>n</i> or more times"
+ "<li><b>{,<i>n</i>}</b> - The preceding item is matched at most <i>n</i> times"
+ "<li><b>{<i>n</i>,<i>m</i>}</b> - The preceding item is matched at least <i>n</i>, "
+ "but at most <i>m</i> times."
+ "</ul>"
+ "Furthermore, backreferences to bracketed subexpressions are "
+ "available via the notation \\<i>n</i>.</qt>"
+ ));
+ QWhatsThis::add(files_combo,
+ i18n("Enter the file name pattern of the files to search here. "
+ "You may give several patterns separated by commas"));
+ QWhatsThis::add(template_edit,
+ i18n("You can choose a template for the pattern from the combo box "
+ "and edit it here. The string %s in the template is replaced "
+ "by the pattern input field, resulting in the regular expression "
+ "to search for."));
+
+ connect( template_combo, SIGNAL(activated(int)),
+ SLOT(templateActivated(int)) );
+ connect( search_button, SIGNAL(clicked()),
+ SLOT(slotSearchClicked()) );
+ connect( done_button, SIGNAL(clicked()),
+ SLOT(hide()) );
+ connect( pattern_combo->lineEdit(), SIGNAL( textChanged ( const QString & ) ),
+ SLOT( slotPatternChanged( const QString & ) ) );
+ connect( synch_button, SIGNAL(clicked()), this, SLOT(slotSynchDirectory()) );
+ slotPatternChanged( pattern_combo->currentText() );
+}
+
+// Returns the contents of a QComboBox as a QStringList
+static QStringList qCombo2StringList( QComboBox* combo )
+{
+ QStringList list;
+ if (!combo)
+ return list;
+ for (int i = 0; i < combo->count(); ++i ) {
+ list << combo->text(i);
+ }
+ return list;
+}
+
+GrepDialog::~GrepDialog()
+{
+ config->setGroup("GrepDialog");
+ // memorize the last patterns and paths
+ config->writeEntry("LastSearchItems", qCombo2StringList(pattern_combo));
+ config->writePathEntry("LastSearchPaths", qCombo2StringList(dir_combo));
+ config->writeEntry("regexp", regexp_box->isChecked());
+ config->writeEntry("recursive", recursive_box->isChecked());
+ config->writeEntry("search_project_files", use_project_box->isChecked());
+ config->writeEntry("case_sens", case_sens_box->isChecked());
+ config->writeEntry("new_view", keep_output_box->isChecked());
+ config->writeEntry("no_find_errs", no_find_err_box->isChecked());
+ config->writeEntry("exclude_patterns", qCombo2StringList(exclude_combo));
+}
+
+void GrepDialog::slotPatternChanged( const QString & _text )
+{
+ search_button->setEnabled( !_text.isEmpty() );
+}
+
+void GrepDialog::templateActivated(int index)
+{
+ template_edit->setText(template_str[index]);
+}
+
+// Find out whether the string s is already contained in combo
+static bool qComboContains( const QString& s, QComboBox* combo )
+{
+ if (!combo)
+ return false;
+ for (int i = 0; i < combo->count(); ++i ) {
+ if (combo->text(i) == s) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void GrepDialog::slotSearchClicked()
+{
+ if (pattern_combo->currentText().isEmpty()) {
+ KMessageBox::sorry(this, i18n("Please enter a search pattern"));
+ pattern_combo->setFocus();
+ return;
+ }
+ // add the last patterns and paths to the combo
+ if (!qComboContains(pattern_combo->currentText(), pattern_combo)) {
+ pattern_combo->addToHistory(pattern_combo->currentText());
+ }
+ if (pattern_combo->count() > 15) {
+ pattern_combo->removeFromHistory(pattern_combo->text(15));
+ }
+ if (!qComboContains(exclude_combo->currentText(), exclude_combo)) {
+ exclude_combo->insertItem(exclude_combo->currentText(), 0);
+ }
+ if (exclude_combo->count() > 15) {
+ exclude_combo->removeItem(15);
+ }
+ if (!qComboContains(dir_combo->currentText(), dir_combo)) {
+ dir_combo->insertItem(dir_combo->currentText(), 0);
+ }
+ if (dir_combo->count() > 15) {
+ dir_combo->removeItem(15);
+ }
+
+ emit searchClicked();
+ hide();
+}
+
+void GrepDialog::show()
+{
+ // not beautiful, but works with all window
+ // managers and Qt versions
+ if (isVisible())
+ hide();
+// QDialog::hide();
+ QDialog::show();
+ pattern_combo->setFocus();
+}
+
+void GrepDialog::hide()
+{
+ pattern_combo->setFocus();
+ QDialog::hide();
+}
+
+void GrepDialog::slotSynchDirectory( )
+{
+ KParts::ReadOnlyPart * part = dynamic_cast<KParts::ReadOnlyPart*>( m_part->partController()->activePart() );
+ if ( part )
+ {
+ KURL url = part->url();
+ if ( url.isLocalFile() )
+ {
+ dir_combo->setEditText( url.upURL().path( +1 ) );
+ }
+ }
+}
+
+void GrepDialog::setEnableProjectBox(bool enable)
+{
+ use_project_box->setEnabled(enable);
+ if (!enable) use_project_box->setChecked(false);
+}
+
+#include "grepdlg.moc"
diff --git a/parts/grepview/grepdlg.h b/parts/grepview/grepdlg.h
new file mode 100644
index 00000000..c24332bd
--- /dev/null
+++ b/parts/grepview/grepdlg.h
@@ -0,0 +1,104 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann and the KDevelop Team *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _GREPDLG_H_
+#define _GREPDLG_H_
+
+#include <qdialog.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+
+
+class KConfig;
+class KURLRequester;
+class QPushButton;
+class GrepViewPart;
+class KLineEdit;
+
+class GrepDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ GrepDialog( GrepViewPart * part, QWidget *parent=0, const char *name=0 );
+ ~GrepDialog();
+
+ void setPattern(const QString &pattern)
+ { pattern_combo->setEditText(pattern); }
+ void setDirectory(const QString &dir)
+ { dir_combo->setEditText(dir); }
+ void setEnableProjectBox(bool enable);
+
+ QString patternString() const
+ { return pattern_combo->currentText(); }
+ QString templateString() const
+ { return template_edit->text(); }
+ QString filesString() const
+ { return files_combo->currentText(); }
+ QString excludeString() const
+ { return exclude_combo->currentText(); }
+ QString directoryString() const
+ { return dir_combo->currentText(); }
+
+ bool useProjectFilesFlag() const
+ { return use_project_box->isChecked(); }
+ bool regexpFlag() const
+ { return regexp_box->isChecked(); }
+ bool recursiveFlag() const
+ { return recursive_box->isChecked(); }
+ bool noFindErrorsFlag() const
+ { return no_find_err_box->isChecked(); }
+ bool caseSensitiveFlag() const
+ { return case_sens_box->isChecked(); }
+ bool keepOutputFlag() const
+ { return keep_output_box->isChecked(); }
+
+ void show();
+ void hide();
+
+signals:
+ void searchClicked();
+
+private slots:
+ void templateActivated(int index);
+ void slotSearchClicked();
+ void slotPatternChanged( const QString &);
+ void slotSynchDirectory();
+
+private:
+ KLineEdit *template_edit;
+ KHistoryCombo *pattern_combo;
+ KComboBox *files_combo;
+ KComboBox *exclude_combo;
+ KComboBox * dir_combo;
+ KURLRequester * url_requester;
+
+ QCheckBox *regexp_box;
+ QCheckBox *recursive_box;
+ QCheckBox *use_project_box;
+ QCheckBox *no_find_err_box;
+ QCheckBox *case_sens_box;
+ QCheckBox *keep_output_box;
+ KConfig* config;
+ QPushButton *search_button;
+ QPushButton *synch_button;
+ GrepViewPart * m_part;
+};
+
+
+#endif
+
+
+
+
+
diff --git a/parts/grepview/grepviewpart.cpp b/parts/grepview/grepviewpart.cpp
new file mode 100644
index 00000000..7b1f75d9
--- /dev/null
+++ b/parts/grepview/grepviewpart.cpp
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "grepviewpart.h"
+
+#include <qpopupmenu.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <kprocess.h>
+#include <kstringhandler.h>
+#include <ktexteditor/document.h>
+
+#include "kdevcore.h"
+#include "kdevpartcontroller.h"
+#include "kdevmainwindow.h"
+#include "kdevplugininfo.h"
+#include "kdeveditorutil.h"
+#include "grepviewwidget.h"
+
+static const KDevPluginInfo data("kdevgrepview");
+
+K_EXPORT_COMPONENT_FACTORY(libkdevgrepview, GrepViewFactory(data))
+
+GrepViewPart::GrepViewPart( QObject *parent, const char *name, const QStringList & )
+ : KDevPlugin( &data, parent, name ? name : "GrepViewPart" )
+{
+ setInstance(GrepViewFactory::instance());
+
+ setXMLFile("kdevgrepview.rc");
+
+ connect( core(), SIGNAL(stopButtonClicked(KDevPlugin*)),
+ this, SLOT(stopButtonClicked(KDevPlugin*)) );
+ connect( core(), SIGNAL(projectOpened()), this, SLOT(projectOpened()) );
+ connect( core(), SIGNAL(projectClosed()), this, SLOT(projectClosed()) );
+ connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)),
+ this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
+
+ m_widget = new GrepViewWidget(this);
+ m_widget->setIcon(SmallIcon("grep"));
+ m_widget->setCaption(i18n("Grep Output"));
+ QWhatsThis::add(m_widget, i18n("<b>Find in files</b><p>"
+ "This window contains the output of a grep "
+ "command. Clicking on an item in the list "
+ "will automatically open the corresponding "
+ "source file and set the cursor to the line "
+ "with the match."));
+
+ mainWindow()->embedOutputView(m_widget, i18n("Find in Files"), i18n("Output of the grep command"));
+
+ KAction *action;
+
+ action = new KAction(i18n("Find in Fi&les..."), "grep", CTRL+ALT+Key_F,
+ this, SLOT(slotGrep()),
+ actionCollection(), "edit_grep");
+ action->setToolTip( i18n("Search for expressions over several files") );
+ action->setWhatsThis( i18n("<b>Find in files</b><p>"
+ "Opens the 'Find in files' dialog. There you "
+ "can enter a regular expression which is then "
+ "searched for within all files in the directories "
+ "you specify. Matches will be displayed, you "
+ "can switch to a match directly.") );
+}
+
+
+GrepViewPart::~GrepViewPart()
+{
+ if ( m_widget )
+ mainWindow()->removeView( m_widget );
+ delete m_widget;
+}
+
+
+void GrepViewPart::stopButtonClicked(KDevPlugin* which)
+{
+ if ( which != 0 && which != this )
+ return;
+ kdDebug(9001) << "GrepViewPart::stopButtonClicked()" << endl;
+ m_widget->killJob( SIGHUP );
+}
+
+
+void GrepViewPart::projectOpened()
+{
+ kdDebug(9001) << "GrepViewPart::projectOpened()" << endl;
+ m_widget->projectChanged(project());
+}
+
+
+void GrepViewPart::projectClosed()
+{
+ m_widget->projectChanged(0);
+}
+
+
+void GrepViewPart::contextMenu(QPopupMenu *popup, const Context *context)
+{
+ kdDebug(9001) << "context in grepview" << endl;
+ if (!context->hasType( Context::EditorContext ))
+ return;
+
+ const EditorContext *econtext = static_cast<const EditorContext*>(context);
+ QString ident = econtext->currentWord();
+ if (!ident.isEmpty()) {
+ m_popupstr = ident;
+ QString squeezed = KStringHandler::csqueeze(ident, 30);
+ int id = popup->insertItem( i18n("Grep: %1").arg(squeezed),
+ this, SLOT(slotContextGrep()) );
+ popup->setWhatsThis(id, i18n("<b>Grep</b><p>Opens the find in files dialog "
+ "and sets the pattern to the text under the cursor."));
+ popup->insertSeparator();
+ }
+}
+
+
+void GrepViewPart::slotGrep()
+{
+ if ( !m_widget->isRunning() )
+ {
+ QString contextString = KDevEditorUtil::currentSelection( dynamic_cast<KTextEditor::Document*>( partController()->activePart() ) );
+ if ( contextString.isEmpty() )
+ {
+ contextString = KDevEditorUtil::currentWord( dynamic_cast<KTextEditor::Document*>( partController()->activePart() ) );
+ }
+ m_widget->showDialogWithPattern( contextString );
+ }
+}
+
+
+void GrepViewPart::slotContextGrep()
+{
+ if ( !m_widget->isRunning() )
+ {
+ m_widget->showDialogWithPattern(m_popupstr);
+ }
+}
+
+#include "grepviewpart.moc"
diff --git a/parts/grepview/grepviewpart.h b/parts/grepview/grepviewpart.h
new file mode 100644
index 00000000..c6031a3b
--- /dev/null
+++ b/parts/grepview/grepviewpart.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _GREPVIEWPART_H_
+#define _GREPVIEWPART_H_
+
+#include <qguardedptr.h>
+#include <kdevgenericfactory.h>
+#include "kdevplugin.h"
+
+class KDialogBase;
+class QPopupMenu;
+class Context;
+class GrepViewWidget;
+
+
+class GrepViewPart : public KDevPlugin
+{
+ Q_OBJECT
+
+public:
+ GrepViewPart( QObject *parent, const char *name, const QStringList & );
+ ~GrepViewPart();
+
+private slots:
+ void stopButtonClicked(KDevPlugin *which);
+ void projectOpened();
+ void projectClosed();
+ void contextMenu(QPopupMenu *popup, const Context *context);
+
+ void slotGrep();
+ void slotContextGrep();
+
+private:
+ QGuardedPtr<GrepViewWidget> m_widget;
+ QString m_popupstr;
+ friend class GrepViewWidget;
+};
+
+typedef KDevGenericFactory<GrepViewPart> GrepViewFactory;
+
+#endif
diff --git a/parts/grepview/grepviewwidget.cpp b/parts/grepview/grepviewwidget.cpp
new file mode 100644
index 00000000..326e2897
--- /dev/null
+++ b/parts/grepview/grepviewwidget.cpp
@@ -0,0 +1,535 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qdir.h>
+#include <qlayout.h>
+#include <qregexp.h>
+#include <qpainter.h>
+#include <qtoolbutton.h>
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <kparts/part.h>
+#include <ktexteditor/selectioninterface.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <ktabwidget.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+using namespace KTextEditor;
+
+#include "kdevcore.h"
+#include "kdevproject.h"
+#include "kdevmainwindow.h"
+#include "kdevpartcontroller.h"
+
+#include "grepdlg.h"
+#include "grepviewpart.h"
+#include "grepviewwidget.h"
+
+
+class GrepListBoxItem : public ProcessListBoxItem
+{
+public:
+ GrepListBoxItem(const QString &fileName, const QString &lineNumber, const QString &text, bool showFilename);
+ QString filename()
+ { return fileName; }
+ int linenumber()
+ { return lineNumber.toInt(); }
+ virtual bool isCustomItem();
+
+private:
+ virtual void paint(QPainter *p);
+ QString fileName, lineNumber, text;
+ bool show;
+};
+
+
+GrepListBoxItem::GrepListBoxItem(const QString &fileName, const QString &lineNumber, const QString &text, bool showFilename)
+ : ProcessListBoxItem( QString::null, Normal),
+ fileName(fileName), lineNumber(lineNumber), text(text.stripWhiteSpace()),
+ show(showFilename)
+{
+ this->text.replace( QChar('\t'), QString(" ") );
+}
+
+
+bool GrepListBoxItem::isCustomItem()
+{
+ return true;
+}
+
+
+void GrepListBoxItem::paint(QPainter *p)
+{
+ QColor base, dim, result, bkground;
+ if (listBox()) {
+ const QColorGroup& group = listBox()->palette().active();
+ if (isSelected()) {
+ bkground = group.button();
+ base = group.buttonText();
+ }
+ else
+ {
+ bkground = group.base();
+ base = group.text();
+ }
+ dim = blend(base, bkground);
+ result = group.link();
+ }
+ else
+ {
+ base = Qt::black;
+ dim = Qt::darkGreen;
+ result = Qt::blue;
+ if (isSelected())
+ bkground = Qt::lightGray;
+ else
+ bkground = Qt::white;
+ }
+ QFontMetrics fm = p->fontMetrics();
+ QString stx = lineNumber + ": ";
+ int y = fm.ascent()+fm.leading()/2;
+ int x = 3;
+ p->fillRect(p->window(), QBrush(bkground));
+ if (show)
+ {
+ p->setPen(dim);
+ p->drawText(x, y, fileName);
+ x += fm.width(fileName);
+ }
+ else
+ {
+ p->setPen(base);
+ QFont font1(p->font());
+ QFont font2(font1);
+ font2.setBold(true);
+ p->setFont(font2);
+ p->drawText(x, y, stx);
+ p->setFont(font1);
+ x += fm.width(stx);
+
+ p->setPen(result);
+ p->drawText(x, y, text);
+ }
+}
+
+
+GrepViewWidget::GrepViewWidget(GrepViewPart *part) : QWidget(0, "grepview widget")
+{
+ m_layout = new QHBoxLayout(this, 0, -1, "greplayout");
+
+ m_tabWidget = new KTabWidget(this);
+
+ m_layout->add(m_tabWidget);
+
+ m_curOutput = new GrepViewProcessWidget(m_tabWidget);
+
+ m_tabWidget->addTab(m_curOutput, i18n("Search Results"));
+
+ grepdlg = new GrepDialog( part, this, "grep widget");
+ connect( grepdlg, SIGNAL(searchClicked()), this, SLOT(searchActivated()) );
+ connect( m_curOutput, SIGNAL(processExited(KProcess* )), this, SLOT(slotSearchProcessExited()) );
+
+ connect( m_tabWidget, SIGNAL(currentChanged(QWidget*)), this, SLOT(slotOutputTabChanged()) );
+
+ connect( m_curOutput, SIGNAL(clicked(QListBoxItem*)),
+ this, SLOT(slotExecuted(QListBoxItem*)) );
+ connect( m_curOutput, SIGNAL(returnPressed(QListBoxItem*)),
+ this, SLOT(slotExecuted(QListBoxItem*)) );
+
+
+ connect( m_curOutput, SIGNAL(contextMenuRequested( QListBoxItem*, const QPoint&)), this, SLOT(popupMenu(QListBoxItem*, const QPoint&)));
+ m_part = part;
+
+ m_closeButton = new QToolButton(m_tabWidget);//@todo change text/icon
+ m_closeButton->setIconSet(SmallIconSet("tab_remove"));
+ m_closeButton->setEnabled(false);
+
+ connect (m_closeButton, SIGNAL(clicked()), this, SLOT(slotCloseCurrentOutput()));
+ m_tabWidget->setCornerWidget(m_closeButton);
+}
+
+
+GrepViewWidget::~GrepViewWidget()
+{}
+
+
+void GrepViewWidget::showDialog()
+{
+ // Get the selected text if there is any
+ KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(m_part->partController()->activePart());
+ if (ro_part)
+ {
+ SelectionInterface *selectIface = dynamic_cast<SelectionInterface*>(ro_part);
+ if(selectIface && selectIface->hasSelection())
+ {
+ QString selText = selectIface->selection();
+ if(!selText.contains('\n'))
+ {
+ grepdlg->setPattern(selText);
+ }
+ }
+ }
+ // Determine if we have a list of project files
+ KDevProject *openProject = m_part->project();
+ if (openProject)
+ {
+ grepdlg->setEnableProjectBox(!openProject->allFiles().isEmpty());
+ }
+ else
+ {
+ grepdlg->setEnableProjectBox(false);
+ }
+ grepdlg->show();
+}
+
+// @todo - put this somewhere common - or just use Qt if possible
+static QString escape(const QString &str)
+{
+ QString escaped("[]{}()\\^$?.+-*|");
+ QString res;
+
+ for (uint i=0; i < str.length(); ++i)
+ {
+ if (escaped.find(str[i]) != -1)
+ res += "\\";
+ res += str[i];
+ }
+
+ return res;
+}
+
+
+void GrepViewWidget::showDialogWithPattern(QString pattern)
+{
+ // Before anything, this removes line feeds from the
+ // beginning and the end.
+ int len = pattern.length();
+ if (len > 0 && pattern[0] == '\n')
+ {
+ pattern.remove(0, 1);
+ len--;
+ }
+ if (len > 0 && pattern[len-1] == '\n')
+ pattern.truncate(len-1);
+ grepdlg->setPattern( pattern );
+
+ // Determine if we have a list of project files
+ KDevProject *openProject = m_part->project();
+ if (openProject)
+ {
+ grepdlg->setEnableProjectBox(!openProject->allFiles().isEmpty());
+ }
+ else
+ {
+ grepdlg->setEnableProjectBox(false);
+ }
+ grepdlg->show();
+}
+
+
+void GrepViewWidget::searchActivated()
+{
+ if ( grepdlg->keepOutputFlag() )
+ slotKeepOutput();
+
+ m_tabWidget->showPage( m_curOutput );
+
+ m_curOutput->setLastFileName("");
+ m_curOutput->setMatchCount( 0 );
+
+ QString command, files;
+
+ // waba: code below breaks on filenames containing a ',' !!!
+ QStringList filelist = QStringList::split(",", grepdlg->filesString());
+
+ if (grepdlg->useProjectFilesFlag())
+ {
+ KDevProject *openProject = m_part->project();
+ if (openProject)
+ {
+ QString tmpFilePath;
+ QStringList projectFiles = openProject->allFiles();
+ if (!projectFiles.isEmpty())
+ {
+ tmpFilePath = openProject->projectDirectory() + QChar(QDir::separator()) + ".grep.tmp";
+ QString dir = grepdlg->directoryString(), file;
+ QValueList<QRegExp> regExpList;
+
+ if (dir.endsWith(QChar(QDir::separator())))
+ dir.truncate(dir.length() - 1);
+
+ if (!filelist.isEmpty())
+ {
+ for (QStringList::Iterator it = filelist.begin(); it != filelist.end(); ++it)
+ regExpList.append(QRegExp(*it, true, true));
+ }
+
+ m_tempFile.setName(tmpFilePath);
+ if (m_tempFile.open(IO_WriteOnly))
+ {
+ QTextStream out(&m_tempFile);
+ for (QStringList::Iterator it = projectFiles.begin(); it != projectFiles.end(); ++it)
+ {
+ file = QDir::cleanDirPath(openProject->projectDirectory() + QChar(QDir::separator()) + *it);
+
+ QFileInfo info(file);
+ if (grepdlg->recursiveFlag() && !info.dirPath(true).startsWith(dir)) continue;
+ if (!grepdlg->recursiveFlag() && info.dirPath(true) != dir) continue;
+
+ bool matchOne = regExpList.count() == 0;
+ for (QValueList<QRegExp>::Iterator it2 = regExpList.begin(); it2 != regExpList.end() && !matchOne; ++it2)
+ matchOne = (*it2).exactMatch(file);
+
+ if (matchOne)
+ out << KShellProcess::quote(file) + "\n";
+ }
+
+ m_tempFile.close();
+ }
+ else
+ {
+ KMessageBox::error(this, i18n("Unable to create a temporary file for search."));
+ return;
+ }
+ }
+
+ command = "cat ";
+ command += tmpFilePath.replace(' ', "\\ ");
+ }
+ }
+ else
+ {
+ if (!filelist.isEmpty())
+ {
+ QStringList::Iterator it(filelist.begin());
+ files = KShellProcess::quote(*it);
+ ++it;
+ for (; it != filelist.end(); ++it)
+ files += " -o -name " + KShellProcess::quote(*it);
+ }
+
+ QString filepattern = "find ";
+ filepattern += KShellProcess::quote(grepdlg->directoryString());
+ if (!grepdlg->recursiveFlag())
+ filepattern += " -maxdepth 1";
+ filepattern += " \\( -name ";
+ filepattern += files;
+ filepattern += " \\) -print -follow";
+ if (grepdlg->noFindErrorsFlag())
+ filepattern += " 2>/dev/null";
+
+ command = filepattern + " " ;
+ }
+
+ QStringList excludelist = QStringList::split(",", grepdlg->excludeString());
+ if (!excludelist.isEmpty())
+ {
+ QStringList::Iterator it(excludelist.begin());
+ command += "| grep -v ";
+ for (; it != excludelist.end(); ++it)
+ command += "-e " + KShellProcess::quote(*it) + " ";
+ }
+
+ if (!grepdlg->useProjectFilesFlag())
+ {
+ // quote spaces in filenames going to xargs
+ command += "| sed \"s/ /\\\\\\ /g\" ";
+ }
+
+ command += "| xargs " ;
+
+#ifndef USE_SOLARIS
+ command += "egrep -H -n -s ";
+#else
+ // -H reported as not being available on Solaris,
+ // but we're buggy without it on Linux.
+ command += "egrep -n ";
+#endif
+
+ if (!grepdlg->caseSensitiveFlag())
+ {
+ command += "-i ";
+ }
+ command += "-e ";
+
+ m_lastPattern = grepdlg->patternString();
+ QString pattern = grepdlg->templateString();
+ if (grepdlg->regexpFlag())
+ pattern.replace(QRegExp("%s"), grepdlg->patternString());
+ else
+ pattern.replace(QRegExp("%s"), escape( grepdlg->patternString() ) );
+ command += KShellProcess::quote(pattern);
+ m_curOutput->startJob("", command);
+
+ m_part->mainWindow()->raiseView(this);
+ m_part->core()->running(m_part, true);
+}
+
+
+void GrepViewWidget::slotExecuted(QListBoxItem* item)
+{
+ ProcessListBoxItem *i = static_cast<ProcessListBoxItem*>(item);
+ if (!i || !i->isCustomItem())
+ return;
+
+ GrepListBoxItem *gi = static_cast<GrepListBoxItem*>(i);
+ m_part->partController()->editDocument( KURL( gi->filename() ), gi->linenumber()-1 );
+}
+
+
+void GrepViewProcessWidget::insertStdoutLine(const QCString &line)
+{
+ int pos;
+ QString filename, linenumber, rest;
+
+ QString str;
+ if( !grepbuf.isEmpty() )
+ {
+ str = QString::fromLocal8Bit( grepbuf+line );
+ grepbuf.truncate( 0 );
+ }else
+ {
+ str = QString::fromLocal8Bit( line );
+ }
+ if ( (pos = str.find(':')) != -1)
+ {
+ filename = str.left(pos);
+ str.remove( 0, pos+1 );
+ if ( ( pos = str.find(':') ) != -1)
+ {
+ linenumber = str.left(pos);
+ str.remove( 0, pos+1 );
+ // filename will be displayed only once
+ // selecting filename will display line 1 of file,
+ // otherwise, line of requested search
+ if ( _lastfilename != filename )
+ {
+ _lastfilename = filename;
+ insertItem(new GrepListBoxItem(filename, "0", str, true));
+ insertItem(new GrepListBoxItem(filename, linenumber, str, false));
+ }
+ else
+ {
+ insertItem(new GrepListBoxItem(filename, linenumber, str, false));
+ }
+ maybeScrollToBottom();
+ }
+ m_matchCount++;
+ }
+}
+
+
+void GrepViewWidget::projectChanged(KDevProject *project)
+{
+ QString dir = project? project->projectDirectory() : QDir::homeDirPath();
+ grepdlg->setDirectory(dir);
+}
+
+void GrepViewWidget::popupMenu(QListBoxItem*, const QPoint& p)
+{
+ if(m_curOutput->isRunning()) return;
+
+ KPopupMenu rmbMenu;
+
+ if(KAction *findAction = m_part->actionCollection()->action("edit_grep"))
+ {
+ rmbMenu.insertTitle(i18n("Find in Files"));
+ findAction->plug(&rmbMenu);
+ rmbMenu.exec(p);
+ }
+}
+
+void GrepViewWidget::slotKeepOutput( )
+{
+ if ( m_lastPattern == QString::null ) return;
+
+ m_tabWidget->changeTab(m_curOutput, m_lastPattern);
+
+ m_curOutput = new GrepViewProcessWidget(m_tabWidget);
+ m_tabWidget->insertTab(m_curOutput, i18n("Search Results"), 0);
+
+ connect( m_curOutput, SIGNAL(clicked(QListBoxItem*)), this, SLOT(slotExecuted(QListBoxItem*)) );
+ connect( m_curOutput, SIGNAL(returnPressed(QListBoxItem*)), this, SLOT(slotExecuted(QListBoxItem*)) );
+ connect( m_curOutput, SIGNAL(processExited(KProcess* )), this, SLOT(slotSearchProcessExited()) );
+ connect( m_curOutput, SIGNAL(contextMenuRequested( QListBoxItem*, const QPoint&)), this, SLOT(popupMenu(QListBoxItem*, const QPoint&)));
+}
+
+void GrepViewWidget::slotCloseCurrentOutput( )
+{
+ ProcessWidget* pw = static_cast<ProcessWidget*>(m_tabWidget->currentPage());
+ if (pw == m_curOutput)
+ return;
+
+ m_tabWidget->removePage(pw);
+ delete pw;
+
+ if (m_tabWidget->count() == 1)
+ m_closeButton->setEnabled( false );
+}
+
+void GrepViewWidget::killJob( int signo )
+{
+ m_curOutput->killJob( signo );
+
+ if (!m_tempFile.name().isEmpty() && m_tempFile.exists())
+ m_tempFile.remove();
+}
+
+bool GrepViewWidget::isRunning( ) const
+{
+ return m_curOutput->isRunning();
+}
+
+void GrepViewWidget::slotOutputTabChanged( )
+{
+ ProcessWidget* pw = static_cast<ProcessWidget*>(m_tabWidget->currentPage());
+ if (pw == m_curOutput)
+ m_closeButton->setEnabled( false );
+ else
+ m_closeButton->setEnabled( true );
+}
+
+void GrepViewWidget::slotSearchProcessExited( )
+{
+ m_part->core()->running(m_part, false);
+
+ if (!m_tempFile.name().isEmpty() && m_tempFile.exists())
+ m_tempFile.remove();
+}
+
+void GrepViewProcessWidget::childFinished( bool normal, int status )
+{
+ // When xargs executes grep several times (because the command line
+ // generated would be too large for a single grep) and one of those
+ // sets of files passed to grep does not contain a match, then an
+ // error status of 123 is set by xargs, even if there is a match in
+ // another set of files.
+ // Reset this false status here.
+
+ if (status == 123 && numRows() > 1)
+ status = 0;
+
+ insertItem(new ProcessListBoxItem(i18n("*** %n match found. ***", "*** %n matches found. ***", m_matchCount), ProcessListBoxItem::Diagnostic));
+ maybeScrollToBottom();
+
+ ProcessWidget::childFinished(normal, status);
+}
+
+void GrepViewProcessWidget::addPartialStdoutLine(const QCString & line)
+{
+ grepbuf += line;
+}
+
+
+#include "grepviewwidget.moc"
diff --git a/parts/grepview/grepviewwidget.h b/parts/grepview/grepviewwidget.h
new file mode 100644
index 00000000..bf3fca4b
--- /dev/null
+++ b/parts/grepview/grepviewwidget.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _GREPVIEWWIDGET_H_
+#define _GREPVIEWWIDGET_H_
+
+#include "processwidget.h"
+#include <qwidget.h>
+#include <qfile.h>
+
+class GrepDialog;
+class GrepViewPart;
+class KDevProject;
+class KTabWidget;
+class QHBoxLayout;
+class QToolButton;
+class GrepViewProcessWidget : public ProcessWidget
+{
+ Q_OBJECT
+public:
+ GrepViewProcessWidget(QWidget* parent) : ProcessWidget(parent) {};
+ ~GrepViewProcessWidget(){};
+ void setMatchCount(int newCount)
+ {
+ m_matchCount = newCount;
+ }
+
+ void incrementMatchCount(uint amount = 1)
+ {
+ m_matchCount += amount;
+ }
+
+ void setLastFileName(const QString& lastFileName)
+ {
+ _lastfilename = lastFileName;
+ }
+
+public slots:
+ virtual void insertStdoutLine(const QCString &line);
+ virtual void addPartialStdoutLine( const QCString &line );
+
+protected:
+ virtual void childFinished(bool normal, int status);
+
+private:
+ int m_matchCount;
+ QString _lastfilename;
+ QCString grepbuf;
+};
+
+class GrepViewWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ GrepViewWidget(GrepViewPart *part);
+ ~GrepViewWidget();
+
+ void projectChanged(KDevProject *project);
+ void killJob( int signo = SIGTERM );
+ bool isRunning() const;
+
+public slots:
+ void showDialog();
+ void showDialogWithPattern(QString pattern);
+
+private slots:
+ void searchActivated();
+ /**
+ * If item is a valid result of a search run, it opens the file at the position, where the stuff was found.
+ * @param item item containing filename and linenumber of the file to open.
+ */
+ void slotExecuted(QListBoxItem *item);
+ void popupMenu(QListBoxItem*, const QPoint& p);
+ /**
+ * Creates a new tab containing the current output in the main tab and clears the main tab.
+ */
+ void slotKeepOutput();
+ /**
+ * Closes the currently active tab, if it is not the main output.
+ */
+ void slotCloseCurrentOutput();
+ /**
+ * Slot reacting on changes of the active tab, to activate/deactivate the close button,
+ * as the main output tab must not be closed.
+ */
+ void slotOutputTabChanged();
+
+ void slotSearchProcessExited();
+
+private:
+
+ QHBoxLayout* m_layout;
+ KTabWidget* m_tabWidget;
+ GrepViewProcessWidget* m_curOutput;
+ GrepDialog *grepdlg;
+ GrepViewPart *m_part;
+ QToolButton* m_closeButton;
+ QString m_lastPattern;
+ QFile m_tempFile;
+};
+
+#endif
diff --git a/parts/grepview/kdevgrepview.desktop b/parts/grepview/kdevgrepview.desktop
new file mode 100644
index 00000000..41661c73
--- /dev/null
+++ b/parts/grepview/kdevgrepview.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Type=Service
+Exec=blubb
+Comment=Integrates "find|grep" in KDevelop - allows fast searching of multiple files using patterns or regular expressions.
+Comment[ca]=Integra "find|grep" en el KDevelop, permetent la recerca ràpida de diversos fitxers emprant patrons o expressions regulars.
+Comment[da]=Integrerer "find|grep" i KDevelop - tillader hurtig søgning i flere filer ved brug af mønstre eller regulære udtryk.
+Comment[de]=Integration von "find|grep" in KDevelop. - Ermöglicht das schnelle Durchsuchen mehrere Dateien mit Hilfe von Suchmustern und regulären Ausdrücken.
+Comment[el]=Ενσωματώνει τα "find|grep" στο KDevelop - επιτρέπει τη γρήγορη αναζήτηση σε πολλά αρχεία χρησιμοποιώντας μοτίβα ή κανονικές εκφράσεις.
+Comment[es]=Integra «find|grep» en KDevelop, permitiendo la búsqueda rápida de varios archivos utilizando patrones o expresiones regulares.
+Comment[et]=Integreerib KDevelopi programmi "Find|grep", mis lubab mustreid või regulaaravaldisi kasutades kiiresti paljudes failides teksti otsida.
+Comment[eu]="find|grep" KDevelop-en txertatzen du - fitxategi anitzetan eredu edo espresio erregularrak erabiliz bilaketa azkarrak egiteko aukera ematen du.
+Comment[fa]=«find|grep» را در KDevelop مجتمع‌سازی می‌کند. اجازۀ جستجوی سریع پرونده‌های چندگانه را با استفاده از الگوها یا عبارتهای منظم می‌دهد.
+Comment[fr]=Intègre « find|grep » dans KDevelop - permet d'effectuer une recherche rapide dans des fichiers multiples en utilisant des motifs ou des expressions rationnelles.
+Comment[gl]=Integra "find|grep" en KDevelop - permite a procura rápida de varios ficheiros usando patróns ou expresións regulares.
+Comment[hu]=A "find|grep" programok integrálása a KDevelopba - lehetővé teszi szövegek fájlokban való gyors keresését minták és reguláris kifejezések felhasználásával
+Comment[it]=Integra "find|grep" in KDevelop - permette la ricerca rapida di file multipli utilizzando motivi o espressioni regolari.
+Comment[ja]="find|grep" を KDevelop 内に統合し、正規表現やパターンを用いて素早く複数のファイルを検索することを可能にします。
+Comment[ms]=Menggabungkan "find|grep" dalam KDevelop - membenarkan carian pantas beberapa fail menggunakan corak atau regular expression.
+Comment[nds]=Buut "find|grep" na KDevelop in. - Stellt gau Dörsöken vun mehr Dateien mit Söökmustern oder reguleer Utdrück praat.
+Comment[ne]=केडीई विकासमा "find|grep" एकीकरण गर्दछ - जसले नियमित अभिव्यक्ति वा बाँन्की प्रयोग गरेर बहुविध फाइलको छिटो खोजी गर्न अनुमति दिन्छ ।
+Comment[nl]=Integreert "find|grep" in KDevelop - snel zoeken door verschillende bestanden naar patronen of reguliere expressies.
+Comment[pl]=Integracja "find|grep" z KDevelop - pozwala na szybie wyszukiwanie wielu plików przy użyciu wzorców i wyrażeń regularnych.
+Comment[pt]=Integra o "find|grep" no KDevelop - permite a procura rápida em vários ficheiros usando padrões ou expressões regulares.
+Comment[pt_BR]=Integra o "find/grep" no KDevelop - permite busca rápida de múltiplos arquivos usando padrões e expressões regulares.
+Comment[ru]=Интегрирует "find|grep" в KDevelop - позволяет производить быстрый поиск по нескольким файлам с использованием шаблонов или регулярных выражений.
+Comment[sk]=Integruje "find|grep" do Kdevelop - umožní rýchle vyhľadávanie rôznych súborov pomocou vzorov alebo regulárnych výrazov.
+Comment[sr]=Интегрише „find|grep“ у KDevelop — омогућава брзо претраживање више фајлова коришћењем облика имена или регуларних израза.
+Comment[sr@Latn]=Integriše „find|grep“ u KDevelop — omogućava brzo pretraživanje više fajlova korišćenjem oblika imena ili regularnih izraza.
+Comment[sv]=Integrerar "find | grep" med KDevelop - tillåter snabb sökning i flera filer med mönster eller reguljära uttryck.
+Comment[ta]=KDevelopபில் "find|grep" ஒருங்கினை-வடிவங்கள் அல்லது வழக்கமான தொடர்களை பயன்படுத்தி பல்வகை கோப்பினை மிக வேகமாய் தேடலாம்.
+Comment[tg]=Интегралёбии "find|grep" дар KDevelop - бо истифодаи қолиб ё инки баёни ботартиб имкон медиҳад бо якчанд файлҳо ковтуковро барпо намоед.
+Comment[tr]=KDevelop'a "find|grep"i yerleştirir - desen veya düzenli ifadeler kullanılara çoklu dosyalarda hızlı arama sağlar.
+Comment[zh_CN]=在 KDevelop 中集成“查找|grep” - 可以使用模式或正则表达式在多个文件中快速查找。
+Comment[zh_TW]=在 KDevelop 中整合 "find|grep" - 允許使用特定樣式或正規表式示來快速搜尋多個檔案內容。
+Name=KDevGrepView
+Name[da]=KDevelop Grep-visning
+Name[de]=Grep-Ansicht (KDevelop)
+Name[hi]=के-डेव-ग्रेप-व्यू
+Name[nds]=KDevelop-Grepkieker
+Name[pl]=KDevWidokGrep
+Name[sk]=KDev pohľad na grep
+Name[sv]=KDevelop grep-visning
+Name[ta]=KDevGrep காட்சி
+Name[tg]=Намоиши KDevGrep
+Name[tr]=KDevGrepView
+Name[zh_TW]=KDevelop Grep 檢視
+GenericName=Grep Frontend
+GenericName[ca]=Entorn per a grep
+GenericName[da]=Grep-grænseflade
+GenericName[de]=Grep-Ansicht
+GenericName[el]=Πρόγραμμα Grep
+GenericName[es]=Entorno para grep
+GenericName[et]=Programmi grep kasutajaliides
+GenericName[eu]=Grep interfazea
+GenericName[fa]=پایانۀ Grep
+GenericName[fr]=Interface pour Grep
+GenericName[ga]=Comhéadan Grep
+GenericName[gl]=Frontal para Grep
+GenericName[hi]=ग्रेप फ्रन्टएण्ड
+GenericName[hu]=Grafikus felület a Grep-hez
+GenericName[it]=Interfaccia a "grep"
+GenericName[ja]=Grep フロントエンド
+GenericName[ms]=Frontend Grep
+GenericName[nds]=Grep-Böversiet
+GenericName[ne]=ग्रिप फ्रन्टइन्ड
+GenericName[nl]=Grep-frontend
+GenericName[pl]=Interfejs do grepa
+GenericName[pt]=Interface do Grep
+GenericName[pt_BR]=Frontend do Grep
+GenericName[ru]=Интеграция Grep
+GenericName[sk]=Grep rozhranie
+GenericName[sl]=Vmesnik za Grep
+GenericName[sr]=Кориснички интерфејс за grep
+GenericName[sr@Latn]=Korisnički interfejs za grep
+GenericName[sv]=Gränssnitt till grep
+GenericName[ta]=Grep முன் பகுதி
+GenericName[tg]=Интегратсияи Grep
+GenericName[tr]=Grep Önucu
+GenericName[zh_CN]=Grep 前端
+GenericName[zh_TW]=Grep 前端介面
+Icon=find
+ServiceTypes=KDevelop/Plugin
+X-KDE-Library=libkdevgrepview
+X-KDevelop-Version=5
+X-KDevelop-Scope=Global
+X-KDevelop-Properties=FileSearch
diff --git a/parts/grepview/kdevgrepview.rc b/parts/grepview/kdevgrepview.rc
new file mode 100644
index 00000000..80b20389
--- /dev/null
+++ b/parts/grepview/kdevgrepview.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="KDevGrepView" version="1">
+<MenuBar>
+ <Menu name="edit">
+ <Action name="edit_grep" group="kdev_edit_find_merge"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
+