diff options
Diffstat (limited to 'parts/outputviews/makewidget.cpp')
-rw-r--r-- | parts/outputviews/makewidget.cpp | 847 |
1 files changed, 847 insertions, 0 deletions
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 * + * [email protected] * + * * + * 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" |