kate Library API Documentation

kateviewhelpers.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> 00003 Copyright (C) 2001 Anders Lund <anders@alweb.dk> 00004 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include "kateviewhelpers.h" 00022 #include "kateviewhelpers.moc" 00023 00024 #include "kateview.h" 00025 #include "kateviewinternal.h" 00026 #include "katedocument.h" 00027 #include "katecodefoldinghelpers.h" 00028 #include "katerenderer.h" 00029 #include "kateattribute.h" 00030 #include "kateconfig.h" 00031 00032 #include <kglobalsettings.h> 00033 #include <klocale.h> 00034 00035 #include <qpainter.h> 00036 #include <qpopupmenu.h> 00037 #include <qcursor.h> 00038 #include <qstyle.h> 00039 #include <qtimer.h> 00040 00041 #include <math.h> 00042 00043 #include "kateview.h" 00044 #include "katefactory.h" 00045 00046 #include "../interfaces/katecmd.h" 00047 #include "../interfaces/document.h" 00048 00049 #include <klocale.h> 00050 00051 #include <qtimer.h> 00052 00053 KateCmdLine::KateCmdLine (KateView *view) 00054 : KLineEdit (view) 00055 , m_view (view) 00056 , m_msgMode (false) 00057 { 00058 connect (this, SIGNAL(returnPressed(const QString &)), 00059 this, SLOT(slotReturnPressed(const QString &))); 00060 00061 completionObject()->insertItems (KateCmd::self()->cmds()); 00062 } 00063 00064 KateCmdLine::~KateCmdLine () 00065 { 00066 } 00067 00068 void KateCmdLine::slotReturnPressed ( const QString& cmd ) 00069 { 00070 if (cmd.length () > 0) 00071 { 00072 Kate::Command *p = KateCmd::self()->queryCommand (cmd); 00073 00074 m_oldText = cmd; 00075 m_msgMode = true; 00076 00077 if (p) 00078 { 00079 QString msg; 00080 00081 if (p->exec (m_view, cmd, msg)) 00082 { 00083 completionObject()->addItem (cmd); 00084 m_oldText = QString (); 00085 00086 if (msg.length() > 0) 00087 setText (i18n ("Success: ") + msg); 00088 else 00089 setText (i18n ("Success")); 00090 } 00091 else 00092 { 00093 if (msg.length() > 0) 00094 setText (i18n ("Error: ") + msg); 00095 else 00096 setText (i18n ("Command \"%1\" failed.").arg (cmd)); 00097 } 00098 } 00099 else 00100 setText (i18n ("No such command: \"%1\"").arg (cmd)); 00101 } 00102 00103 m_view->setFocus (); 00104 QTimer::singleShot( 4000, this, SLOT(hideMe()) ); 00105 } 00106 00107 void KateCmdLine::hideMe () 00108 { 00109 m_view->showCmdLine (false); 00110 } 00111 00112 void KateCmdLine::focusInEvent ( QFocusEvent *ev ) 00113 { 00114 if (m_msgMode) 00115 { 00116 m_msgMode = false; 00117 setText (m_oldText); 00118 } 00119 00120 KLineEdit::focusInEvent (ev); 00121 } 00122 00123 void KateCmdLine::keyPressEvent( QKeyEvent *ev ) 00124 { 00125 if (ev->key() == Key_Escape) 00126 { 00127 m_view->setFocus (); 00128 m_view->showCmdLine (false); 00129 } 00130 00131 return KLineEdit::keyPressEvent (ev); 00132 } 00133 00134 using namespace KTextEditor; 00135 00136 static const char* const plus_xpm[] = { 00137 "11 11 3 1", 00138 " c None", 00139 ". c #000000", 00140 "+ c #FFFFFF", 00141 "...........", 00142 ".+++++++++.", 00143 ".+++++++++.", 00144 ".++++.++++.", 00145 ".++++.++++.", 00146 ".++.....++.", 00147 ".++++.++++.", 00148 ".++++.++++.", 00149 ".+++++++++.", 00150 ".+++++++++.", 00151 "..........."}; 00152 00153 static const char* const minus_xpm[] = { 00154 "11 11 3 1", 00155 " c None", 00156 ". c #000000", 00157 "+ c #FFFFFF", 00158 "...........", 00159 ".+++++++++.", 00160 ".+++++++++.", 00161 ".+++++++++.", 00162 ".+++++++++.", 00163 ".++.....++.", 00164 ".+++++++++.", 00165 ".+++++++++.", 00166 ".+++++++++.", 00167 ".+++++++++.", 00168 "..........."}; 00169 00170 00171 static const char* const bookmark_xpm[]={ 00172 "12 12 4 1", 00173 "b c #808080", 00174 "a c #000080", 00175 "# c #0000ff", 00176 ". c None", 00177 "........###.", 00178 ".......#...a", 00179 "......#.##.a", 00180 ".....#.#..aa", 00181 "....#.#...a.", 00182 "...#.#.a.a..", 00183 "..#.#.a.a...", 00184 ".#.#.a.a....", 00185 "#.#.a.a.....", 00186 "#.#a.a...bbb", 00187 "#...a..bbb..", 00188 ".aaa.bbb...."}; 00189 00190 const int iconPaneWidth = 16; 00191 const int halfIPW = 8; 00192 00193 static QPixmap minus_px ((const char**)minus_xpm); 00194 static QPixmap plus_px ((const char**)plus_xpm); 00195 00196 KateIconBorder::KateIconBorder ( KateViewInternal* internalView, QWidget *parent ) 00197 : QWidget(parent, "", Qt::WStaticContents | Qt::WRepaintNoErase | Qt::WResizeNoErase ) 00198 , m_view( internalView->m_view ) 00199 , m_doc( internalView->m_doc ) 00200 , m_viewInternal( internalView ) 00201 , m_iconBorderOn( false ) 00202 , m_lineNumbersOn( false ) 00203 , m_foldingMarkersOn( false ) 00204 , m_dynWrapIndicatorsOn( false ) 00205 , m_dynWrapIndicators( 0 ) 00206 , m_cachedLNWidth( 0 ) 00207 , m_maxCharWidth( 0 ) 00208 { 00209 setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) ); 00210 00211 setBackgroundMode( NoBackground ); 00212 00213 m_doc->setDescription( MarkInterface::markType01, i18n("Bookmark") ); 00214 m_doc->setPixmap( MarkInterface::markType01, QPixmap((const char**)bookmark_xpm) ); 00215 00216 updateFont(); 00217 } 00218 00219 void KateIconBorder::setIconBorderOn( bool enable ) 00220 { 00221 if( enable == m_iconBorderOn ) 00222 return; 00223 00224 m_iconBorderOn = enable; 00225 00226 updateGeometry(); 00227 00228 QTimer::singleShot( 0, this, SLOT(update()) ); 00229 } 00230 00231 void KateIconBorder::setLineNumbersOn( bool enable ) 00232 { 00233 if( enable == m_lineNumbersOn ) 00234 return; 00235 00236 m_lineNumbersOn = enable; 00237 m_dynWrapIndicatorsOn = (m_dynWrapIndicators == 1) ? enable : m_dynWrapIndicators; 00238 00239 updateGeometry(); 00240 00241 QTimer::singleShot( 0, this, SLOT(update()) ); 00242 } 00243 00244 void KateIconBorder::setDynWrapIndicators( int state ) 00245 { 00246 if (state == m_dynWrapIndicators ) 00247 return; 00248 00249 m_dynWrapIndicators = state; 00250 m_dynWrapIndicatorsOn = (state == 1) ? m_lineNumbersOn : state; 00251 00252 updateGeometry (); 00253 00254 QTimer::singleShot( 0, this, SLOT(update()) ); 00255 } 00256 00257 void KateIconBorder::setFoldingMarkersOn( bool enable ) 00258 { 00259 if( enable == m_foldingMarkersOn ) 00260 return; 00261 00262 m_foldingMarkersOn = enable; 00263 00264 updateGeometry(); 00265 00266 QTimer::singleShot( 0, this, SLOT(update()) ); 00267 } 00268 00269 QSize KateIconBorder::sizeHint() const 00270 { 00271 int w = 0; 00272 00273 if (m_iconBorderOn) 00274 w += iconPaneWidth + 1; 00275 00276 if (m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn)) { 00277 w += lineNumberWidth(); 00278 } 00279 00280 if (m_foldingMarkersOn) 00281 w += iconPaneWidth; 00282 00283 w += 4; 00284 00285 return QSize( w, 0 ); 00286 } 00287 00288 // This function (re)calculates the maximum width of any of the digit characters (0 -> 9) 00289 // for graceful handling of variable-width fonts as the linenumber font. 00290 void KateIconBorder::updateFont() 00291 { 00292 const QFontMetrics *fm = m_view->renderer()->config()->fontMetrics(); 00293 m_maxCharWidth = 0; 00294 // Loop to determine the widest numeric character in the current font. 00295 // 48 is ascii '0' 00296 for (int i = 48; i < 58; i++) { 00297 int charWidth = fm->width( QChar(i) ); 00298 m_maxCharWidth = QMAX(m_maxCharWidth, charWidth); 00299 } 00300 } 00301 00302 int KateIconBorder::lineNumberWidth() const 00303 { 00304 int width = m_lineNumbersOn ? ((int)log10((double)(m_view->doc()->numLines())) + 1) * m_maxCharWidth + 4 : 0; 00305 00306 if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) { 00307 width = QMAX(style().scrollBarExtent().width() + 4, width); 00308 00309 if (m_cachedLNWidth != width || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor()) { 00310 int w = style().scrollBarExtent().width(); 00311 int h = m_view->renderer()->config()->fontMetrics()->height(); 00312 00313 QSize newSize(w, h); 00314 if ((m_arrow.size() != newSize || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor()) && !newSize.isEmpty()) { 00315 m_arrow.resize(newSize); 00316 00317 QPainter p(&m_arrow); 00318 p.fillRect( 0, 0, w, h, *m_view->renderer()->config()->iconBarColor() ); 00319 00320 h = m_view->renderer()->config()->fontMetrics()->ascent(); 00321 00322 p.setPen(m_view->renderer()->attribute(0)->textColor()); 00323 p.drawLine(w/2, h/2, w/2, 0); 00324 #if 1 00325 p.lineTo(w/4, h/4); 00326 p.lineTo(0, 0); 00327 p.lineTo(0, h/2); 00328 p.lineTo(w/2, h-1); 00329 p.lineTo(w*3/4, h-1); 00330 p.lineTo(w-1, h*3/4); 00331 p.lineTo(w*3/4, h/2); 00332 p.lineTo(0, h/2); 00333 #else 00334 p.lineTo(w*3/4, h/4); 00335 p.lineTo(w-1,0); 00336 p.lineTo(w-1, h/2); 00337 p.lineTo(w/2, h-1); 00338 p.lineTo(w/4,h-1); 00339 p.lineTo(0, h*3/4); 00340 p.lineTo(w/4, h/2); 00341 p.lineTo(w-1, h/2); 00342 #endif 00343 } 00344 } 00345 } 00346 00347 return width; 00348 } 00349 00350 void KateIconBorder::paintEvent(QPaintEvent* e) 00351 { 00352 paintBorder(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height()); 00353 } 00354 00355 void KateIconBorder::paintBorder (int /*x*/, int y, int /*width*/, int height) 00356 { 00357 uint h = m_view->renderer()->config()->fontStruct()->fontHeight; 00358 uint startz = (y / h); 00359 uint endz = startz + 1 + (height / h); 00360 uint lineRangesSize = m_viewInternal->lineRanges.size(); 00361 00362 // center the folding boxes 00363 int m_px = (h - 11) / 2; 00364 if (m_px < 0) 00365 m_px = 0; 00366 00367 int lnWidth( 0 ); 00368 if ( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) // avoid calculating unless needed ;-) 00369 { 00370 lnWidth = lineNumberWidth(); 00371 if ( lnWidth != m_cachedLNWidth || m_oldBackgroundColor != *m_view->renderer()->config()->iconBarColor() ) 00372 { 00373 // we went from n0 ->n9 lines or vice verca 00374 // this causes an extra updateGeometry() first time the line numbers 00375 // are displayed, but sizeHint() is supposed to be const so we can't set 00376 // the cached value there. 00377 m_cachedLNWidth = lnWidth; 00378 m_oldBackgroundColor = *m_view->renderer()->config()->iconBarColor(); 00379 updateGeometry(); 00380 update (); 00381 return; 00382 } 00383 } 00384 00385 int w( this->width() ); // sane value/calc only once 00386 00387 QPainter p ( this ); 00388 p.setFont ( *m_view->renderer()->config()->font() ); // for line numbers 00389 p.setPen ( m_view->renderer()->attribute(0)->textColor() ); 00390 00391 KateLineInfo oldInfo; 00392 if (startz < lineRangesSize) 00393 { 00394 if ((m_viewInternal->lineRanges[startz].line-1) < 0) 00395 oldInfo.topLevel = true; 00396 else 00397 m_doc->lineInfo(&oldInfo,m_viewInternal->lineRanges[startz].line-1); 00398 } 00399 00400 for (uint z=startz; z <= endz; z++) 00401 { 00402 int y = h * z; 00403 int realLine = -1; 00404 00405 if (z < lineRangesSize) 00406 realLine = m_viewInternal->lineRanges[z].line; 00407 00408 int lnX ( 0 ); 00409 00410 p.fillRect( 0, y, w-4, h, *m_view->renderer()->config()->iconBarColor() ); 00411 p.fillRect( w-4, y, 4, h, *m_view->renderer()->config()->backgroundColor() ); 00412 00413 // icon pane 00414 if( m_iconBorderOn ) 00415 { 00416 p.drawLine(lnX+iconPaneWidth, y, lnX+iconPaneWidth, y+h); 00417 00418 if( (realLine > -1) && (m_viewInternal->lineRanges[z].startCol == 0) ) 00419 { 00420 uint mrk ( m_doc->mark( realLine ) ); // call only once 00421 00422 if ( mrk ) 00423 { 00424 for( uint bit = 0; bit < 32; bit++ ) 00425 { 00426 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit); 00427 if( mrk & markType ) 00428 { 00429 QPixmap *px_mark (m_doc->markPixmap( markType )); 00430 00431 if (px_mark) 00432 { 00433 // center the mark pixmap 00434 int x_px = (iconPaneWidth - px_mark->width()) / 2; 00435 if (x_px < 0) 00436 x_px = 0; 00437 00438 int y_px = (h - px_mark->height()) / 2; 00439 if (y_px < 0) 00440 y_px = 0; 00441 00442 p.drawPixmap( lnX+x_px, y+y_px, *px_mark); 00443 } 00444 } 00445 } 00446 } 00447 } 00448 00449 lnX += iconPaneWidth + 1; 00450 } 00451 00452 // line number 00453 if( m_lineNumbersOn || (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) ) 00454 { 00455 lnX +=2; 00456 00457 if (realLine > -1) 00458 if (m_viewInternal->lineRanges[z].startCol == 0) { 00459 if (m_lineNumbersOn) 00460 p.drawText( lnX + 1, y, lnWidth-4, h, Qt::AlignRight|Qt::AlignVCenter, QString("%1").arg( realLine + 1 ) ); 00461 } else if (m_view->dynWordWrap() && m_dynWrapIndicatorsOn) { 00462 p.drawPixmap(lnX + lnWidth - m_arrow.width() - 4, y, m_arrow); 00463 } 00464 00465 lnX += lnWidth; 00466 } 00467 00468 // folding markers 00469 if( m_foldingMarkersOn ) 00470 { 00471 if( realLine > -1 ) 00472 { 00473 KateLineInfo info; 00474 m_doc->lineInfo(&info,realLine); 00475 00476 if (!info.topLevel) 00477 { 00478 if (info.startsVisibleBlock && (m_viewInternal->lineRanges[z].startCol == 0)) 00479 { 00480 if (oldInfo.topLevel) 00481 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1); 00482 else 00483 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00484 00485 p.drawPixmap(lnX+3,y+m_px,minus_px); 00486 } 00487 else if (info.startsInVisibleBlock) 00488 { 00489 if (m_viewInternal->lineRanges[z].startCol == 0) 00490 { 00491 if (oldInfo.topLevel) 00492 p.drawLine(lnX+halfIPW,y+m_px,lnX+halfIPW,y+h-1); 00493 else 00494 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00495 00496 p.drawPixmap(lnX+3,y+m_px,plus_px); 00497 } 00498 else 00499 { 00500 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00501 } 00502 00503 if (!m_viewInternal->lineRanges[z].wrap) 00504 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1); 00505 } 00506 else 00507 { 00508 p.drawLine(lnX+halfIPW,y,lnX+halfIPW,y+h-1); 00509 00510 if (info.endsBlock && !m_viewInternal->lineRanges[z].wrap) 00511 p.drawLine(lnX+halfIPW,y+h-1,lnX+iconPaneWidth-2,y+h-1); 00512 } 00513 } 00514 00515 oldInfo = info; 00516 } 00517 00518 lnX += iconPaneWidth; 00519 } 00520 } 00521 } 00522 00523 KateIconBorder::BorderArea KateIconBorder::positionToArea( const QPoint& p ) const 00524 { 00525 int x = 0; 00526 00527 if( m_iconBorderOn ) { 00528 x += iconPaneWidth; 00529 if( p.x() <= x ) 00530 return IconBorder; 00531 } 00532 if( m_lineNumbersOn || m_dynWrapIndicators ) { 00533 x += lineNumberWidth(); 00534 if( p.x() <= x ) 00535 return LineNumbers; 00536 } 00537 if( m_foldingMarkersOn ) { 00538 x += iconPaneWidth; 00539 if( p.x() <= x ) 00540 return FoldingMarkers; 00541 } 00542 return None; 00543 } 00544 00545 void KateIconBorder::mousePressEvent( QMouseEvent* e ) 00546 { 00547 m_lastClickedLine = m_viewInternal->yToLineRange(e->y()).line; 00548 00549 if ( positionToArea( e->pos() ) != IconBorder ) 00550 { 00551 QMouseEvent forward( QEvent::MouseButtonPress, 00552 QPoint( 0, e->y() ), e->button(), e->state() ); 00553 m_viewInternal->mousePressEvent( &forward ); 00554 } 00555 e->accept(); 00556 } 00557 00558 void KateIconBorder::mouseMoveEvent( QMouseEvent* e ) 00559 { 00560 QMouseEvent forward( QEvent::MouseMove, 00561 QPoint( 0, e->y() ), e->button(), e->state() ); 00562 m_viewInternal->mouseMoveEvent( &forward ); 00563 } 00564 00565 void KateIconBorder::mouseReleaseEvent( QMouseEvent* e ) 00566 { 00567 uint cursorOnLine = m_viewInternal->yToLineRange(e->y()).line; 00568 00569 if (cursorOnLine == m_lastClickedLine && 00570 cursorOnLine <= m_doc->lastLine() ) 00571 { 00572 BorderArea area = positionToArea( e->pos() ); 00573 if( area == IconBorder) { 00574 if (e->button() == LeftButton) { 00575 if( m_doc->editableMarks() & KateViewConfig::global()->defaultMarkType() ) { 00576 if( m_doc->mark( cursorOnLine ) & KateViewConfig::global()->defaultMarkType() ) 00577 m_doc->removeMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() ); 00578 else 00579 m_doc->addMark( cursorOnLine, KateViewConfig::global()->defaultMarkType() ); 00580 } else { 00581 showMarkMenu( cursorOnLine, QCursor::pos() ); 00582 } 00583 } 00584 else 00585 if (e->button() == RightButton) { 00586 showMarkMenu( cursorOnLine, QCursor::pos() ); 00587 } 00588 } 00589 00590 if ( area == FoldingMarkers) { 00591 KateLineInfo info; 00592 m_doc->lineInfo(&info,cursorOnLine); 00593 if ((info.startsVisibleBlock) || (info.startsInVisibleBlock)) { 00594 emit toggleRegionVisibility(cursorOnLine); 00595 } 00596 } 00597 } 00598 00599 QMouseEvent forward( QEvent::MouseButtonRelease, 00600 QPoint( 0, e->y() ), e->button(), e->state() ); 00601 m_viewInternal->mouseReleaseEvent( &forward ); 00602 } 00603 00604 void KateIconBorder::mouseDoubleClickEvent( QMouseEvent* e ) 00605 { 00606 QMouseEvent forward( QEvent::MouseButtonDblClick, 00607 QPoint( 0, e->y() ), e->button(), e->state() ); 00608 m_viewInternal->mouseDoubleClickEvent( &forward ); 00609 } 00610 00611 void KateIconBorder::showMarkMenu( uint line, const QPoint& pos ) 00612 { 00613 QPopupMenu markMenu; 00614 QPopupMenu selectDefaultMark; 00615 00616 typedef QValueVector<int> MarkTypeVector; 00617 MarkTypeVector vec( 33 ); 00618 int i=1; 00619 00620 for( uint bit = 0; bit < 32; bit++ ) { 00621 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1<<bit); 00622 if( !(m_doc->editableMarks() & markType) ) 00623 continue; 00624 00625 if( !m_doc->markDescription( markType ).isEmpty() ) { 00626 markMenu.insertItem( m_doc->markDescription( markType ), i ); 00627 selectDefaultMark.insertItem( m_doc->markDescription( markType ), i+100); 00628 } else { 00629 markMenu.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i ); 00630 selectDefaultMark.insertItem( i18n("Mark Type %1").arg( bit + 1 ), i+100); 00631 } 00632 00633 if( m_doc->mark( line ) & markType ) 00634 markMenu.setItemChecked( i, true ); 00635 00636 if( markType & KateViewConfig::global()->defaultMarkType() ) 00637 selectDefaultMark.setItemChecked( i+100, true ); 00638 00639 vec[i++] = markType; 00640 } 00641 00642 if( markMenu.count() == 0 ) 00643 return; 00644 00645 if( markMenu.count() > 1 ) 00646 markMenu.insertItem( i18n("Set Default Mark Type" ), &selectDefaultMark); 00647 00648 int result = markMenu.exec( pos ); 00649 if( result <= 0 ) 00650 return; 00651 00652 if ( result > 100) 00653 KateViewConfig::global()->setDefaultMarkType (vec[result-100]); 00654 else 00655 { 00656 MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes) vec[result]; 00657 if( m_doc->mark( line ) & markType ) { 00658 m_doc->removeMark( line, markType ); 00659 } else { 00660 m_doc->addMark( line, markType ); 00661 } 00662 } 00663 } 00664 00665 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:16:27 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003