korganizer Library API Documentation

koagendaitem.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 2000,2001,2003 Cornelius Schumacher <schumacher@kde.org>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include <qtooltip.h>
00026 #include <qdragobject.h>
00027 #include <qpainter.h>
00028 
00029 #include <kiconloader.h>
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kwordwrap.h>
00033 
00034 #include <libkcal/icaldrag.h>
00035 #include <libkcal/vcaldrag.h>
00036 #include <libkdepim/kvcarddrag.h>
00037 #ifndef KORG_NOKABC
00038 #include <kabc/addressee.h>
00039 #include <kabc/vcardconverter.h>
00040 #endif
00041 
00042 #include "koprefs.h"
00043 #include "koglobals.h"
00044 
00045 #include "koincidencetooltip.h"
00046 #include "koagendaitem.h"
00047 #include "koagendaitem.moc"
00048 
00049 //--------------------------------------------------------------------------
00050 
00051 QToolTipGroup *KOAgendaItem::mToolTipGroup = 0;
00052 
00053 //--------------------------------------------------------------------------
00054 
00055 KOAgendaItem::KOAgendaItem( Incidence *incidence, QDate qd, QWidget *parent,
00056                             const char *name, WFlags f ) :
00057   QWidget( parent, name, f ), mIncidence( incidence ), mDate( qd ),
00058   mLabelText( mIncidence->summary() ), mIconAlarm( false ),
00059   mIconRecur( false ), mIconReadonly( false ), mIconReply( false ),
00060   mIconGroup( false ), mIconOrganizer( false ),
00061   mMultiItemInfo( 0 ), mStartMoveInfo( 0 )
00062 {
00063   setBackgroundMode( Qt::NoBackground );
00064 
00065   setCellXY( 0, 0, 1 );
00066   setCellXRight( 0 );
00067   setMouseTracking( true );
00068 
00069   updateIcons();
00070 
00071   // select() does nothing, if state hasn't change, so preset mSelected.
00072   mSelected = true;
00073   select( false );
00074 
00075   KOIncidenceToolTip::add( this, incidence, toolTipGroup() );
00076   setAcceptDrops( true );
00077 }
00078 
00079 void KOAgendaItem::updateIcons()
00080 {
00081   mIconReadonly = mIncidence->isReadOnly();
00082   mIconRecur = mIncidence->doesRecur();
00083   mIconAlarm = mIncidence->isAlarmEnabled();
00084   if ( mIncidence->attendeeCount() > 0 ) {
00085     if ( mIncidence->organizer() == KOPrefs::instance()->email() ) {
00086       mIconReply = false;
00087       mIconGroup = false;
00088       mIconOrganizer = true;
00089     } else {
00090       Attendee *me = mIncidence->attendeeByMails( KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email() );
00091       if ( me ) {
00092         if ( me->status() == Attendee::NeedsAction && me->RSVP() ) {
00093           mIconReply = true;
00094           mIconGroup = false;
00095           mIconOrganizer = false;
00096         } else {
00097           mIconReply = false;
00098           mIconGroup = true;
00099           mIconOrganizer = false;
00100         }
00101       } else {
00102         mIconReply = false;
00103         mIconGroup = true;
00104         mIconOrganizer = false;
00105       }
00106     }
00107   }
00108   update();
00109 }
00110 
00111 
00112 void KOAgendaItem::select( bool selected )
00113 {
00114   if ( mSelected == selected ) return;
00115   mSelected = selected;
00116 
00117   update();
00118 }
00119 
00120 
00121 /*
00122   Return height of item in units of agenda cells
00123 */
00124 int KOAgendaItem::cellHeight() const
00125 {
00126   return mCellYBottom - mCellYTop + 1;
00127 }
00128 
00129 /*
00130   Return height of item in units of agenda cells
00131 */
00132 int KOAgendaItem::cellWidth() const
00133 {
00134   return mCellXRight - mCellXLeft + 1;
00135 }
00136 
00137 void KOAgendaItem::setItemDate( QDate qd )
00138 {
00139   mDate = qd;
00140 }
00141 
00142 void KOAgendaItem::setCellXY( int X, int YTop, int YBottom )
00143 {
00144   mCellXLeft = X;
00145   mCellYTop = YTop;
00146   mCellYBottom = YBottom;
00147 }
00148 
00149 void KOAgendaItem::setCellXRight( int xright )
00150 {
00151   mCellXRight = xright;
00152 }
00153 
00154 void KOAgendaItem::setCellX( int XLeft, int XRight )
00155 {
00156   mCellXLeft = XLeft;
00157   mCellXRight = XRight;
00158 }
00159 
00160 void KOAgendaItem::setCellY( int YTop, int YBottom )
00161 {
00162   mCellYTop = YTop;
00163   mCellYBottom = YBottom;
00164 }
00165 
00166 void KOAgendaItem::setMultiItem(KOAgendaItem *first, KOAgendaItem *prev,
00167                                 KOAgendaItem *next, KOAgendaItem *last)
00168 {
00169   if (!mMultiItemInfo) mMultiItemInfo=new MultiItemInfo;
00170   mMultiItemInfo->mFirstMultiItem = first;
00171   mMultiItemInfo->mPrevMultiItem = prev;
00172   mMultiItemInfo->mNextMultiItem = next;
00173   mMultiItemInfo->mLastMultiItem = last;
00174 }
00175 bool KOAgendaItem::isMultiItem()
00176 {
00177   return mMultiItemInfo;
00178 }
00179 KOAgendaItem* KOAgendaItem::prependMoveItem(KOAgendaItem* e)
00180 {
00181   if (!e) return e;
00182 
00183   KOAgendaItem*first=0, *last=0;
00184   if (isMultiItem()) {
00185     first=mMultiItemInfo->mFirstMultiItem;
00186     last=mMultiItemInfo->mLastMultiItem;
00187   }
00188   if (!first) first=this;
00189   if (!last) last=this;
00190 
00191   e->setMultiItem(0, 0, first, last);
00192   first->setMultiItem(e, e, first->nextMultiItem(), first->lastMultiItem() );
00193 
00194   KOAgendaItem*tmp=first->nextMultiItem();
00195   while (tmp) {
00196     tmp->setMultiItem( e, tmp->prevMultiItem(), tmp->nextMultiItem(), tmp->lastMultiItem() );
00197     tmp = tmp->nextMultiItem();
00198   }
00199 
00200   if ( mStartMoveInfo && !e->moveInfo() ) {
00201     e->mStartMoveInfo=new MultiItemInfo( *mStartMoveInfo );
00202 //    e->moveInfo()->mFirstMultiItem = moveInfo()->mFirstMultiItem;
00203 //    e->moveInfo()->mLastMultiItem = moveInfo()->mLastMultiItem;
00204     e->moveInfo()->mPrevMultiItem = 0;
00205     e->moveInfo()->mNextMultiItem = first;
00206   }
00207 
00208   if (first && first->moveInfo()) {
00209     first->moveInfo()->mPrevMultiItem = e;
00210   }
00211   return e;
00212 }
00213 
00214 KOAgendaItem* KOAgendaItem::appendMoveItem(KOAgendaItem* e)
00215 {
00216   if (!e) return e;
00217 
00218   KOAgendaItem*first=0, *last=0;
00219   if (isMultiItem()) {
00220     first=mMultiItemInfo->mFirstMultiItem;
00221     last=mMultiItemInfo->mLastMultiItem;
00222   }
00223   if (!first) first=this;
00224   if (!last) last=this;
00225 
00226   e->setMultiItem( first, last, 0, 0 );
00227   KOAgendaItem*tmp=first;
00228 
00229   while (tmp) {
00230     tmp->setMultiItem(tmp->firstMultiItem(), tmp->prevMultiItem(), tmp->nextMultiItem(), e);
00231     tmp = tmp->nextMultiItem();
00232   }
00233   last->setMultiItem( last->firstMultiItem(), last->prevMultiItem(), e, e);
00234 
00235   if ( mStartMoveInfo && !e->moveInfo() ) {
00236     e->mStartMoveInfo=new MultiItemInfo( *mStartMoveInfo );
00237 //    e->moveInfo()->mFirstMultiItem = moveInfo()->mFirstMultiItem;
00238 //    e->moveInfo()->mLastMultiItem = moveInfo()->mLastMultiItem;
00239     e->moveInfo()->mPrevMultiItem = last;
00240     e->moveInfo()->mNextMultiItem = 0;
00241   }
00242   if (last && last->moveInfo()) {
00243     last->moveInfo()->mNextMultiItem = e;
00244   }
00245   return e;
00246 }
00247 
00248 KOAgendaItem* KOAgendaItem::removeMoveItem(KOAgendaItem* e)
00249 {
00250   if (isMultiItem()) {
00251     KOAgendaItem *first = mMultiItemInfo->mFirstMultiItem;
00252     KOAgendaItem *next, *prev;
00253     KOAgendaItem *last = mMultiItemInfo->mLastMultiItem;
00254     if (!first) first = this;
00255     if (!last) last = this;
00256     if ( first==e ) {
00257       first = first->nextMultiItem();
00258       first->setMultiItem( 0, 0, first->nextMultiItem(), first->lastMultiItem() );
00259     }
00260     if ( last==e ) {
00261       last=last->prevMultiItem();
00262       last->setMultiItem( last->firstMultiItem(), last->prevMultiItem(), 0, 0 );
00263     }
00264 
00265     KOAgendaItem *tmp =  first;
00266     if ( first==last ) {
00267       delete mMultiItemInfo;
00268       tmp = 0;
00269       mMultiItemInfo = 0;
00270     }
00271     while ( tmp ) {
00272       next = tmp->nextMultiItem();
00273       prev = tmp->prevMultiItem();
00274       if ( e==next ) {
00275         next = next->nextMultiItem();
00276       }
00277       if ( e==prev ) {
00278         prev = prev->prevMultiItem();
00279       }
00280       tmp->setMultiItem((tmp==first)?0:first, (tmp==prev)?0:prev, (tmp==next)?0:next, (tmp==last)?0:last);
00281       tmp = tmp->nextMultiItem();
00282     }
00283   }
00284 
00285   return e;
00286 }
00287 
00288 
00289 void KOAgendaItem::startMove()
00290 {
00291   KOAgendaItem* first = this;
00292   if ( isMultiItem() && mMultiItemInfo->mFirstMultiItem ) {
00293     first=mMultiItemInfo->mFirstMultiItem;
00294   }
00295   first->startMovePrivate();
00296 }
00297 
00298 void KOAgendaItem::startMovePrivate()
00299 {
00300   mStartMoveInfo = new MultiItemInfo;
00301   mStartMoveInfo->mStartCellXLeft = mCellXLeft;
00302   mStartMoveInfo->mStartCellXRight = mCellXRight;
00303   mStartMoveInfo->mStartCellYTop = mCellYTop;
00304   mStartMoveInfo->mStartCellYBottom = mCellYBottom;
00305   if (mMultiItemInfo) {
00306     mStartMoveInfo->mFirstMultiItem = mMultiItemInfo->mFirstMultiItem;
00307     mStartMoveInfo->mLastMultiItem = mMultiItemInfo->mLastMultiItem;
00308     mStartMoveInfo->mPrevMultiItem = mMultiItemInfo->mPrevMultiItem;
00309     mStartMoveInfo->mNextMultiItem = mMultiItemInfo->mNextMultiItem;
00310   } else {
00311     mStartMoveInfo->mFirstMultiItem = 0;
00312     mStartMoveInfo->mLastMultiItem = 0;
00313     mStartMoveInfo->mPrevMultiItem = 0;
00314     mStartMoveInfo->mNextMultiItem = 0;
00315   }
00316   if ( isMultiItem() && mMultiItemInfo->mNextMultiItem )
00317   {
00318     mMultiItemInfo->mNextMultiItem->startMovePrivate();
00319   }
00320 }
00321 
00322 void KOAgendaItem::resetMove()
00323 {
00324   if ( mStartMoveInfo ) {
00325     if ( mStartMoveInfo->mFirstMultiItem ) {
00326       mStartMoveInfo->mFirstMultiItem->resetMovePrivate();
00327     } else {
00328       resetMovePrivate();
00329     }
00330   }
00331 }
00332 
00333 void KOAgendaItem::resetMovePrivate()
00334 {
00335   if (mStartMoveInfo) {
00336     mCellXLeft = mStartMoveInfo->mStartCellXLeft;
00337     mCellXRight = mStartMoveInfo->mStartCellXRight;
00338     mCellYTop = mStartMoveInfo->mStartCellYTop;
00339     mCellYBottom = mStartMoveInfo->mStartCellYBottom;
00340 
00341     // if we don't have mMultiItemInfo, the item didn't span two days before, 
00342     // and wasn't moved over midnight, either, so we don't have to reset 
00343     // anything. Otherwise, restore from mMoveItemInfo
00344     if ( mMultiItemInfo ) {
00345       // It was already a multi-day info
00346       mMultiItemInfo->mFirstMultiItem = mStartMoveInfo->mFirstMultiItem;
00347       mMultiItemInfo->mPrevMultiItem = mStartMoveInfo->mPrevMultiItem;
00348       mMultiItemInfo->mNextMultiItem = mStartMoveInfo->mNextMultiItem;
00349       mMultiItemInfo->mLastMultiItem = mStartMoveInfo->mLastMultiItem;
00350     
00351       if ( !mStartMoveInfo->mFirstMultiItem ) {
00352         // This was the first multi-item when the move started, delete all previous
00353         KOAgendaItem*toDel=mStartMoveInfo->mPrevMultiItem;
00354         KOAgendaItem*nowDel=0L;
00355         while (toDel) {
00356           nowDel=toDel;
00357           if (nowDel->moveInfo()) {
00358             toDel=nowDel->moveInfo()->mPrevMultiItem;
00359           }
00360           emit removeAgendaItem( nowDel );
00361         }
00362         mMultiItemInfo->mFirstMultiItem = 0L;
00363         mMultiItemInfo->mPrevMultiItem = 0L;
00364       }
00365       if ( !mStartMoveInfo->mLastMultiItem ) {
00366         // This was the last multi-item when the move started, delete all next
00367         KOAgendaItem*toDel=mStartMoveInfo->mNextMultiItem;
00368         KOAgendaItem*nowDel=0L;
00369         while (toDel) {
00370           nowDel=toDel;
00371           if (nowDel->moveInfo()) {
00372             toDel=nowDel->moveInfo()->mNextMultiItem;
00373           }
00374           emit removeAgendaItem( nowDel );
00375         }
00376         mMultiItemInfo->mLastMultiItem = 0L;
00377         mMultiItemInfo->mNextMultiItem = 0L;
00378       }
00379     
00380       if ( mStartMoveInfo->mFirstMultiItem==0 && mStartMoveInfo->mLastMultiItem==0 ) {
00381         // it was a single-day event before we started the move. 
00382         delete mMultiItemInfo;
00383         mMultiItemInfo = 0;
00384       }
00385     }
00386     delete mStartMoveInfo;
00387     mStartMoveInfo = 0;
00388   }
00389   emit showAgendaItem( this );
00390   if ( nextMultiItem() ) {
00391     nextMultiItem()->resetMovePrivate();
00392   }
00393 }
00394 
00395 void KOAgendaItem::endMove()
00396 {
00397   KOAgendaItem*first=firstMultiItem();
00398   if (!first) first=this;
00399   first->endMovePrivate();
00400 }
00401 
00402 void KOAgendaItem::endMovePrivate()
00403 {
00404   if ( mStartMoveInfo ) {
00405     // if first, delete all previous
00406     if ( !firstMultiItem() || firstMultiItem()==this ) {
00407       KOAgendaItem*toDel=mStartMoveInfo->mPrevMultiItem;
00408       KOAgendaItem*nowDel = 0;
00409       while (toDel) {
00410         nowDel=toDel;
00411         if (nowDel->moveInfo()) {
00412           toDel=nowDel->moveInfo()->mPrevMultiItem;
00413         }
00414         emit removeAgendaItem( nowDel );
00415       }
00416     }
00417     // if last, delete all next
00418     if ( !lastMultiItem() || lastMultiItem()==this ) {
00419       KOAgendaItem*toDel=mStartMoveInfo->mNextMultiItem;
00420       KOAgendaItem*nowDel = 0;
00421       while (toDel) {
00422         nowDel=toDel;
00423         if (nowDel->moveInfo()) {
00424           toDel=nowDel->moveInfo()->mNextMultiItem;
00425         }
00426         emit removeAgendaItem( nowDel );
00427       }
00428     }
00429     // also delete the moving info
00430     delete mStartMoveInfo;
00431     mStartMoveInfo=0;
00432     if ( nextMultiItem() )
00433       nextMultiItem()->endMovePrivate();
00434   }
00435 }
00436 
00437 void KOAgendaItem::moveRelative(int dx, int dy)
00438 {
00439   int newXLeft = cellXLeft() + dx;
00440   int newXRight = cellXRight() + dx;
00441   int newYTop = cellYTop() + dy;
00442   int newYBottom = cellYBottom() + dy;
00443   setCellXY(newXLeft,newYTop,newYBottom);
00444   setCellXRight(newXRight);
00445 }
00446 
00447 void KOAgendaItem::expandTop(int dy)
00448 {
00449   int newYTop = cellYTop() + dy;
00450   int newYBottom = cellYBottom();
00451   if (newYTop > newYBottom) newYTop = newYBottom;
00452   setCellY(newYTop, newYBottom);
00453 }
00454 
00455 void KOAgendaItem::expandBottom(int dy)
00456 {
00457   int newYTop = cellYTop();
00458   int newYBottom = cellYBottom() + dy;
00459   if (newYBottom < newYTop) newYBottom = newYTop;
00460   setCellY(newYTop, newYBottom);
00461 }
00462 
00463 void KOAgendaItem::expandLeft(int dx)
00464 {
00465   int newXLeft = cellXLeft() + dx;
00466   int newXRight = cellXRight();
00467   if ( newXLeft > newXRight ) newXLeft = newXRight;
00468   setCellX( newXLeft, newXRight );
00469 }
00470 
00471 void KOAgendaItem::expandRight(int dx)
00472 {
00473   int newXLeft = cellXLeft();
00474   int newXRight = cellXRight() + dx;
00475   if ( newXRight < newXLeft ) newXRight = newXLeft;
00476   setCellX( newXLeft, newXRight );
00477 }
00478 
00479 QToolTipGroup *KOAgendaItem::toolTipGroup()
00480 {
00481   if (!mToolTipGroup) mToolTipGroup = new QToolTipGroup(0);
00482   return mToolTipGroup;
00483 }
00484 
00485 void KOAgendaItem::dragEnterEvent( QDragEnterEvent *e )
00486 {
00487 #ifndef KORG_NODND
00488   if ( ICalDrag::canDecode( e ) || VCalDrag::canDecode( e ) ) {
00489     e->ignore();
00490     return;
00491   }
00492   if ( KVCardDrag::canDecode( e ) || QTextDrag::canDecode( e ) )
00493     e->accept();
00494   else
00495     e->ignore();
00496 #endif
00497 }
00498 
00499 void KOAgendaItem::addAttendee(QString newAttendee)
00500 {
00501   kdDebug(5850) << " Email: " << newAttendee << endl;
00502   int pos = newAttendee.find("<");
00503   QString name = newAttendee.left(pos);
00504   QString email = newAttendee.mid(pos);
00505   if (!email.isEmpty()) {
00506     mIncidence->addAttendee(new Attendee(name,email));
00507   } else if (name.contains("@")) {
00508     mIncidence->addAttendee(new Attendee(name,name));
00509   } else {
00510     mIncidence->addAttendee(new Attendee(name,QString::null));
00511   }
00512 }
00513 
00514 void KOAgendaItem::dropEvent( QDropEvent *e )
00515 {
00516 #ifndef KORG_NODND
00517   QString text;
00518   QString vcards;
00519 
00520 #ifndef KORG_NOKABC
00521   if ( KVCardDrag::decode( e, vcards ) ) {
00522     KABC::VCardConverter converter;
00523 
00524     KABC::Addressee::List list = converter.parseVCards( vcards );
00525     KABC::Addressee::List::Iterator it;
00526     for ( it = list.begin(); it != list.end(); ++it ) {
00527       QString em( (*it).fullEmail() );
00528       if (em.isEmpty()) {
00529         em=(*it).realName();
00530       }
00531       addAttendee( em );
00532     }
00533   } else
00534 #endif
00535   if( QTextDrag::decode( e, text ) ) {
00536     kdDebug(5850) << "Dropped : " << text << endl;
00537     QStringList emails = QStringList::split( ",", text );
00538     for( QStringList::ConstIterator it = emails.begin(); it != emails.end();
00539          ++it ) {
00540       addAttendee( *it );
00541     }
00542   }
00543 #endif
00544 }
00545 
00546 
00547 QPtrList<KOAgendaItem> KOAgendaItem::conflictItems()
00548 {
00549   return mConflictItems;
00550 }
00551 
00552 void KOAgendaItem::setConflictItems( QPtrList<KOAgendaItem> ci )
00553 {
00554   mConflictItems = ci;
00555   KOAgendaItem *item;
00556   for ( item = mConflictItems.first(); item != 0;
00557         item = mConflictItems.next() ) {
00558     item->addConflictItem( this );
00559   }
00560 }
00561 
00562 void KOAgendaItem::addConflictItem( KOAgendaItem *ci )
00563 {
00564   if ( mConflictItems.find( ci ) < 0 ) mConflictItems.append( ci );
00565 }
00566 
00567 QString KOAgendaItem::label() const
00568 {
00569   return mLabelText;
00570 }
00571 
00572 bool KOAgendaItem::overlaps( KOrg::CellItem *o ) const
00573 {
00574   KOAgendaItem *other = static_cast<KOAgendaItem *>( o );
00575 
00576   if ( cellXLeft() <= other->cellXRight() &&
00577        cellXRight() >= other->cellXLeft() ) {
00578     if ( ( cellYTop() <= other->cellYBottom() ) &&
00579          ( cellYBottom() >= other->cellYTop() ) ) {
00580       return true;
00581     }
00582   }
00583 
00584   return false;
00585 }
00586 
00587 void KOAgendaItem::paintFrame( QPainter *p, const QColor &color )
00588 {
00589   QColor oldpen(p->pen().color());
00590   p->setPen( color );
00591   p->drawRect( 0, 0, width(), height() );
00592   p->drawRect( 1, 1, width() - 2, height() - 2 );
00593   p->setPen( oldpen );
00594 }
00595 
00596 static void conditionalPaint( QPainter *p, bool cond, int &x, int ft,
00597                               const QPixmap &pxmp )
00598 {
00599   if ( !cond ) return;
00600 
00601   p->drawPixmap( x, ft, pxmp );
00602   x += pxmp.width() + ft;
00603 }
00604 
00605 void KOAgendaItem::paintTodoIcon( QPainter *p, int &x, int ft )
00606 {
00607   static const QPixmap todoPxmp = KOGlobals::self()->smallIcon("todo");
00608   static const QPixmap completedPxmp = KOGlobals::self()->smallIcon("checkedbox");
00609   if ( mIncidence->type() != "Todo" )
00610     return;
00611   bool b = ( static_cast<Todo *>( mIncidence ) )->isCompleted();
00612   conditionalPaint( p, b, x, ft, todoPxmp );
00613   conditionalPaint( p, !b, x, ft, completedPxmp );
00614 }
00615 
00616 void KOAgendaItem::paintEvent( QPaintEvent * )
00617 {
00618   QPainter p( this );
00619   const int ft = 2; // frame thickness for layout, see paintFrame()
00620   const int margin = 1 + ft; // frame + space between frame and content
00621 
00622   static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon("bell");
00623   static const QPixmap recurPxmp = KOGlobals::self()->smallIcon("recur");
00624   static const QPixmap readonlyPxmp = KOGlobals::self()->smallIcon("readonlyevent");
00625   static const QPixmap replyPxmp = KOGlobals::self()->smallIcon("mail_reply");
00626   static const QPixmap groupPxmp = KOGlobals::self()->smallIcon("groupevent");
00627   static const QPixmap organizerPxmp = KOGlobals::self()->smallIcon("organizer");
00628 
00629   QColor bgColor;
00630   if ( (mIncidence->type() == "Todo") &&
00631        ( !((static_cast<Todo*>(mIncidence))->isCompleted()) &&
00632          ((static_cast<Todo*>(mIncidence))->dtDue() < QDate::currentDate()) ) )
00633     bgColor = KOPrefs::instance()->mTodoOverdueColor;
00634   else {
00635     QStringList categories = mIncidence->categories();
00636     QString cat = categories.first();
00637     if (cat.isEmpty())
00638       bgColor = KOPrefs::instance()->mEventColor;
00639     else
00640       bgColor = *(KOPrefs::instance()->categoryColor(cat));
00641   }
00642 
00643   QColor frameColor = mSelected ? QColor( 85 + bgColor.red()*2/3,
00644                                           85 + bgColor.green()*2/3,
00645                                           85 + bgColor.blue()*2/3 )
00646                                 : bgColor.dark(115);
00647   QColor textColor = getTextColor(bgColor);
00648   p.setPen( textColor );
00649   p.setBackgroundColor( bgColor );
00650   p.setFont(KOPrefs::instance()->mAgendaViewFont);
00651   QFontMetrics fm = p.fontMetrics();
00652 
00653   int singleLineHeight = fm.boundingRect( mLabelText ).height();
00654 
00655   // case 1: do not draw text when not even a single line fits
00656   if ( //( singleLineHeight > height()-4 ) || // ignore margin, be gentle.. Even ignore 2 pixel outside the item
00657        ( width() < 16 ) ) {
00658     p.eraseRect( 0, 0, width(), height() );
00659     int x = margin;
00660     paintTodoIcon( &p, x, ft );
00661     paintFrame( &p, frameColor );
00662     return;
00663   }
00664 
00665   // Used for multi-day events to make sure the summary is on screen
00666   QRect visRect=visibleRect();
00667 
00668   // case 2: draw a single line when no more space
00669   if ( (2 * singleLineHeight) > (height() - 2 * margin) ) {
00670     p.eraseRect( 0, 0, width(), height() );
00671     int x = margin;
00672     int txtWidth = width() - margin - x;
00673     if (mIncidence->doesFloat() ) {
00674       x += visRect.left();
00675       txtWidth = visRect.right() - margin - x;
00676     }
00677 
00678     paintTodoIcon( &p, x, ft );
00679     paintFrame( &p, frameColor );
00680     int y = ((height() - 2 * ft - singleLineHeight) / 2) + fm.ascent();
00681     KWordWrap::drawFadeoutText( &p, x, y,
00682                                 txtWidth, mLabelText );
00683     return;
00684   }
00685 
00686   KWordWrap *ww = KWordWrap::formatText( fm,
00687                                          QRect(0, 0,
00688                                          width() - (2 * margin), 0),
00689                                          0,
00690                                          mLabelText );
00691   int th = ww->boundingRect().height();
00692   delete ww;
00693 
00694   // calculate the height of the full version (case 4) to test whether it is
00695   // possible
00696   QString shortH;
00697   QString longH;
00698   if ( !isMultiItem() ) {
00699     shortH = KGlobal::locale()->formatTime(mIncidence->dtStart().time());
00700     if (mIncidence->type() != "Todo")
00701       longH = i18n("%1 - %2").arg(shortH)
00702                .arg(KGlobal::locale()->formatTime(mIncidence->dtEnd().time()));
00703     else
00704       longH = shortH;
00705   } else if ( !mMultiItemInfo->mFirstMultiItem ) {
00706     shortH = KGlobal::locale()->formatTime(mIncidence->dtStart().time());
00707     longH = shortH;
00708   } else {
00709     shortH = KGlobal::locale()->formatTime(mIncidence->dtEnd().time());
00710     longH = i18n("- %1").arg(shortH);
00711   }
00712 
00713   int hlHeight = QMAX(fm.boundingRect(longH).height(),
00714      QMAX(alarmPxmp.height(), QMAX(recurPxmp.height(),
00715      QMAX(readonlyPxmp.height(), QMAX(replyPxmp.height(),
00716      QMAX(groupPxmp.height(), organizerPxmp.height()))))));
00717   bool completelyRenderable =
00718     th < (height() - 2 * ft - 2 - hlHeight);
00719   // case 3: enough for 2-5 lines, but not for the header.
00720   //         Also used for the middle days in multi-events
00721   //         or all-day events  
00722   if ( ((!completelyRenderable) && ((height() - (2 * margin)) <= (5 * singleLineHeight)) ) ||
00723        (isMultiItem() && mMultiItemInfo->mNextMultiItem && mMultiItemInfo->mFirstMultiItem) ||
00724        mIncidence->doesFloat() ) {
00725     int x = margin;
00726     int txtWidth = width() - margin - x;
00727     if (mIncidence->doesFloat() ) {
00728       x += visRect.left();
00729       txtWidth = visRect.right() - margin - x;
00730     }
00731     ww = KWordWrap::formatText( fm,
00732                                 QRect(x, 0, txtWidth,
00733                                 height() - (2 * margin)),
00734                                 0,
00735                                 mLabelText );
00736     p.eraseRect( 0, 0, width(), height() );
00737     paintTodoIcon( &p, x, ft );
00738     paintFrame( &p, frameColor );
00739     ww->drawText( &p, x, margin, Qt::AlignAuto | KWordWrap::FadeOut );
00740     delete ww;
00741     return;
00742   }
00743 
00744   // case 4: paint everything, with header:
00745   // consists of (vertically) ft + headline&icons + ft + text + margin
00746   int y = 2 * ft + hlHeight;
00747   if ( completelyRenderable )
00748     y += (height() - (2 * ft) - margin - hlHeight - th) / 2;
00749   ww = KWordWrap::formatText( fm,
00750                               QRect(0, 0, width() - (2 * margin),
00751                               height() - margin - y),
00752                               0,
00753                               mLabelText );
00754 
00755   p.eraseRect( 0, 0, width(), height() );
00756 
00757   // paint headline
00758   p.fillRect( 0, 0, width(), (ft/2) + margin + hlHeight,
00759               QBrush( frameColor ) );
00760 
00761   int x = margin;
00762   paintTodoIcon( &p, x, ft );
00763   conditionalPaint( &p, mIconAlarm, x, ft, alarmPxmp );
00764   conditionalPaint( &p, mIconRecur, x, ft, recurPxmp );
00765   conditionalPaint( &p, mIconReadonly, x, ft, readonlyPxmp );
00766   conditionalPaint( &p, mIconReply, x, ft, replyPxmp );
00767   conditionalPaint( &p, mIconGroup, x, ft, groupPxmp );
00768   conditionalPaint( &p, mIconOrganizer, x, ft, organizerPxmp );
00769 
00770   QString headline;
00771   int hw = fm.boundingRect( longH ).width();
00772   if ( hw > (width() - x - margin) ) {
00773     headline = shortH;
00774     hw = fm.boundingRect( shortH ).width();
00775     if ( hw < (width() - x - margin) )
00776       x += (width() - x - margin - hw) / 2;
00777     else
00778       headline = "";
00779   } else {
00780     headline = longH;
00781     x += (width() - x - margin - hw) / 2;
00782   }
00783   p.setBackgroundColor( frameColor );
00784   p.setPen( getTextColor( frameColor ) );
00785   KWordWrap::drawFadeoutText( &p, x, ft + fm.ascent(),
00786                               width() - margin - x, headline );
00787 
00788   // draw event text
00789   p.setBackgroundColor( bgColor );
00790   p.setPen( textColor );
00791   paintFrame( &p, frameColor );
00792   QString ws = ww->wrappedString();
00793   if ( ws.left( ws.length()-1 ).find( '\n' ) >= 0 )
00794     ww->drawText( &p, margin, y,
00795                   Qt::AlignAuto | KWordWrap::FadeOut );
00796   else
00797     ww->drawText( &p, margin + (width()-ww->boundingRect().width()-2*margin)/2,
00798                   y, Qt::AlignHCenter | KWordWrap::FadeOut );
00799   delete ww;
00800 }
00801 
KDE Logo
This file is part of the documentation for korganizer Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:38:28 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003