KDevelop API Documentation

parts/outputviews/makewidget.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 1999-2001 by Bernd Gehrmann and the KDevelop Team * 00003 * bernd@kdevelop.org * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 ***************************************************************************/ 00011 00012 #include "makewidget.h" 00013 #include "kdevcore.h" 00014 #include "kdevmainwindow.h" 00015 #include "kdevproject.h" 00016 #include "kdevpartcontroller.h" 00017 #include "processlinemaker.h" 00018 #include "makeviewpart.h" 00019 #include "makeitem.h" 00020 #include "ktexteditor/document.h" 00021 #include "ktexteditor/cursorinterface.h" 00022 #include "ktexteditor/editinterface.h" 00023 #include "urlutil.h" 00024 00025 #include <kdebug.h> 00026 #include <klocale.h> 00027 #include <knotifyclient.h> 00028 #include <kprocess.h> 00029 #include <kglobal.h> 00030 #include <kstandarddirs.h> 00031 #include <kinstance.h> 00032 #include <kstatusbar.h> 00033 #include <kapplication.h> 00034 #include <kconfig.h> 00035 00036 #include <qmessagebox.h> 00037 #include <qapplication.h> 00038 #include <qdir.h> 00039 #include <qimage.h> 00040 #include <qstylesheet.h> 00041 #include <qtimer.h> 00042 #include <qfileinfo.h> 00043 #include <qclipboard.h> 00044 #include <qpopupmenu.h> 00045 #include <private/qrichtext_p.h> 00046 00047 #include <stdlib.h> 00048 #include <limits.h> 00049 00050 static const char *const error_xpm[] = 00051 { 00052 "11 11 5 1", 00053 ". c None", 00054 "# c #313062", 00055 "a c #6261cd", 00056 "b c #c50000", 00057 "c c #ff8583", 00058 "...........", 00059 "...####....", 00060 ".a#bbbb#a..", 00061 ".#ccbbbb#..", 00062 "#bccbbbbb#.", 00063 "#bbbbbbbb#.", 00064 "#bbbbbbcb#.", 00065 "#bbbbbccb#.", 00066 ".#bbbccb#..", 00067 ".a#bbbb#a..", 00068 "...####...." 00069 }; 00070 00071 00072 static const char *const warning_xpm[] = 00073 { 00074 "11 11 5 1", 00075 ". c None", 00076 "# c #313062", 00077 "a c #6261cd", 00078 "b c #c5c600", 00079 "c c #ffff41", 00080 "...........", 00081 "...####....", 00082 ".a#bbbb#a..", 00083 ".#ccbbbb#..", 00084 "#bccbbbbb#.", 00085 "#bbbbbbbb#.", 00086 "#bbbbbbcb#.", 00087 "#bbbbbccb#.", 00088 ".#bbbccb#..", 00089 ".a#bbbb#a..", 00090 "...####...." 00091 }; 00092 00093 00094 static const char *const message_xpm[] = 00095 { 00096 "11 11 5 1", 00097 ". c None", 00098 "b c #3100c5", 00099 "# c #313062", 00100 "c c #3189ff", 00101 "a c #6265cd", 00102 "...........", 00103 "...####....", 00104 ".a#bbbb#a..", 00105 ".#ccbbbb#..", 00106 "#bccbbbbb#.", 00107 "#bbbbbbbb#.", 00108 "#bbbbbbcb#.", 00109 "#bbbbbccb#.", 00110 ".#bbbccb#..", 00111 ".a#bbbb#a..", 00112 "...####...." 00113 }; 00114 00115 00116 class SelectionPreserver 00117 { 00118 public: 00119 SelectionPreserver( QTextEdit& textEdit, bool stayAtEnd ) 00120 : m_textEdit( textEdit ) 00121 , m_atEnd( false ) 00122 { 00123 int para, index; 00124 m_textEdit.getCursorPosition( &para, &index ); 00125 00126 m_atEnd = stayAtEnd 00127 && para == m_textEdit.paragraphs() - 1 00128 && index == m_textEdit.paragraphLength( para ); 00129 00130 m_textEdit.getSelection(&paraFrom, &indexFrom, &paraTo, &indexTo, 0); 00131 } 00132 00133 ~SelectionPreserver() 00134 { 00135 m_textEdit.setSelection(paraFrom, indexFrom, paraTo, indexTo, 0); 00136 00137 if ( m_atEnd ) 00138 { 00139 m_textEdit.moveCursor(QTextEdit::MoveEnd, false); 00140 m_textEdit.moveCursor(QTextEdit::MoveLineStart, false);//if linewrap is off we must avoid the jumping of the vertical scrollbar 00141 } 00142 } 00143 00144 QTextEdit& m_textEdit; 00145 bool m_atEnd; 00146 int paraFrom, indexFrom, paraTo, indexTo; 00147 }; 00148 00149 MakeWidget::MakeWidget(MakeViewPart *part) 00150 : QTextEdit(0, "make widget") 00151 , m_directoryStatusFilter( m_errorFilter ) 00152 , m_errorFilter( m_continuationFilter ) 00153 , m_continuationFilter( m_actionFilter ) 00154 , m_actionFilter( m_otherFilter ) 00155 , m_paragraphs(0) 00156 , m_lastErrorSelected(-1) 00157 , m_part(part) 00158 , m_vertScrolling(false) 00159 , m_horizScrolling(false) 00160 , m_bCompiling(false) 00161 { 00162 updateSettingsFromConfig(); 00163 00164 if ( m_bLineWrapping ) 00165 setWordWrap(WidgetWidth); 00166 setWrapPolicy(Anywhere); 00167 setReadOnly(true); 00168 setMimeSourceFactory(new QMimeSourceFactory); 00169 mimeSourceFactory()->setImage("error", QImage((const char**)error_xpm)); 00170 mimeSourceFactory()->setImage("warning", QImage((const char**)warning_xpm)); 00171 mimeSourceFactory()->setImage("message", QImage((const char**)message_xpm)); 00172 00173 childproc = new KShellProcess("/bin/sh"); 00174 procLineMaker = new ProcessLineMaker( childproc ); 00175 00176 connect( procLineMaker, SIGNAL(receivedStdoutLine(const QString&)), 00177 this, SLOT(insertStdoutLine(const QString&) )); 00178 connect( procLineMaker, SIGNAL(receivedStderrLine(const QString&)), 00179 this, SLOT(insertStderrLine(const QString&) )); 00180 00181 connect( childproc, SIGNAL(processExited(KProcess*)), 00182 this, SLOT(slotProcessExited(KProcess*) )) ; 00183 00184 connect( &m_directoryStatusFilter, SIGNAL(item(EnteringDirectoryItem*)), 00185 this, SLOT(slotEnteredDirectory(EnteringDirectoryItem*)) ); 00186 connect( &m_directoryStatusFilter, SIGNAL(item(ExitingDirectoryItem*)), 00187 this, SLOT(slotExitedDirectory(ExitingDirectoryItem*)) ); 00188 connect( &m_errorFilter, SIGNAL(item(MakeItem*)), 00189 this, SLOT(insertItem(MakeItem*)) ); 00190 connect( &m_actionFilter, SIGNAL(item(MakeItem*)), 00191 this, SLOT(insertItem(MakeItem*)) ); 00192 connect( &m_otherFilter, SIGNAL(item(MakeItem*)), 00193 this, SLOT(insertItem(MakeItem*)) ); 00194 00195 connect( verticalScrollBar(), SIGNAL(sliderPressed()), 00196 this, SLOT(verticScrollingOn()) ); 00197 connect( verticalScrollBar(), SIGNAL(sliderReleased()), 00198 this, SLOT(verticScrollingOff()) ); 00199 connect( horizontalScrollBar(), SIGNAL(sliderPressed()), 00200 this, SLOT(horizScrollingOn()) ); 00201 connect( horizontalScrollBar(), SIGNAL(sliderReleased()), 00202 this, SLOT(horizScrollingOff()) ); 00203 00204 connect( m_part->partController(), SIGNAL(loadedFile(const QString&)), 00205 this, SLOT(slotDocumentOpened(const QString&)) ); 00206 } 00207 00208 MakeWidget::~MakeWidget() 00209 { 00210 delete mimeSourceFactory(); 00211 delete childproc; 00212 delete procLineMaker; 00213 } 00214 00215 void MakeWidget::queueJob(const QString &dir, const QString &command) 00216 { 00217 commandList.append(command); 00218 dirList.append(dir); 00219 if (!isRunning()) 00220 { 00221 // Store the current output view so that it 00222 // can be restored after a successful compilation 00223 m_part->mainWindow()->storeOutputViewTab(); 00224 startNextJob(); 00225 } 00226 } 00227 00228 void MakeWidget::startNextJob() 00229 { 00230 QStringList::Iterator it = commandList.begin(); 00231 if ( it == commandList.end() ) 00232 return; 00233 00234 currentCommand = *it; 00235 commandList.remove(it); 00236 00237 int i = currentCommand.findRev(" gmake"); 00238 if ( i == -1 ) 00239 i = currentCommand.findRev(" make"); 00240 if ( i == -1 ) 00241 m_bCompiling = false; 00242 else 00243 { 00244 QString s = currentCommand.right(currentCommand.length() - i); 00245 if ( s.contains("configure ") || 00246 s.contains(" Makefile.cvs") || 00247 s.contains(" clean") || 00248 s.contains(" distclean") || 00249 s.contains(" package-messages") || 00250 s.contains(" install") ) 00251 { 00252 m_bCompiling = false; 00253 } 00254 else { 00255 m_bCompiling = true; 00256 } 00257 } 00258 00259 it = dirList.begin(); 00260 QString dir = *it; 00261 dirList.remove(it); 00262 00263 clear(); // clear the widget 00264 for ( QValueVector<MakeItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it ) 00265 delete *it; 00266 m_items.clear(); 00267 m_paragraphToItem.clear(); 00268 m_paragraphs = 0; 00269 m_lastErrorSelected = -1; 00270 00271 insertItem( new CommandItem( currentCommand ) ); 00272 00273 childproc->clearArguments(); 00274 *childproc << currentCommand; 00275 childproc->start(KProcess::NotifyOnExit, KProcess::AllOutput); 00276 00277 dirstack.clear(); 00278 dirstack.push(new QString(dir)); 00279 00280 m_part->mainWindow()->raiseView(this); 00281 m_part->core()->running(m_part, true); 00282 } 00283 00284 void MakeWidget::killJob() 00285 { 00286 childproc->kill(); 00287 } 00288 00289 bool MakeWidget::isRunning() 00290 { 00291 return childproc->isRunning(); 00292 } 00293 00294 void MakeWidget::copy() 00295 { 00296 int parafrom=0, indexfrom=0, parato=0, indexto=0; 00297 getSelection(&parafrom, &indexfrom, &parato, &indexto); 00298 if( parafrom < 0 || indexfrom < 0 || parato < 0 || indexto < 0 00299 || ((parafrom == parato) && (indexfrom == indexto)) ) 00300 { 00301 return; 00302 } 00303 00304 QString selection; 00305 for(int i = parafrom; i<=parato; i++) 00306 selection += text(i) + "\n"; 00307 00308 selection.remove(0, indexfrom); 00309 int removeend = text(parato).length() - indexto; 00310 00311 selection.remove((selection.length()-1) - removeend, removeend); 00312 00313 #if QT_VERSION >= 0x030100 00314 kapp->clipboard()->setText(selection, QClipboard::Clipboard); 00315 #else 00316 kapp->clipboard()->setText(selection); 00317 #endif 00318 } 00319 00320 void MakeWidget::nextError() 00321 { 00322 int parag; 00323 if (m_lastErrorSelected != -1) 00324 parag = m_lastErrorSelected; 00325 else 00326 parag = 0; 00327 00328 //if there are no errors after m_lastErrorSelected try again from the beginning 00329 if (!scanErrorForward(parag)) 00330 if (m_lastErrorSelected != -1) 00331 { 00332 m_lastErrorSelected = -1; 00333 if (!scanErrorForward(0)) 00334 KNotifyClient::beep(); 00335 } 00336 else 00337 KNotifyClient::beep(); 00338 } 00339 00340 void MakeWidget::prevError() 00341 { 00342 int parag; 00343 if (m_lastErrorSelected != -1) 00344 parag = m_lastErrorSelected; 00345 else 00346 parag = 0; 00347 00348 //if there are no errors before m_lastErrorSelected try again from the end 00349 if (!scanErrorBackward(parag)) 00350 if (m_lastErrorSelected != -1) 00351 { 00352 m_lastErrorSelected = -1; 00353 #if QT_VERSION >= 0x030100 00354 parag = (int)m_items.count(); 00355 #else 00356 parag = m_items.size(); 00357 #endif 00358 if (!scanErrorBackward(parag)) 00359 KNotifyClient::beep(); 00360 } 00361 else 00362 KNotifyClient::beep(); 00363 } 00364 00365 void MakeWidget::contentsMouseReleaseEvent( QMouseEvent* e ) 00366 { 00367 QTextEdit::contentsMouseReleaseEvent(e); 00368 if ( e->button() != LeftButton ) 00369 return; 00370 searchItem(paragraphAt(e->pos())); 00371 } 00372 00373 void MakeWidget::keyPressEvent(QKeyEvent *e) 00374 { 00375 if (e->key() == Key_Return || e->key() == Key_Enter) 00376 { 00377 int parag, index; 00378 getCursorPosition(&parag, &index); 00379 searchItem(parag); 00380 } 00381 else 00382 QTextEdit::keyPressEvent(e); 00383 } 00384 00385 // returns the current directory for parag 00386 QString MakeWidget::directory(int parag) const 00387 { 00388 QValueVector<MakeItem*>::const_iterator it = qFind( m_items.begin(), m_items.end(), m_paragraphToItem[parag] ); 00389 if ( it == m_items.end() ) 00390 return QString::null; 00391 // run backwards over directories and figure out where we are 00392 while ( it != m_items.begin() ) { 00393 --it; 00394 EnteringDirectoryItem* edi = dynamic_cast<EnteringDirectoryItem*>( *it ); 00395 if ( edi ) 00396 return edi->directory + "/"; 00397 } 00398 return QString::null; 00399 } 00400 00401 // hackish function that will return true and put string "file" in "fName" if the file 00402 // exists 00403 static bool checkFileExists( const QString& file, QString& fName ) 00404 { 00405 if ( QFile::exists( file ) ) { 00406 fName = file; 00407 return true; 00408 } 00409 return false; 00410 } 00411 00412 QString MakeWidget::guessFileName( const QString& fName, int parag ) const 00413 { 00414 // pathological case 00415 if ( ! m_part->project() ) return fName; 00416 00417 QString name; 00418 QString dir = directory( parag ); 00419 00420 if ( fName.startsWith( "/" ) ) 00421 { 00422 // absolute path given 00423 name = fName; 00424 } 00425 else if ( !dir.isEmpty() ) 00426 { 00427 name = dir + fName; 00428 } 00429 else 00430 { 00431 // now it gets tricky - no directory navigation messages, 00432 // no absolute path - let's guess. 00433 name = fName; 00434 if ( !checkFileExists( m_part->project()->projectDirectory() + "/" + fName, name ) && 00435 !checkFileExists( m_part->project()->projectDirectory() + "/" + m_part->project()->activeDirectory() + "/" + fName, name ) ) 00436 checkFileExists( m_part->project()->buildDirectory() + "/" + fName, name ); 00437 } 00438 00439 kdDebug(9004) << "Opening file: " << fName << endl; 00440 00441 // GNU make resolves symlinks. if "name" is a real path to a file the 00442 // project know by symlink path, we need to return the symlink path 00443 QStringList projectFiles = m_part->project()->allFiles(); 00444 QStringList::iterator it = projectFiles.begin(); 00445 while ( it != projectFiles.end() ) 00446 { 00447 QString file = m_part->project()->projectDirectory() + "/" + *it; 00448 if ( name == URLUtil::canonicalPath( file ) ) 00449 { 00450 kdDebug(9004) << "Found file in project - " << file << " == " << name << endl; 00451 return file; 00452 } 00453 ++it; 00454 } 00455 00456 // this should only happen if the file is not in the project 00457 return name; 00458 } 00459 00460 void MakeWidget::searchItem(int parag) 00461 { 00462 ErrorItem* item = dynamic_cast<ErrorItem*>( m_paragraphToItem[parag] ); 00463 if ( item ) 00464 { 00465 // open the file 00466 kdDebug(9004) << "Opening file: " << guessFileName(item->fileName, parag) << endl; 00467 if (item->m_cursor) { 00468 uint line, col; 00469 item->m_cursor->position(&line, &col); 00470 kdDebug() << "Cursor new position: " << col << endl; 00471 m_part->partController()->editDocument(guessFileName(item->fileName, parag), line, col); 00472 } else { 00473 m_part->partController()->editDocument(guessFileName(item->fileName, parag), item->lineNum); 00474 } 00475 m_part->mainWindow()->statusBar()->message( item->m_error, 10000 ); 00476 m_part->mainWindow()->lowerView(this); 00477 m_lastErrorSelected = parag; 00478 } 00479 } 00480 00481 void MakeWidget::insertStdoutLine( const QString& line ) 00482 { 00483 if ( !appendToLastLine( line ) ) 00484 m_directoryStatusFilter.processLine( line ); 00485 } 00486 00487 void MakeWidget::insertStderrLine( const QString& line ) 00488 { 00489 if ( !appendToLastLine( line ) ) 00490 { 00491 kdDebug() << "inserting stderr line: " << line << endl; 00492 m_errorFilter.processLine( line ); 00493 } 00494 } 00495 00496 void MakeWidget::slotProcessExited(KProcess *) 00497 { 00498 if (childproc->normalExit()) 00499 { 00500 if (childproc->exitStatus()) 00501 { 00502 KNotifyClient::event( "ProcessError", i18n("The process has finished with errors")); 00503 emit m_part->commandFailed(currentCommand); 00504 } 00505 else 00506 { 00507 KNotifyClient::event( "ProcessSuccess", i18n("The process has finished successfully")); 00508 emit m_part->commandFinished(currentCommand); 00509 } 00510 } 00511 00512 MakeItem* item = new ExitStatusItem( childproc->normalExit(), childproc->exitStatus() ); 00513 insertItem( item ); 00514 00515 m_part->mainWindow()->statusBar()->message( QString("%1: %2").arg(currentCommand).arg(item->m_text), 3000); 00516 m_part->core()->running(m_part, false); 00517 00518 // Defensive programming: We emit this with a single shot timer so that we go once again 00519 // through the event loop. After that, we can be sure that the process is really finished 00520 // and its KProcess object can be reused. 00521 if (childproc->normalExit() && !childproc->exitStatus()) 00522 { 00523 QTimer::singleShot(0, this, SLOT(startNextJob())); 00524 if (commandList.isEmpty()) 00525 // The last command on the list was successful so restore the 00526 // output view to what it had before the compilation process started 00527 m_part->mainWindow()->restoreOutputViewTab(); 00528 } 00529 else 00530 { 00531 commandList.clear(); 00532 dirList.clear(); 00533 } 00534 } 00535 00536 void MakeWidget::slotEnteredDirectory( EnteringDirectoryItem* item ) 00537 { 00538 // kdDebug(9004) << "Entering dir: " << item->directory << endl; 00539 QString* dir = new QString( item->directory ); 00540 dirstack.push( dir ); 00541 insertItem( item ); 00542 } 00543 00544 void MakeWidget::slotExitedDirectory( ExitingDirectoryItem* item ) 00545 { 00546 QString eDir = item->directory; 00547 // kdDebug(9004) << "Leaving dir: " << eDir << endl; 00548 QString *dir = dirstack.pop(); 00549 if (!dir) 00550 { 00551 kdWarning(9004) << "Left more directories than entered: " << eDir; 00552 } 00553 else if (dir->compare(eDir) != 0) 00554 { 00555 kdWarning(9004) << "Expected directory: \"" << *dir << "\" but got \"" << eDir << "\"" << endl; 00556 } 00557 insertItem( item ); 00558 delete dir; 00559 } 00560 00561 bool MakeWidget::appendToLastLine( const QString& text ) 00562 { 00563 #if QT_VERSION >= 0x030100 00564 if ( m_items.count() == 0 ) 00565 #else 00566 if ( m_items.size() == 0 ) 00567 #endif 00568 return false; 00569 #if QT_VERSION >= 0x030100 00570 MakeItem* item = m_items[m_items.count() - 1]; 00571 #else 00572 MakeItem* item = m_items[m_items.size() - 1]; 00573 #endif 00574 if ( !item->append( text ) ) 00575 return false; 00576 00577 SelectionPreserver preserveSelection( *this, !m_vertScrolling && !m_horizScrolling ); 00578 00579 removeParagraph( paragraphs() - 1 ); 00580 append( item->formattedText( m_compilerOutputLevel, brightBg() ) ); 00581 00582 00583 00584 return true; 00585 } 00586 00587 void MakeWidget::insertItem( MakeItem* item ) 00588 { 00589 ErrorItem* e = dynamic_cast<ErrorItem*>(item); 00590 if (e) 00591 createCursor(e, 0L); 00592 00593 m_items.push_back( item ); 00594 00595 if ( m_bCompiling && !item->visible( m_compilerOutputLevel ) ) 00596 return; 00597 00598 SelectionPreserver preserveSelection( *this, !m_vertScrolling && !m_horizScrolling ); 00599 00600 m_paragraphToItem.insert( m_paragraphs++, item ); 00601 append( item->formattedText( m_compilerOutputLevel, brightBg() ) ); 00602 } 00603 00604 void MakeWidget::slotDocumentOpened( const QString & filename ) 00605 { 00606 KParts::Part* part = m_part->partController()->findOpenDocument(filename); 00607 KTextEditor::Document* doc = dynamic_cast<KTextEditor::Document*>(part); 00608 00609 if (!doc) { 00610 kdWarning() << k_funcinfo << "Couldn't find the document that was just opened." << endl; 00611 return; 00612 } 00613 00614 connect(part, SIGNAL(destroyed(QObject*)), this, SLOT(slotDocumentClosed(QObject*)) ); 00615 00616 for (QValueVector<MakeItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it) { 00617 ErrorItem* e = dynamic_cast<ErrorItem*>(*it); 00618 00619 if (!e || e->m_cursor) continue; 00620 00621 if (filename.endsWith(e->fileName)) 00622 createCursor(e, doc); 00623 } 00624 } 00625 00626 void MakeWidget::createCursor(ErrorItem* e, KTextEditor::Document* doc) 00627 { 00628 // Disabled for now - comment out to test. You need an up-to-date cvs head katepart to avoid mem leaks 00629 return; 00630 00631 // try to get a KTextEditor::Cursor, so that we can retain position in 00632 // a document even when it is edited 00633 if (!doc) 00634 doc = dynamic_cast<KTextEditor::Document*>(m_part->partController()->findOpenDocument(guessFileName(e->fileName, m_paragraphs + 1))); 00635 00636 if (doc) { 00637 KTextEditor::EditInterface* edit = dynamic_cast<KTextEditor::EditInterface*>(doc); 00638 KTextEditor::CursorInterface* cursor = dynamic_cast<KTextEditor::CursorInterface*>(doc); 00639 if (cursor) { 00640 e->m_cursor = cursor->createCursor(); 00641 uint col = 0; 00642 static QRegExp startOfText("[\\S]"); 00643 if (edit) { 00644 int newcol = edit->textLine(e->lineNum).find(startOfText); 00645 if (newcol != -1) col = uint(newcol); 00646 } 00647 e->m_cursor->setPosition(e->lineNum, col); 00648 e->m_doc = doc; 00649 } 00650 } 00651 } 00652 00653 void MakeWidget::slotDocumentClosed(QObject* doc) 00654 { 00655 KTextEditor::Document* document = static_cast<KTextEditor::Document*>(doc); 00656 00657 for (QValueVector<MakeItem*>::iterator it = m_items.begin(); it != m_items.end(); ++it) { 00658 ErrorItem* e = dynamic_cast<ErrorItem*>(*it); 00659 00660 if (!e || e->m_doc != document) continue; 00661 00662 e->m_cursor = 0L; 00663 e->m_doc = 0L; 00664 } 00665 } 00666 00667 bool MakeWidget::brightBg() 00668 { 00669 int h,s,v; 00670 paletteBackgroundColor().hsv( &h, &s, &v ); 00671 return (v > 127); 00672 } 00673 00674 QPopupMenu* MakeWidget::createPopupMenu( const QPoint& pos ) 00675 { 00676 QPopupMenu* pMenu = QTextEdit::createPopupMenu(pos); 00677 pMenu->setCheckable(true); 00678 00679 pMenu->insertSeparator(); 00680 int id = pMenu->insertItem(i18n("Line Wrapping"), this, SLOT(toggleLineWrapping()) ); 00681 pMenu->setItemChecked(id, m_bLineWrapping); 00682 pMenu->setWhatsThis(id, i18n("<b>Line wrapping</b><p>Enables or disables wrapping of command lines displayed.")); 00683 00684 pMenu->insertSeparator(); 00685 id = pMenu->insertItem(i18n("Very Short Compiler Output"), this, SLOT(slotVeryShortCompilerOutput()) ); 00686 pMenu->setWhatsThis(id, i18n("<b>Very short compiler output</b><p>Displays only warnings, errors and the file names which are compiled.")); 00687 pMenu->setItemChecked(id, m_compilerOutputLevel == eVeryShort); 00688 id = pMenu->insertItem(i18n("Short Compiler Output"), this, SLOT(slotShortCompilerOutput()) ); 00689 pMenu->setWhatsThis(id, i18n("<b>Short compiler output</b><p>Suppresses all the compiler flags and formats to something readable.")); 00690 pMenu->setItemChecked(id, m_compilerOutputLevel == eShort); 00691 id = pMenu->insertItem(i18n("Full Compiler Output"), this, SLOT(slotFullCompilerOutput()) ); 00692 pMenu->setWhatsThis(id, i18n("<b>Full compiler output</b><p>Displays unmodified compiler output.")); 00693 pMenu->setItemChecked(id, m_compilerOutputLevel == eFull); 00694 00695 pMenu->insertSeparator(); 00696 id = pMenu->insertItem(i18n("Show Directory Navigation Messages"), this, SLOT(toggleShowDirNavigMessages())); 00697 pMenu->setWhatsThis(id, i18n("<b>Show directory navigation messages</b><p>Shows <b>cd</b> commands that are executed while building.")); 00698 pMenu->setItemChecked(id, DirectoryItem::getShowDirectoryMessages()); 00699 00700 return pMenu; 00701 } 00702 00703 void MakeWidget::toggleLineWrapping() 00704 { 00705 m_bLineWrapping = !m_bLineWrapping; 00706 KConfig *pConfig = kapp->config(); 00707 pConfig->setGroup("MakeOutputView"); 00708 pConfig->writeEntry("LineWrapping", m_bLineWrapping); 00709 pConfig->sync(); 00710 if (m_bLineWrapping) { 00711 setWordWrap(WidgetWidth); 00712 } 00713 else 00714 { 00715 setWordWrap(NoWrap); 00716 } 00717 } 00718 00719 void MakeWidget::refill() 00720 { 00721 clear(); 00722 m_paragraphToItem.clear(); 00723 m_paragraphs = 0; 00724 for( uint i = 0; i < m_items.size(); i++ ) 00725 { 00726 if ( m_bCompiling && !m_items[i]->visible( m_compilerOutputLevel ) ) 00727 continue; 00728 m_paragraphToItem.insert( m_paragraphs++, m_items[i] ); 00729 append( m_items[i]->formattedText( m_compilerOutputLevel, brightBg() ) ); 00730 } 00731 00732 } 00733 00734 void MakeWidget::slotVeryShortCompilerOutput() { setCompilerOutputLevel(eVeryShort); } 00735 void MakeWidget::slotShortCompilerOutput() { setCompilerOutputLevel(eShort); } 00736 void MakeWidget::slotFullCompilerOutput() { setCompilerOutputLevel(eFull); } 00737 00738 void MakeWidget::setCompilerOutputLevel(EOutputLevel level) 00739 { 00740 m_compilerOutputLevel = level; 00741 KConfig *pConfig = kapp->config(); 00742 pConfig->setGroup("MakeOutputView"); 00743 pConfig->writeEntry("CompilerOutputLevel", (int) level); 00744 pConfig->sync(); 00745 refill(); 00746 } 00747 00748 void MakeWidget::toggleShowDirNavigMessages() 00749 { 00750 DirectoryItem::setShowDirectoryMessages( !DirectoryItem::getShowDirectoryMessages() ); 00751 KConfig *pConfig = kapp->config(); 00752 pConfig->setGroup("MakeOutputView"); 00753 pConfig->writeEntry("ShowDirNavigMsg", DirectoryItem::getShowDirectoryMessages()); 00754 pConfig->sync(); 00755 refill(); 00756 } 00757 00758 void MakeWidget::updateSettingsFromConfig() 00759 { 00760 KConfig *pConfig = kapp->config(); 00761 pConfig->setGroup("MakeOutputView"); 00762 setFont(pConfig->readFontEntry("Messages Font")); 00763 m_bLineWrapping = pConfig->readBoolEntry("LineWrapping", true); 00764 m_compilerOutputLevel = (EOutputLevel) pConfig->readNumEntry("CompilerOutputLevel", (int) eVeryShort); 00765 DirectoryItem::setShowDirectoryMessages( pConfig->readBoolEntry("ShowDirNavigMsg", false) ); 00766 } 00767 00768 bool MakeWidget::scanErrorForward( int parag ) 00769 { 00770 for ( int it = parag + 1; 00771 #if QT_VERSION >= 0x030100 00772 it < (int)m_items.count(); 00773 #else 00774 it < m_items.size(); 00775 #endif 00776 ++it ) 00777 { 00778 ErrorItem* item = dynamic_cast<ErrorItem*>( m_paragraphToItem[it] ); 00779 if ( !item ) 00780 continue; 00781 parag = it; 00782 document()->removeSelection(0); 00783 setSelection(parag, 0, parag+1, 0, 0); 00784 setCursorPosition(parag, 0); 00785 ensureCursorVisible(); 00786 searchItem( it ); 00787 return true; 00788 } 00789 return false; 00790 } 00791 00792 bool MakeWidget::scanErrorBackward( int parag ) 00793 { 00794 for ( int it = parag - 1; it >= 0; --it) 00795 { 00796 ErrorItem* item = dynamic_cast<ErrorItem*>( m_paragraphToItem[it] ); 00797 if ( !item ) 00798 continue; 00799 parag = it; 00800 document()->removeSelection(0); 00801 setSelection(parag, 0, parag+1, 0, 0); 00802 setCursorPosition(parag, 0); 00803 ensureCursorVisible(); 00804 searchItem( it ); 00805 return true; 00806 } 00807 return false; 00808 } 00809 00810 #include "makewidget.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:52 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003