summaryrefslogtreecommitdiffstats
path: root/parts/outputviews
diff options
context:
space:
mode:
Diffstat (limited to 'parts/outputviews')
-rw-r--r--parts/outputviews/Makefile.am35
-rw-r--r--parts/outputviews/README.dox16
-rw-r--r--parts/outputviews/appoutputviewpart.cpp178
-rw-r--r--parts/outputviews/appoutputviewpart.h56
-rw-r--r--parts/outputviews/appoutputwidget.cpp355
-rw-r--r--parts/outputviews/appoutputwidget.h69
-rw-r--r--parts/outputviews/commandcontinuationfilter.cpp40
-rw-r--r--parts/outputviews/commandcontinuationfilter.h29
-rw-r--r--parts/outputviews/compileerrorfilter.cpp128
-rw-r--r--parts/outputviews/compileerrorfilter.h48
-rw-r--r--parts/outputviews/directorystatusmessagefilter.cpp187
-rw-r--r--parts/outputviews/directorystatusmessagefilter.h39
-rw-r--r--parts/outputviews/filterdlg.ui164
-rw-r--r--parts/outputviews/kdevappoutputview.desktop84
-rw-r--r--parts/outputviews/kdevmakeview.desktop87
-rw-r--r--parts/outputviews/kdevmakeview.rc9
-rw-r--r--parts/outputviews/makeactionfilter.cpp319
-rw-r--r--parts/outputviews/makeactionfilter.h62
-rw-r--r--parts/outputviews/makeitem.cpp166
-rw-r--r--parts/outputviews/makeitem.h164
-rw-r--r--parts/outputviews/makeviewpart.cpp105
-rw-r--r--parts/outputviews/makeviewpart.h46
-rw-r--r--parts/outputviews/makewidget.cpp847
-rw-r--r--parts/outputviews/makewidget.h129
-rw-r--r--parts/outputviews/otherfilter.cpp26
-rw-r--r--parts/outputviews/otherfilter.h34
-rw-r--r--parts/outputviews/outputfilter.cpp24
-rw-r--r--parts/outputviews/outputfilter.h29
-rw-r--r--parts/outputviews/outputviewsfactory.cpp21
-rw-r--r--parts/outputviews/outputviewsfactory.h27
30 files changed, 3523 insertions, 0 deletions
diff --git a/parts/outputviews/Makefile.am b/parts/outputviews/Makefile.am
new file mode 100644
index 00000000..81b7ca4e
--- /dev/null
+++ b/parts/outputviews/Makefile.am
@@ -0,0 +1,35 @@
+# Here reside the output view and make view parts.
+
+INCLUDES = -I$(top_srcdir)/lib/interfaces \
+ -I$(top_srcdir)/lib/interfaces/extensions -I$(top_srcdir)/lib/interfaces/extensions/dcop -I$(top_srcdir)/lib/util \
+ -I$(top_srcdir)/lib/widgets $(all_includes)
+
+kde_module_LTLIBRARIES = libkdevmakeview.la libkdevappview.la
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = kdevappoutputview.desktop kdevmakeview.desktop
+
+rc1dir = $(kde_datadir)/kdevappoutputview
+rc1_DATA = kdevmakeview.rc
+
+rc2dir = $(kde_datadir)/kdevmakeview
+rc2_DATA = kdevmakeview.rc
+
+noinst_HEADERS = filterdlg.h
+
+libkdevmakeview_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN)
+libkdevmakeview_la_LIBADD = $(top_builddir)/lib/widgets/libkdevwidgets.la \
+ $(top_builddir)/lib/interfaces/extensions/dcop/libkdevdcopextensions.la $(top_builddir)/lib/libkdevelop.la \
+ $(LIB_KHTML) $(top_builddir)/lib/interfaces/extensions/libkdevextensions.la
+libkdevmakeview_la_SOURCES = makeviewpart.cpp makewidget.cpp \
+ directorystatusmessagefilter.cpp outputfilter.cpp compileerrorfilter.cpp commandcontinuationfilter.cpp \
+ makeitem.cpp makeactionfilter.cpp otherfilter.cpp
+
+libkdevappview_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN)
+libkdevappview_la_LIBADD = $(top_builddir)/lib/widgets/libkdevwidgets.la \
+ $(top_builddir)/lib/interfaces/extensions/dcop/libkdevdcopextensions.la $(top_builddir)/lib/libkdevelop.la \
+ $(LIB_KHTML) $(top_builddir)/lib/interfaces/extensions/libkdevextensions.la
+libkdevappview_la_SOURCES = appoutputviewpart.cpp appoutputwidget.cpp \
+ filterdlg.ui
diff --git a/parts/outputviews/README.dox b/parts/outputviews/README.dox
new file mode 100644
index 00000000..6e17bea3
--- /dev/null
+++ b/parts/outputviews/README.dox
@@ -0,0 +1,16 @@
+/** \class MakeViewPart
+Two output views: one displays compiler output, the other displays the application output.
+
+\authors <a href="mailto:bernd AT kdevelop.org">Bernd Gehrmann</a>
+
+\feature Auto scroll down
+\feature Auto hide when it's not needed
+\feature Jump to error when clicked
+
+\bug bugs in <a href="http://bugs.kde.org/buglist.cgi?product=kdevelop&component=outputviews&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=Bug+Number">outputviews component at Bugzilla database</a>
+
+\todo Make the contents of the application output copyable.
+
+\faq <b>How does the auto-hide feature work?</b> If there are no compilation errors the output view hides itself (if it was hidden before compilation start) or switches to the previously selected view.
+
+*/
diff --git a/parts/outputviews/appoutputviewpart.cpp b/parts/outputviews/appoutputviewpart.cpp
new file mode 100644
index 00000000..79a62471
--- /dev/null
+++ b/parts/outputviews/appoutputviewpart.cpp
@@ -0,0 +1,178 @@
+/***************************************************************************
+ * Copyright (C) 1999-2002 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 "appoutputviewpart.h"
+
+#include <qwhatsthis.h>
+#include <qdir.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kiconloader.h>
+#include <kparts/part.h>
+#include <kdevgenericfactory.h>
+#include <kdevplugininfo.h>
+#include <kapplication.h>
+
+#include "kdevproject.h"
+#include "kdevcore.h"
+#include "kdevmainwindow.h"
+#include "appoutputwidget.h"
+#include "kdevpartcontroller.h"
+#include "settings.h"
+
+static const KDevPluginInfo data("kdevappoutputview");
+typedef KDevGenericFactory< AppOutputViewPart > AppViewFactory;
+K_EXPORT_COMPONENT_FACTORY( libkdevappview, AppViewFactory( data ) )
+
+AppOutputViewPart::AppOutputViewPart(QObject *parent, const char *name, const QStringList &)
+ : KDevAppFrontend(&data, parent, name ? name : "AppOutputViewPart")
+{
+ setInstance(AppViewFactory::instance());
+
+ m_dcop = new KDevAppFrontendIface(this);
+
+ m_widget = new AppOutputWidget(this);
+ m_widget->setIcon( SmallIcon("openterm") );
+ m_widget->setCaption(i18n("Application Output"));
+ QWhatsThis::add(m_widget, i18n("<b>Application output</b><p>"
+ "The stdout/stderr output window is a replacement for "
+ "terminal-based application communication. Running terminal "
+ "applications use this instead of a terminal window."));
+
+ mainWindow()->embedOutputView(m_widget, i18n("Application"), i18n("Output of the executed user program"));
+ hideView();
+
+ connect( core(), SIGNAL(stopButtonClicked(KDevPlugin*)),
+ this, SLOT(slotStopButtonClicked(KDevPlugin*)) );
+ connect(m_widget, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited()));
+ connect(m_widget, SIGNAL(processExited(KProcess*)), SIGNAL(processExited()));
+}
+
+
+AppOutputViewPart::~AppOutputViewPart()
+{
+ if ( m_widget )
+ mainWindow()->removeView( m_widget );
+ delete m_widget;
+ delete m_dcop;
+}
+
+void AppOutputViewPart::slotStopButtonClicked( KDevPlugin* which )
+{
+ if ( which != 0 && which != this )
+ return;
+ stopApplication();
+}
+
+void AppOutputViewPart::stopApplication()
+{
+ m_widget->killJob();
+
+ core()->running( this, false );
+}
+
+void AppOutputViewPart::slotProcessExited()
+{
+ core()->running( this, false );
+ if ( partController()->activePart() && partController()->activePart()->widget() )
+ partController()->activePart()->widget()->setFocus();
+}
+
+/**
+ * If directory is empty it will use the user's home directory.
+ * If inTerminal is true, the program is started in an external
+ * konsole.
+ */
+void AppOutputViewPart::startAppCommand(const QString &directory, const QString &program, bool inTerminal)
+{
+ QString cmd;
+
+ if (inTerminal) {
+ cmd = Settings::terminalEmulatorName( *kapp->config() );
+ if ( cmd == "konsole" && !directory.isNull() ) { // isn't setting the working directory below enough?
+ // If a directory was specified, use it
+ cmd += QString(" --workdir '%1'").arg(directory);
+ }
+ cmd += " -e /bin/sh -c '";
+ cmd += program;
+ cmd += "; echo \"";
+ cmd += i18n("Press Enter to continue!");
+ cmd += "\";read dummy'";
+ } else
+ cmd = program;
+
+ m_widget->clearViewAndContents();
+
+ if ( directory.isNull() )
+ // use the user's home directory
+ m_widget->startJob(QDir::homeDirPath(), cmd);
+ else
+ // use the supplied directory
+ m_widget->startJob(directory, cmd);
+
+ core()->running( this, true );
+
+ showView();
+ mainWindow()->raiseView(m_widget);
+}
+
+
+bool AppOutputViewPart::isRunning()
+{
+ return m_widget->isRunning();
+}
+
+
+void AppOutputViewPart::insertStdoutLine(const QCString &line)
+{
+ m_widget->insertStdoutLine(line);
+}
+
+
+void AppOutputViewPart::insertStderrLine(const QCString &line)
+{
+ m_widget->insertStderrLine(line);
+}
+
+void AppOutputViewPart::clearView()
+{
+ m_widget->clearViewAndContents();
+}
+
+void AppOutputViewPart::hideView()
+{
+ m_viewIsVisible = false;
+ mainWindow()->setViewAvailable( m_widget, m_viewIsVisible );
+}
+
+void AppOutputViewPart::showView()
+{
+ m_viewIsVisible = true;
+ mainWindow()->setViewAvailable( m_widget, m_viewIsVisible );
+}
+
+bool AppOutputViewPart::isViewVisible()
+{
+ return m_viewIsVisible;
+}
+
+void AppOutputViewPart::addPartialStderrLine(const QCString & line)
+{
+ m_widget->addPartialStderrLine(line);
+}
+
+void AppOutputViewPart::addPartialStdoutLine(const QCString & line)
+{
+ m_widget->addPartialStdoutLine(line);
+}
+
+#include "appoutputviewpart.moc"
diff --git a/parts/outputviews/appoutputviewpart.h b/parts/outputviews/appoutputviewpart.h
new file mode 100644
index 00000000..76d708f9
--- /dev/null
+++ b/parts/outputviews/appoutputviewpart.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * Copyright (C) 1999-2002 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 _APPOUTPUTVIEWSPART_H_
+#define _APPOUTPUTVIEWSPART_H_
+
+#include <qguardedptr.h>
+
+#include "kdevappfrontend.h"
+#include "KDevAppFrontendIface.h"
+
+
+class AppOutputWidget;
+
+class AppOutputViewPart : public KDevAppFrontend
+{
+ Q_OBJECT
+
+public:
+ AppOutputViewPart( QObject *parent, const char *name, const QStringList & );
+ ~AppOutputViewPart();
+
+ virtual void startAppCommand(const QString &directory, const QString &command, bool inTerminal);
+ virtual void stopApplication();
+ virtual bool isRunning();
+ virtual void insertStdoutLine(const QCString &line);
+ virtual void insertStderrLine(const QCString &line);
+ virtual void addPartialStdoutLine(const QCString &line);
+ virtual void addPartialStderrLine(const QCString &line);
+ virtual void clearView();
+ void hideView();
+ void showView();
+ bool isViewVisible();
+
+signals:
+ void processExited();
+
+private slots:
+ void slotStopButtonClicked(KDevPlugin*);
+ void slotProcessExited();
+
+private:
+ QGuardedPtr<AppOutputWidget> m_widget;
+ KDevAppFrontendIface *m_dcop;
+ bool m_viewIsVisible;
+};
+
+#endif
diff --git a/parts/outputviews/appoutputwidget.cpp b/parts/outputviews/appoutputwidget.cpp
new file mode 100644
index 00000000..e3c3810a
--- /dev/null
+++ b/parts/outputviews/appoutputwidget.cpp
@@ -0,0 +1,355 @@
+/***************************************************************************
+ * Copyright (C) 1999-2001 by Bernd Gehrmann *
+ * bernd@kdevelop.org *
+ * *
+ * Copyright (C) 2003 by Hamish Rodda *
+ * meddie@yoyo.its.monash.edu.au *
+ * *
+ * 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 "appoutputwidget.h"
+
+#include <qregexp.h>
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qclipboard.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kstatusbar.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kpopupmenu.h>
+#include <klineedit.h>
+#include <kfiledialog.h>
+
+#include "appoutputviewpart.h"
+#include "filterdlg.h"
+#include "kdevpartcontroller.h"
+#include "kdevmainwindow.h"
+#include "kdevproject.h"
+
+AppOutputWidget::AppOutputWidget(AppOutputViewPart* part)
+ : ProcessWidget(0, "app output widget"), m_part(part)
+{
+ connect(this, SIGNAL(executed(QListBoxItem*)), SLOT(slotRowSelected(QListBoxItem*)));
+ connect(this, SIGNAL(rightButtonClicked( QListBoxItem *, const QPoint & )),
+ SLOT(slotContextMenu( QListBoxItem *, const QPoint & )));
+ KConfig *config = kapp->config();
+ config->setGroup("General Options");
+ setFont(config->readFontEntry("OutputViewFont"));
+ setSelectionMode(QListBox::Extended);
+}
+
+void AppOutputWidget::clearViewAndContents()
+{
+ m_contentList.clear();
+ clear();
+}
+
+AppOutputWidget::~AppOutputWidget()
+{}
+
+
+void AppOutputWidget::childFinished(bool normal, int status)
+{
+ if( !stdoutbuf.isEmpty() )
+ insertStdoutLine("");
+ if( !stderrbuf.isEmpty() )
+ insertStderrLine("");
+
+ ProcessWidget::childFinished(normal, status);
+}
+
+
+void AppOutputWidget::slotRowSelected(QListBoxItem* row)
+{
+ static QRegExp assertMatch("ASSERT: \\\"([^\\\"]+)\\\" in ([^\\( ]+) \\(([\\d]+)\\)");
+ static QRegExp lineInfoMatch("\\[([^:]+):([\\d]+)\\]");
+ static QRegExp rubyErrorMatch("([^:\\s]+\\.rb):([\\d]+):?.*$");
+
+ if (row) {
+ if (assertMatch.exactMatch(row->text())) {
+ m_part->partController()->editDocument(KURL( assertMatch.cap(2) ), assertMatch.cap(3).toInt() - 1);
+ m_part->mainWindow()->statusBar()->message(i18n("Assertion failed: %1").arg(assertMatch.cap(1)), 10000);
+ m_part->mainWindow()->lowerView(this);
+
+ } else if (lineInfoMatch.search(row->text()) != -1) {
+ m_part->partController()->editDocument(KURL( lineInfoMatch.cap(1) ), lineInfoMatch.cap(2).toInt() - 1);
+ m_part->mainWindow()->statusBar()->message(row->text(), 10000);
+ m_part->mainWindow()->lowerView(this);
+ } else if (rubyErrorMatch.search(row->text()) != -1) {
+ QString file;
+ if (rubyErrorMatch.cap(1).startsWith("/")) {
+ file = rubyErrorMatch.cap(1);
+ } else {
+ file = m_part->project()->projectDirectory() + "/" + rubyErrorMatch.cap(1);
+ }
+ m_part->partController()->editDocument(KURL(rubyErrorMatch.cap(1)), rubyErrorMatch.cap(2).toInt() - 1);
+ m_part->mainWindow()->statusBar()->message(row->text(), 10000);
+ m_part->mainWindow()->lowerView(this);
+ }
+ }
+}
+
+
+void AppOutputWidget::insertStdoutLine(const QCString &line)
+{
+// kdDebug(9004) << k_funcinfo << line << endl;
+
+ if ( !m_part->isViewVisible() )
+ {
+ m_part->showView();
+ }
+
+ QString sline;
+ if( !stdoutbuf.isEmpty() )
+ {
+ sline = QString::fromLocal8Bit( stdoutbuf+line );
+ stdoutbuf.truncate( 0 );
+ }else
+ {
+ sline = QString::fromLocal8Bit( line );
+ }
+
+ m_contentList.append(QString("o-")+sline);
+ if ( filterSingleLine( sline ) )
+ {
+ ProcessWidget::insertStdoutLine( sline.local8Bit() );
+ }
+}
+
+
+void AppOutputWidget::insertStderrLine(const QCString &line)
+{
+// kdDebug(9004) << k_funcinfo << line << endl;
+
+ if ( !m_part->isViewVisible() )
+ {
+ m_part->showView();
+ }
+
+
+ QString sline;
+ if( !stderrbuf.isEmpty() )
+ {
+ sline = QString::fromLocal8Bit( stderrbuf+line );
+ stderrbuf.truncate( 0 );
+ }else
+ {
+ sline = QString::fromLocal8Bit( line );
+ }
+
+ m_contentList.append(QString("e-")+sline);
+ if ( filterSingleLine( sline ) )
+ {
+ ProcessWidget::insertStderrLine( sline.local8Bit() );
+ }
+}
+
+void AppOutputWidget::editFilter()
+{
+ FilterDlg dlg( this );
+ dlg.caseSensitive->setChecked( m_filter.m_caseSensitive );
+ dlg.regularExpression->setChecked( m_filter.m_isRegExp );
+ dlg.filterString->setText( m_filter.m_filterString );
+
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ m_filter.m_caseSensitive = dlg.caseSensitive->isChecked();
+ m_filter.m_isRegExp = dlg.regularExpression->isChecked();
+ m_filter.m_filterString = dlg.filterString->text();
+
+ m_filter.m_isActive = !m_filter.m_filterString.isEmpty();
+
+ reinsertAndFilter();
+ }
+
+}
+bool AppOutputWidget::filterSingleLine(const QString & line)
+{
+ if ( !m_filter.m_isActive ) return true;
+
+ if ( m_filter.m_isRegExp )
+ {
+ return ( line.find( QRegExp( m_filter.m_filterString, m_filter.m_caseSensitive, false ) ) != -1 );
+ }
+ else
+ {
+ return ( line.find( m_filter.m_filterString, 0, m_filter.m_caseSensitive ) != -1 );
+ }
+}
+
+void AppOutputWidget::reinsertAndFilter()
+{
+ //copy the first item from the listbox
+ //if a programm was started, this contains the issued command
+ QString issuedCommand;
+ if ( count() > 0 )
+ {
+ setTopItem(0);
+ issuedCommand = item(topItem())->text();
+ }
+
+ clear();
+
+ //write back the issued command
+ if ( !issuedCommand.isEmpty() )
+ {
+ insertItem( new ProcessListBoxItem( issuedCommand, ProcessListBoxItem::Diagnostic ) );
+ }
+
+ //grep through the list for items matching the filter...
+ QStringList strListFound;
+ if ( m_filter.m_isActive )
+ {
+ if ( m_filter.m_isRegExp )
+ {
+ strListFound = m_contentList.grep( QRegExp(m_filter.m_filterString, m_filter.m_caseSensitive, false ) );
+ }
+ else
+ {
+ strListFound = m_contentList.grep( m_filter.m_filterString, m_filter.m_caseSensitive );
+ }
+ }
+ else
+ {
+ strListFound = m_contentList;
+ }
+
+ //... and reinsert the found items into the listbox
+ for ( QStringList::Iterator it = strListFound.begin(); it != strListFound.end(); ++it )
+ {
+ if ((*it).startsWith("o-"))
+ {
+ (*it).remove(0,2);
+ insertItem(new ProcessListBoxItem(*it, ProcessListBoxItem::Normal));
+ }
+ else if ((*it).startsWith("e-"))
+ {
+ (*it).remove(0,2);
+ insertItem(new ProcessListBoxItem(*it, ProcessListBoxItem::Error));
+ }
+ }
+}
+
+void AppOutputWidget::clearFilter()
+{
+ m_filter.m_isActive = false;
+ reinsertAndFilter();
+}
+
+void AppOutputWidget::slotContextMenu( QListBoxItem *, const QPoint &p )
+{
+ KPopupMenu popup(this, "filter output");
+
+ int id = popup.insertItem( i18n("Clear output"), this, SLOT(clearViewAndContents()) );
+ popup.setItemEnabled( id, m_contentList.size() > 0 );
+
+ popup.insertItem( i18n("Copy selected lines"), this, SLOT(copySelected()) );
+ popup.insertSeparator();
+
+ popup.insertItem( i18n("Save unfiltered"), this, SLOT(saveAll()) );
+ id = popup.insertItem( i18n("Save filtered output"), this, SLOT(saveFiltered()) );
+ popup.setItemEnabled( id, m_filter.m_isActive );
+ popup.insertSeparator();
+
+ id = popup.insertItem( i18n("Clear filter"), this, SLOT(clearFilter()) );
+ popup.setItemEnabled( id, m_filter.m_isActive );
+
+ popup.insertItem( i18n("Edit filter"), this, SLOT(editFilter() ) );
+
+ popup.insertSeparator();
+ popup.insertItem( i18n("Hide view"), this, SLOT(hideView()) );
+
+ popup.exec(p);
+}
+
+void AppOutputWidget::hideView()
+{
+ m_part->hideView();
+}
+
+void AppOutputWidget::saveAll()
+{
+ saveOutputToFile( false );
+}
+
+void AppOutputWidget::saveFiltered()
+{
+ saveOutputToFile( true );
+}
+
+void AppOutputWidget::saveOutputToFile(bool useFilter)
+{
+ QString filename = KFileDialog::getSaveFileName();
+
+ if ( filename.isEmpty() ) return;
+
+ QStringList contents;
+ if ( useFilter && m_filter.m_isActive )
+ {
+ if ( m_filter.m_isRegExp )
+ {
+ contents = m_contentList.grep( QRegExp(m_filter.m_filterString, m_filter.m_caseSensitive, false ) );
+ }
+ else
+ {
+ contents = m_contentList.grep( m_filter.m_filterString, m_filter.m_caseSensitive );
+ }
+ }
+ else
+ {
+ contents = m_contentList;
+ }
+
+ QFile file( filename );
+ if ( file.open( IO_WriteOnly ) )
+ {
+ QTextStream ostream( &file );
+ QStringList::ConstIterator it = contents.begin();
+ while( it != contents.end() )
+ {
+ QString line = *it;
+ if ( line.startsWith("o-") || line.startsWith("e-") )
+ {
+ line.remove( 0, 2 );
+ }
+ ostream << line << endl;
+ ++it;
+ }
+ file.close();
+ }
+}
+
+void AppOutputWidget::copySelected()
+{
+ uint n = count();
+ QString buffer;
+ for (uint i = 0; i < n; i++)
+ {
+ if (isSelected(i))
+ buffer += item(i)->text() + "\n";
+ }
+ kapp->clipboard()->setText(buffer, QClipboard::Clipboard);
+}
+
+void AppOutputWidget::addPartialStderrLine(const QCString & line)
+{
+ stderrbuf += line;
+}
+
+void AppOutputWidget::addPartialStdoutLine(const QCString & line)
+{
+ stdoutbuf += line;
+}
+
+#include "appoutputwidget.moc"
diff --git a/parts/outputviews/appoutputwidget.h b/parts/outputviews/appoutputwidget.h
new file mode 100644
index 00000000..9a0d1e71
--- /dev/null
+++ b/parts/outputviews/appoutputwidget.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * 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 _APPOUTPUTWIDGET_H_
+#define _APPOUTPUTWIDGET_H_
+
+#include <qstringlist.h>
+#include <kregexp.h>
+
+#include "processwidget.h"
+
+class AppOutputViewPart;
+
+class AppOutputWidget : public ProcessWidget
+{
+ Q_OBJECT
+friend class AppOutputViewPart;
+public:
+ AppOutputWidget(AppOutputViewPart* part);
+ ~AppOutputWidget();
+ // clears our own store and the one of our base ProcessWidget
+
+public slots:
+ void slotRowSelected(QListBoxItem* row);
+ void insertStdoutLine(const QCString &line);
+ void insertStderrLine(const QCString &line);
+ void addPartialStdoutLine(const QCString &line);
+ void addPartialStderrLine(const QCString &line);
+ void slotContextMenu(QListBoxItem *, const QPoint &);
+ void hideView();
+ void clearViewAndContents();
+ void clearFilter();
+ void editFilter();
+ void saveAll();
+ void saveFiltered();
+ void copySelected();
+
+private:
+ virtual void childFinished(bool normal, int status);
+ void saveOutputToFile( bool useFilter );
+ void reinsertAndFilter();
+ bool filterSingleLine( const QString & line );
+
+ QStringList m_contentList;
+
+ struct OutputFilter
+ {
+ OutputFilter() : m_isActive(false), m_isRegExp(false), m_caseSensitive(false) {}
+ bool m_isActive;
+ bool m_isRegExp;
+ bool m_caseSensitive;
+ QString m_filterString;
+ };
+
+ AppOutputViewPart* m_part;
+ OutputFilter m_filter;
+ QCString stdoutbuf;
+ QCString stderrbuf;
+};
+
+#endif
diff --git a/parts/outputviews/commandcontinuationfilter.cpp b/parts/outputviews/commandcontinuationfilter.cpp
new file mode 100644
index 00000000..474cec15
--- /dev/null
+++ b/parts/outputviews/commandcontinuationfilter.cpp
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * 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 "commandcontinuationfilter.h"
+#include <qregexp.h>
+#include <kdebug.h>
+
+CommandContinuationFilter::CommandContinuationFilter( OutputFilter& next )
+ : OutputFilter( next )
+{
+}
+
+void CommandContinuationFilter::processLine( const QString& line )
+{
+ int index=line.length()-1;
+ while (index>=0)
+ {
+ if (line[index]=='\\')
+ {
+ m_text += line.left(index);
+ return;
+ }
+
+ if (!line[index].isSpace())
+ break;
+ index--;
+ }
+
+ m_text+=line;
+ OutputFilter::processLine( m_text );
+ m_text = "";
+}
diff --git a/parts/outputviews/commandcontinuationfilter.h b/parts/outputviews/commandcontinuationfilter.h
new file mode 100644
index 00000000..d0239caf
--- /dev/null
+++ b/parts/outputviews/commandcontinuationfilter.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * 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 CommandContinuationFilter_h
+#define CommandContinuationFilter_h
+
+#include "outputfilter.h"
+#include <qstring.h>
+
+class CommandContinuationFilter : public OutputFilter
+{
+public:
+ CommandContinuationFilter( OutputFilter& );
+
+ void processLine( const QString& line );
+
+private:
+ QString m_text;
+};
+
+#endif
diff --git a/parts/outputviews/compileerrorfilter.cpp b/parts/outputviews/compileerrorfilter.cpp
new file mode 100644
index 00000000..f8246346
--- /dev/null
+++ b/parts/outputviews/compileerrorfilter.cpp
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * 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 "compileerrorfilter.h"
+#include "compileerrorfilter.moc"
+#include "makeitem.h"
+
+#include <kdebug.h>
+
+CompileErrorFilter::ErrorFormat::ErrorFormat( const char * regExp, int file, int line, int text )
+ : expression( regExp )
+ , fileGroup( file )
+ , lineGroup( line )
+ , textGroup( text )
+{
+}
+
+CompileErrorFilter::ErrorFormat::ErrorFormat( const char * regExp, int file, int line, int text, QString comp )
+ : expression( regExp )
+ , fileGroup( file )
+ , lineGroup( line )
+ , textGroup( text )
+ , compiler( comp )
+{
+}
+
+
+CompileErrorFilter::CompileErrorFilter( OutputFilter& next )
+ : OutputFilter( next )
+{
+}
+
+CompileErrorFilter::ErrorFormat* CompileErrorFilter::errorFormats()
+{
+ /// @todo could get these from emacs compile.el
+ static ErrorFormat formats[] = {
+ // GCC - another case, eg. for #include "pixmap.xpm" which does not exists
+ ErrorFormat( "^([^:\t]{1,1024}):([0-9]{1,10}):(?:[0-9]+):([^0-9]+)", 1, 2, 3 ),
+ // GCC
+ ErrorFormat( "^([^:\t]{1,1024}):([0-9]{1,10}):([^0-9]+)", 1, 2, 3 ),
+ // ICC
+ ErrorFormat( "^([^:\\t]{1,1024})\\(([0-9]{1,10})\\):([^0-9]+)", 1, 2, 3, "intel" ),
+ //libtool link
+ ErrorFormat( "(libtool):( link):( warning): ", 0, 0, 0 ),
+ // ld
+ ErrorFormat( "undefined reference", 0, 0, 0 ),
+ ErrorFormat( "undefined symbol", 0, 0, 0 ),
+ ErrorFormat( "ld: cannot find", 0, 0, 0 ),
+ ErrorFormat( "No such file", 0, 0, 0 ),
+ // make
+ ErrorFormat( "No rule to make target", 0, 0, 0 ),
+ // Fortran
+ ErrorFormat( "\"(.*)\", line ([0-9]+):(.*)", 1, 2, 3 ),
+ // Jade
+ ErrorFormat( "[a-zA-Z]+:([^: \t]+):([0-9]+):[0-9]+:[a-zA-Z]:(.*)", 1, 2, 3 ),
+ // ifort
+ ErrorFormat( "fortcom: Error: (.*), line ([0-9]+):(.*)", 1, 2, 3, "intel" ),
+ // PGI
+ ErrorFormat( "PGF9(.*)-(.*)-(.*)-(.*) \\((.*): ([0-9]+)\\)", 5, 6, 4, "pgi" ),
+ // PGI (2)
+ ErrorFormat( "PGF9(.*)-(.*)-(.*)-Symbol, (.*) \\((.*)\\)", 5, 5, 4, "pgi" ),
+
+ ErrorFormat( 0, 0, 0, 0 ) // this one last
+ };
+
+ return formats;
+
+}
+
+void CompileErrorFilter::processLine( const QString& line )
+{
+ bool hasmatch = false;
+ QString file;
+ int lineNum = 0;
+ QString text;
+ QString compiler;
+ int i = 0;
+ bool isWarning = false;
+ bool isInstantiationInfo = false;
+ ErrorFormat* const errFormats = errorFormats();
+ ErrorFormat* format = &errFormats[i];
+ while( !format->expression.isEmpty() )
+ {
+ QRegExp& regExp = format->expression;
+
+ if ( regExp.search( line ) != -1 ) {
+ hasmatch = true;
+ file = regExp.cap( format->fileGroup );
+ lineNum = regExp.cap( format->lineGroup ).toInt() - 1;
+ text = regExp.cap( format->textGroup );
+ compiler = format->compiler;
+ QString cap = regExp.cap(3);
+ if (cap.contains("warning:", false) || cap.contains("Warnung:", false))
+ isWarning = true;
+ if (regExp.cap(3).contains("instantiated from", false)) {
+ isInstantiationInfo = true;
+ }
+ break;
+ }
+
+ format = &errFormats[++i];
+ }
+
+ if( hasmatch )
+ {
+ // Add hacks for error strings you want excluded here
+ if( text.find( QString::fromLatin1("(Each undeclared identifier is reported only once") ) >= 0
+ || text.find( QString::fromLatin1("for each function it appears in.)") ) >= 0 )
+ hasmatch = false;
+ }
+
+ if ( hasmatch )
+ {
+ emit item( new ErrorItem( file, lineNum, text, line, isWarning, isInstantiationInfo, compiler ) );
+ }
+ else
+ {
+ OutputFilter::processLine( line );
+ }
+}
diff --git a/parts/outputviews/compileerrorfilter.h b/parts/outputviews/compileerrorfilter.h
new file mode 100644
index 00000000..d07495cf
--- /dev/null
+++ b/parts/outputviews/compileerrorfilter.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * 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 CompileErrorFilter_h
+#define CompileErrorFilter_h
+
+#include <qobject.h>
+#include <qregexp.h>
+#include <qvaluelist.h>
+#include "outputfilter.h"
+
+class MakeItem;
+
+class CompileErrorFilter : public QObject, public OutputFilter
+{
+Q_OBJECT
+
+public:
+ CompileErrorFilter( OutputFilter& );
+
+ struct ErrorFormat
+ {
+ ErrorFormat() {}
+ ErrorFormat( const char *, int, int, int );
+ ErrorFormat( const char *, int, int, int, QString );
+ QRegExp expression;
+ int fileGroup;
+ int lineGroup;
+ int textGroup;
+ QString compiler;
+ };
+ static ErrorFormat* errorFormats();
+
+ void processLine( const QString& line );
+
+signals:
+ void item( MakeItem* );
+};
+
+#endif
diff --git a/parts/outputviews/directorystatusmessagefilter.cpp b/parts/outputviews/directorystatusmessagefilter.cpp
new file mode 100644
index 00000000..5738f41d
--- /dev/null
+++ b/parts/outputviews/directorystatusmessagefilter.cpp
@@ -0,0 +1,187 @@
+/***************************************************************************
+ * 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 "directorystatusmessagefilter.h"
+#include "directorystatusmessagefilter.moc"
+#include "makeitem.h"
+
+#include <qregexp.h>
+#include <kdebug.h>
+
+DirectoryStatusMessageFilter::DirectoryStatusMessageFilter( OutputFilter& next )
+ : OutputFilter( next )
+{
+}
+
+void DirectoryStatusMessageFilter::processLine( const QString& line )
+{
+ QString dir;
+ if ( matchEnterDir( line, dir ) )
+ {
+ emit item( new EnteringDirectoryItem( dir, line ) );
+ }
+ else if ( matchLeaveDir( line, dir ) )
+ {
+ emit item( new ExitingDirectoryItem( dir, line ) );
+ }
+ else
+ {
+ OutputFilter::processLine( line );
+ }
+}
+
+// simple helper function - checks whether we entered a new directory
+// (locale and Utf8 aware)
+bool DirectoryStatusMessageFilter::matchEnterDir( const QString& line, QString& dir )
+{
+ // make outputs localised strings in Utf8 for entering/leaving directories...
+ static const unsigned short fr_enter[] =
+ {'E','n','t','r','e',' ','d','a','n','s',' ','l','e',' ','r',0xe9,'p','e','r','t','o','i','r','e'
+ };
+ static const unsigned short pl_enter[] =
+ {'W','c','h','o','d','z',0x119,' ','k','a','t','a','l','o','g'
+ };
+ static const unsigned short ja_enter[] =
+ {
+ 0x5165,0x308a,0x307e,0x3059,0x20,0x30c7,0x30a3,0x30ec,0x30af,0x30c8,0x30ea
+ };
+ static const unsigned short ko_enter[] =
+ {
+ 0xb4e4,0xc5b4,0xac10
+ };
+ static const unsigned short ko_behind[] =
+ {
+ 0x20,0xb514,0xb809,0xd1a0,0xb9ac
+ };
+ static const unsigned short pt_br_enter[] =
+ {
+ 0x45,0x6e,0x74,0x72,0x61,0x6e,0x64,0x6f,0x20,0x6e,0x6f,0x20,0x64,0x69,0x72,0x65,0x74,0xf3,0x72,0x69,0x6f
+ };
+ static const unsigned short ru_enter[] =
+ {
+ 0x412,0x445,0x43e,0x434,0x20,0x432,0x20,0x43a,0x430,0x442,0x430,0x43b,0x43e,0x433
+ };
+
+ static const QString fr_e( (const QChar*)fr_enter, sizeof(fr_enter) / 2 );
+ static const QString pl_e( (const QChar*)pl_enter, sizeof(pl_enter) / 2 );
+ static const QString ja_e( (const QChar*)ja_enter, sizeof(ja_enter) / 2 );
+ static const QString ko_e( (const QChar*)ko_enter, sizeof(ko_enter) / 2 );
+ static const QString ko_b( (const QChar*)ko_behind, sizeof(ko_behind) / 2 );
+ static const QString pt_br_e( (const QChar*)pt_br_enter, sizeof(pt_br_enter) / 2 );
+ static const QString ru_e( (const QChar*)ru_enter, sizeof(ru_enter) / 2 );
+ static const QString en_e("Entering directory");
+ static const QString de_e1("Wechsel in das Verzeichnis Verzeichnis");
+ static const QString de_e2("Wechsel in das Verzeichnis");
+ static const QString es_e("Cambiando a directorio");
+ static const QString nl_e("Binnengaan van directory");
+ //@todo: other translations!
+
+ // we need a QRegExp because KRegExp is not Utf8 aware.
+ // 0x00AB is LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // 0X00BB is RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ static QRegExp dirChange(QString::fromLatin1(".*: (.+) (`|") + QChar(0x00BB) + QString::fromLatin1(")(.*)('|") + QChar(0x00AB) + QString::fromLatin1(")(.*)"));
+ static QRegExp enEnter(QString::fromLatin1(".*: Entering directory"));
+ kdDebug(9004) << "Directory filter line " << line << endl;
+
+ // avoid QRegExp if possible. This regex performs VERY badly with large inputs,
+ // and the input required is very short if these strings match.
+ if(line.find(en_e) > -1 ||
+ line.find(fr_e) > -1 ||
+ line.find(pl_e) > -1 ||
+ line.find(ja_e) > -1 ||
+ line.find(ko_e) > -1 ||
+ line.find(ko_b) > -1 ||
+ line.find(pt_br_e) > -1 ||
+ line.find(ru_e) > -1 ||
+ line.find(de_e1) > -1 ||
+ line.find(de_e2) > -1 ||
+ line.find(es_e) > -1 ||
+ line.find(nl_e) > -1)
+ {
+ // grab the directory name
+ if(dirChange.search(line) > -1)
+ {
+ dir = dirChange.cap(3);
+ return true;
+ }
+ }
+ return false;
+}
+
+// simple helper function - checks whether we left a directory
+// (locale and Utf8 aware).
+bool DirectoryStatusMessageFilter::matchLeaveDir( const QString& line, QString& dir )
+{
+ static const unsigned short fr_leave[] =
+ { 'Q','u','i','t','t','e',' ','l','e',' ','r',0xe9,'p','e','r','t','o','i','r','e'
+ };
+ static const unsigned short ja_leave[] =
+ {
+ 0x51fa,0x307e,0x3059,0x20,0x30c7,0x30a3,0x30ec,0x30af,0x30c8,0x30ea
+ };
+ static const unsigned short pt_br_leave[] =
+ {'S','a','i','n','d','o',' ','d','o',' ','d','i','r','e','t',0xf3,'r','i','o'
+ };
+ static const unsigned short ru_leave[] =
+ {
+ 0x412,0x44b,0x445,0x43e,0x434,0x20,0x438,0x437,0x20,0x43a,0x430,0x442,0x430,0x43b,0x43e,0x433
+ };
+ static const unsigned short ko_leave[] =
+ {
+ 0xb098,0xac10
+ };
+ static const unsigned short ko_behind[] =
+ {
+ 0x20,0xb514,0xb809,0xd1a0,0xb9ac
+ };
+
+ static const QString fr_l( (const QChar*)fr_leave, sizeof(fr_leave) / 2 );
+ static const QString ja_l( (const QChar*)ja_leave, sizeof(ja_leave) / 2 );
+ static const QString ko_l( (const QChar*)ko_leave, sizeof(ko_leave) / 2 );
+ static const QString ko_b( (const QChar*)ko_behind, sizeof(ko_behind) / 2 );
+ static const QString pt_br_l( (const QChar*)pt_br_leave, sizeof(pt_br_leave) / 2 );
+ static const QString ru_l( (const QChar*)ru_leave, sizeof(ru_leave) / 2 );
+ static const QString en_l("Leaving directory");
+ static const QString de_l1("Verlassen des Verzeichnisses Verzeichnis");
+ static const QString de_l2("Verlassen des Verzeichnisses");
+ static const QString es_l("Saliendo directorio");
+ static const QString nl_l("Verdwijnen uit directory");
+ static const QString po_l("Opuszczam katalog");
+
+ // we need a QRegExp because KRegExp is not Utf8 aware.
+ // 0x00AB is LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ // 0X00BB is RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+
+ static QRegExp dirChange(QString::fromLatin1(".*: (.+) (`|") + QChar(0x00BB) + QString::fromLatin1(")(.*)('|") + QChar(0x00AB) + QString::fromLatin1(")(.*)"));
+
+ // avoid QRegExp if possible. This regex performs VERY badly with large inputs,
+ // and the input required is very short if these strings match.
+ if(line.find(en_l) > -1 ||
+ line.find(fr_l) > -1 ||
+ line.find(ja_l) > -1 ||
+ (line.find(ko_l) > -1 && line.find(ko_b) > -1) ||
+ line.find(pt_br_l) > -1 ||
+ line.find(ru_l) > -1 ||
+ line.find(de_l1) > -1 ||
+ line.find(de_l2) > -1 ||
+ line.find(es_l) > -1 ||
+ line.find(nl_l) > -1 ||
+ line.find(po_l) > -1)
+ {
+ // grab the directory name
+ if(dirChange.search(line) > -1 )
+ {
+ dir = dirChange.cap(3);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/parts/outputviews/directorystatusmessagefilter.h b/parts/outputviews/directorystatusmessagefilter.h
new file mode 100644
index 00000000..18972487
--- /dev/null
+++ b/parts/outputviews/directorystatusmessagefilter.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * 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 DirectoryStatusMessageFilter_h
+#define DirectoryStatusMessageFilter_h
+
+#include <qobject.h>
+#include "outputfilter.h"
+
+class EnteringDirectoryItem;
+class ExitingDirectoryItem;
+
+class DirectoryStatusMessageFilter : public QObject, public OutputFilter
+{
+Q_OBJECT
+
+public:
+ DirectoryStatusMessageFilter( OutputFilter& );
+
+ void processLine( const QString& line );
+
+signals:
+ void item( EnteringDirectoryItem* );
+ void item( ExitingDirectoryItem* );
+
+private:
+ bool matchEnterDir( const QString& line, QString& dir );
+ bool matchLeaveDir( const QString& line, QString& dir );
+};
+
+#endif
diff --git a/parts/outputviews/filterdlg.ui b/parts/outputviews/filterdlg.ui
new file mode 100644
index 00000000..729af672
--- /dev/null
+++ b/parts/outputviews/filterdlg.ui
@@ -0,0 +1,164 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>FilterDlg</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>FilterDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>326</width>
+ <height>200</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Output Filter Settings</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>filtergroup</cstring>
+ </property>
+ <property name="title">
+ <string>Filter</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="selectedId" stdset="0">
+ <number>-1</number>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Only show lines matching:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>filterString</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>caseSensitive</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;ase sensitive</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>regularExpression</cstring>
+ </property>
+ <property name="text">
+ <string>Re&amp;gular expression</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>FilterDlg</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>FilterDlg</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>filterString</tabstop>
+ <tabstop>caseSensitive</tabstop>
+ <tabstop>regularExpression</tabstop>
+ <tabstop>buttonOk</tabstop>
+ <tabstop>buttonCancel</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/parts/outputviews/kdevappoutputview.desktop b/parts/outputviews/kdevappoutputview.desktop
new file mode 100644
index 00000000..2460ad6d
--- /dev/null
+++ b/parts/outputviews/kdevappoutputview.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+Type=Service
+Exec=blubb
+Comment=Application Output View
+Comment[ca]=Visor de l'eixida de les aplicacions
+Comment[da]=Program-uddata fremvisning
+Comment[de]=Anwendungsausgabe für KDevelop
+Comment[el]=Προβολή εξόδου εφαρμογής
+Comment[es]=Visor de la salida de las aplicaciones
+Comment[et]=Rakenduse väljundi vaade
+Comment[eu]=Aplikazioen irteera ikustailua
+Comment[fa]=نمای خروجی کاربرد
+Comment[fr]=Fenêtre de sortie d'une application
+Comment[gl]=Vista da saída da aplicación
+Comment[hi]=अनुप्रयोग आउटपुट व्यू
+Comment[hu]=Alkalmazáskimenet-megjelenítő
+Comment[it]=Vista dell'output dell'applicazione
+Comment[ja]=アプリケーション出力ビュー
+Comment[ms]=Lihat Keluaran Aplikasi
+Comment[nds]=Programmutgaav-Kieker
+Comment[ne]=अनुप्रयोग निर्गत दृश्य
+Comment[nl]=Weergave van toepassingsuitvoer
+Comment[pl]=Widok wyjścia programu
+Comment[pt]=Vista do Resultado da Aplicação
+Comment[pt_BR]=Visão da Saída do Aplicativo
+Comment[ru]=Окно вывода приложения
+Comment[sk]=Pohľad na výstup aplikácie
+Comment[sl]=Prikaz programskega izhoda
+Comment[sr]=Приказ излаза апликације
+Comment[sr@Latn]=Prikaz izlaza aplikacije
+Comment[sv]=Programutmatningsvy
+Comment[ta]=பயன்பாட்டு வெளியீட்டுக் காட்சி
+Comment[tg]=Тирезаи хориҷ кардани гузориш
+Comment[tr]=Uygulama Çıktı Görünümü
+Comment[zh_CN]=应用程序输出查看器
+Comment[zh_TW]=應用程式輸出檢視
+Name=KDevAppOutputView
+Name[da]=KDevelop Program-uddata fremvisning
+Name[de]=Anwendungsausgabe (KDevelop)
+Name[hi]=के-डेव-एप्प-आउटपुट-व्यू
+Name[nds]=Programmutgaav-Kieker (KDevelop)
+Name[pl]=KDevAppWidokWyjścia
+Name[sk]=KDev pohľad na výstup aplikácie
+Name[sv]=KDevelop programutmatningsvy
+Name[ta]=KDevApp வெளியீட்டுக் காட்சி
+Name[zh_TW]=KDevelop 應用程式輸出檢視
+GenericName=Application Output View
+GenericName[ca]=Visor de l'eixida de les aplicacions
+GenericName[da]=Program-uddata fremvisning
+GenericName[de]=Anwendungsausgabe
+GenericName[el]=Προβολή εξόδου εφαρμογής
+GenericName[es]=Visor de la salida de las aplicaciones
+GenericName[et]=Rakenduse väljundi vaade
+GenericName[eu]=Aplikazioen irteera ikustailua
+GenericName[fa]=نمای خروجی کاربرد
+GenericName[fr]=Fenêtre de sortie d'une application
+GenericName[gl]=Vista da saída da aplicación
+GenericName[hi]=अनुप्रयोग आउटपुट व्यू
+GenericName[hu]=Alkalmazáskimenet-megjelenítő
+GenericName[it]=Visualizza l'output dell'applicazione
+GenericName[ja]=アプリケーション出力ビュー
+GenericName[nds]=Programmutgaav-Kieker
+GenericName[ne]=अनुप्रयोग निर्गत दृश्य
+GenericName[nl]=Weergave van toepassingsuitvoer
+GenericName[pl]=Widok wyjścia programu
+GenericName[pt]=Vista do Resultado da Aplicação
+GenericName[pt_BR]=Visão da Saída do Aplicativo
+GenericName[ru]=Окно вывода приложения
+GenericName[sk]=Pohľad na výstup aplikácie
+GenericName[sl]=Prikaz programskega izhoda
+GenericName[sr]=Приказ излаза апликације
+GenericName[sr@Latn]=Prikaz izlaza aplikacije
+GenericName[sv]=Programutmatningsvy
+GenericName[ta]=பயன்பாட்டு வெளியீட்டுக் காட்சி
+GenericName[tg]=Тирезаи хориҷ кардани гузориш
+GenericName[tr]=Uygulama Çıktı Görünümü
+GenericName[zh_CN]=应用程序输出查看器
+GenericName[zh_TW]=應用程式輸出檢視
+Icon=exec
+ServiceTypes=KDevelop/AppFrontend
+X-KDE-Library=libkdevappview
+X-KDevelop-Version=5
+X-KDevelop-Scope=Core
+X-KDevelop-Properties=OutputTool
diff --git a/parts/outputviews/kdevmakeview.desktop b/parts/outputviews/kdevmakeview.desktop
new file mode 100644
index 00000000..e4498d0a
--- /dev/null
+++ b/parts/outputviews/kdevmakeview.desktop
@@ -0,0 +1,87 @@
+[Desktop Entry]
+Type=Service
+Exec=blubb
+Comment=Compiler Frontend
+Comment[ca]=Entorn per al compilador
+Comment[da]=Grænseflade til oversætter
+Comment[de]=Make-Ausgabe für KDevelop
+Comment[el]=Πρόγραμμα μεταγλωττιστή
+Comment[es]=Entorno para el compilador
+Comment[et]=Kompilaatori kasutajaliides
+Comment[eu]=Konpiladore interfazea
+Comment[fa]=پایانۀ مترجم
+Comment[fr]=Interface pour le compilateur
+Comment[ga]=Comhéadan Tiomsaitheora
+Comment[gl]=Frontal para o compilador
+Comment[hi]=कम्पायलर फ्रन्टएण्ड
+Comment[hu]=Grafikus felület fordítóprogramokhoz
+Comment[it]=Interfaccia al compilatore
+Comment[ja]=コンパイラフロントエンド
+Comment[ms]=Frontend Penghimpun
+Comment[nds]=Kompilerer-Böversiet
+Comment[ne]=कम्पाइलर फ्रन्टइन्ड
+Comment[nl]=Compiler-frontend
+Comment[pl]=Interfejs do kompilatora
+Comment[pt]=Interface de Compilador
+Comment[pt_BR]=Frontend do Compilador
+Comment[ru]=Интерфейс к компилятору
+Comment[sk]=Rozhranie kompilátora
+Comment[sl]=Vmesnik prevajalnika
+Comment[sr]=Кориснички интерфејс за преводилац
+Comment[sr@Latn]=Korisnički interfejs za prevodilac
+Comment[sv]=Kompilatorgränssnitt
+Comment[ta]=முன்பகுதி தொகுப்பான்
+Comment[tg]=Интерфейс ба талфифгар
+Comment[tr]=Derleyici Önucu
+Comment[zh_CN]=编译器前端
+Comment[zh_TW]=編譯器前端介面
+Name=KDevMakeView
+Name[da]=KDevelop Make-visning
+Name[de]=Make-Ausgabe (KDevelop)
+Name[hi]=के-डेव-मेक-व्यू
+Name[nds]=Make-Kieker (KDevelop)
+Name[pl]=KDevWIdokMake
+Name[sk]=KDev pohľad na make
+Name[sv]=KDevelop byggvy
+Name[ta]=KDev காட்சியாக்கு
+Name[zh_TW]=KDevelop Make 檢視
+GenericName=Compiler Frontend
+GenericName[ca]=Entorn per al compilador
+GenericName[da]=Grænseflade til oversætter
+GenericName[de]=Make-Ausgabe
+GenericName[el]=Πρόγραμμα μεταγλωττιστή
+GenericName[es]=Entorno para el compilador
+GenericName[et]=Kompilaatori kasutajaliides
+GenericName[eu]=Konpiladore interfazea
+GenericName[fa]=پایانۀ مترجم
+GenericName[fr]=Interface pour le compilateur
+GenericName[ga]=Comhéadan Tiomsaitheora
+GenericName[gl]=Frontal para o compilador
+GenericName[hi]=कम्पायलर फ्रन्टएण्ड
+GenericName[hu]=Grafikus felület fordítóprogramokhoz
+GenericName[it]=Interfaccia al compilatore
+GenericName[ja]=コンパイラフロントエンド
+GenericName[ms]=Frontend Penghimpun
+GenericName[nds]=Kompilerer-Böversiet
+GenericName[ne]=कम्पाइलर फ्रन्टइन्ड
+GenericName[nl]=Compiler-frontend
+GenericName[pl]=Interfejs do kompilatora
+GenericName[pt]=Interface de Compilador
+GenericName[pt_BR]=Frontend do Compilador
+GenericName[ru]=Интерфейс к компилятору
+GenericName[sk]=Rozhranie kompilátor
+GenericName[sl]=Vmesnik prevajalnika
+GenericName[sr]=Кориснички интерфејс преводиоца
+GenericName[sr@Latn]=Korisnički interfejs prevodioca
+GenericName[sv]=Kompilatorgränssnitt
+GenericName[ta]=முன் பகுதி தொகுப்பான்
+GenericName[tg]=Интерфейс ба талфифгар
+GenericName[tr]=Derleyici Önucu
+GenericName[zh_CN]=编译器前端
+GenericName[zh_TW]=編譯器前端介面
+Icon=konsole
+ServiceTypes=KDevelop/MakeFrontend
+X-KDE-Library=libkdevmakeview
+X-KDevelop-Version=5
+X-KDevelop-Scope=Core
+X-KDevelop-Properties=OutputTool
diff --git a/parts/outputviews/kdevmakeview.rc b/parts/outputviews/kdevmakeview.rc
new file mode 100644
index 00000000..fc8c82f6
--- /dev/null
+++ b/parts/outputviews/kdevmakeview.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="KDevMakeView" version="1">
+<MenuBar>
+ <Menu name="view">
+ <Action name="view_next_error" group="error_operations"/>
+ <Action name="view_previous_error" group="error_operations"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/parts/outputviews/makeactionfilter.cpp b/parts/outputviews/makeactionfilter.cpp
new file mode 100644
index 00000000..bbcc61fb
--- /dev/null
+++ b/parts/outputviews/makeactionfilter.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+ * 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 <qdatetime.h>
+#include <kdebug.h>
+
+#include "makeactionfilter.h"
+#include "makeactionfilter.moc"
+#include "makeitem.h"
+
+#include <klocale.h>
+
+//#define DEBUG
+
+MakeActionFilter::ActionFormat::ActionFormat( const QString& _action, const QString& _tool, const char * regExp, int file )
+ : m_action( _action )
+ , m_expression( regExp )
+ , m_tool( _tool )
+ , m_toolGroup(-1)
+ , m_fileGroup( file )
+{
+}
+
+MakeActionFilter::ActionFormat::ActionFormat( const QString& _action, int tool, int file, const char * regExp)
+ : m_action( _action )
+ , m_expression( regExp )
+ , m_tool()
+ , m_toolGroup(tool)
+ , m_fileGroup( file )
+{
+}
+
+QString MakeActionFilter::ActionFormat::tool()
+{
+ if (m_toolGroup==-1)
+ return m_tool;
+ return m_expression.cap(m_toolGroup);
+}
+
+QString MakeActionFilter::ActionFormat::file()
+{
+ return m_expression.cap(m_fileGroup);
+}
+
+bool MakeActionFilter::ActionFormat::matches(const QString& line)
+{
+ return ( m_expression.search( line ) != -1 );
+}
+
+
+MakeActionFilter::MakeActionFilter( OutputFilter& next )
+ : OutputFilter( next )
+{
+
+#ifdef DEBUG
+ test();
+#endif
+}
+
+//NOTE: whenever you discover a case that is not correctly recognized by the filter, please add it as a test
+//item and be sure that your modifications don't break the already existing test cases.
+
+// returns an array of ActionFormat
+MakeActionFilter::ActionFormat* MakeActionFilter::actionFormats()
+{
+ static ActionFormat formats[] = {
+ ActionFormat( i18n("compiling"), 1, 2, "(?:^|[^=])\\b(gcc|CC|cc|distcc|c\\+\\+|g\\+\\+)\\s+.*-c.*[/ '\\\\]+(\\w+\\.(?:cpp|CPP|c|C|cxx|CXX|cs|java|hpf|f|F|f90|F90|f95|F95))"),
+ ActionFormat( i18n("compiling"), 1, 1, "^compiling (.*)" ), //unsermake
+ ActionFormat( i18n("compiling"), 1, 1, "\\[.+%\\] Building .* object (.*)" ), //cmake
+
+ ActionFormat( i18n("built"), 1, 1, "\\[.+%\\] Built target (.*)" ), //cmake
+ ActionFormat( i18n("generating"), 1, 1, "\\[.+%\\] Generating (.*)" ), //cmake
+
+ //moc and uic
+ ActionFormat( i18n("generating"), 1, 2, "/(moc|uic)\\b.*\\s-o\\s([^\\s;]+)"),
+ ActionFormat( i18n("generating"), 1, 2, "^generating (.*)" ), //unsermake
+
+ ActionFormat( i18n("linking"), "libtool", "/bin/sh\\s.*libtool.*--mode=link\\s.*\\s-o\\s([^\\s;]+)", 1 ),
+ //can distcc link too ?
+ ActionFormat( i18n("linking"), 1, 2, "(gcc|CC|cc|c\\+\\+|g\\+\\+)\\S* (?:\\S* )*-o ([^\\s;]+)"),
+ ActionFormat( i18n("linking"), 1, 2, "^linking (.*)" ), //unsermaker
+ ActionFormat( i18n("linking"), 1, 1, "^Linking .* module (.*)" ), //cmake
+ ActionFormat( i18n("linking"), 1, 1, "^Linking (.*)" ), //cmake
+
+ ActionFormat( i18n("creating"), "", "/(?:bin/sh\\s.*mkinstalldirs).*\\s([^\\s;]+)", 1 ),
+ ActionFormat( i18n("installing"), "", "/(?:usr/bin/install|bin/sh\\s.*mkinstalldirs|bin/sh\\s.*libtool.*--mode=install).*\\s([^\\s;]+)", 1 ),
+ ActionFormat( i18n("generating"), "dcopidl", "dcopidl .* > ([^\\s;]+)", 1 ),
+ ActionFormat( i18n("compiling"), "dcopidl2cpp", "dcopidl2cpp (?:\\S* )*([^\\s;]+)", 1 ),
+ ActionFormat( i18n("installing"), 1, 1, "-- Installing (.*)" ), //cmake
+
+ ActionFormat( QString::null, QString::null, 0, 0 )
+ };
+
+ return formats;
+}
+
+void MakeActionFilter::processLine( const QString& line )
+{
+ ActionItem* actionItem = matchLine( line );
+ if ( actionItem != NULL )
+ {
+ emit item( actionItem );
+ }
+ else
+ {
+ OutputFilter::processLine( line );
+ }
+}
+
+ActionItem* MakeActionFilter::matchLine( const QString& line )
+{
+#ifdef DEBUG
+ QTime t;
+ t.start();
+#endif
+ /// \FIXME This is very slow, possibly due to the regexr matching. It can take
+ //900-1000ms to execute on an Athlon XP 2000+, while the UI is completely blocked.
+ int i = 0;
+ ActionFormat* aFormats = actionFormats();
+ ActionFormat* format = &aFormats[i];
+
+ while ( !format->action().isNull() )
+ {
+// kdDebug(9004) << "Testing filter: " << format->action << ": " << format->tool << endl;
+ if ( format->matches( line ) )
+ {
+ ActionItem *actionItem = new ActionItem( format->action(), format->file(), format->tool(), line );
+ kdDebug( 9004 ) << "Found: " << actionItem->m_action << " " << actionItem->m_file << "(" << actionItem->m_tool << ")" << endl;
+ return actionItem;
+ }
+#ifdef DEBUG
+ if ( t.elapsed() > 100 )
+ kdDebug(9004) << "MakeActionFilter::processLine: SLOW regexp matching: " << t.elapsed() << " ms \n";
+#endif
+ format = &aFormats[++i];
+ }
+ return 0;
+}
+
+struct TestItem
+{
+ TestItem() {}
+ TestItem( const QString& _line, const QString& _action, const QString& _tool, const QString& _file )
+ : line( _line )
+ , action( _action )
+ , tool( _tool )
+ , file( _file )
+ {}
+ QString line;
+ QString action;
+ QString tool;
+ QString file;
+};
+
+#ifdef DEBUG
+
+void MakeActionFilter::test()
+{
+ static QValueList<TestItem> testItems = QValueList<TestItem>()
+
+ << TestItem( // simple qmake compile
+ "g++ -c -pipe -Wall -W -O2 -DQT_NO_DEBUG -I/home/john/src/kde/qt-copy/mkspecs/default -I. "
+ "-I/home/john/src/kde/qt-copy/include -o test.o test.cpp",
+ "compiling", "g++", "test.cpp" )
+ << TestItem( // simple qmake compile different option order
+ "g++ -c -o test.o -pipe -Wall -W -O2 -DQT_NO_DEBUG -I/home/john/src/kde/qt-copy/mkspecs/default -I. "
+ "-I/home/john/src/kde/qt-copy/include test.cpp",
+ "compiling", "g++", "test.cpp" )
+ << TestItem( // simple qmake link
+ "g++ -o ../bin/test test.o -Wl,-rpath,/home/john/src/kde/qt-copy/lib -L/home/john/src/kde/qt-copy/lib "
+ "-L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm",
+ "linking", "g++", "../bin/test" )
+ << TestItem( // automake 1.7, srcdir != builddir
+ "if /bin/sh ../../libtool --silent --mode=compile --tag=CXX g++ -DHAVE_CONFIG_H -I. "
+ "-I/home/john/src/kde/kdevelop/lib/interfaces -I../.. -I/usr/local/kde/include -I/home/john/src/kde/qt-copy/include "
+ "-I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic -W "
+ "-Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion "
+ "-Wchar-subscripts -fno-builtin -g3 -Wformat-security -Wmissing-format-attribute -fno-exceptions -fno-check-new "
+ "-fno-common -MT kdevcore.lo -MD -MP -MF \".deps/kdevcore.Tpo\" -c -o kdevcore.lo `test -f "
+ "'/home/john/src/kde/kdevelop/lib/interfaces/kdevcore.cpp' || echo "
+ "'/home/john/src/kde/kdevelop/lib/interfaces/'`/home/john/src/kde/kdevelop/lib/interfaces/kdevcore.cpp; then mv "
+ "\".deps/kdevcore.Tpo\" \".deps/kdevcore.Plo\"; else rm -f \".deps/kdevcore.Tpo\"; exit 1; fi",
+ "compiling", "g++", "kdevcore.cpp" )
+ << TestItem( // automake 1.7, srcdir != builddir
+ "if g++ -DHAVE_CONFIG_H -I. -I/home/john/src/kde/kdevelop/src -I.. -I/home/john/src/kde/kdevelop/lib/interfaces "
+ "-I/home/john/src/kde/kdevelop/lib/sourceinfo -I/home/john/src/kde/kdevelop/lib/util -I/home/john/src/kde/kdevelop/lib "
+ "-I/home/john/src/kde/kdevelop/lib/qextmdi/include -I/home/john/src/kde/kdevelop/lib/structure -I/usr/local/kde/include "
+ "-I/home/john/src/kde/qt-copy/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor "
+ "-Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi "
+ "-D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -Wchar-subscripts -fno-builtin -g3 -Wformat-security "
+ "-Wmissing-format-attribute -fno-exceptions -fno-check-new -fno-common -MT mainwindowideal.o -MD -MP -MF "
+ "\".deps/mainwindowideal.Tpo\" -c -o mainwindowideal.o `test -f '/home/john/src/kde/kdevelop/src/mainwindowideal.cpp' "
+ "|| echo '/home/john/src/kde/kdevelop/src/'`/home/john/src/kde/kdevelop/src/mainwindowideal.cpp; then mv "
+ "\".deps/mainwindowideal.Tpo\" \".deps/mainwindowideal.Po\"; else rm -f \".deps/mainwindowideal.Tpo\"; exit 1; fi",
+ "compiling", "g++", "mainwindowideal.cpp" )
+ << TestItem( // automake and libtool compiling *.c files
+ "if /bin/sh ../../libtool --silent --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I. -I../.. -I../../lib/interfaces"
+ "-I../../lib/util -I/opt/kde3/include -I/usr/lib/qt3/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT "
+ "-std=iso9899:1990 -W -Wall -Wchar-subscripts -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings "
+ "-D_XOPEN_SOURCE=500 -D_BSD_SOURCE -g3 -fno-inline -Wformat-security -Wmissing-format-attribute -MT readtags.lo "
+ "-MD -MP -MF \".deps/readtags.Tpo\" -c -o readtags.lo readtags.c; then mv -f \".deps/readtags.Tpo\" "
+ "\".deps/readtags.Plo\"; else rm -f \".deps/readtags.Tpo\"; exit 1; fi",
+ i18n("compiling"), "gcc", "readtags.c" )
+ << TestItem(
+ "source='makewidget.cpp' object='makewidget.lo' libtool=yes depfile='.deps/makewidget.Plo' "
+ "tmpdepfile='.deps/makewidget.TPlo' depmode=gcc3 /bin/sh ../../admin/depcomp /bin/sh ../../libtool --mode=compile "
+ "--tag=CXX g++ -DHAVE_CONFIG_H -I. -I. -I../.. -I../../lib/interfaces -I../../lib/util -I/opt/kde3/include "
+ "-I/usr/lib/qt3/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor -Wno-long-long -Wundef "
+ "-Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE "
+ "-Wcast-align -Wconversion -fno-builtin -g -O2 -g3 -O0 -fno-exceptions -fno-check-new -c -o makewidget.lo `test -f "
+ "'makewidget.cpp' || echo './'`makewidget.cpp",
+ "compiling", "g++", "makewidget.cpp" )
+ << TestItem( // automake 1.7, srcdir != builddir
+ "/bin/sh ../../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic "
+ "-W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align "
+ "-Wconversion -Wchar-subscripts -fno-builtin -g3 -Wformat-security -Wmissing-format-attribute -fno-exceptions "
+ "-fno-check-new -fno-common -o libkdevoutputviews.la.closure libkdevoutputviews_la_closure.lo -L/usr/X11R6/lib "
+ "-L/home/john/src/kde/qt-copy/lib -L/usr/local/kde/lib -avoid-version -module -no-undefined -R /usr/local/kde/lib "
+ "-R /home/john/src/kde/qt-copy/lib -R /usr/X11R6/lib outputviewsfactory.lo makeviewpart.lo makewidget.lo "
+ "appoutputviewpart.lo appoutputwidget.lo directorystatusmessagefilter.lo outputfilter.lo compileerrorfilter.lo "
+ "commandcontinuationfilter.lo makeitem.lo makeactionfilter.lo otherfilter.lo ../../lib/libkdevelop.la",
+ "linking", "libtool", "libkdevoutputviews.la.closure" )
+ << TestItem( //libtool, linking 2
+ "/bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic "
+ "-W -Wpointer-arith -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -Wchar-subscripts "
+ "-fno-builtin -g3 -fno-exceptions -fno-check-new -fno-common -o libkfilereplacepart.la.closure libkfilereplacepart_la_closure.lo "
+ "-module -no-undefined -L/usr/X11R6/lib -L/usr/lib/qt3/lib -L/opt/kde3/lib -version-info 1:0:0 kfilereplacepart.lo kfilereplacedoc.lo "
+ "kfilereplaceview.lo kaboutkfilereplace.lo kaddstringdlg.lo kconfirmdlg.lo kernel.lo kexpression.lo kfilereplacepref.lo "
+ "klistviewstring.lo knewprojectdlg.lo koptionsdlg.lo kresultview.lo filelib.lo knewprojectdlgs.lo -lkio -lkparts -lkhtml",
+ "linking", "libtool", "libkfilereplacepart.la.closure")
+ << TestItem( //libtool, linking 3
+ "/bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall -pedantic "
+ "-W -Wpointer-arith -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -Wchar-subscripts "
+ "-fno-builtin -g3 -fno-exceptions -fno-check-new -fno-common -o libkfilereplacepart.la -rpath /opt/kde3/lib/kde3 "
+ "-module -no-undefined -L/usr/X11R6/lib -L/usr/lib/qt3/lib -L/opt/kde3/lib -version-info 1:0:0 kfilereplacepart.lo "
+ "kfilereplacedoc.lo kfilereplaceview.lo kaboutkfilereplace.lo kaddstringdlg.lo kconfirmdlg.lo kernel.lo kexpression.lo "
+ "kfilereplacepref.lo klistviewstring.lo knewprojectdlg.lo koptionsdlg.lo kresultview.lo filelib.lo knewprojectdlgs.lo -lkio -lkparts -lkhtml",
+ "linking", "libtool", "libkfilereplacepart.la")
+ << TestItem( //automake, builddir!=srcdir, libtool=no, compiling
+ " g++ -DHAVE_CONFIG_H -I. -I/home/andris/cvs-developement/head/quanta/quanta/project "
+ "-I../.. -I/home/andris/cvs-developement/head/quanta/quanta/dialogs -I/opt/kde3/include -I/usr/lib/qt3/include -I/usr/X11R6/include "
+ "-I../../quanta/dialogs -DQT_THREAD_SUPPORT -D_REENTRANT -DKOMMANDER -DDESIGNER -DQT_NO_SQL -DHAVE_KDE -Wnon-virtual-dtor "
+ "-Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE "
+ "-Wcast-align -Wconversion -Wchar-subscripts -fno-builtin -g3 -DKDE_NO_COMPAT -fno-exceptions -fno-check-new -fno-common -c -o project.o "
+ "`test -f '/home/andris/cvs-developement/head/quanta/quanta/project/project.cpp' || "
+ "echo '/home/andris/cvs-developement/head/quanta/quanta/project/'`/home/andris/cvs-developement/head/quanta/quanta/project/project.cpp ",
+ "compiling", "g++", "project.cpp")
+ << TestItem(
+ "/usr/local/kde/bin/dcopidl /home/john/src/kde/kdevelop/lib/interfaces/KDevAppFrontendIface.h > KDevAppFrontendIface.kidl "
+ "|| ( rm -f KDevAppFrontendIface.kidl ; /bin/false )",
+ "generating", "dcopidl", "KDevAppFrontendIface.kidl" )
+ << TestItem(
+ "/usr/local/kde/bin/dcopidl2cpp --c++-suffix cpp --no-signals --no-stub KDevAppFrontendIface.kidl",
+ "compiling", "dcopidl2cpp", "KDevAppFrontendIface.kidl" )
+ << TestItem( //install
+ "/usr/bin/install -c -p -m 644 /home/andris/development/quanta/quanta/kommander/editor/kmdr-editor.desktop "
+ "/opt/kde3/share/applnk/Editors/kmdr-editor.desktop", "installing", "", "/opt/kde3/share/applnk/Editors/kmdr-editor.desktop")
+ << TestItem( //libtool install
+ "/bin/sh ../../libtool --silent --mode=install /usr/bin/install -c -p libkommanderwidgets.la "
+ "/opt/kde3/lib/libkommanderwidgets.la", "installing", "", "/opt/kde3/lib/libkommanderwidgets.la")
+ << TestItem( //libtool, automake 1.8
+ "if g++ -DHAVE_CONFIG_H -I. -I/home/andris/ "
+ "-DBUILD_KAFKAPART -MT quanta_init.o -MD -MP -MF \".deps/quanta_init.Tpo\" -c -o quanta_init.o "
+ "quanta_init.cpp; "
+ "then mv -f \".deps/quanta_init.Tpo\" \".deps/quanta_init.Po\"; else rm -f \".deps/quanta_init.Tpo\"; "
+ "exit 1; fi",
+ "compiling", "g++", "quanta_init.cpp")
+ << TestItem( //libtool, automake 1.8, file with full path
+ "if g++ -DHAVE_CONFIG_H -I. -I/home/andris/ "
+ "-DBUILD_KAFKAPART -MT quanta_init.o -MD -MP -MF \".deps/quanta_init.Tpo\" -c -o quanta_init.o "
+ "/home/andris/quanta_init.cpp; "
+ "then mv -f \".deps/quanta_init.Tpo\" \".deps/quanta_init.Po\"; else rm -f \".deps/quanta_init.Tpo\"; "
+ "exit 1; fi",
+ "compiling", "g++", "quanta_init.cpp")
+ ;
+
+ QValueList<TestItem>::const_iterator it = testItems.begin();
+ for( ; it != testItems.end(); ++it )
+ {
+ ActionItem* actionItem = matchLine( (*it).line );
+ if ( actionItem == NULL )
+ {
+ kdError( 9004 ) << "MakeActionFilter::test(): match failed (no match):" << endl;
+ kdError( 9004 ) << (*it).line << endl;
+ }
+ else if ( actionItem->m_action != (*it).action )
+ {
+ kdError( 9004 ) << "MakeActionFilter::test(): match failed (expected action "
+ << (*it).action << ", got " << actionItem->m_action << endl;
+ kdError( 9004 ) << (*it).line << endl;
+ }
+ else if ( actionItem->m_tool != (*it).tool )
+ {
+ kdError( 9004 ) << "MakeActionFilter::test(): match failed (expected tool "
+ << (*it).tool << ", got " << actionItem->m_tool << endl;
+ kdError( 9004 ) << (*it).line << endl;
+ }
+ else if ( actionItem->m_file != (*it).file )
+ {
+ kdError( 9004 ) << "MakeActionFilter::test(): match failed (expected file "
+ << (*it).file << ", got " << actionItem->m_file << endl;
+ kdError( 9004 ) << (*it).line << endl;
+ } else
+ kdDebug( 9004 ) << "Test passed, " << actionItem->m_action << " " << actionItem->m_file << " (" << actionItem->m_tool << ") found." << endl;
+ if ( actionItem != NULL )
+ delete actionItem;
+ }
+
+}
+
+#endif
diff --git a/parts/outputviews/makeactionfilter.h b/parts/outputviews/makeactionfilter.h
new file mode 100644
index 00000000..66de7a3b
--- /dev/null
+++ b/parts/outputviews/makeactionfilter.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * 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 MakeActionFilter_h
+#define MakeActionFilter_h
+
+#include <qobject.h>
+#include <qregexp.h>
+#include <qvaluelist.h>
+#include "outputfilter.h"
+
+class MakeItem;
+class ActionItem;
+
+class MakeActionFilter : public QObject, public OutputFilter
+{
+Q_OBJECT
+
+public:
+#ifdef DEBUG
+ static void test();
+#endif
+
+ MakeActionFilter( OutputFilter& );
+
+ class ActionFormat
+ {
+ public:
+ ActionFormat():m_toolGroup(-1) {}
+ ActionFormat( const QString&, const QString&, const char * regExp, int file);
+ ActionFormat( const QString&, int tool, int file, const char * regExp);
+ QString tool();
+ QString file();
+ const QString& action() const {return m_action;}
+ bool matches(const QString& line);
+ private:
+ QString m_action;
+ QRegExp m_expression;
+ QString m_tool;
+ int m_toolGroup;
+ int m_fileGroup;
+ };
+ static ActionFormat* actionFormats();
+
+ void processLine( const QString& line );
+
+signals:
+ void item( MakeItem* );
+
+private:
+ static ActionItem* matchLine( const QString& line );
+};
+
+#endif
diff --git a/parts/outputviews/makeitem.cpp b/parts/outputviews/makeitem.cpp
new file mode 100644
index 00000000..c4d5a04c
--- /dev/null
+++ b/parts/outputviews/makeitem.cpp
@@ -0,0 +1,166 @@
+/***************************************************************************
+ * 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 "makeitem.h"
+
+#include <qstylesheet.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "ktexteditor/cursorinterface.h"
+
+MakeItem::MakeItem()
+{
+}
+
+MakeItem::MakeItem( const QString& text )
+ : m_text( text )
+{
+}
+
+MakeItem::~MakeItem()
+{
+}
+
+QString MakeItem::color( bool bright_bg )
+{
+ switch ( type() )
+ {
+ case Error:
+ return bright_bg ? "maroon" : "red";
+ case Warning:
+ return bright_bg ? "#666" : "#999";
+ case Diagnostic:
+ return bright_bg ? "black" : "white";
+ default:
+ return bright_bg ? "navy" : "blue";
+ }
+}
+
+QString MakeItem::icon()
+{
+ switch ( type() )
+ {
+ case Error:
+ case Warning:
+ return "<img src=\"error\"></img><nobr> </nobr>";
+ case Diagnostic:
+ return "<img src=\"warning\"></img><nobr> </nobr>";
+ default:
+ return "<img src=\"message\"></img><nobr> </nobr>";
+ }
+}
+
+QString MakeItem::text( EOutputLevel )
+{
+ return QStyleSheet::escape( m_text );
+}
+
+QString MakeItem::formattedText( EOutputLevel level, bool bright_bg )
+{
+ QString txt = text(level);
+ if (txt.isEmpty())
+ return "<br>";
+ if ( level == eFull )
+ {
+ return txt;
+ }
+ else
+ {
+ return QString("<code>")
+ .append( icon() ).append("<font color=\"").append( color( bright_bg) ).append("\">")
+ .append( txt ).append("</font></code>").append( br() );
+ }
+}
+
+QString MakeItem::br()
+{
+ // Qt >= 3.1 doesn't need a <br>.
+#if QT_VERSION < 0x040000
+ static const QString br = QString::fromLatin1( qVersion() ).section( ".", 1, 1 ).toInt() > 0 ? "" : "<br>";
+#else
+ static const QString br;
+#endif
+ return br;
+}
+
+ErrorItem::ErrorItem( const QString& fn, int ln, const QString& tx, const QString& line, bool isWarning, bool isInstatiationInfo, const QString& compiler )
+ : MakeItem( line )
+ , fileName(fn)
+ , lineNum(ln)
+ , m_error(tx)
+ , m_isWarning(isWarning | isInstatiationInfo)
+ , m_isInstatiationInfo( isInstatiationInfo )
+ , m_compiler(compiler)
+{}
+
+ErrorItem::~ErrorItem()
+{
+}
+
+bool ErrorItem::append( const QString& text )
+{
+ if ( !text.startsWith(" ") )
+ return false;
+ if ( text.startsWith(" ") && (m_compiler == "intel") )
+ return false;
+ m_text += text;
+ m_error += text;
+ m_error = m_error.simplifyWhiteSpace();
+ m_text = m_text.simplifyWhiteSpace();
+ return true;
+}
+
+ExitStatusItem::ExitStatusItem( bool normalExit, int exitStatus )
+ : m_normalExit( normalExit )
+ , m_exitStatus( exitStatus )
+{
+// kdDebug() << "ExitStatusItem: normalExit=" << normalExit << "; exitStatus=" << exitStatus << endl;
+ m_text = i18n("*** Compilation aborted ***");
+ if ( m_normalExit )
+ if (m_exitStatus )
+ m_text = i18n("*** Exited with status: %1 ***").arg( m_exitStatus );
+ else
+ m_text = i18n("*** Success ***");
+}
+
+QString ExitStatusItem::text( EOutputLevel )
+{
+ return m_text;
+}
+
+bool DirectoryItem::m_showDirectoryMessages = true;
+
+QString EnteringDirectoryItem::text( EOutputLevel outputLevel )
+{
+ if ( outputLevel < eFull )
+ return i18n("Entering directory %1").arg( directory );
+ return m_text;
+}
+
+QString ExitingDirectoryItem::text( EOutputLevel outputLevel )
+{
+ if ( outputLevel < eFull )
+ return i18n("Leaving directory %1").arg( directory );
+ return m_text;
+}
+
+QString ActionItem::text( EOutputLevel outputLevel )
+{
+ if ( outputLevel < eFull )
+ {
+ if ( m_tool.isEmpty() )
+ return QString(m_action).append(" <b>").append(m_file).append("</b>");
+ return QString(m_action).append(" <b>").append(m_file).append("</b>").append(" (").append(m_tool).append(")");
+ }
+ return MakeItem::text( outputLevel );
+}
diff --git a/parts/outputviews/makeitem.h b/parts/outputviews/makeitem.h
new file mode 100644
index 00000000..e95dd4df
--- /dev/null
+++ b/parts/outputviews/makeitem.h
@@ -0,0 +1,164 @@
+/***************************************************************************
+ * 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 MakeItem_h
+#define MakeItem_h
+
+#include <qstring.h>
+
+enum EOutputLevel
+{
+ // appropriate to the ID's in the button group of settingswidget.ui
+ eVeryShort = 0
+ ,eShort
+ ,eFull
+};
+
+class MakeItem
+{
+public:
+ enum Type { Normal, Error, Warning, Diagnostic };
+ MakeItem();
+ MakeItem( const QString& text );
+ virtual ~MakeItem();
+
+ enum DisplayModes
+ {
+ DelayedDisplay = 0, // item can be displayed later
+ ImmDisplay = 1, // item has to be displayed ASAP
+ Append = 2 // item's text can be appended (append has been overloaded)
+ };
+ virtual int displayMode() const { return ImmDisplay; }
+ virtual bool append( const QString& ) { return false; }
+ virtual Type type() { return Diagnostic; }
+ virtual bool visible( EOutputLevel level ) { return level > eVeryShort; }
+ virtual QString text( EOutputLevel );
+ virtual QString formattedText( EOutputLevel, bool bright_bg );
+ QString icon();
+ QString color( bool bright_bg );
+
+ static QString br();
+
+ QString m_text;
+};
+
+class CommandItem : public MakeItem
+{
+public:
+ CommandItem(const QString command)
+ : MakeItem( command )
+ {}
+
+ Type type() { return Diagnostic; }
+ virtual bool visible( EOutputLevel ) { return true; }
+};
+
+class ExitStatusItem : public MakeItem
+{
+public:
+ ExitStatusItem( bool normalExit, int exitStatus );
+
+ Type type() { return m_normalExit && m_exitStatus == 0 ? Diagnostic : Error; }
+ virtual bool visible( EOutputLevel ) { return true; }
+ QString text( EOutputLevel level );
+
+private:
+ bool m_normalExit;
+ int m_exitStatus;
+};
+
+class DirectoryItem : public MakeItem
+{
+public:
+ DirectoryItem( const QString& dir, const QString& text )
+ : MakeItem( text )
+ , directory( dir )
+ {}
+
+ Type type() { return Diagnostic; }
+
+ static void setShowDirectoryMessages( bool show ) { m_showDirectoryMessages = show; }
+ static bool getShowDirectoryMessages() { return m_showDirectoryMessages; }
+
+ QString directory;
+
+protected:
+ static bool m_showDirectoryMessages;
+};
+
+class EnteringDirectoryItem : public DirectoryItem
+{
+public:
+ EnteringDirectoryItem( const QString& dir, const QString& text )
+ : DirectoryItem( dir, text )
+ {}
+ bool visible( EOutputLevel )
+ {
+ return m_showDirectoryMessages;
+ }
+
+ virtual QString text( EOutputLevel );
+};
+
+class ExitingDirectoryItem : public DirectoryItem
+{
+public:
+ ExitingDirectoryItem( const QString& dir, const QString& text )
+ : DirectoryItem( dir, text )
+ {}
+ bool visible( EOutputLevel level )
+ {
+ return m_showDirectoryMessages && level > eVeryShort;
+ }
+
+ virtual QString text( EOutputLevel );
+};
+
+namespace KTextEditor { class Cursor; class Document; }
+
+class ErrorItem : public MakeItem
+{
+public:
+ ErrorItem( const QString& fn, int ln, const QString& tx, const QString& line, bool isWarning, bool isInstatiationInfo, const QString& compiler );
+ virtual ~ErrorItem();
+
+ virtual bool append( const QString& text );
+ virtual int displayMode() const { return DelayedDisplay | Append; }
+ Type type() { return m_isInstatiationInfo ? Diagnostic : (m_isWarning ? Warning : Error); }
+ virtual bool visible( EOutputLevel ) { return true; }
+
+ QString fileName;
+ int lineNum;
+ QString m_error;
+ bool m_isWarning;
+ bool m_isInstatiationInfo; ///this also implies isWarning
+ QString m_compiler;
+};
+
+class ActionItem : public MakeItem
+{
+public:
+ ActionItem( const QString& action, const QString& file, const QString& tool, const QString& line )
+ : MakeItem( line )
+ , m_action( action )
+ , m_file( file )
+ , m_tool( tool )
+ {}
+
+ virtual bool visible( EOutputLevel ) { return true; }
+ virtual QString text( EOutputLevel level );
+
+ QString m_action;
+ QString m_file;
+ QString m_tool;
+};
+
+#endif
diff --git a/parts/outputviews/makeviewpart.cpp b/parts/outputviews/makeviewpart.cpp
new file mode 100644
index 00000000..3f2ebbd8
--- /dev/null
+++ b/parts/outputviews/makeviewpart.cpp
@@ -0,0 +1,105 @@
+/***************************************************************************
+ * 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 "makeviewpart.h"
+
+#include <qwhatsthis.h>
+#include <qdir.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kiconloader.h>
+#include <kdevgenericfactory.h>
+#include <kdevplugininfo.h>
+
+#include "kdevproject.h"
+#include "kdevcore.h"
+#include "kdevmainwindow.h"
+
+#include "makewidget.h"
+
+static const KDevPluginInfo data("kdevmakeview");
+typedef KDevGenericFactory< MakeViewPart > MakeViewFactory;
+K_EXPORT_COMPONENT_FACTORY( libkdevmakeview, MakeViewFactory( data ) )
+
+MakeViewPart::MakeViewPart(QObject *parent, const char *name, const QStringList &)
+ : KDevMakeFrontend(&data, parent, name)
+{
+ setInstance(MakeViewFactory::instance());
+
+ setXMLFile("kdevmakeview.rc");
+
+ m_dcop = new KDevMakeFrontendIface(this);
+
+ m_widget = new MakeWidget(this);
+ m_widget->setIcon( SmallIcon("exec") );
+ m_widget->setCaption(i18n("Messages Output"));
+ QWhatsThis::add(m_widget, i18n("<b>Messages output</b><p>"
+ "The messages window shows the output of the compiler and "
+ "used build tools like make, ant, uic, dcopidl etc. "
+ "For compiler error messages, click on the error message. "
+ "This will automatically open the source file and set the "
+ "cursor to the line that caused the compiler error/warning."));
+
+ mainWindow()->embedOutputView(m_widget, i18n("Messages"), i18n("Compiler output messages"));
+
+ KAction *action;
+ action = new KAction( i18n("&Next Error"), Key_F4, m_widget, SLOT(nextError()),
+ actionCollection(), "view_next_error");
+ action->setToolTip( i18n("Go to the next error") );
+ action->setWhatsThis(i18n("<b>Next error</b><p>Switches to the file and line where the next error was reported from."));
+ action = new KAction( i18n("&Previous Error"), SHIFT+Key_F4, m_widget, SLOT(prevError()),
+ actionCollection(), "view_previous_error");
+ action->setToolTip( i18n("Go to the previous error") );
+ action->setWhatsThis(i18n("<b>Previous error</b><p>Switches to the file and line where the previous error was reported from."));
+
+ connect( core(), SIGNAL(stopButtonClicked(KDevPlugin*)),
+ this, SLOT(slotStopButtonClicked(KDevPlugin*)) );
+}
+
+
+MakeViewPart::~MakeViewPart()
+{
+ if ( m_widget )
+ mainWindow()->removeView( m_widget );
+ delete m_widget;
+ delete m_dcop;
+}
+
+void MakeViewPart::slotStopButtonClicked(KDevPlugin* which)
+{
+ if ( which != 0 && which != this )
+ return;
+ m_widget->killJob();
+}
+
+void MakeViewPart::queueCommand(const QString &dir, const QString &command)
+{
+ m_widget->queueJob(dir, command);
+}
+
+
+bool MakeViewPart::isRunning()
+{
+ return m_widget->isRunning();
+}
+
+QWidget* MakeViewPart::widget()
+{
+ return m_widget.operator->();
+}
+
+void MakeViewPart::updateSettingsFromConfig()
+{
+ m_widget->updateSettingsFromConfig();
+}
+
+#include "makeviewpart.moc"
diff --git a/parts/outputviews/makeviewpart.h b/parts/outputviews/makeviewpart.h
new file mode 100644
index 00000000..78f969ff
--- /dev/null
+++ b/parts/outputviews/makeviewpart.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * 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 _MAKEVIEWPART_H_
+#define _MAKEVIEWPART_H_
+
+#include <qguardedptr.h>
+
+#include "kdevmakefrontend.h"
+#include "KDevMakeFrontendIface.h"
+
+
+class MakeWidget;
+
+class MakeViewPart : public KDevMakeFrontend
+{
+ Q_OBJECT
+
+public:
+ MakeViewPart( QObject *parent, const char *name, const QStringList & );
+ ~MakeViewPart();
+ virtual QWidget* widget();
+ virtual void updateSettingsFromConfig();
+
+private slots:
+ void slotStopButtonClicked(KDevPlugin*);
+
+protected:
+ virtual void queueCommand(const QString &dir, const QString &command);
+ virtual bool isRunning();
+
+private:
+ QGuardedPtr<MakeWidget> m_widget;
+ KDevMakeFrontendIface *m_dcop;
+ friend class MakeWidget;
+};
+
+#endif
diff --git a/parts/outputviews/makewidget.cpp b/parts/outputviews/makewidget.cpp
new file mode 100644
index 00000000..554713c4
--- /dev/null
+++ b/parts/outputviews/makewidget.cpp
@@ -0,0 +1,847 @@
+/***************************************************************************
+ * 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 "makewidget.h"
+#include "kdevcore.h"
+#include "kdevmainwindow.h"
+#include "kdevproject.h"
+#include "kdevpartcontroller.h"
+#include "processlinemaker.h"
+#include "makeviewpart.h"
+#include "makeitem.h"
+#include "ktexteditor/document.h"
+#include "ktexteditor/cursorinterface.h"
+#include "ktexteditor/editinterface.h"
+#include "urlutil.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <knotifyclient.h>
+#include <kprocess.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kinstance.h>
+#include <kstatusbar.h>
+#include <kapplication.h>
+#include <kconfig.h>
+
+#include <qmessagebox.h>
+#include <qapplication.h>
+#include <qdir.h>
+#include <qimage.h>
+#include <qstylesheet.h>
+#include <qtimer.h>
+#include <qfileinfo.h>
+#include <qclipboard.h>
+#include <qpopupmenu.h>
+#include <private/qrichtext_p.h>
+
+#include <stdlib.h>
+#include <limits.h>
+
+static const char *const error_xpm[] =
+ {
+ "11 11 5 1",
+ ". c None",
+ "# c #313062",
+ "a c #6261cd",
+ "b c #c50000",
+ "c c #ff8583",
+ "...........",
+ "...####....",
+ ".a#bbbb#a..",
+ ".#ccbbbb#..",
+ "#bccbbbbb#.",
+ "#bbbbbbbb#.",
+ "#bbbbbbcb#.",
+ "#bbbbbccb#.",
+ ".#bbbccb#..",
+ ".a#bbbb#a..",
+ "...####...."
+ };
+
+
+static const char *const warning_xpm[] =
+ {
+ "11 11 5 1",
+ ". c None",
+ "# c #313062",
+ "a c #6261cd",
+ "b c #c5c600",
+ "c c #ffff41",
+ "...........",
+ "...####....",
+ ".a#bbbb#a..",
+ ".#ccbbbb#..",
+ "#bccbbbbb#.",
+ "#bbbbbbbb#.",
+ "#bbbbbbcb#.",
+ "#bbbbbccb#.",
+ ".#bbbccb#..",
+ ".a#bbbb#a..",
+ "...####...."
+ };
+
+
+static const char *const message_xpm[] =
+ {
+ "11 11 5 1",
+ ". c None",
+ "b c #3100c5",
+ "# c #313062",
+ "c c #3189ff",
+ "a c #6265cd",
+ "...........",
+ "...####....",
+ ".a#bbbb#a..",
+ ".#ccbbbb#..",
+ "#bccbbbbb#.",
+ "#bbbbbbbb#.",
+ "#bbbbbbcb#.",
+ "#bbbbbccb#.",
+ ".#bbbccb#..",
+ ".a#bbbb#a..",
+ "...####...."
+ };
+
+
+class SelectionPreserver
+{
+public:
+ SelectionPreserver( QTextEdit& textEdit, bool stayAtEnd )
+ : m_textEdit( textEdit )
+ , m_atEnd( false )
+ {
+ int para, index;
+ m_textEdit.getCursorPosition( &para, &index );
+
+ m_atEnd = stayAtEnd
+ && para == m_textEdit.paragraphs() - 1
+ && index == m_textEdit.paragraphLength( para );
+
+ m_textEdit.getSelection(&paraFrom, &indexFrom, &paraTo, &indexTo, 0);
+ }
+
+ ~SelectionPreserver()
+ {
+ m_textEdit.setSelection(paraFrom, indexFrom, paraTo, indexTo, 0);
+
+ if ( m_atEnd )
+ {
+ m_textEdit.moveCursor(QTextEdit::MoveEnd, false);
+ m_textEdit.moveCursor(QTextEdit::MoveLineStart, false);//if linewrap is off we must avoid the jumping of the vertical scrollbar
+ }
+ }
+
+ QTextEdit& m_textEdit;
+ bool m_atEnd;
+ int paraFrom, indexFrom, paraTo, indexTo;
+};
+
+MakeWidget::MakeWidget(MakeViewPart *part)
+ : QTextEdit(0, "make widget")
+ , m_directoryStatusFilter( m_errorFilter )
+ , m_errorFilter( m_continuationFilter )
+ , m_continuationFilter( m_actionFilter )
+ , m_actionFilter( m_otherFilter )
+ , m_pendingItem(0)
+ , m_paragraphs(0)
+ , m_lastErrorSelected(-1)
+ , m_part(part)
+ , m_vertScrolling(false)
+ , m_horizScrolling(false)
+ , m_bCompiling(false)
+{
+ updateSettingsFromConfig();
+
+ setTextFormat( Qt::RichText );
+
+ if ( m_bLineWrapping )
+ setWordWrap(WidgetWidth);
+ else
+ setWordWrap(NoWrap);
+
+ setWrapPolicy(Anywhere);
+ setReadOnly(true);
+ setMimeSourceFactory(new QMimeSourceFactory);
+ mimeSourceFactory()->setImage("error", QImage((const char**)error_xpm));
+ mimeSourceFactory()->setImage("warning", QImage((const char**)warning_xpm));
+ mimeSourceFactory()->setImage("message", QImage((const char**)message_xpm));
+
+ dirstack.setAutoDelete(true);
+
+ childproc = new KProcess(this);
+ procLineMaker = new ProcessLineMaker( childproc );
+
+ connect( procLineMaker, SIGNAL(receivedStdoutLine(const QCString&)),
+ this, SLOT(insertStdoutLine(const QCString&) ));
+ connect( procLineMaker, SIGNAL(receivedStderrLine(const QCString&)),
+ this, SLOT(insertStderrLine(const QCString&) ));
+ connect( procLineMaker, SIGNAL(receivedPartialStdoutLine(const QCString&)),
+ this, SLOT(storePartialStdoutLine(const QCString&) ));
+ connect( procLineMaker, SIGNAL(receivedPartialStderrLine(const QCString&)),
+ this, SLOT(storePartialStderrLine(const QCString&) ));
+
+ connect( childproc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*) )) ;
+
+ connect( &m_directoryStatusFilter, SIGNAL(item(EnteringDirectoryItem*)),
+ this, SLOT(slotEnteredDirectory(EnteringDirectoryItem*)) );
+ connect( &m_directoryStatusFilter, SIGNAL(item(ExitingDirectoryItem*)),
+ this, SLOT(slotExitedDirectory(ExitingDirectoryItem*)) );
+ connect( &m_errorFilter, SIGNAL(item(MakeItem*)),
+ this, SLOT(insertItem(MakeItem*)) );
+ connect( &m_actionFilter, SIGNAL(item(MakeItem*)),
+ this, SLOT(insertItem(MakeItem*)) );
+ connect( &m_otherFilter, SIGNAL(item(MakeItem*)),
+ this, SLOT(insertItem(MakeItem*)) );
+
+ connect( verticalScrollBar(), SIGNAL(sliderPressed()),
+ this, SLOT(verticScrollingOn()) );
+ connect( verticalScrollBar(), SIGNAL(sliderReleased()),
+ this, SLOT(verticScrollingOff()) );
+ connect( horizontalScrollBar(), SIGNAL(sliderPressed()),
+ this, SLOT(horizScrollingOn()) );
+ connect( horizontalScrollBar(), SIGNAL(sliderReleased()),
+ this, SLOT(horizScrollingOff()) );
+
+// this slot doesn't exist anymore
+// connect( m_part->partController(), SIGNAL(loadedFile(const KURL&)),
+// this, SLOT(slotDocumentOpened(const KURL&)) );
+}
+
+MakeWidget::~MakeWidget()
+{
+ delete mimeSourceFactory();
+ delete childproc;
+ delete procLineMaker;
+}
+
+void MakeWidget::queueJob(const QString &dir, const QString &command)
+{
+ commandList.append(command);
+ dirList.append(dir);
+ if (!isRunning())
+ {
+ // Store the current output view so that it
+ // can be restored after a successful compilation
+// m_part->mainWindow()->storeOutputViewTab();
+ startNextJob();
+ }
+}
+
+void MakeWidget::startNextJob()
+{
+ QStringList::Iterator it = commandList.begin();
+ if ( it == commandList.end() )
+ return;
+
+ currentCommand = *it;
+ commandList.remove(it);
+
+ int i = currentCommand.findRev(" gmake");
+ if ( i == -1 )
+ i = currentCommand.findRev(" make");
+ if ( i == -1 )
+ m_bCompiling = false;
+ else
+ {
+ QString s = currentCommand.right(currentCommand.length() - i);
+ if ( s.contains("configure ") ||
+ s.contains(" Makefile.cvs") ||
+ s.contains(" clean") ||
+ s.contains(" distclean") ||
+ s.contains(" package-messages") ||
+ s.contains(" install") )
+ {
+ m_bCompiling = false;
+ }
+ else {
+ m_bCompiling = true;
+ }
+ }
+
+ it = dirList.begin();
+ QString dir = *it;
+ m_lastBuildDir = dir;
+ dirList.remove(it);
+
+ clear(); // clear the widget
+ for ( QValueVector<MakeItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it )
+ delete *it;
+ m_items.clear();
+ m_paragraphToItem.clear();
+ m_paragraphs = 0;
+ m_lastErrorSelected = -1;
+
+ insertItem( new CommandItem( currentCommand ) );
+
+ childproc->clearArguments();
+ *childproc << currentCommand;
+ childproc->setUseShell(true);
+ childproc->start(KProcess::OwnGroup, KProcess::AllOutput);
+
+ dirstack.clear();
+ dirstack.push(new QString(dir));
+
+ m_part->mainWindow()->raiseView(this);
+ m_part->core()->running(m_part, true);
+}
+
+void MakeWidget::killJob()
+{
+ if (!childproc->kill(SIGINT))
+ childproc->kill();
+}
+
+bool MakeWidget::isRunning()
+{
+ return childproc->isRunning();
+}
+
+void MakeWidget::copy()
+{
+ int parafrom=0, indexfrom=0, parato=0, indexto=0;
+ getSelection(&parafrom, &indexfrom, &parato, &indexto);
+ if( parafrom < 0 || indexfrom < 0 || parato < 0 || indexto < 0
+ || ((parafrom == parato) && (indexfrom == indexto)) )
+ {
+ return;
+ }
+
+ QString selection;
+ for(int i = parafrom; i<=parato; i++)
+ selection += text(i) + "\n";
+
+
+ if(m_compilerOutputLevel == eShort ||
+ m_compilerOutputLevel == eVeryShort )
+ {
+ QRegExp regexp("<.*>");
+ regexp.setMinimal(true);
+ selection.remove(regexp);
+ }
+ else
+ { //FIXME: Selections should be precise in the eShort and eVeryShort modes, too.
+ selection.remove(0, indexfrom);
+ int removeend = text(parato).length() - indexto;
+
+ selection.remove((selection.length()-1) - removeend, removeend);
+ }
+
+ selection.replace("&lt;","<");
+ selection.replace("&gt;",">");
+ selection.replace("&quot;","\"");
+ selection.replace("&amp;","&");
+
+ kapp->clipboard()->setText(selection, QClipboard::Clipboard);
+}
+
+void MakeWidget::nextError()
+{
+ int parag;
+ if (m_lastErrorSelected != -1)
+ parag = m_lastErrorSelected;
+ else
+ parag = 0;
+
+ //if there are no errors after m_lastErrorSelected try again from the beginning
+ if (!scanErrorForward(parag))
+ if (m_lastErrorSelected != -1)
+ {
+ m_lastErrorSelected = -1;
+ if (!scanErrorForward(0))
+ KNotifyClient::beep();
+ }
+ else
+ KNotifyClient::beep();
+}
+
+void MakeWidget::prevError()
+{
+ int parag;
+ if (m_lastErrorSelected != -1)
+ parag = m_lastErrorSelected;
+ else
+ parag = 0;
+
+ //if there are no errors before m_lastErrorSelected try again from the end
+ if (!scanErrorBackward(parag))
+ if (m_lastErrorSelected != -1)
+ {
+ m_lastErrorSelected = -1;
+#if QT_VERSION >= 0x030100
+ parag = (int)m_items.count();
+#else
+ parag = m_items.size();
+#endif
+ if (!scanErrorBackward(parag))
+ KNotifyClient::beep();
+ }
+ else
+ KNotifyClient::beep();
+}
+
+void MakeWidget::contentsMouseReleaseEvent( QMouseEvent* e )
+{
+ QTextEdit::contentsMouseReleaseEvent(e);
+ if ( e->button() != LeftButton )
+ return;
+ searchItem(paragraphAt(e->pos()));
+}
+
+void MakeWidget::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Key_Return || e->key() == Key_Enter)
+ {
+ int parag, index;
+ getCursorPosition(&parag, &index);
+ searchItem(parag);
+ }
+ else
+ QTextEdit::keyPressEvent(e);
+}
+
+// returns the current directory for parag
+QString MakeWidget::directory(int parag) const
+{
+ QValueVector<MakeItem*>::const_iterator it = qFind( m_items.begin(), m_items.end(), m_paragraphToItem[parag] );
+ if ( it == m_items.end() )
+ return QString::null;
+ // run backwards over directories and figure out where we are
+ while ( it != m_items.begin() ) {
+ --it;
+ EnteringDirectoryItem* edi = dynamic_cast<EnteringDirectoryItem*>( *it );
+ if ( edi )
+ return edi->directory + "/";
+ }
+ return QString::null;
+}
+
+// hackish function that will return true and put string "file" in "fName" if the file
+// exists
+static bool checkFileExists( const QString& file, QString& fName )
+{
+ if ( QFile::exists( file ) ) {
+ fName = file;
+ return true;
+ }
+ return false;
+}
+
+void MakeWidget::specialCheck( const QString& file, QString& fName ) const
+{
+ QString firstLine = text(0);
+ QRegExp rx("cd \\'(.*)\\'.*");
+ if (rx.search(firstLine) != -1)
+ {
+ KURL url(rx.cap(1)+"/", file);
+ if (url.isValid())
+ {
+ kdDebug(9004) << "MakeWidget::specialCheck thinks that url is: " << url.url()
+ << " origin: " << file << endl;
+ fName = url.url();
+ return;
+ }
+ }
+ // Ok the "worst case", lets see if we can find a file in the project that has the same name
+ // obviously this will pick always the wrong file when you've got the same filename multiple times.
+ QStringList files = m_part->project()->allFiles();
+ for( QStringList::iterator it = files.begin() ; it != files.end(); ++it)
+ {
+ if( (*it).contains( file ) )
+ {
+ fName = URLUtil::canonicalPath( m_part->project()->projectDirectory() + "/" + *it );
+ }
+ }
+}
+
+QString MakeWidget::guessFileName( const QString& fName, int parag ) const
+{
+ // pathological case
+ if ( ! m_part->project() ) return fName;
+
+ QString name;
+ QString dir = directory( parag );
+
+ if ( fName.startsWith( "/" ) )
+ {
+ // absolute path given
+ name = fName;
+ }
+ else if ( !dir.isEmpty() )
+ {
+ name = dir + fName;
+ }
+ else
+ {
+ // now it gets tricky - no directory navigation messages,
+ // no absolute path - let's guess.
+ name = fName;
+ if ( !checkFileExists( m_lastBuildDir + "/" + fName, name) &&
+ !checkFileExists( m_part->project()->projectDirectory() + "/" + fName, name ) &&
+ !checkFileExists( m_part->project()->projectDirectory() + "/" + m_part->project()->activeDirectory() + "/" + fName, name ) &&
+ !checkFileExists( m_part->project()->buildDirectory() + "/" + fName, name ) )
+ specialCheck(fName, name);
+ }
+
+ kdDebug(9004) << "Opening file: " << name << endl;
+
+ // GNU make resolves symlinks. if "name" is a real path to a file the
+ // project know by symlink path, we need to return the symlink path
+// QStringList projectFiles = m_part->project()->allFiles();
+ QStringList projectFiles = m_part->project()->symlinkProjectFiles();
+ QStringList::iterator it = projectFiles.begin();
+ while ( it != projectFiles.end() )
+ {
+ QString file = m_part->project()->projectDirectory() + "/" + *it;
+ if ( name == URLUtil::canonicalPath( file ) )
+ {
+ kdDebug(9004) << "Found file in project - " << file << " == " << name << endl;
+ return file;
+ }
+ ++it;
+ }
+
+ // this should only happen if the file is not in the project
+ return name;
+}
+
+void MakeWidget::searchItem(int parag)
+{
+ ErrorItem* item = dynamic_cast<ErrorItem*>( m_paragraphToItem[parag] );
+ if ( item )
+ {
+ // open the file
+ kdDebug(9004) << "Opening file: " << guessFileName(item->fileName, parag) << endl;
+ m_part->partController()->editDocument(KURL( guessFileName(item->fileName, parag) ), item->lineNum);
+ m_part->mainWindow()->statusBar()->message( item->m_error, 10000 );
+ m_lastErrorSelected = parag;
+ }
+}
+
+void MakeWidget::insertStdoutLine( const QCString& line )
+{
+ QString sline;
+ bool forceCLocale = KConfigGroup( kapp->config(), "MakeOutputWidget" ).readBoolEntry( "ForceCLocale", true );
+
+ if( forceCLocale )
+ sline = QString::fromAscii( stdoutbuf+line );
+ else
+ sline = QString::fromLocal8Bit( stdoutbuf+line );
+
+ if ( !appendToLastLine( sline ) )
+ m_directoryStatusFilter.processLine( sline );
+ stdoutbuf.truncate(0);
+}
+
+void MakeWidget::insertStderrLine( const QCString& line )
+{
+ QString sline;
+ bool forceCLocale = KConfigGroup( kapp->config(), "MakeOutputWidget" ).readBoolEntry( "ForceCLocale", true );
+
+ if( forceCLocale ) {
+ sline = QString( stderrbuf+line );
+ }
+ else
+ sline = QString::fromLocal8Bit( stderrbuf+line );
+
+ if ( !appendToLastLine( sline ) )
+ m_errorFilter.processLine( sline );
+ stderrbuf.truncate(0);
+}
+
+void MakeWidget::slotProcessExited(KProcess *)
+{
+ procLineMaker->flush();
+ if( !stderrbuf.isEmpty() )
+ insertStderrLine("");
+ if( !stdoutbuf.isEmpty() )
+ insertStdoutLine("");
+ if (childproc->normalExit())
+ {
+ if (childproc->exitStatus())
+ {
+ KNotifyClient::event( topLevelWidget()->winId(), "ProcessError", i18n("The process has finished with errors"));
+ emit m_part->commandFailed(currentCommand);
+ }
+ else
+ {
+ KNotifyClient::event( topLevelWidget()->winId(), "ProcessSuccess", i18n("The process has finished successfully"));
+ emit m_part->commandFinished(currentCommand);
+ }
+ }
+
+ MakeItem* item = new ExitStatusItem( childproc->normalExit(), childproc->exitStatus() );
+ insertItem( item );
+ displayPendingItem();
+
+ m_part->mainWindow()->statusBar()->message( QString("%1: %2").arg(currentCommand).arg(item->m_text), 3000);
+ m_part->core()->running(m_part, false);
+
+ // Defensive programming: We emit this with a single shot timer so that we go once again
+ // through the event loop. After that, we can be sure that the process is really finished
+ // and its KProcess object can be reused.
+ if (childproc->normalExit() && !childproc->exitStatus())
+ {
+ QTimer::singleShot(0, this, SLOT(startNextJob()));
+// if (commandList.isEmpty())
+ // The last command on the list was successful so restore the
+ // output view to what it had before the compilation process started
+// m_part->mainWindow()->restoreOutputViewTab();
+ }
+ else
+ {
+ commandList.clear();
+ dirList.clear();
+ }
+}
+
+void MakeWidget::slotEnteredDirectory( EnteringDirectoryItem* item )
+{
+// kdDebug(9004) << "Entering dir: " << item->directory << endl;
+ QString* dir = new QString( item->directory );
+ dirstack.push( dir );
+ insertItem( item );
+}
+
+void MakeWidget::slotExitedDirectory( ExitingDirectoryItem* item )
+{
+ QString eDir = item->directory;
+// kdDebug(9004) << "Leaving dir: " << eDir << endl;
+ QString *dir = dirstack.pop();
+ if (!dir)
+ {
+ kdWarning(9004) << "Left more directories than entered: " << eDir;
+ }
+ else if (dir->compare(eDir) != 0)
+ {
+ kdWarning(9004) << "Expected directory: \"" << *dir << "\" but got \"" << eDir << "\"" << endl;
+ }
+ insertItem( item );
+ if (dirstack.top())
+ insertItem( new EnteringDirectoryItem( *dirstack.top(), "" ) );
+ delete dir;
+}
+
+void MakeWidget::displayPendingItem()
+{
+ if (!m_pendingItem) return;
+ // this handles the case of ImmDisplay|Append
+ // We call displayPendingItem once in insertItem
+ // and the appends are handled directly in
+ // appendToLastLine
+ if (!m_items.empty()
+ && m_items.last() == m_pendingItem) return;
+
+ m_items.push_back(m_pendingItem);
+
+ if ( m_bCompiling && !m_pendingItem->visible( m_compilerOutputLevel ) )
+ return;
+
+ SelectionPreserver preserveSelection( *this, !m_vertScrolling && !m_horizScrolling );
+ m_paragraphToItem.insert( m_paragraphs++, m_pendingItem );
+ append( m_pendingItem->formattedText( m_compilerOutputLevel, brightBg() ) );
+}
+
+bool MakeWidget::appendToLastLine( const QString& text )
+{
+ if ( !m_pendingItem ) return false;
+ if ( !m_pendingItem->append( text ) )
+ {
+ displayPendingItem();
+ m_pendingItem = 0;
+ return false;
+ }
+
+ int mode = m_pendingItem -> displayMode();
+ if ((mode & MakeItem::Append) && (mode & MakeItem::ImmDisplay))
+ {
+ removeParagraph(paragraphs() - 1);
+ SelectionPreserver preserveSelection( *this, !m_vertScrolling && !m_horizScrolling );
+ append( m_pendingItem->formattedText( m_compilerOutputLevel, brightBg() ) );
+ }
+
+ return true;
+}
+
+void MakeWidget::insertItem( MakeItem* new_item )
+{
+ displayPendingItem();
+ m_pendingItem = new_item;
+
+ if (!new_item) return;
+
+ int mode = new_item -> displayMode();
+ if (mode & MakeItem::ImmDisplay)
+ {
+ displayPendingItem();
+ if (!(mode & MakeItem::Append))
+ m_pendingItem = 0;
+ }
+}
+
+bool MakeWidget::brightBg()
+{
+ int h,s,v;
+ paletteBackgroundColor().hsv( &h, &s, &v );
+ return (v > 127);
+}
+
+QPopupMenu* MakeWidget::createPopupMenu( const QPoint& pos )
+{
+ QPopupMenu* pMenu = QTextEdit::createPopupMenu(pos);
+ pMenu->setCheckable(true);
+
+ pMenu->insertSeparator();
+ int id = pMenu->insertItem(i18n("Line Wrapping"), this, SLOT(toggleLineWrapping()) );
+ pMenu->setItemChecked(id, m_bLineWrapping);
+ pMenu->setWhatsThis(id, i18n("<b>Line wrapping</b><p>Enables or disables wrapping of command lines displayed."));
+
+ pMenu->insertSeparator();
+ id = pMenu->insertItem(i18n("Very Short Compiler Output"), this, SLOT(slotVeryShortCompilerOutput()) );
+ pMenu->setWhatsThis(id, i18n("<b>Very short compiler output</b><p>Displays only warnings, errors and the file names which are compiled."));
+ pMenu->setItemChecked(id, m_compilerOutputLevel == eVeryShort);
+ id = pMenu->insertItem(i18n("Short Compiler Output"), this, SLOT(slotShortCompilerOutput()) );
+ pMenu->setWhatsThis(id, i18n("<b>Short compiler output</b><p>Suppresses all the compiler flags and formats to something readable."));
+ pMenu->setItemChecked(id, m_compilerOutputLevel == eShort);
+ id = pMenu->insertItem(i18n("Full Compiler Output"), this, SLOT(slotFullCompilerOutput()) );
+ pMenu->setWhatsThis(id, i18n("<b>Full compiler output</b><p>Displays unmodified compiler output."));
+ pMenu->setItemChecked(id, m_compilerOutputLevel == eFull);
+
+ pMenu->insertSeparator();
+ id = pMenu->insertItem(i18n("Show Directory Navigation Messages"), this, SLOT(toggleShowDirNavigMessages()));
+ pMenu->setWhatsThis(id, i18n("<b>Show directory navigation messages</b><p>Shows <b>cd</b> commands that are executed while building."));
+ pMenu->setItemChecked(id, DirectoryItem::getShowDirectoryMessages());
+
+ return pMenu;
+}
+
+void MakeWidget::toggleLineWrapping()
+{
+ m_bLineWrapping = !m_bLineWrapping;
+ KConfig *pConfig = kapp->config();
+ pConfig->setGroup("MakeOutputView");
+ pConfig->writeEntry("LineWrapping", m_bLineWrapping);
+ pConfig->sync();
+ if (m_bLineWrapping) {
+ setWordWrap(WidgetWidth);
+ }
+ else
+ {
+ setWordWrap(NoWrap);
+ }
+}
+
+void MakeWidget::refill()
+{
+ clear();
+ m_paragraphToItem.clear();
+ m_paragraphs = 0;
+ for( uint i = 0; i < m_items.size(); i++ )
+ {
+ if ( m_bCompiling && !m_items[i]->visible( m_compilerOutputLevel ) )
+ continue;
+ m_paragraphToItem.insert( m_paragraphs++, m_items[i] );
+ append( m_items[i]->formattedText( m_compilerOutputLevel, brightBg() ) );
+ }
+
+}
+
+void MakeWidget::slotVeryShortCompilerOutput() { setTextFormat( Qt::RichText ); setCompilerOutputLevel(eVeryShort); }
+void MakeWidget::slotShortCompilerOutput() { setTextFormat( Qt::RichText ); setCompilerOutputLevel(eShort); }
+void MakeWidget::slotFullCompilerOutput() { setTextFormat( Qt::RichText ); setCompilerOutputLevel(eFull); }
+
+void MakeWidget::setCompilerOutputLevel(EOutputLevel level)
+{
+ m_compilerOutputLevel = level;
+ KConfig *pConfig = kapp->config();
+ pConfig->setGroup("MakeOutputView");
+ pConfig->writeEntry("CompilerOutputLevel", (int) level);
+ pConfig->sync();
+ refill();
+}
+
+void MakeWidget::toggleShowDirNavigMessages()
+{
+ DirectoryItem::setShowDirectoryMessages( !DirectoryItem::getShowDirectoryMessages() );
+ KConfig *pConfig = kapp->config();
+ pConfig->setGroup("MakeOutputView");
+ pConfig->writeEntry("ShowDirNavigMsg", DirectoryItem::getShowDirectoryMessages());
+ pConfig->sync();
+ refill();
+}
+
+void MakeWidget::updateSettingsFromConfig()
+{
+ KConfig *pConfig = kapp->config();
+ pConfig->setGroup("General Options");
+ QFont outputFont = pConfig->readFontEntry("OutputViewFont");
+ setFont(outputFont);
+ pConfig->setGroup("MakeOutputView");
+ m_bLineWrapping = pConfig->readBoolEntry("LineWrapping", true);
+ m_compilerOutputLevel = (EOutputLevel) pConfig->readNumEntry("CompilerOutputLevel", (int) eShort);
+ DirectoryItem::setShowDirectoryMessages( pConfig->readBoolEntry("ShowDirNavigMsg", false) );
+}
+
+bool MakeWidget::scanErrorForward( int parag )
+{
+ for ( int it = parag + 1;
+ it < (int)m_items.count();
+ ++it )
+ {
+ ErrorItem* item = dynamic_cast<ErrorItem*>( m_paragraphToItem[it] );
+ if ( !item )
+ continue;
+ if( item->m_isWarning )
+ continue;
+ parag = it;
+ document()->removeSelection(0);
+ setSelection(parag, 0, parag+1, 0, 0);
+ setCursorPosition(parag, 0);
+ ensureCursorVisible();
+ searchItem( it );
+ return true;
+ }
+ return false;
+}
+
+bool MakeWidget::scanErrorBackward( int parag )
+{
+ for ( int it = parag - 1; it >= 0; --it)
+ {
+ ErrorItem* item = dynamic_cast<ErrorItem*>( m_paragraphToItem[it] );
+ if ( !item )
+ continue;
+ if( item->m_isWarning )
+ continue;
+ parag = it;
+ document()->removeSelection(0);
+ setSelection(parag, 0, parag+1, 0, 0);
+ setCursorPosition(parag, 0);
+ ensureCursorVisible();
+ searchItem( it );
+ return true;
+ }
+ return false;
+}
+
+void MakeWidget::storePartialStderrLine(const QCString & line)
+{
+ stderrbuf += line;
+}
+
+void MakeWidget::storePartialStdoutLine(const QCString & line)
+{
+ stdoutbuf += line;
+}
+
+#include "makewidget.moc"
diff --git a/parts/outputviews/makewidget.h b/parts/outputviews/makewidget.h
new file mode 100644
index 00000000..ff65eb5e
--- /dev/null
+++ b/parts/outputviews/makewidget.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * 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 _MAKEWIDGET_H_
+#define _MAKEWIDGET_H_
+
+#include <qptrstack.h>
+#include <qregexp.h>
+#include <qtextedit.h>
+#include <qvaluevector.h>
+#include <qintdict.h>
+
+#include "outputfilter.h"
+#include "directorystatusmessagefilter.h"
+#include "compileerrorfilter.h"
+#include "commandcontinuationfilter.h"
+#include "makeactionfilter.h"
+#include "otherfilter.h"
+#include "makeitem.h"
+
+class MakeViewPart;
+class MakeItem;
+class KProcess;
+class ProcessLineMaker;
+class KURL;
+
+namespace KTextEditor { class Document; }
+
+class MakeWidget : public QTextEdit
+{
+ Q_OBJECT
+
+public:
+ MakeWidget(MakeViewPart *part);
+ ~MakeWidget();
+
+ void queueJob(const QString &dir, const QString &command);
+ bool isRunning();
+ void updateSettingsFromConfig();
+ void processLine( const QString& line );
+
+public slots:
+ void startNextJob();
+ void killJob();
+ void nextError();
+ void prevError();
+ void copy();
+
+protected:
+ virtual QPopupMenu *createPopupMenu( const QPoint& pos );
+ virtual void contentsMouseReleaseEvent( QMouseEvent* e );
+
+private slots:
+ void insertStdoutLine(const QCString& line);
+ void insertStderrLine(const QCString& line);
+ void storePartialStdoutLine(const QCString& line);
+ void storePartialStderrLine(const QCString& line);
+ void slotProcessExited(KProcess *);
+ void verticScrollingOn() { m_vertScrolling = true; }
+ void verticScrollingOff() { m_vertScrolling = false; }
+ void horizScrollingOn() { m_horizScrolling = true; }
+ void horizScrollingOff() { m_horizScrolling = false; }
+ void toggleLineWrapping();
+ void slotVeryShortCompilerOutput();
+ void slotShortCompilerOutput();
+ void slotFullCompilerOutput();
+ void toggleShowDirNavigMessages();
+ void slotEnteredDirectory( EnteringDirectoryItem* );
+ void slotExitedDirectory( ExitingDirectoryItem* );
+ void insertItem( MakeItem* );
+
+private:
+ void specialCheck( const QString& file, QString& fName ) const;
+ virtual void keyPressEvent(QKeyEvent *e);
+ void searchItem(int parag);
+ QString guessFileName( const QString& fName, int parag ) const;
+ QString directory(int parag) const;
+ bool brightBg();
+ void refill();
+ void createCursor(ErrorItem* e, KTextEditor::Document* doc);
+
+ bool scanErrorForward(int parag);
+ bool scanErrorBackward(int parag);
+
+ DirectoryStatusMessageFilter m_directoryStatusFilter;
+ CompileErrorFilter m_errorFilter;
+ CommandContinuationFilter m_continuationFilter;
+ MakeActionFilter m_actionFilter;
+ OtherFilter m_otherFilter;
+
+ void setPendingItem(MakeItem* new_item);
+ void displayPendingItem();
+ bool appendToLastLine( const QString& text );
+ void setCompilerOutputLevel(EOutputLevel level);
+
+ QStringList commandList;
+ QStringList dirList;
+ QString m_lastBuildDir; //stores directory of last build, for the case we don't have proper path information
+ QString currentCommand;
+ KProcess *childproc;
+ ProcessLineMaker* procLineMaker;
+ QPtrStack<QString> dirstack;
+ MakeItem* m_pendingItem;
+ QValueVector<MakeItem*> m_items;
+ QIntDict<MakeItem> m_paragraphToItem;
+ long m_paragraphs;
+ int m_lastErrorSelected;
+
+ MakeViewPart *m_part;
+
+ bool m_vertScrolling, m_horizScrolling;
+ bool m_bCompiling;
+
+ QCString stderrbuf;
+ QCString stdoutbuf;
+
+ bool m_bLineWrapping;
+ EOutputLevel m_compilerOutputLevel;
+};
+
+#endif
diff --git a/parts/outputviews/otherfilter.cpp b/parts/outputviews/otherfilter.cpp
new file mode 100644
index 00000000..5f14937c
--- /dev/null
+++ b/parts/outputviews/otherfilter.cpp
@@ -0,0 +1,26 @@
+/***************************************************************************
+ * 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 "otherfilter.h"
+#include "otherfilter.moc"
+#include "makeitem.h"
+
+#include <kdebug.h>
+
+OtherFilter::OtherFilter()
+ : OutputFilter( *this )
+{
+}
+
+void OtherFilter::processLine( const QString& line )
+{
+ emit item( new MakeItem( line ) );
+}
diff --git a/parts/outputviews/otherfilter.h b/parts/outputviews/otherfilter.h
new file mode 100644
index 00000000..9a2c6c17
--- /dev/null
+++ b/parts/outputviews/otherfilter.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * 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 OtherFilter_h
+#define OtherFilter_h
+
+#include "outputfilter.h"
+
+#include <qobject.h>
+
+class MakeItem;
+
+class OtherFilter : public QObject, public OutputFilter
+{
+Q_OBJECT
+
+public:
+ OtherFilter();
+
+ virtual void processLine( const QString& line );
+
+signals:
+ void item( MakeItem* );
+};
+
+#endif
diff --git a/parts/outputviews/outputfilter.cpp b/parts/outputviews/outputfilter.cpp
new file mode 100644
index 00000000..5692efce
--- /dev/null
+++ b/parts/outputviews/outputfilter.cpp
@@ -0,0 +1,24 @@
+/***************************************************************************
+ * 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 "outputfilter.h"
+
+#include <kdebug.h>
+
+OutputFilter::OutputFilter( OutputFilter& next )
+ : m_next( next )
+{
+}
+
+void OutputFilter::processLine( const QString& line )
+{
+ m_next.processLine( line );
+}
diff --git a/parts/outputviews/outputfilter.h b/parts/outputviews/outputfilter.h
new file mode 100644
index 00000000..dd84f7d7
--- /dev/null
+++ b/parts/outputviews/outputfilter.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * 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 OutputFilter_h
+#define OutputFilter_h
+
+#include <qstring.h>
+
+class OutputFilter
+{
+public:
+ OutputFilter( OutputFilter& );
+ virtual ~OutputFilter() {}
+
+ virtual void processLine( const QString& line );
+
+private:
+ OutputFilter& m_next;
+};
+
+#endif
diff --git a/parts/outputviews/outputviewsfactory.cpp b/parts/outputviews/outputviewsfactory.cpp
new file mode 100644
index 00000000..55e5bf55
--- /dev/null
+++ b/parts/outputviews/outputviewsfactory.cpp
@@ -0,0 +1,21 @@
+/***************************************************************************
+ * Copyright (C) 2000-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 "outputviewsfactory.h"
+
+static const KDevPluginInfo data("kdevoutputviews", I18N_NOOP("Messages Output"), "1.0");
+
+K_EXPORT_COMPONENT_FACTORY( libkdevoutputviews, OutputViewsFactory( &data ) )
+
+const KDevPluginInfo *outputViewsInfo()
+{
+ return data;
+}
diff --git a/parts/outputviews/outputviewsfactory.h b/parts/outputviews/outputviewsfactory.h
new file mode 100644
index 00000000..4bcba666
--- /dev/null
+++ b/parts/outputviews/outputviewsfactory.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * Copyright (C) 2000-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 _OUTPUTVIEWSFACTORY_H_
+#define _OUTPUTVIEWSFACTORY_H_
+
+#include <kdevgenericfactory.h>
+
+#include "appoutputviewpart.h"
+#include "makeviewpart.h"
+
+class KDevPluginInfo;
+
+typedef K_TYPELIST_2( AppOutputViewPart, MakeViewPart ) OutputViews;
+typedef KDevGenericFactory< OutputViews > OutputViewsFactory;
+
+const KDevPluginInfo *outputViewsInfo();
+
+#endif