• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Plasma

desktoptoolbox.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2007 by Aaron Seigo <aseigo@kde.org>
00003  *   Copyright 2008 by Marco Martin <notmart@gmail.com>
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU Library General Public License as
00007  *   published by the Free Software Foundation; either version 2, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program 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
00013  *   GNU General Public License for more details
00014  *
00015  *   You should have received a copy of the GNU Library General Public
00016  *   License along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.,
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include "desktoptoolbox_p.h"
00022 
00023 #include <QGraphicsSceneHoverEvent>
00024 #include <QPainter>
00025 #include <QRadialGradient>
00026 #include <QGraphicsView>
00027 #include <QAction>
00028 
00029 #include <kcolorscheme.h>
00030 #include <kdebug.h>
00031 
00032 #include <plasma/theme.h>
00033 #include <plasma/paintutils.h>
00034 #include <plasma/framesvg.h>
00035 
00036 #include <plasma/applet.h>
00037 #include <plasma/containment.h>
00038 #include <plasma/widgets/iconwidget.h>
00039 
00040 namespace Plasma
00041 {
00042 
00043 class EmptyGraphicsItem : public QGraphicsItem
00044 {
00045     public:
00046         EmptyGraphicsItem(QGraphicsItem *parent)
00047             : QGraphicsItem(parent),
00048               m_toolbar(false)
00049         {
00050             setAcceptsHoverEvents(true);
00051             m_background = new Plasma::FrameSvg();
00052             m_toolbarBackground = new Plasma::FrameSvg();
00053 
00054             m_toolbarBackground->setImagePath("widgets/background");
00055             m_background->setImagePath("widgets/translucentbackground");
00056 
00057             m_toolbarBackground->setEnabledBorders(FrameSvg::LeftBorder|FrameSvg::RightBorder|FrameSvg::BottomBorder);
00058             m_background->setEnabledBorders(FrameSvg::AllBorders);
00059         }
00060 
00061         ~EmptyGraphicsItem()
00062         {
00063             delete m_background;
00064             delete m_toolbarBackground;
00065         }
00066 
00067         QRectF boundingRect() const
00068         {
00069             return QRectF(QPointF(0, 0), m_rect.size());
00070         }
00071 
00072         QRectF rect() const
00073         {
00074             return m_rect;
00075         }
00076 
00077         void setIsToolbar(bool toolbar)
00078         {
00079             m_toolbar = toolbar;
00080         }
00081 
00082         bool isToolbar() const
00083         {
00084             return m_toolbar;
00085         }
00086 
00087         void getContentsMargins(qreal &left, qreal &top, qreal &right, qreal &bottom)
00088         {
00089             if (m_toolbar) {
00090                 m_toolbarBackground->getMargins(left, top, right, bottom);
00091             } else {
00092                 m_background->getMargins(left, top, right, bottom);
00093             }
00094         }
00095 
00096         QRectF contentsRect() const
00097         {
00098             qreal left, top, right, bottom;
00099 
00100             if (m_toolbar) {
00101                 m_toolbarBackground->getMargins(left, top, right, bottom);
00102             } else {
00103                 m_background->getMargins(left, top, right, bottom);
00104             }
00105             return m_rect.adjusted(left, top, -right, -bottom);
00106         }
00107 
00108         void setRect(const QRectF &rect)
00109         {
00110             //kDebug() << "setting rect to" << rect;
00111             prepareGeometryChange();
00112             m_rect = rect;
00113             setPos(m_rect.topLeft());
00114             if (m_toolbar) {
00115                 m_toolbarBackground->resizeFrame(m_rect.size());
00116             } else {
00117                 m_background->resizeFrame(m_rect.size());
00118             }
00119         }
00120 
00121         void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
00122         {
00123             if (m_toolbar) {
00124                 m_toolbarBackground->paintFrame(p);
00125             } else {
00126                 m_background->paintFrame(p);
00127             }
00128         }
00129 
00130     private:
00131         bool m_toolbar;
00132         QRectF m_rect;
00133         Plasma::FrameSvg *m_toolbarBackground;
00134         Plasma::FrameSvg *m_background;
00135 };
00136 
00137 // used with QGrahphicsItem::setData
00138 static const int ToolName = 7001;
00139 
00140 class DesktopToolBoxPrivate
00141 {
00142 public:
00143     DesktopToolBoxPrivate(DesktopToolBox *toolbox)
00144       : q(toolbox),
00145         containment(0),
00146         icon("plasma"),
00147         toolBacker(0),
00148         animCircleId(0),
00149         animHighlightId(0),
00150         animCircleFrame(0),
00151         animHighlightFrame(0),
00152         hovering(0)
00153     {}
00154 
00155 
00156     DesktopToolBox *q;
00157     Plasma::FrameSvg *background;
00158     Containment *containment;
00159     KIcon icon;
00160     EmptyGraphicsItem *toolBacker;
00161     int animCircleId;
00162     int animHighlightId;
00163     qreal animCircleFrame;
00164     qreal animHighlightFrame;
00165     QRect shapeRect;
00166     QColor fgColor;
00167     QColor bgColor;
00168     bool hovering : 1;
00169 };
00170 
00171 DesktopToolBox::DesktopToolBox(Containment *parent)
00172     : ToolBox(parent),
00173       d(new DesktopToolBoxPrivate(this))
00174 {
00175     d->containment = parent;
00176     setZValue(10000000);
00177     setFlag(ItemClipsToShape, true);
00178     setFlag(ItemClipsChildrenToShape, false);
00179     setFlag(ItemIgnoresTransformations, true);
00180     setIsMovable(true);
00181     assignColors();
00182 
00183     d->background = new Plasma::FrameSvg();
00184     d->background->setImagePath("widgets/translucentbackground");
00185 
00186     connect(Plasma::Animator::self(), SIGNAL(movementFinished(QGraphicsItem*)),
00187             this, SLOT(toolMoved(QGraphicsItem*)));
00188     connect(this, SIGNAL(toggled()), this, SLOT(toggle()));
00189     connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()),
00190             this, SLOT(assignColors()));
00191 }
00192 
00193 DesktopToolBox::~DesktopToolBox()
00194 {
00195     delete d;
00196 }
00197 
00198 QRectF DesktopToolBox::boundingRect() const
00199 {
00200     return QRectF(0, 0, size(), size());
00201 }
00202 
00203 void DesktopToolBox::assignColors()
00204 {
00205     d->bgColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
00206     d->fgColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00207 }
00208 
00209 void DesktopToolBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00210 {
00211     Q_UNUSED(option)
00212     Q_UNUSED(widget)
00213 
00214     if (isToolbar()){
00215         return;
00216     }
00217 
00218     QPainterPath p = shape();
00219 
00220     QPoint iconPos;
00221     QPointF gradientCenter;
00222     const QRectF rect = boundingRect();
00223     const QSize icons = iconSize();
00224     bool atCorner;
00225 
00226     switch (corner()) {
00227     case TopRight:
00228         iconPos = QPoint((int)rect.right() - icons.width() + 2, 2);
00229         gradientCenter = rect.topRight();
00230         atCorner = true;
00231         break;
00232     case Top:
00233         iconPos = QPoint(rect.center().x() - icons.width() / 2, 2);
00234         gradientCenter = QPoint(rect.center().x(), rect.y());
00235         atCorner = false;
00236         d->background->setEnabledBorders(FrameSvg::BottomBorder|FrameSvg::LeftBorder|FrameSvg::RightBorder);
00237         break;
00238     case TopLeft:
00239         iconPos = QPoint(2, 2);
00240         gradientCenter = rect.topLeft();
00241         atCorner = true;
00242         break;
00243     case Left:
00244         iconPos = QPoint(2, rect.center().y() - icons.height() / 2);
00245         gradientCenter = QPointF(rect.left(), rect.center().y());
00246         atCorner = false;
00247         d->background->setEnabledBorders(FrameSvg::BottomBorder|FrameSvg::TopBorder|FrameSvg::RightBorder);
00248         break;
00249     case Right:
00250         iconPos = QPoint((int)rect.right() - icons.width() + 2,
00251                          rect.center().y() - icons.height() / 2);
00252         gradientCenter = QPointF(rect.right(), rect.center().y());
00253         atCorner = false;
00254         d->background->setEnabledBorders(FrameSvg::BottomBorder|FrameSvg::TopBorder|FrameSvg::LeftBorder);
00255         break;
00256     case BottomLeft:
00257         iconPos = QPoint(2, rect.bottom() - icons.height() - 2);
00258         gradientCenter = rect.bottomLeft();
00259         atCorner = true;
00260         break;
00261     case Bottom:
00262         iconPos = QPoint(rect.center().x() - icons.width() / 2,
00263                          rect.bottom() - icons.height() - 2);
00264         gradientCenter = QPointF(rect.center().x(), rect.bottom());
00265         atCorner = false;
00266         d->background->setEnabledBorders(FrameSvg::TopBorder|FrameSvg::LeftBorder|FrameSvg::RightBorder);
00267         break;
00268     case BottomRight:
00269     default:
00270         iconPos = QPoint((int)rect.right() - icons.width() + 2,
00271                          (int)rect.bottom() - icons.height() - 2);
00272         gradientCenter = rect.bottomRight();
00273         atCorner = true;
00274         break;
00275     }
00276 
00277     if (atCorner) {
00278         d->bgColor.setAlpha(64);
00279         d->fgColor.setAlpha(64);
00280         QRadialGradient gradient(gradientCenter, size() + d->animCircleFrame);
00281         gradient.setFocalPoint(gradientCenter);
00282         gradient.setColorAt(0, d->bgColor);
00283         gradient.setColorAt(.87, d->bgColor);
00284         gradient.setColorAt(.97, d->fgColor);
00285         d->fgColor.setAlpha(0);
00286         gradient.setColorAt(1, d->fgColor);
00287         painter->save();
00288         painter->setPen(Qt::NoPen);
00289         painter->setRenderHint(QPainter::Antialiasing, true);
00290         painter->setBrush(gradient);
00291         painter->drawPath(p);
00292         painter->restore();
00293     } else {
00294         d->background->resizeFrame(rect.size());
00295         d->background->paintFrame(painter);
00296     }
00297 
00298     const qreal progress = d->animHighlightFrame;
00299 
00300     if (qFuzzyCompare(qreal(1.0), progress)) {
00301         d->icon.paint(painter, QRect(iconPos, iconSize()));
00302     } else if (qFuzzyCompare(qreal(1.0), 1 + progress)) {
00303         d->icon.paint(painter, QRect(iconPos, iconSize()),
00304                       Qt::AlignCenter, QIcon::Disabled, QIcon::Off);
00305     } else {
00306         QPixmap disabled = d->icon.pixmap(iconSize(), QIcon::Disabled, QIcon::Off);
00307         QPixmap enabled = d->icon.pixmap(iconSize());
00308         QPixmap result = PaintUtils::transition(
00309             d->icon.pixmap(iconSize(), QIcon::Disabled, QIcon::Off),
00310             d->icon.pixmap(iconSize()), progress);
00311         painter->drawPixmap(QRect(iconPos, iconSize()), result);
00312     }
00313 }
00314 
00315 QPainterPath DesktopToolBox::shape() const
00316 {
00317     const QRectF rect = boundingRect();
00318     const int w = rect.width();
00319     const int h = rect.height();
00320 
00321     QPainterPath path;
00322     switch (corner()) {
00323     case BottomLeft:
00324         path.moveTo(rect.bottomLeft());
00325         path.arcTo(QRectF(rect.left() - w, rect.top(), w * 2, h * 2), 0, 90);
00326         break;
00327     case BottomRight:
00328         path.moveTo(rect.bottomRight());
00329         path.arcTo(QRectF(rect.left(), rect.top(), w * 2, h * 2), 90, 90);
00330         break;
00331     case TopRight:
00332         path.moveTo(rect.topRight());
00333         path.arcTo(QRectF(rect.left(), rect.top() - h, w * 2, h * 2), 180, 90);
00334         break;
00335     case TopLeft:
00336         path.arcTo(QRectF(rect.left() - w, rect.top() - h, w * 2, h * 2), 270, 90);
00337         break;
00338     default:
00339         path.addRect(rect);
00340         break;
00341     }
00342 
00343     return path;
00344 }
00345 
00346 void DesktopToolBox::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00347 {
00348     if (showing() || d->hovering) {
00349         QGraphicsItem::hoverEnterEvent(event);
00350         return;
00351     }
00352     Plasma::Animator *animdriver = Plasma::Animator::self();
00353     if (d->animHighlightId) {
00354         animdriver->stopCustomAnimation(d->animHighlightId);
00355     }
00356     d->hovering = true;
00357     d->animHighlightId =
00358         animdriver->customAnimation(
00359             10, 240, Plasma::Animator::EaseInCurve, this, "animateHighlight");
00360 
00361     QGraphicsItem::hoverEnterEvent(event);
00362 }
00363 
00364 void DesktopToolBox::showToolBox()
00365 {
00366     if (showing() && !isToolbar()) {
00367         return;
00368     }
00369 
00370     // put tools 5px from icon edge
00371     const int iconWidth = 32;
00372     int x;
00373     int y;
00374     switch (corner()) {
00375     case TopRight:
00376         x = (int)boundingRect().right() - iconWidth - 5;
00377         y = (int)boundingRect().top() + 10;
00378         break;
00379     case Top:
00380         x = (int)boundingRect().center().x() - iconWidth;
00381         y = (int)boundingRect().top() + iconWidth + 10;
00382         break;
00383     case TopLeft:
00384         x = (int)boundingRect().left() + iconWidth + 5;
00385         y = (int)boundingRect().top() + 10;
00386         break;
00387     case Left:
00388         x = (int)boundingRect().left() + iconWidth + 5;
00389         y = (int)boundingRect().center().y() - iconWidth;
00390         break;
00391     case Right:
00392         x = (int)boundingRect().right() - iconWidth - 5;
00393         y = (int)boundingRect().center().y() - iconWidth;
00394         break;
00395     case BottomLeft:
00396         x = (int)boundingRect().left() + iconWidth + 5;
00397         y = (int)boundingRect().bottom() - 5;
00398         break;
00399     case Bottom:
00400         x = (int)boundingRect().center().x() - iconWidth;
00401         y = (int)boundingRect().bottom() - iconWidth - 5;
00402         break;
00403     case BottomRight:
00404     default:
00405         x = (int)boundingRect().right() - iconWidth - 5;
00406         y = (int)boundingRect().bottom() - iconWidth - 5;
00407         break;
00408     }
00409 
00410     int startY = y;
00411 
00412     // find our theoretical X and Y end coordinates
00413 
00414     int maxWidth = 0;
00415     int maxHeight = 0;
00416     int totalWidth = 0;
00417 
00418     foreach (QGraphicsItem *tool, QGraphicsItem::children()) {
00419         if (tool == d->toolBacker) {
00420             continue;
00421         }
00422 
00423         Plasma::IconWidget *icon = qgraphicsitem_cast<Plasma::IconWidget *>(tool);
00424         if (icon) {
00425             if (viewTransform().m11() != Plasma::scalingFactor(Plasma::OverviewZoom) &&
00426                 (viewTransform().m11() == Plasma::scalingFactor(Plasma::DesktopZoom) ||
00427                  icon->action() == d->containment->action("add sibling containment") ||
00428                  icon->action() == d->containment->action("add widgets"))) {
00429                 icon->setText(icon->action()->text());
00430                 icon->resize(icon->sizeFromIconSize(22));
00431             } else {
00432                 icon->setText(QString());
00433                 icon->resize(icon->sizeFromIconSize(22));
00434             }
00435         }
00436 
00437         if (tool->isEnabled()) {
00438             tool->show();
00439             //kDebug() << tool << "is enabled";
00440             y += 5;
00441             QSize toolSize = tool->boundingRect().size().toSize();
00442             totalWidth += toolSize.width() + 5;
00443 
00444             maxWidth = qMax(toolSize.width(), maxWidth);
00445             maxHeight = qMax(toolSize.height(), maxHeight);
00446             y += static_cast<int>(tool->boundingRect().height());
00447         }
00448     }
00449 
00450     if (corner() == TopRight || corner() == Right || corner() == BottomRight) {
00451         x -= maxWidth;
00452     }
00453 
00454     y += 5;
00455     // the rect the tools back should have
00456     QRectF backerRect = QRectF(QPointF(x, startY), QSizeF(maxWidth + 10, y - startY));
00457 
00458     if (!d->toolBacker) {
00459         d->toolBacker = new EmptyGraphicsItem(this);
00460         d->toolBacker->setZValue(zValue() + 1);
00461     }
00462 
00463     d->toolBacker->setIsToolbar(isToolbar());
00464 
00465     if (isToolbar()) {
00466         QPointF topRight;
00467 
00468         //could that cast ever fail?
00469         if (d->containment) {
00470             topRight = viewTransform().map(mapFromParent(d->containment->boundingRect().bottomRight()));
00471         } else {
00472             topRight = boundingRect().topRight();
00473         }
00474 
00475         qreal left, top, right, bottom;
00476         d->toolBacker->getContentsMargins(left, top, right, bottom);
00477         x -= left;
00478 
00479         backerRect.setSize(QSize(totalWidth+left+right, maxHeight+top+bottom));
00480         backerRect.moveTopRight(topRight);
00481     } else {
00482         //kDebug() << "starting at" <<  x << startY;
00483 
00484         // now check that is actually fits within the parent's boundaries
00485         backerRect = mapToParent(backerRect).boundingRect();
00486         QSizeF parentSize = parentWidget()->size();
00487         if (backerRect.x() < 5) {
00488             backerRect.moveLeft(5);
00489         } else if (backerRect.right() > parentSize.width() - 5) {
00490             backerRect.moveRight(parentSize.width() - 5);
00491         }
00492 
00493         if (backerRect.y() < 5) {
00494             backerRect.moveTop(5);
00495         } else if (backerRect.bottom() > parentSize.height() - 5) {
00496             backerRect.moveBottom(parentSize.height() - 5);
00497         }
00498 
00499         // re-map our starting points back to our coordinate system
00500         backerRect = mapFromParent(backerRect).boundingRect();
00501     }
00502     x = backerRect.x() + 5;
00503     y = backerRect.y();
00504 
00505     // now move the items
00506     Plasma::Animator *animdriver = Plasma::Animator::self();
00507     foreach (QGraphicsItem *tool, QGraphicsItem::children()) {
00508         if (tool == d->toolBacker) {
00509             continue;
00510         }
00511 
00512         if (tool->isEnabled()) {
00513             if (isToolbar()) {
00514                 //kDebug() << tool << "is enabled";
00515                 x += 5;
00516                 //kDebug() << "let's show and move" << tool << tool->boundingRect();
00517                 tool->show();
00518                 tool->setPos(QPoint(x, y));
00519                 x += static_cast<int>(tool->boundingRect().width());
00520             } else {
00521                 //kDebug() << tool << "is enabled";
00522                 y += 5;
00523                 //kDebug() << "let's show and move" << tool << tool->boundingRect();
00524                 tool->show();
00525                 animdriver->moveItem(tool, Plasma::Animator::SlideInMovement, QPoint(x, y));
00526                 //x += 0;
00527                 y += static_cast<int>(tool->boundingRect().height());
00528             }
00529         } else if (tool->isVisible()) {
00530             // disabled, but visible, so hide it!
00531             const int height = static_cast<int>(tool->boundingRect().height());
00532             if (isToolbar()) {
00533                 tool->hide();
00534             } else {
00535                 animdriver->moveItem(tool, Plasma::Animator::SlideOutMovement, toolPosition(height));
00536             }
00537         }
00538     }
00539 
00540 
00541     d->toolBacker->setRect(backerRect);
00542     d->toolBacker->show();
00543 
00544     if (d->animCircleId) {
00545         animdriver->stopCustomAnimation(d->animCircleId);
00546     }
00547 
00548     setShowing(true);
00549 }
00550 
00551 void DesktopToolBox::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00552 {
00553     //kDebug() << event->pos() << event->scenePos()
00554     //         << d->toolBacker->rect().contains(event->scenePos().toPoint());
00555     if (!d->hovering || isToolbar()) {
00556         QGraphicsItem::hoverLeaveEvent(event);
00557         return;
00558     }
00559 
00560     hideToolBox();
00561     Plasma::Animator *animdriver = Plasma::Animator::self();
00562     if (d->animHighlightId) {
00563         animdriver->stopCustomAnimation(d->animHighlightId);
00564     }
00565     d->hovering = false;
00566     d->animHighlightId =
00567         animdriver->customAnimation(
00568             10, 240, Plasma::Animator::EaseOutCurve, this, "animateHighlight");
00569 
00570     QGraphicsItem::hoverLeaveEvent(event);
00571 }
00572 
00573 void DesktopToolBox::hideToolBox()
00574 {
00575     if (!showing()) {
00576         return;
00577     }
00578 
00579     Plasma::Animator *animdriver = Plasma::Animator::self();
00580     foreach (QGraphicsItem *tool, QGraphicsItem::children()) {
00581         if (tool == d->toolBacker) {
00582             continue;
00583         }
00584 
00585         const int height = static_cast<int>(tool->boundingRect().height());
00586         if (isToolbar()) {
00587             tool->setPos(toolPosition(height));
00588             tool->hide();
00589         } else {
00590             animdriver->moveItem(tool, Plasma::Animator::SlideOutMovement, toolPosition(height));
00591         }
00592     }
00593 
00594     if (d->animCircleId) {
00595         animdriver->stopCustomAnimation(d->animCircleId);
00596     }
00597 
00598     setShowing(false);
00599 
00600     if (d->toolBacker) {
00601         d->toolBacker->hide();
00602     }
00603 }
00604 
00605 void DesktopToolBox::animateHighlight(qreal progress)
00606 {
00607     if (d->hovering) {
00608         d->animHighlightFrame = progress;
00609     } else {
00610         d->animHighlightFrame = 1.0 - progress;
00611     }
00612 
00613     if (progress >= 1) {
00614         d->animHighlightId = 0;
00615     }
00616 
00617     update();
00618 }
00619 
00620 void DesktopToolBox::toolMoved(QGraphicsItem *item)
00621 {
00622     //kDebug() << "geometry is now " << static_cast<Plasma::Widget*>(item)->geometry();
00623     if (!showing() &&
00624         QGraphicsItem::children().indexOf(static_cast<Plasma::Applet*>(item)) != -1) {
00625         item->hide();
00626     }
00627 }
00628 
00629 void DesktopToolBox::toggle()
00630 {
00631     if (isToolbar()) {
00632         return;
00633     }
00634 
00635     if (showing()) {
00636         hideToolBox();
00637     } else {
00638         showToolBox();
00639     }
00640 }
00641 
00642 } // plasma namespace
00643 
00644 #include "desktoptoolbox_p.moc"

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal