diff options
Diffstat (limited to 'parts/outputviews')
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>&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>&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&ase sensitive</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>regularExpression</cstring> + </property> + <property name="text"> + <string>Re&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( ¶, &index ); + + m_atEnd = stayAtEnd + && para == m_textEdit.paragraphs() - 1 + && index == m_textEdit.paragraphLength( para ); + + m_textEdit.getSelection(¶From, &indexFrom, ¶To, &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(¶from, &indexfrom, ¶to, &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("<","<"); + selection.replace(">",">"); + selection.replace(""","\""); + selection.replace("&","&"); + + 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(¶g, &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 |