kspread Library API Documentation

kspread_util.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "kspread_util.h"
00021 #include "kspread_map.h"
00022 #include "kspread_doc.h"
00023 #include "kspread_locale.h"
00024 #include <ctype.h>
00025 
00026 #include <qregexp.h>
00027 
00028 #include <kdebug.h>
00029 
00030 //helper functions for the formatting
00031 bool formatIsDate (FormatType fmt)
00032 {
00033   return ((fmt == ShortDate_format) || (fmt == TextDate_format) ||
00034       (((int) fmt >= 200) && ((int) fmt < 300)));
00035 }
00036 
00037 bool formatIsTime (FormatType fmt)
00038 {
00039   return (((int) fmt >= 50) && ((int) fmt < 70));
00040 }
00041 
00042 bool formatIsFraction (FormatType fmt)
00043 {
00044   return (((int) fmt >= 70) && ((int) fmt < 80));
00045 }
00046 
00047 
00048 //used in KSpreadPoint::init, KSpreadCell::encodeFormula and
00049 //  dialogs/kspread_dlg_paperlayout.cc
00050 int util_decodeColumnLabelText( const QString &_col )
00051 {
00052     int col = 0;
00053     int offset='a'-'A';
00054     int counterColumn = 0;
00055     for ( uint i=0; i < _col.length(); i++ )
00056     {
00057         counterColumn = (int) pow(26.0 , static_cast<int>(_col.length() - i - 1));
00058         if( _col[i] >= 'A' && _col[i] <= 'Z' )
00059             col += counterColumn * ( _col[i].latin1() - 'A' + 1);  // okay here (Werner)
00060         else if( _col[i] >= 'a' && _col[i] <= 'z' )
00061             col += counterColumn * ( _col[i].latin1() - 'A' - offset + 1 );
00062         else
00063             kdDebug(36001) << "util_decodeColumnLabelText: Wrong characters in label text for col:'" << _col << "'" << endl;
00064     }
00065     return col;
00066 }
00067 
00068 //used in dialogs/kspread_dlg_paperlayout.cc
00069 QString util_rangeColumnName( const QRect &_area)
00070 {
00071     return QString("%1:%2")
00072         .arg( KSpreadCell::columnName( _area.left()))
00073         .arg( KSpreadCell::columnName(_area.right()));
00074 }
00075 
00076 //used in dialogs/kspread_dlg_paperlayout.cc
00077 QString util_rangeRowName( const QRect &_area)
00078 {
00079     return QString("%1:%2")
00080         .arg( _area.top())
00081         .arg(_area.bottom());
00082 }
00083 
00084 
00085 QString util_rangeName(const QRect &_area)
00086 {
00087     return KSpreadCell::name( _area.left(), _area.top() ) + ":" +
00088     KSpreadCell::name( _area.right(), _area.bottom() );
00089 }
00090 
00091 QString util_rangeName(KSpreadSheet * _sheet, const QRect &_area)
00092 {
00093     return _sheet->sheetName() + "!" + util_rangeName(_area);
00094 }
00095 
00096 QDomElement util_createElement( const QString & tagName, const QFont & font, QDomDocument & doc )
00097 {
00098   QDomElement e( doc.createElement( tagName ) );
00099 
00100   e.setAttribute( "family", font.family() );
00101   e.setAttribute( "size", font.pointSize() );
00102   e.setAttribute( "weight", font.weight() );
00103   if ( font.bold() )
00104     e.setAttribute( "bold", "yes" );
00105   if ( font.italic() )
00106     e.setAttribute( "italic", "yes" );
00107   if ( font.underline() )
00108     e.setAttribute( "underline", "yes" );
00109   if ( font.strikeOut() )
00110     e.setAttribute( "strikeout", "yes" );
00111   //e.setAttribute( "charset", KGlobal::charsets()->name( font ) );
00112 
00113   return e;
00114 }
00115 
00116 QDomElement util_createElement( const QString & tagname, const QPen & pen, QDomDocument & doc )
00117 {
00118   QDomElement e( doc.createElement( tagname ) );
00119   e.setAttribute( "color", pen.color().name() );
00120   e.setAttribute( "style", (int)pen.style() );
00121   e.setAttribute( "width", (int)pen.width() );
00122   return e;
00123 }
00124 
00125 QFont util_toFont( QDomElement & element )
00126 {
00127   QFont f;
00128   f.setFamily( element.attribute( "family" ) );
00129 
00130   bool ok;
00131   f.setPointSize( element.attribute("size").toInt( &ok ) );
00132   if ( !ok )
00133     return QFont();
00134 
00135   f.setWeight( element.attribute("weight").toInt( &ok ) );
00136   if ( !ok )
00137     return QFont();
00138 
00139   if ( element.hasAttribute( "italic" ) && element.attribute("italic") == "yes" )
00140     f.setItalic( TRUE );
00141 
00142   if ( element.hasAttribute( "bold" ) && element.attribute("bold") == "yes" )
00143     f.setBold( TRUE );
00144 
00145   if ( element.hasAttribute( "underline" ) && element.attribute("underline") == "yes" )
00146     f.setUnderline( TRUE );
00147 
00148   if ( element.hasAttribute( "strikeout" ) && element.attribute("strikeout") == "yes" )
00149     f.setStrikeOut( TRUE );
00150 
00151   /* Uncomment when charset is added to kspread_dlg_layout
00152      + save a document-global charset
00153      if ( element.hasAttribute( "charset" ) )
00154        KGlobal::charsets()->setQFont( f, element.attribute("charset") );
00155       else
00156   */
00157   // ######## Not needed anymore in 3.0?
00158   //KGlobal::charsets()->setQFont( f, KGlobal::locale()->charset() );
00159 
00160   return f;
00161 }
00162 
00163 QPen util_toPen( QDomElement & element )
00164 {
00165   bool ok;
00166   QPen p;
00167 
00168   p.setStyle( (Qt::PenStyle)element.attribute("style").toInt( &ok ) );
00169   if ( !ok )
00170     return QPen();
00171 
00172   p.setWidth( element.attribute("width").toInt( &ok ) );
00173   if ( !ok )
00174     return QPen();
00175 
00176   p.setColor( QColor( element.attribute("color") ) );
00177 
00178   return p;
00179 }
00180 
00181 KSpreadPoint::KSpreadPoint(const QString & _str)
00182 {
00183     sheet = 0;
00184     init(_str);
00185 }
00186 
00187 void KSpreadPoint::init(const QString & _str)
00188 {
00189 
00190 //    kdDebug(36001) <<"KSpreadPoint::init ("<<_str<<")"<<endl;
00191     pos.setX(-1);
00192 
00193     uint len = _str.length();
00194     if ( !len )
00195     {
00196     kdDebug(36001) << "KSpreadPoint::init: len = 0" << endl;
00197     return;
00198     }
00199 
00200     QString str( _str );
00201     int n = _str.find( '!' );
00202     if ( n != -1 )
00203     {
00204       sheetName = _str.left( n );
00205       str = _str.right( len - n - 1 ); // remove the '!'
00206       len = str.length();
00207     }
00208 
00209     uint p = 0;
00210 
00211     // Fixed ?
00212     if ( str[0] == '$' )
00213     {
00214     columnFixed = true;
00215     p++;
00216     }
00217     else
00218     columnFixed = false;
00219 
00220     // Malformed ?
00221     if ( p == len )
00222     {
00223     kdDebug(36001) << "KSpreadPoint::init: no point after '$' (str: '" << str.mid( p ) << "'" << endl;
00224     return;
00225     }
00226     if ( str[p] < 'A' || str[p] > 'Z' )
00227     {
00228     if ( str[p] < 'a' || str[p] > 'z' )
00229     {
00230         kdDebug(36001) << "KSpreadPoint::init: wrong first character in point (str: '" << str.mid( p ) << "'" << endl;
00231         return;
00232     }
00233     }
00234     //default is error
00235     int x = -1;
00236     //search for the first character != text
00237     int result = str.find( QRegExp("[^A-Za-z]+"), p );
00238 
00239     //get the colomn number for the character between actual position and the first non text charakter
00240     if ( result != -1 )
00241     x = util_decodeColumnLabelText( str.mid( p, result - p ) ); // x is defined now
00242     else  // If there isn't any, then this is not a point -> return
00243     {
00244     kdDebug(36001) << "KSpreadPoint::init: no number in string (str: '" << str.mid( p, result ) << "'" << endl;
00245     return;
00246     }
00247     p = result;
00248 
00249     //limit is KS_colMax
00250     if ( x > KS_colMax )
00251     {
00252     kdDebug(36001) << "KSpreadPoint::init: column value too high (col: " << x << ")" << endl;
00253     return;
00254     }
00255 
00256     // Malformed ?
00257     if (p == len)
00258     {
00259     kdDebug(36001) << "KSpreadPoint::init: p==len after cols" << endl;
00260     return;
00261     }
00262 
00263     if (str[p] == '$')
00264     {
00265     rowFixed = true;
00266     p++;
00267     // Malformed ?
00268     if ( p == len )
00269     {
00270         kdDebug(36001) << "KSpreadPoint::init: p==len after $ of row" << endl;
00271         return;
00272     }
00273     }
00274     else
00275     rowFixed = false;
00276 
00277     uint p2 = p;
00278     while ( p < len )
00279     {
00280     if ( !isdigit( QChar(str[p++]) ) )
00281     {
00282         kdDebug(36001) << "KSpreadPoint::init: no number" << endl;
00283         return;
00284     }
00285     }
00286 
00287     bool ok;
00288     int y = str.mid( p2, p-p2 ).toInt( &ok );
00289     if ( !ok )
00290     {
00291     kdDebug(36001) << "KSpreadPoint::init: Invalid number (str: '" << str.mid( p2, p-p2 ) << "'" << endl;
00292     return;
00293     }
00294     if ( y > KS_rowMax )
00295     {
00296     kdDebug(36001) << "KSpreadPoint::init: row value too high (row: " << y << ")" << endl;
00297     return;
00298     }
00299     if ( y <= 0 )
00300     {
00301     kdDebug(36001) << "KSpreadPoint::init: y <= 0" << endl;
00302     return;
00303     }
00304     pos = QPoint( x, y );
00305 }
00306 
00307 KSpreadPoint::KSpreadPoint( const QString & _str, KSpreadMap * _map,
00308                             KSpreadSheet * _sheet )
00309 {
00310     uint p = 0;
00311     int p2 = _str.find( '!' );
00312     if ( p2 != -1 )
00313     {
00314         sheetName = _str.left( p2++ );
00315         while ( true )
00316         {
00317             sheet = _map->findSheet( sheetName );
00318             if ( !sheet && sheetName[0] == ' ' )
00319             {
00320                 sheetName = sheetName.right( sheetName.length() - 1 );
00321                 continue;
00322             }
00323             break;
00324         }
00325         p = p2;
00326 
00327         //If the loop didn't return a sheet, better keep a string for isValid
00328         if ( sheetName.isEmpty() )
00329         {
00330             kdDebug(36001) << "KSpreadPoint: tableName is unknown" << endl;
00331             sheetName = "unknown";
00332         }
00333     }
00334     else
00335     {
00336         if ( _sheet != 0 )
00337         {
00338             sheet = _sheet;
00339             sheetName = _sheet->sheetName();
00340         }
00341         else
00342             sheet = 0;
00343     }
00344 
00345     init( _str.mid( p ) );
00346 }
00347 
00348 KSpreadCell *KSpreadPoint::cell() const
00349 {
00350     return sheet->cellAt(pos);
00351 }
00352 
00353 bool KSpreadPoint::operator== (const KSpreadPoint &cell) const
00354 {
00355   //sheet info ignored
00356   return (pos == cell.pos);
00357 }
00358 
00359 bool KSpreadPoint::operator< (const KSpreadPoint &cell) const
00360 {
00361   //sheet info ignored
00362   return (pos.y() < cell.pos.y()) ? true :
00363       ((pos.y() == cell.pos.y()) && (pos.x() < cell.pos.x()));
00364 }
00365 
00366 KSpreadRange::KSpreadRange(const QString & _str)
00367 {
00368     range.setLeft(-1);
00369     sheet = 0;
00370 
00371     int p = _str.find(':');
00372     if (p == -1)
00373     return;
00374 
00375     KSpreadPoint ul(_str.left(p));
00376     KSpreadPoint lr(_str.mid(p + 1));
00377     range = QRect(ul.pos, lr.pos);
00378     sheetName = ul.sheetName;
00379 
00380     leftFixed = ul.columnFixed;
00381     rightFixed = lr.columnFixed;
00382     topFixed = ul.rowFixed;
00383     bottomFixed = lr.rowFixed;
00384 }
00385 
00386 KSpreadRange::KSpreadRange(const QString & _str, KSpreadMap * _map,
00387                KSpreadSheet * _sheet)
00388 {
00389     range.setLeft(-1);
00390     sheet = 0;
00391     //used area Name as range
00392     if (_str.at(0) == "'" && _str.at(_str.length() - 1) == "'") {
00393     QString tmp = _str.right(_str.length() - 1);
00394     tmp = tmp.left(tmp.length() - 1);
00395     QValueList < Reference >::Iterator it;
00396     QValueList < Reference > area = _map->doc()->listArea();
00397     for (it = area.begin(); it != area.end(); ++it) {
00398         if ((*it).ref_name == tmp) {
00399         range = (*it).rect;
00400         sheet = _map->findSheet((*it).sheet_name);
00401         break;
00402         }
00403     }
00404     leftFixed = false;
00405     rightFixed = false;
00406     topFixed = false;
00407     bottomFixed = false;
00408     return;
00409     }
00410     range.setLeft(-1);
00411     sheet = 0;
00412 
00413     int p = 0;
00414     int p2 = _str.find('!');
00415     if (p2 != -1)
00416     {
00417       sheetName = _str.left(p2++);
00418       while ( true )
00419       {
00420     sheet = _map->findSheet(sheetName);
00421         if ( !sheet && sheetName[0] == ' ' )
00422         {
00423           sheetName = sheetName.right( sheetName.length() - 1 );
00424           continue;
00425         }
00426         break;
00427       }
00428       p = p2;
00429     } else
00430       sheet = _sheet;
00431 
00432 
00433     int p3 = _str.find(':', p);
00434     if (p3 == -1)
00435     return;
00436 
00437     KSpreadPoint ul(_str.mid(p, p3 - p));
00438     KSpreadPoint lr(_str.mid(p3 + 1));
00439     range = QRect(ul.pos, lr.pos);
00440 
00441     leftFixed = ul.columnFixed;
00442     rightFixed = lr.columnFixed;
00443     topFixed = ul.rowFixed;
00444     bottomFixed = lr.rowFixed;
00445 }
00446 
00447 bool KSpreadRange::contains (const KSpreadPoint &cell) const
00448 {
00449   return range.contains (cell.pos);
00450 }
00451 
00452 bool KSpreadRange::intersects (const KSpreadRange &r) const
00453 {
00454   return range.intersects (r.range);
00455 }
00456 
00457 //used in some math and statistical functions
00458 double util_fact( double val, double end )
00459 {
00460   /* fact =i*(i-1)*(i-2)*...*1 */
00461   if(val<0.0 || end<0.0)
00462     return (-1);
00463   if(val==0.0)
00464     return (1);
00465   else if (val==end)
00466     return(1);
00467   /*val==end => you don't multiplie it */
00468   else
00469     return (val*util_fact((double)(val-1),end));
00470 }
00471 
00472 bool util_isAllSelected(const QRect &selection)
00473 {
00474   return ( selection.top() == 1 && selection.bottom() == KS_rowMax
00475        && selection.left() == 1 && selection.right() == KS_colMax);
00476 }
00477 
00478 bool util_isColumnSelected(const QRect &selection)
00479 {
00480   return ( (selection.top() == 1) && (selection.bottom() == KS_rowMax) );
00481 }
00482 
00483 bool util_isRowSelected(const QRect &selection)
00484 {
00485   return ( (selection.left() == 1) && (selection.right() == KS_colMax) );
00486 }
00487 
00488 //used in KSpreadView::slotRename
00489 bool util_validateSheetName(const QString &name)
00490 {
00491   if (name[0] == ' ')
00492   {
00493     return false;
00494   }
00495   for (unsigned int i = 0; i < name.length(); i++)
00496   {
00497     if ( !(name[i].isLetterOrNumber() ||
00498            name[i] == ' ' || name[i] == '.' ||
00499            name[i] == '_'))
00500     {
00501       return false;
00502     }
00503   }
00504   return true;
00505 }
00506 
00507 
00508 KSpreadRangeIterator::KSpreadRangeIterator(QRect _range, KSpreadSheet* _sheet)
00509 {
00510   range = _range;
00511   sheet = _sheet;
00512   current = QPoint(0,0);
00513 }
00514 
00515 KSpreadRangeIterator::~KSpreadRangeIterator()
00516 {
00517 }
00518 
00519 KSpreadCell* KSpreadRangeIterator::first()
00520 {
00521   current.setY(range.top());
00522 
00523   /* OK, because even if this equals zero, the 'getNextCellRight' won't
00524      try to access it*/
00525   current.setX(range.left() - 1);
00526   return next();
00527 }
00528 
00529 KSpreadCell* KSpreadRangeIterator::next()
00530 {
00531   if (current.x() == 0 && current.y() == 0)
00532   {
00533     return first();
00534   }
00535 
00536   KSpreadCell* cell = NULL;
00537   bool done = false;
00538 
00539   while (cell == NULL && !done)
00540   {
00541     cell = sheet->getNextCellRight(current.x(), current.y());
00542     if (cell != NULL && cell->column() > range.right())
00543     {
00544       cell = NULL;
00545     }
00546 
00547     if (cell == NULL)
00548     {
00549       current.setX(range.left() - 1);
00550       current.setY(current.y() + 1);
00551       done = (current.y() > range.bottom());
00552     }
00553   }
00554   return cell;
00555 }
00556 
00557 //not used anywhere
00558 int util_penCompare( QPen const & pen1, QPen const & pen2 )
00559 {
00560   if ( pen1.style() == Qt::NoPen && pen2.style() == Qt::NoPen )
00561     return 0;
00562 
00563   if ( pen1.style() == Qt::NoPen )
00564     return -1;
00565 
00566   if ( pen2.style() == Qt::NoPen )
00567     return 1;
00568 
00569   if ( pen1.width() < pen2.width() )
00570     return -1;
00571 
00572   if ( pen1.width() > pen2.width() )
00573     return 1;
00574 
00575   if ( pen1.style() < pen2.style() )
00576     return -1;
00577 
00578   if ( pen1.style() > pen2.style() )
00579     return 1;
00580 
00581   if ( pen1.color().name() < pen2.color().name() )
00582     return -1;
00583 
00584   if ( pen1.color().name() > pen2.color().name() )
00585     return 1;
00586 
00587   return 0;
00588 }
00589 
00590 
00591 QString convertRefToBase( const QString & sheet, const QRect & rect )
00592 {
00593   QPoint bottomRight( rect.bottomRight() );
00594 
00595   QString s( "$" );
00596   s += sheet;
00597   s += ".$";
00598   s += KSpreadCell::columnName( bottomRight.x() );
00599   s += '$';
00600   s += QString::number( bottomRight.y() );
00601 
00602   return s;
00603 }
00604 
00605 QString convertRefToRange( const QString & sheet, const QRect & rect )
00606 {
00607   QPoint topLeft( rect.topLeft() );
00608   QPoint bottomRight( rect.bottomRight() );
00609 
00610   if ( topLeft == bottomRight )
00611     return convertRefToBase( sheet, rect );
00612 
00613   QString s( "$" );
00614   s += sheet;
00615   s += ".$";
00616   s += /*util_encodeColumnLabelText*/KSpreadCell::columnName( topLeft.x() );
00617   s += '$';
00618   s += QString::number( topLeft.y() );
00619   s += ":.$";
00620   s += /*util_encodeColumnLabelText*/KSpreadCell::columnName( bottomRight.x() );
00621   s += '$';
00622   s += QString::number( bottomRight.y() );
00623 
00624   return s;
00625 }
00626 
00627 //used in KSpreadCell::convertFormulaToOasisFormat
00628 void insertBracket( QString & s )
00629 {
00630   QChar c;
00631   int i = (int) s.length() - 1;
00632 
00633   while ( i >= 0 )
00634   {
00635     c = s[i];
00636     if ( c == ' ' )
00637       s[i] = '_';
00638     if ( !(c.isLetterOrNumber() || c == ' ' || c == '.'
00639            || c == '_') )
00640     {
00641       s.insert( i + 1, '[' );
00642       return;
00643     }
00644     --i;
00645   }
00646 }
00647 
00648  // e.g.: Sheet4.A1:Sheet4.E28
00649  //used in KSpreadSheet::saveOasis
00650 QString convertRangeToRef( const QString & sheetName, const QRect & _area )
00651 {
00652     return sheetName + "." + KSpreadCell::name( _area.left(), _area.top() ) + ":" + sheetName + "."+ KSpreadCell::name( _area.right(), _area.bottom() );
00653 }
00654 
00655 QString convertOasisPenToString( const QPen & pen )
00656 {
00657     kdDebug()<<"convertOasisPenToString( const QPen & pen ) :"<<pen<<endl;
00658     QString s = QString( "%1pt " ).arg( pen.width() );
00659     switch( pen.style() )
00660     {
00661     case Qt::NoPen:
00662         return "none";
00663     case Qt::SolidLine:
00664         s+="solid";
00665         break;
00666     case Qt::DashLine:
00667         s+="dashed";
00668         break;
00669     case Qt::DotLine:
00670         s+="dotted";
00671         break;
00672     case Qt::DashDotLine:
00673         s+="dot-dash";
00674         break;
00675     case Qt::DashDotDotLine:
00676         s+="dot-dot-dash";
00677         break;
00678     }
00679     kdDebug()<<" convertOasisPenToString :"<<s<<endl;
00680     if ( pen.color().isValid() )
00681     {
00682         s+=' ';
00683         s+=pen.color().name();
00684     }
00685     return s;
00686 }
00687 
00688 QPen convertOasisStringToPen( const QString &border )
00689 {
00690     QPen pen;
00691     //string like "0.088cm solid #800000"
00692     if (border.isEmpty() || border=="none" || border=="hidden") // in fact no border
00693     {
00694         pen.setStyle( Qt::NoPen );
00695         return pen;
00696     }
00697     //code from koborder, for the moment kspread doesn't use koborder
00698     // ## isn't it faster to use QStringList::split than parse it 3 times?
00699     QString _width = border.section(' ', 0, 0);
00700     QCString _style = border.section(' ', 1, 1).latin1();
00701     QString _color = border.section(' ', 2, 2);
00702 
00703     pen.setWidth( ( int )( KoUnit::parseValue( _width, 1.0 ) ) );
00704 
00705     if ( _style =="none" )
00706         pen.setStyle( Qt::NoPen );
00707     else if ( _style =="solid" )
00708         pen.setStyle( Qt::SolidLine );
00709     else if ( _style =="dashed" )
00710         pen.setStyle( Qt::DashLine );
00711     else if ( _style =="dotted" )
00712         pen.setStyle( Qt::DotLine );
00713     else if ( _style =="dot-dash" )
00714         pen.setStyle( Qt::DashDotLine );
00715     else if ( _style =="dot-dot-dash" )
00716         pen.setStyle( Qt::DashDotDotLine );
00717     else
00718         kdDebug()<<" style undefined : "<<_style<<endl;
00719 
00720     if ( _color.isEmpty() )
00721         pen.setColor( QColor() );
00722     else
00723         pen.setColor(  QColor( _color ) );
00724 
00725     return pen;
00726 }
00727 
00728 //Return true when it's a reference to cell from sheet.
00729 bool localReferenceAnchor( const QString &_ref )
00730 {
00731     bool isLocalRef = (_ref.find("http://") != 0 &&
00732                        _ref.find("mailto:") != 0 &&
00733                        _ref.find("ftp://") != 0  &&
00734                        _ref.find("file:") != 0 );
00735     return isLocalRef;
00736 }
KDE Logo
This file is part of the documentation for kspread Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:43:26 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003