| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kiconeffect.cpp

    00001 /* vi: ts=8 sts=4 sw=4
    00002  * $Id: kiconeffect.cpp,v 1.44 2002/11/21 19:18:51 pfeiffer Exp $
    00003  *
    00004  * This file is part of the KDE project, module kdecore.
    00005  * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
    00006  * with minor additions and based on ideas from
    00007  * Torsten Rahn <torsten@kde.org>
    00008  *
    00009  * This is free software; it comes under the GNU Library General
    00010  * Public License, version 2. See the file "COPYING.LIB" for the
    00011  * exact licensing terms.
    00012  */
    00013
    00014 #include <config.h>
    00015 #include <unistd.h>
    00016 #include <math.h>
    00017
    00018 #include <qstring.h>
    00019 #include <qstringlist.h>
    00020 #include <qbitmap.h>
    00021 #include <qpixmap.h>
    00022 #include <qimage.h>
    00023 #include <qcolor.h>
    00024 #include <qwidget.h>
    00025 #include <qpainter.h>
    00026 #include <qpen.h>
    00027
    00028 #include <kdebug.h>
    00029 #include <kglobal.h>
    00030 #include <kconfig.h>
    00031 #include <kglobalsettings.h>
    00032 #include <kicontheme.h>
    00033 #include "kiconeffect.h"
    00034
    00035 extern bool qt_use_xrender;
    00036 extern bool qt_has_xft;
    00037
    00038 class KIconEffectPrivate
    00039 {
    00040 public:
    00041         QString mKey[6][3];
    00042 };
    00043
    00044 KIconEffect::KIconEffect()
    00045 {
    00046     d = new KIconEffectPrivate;
    00047     init();
    00048 }
    00049
    00050 KIconEffect::~KIconEffect()
    00051 {
    00052     delete d;
    00053 }
    00054
    00055 void KIconEffect::init()
    00056 {
    00057     KConfig *config = KGlobal::config();
    00058
    00059     int i, j, effect=-1;
    00060     QStringList groups;
    00061     groups += "Desktop";
    00062     groups += "Toolbar";
    00063     groups += "MainToolbar";
    00064     groups += "Small";
    00065     groups += "Panel";
    00066
    00067     QStringList states;
    00068     states += "Default";
    00069     states += "Active";
    00070     states += "Disabled";
    00071
    00072     QStringList::ConstIterator it, it2;
    00073     QString _togray("togray");
    00074     QString _colorize("colorize");
    00075     QString _desaturate("desaturate");
    00076     QString _togamma("togamma");
    00077     QString _none("none");
    00078
    00079     KConfigGroupSaver cs(config, "default");
    00080
    00081     for (it=groups.begin(), i=0; it!=groups.end(); it++, i++)
    00082     {
    00083         // Default effects
    00084         mEffect[i][0] = NoEffect;
    00085         mEffect[i][1] =  ((i==0)||(i==4)) ? ToGamma : NoEffect;
    00086         mEffect[i][2] = ToGray;
    00087
    00088         mTrans[i][0] = false;
    00089         mTrans[i][1] = false;
    00090         mTrans[i][2] = true;
    00091         mValue[i][0] = 1.0;
    00092         mValue[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0;
    00093         mValue[i][2] = 1.0;
    00094         mColor[i][0] = QColor(144,128,248);
    00095         mColor[i][1] = QColor(169,156,255);
    00096         mColor[i][2] = QColor(34,202,0);
    00097
    00098         config->setGroup(*it + "Icons");
    00099         for (it2=states.begin(), j=0; it2!=states.end(); it2++, j++)
    00100         {
    00101             QString tmp = config->readEntry(*it2 + "Effect");
    00102             if (tmp == _togray)
    00103                 effect = ToGray;
    00104             else if (tmp == _colorize)
    00105                 effect = Colorize;
    00106             else if (tmp == _desaturate)
    00107                 effect = DeSaturate;
    00108             else if (tmp == _togamma)
    00109                 effect = ToGamma;
    00110             else if (tmp == _none)
    00111                 effect = NoEffect;
    00112             else
    00113                 continue;
    00114             if(effect != -1)
    00115                 mEffect[i][j] = effect;
    00116             mValue[i][j] = config->readDoubleNumEntry(*it2 + "Value");
    00117             mColor[i][j] = config->readColorEntry(*it2 + "Color");
    00118             mTrans[i][j] = config->readBoolEntry(*it2 + "SemiTransparent");
    00119
    00120         }
    00121     }
    00122 }
    00123
    00124 bool KIconEffect::hasEffect(int group, int state) const
    00125 {
    00126     return mEffect[group][state] != NoEffect;
    00127 }
    00128
    00129 QString KIconEffect::fingerprint(int group, int state) const
    00130 {
    00131     if ( group >= KIcon::LastGroup ) return "";
    00132     QString cached = d->mKey[group][state];
    00133     if (cached.isEmpty())
    00134     {
    00135         QString tmp;
    00136         cached = tmp.setNum(mEffect[group][state]);
    00137         cached += ':';
    00138         cached += tmp.setNum(mValue[group][state]);
    00139         cached += ':';
    00140         cached += mTrans[group][state] ? QString::fromLatin1("trans")
    00141             : QString::fromLatin1("notrans");
    00142         if (mEffect[group][state] == Colorize)
    00143         {
    00144             cached += ':';
    00145             cached += mColor[group][state].name();
    00146         }
    00147
    00148         d->mKey[group][state] = cached;
    00149     }
    00150
    00151     return cached;
    00152 }
    00153
    00154 QImage KIconEffect::apply(QImage image, int group, int state) const
    00155 {
    00156     if (state >= KIcon::LastState)
    00157     {
    00158         kdDebug(265) << "Illegal icon state: " << state << "\n";
    00159         return image;
    00160     }
    00161     if (group >= KIcon::LastGroup)
    00162     {
    00163         kdDebug(265) << "Illegal icon group: " << group << "\n";
    00164         return image;
    00165     }
    00166     return apply(image, mEffect[group][state], mValue[group][state],
    00167             mColor[group][state], mTrans[group][state]);
    00168 }
    00169
    00170 QImage KIconEffect::apply(QImage image, int effect, float value, const QColor col, bool trans) const
    00171 {
    00172     if (effect >= LastEffect )
    00173     {
    00174         kdDebug(265) << "Illegal icon effect: " << effect << "\n";
    00175         return image;
    00176     }
    00177     if (value > 1.0)
    00178         value = 1.0;
    00179     else if (value < 0.0)
    00180         value = 0.0;
    00181     switch (effect)
    00182     {
    00183     case ToGray:
    00184         toGray(image, value);
    00185         break;
    00186     case DeSaturate:
    00187         deSaturate(image, value);
    00188         break;
    00189     case Colorize:
    00190         colorize(image, col, value);
    00191         break;
    00192     case ToGamma:
    00193         toGamma(image, value);
    00194         break;
    00195     }
    00196     if (trans == true)
    00197     {
    00198         semiTransparent(image);
    00199     }
    00200     return image;
    00201 }
    00202
    00203 QPixmap KIconEffect::apply(QPixmap pixmap, int group, int state) const
    00204 {
    00205     if (state >= KIcon::LastState)
    00206     {
    00207         kdDebug(265) << "Illegal icon state: " << state << "\n";
    00208         return pixmap;
    00209     }
    00210     if (group >= KIcon::LastGroup)
    00211     {
    00212         kdDebug(265) << "Illegal icon group: " << group << "\n";
    00213         return pixmap;
    00214     }
    00215     return apply(pixmap, mEffect[group][state], mValue[group][state],
    00216             mColor[group][state], mTrans[group][state]);
    00217 }
    00218
    00219 QPixmap KIconEffect::apply(QPixmap pixmap, int effect, float value,
    00220         const QColor col, bool trans) const
    00221 {
    00222     QPixmap result;
    00223
    00224     if (effect >= LastEffect )
    00225     {
    00226         kdDebug(265) << "Illegal icon effect: " << effect << "\n";
    00227         return result;
    00228     }
    00229
    00230     if ((trans == true) && (effect == NoEffect))
    00231     {
    00232         result = pixmap;
    00233         semiTransparent(result);
    00234     }
    00235     else if ( effect != NoEffect )
    00236     {
    00237         QImage tmpImg = pixmap.convertToImage();
    00238         tmpImg = apply(tmpImg, effect, value, col, trans);
    00239         result.convertFromImage(tmpImg);
    00240     }
    00241     else
    00242         result = pixmap;
    00243
    00244     return result;
    00245 }
    00246
    00247 // Taken from KImageEffect. We don't want to link kdecore to kdeui! As long
    00248 // as this code is not too big, it doesn't seem much of a problem to me.
    00249
    00250 void KIconEffect::toGray(QImage &img, float value)
    00251 {
    00252     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00253             : img.numColors();
    00254     unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
    00255             : (unsigned int *) img.colorTable();
    00256     int rval, gval, bval, val, alpha, i;
    00257     for (i=0; i<pixels; i++)
    00258     {
    00259         val = qGray(data[i]);
    00260         alpha = qAlpha(data[i]);
    00261         if (value < 1.0)
    00262         {
    00263             rval = static_cast<int>(value*val+(1.0-value)*qRed(data[i]));
    00264             gval = static_cast<int>(value*val+(1.0-value)*qGreen(data[i]));
    00265             bval = static_cast<int>(value*val+(1.0-value)*qBlue(data[i]));
    00266             data[i] = qRgba(rval, gval, bval, alpha);
    00267         } else
    00268             data[i] = qRgba(val, val, val, alpha);
    00269     }
    00270 }
    00271
    00272 void KIconEffect::colorize(QImage &img, const QColor &col, float value)
    00273 {
    00274     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00275             : img.numColors();
    00276     unsigned int *data = img.depth() > 8 ? (unsigned int *) img.bits()
    00277             : (unsigned int *) img.colorTable();
    00278     int rval, gval, bval, val, alpha, i;
    00279     float rcol = col.red(), gcol = col.green(), bcol = col.blue();
    00280     for (i=0; i<pixels; i++)
    00281     {
    00282         val = qGray(data[i]);
    00283         if (val < 128)
    00284         {
    00285              rval = static_cast<int>(rcol/128*val);
    00286              gval = static_cast<int>(gcol/128*val);
    00287              bval = static_cast<int>(bcol/128*val);
    00288         }
    00289         else if (val > 128)
    00290         {
    00291              rval = static_cast<int>((val-128)*(2-rcol/128)+rcol-1);
    00292              gval = static_cast<int>((val-128)*(2-gcol/128)+gcol-1);
    00293              bval = static_cast<int>((val-128)*(2-bcol/128)+bcol-1);
    00294         }
    00295         else // val == 128
    00296         {
    00297              rval = static_cast<int>(rcol);
    00298              gval = static_cast<int>(gcol);
    00299              bval = static_cast<int>(bcol);
    00300         }
    00301         if (value < 1.0)
    00302         {
    00303             rval = static_cast<int>(value*rval+(1.0 - value)*qRed(data[i]));
    00304             gval = static_cast<int>(value*gval+(1.0 - value)*qGreen(data[i]));
    00305             bval = static_cast<int>(value*bval+(1.0 - value)*qBlue(data[i]));
    00306         }
    00307
    00308         alpha = qAlpha(data[i]);
    00309         data[i] = qRgba(rval, gval, bval, alpha);
    00310     }
    00311 }
    00312
    00313 void KIconEffect::deSaturate(QImage &img, float value)
    00314 {
    00315     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00316             : img.numColors();
    00317     unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits()
    00318             : (unsigned int *) img.colorTable();
    00319     QColor color;
    00320     int h, s, v, i;
    00321     for (i=0; i<pixels; i++)
    00322     {
    00323         color.setRgb(data[i]);
    00324         color.hsv(&h, &s, &v);
    00325         color.setHsv(h, (int) (s * (1.0 - value) + 0.5), v);
    00326         data[i] = qRgba(color.red(), color.green(), color.blue(),
    00327                 qAlpha(data[i]));
    00328     }
    00329 }
    00330
    00331 void KIconEffect::toGamma(QImage &img, float value)
    00332 {
    00333     int pixels = (img.depth() > 8) ? img.width()*img.height()
    00334             : img.numColors();
    00335     unsigned int *data = (img.depth() > 8) ? (unsigned int *) img.bits()
    00336             : (unsigned int *) img.colorTable();
    00337     QColor color;
    00338     int i, rval, gval, bval;
    00339     float gamma;
    00340     gamma = 1/(2*value+0.5);
    00341
    00342     for (i=0; i<pixels; i++)
    00343     {
    00344         color.setRgb(data[i]);
    00345         color.rgb(&rval, &gval, &bval);
    00346         rval = static_cast<int>(pow(static_cast<float>(rval)/255 , gamma)*255);
    00347         gval = static_cast<int>(pow(static_cast<float>(gval)/255 , gamma)*255);
    00348         bval = static_cast<int>(pow(static_cast<float>(bval)/255 , gamma)*255);
    00349         data[i] = qRgba(rval, gval, bval, qAlpha(data[i]));
    00350     }
    00351 }
    00352
    00353 void KIconEffect::semiTransparent(QImage &img)
    00354 {
    00355     img.setAlphaBuffer(true);
    00356
    00357     int x, y;
    00358     if (img.depth() == 32)
    00359     {
    00360         int width  = img.width();
    00361         int height = img.height();
    00362
    00363         if (qt_use_xrender && qt_has_xft )
    00364           for (y=0; y<height; y++)
    00365           {
    00366 #ifdef WORDS_BIGENDIAN
    00367             uchar *line = (uchar*) img.scanLine(y);
    00368 #else
    00369             uchar *line = (uchar*) img.scanLine(y) + 3;
    00370 #endif
    00371             for (x=0; x<width; x++)
    00372             {
    00373                 *line >>= 1;
    00374                 line += 4;
    00375             }
    00376           }
    00377         else
    00378           for (y=0; y<height; y++)
    00379           {
    00380             QRgb *line = (QRgb *) img.scanLine(y);
    00381             for (x=(y%2); x<width; x+=2)
    00382                 line[x] &= 0x00ffffff;
    00383           }
    00384
    00385     } else
    00386     {
    00387         // Insert transparent pixel into the clut.
    00388         int transColor = -1;
    00389
    00390         // search for a color that is already transparent
    00391         for (x=0; x<img.numColors(); x++)
    00392         {
    00393             // try to find already transparent pixel
    00394             if (qAlpha(img.color(x)) < 127)
    00395             {
    00396                 transColor = x;
    00397                 break;
    00398             }
    00399         }
    00400
    00401
    00402         // FIXME: image must have transparency
    00403         if(transColor < 0 || transColor >= img.numColors())
    00404             return;
    00405
    00406         img.setColor(transColor, 0);
    00407         if(img.depth() == 8)
    00408         {
    00409             for (y=0; y<img.height(); y++)
    00410             {
    00411                 unsigned char *line = img.scanLine(y);
    00412                 for (x=(y%2); x<img.width(); x+=2)
    00413                     line[x] = transColor;
    00414             }
    00415         }
    00416         else
    00417         {
    00418             // SLOOW, but simple, as we would have to
    00419             // deal with endianess etc on our own here
    00420             for (y=0; y<img.height(); y++)
    00421                 for (x=(y%2); x<img.width(); x+=2)
    00422                     img.setPixel(x, y, transColor);
    00423         }
    00424     }
    00425 }
    00426
    00427 void KIconEffect::semiTransparent(QPixmap &pix)
    00428 {
    00429     if ( qt_use_xrender && qt_has_xft )
    00430     {
    00431         QImage img=pix.convertToImage();
    00432         semiTransparent(img);
    00433         pix.convertFromImage(img);
    00434         return;
    00435     }
    00436
    00437     QImage img;
    00438     if (pix.mask() != 0L)
    00439         img = pix.mask()->convertToImage();
    00440     else
    00441     {
    00442         img.create(pix.size(), 1, 2, QImage::BigEndian);
    00443         img.fill(1);
    00444     }
    00445
    00446     for (int y=0; y<img.height(); y++)
    00447     {
    00448         QRgb *line = (QRgb *) img.scanLine(y);
    00449         QRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa;
    00450         for (int x=0; x<(img.width()+31)/32; x++)
    00451             line[x] &= pattern;
    00452     }
    00453     QBitmap mask;
    00454     mask.convertFromImage(img);
    00455     pix.setMask(mask);
    00456 }
    00457
    00458 QImage KIconEffect::doublePixels(QImage src) const
    00459 {
    00460     QImage dst;
    00461     if (src.depth() == 1)
    00462     {
    00463         kdDebug(265) << "image depth 1 not supported\n";
    00464         return dst;
    00465     }
    00466
    00467     int w = src.width();
    00468     int h = src.height();
    00469     dst.create(w*2, h*2, src.depth());
    00470     dst.setAlphaBuffer(src.hasAlphaBuffer());
    00471
    00472     int x, y;
    00473     if (src.depth() == 32)
    00474     {
    00475         QRgb *l1, *l2;
    00476         for (y=0; y<h; y++)
    00477         {
    00478             l1 = (QRgb *) src.scanLine(y);
    00479             l2 = (QRgb *) dst.scanLine(y*2);
    00480             for (x=0; x<w; x++)
    00481             {
    00482                 l2[x*2] = l2[x*2+1] = l1[x];
    00483             }
    00484             memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
    00485         }
    00486     } else
    00487     {
    00488         for (x=0; x<src.numColors(); x++)
    00489             dst.setColor(x, src.color(x));
    00490
    00491         unsigned char *l1, *l2;
    00492         for (y=0; y<h; y++)
    00493         {
    00494             l1 = src.scanLine(y);
    00495             l2 = dst.scanLine(y*2);
    00496             for (x=0; x<w; x++)
    00497             {
    00498                 l2[x*2] = l1[x];
    00499                 l2[x*2+1] = l1[x];
    00500             }
    00501             memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
    00502         }
    00503     }
    00504     return dst;
    00505 }
    00506
    00507 void KIconEffect::overlay(QImage &src, QImage &overlay)
    00508 {
    00509     if (src.depth() != overlay.depth())
    00510     {
    00511         kdDebug(265) << "Image depth src != overlay!\n";
    00512         return;
    00513     }
    00514     if (src.size() != overlay.size())
    00515     {
    00516         kdDebug(265) << "Image size src != overlay\n";
    00517         return;
    00518     }
    00519     if (!overlay.hasAlphaBuffer())
    00520     {
    00521         kdDebug(265) << "Overlay doesn't have alpha buffer!\n";
    00522         return;
    00523     }
    00524
    00525     int i, j;
    00526
    00527     // We don't do 1 bpp
    00528
    00529     if (src.depth() == 1)
    00530     {
    00531         kdDebug(265) << "1bpp not supported!\n";
    00532         return;
    00533     }
    00534
    00535     // Overlay at 8 bpp doesn't use alpha blending
    00536
    00537     if (src.depth() == 8)
    00538     {
    00539         if (src.numColors() + overlay.numColors() > 255)
    00540         {
    00541             kdDebug(265) << "Too many colors in src + overlay!\n";
    00542             return;
    00543         }
    00544
    00545         // Find transparent pixel in overlay
    00546         int trans;
    00547         for (trans=0; trans<overlay.numColors(); trans++)
    00548         {
    00549             if (qAlpha(overlay.color(trans)) == 0)
    00550             {
    00551                 kdDebug(265) << "transparent pixel found at " << trans << "\n";
    00552                 break;
    00553             }
    00554         }
    00555         if (trans == overlay.numColors())
    00556         {
    00557             kdDebug(265) << "transparent pixel not found!\n";
    00558             return;
    00559         }
    00560
    00561         // Merge color tables
    00562         int nc = src.numColors();
    00563         src.setNumColors(nc + overlay.numColors());
    00564         for (i=0; i<overlay.numColors(); i++)
    00565         {
    00566             src.setColor(nc+i, overlay.color(i));
    00567         }
    00568
    00569         // Overwrite nontransparent pixels.
    00570         unsigned char *oline, *sline;
    00571         for (i=0; i<src.height(); i++)
    00572         {
    00573             oline = overlay.scanLine(i);
    00574             sline = src.scanLine(i);
    00575             for (j=0; j<src.width(); j++)
    00576             {
    00577                 if (oline[j] != trans)
    00578                     sline[j] = oline[j]+nc;
    00579             }
    00580         }
    00581     }
    00582
    00583     // Overlay at 32 bpp does use alpha blending
    00584
    00585     if (src.depth() == 32)
    00586     {
    00587         QRgb *oline, *sline;
    00588         int r1, g1, b1, a1;
    00589         int r2, g2, b2, a2;
    00590
    00591         for (i=0; i<src.height(); i++)
    00592         {
    00593             oline = (QRgb *) overlay.scanLine(i);
    00594             sline = (QRgb *) src.scanLine(i);
    00595
    00596             for (j=0; j<src.width(); j++)
    00597             {
    00598                 r1 = qRed(oline[j]);
    00599                 g1 = qGreen(oline[j]);
    00600                 b1 = qBlue(oline[j]);
    00601                 a1 = qAlpha(oline[j]);
    00602
    00603                 r2 = qRed(sline[j]);
    00604                 g2 = qGreen(sline[j]);
    00605                 b2 = qBlue(sline[j]);
    00606                 a2 = qAlpha(sline[j]);
    00607
    00608                 r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
    00609                 g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
    00610                 b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
    00611                 a2 = QMAX(a1, a2);
    00612
    00613                 sline[j] = qRgba(r2, g2, b2, a2);
    00614             }
    00615         }
    00616     }
    00617
    00618     return;
    00619 }
    00620
    00621     void
    00622 KIconEffect::visualActivate(QWidget * widget, QRect rect)
    00623 {
    00624     if (!KGlobalSettings::visualActivate())
    00625         return;
    00626
    00627     uint actSpeed = KGlobalSettings::visualActivateSpeed();
    00628
    00629     uint actCount = QMIN(rect.width(), rect.height()) / 2;
    00630
    00631     // Clip actCount to range 1..10.
    00632
    00633     if (actCount < 1)
    00634         actCount = 1;
    00635
    00636     else if (actCount > 10)
    00637         actCount = 10;
    00638
    00639     // Clip actSpeed to range 1..100.
    00640
    00641     if (actSpeed < 1)
    00642         actSpeed = 1;
    00643
    00644     else if (actSpeed > 100)
    00645         actSpeed = 100;
    00646
    00647     // actSpeed needs to be converted to actDelay.
    00648     // actDelay is inversely proportional to actSpeed and needs to be
    00649     // divided up into actCount portions.
    00650     // We also convert the us value to ms.
    00651
    00652     unsigned int actDelay = (1000 * (100 - actSpeed)) / actCount;
    00653
    00654     //kdDebug() << "actCount=" << actCount << " actDelay=" << actDelay << endl;
    00655
    00656     QPoint c = rect.center();
    00657
    00658     QPainter p(widget);
    00659
    00660     // Use NotROP to avoid having to repaint the pixmap each time.
    00661     p.setPen(QPen(Qt::black, 2, Qt::DotLine));
    00662     p.setRasterOp(Qt::NotROP);
    00663
    00664     // The spacing between the rects we draw.
    00665     // Use the minimum of width and height to avoid painting outside the
    00666     // pixmap area.
    00667     //unsigned int delta(QMIN(rect.width() / actCount, rect.height() / actCount));
    00668
    00669     // Support for rectangles by David
    00670     unsigned int deltaX = rect.width() / actCount;
    00671     unsigned int deltaY = rect.height() / actCount;
    00672
    00673     for (unsigned int i = 1; i < actCount; i++) {
    00674
    00675         int w = i * deltaX;
    00676         int h = i * deltaY;
    00677
    00678         rect.setRect(c.x() - w / 2, c.y() - h / 2, w, h);
    00679
    00680         p.drawRect(rect);
    00681         p.flush();
    00682
    00683         usleep(actDelay);
    00684
    00685         p.drawRect(rect);
    00686     }
    00687 }
    00688

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:32 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001