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

kdgantt

kdganttitemdelegate.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2001-2006 Klarälvdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Gantt library.
00005  **
00006  ** This file may be used under the terms of the GNU General Public
00007  ** License versions 2.0 or 3.0 as published by the Free Software
00008  ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
00009  ** included in the packaging of this file.  Alternatively you may (at
00010  ** your option) use any later version of the GNU General Public
00011  ** License if such license has been publicly approved by
00012  ** Klarälvdalens Datakonsult AB (or its successors, if any).
00013  ** 
00014  ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
00015  ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
00016  ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
00017  ** not expressly granted herein.
00018  ** 
00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021  **
00022  **********************************************************************/
00023 #include "kdganttitemdelegate_p.h"
00024 #include "kdganttglobal.h"
00025 #include "kdganttstyleoptionganttitem.h"
00026 #include "kdganttconstraint.h"
00027 
00028 #include <QPainter>
00029 #include <QPainterPath>
00030 #include <QPen>
00031 #include <QModelIndex>
00032 #include <QAbstractItemModel>
00033 #include <QApplication>
00034 
00035 #ifndef QT_NO_DEBUG_STREAM
00036 
00037 #define PRINT_INTERACTIONSTATE(x) \
00038     case x: dbg << #x; break;
00039 
00040 
00041 QDebug operator<<( QDebug dbg, KDGantt::ItemDelegate::InteractionState state )
00042 {
00043     switch( state ) {
00044         PRINT_INTERACTIONSTATE( KDGantt::ItemDelegate::State_None );
00045         PRINT_INTERACTIONSTATE( KDGantt::ItemDelegate::State_Move );
00046         PRINT_INTERACTIONSTATE( KDGantt::ItemDelegate::State_ExtendLeft );
00047         PRINT_INTERACTIONSTATE( KDGantt::ItemDelegate::State_ExtendRight );
00048     default:
00049         break;
00050     }
00051     return dbg;
00052 }
00053 
00054 #undef PRINT_INTERACTIONSTATE
00055 
00056 #endif /* QT_NO_DEBUG_STREAM */
00057 
00058 using namespace KDGantt;
00059 
00073 ItemDelegate::Private::Private()
00074 {
00075     // Brushes
00076     QLinearGradient taskgrad( 0., 0., 0., QApplication::fontMetrics().height() );
00077     taskgrad.setColorAt( 0., Qt::green );
00078     taskgrad.setColorAt( 1., Qt::darkGreen );
00079 
00080     QLinearGradient summarygrad( 0., 0., 0., QApplication::fontMetrics().height() );
00081     summarygrad.setColorAt( 0., Qt::blue );
00082     summarygrad.setColorAt( 1., Qt::darkBlue );
00083 
00084     QLinearGradient eventgrad( 0., 0., 0., QApplication::fontMetrics().height() );
00085     eventgrad.setColorAt( 0., Qt::red );
00086     eventgrad.setColorAt( 1., Qt::darkRed );
00087 
00088     defaultbrush[TypeTask]    = taskgrad;
00089     defaultbrush[TypeSummary] = summarygrad;
00090     defaultbrush[TypeEvent]   = eventgrad;
00091 
00092     // Pens
00093     QPen pen( Qt::black, 1. );
00094 
00095     defaultpen[TypeTask]    = pen;
00096     defaultpen[TypeSummary] = pen;
00097     defaultpen[TypeEvent]   = pen;
00098 }
00099 
00101 ItemDelegate::ItemDelegate( QObject* parent )
00102     : QItemDelegate( parent ), _d( new Private )
00103 {
00104 }
00105 
00107 ItemDelegate::~ItemDelegate()
00108 {
00109     delete _d;
00110 }
00111 
00112 #define d d_func()
00113 
00120 void ItemDelegate::setDefaultBrush( ItemType type, const QBrush& brush )
00121 {
00122     d->defaultbrush[type] = brush;
00123 }
00124 
00129 QBrush ItemDelegate::defaultBrush( ItemType type ) const
00130 {
00131     return d->defaultbrush[type];
00132 }
00133 
00140 void ItemDelegate::setDefaultPen( ItemType type, const QPen& pen )
00141 {
00142     d->defaultpen[type]=pen;
00143 }
00144 
00149 QPen ItemDelegate::defaultPen( ItemType type ) const
00150 {
00151     return d->defaultpen[type];
00152 }
00153 
00162 Span ItemDelegate::itemBoundingSpan( const StyleOptionGanttItem& opt,
00163                                  const QModelIndex& idx ) const
00164 {
00165     //qDebug() << "itemBoundingSpan("<<opt<<idx<<")";
00166     if ( !idx.isValid() ) return Span();
00167 
00168     QString txt = idx.model()->data( idx, Qt::DisplayRole ).toString();
00169     int typ = idx.model()->data( idx, ItemTypeRole ).toInt();
00170     QRectF itemRect = opt.itemRect;
00171 
00172 
00173     if (  typ == TypeEvent ) itemRect = QRectF( itemRect.left()-itemRect.height()/2.,
00174                                                 itemRect.top(),
00175                                                 itemRect.height(),
00176                                                 itemRect.height() );
00177 
00178     int tw = opt.fontMetrics.width( txt );
00179     tw += static_cast<int>( itemRect.height()/2. );
00180     switch ( opt.displayPosition ) {
00181     case StyleOptionGanttItem::Left:
00182         return Span( itemRect.left()-tw, itemRect.width()+tw );
00183     case StyleOptionGanttItem::Right:
00184         return Span( itemRect.left(), itemRect.width()+tw );
00185     case StyleOptionGanttItem::Center:
00186         return Span( itemRect.left(), itemRect.width() );
00187     }
00188     return Span();
00189 }
00190 
00197 ItemDelegate::InteractionState ItemDelegate::interactionStateFor( const QPointF& pos,
00198                                   const StyleOptionGanttItem& opt,
00199                                   const QModelIndex& idx ) const
00200 {
00201     if ( !idx.isValid() ) return State_None;
00202     if ( !( idx.model()->flags( idx ) & Qt::ItemIsEditable ) ) return State_None;
00203 
00204     int typ = static_cast<ItemType>( idx.model()->data( idx, ItemTypeRole ).toInt() );
00205     if ( typ == TypeNone || typ == TypeSummary ) return State_None;
00206     if ( typ == TypeEvent ) return State_Move;
00207     if ( !opt.itemRect.contains(pos) ) return State_None;
00208 
00209     qreal delta = 5.;
00210     if ( opt.itemRect.width() < 15 ) delta = 1.;
00211     if( pos.x() >= opt.itemRect.left() && pos.x() < opt.itemRect.left()+delta ) {
00212         return State_ExtendLeft;
00213     } else   if( pos.x() <= opt.itemRect.right() && pos.x() > opt.itemRect.right()-delta ) {
00214         return State_ExtendRight;
00215     } else {
00216         return State_Move;
00217     }
00218 }
00219 
00222 void ItemDelegate::paintGanttItem( QPainter* painter,
00223                                    const StyleOptionGanttItem& opt,
00224                                    const QModelIndex& idx )
00225 {
00226     if ( !idx.isValid() ) return;
00227     const ItemType typ = static_cast<ItemType>( idx.model()->data( idx, ItemTypeRole ).toInt() );
00228     const QString& txt = opt.text;
00229     QRectF itemRect = opt.itemRect;
00230     QRectF boundingRect = opt.boundingRect;
00231     boundingRect.setY( itemRect.y() );
00232     boundingRect.setHeight( itemRect.height() );
00233     //qDebug() << "itemRect="<<itemRect<<", boundingRect="<<boundingRect;
00234 
00235     painter->save();
00236 
00237     QPen pen = defaultPen( typ );
00238     if ( opt.state & QStyle::State_Selected ) pen.setWidth( 2*pen.width() );
00239     painter->setPen( pen );
00240     painter->setBrush( defaultBrush( typ ) );
00241 
00242     qreal pw = painter->pen().width()/2.;
00243     switch( typ ) {
00244     case TypeTask:
00245         if ( itemRect.isValid() ) {
00246             // TODO
00247             qreal pw = painter->pen().width()/2.;
00248             pw-=1;
00249             QRectF r = itemRect;
00250             r.translate( 0., r.height()/6. );
00251             r.setHeight( 2.*r.height()/3. );
00252             painter->setBrushOrigin( itemRect.topLeft() );
00253             painter->save();
00254             painter->translate( 0.5, 0.5 );
00255             painter->drawRect( r );
00256             bool ok;
00257             qreal completion = idx.model()->data( idx, KDGantt::TaskCompletionRole ).toDouble( &ok );
00258             if ( ok ) {
00259                 qreal h = r.height();
00260                 QRectF cr( r.x(), r.y()+h/4.,
00261                            r.width()*completion/100., h/2.+1 /*??*/ );
00262                 painter->fillRect( cr, painter->pen().brush() );
00263             }
00264             painter->restore();
00265             Qt::Alignment ta;
00266             switch( opt.displayPosition ) {
00267             case StyleOptionGanttItem::Left: ta = Qt::AlignLeft; break;
00268             case StyleOptionGanttItem::Right: ta = Qt::AlignRight; break;
00269             case StyleOptionGanttItem::Center: ta = Qt::AlignCenter; break;
00270             }
00271             painter->drawText( boundingRect, ta, txt );
00272         }
00273         break;
00274     case TypeSummary:
00275         if ( opt.itemRect.isValid() ) {
00276             // TODO
00277             pw-=1;
00278             const QRectF r = QRectF( opt.itemRect ).adjusted( -pw, -pw, pw, pw );
00279             QPainterPath path;
00280             const qreal delta = r.height()/2.;
00281             path.moveTo( r.topLeft() );
00282             path.lineTo( r.topRight() );
00283             path.lineTo( QPointF( r.right(), r.top() + 2.*delta ) );
00284             //path.lineTo( QPointF( r.right()-3./2.*delta, r.top() + delta ) );
00285             path.quadTo( QPointF( r.right()-.5*delta, r.top() + delta ), QPointF( r.right()-2.*delta, r.top() + delta ) );
00286             //path.lineTo( QPointF( r.left()+3./2.*delta, r.top() + delta ) );
00287             path.lineTo( QPointF( r.left() + 2.*delta, r.top() + delta ) );
00288             path.quadTo( QPointF( r.left()+.5*delta, r.top() + delta ), QPointF( r.left(), r.top() + 2.*delta ) );
00289             path.closeSubpath();
00290             painter->setBrushOrigin( itemRect.topLeft() );
00291             painter->save();
00292             painter->translate( 0.5, 0.5 );
00293             painter->drawPath( path );
00294             painter->restore();
00295             Qt::Alignment ta;
00296             switch( opt.displayPosition ) {
00297             case StyleOptionGanttItem::Left: ta = Qt::AlignLeft; break;
00298             case StyleOptionGanttItem::Right: ta = Qt::AlignRight; break;
00299             case StyleOptionGanttItem::Center: ta = Qt::AlignCenter; break;
00300             }
00301             painter->drawText( boundingRect, ta | Qt::AlignVCenter, txt );
00302         }
00303         break;
00304     case TypeEvent: /* TODO */
00305         //qDebug() << opt.boundingRect << opt.itemRect;
00306         if ( opt.boundingRect.isValid() ) {
00307             const qreal pw = painter->pen().width() / 2. - 1;
00308             const QRectF r = QRectF( opt.rect ).adjusted( -pw, -pw, pw, pw );
00309             QPainterPath path;
00310             const qreal delta = static_cast< int >( r.height() / 2 );
00311             path.moveTo( delta, 0. );
00312             path.lineTo( 2.*delta, delta );
00313             path.lineTo( delta, 2.*delta );
00314             path.lineTo( 0., delta );
00315             path.closeSubpath();
00316             painter->save();
00317             painter->translate( r.topLeft() );
00318             painter->translate( 0.5, 0.5 );
00319             painter->drawPath( path );
00320             painter->restore();
00321             Qt::Alignment ta;
00322             switch( opt.displayPosition ) {
00323             case StyleOptionGanttItem::Left: ta = Qt::AlignLeft; break;
00324             case StyleOptionGanttItem::Right: ta = Qt::AlignRight; break;
00325             case StyleOptionGanttItem::Center: ta = Qt::AlignCenter; break;
00326             }
00327             painter->drawText( boundingRect, ta | Qt::AlignVCenter, txt );
00328         }
00329         break;
00330     default:
00331         break;
00332     }
00333     painter->restore();
00334 }
00335 
00336 static const qreal TURN = 10.;
00337 static const qreal PW = 1.5;
00338 
00343 QRectF ItemDelegate::constraintBoundingRect( const QPointF& start, const QPointF& end, const Constraint &constraint ) const
00344 {
00345     QPolygonF poly;
00346     switch ( constraint.relationType() ) {
00347         case Constraint::FinishStart:
00348             poly = finishStartLine( start, end ) + finishStartArrow( start, end );
00349             break;
00350         case Constraint::FinishFinish:
00351             poly = finishFinishLine( start, end ) + finishFinishArrow( start, end );
00352             break;
00353         case Constraint::StartStart:
00354             poly = startStartLine( start, end ) + startStartArrow( start, end );
00355             break;
00356         case Constraint::StartFinish:
00357             poly = startFinishLine( start, end ) + startFinishArrow( start, end );
00358             break;
00359         default:
00360             break;
00361     }
00362     return poly.boundingRect().adjusted( -PW, -PW, PW, PW );
00363 }
00364 
00365 
00371 void ItemDelegate::paintConstraintItem( QPainter* painter, const QStyleOptionGraphicsItem& opt,
00372                                         const QPointF& start, const QPointF& end, const Constraint &constraint )
00373 {
00374     //qDebug()<<"ItemDelegate::paintConstraintItem"<<start<<end<<constraint;
00375     switch ( constraint.relationType() ) {
00376         case Constraint::FinishStart: 
00377             paintFinishStartConstraint( painter, opt, start, end, constraint );
00378             break;
00379         case Constraint::FinishFinish: 
00380             paintFinishFinishConstraint( painter, opt, start, end, constraint );
00381             break;
00382         case Constraint::StartStart: 
00383             paintStartStartConstraint( painter, opt, start, end, constraint );
00384             break;
00385         case Constraint::StartFinish: 
00386             paintStartFinishConstraint( painter, opt, start, end, constraint );
00387             break;
00388         default:
00389             break;
00390     }
00391 }
00392 
00393 void ItemDelegate::paintFinishStartConstraint( QPainter* painter, const QStyleOptionGraphicsItem& opt, const QPointF& start, const QPointF& end, const Constraint &constraint )
00394 {
00395     Q_UNUSED( opt );
00396     
00397     QPen pen;
00398     QVariant dataPen;
00399 
00400     // default pens
00401     if ( start.x() <= end.x() ) {
00402         pen = QPen( Qt::black );
00403         dataPen = constraint.data( Constraint::ValidConstraintPen );
00404     } else {
00405         pen = QPen( Qt::red );
00406         dataPen = constraint.data( Constraint::InvalidConstraintPen );
00407     }
00408 
00409     // data() pen
00410     if( qVariantCanConvert< QPen >( dataPen ) )
00411         pen = qVariantValue< QPen >( dataPen );
00412 
00413     painter->setPen( pen );
00414     painter->setBrush( pen.color() );
00415     
00416     painter->drawPolyline( finishStartLine( start, end ) );
00417     painter->drawPolygon( finishStartArrow( start, end ) );
00418 }
00419 
00420 QPolygonF ItemDelegate::finishStartLine( const QPointF& start, const QPointF& end ) const
00421 {
00422     QPolygonF poly;
00423     qreal midx = end.x() - TURN;
00424     qreal midy = ( end.y()-start.y() )/2. + start.y();
00425 
00426     if ( start.x() > end.x()-TURN ) {
00427         poly << start
00428                 << QPointF( start.x()+TURN, start.y() )
00429                 << QPointF( start.x()+TURN, midy )
00430                 << QPointF( end.x()-TURN, midy )
00431                 << QPointF( end.x()-TURN, end.y() )
00432                 << end;
00433     } else {
00434         poly << start
00435                 << QPointF( midx, start.y() )
00436                 << QPointF( midx, end.y() )
00437                 << end;
00438     }
00439     return poly;
00440 }
00441 
00442 QPolygonF ItemDelegate::finishStartArrow( const QPointF& start, const QPointF& end ) const
00443 {
00444     QPolygonF poly;
00445     poly << end
00446             << QPointF( end.x()-TURN/2., end.y()-TURN/2. )
00447             << QPointF( end.x()-TURN/2., end.y()+TURN/2. );
00448     return poly;
00449 }
00450 
00451 void ItemDelegate::paintFinishFinishConstraint( QPainter* painter, const QStyleOptionGraphicsItem& opt, const QPointF& start, const QPointF& end, const Constraint &constraint )
00452 {
00453     Q_UNUSED( opt );
00454     
00455     QPen pen;
00456     QVariant dataPen;
00457 
00458     // default pens
00459     if ( start.x() <= end.x() ) {
00460         pen = QPen( Qt::black );
00461         dataPen = constraint.data( Constraint::ValidConstraintPen );
00462     } else {
00463         pen = QPen( Qt::red );
00464         dataPen = constraint.data( Constraint::InvalidConstraintPen );
00465     }
00466 
00467     // data() pen
00468     if( qVariantCanConvert< QPen >( dataPen ) )
00469         pen = qVariantValue< QPen >( dataPen );
00470     
00471     painter->setPen( pen );
00472     painter->setBrush( pen.color() );
00473     
00474     painter->drawPolyline( finishFinishLine( start, end ) );
00475     painter->drawPolygon( finishFinishArrow( start, end ) );
00476 }
00477 
00478 QPolygonF ItemDelegate::finishFinishLine( const QPointF& start, const QPointF& end ) const
00479 {
00480     QPolygonF poly;
00481     qreal midx = end.x() + TURN;
00482     qreal midy = ( end.y()-start.y() )/2. + start.y();
00483 
00484     if ( start.x() > end.x()+TURN ) {
00485         poly << start
00486                 << QPointF( start.x()+TURN, start.y() )
00487                 << QPointF( start.x()+TURN, end.y() )
00488                 << end;
00489     } else {
00490         poly << start
00491                 << QPointF( midx, start.y() )
00492                 << QPointF( midx, midy )
00493                 << QPointF( end.x()+TURN, midy )
00494                 << QPointF( end.x()+TURN, end.y() )
00495                 << end;
00496     }
00497     return poly;
00498 }
00499 
00500 QPolygonF ItemDelegate::finishFinishArrow( const QPointF& start, const QPointF& end ) const
00501 {
00502     QPolygonF poly;
00503     poly << end
00504             << QPointF( end.x()+TURN/2., end.y()-TURN/2. )
00505             << QPointF( end.x()+TURN/2., end.y()+TURN/2. );
00506     return poly;
00507 }
00508 
00509 void ItemDelegate::paintStartStartConstraint( QPainter* painter, const QStyleOptionGraphicsItem& opt, const QPointF& start, const QPointF& end, const Constraint &constraint )
00510 {
00511     Q_UNUSED( opt );
00512         
00513     QPen pen;
00514     QVariant dataPen;
00515 
00516     // default pens
00517     if ( start.x() <= end.x() ) {
00518         pen = QPen( Qt::black );
00519         dataPen = constraint.data( Constraint::ValidConstraintPen );
00520     } else {
00521         pen = QPen( Qt::red );
00522         dataPen = constraint.data( Constraint::InvalidConstraintPen );
00523     }
00524 
00525     // data() pen
00526     if( qVariantCanConvert< QPen >( dataPen ) )
00527         pen = qVariantValue< QPen >( dataPen );
00528 
00529     painter->setPen( pen );
00530     painter->setBrush( pen.color() );
00531     
00532     painter->drawPolyline( startStartLine( start, end ) );
00533     painter->drawPolygon( startStartArrow( start, end ) );
00534 
00535 }
00536 
00537 QPolygonF ItemDelegate::startStartLine( const QPointF& start, const QPointF& end ) const
00538 {
00539     QPolygonF poly;
00540     qreal midx = start.x() - TURN;
00541     qreal midy = ( end.y()-start.y() )/2. + start.y();
00542 
00543     if ( start.x() > end.x() ) {
00544         poly << start
00545                 << QPointF( end.x()-TURN, start.y() )
00546                 << QPointF( end.x()-TURN, end.y() )
00547                 << end;
00548     } else {
00549         poly << start
00550                 << QPointF( start.x()-TURN, start.y() )
00551                 << QPointF( start.x()-TURN, end.y() )
00552                 << QPointF( end.x()-TURN, end.y() )
00553                 << end;
00554     }
00555     return poly;
00556 }
00557 
00558 QPolygonF ItemDelegate::startStartArrow( const QPointF& start, const QPointF& end ) const
00559 {
00560     QPolygonF poly;
00561     poly << end
00562             << QPointF( end.x()-TURN/2., end.y()-TURN/2. )
00563             << QPointF( end.x()-TURN/2., end.y()+TURN/2. );
00564     return poly;
00565 }
00566 
00567 void ItemDelegate::paintStartFinishConstraint( QPainter* painter, const QStyleOptionGraphicsItem& opt, const QPointF& start, const QPointF& end, const Constraint &constraint )
00568 {
00569     Q_UNUSED( opt );
00570         
00571     QPen pen;
00572     QVariant dataPen;
00573 
00574     // default pens
00575     if ( start.x() <= end.x() ) {
00576         pen = QPen( Qt::black );
00577         dataPen = constraint.data( Constraint::ValidConstraintPen );
00578     } else {
00579         pen = QPen( Qt::red );
00580         dataPen = constraint.data( Constraint::InvalidConstraintPen );
00581     }
00582 
00583     // data() pen
00584     if( qVariantCanConvert< QPen >( dataPen ) )
00585         pen = qVariantValue< QPen >( dataPen );
00586 
00587     painter->setPen( pen );
00588     painter->setBrush( pen.color() );
00589     
00590     painter->drawPolyline( startFinishLine( start, end ) );
00591     painter->drawPolygon( startFinishArrow( start, end ) );
00592 }
00593 
00594 QPolygonF ItemDelegate::startFinishLine( const QPointF& start, const QPointF& end ) const
00595 {
00596     QPolygonF poly;
00597     qreal midx = end.x() + TURN;
00598     qreal midy = ( end.y()-start.y() )/2. + start.y();
00599 
00600     if ( start.x()-TURN > end.x()+TURN ) {
00601         poly << start
00602                 << QPointF( midx, start.y() )
00603                 << QPointF( midx, end.y() )
00604                 << end;
00605     } else {
00606         poly << start
00607                 << QPointF( start.x()-TURN, start.y() )
00608                 << QPointF( start.x()-TURN, midy )
00609                 << QPointF( midx, midy )
00610                 << QPointF( end.x()+TURN, end.y() )
00611                 << end;
00612     }
00613     return poly;
00614 }
00615 
00616 QPolygonF ItemDelegate::startFinishArrow( const QPointF& start, const QPointF& end ) const
00617 {
00618     QPolygonF poly;
00619     poly << end
00620             << QPointF( end.x()+TURN/2., end.y()-TURN/2. )
00621             << QPointF( end.x()+TURN/2., end.y()+TURN/2. );
00622     return poly;
00623 }
00624 
00625 
00626 #include "moc_kdganttitemdelegate.cpp"

kdgantt

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

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
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