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("@")) {
    mIncidence->addAttendee(new Attendee(name,name));
  } else {
    mIncidence->addAttendee(new Attendee(name,QString::null));
  }
}

void KOAgendaItem::dropEvent( QDropEvent *e )
{
#ifndef KORG_NODND
  QString text;
  QString vcards;

#ifndef KORG_NOKABC
  if ( KVCardDrag::decode( e, vcards ) ) {
    KABC::VCardConverter converter;

    KABC::Addressee::List list = converter.parseVCards( vcards );
    KABC::Addressee::List::Iterator it;
    for ( it = list.begin(); it != list.end(); ++it ) {
      QString em( (*it).fullEmail() );
      if (em.isEmpty()) {
        em=(*it).realName();
      }
      addAttendee( em );
    }
  } else
#endif
  if( QTextDrag::decode( e, text ) ) {
    kdDebug(5850) << "Dropped : " << text << endl;
00508     QStringList emails = QStringList::split( ",", text );
00509     for( QStringList::ConstIterator it = emails.begin(); it != emails.end();
00510          ++it ) {
00511       addAttendee( *it );
00512     }
00513   }
00514 #endif
00515 }
00516 
00517 
00518 QPtrList<KOAgendaItem> KOAgendaItem::conflictItems()
00519 {
00520   return mConflictItems;
00521 }
00522 
00523 void KOAgendaItem::setConflictItems( QPtrList<KOAgendaItem> ci )
00524 {
00525   mConflictItems = ci;
00526   KOAgendaItem *item;
00527   for ( item = mConflictItems.first(); item != 0;
00528         item = mConflictItems.next() ) {
00529     item->addConflictItem( this );
00530   }
00531 }
00532 
00533 void KOAgendaItem::addConflictItem( KOAgendaItem *ci )
00534 {
00535   if ( mConflictItems.find( ci ) < 0 ) mConflictItems.append( ci );
00536 }
00537 
00538 QString KOAgendaItem::label() const
00539 {
00540   return mLabelText;
00541 }
00542 
00543 bool KOAgendaItem::overlaps( KOrg::CellItem *o ) const
00544 {
00545   KOAgendaItem *other = static_cast<KOAgendaItem *>( o );
00546 
00547   if ( cellXLeft() <= other->cellXRight() &&
00548        cellXRight() >= other->cellXLeft() ) {
00549     if ( ( cellYTop() <= other->cellYBottom() ) &&
00550          ( cellYBottom() >= other->cellYTop() ) ) {
00551       return true;
00552     }
00553   }
00554 
00555   return false;
00556 }
00557 
00558 void KOAgendaItem::paintFrame( QPainter *p, const QColor &color )
00559 {
00560   QColor oldpen(p->pen().color());
00561   p->setPen( color );
00562   p->drawRect( 0, 0, width(), height() );
00563   p->drawRect( 1, 1, width() - 2, height() - 2 );
00564   p->setPen( oldpen );
00565 }
00566 
00567 static void conditionalPaint( QPainter *p, bool cond, int &x, int ft,
00568                               const QPixmap &pxmp )
00569 {
00570   if ( !cond ) return;
00571 
00572   p->drawPixmap( x, ft, pxmp );
00573   x += pxmp.width() + ft;
00574 }
00575 
00576 void KOAgendaItem::paintTodoIcon( QPainter *p, int &x, int ft )
00577 {
00578   static const QPixmap todoPxmp = KOGlobals::self()->smallIcon("todo");
00579   static const QPixmap completedPxmp = KOGlobals::self()->smallIcon("checkedbox");
00580   if ( mIncidence->type() != "Todo" )
00581     return;
00582   bool b = ( static_cast<Todo *>( mIncidence ) )->isCompleted();
00583   conditionalPaint( p, b, x, ft, todoPxmp );
00584   conditionalPaint( p, !b, x, ft, completedPxmp );
00585 }
00586 
00587 void KOAgendaItem::paintEvent( QPaintEvent * )
00588 {
00589   QPainter p( this );
00590   const int ft = 2; // frame thickness for layout, see paintFrame()
00591   const int margin = 1 + ft; // frame + space between frame and content
00592 
00593   static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon("bell");
00594   static const QPixmap recurPxmp = KOGlobals::self()->smallIcon("recur");
00595   static const QPixmap readonlyPxmp = KOGlobals::self()->smallIcon("readonlyevent");
00596   static const QPixmap replyPxmp = KOGlobals::self()->smallIcon("mail_reply");
00597   static const QPixmap groupPxmp = KOGlobals::self()->smallIcon("groupevent");
00598   static const QPixmap organizerPxmp = KOGlobals::self()->smallIcon("organizer");
00599 
00600   QColor bgColor;
00601   if ( (mIncidence->type() == "Todo") &&
00602        ( !((static_cast<Todo*>(mIncidence))->isCompleted()) &&
00603          ((static_cast<Todo*>(mIncidence))->dtDue() < QDate::currentDate()) ) )
00604     bgColor = KOPrefs::instance()->mTodoOverdueColor;
00605   else {
00606     QStringList categories = mIncidence->categories();
00607     QString cat = categories.first();
00608     if (cat.isEmpty())
00609       bgColor = KOPrefs::instance()->mEventColor;
00610     else
00611       bgColor = *(KOPrefs::instance()->categoryColor(cat));
00612   }
00613 
00614   QColor frameColor = mSelected ? QColor( 85 + bgColor.red()*2/3,
00615                                           85 + bgColor.green()*2/3,
00616                                           85 + bgColor.blue()*2/3 )
00617                                 : bgColor.dark(115);
00618   QColor textColor = getTextColor(bgColor);
00619   p.setPen( textColor );
00620   p.setBackgroundColor( bgColor );
00621   p.setFont(KOPrefs::instance()->mAgendaViewFont);
00622   QFontMetrics fm = p.fontMetrics();
00623 
00624   int singleLineHeight = fm.boundingRect( mLabelText ).height();
00625 
00626   // case 1: do not draw text when not even a single line fits
00627   if ( //( singleLineHeight > height()-4 ) || // ignore margin, be gentle.. Even ignore 2 pixel outside the item
00628        ( width() < 16 ) ) {
00629     p.eraseRect( 0, 0, width(), height() );
00630     int x = margin;
00631     paintTodoIcon( &p, x, ft );
00632     paintFrame( &p, frameColor );
00633     return;
00634   }
00635 
00636   // Used for multi-day events to make sure the summary is on screen
00637   QRect visRect=visibleRect();
00638 
00639   // case 2: draw a single line when no more space
00640   if ( (2 * singleLineHeight) > (height() - 2 * margin) ) {
00641     p.eraseRect( 0, 0, width(), height() );
00642     int x = margin;
00643     int txtWidth = width() - margin - x;
00644     if (mIncidence->doesFloat() ) {
00645       x += visRect.left();
00646       txtWidth = visRect.right() - margin - x;
00647     }
00648 
00649     paintTodoIcon( &p, x, ft );
00650     paintFrame( &p, frameColor );
00651     int y = ((height() - 2 * ft - singleLineHeight) / 2) + fm.ascent();
00652     KWordWrap::drawFadeoutText( &p, x, y,
00653                                 txtWidth, mLabelText );
00654     return;
00655   }
00656 
00657   KWordWrap *ww = KWordWrap::formatText( fm,
00658                                          QRect(0, 0,
00659                                          width() - (2 * margin), 0),
00660                                          0,
00661                                          mLabelText );
00662   int th = ww->boundingRect().height();
00663   delete ww;
00664 
00665   // calculate the height of the full version (case 4) to test whether it is
00666   // possible
00667   QString shortH;
00668   QString longH;
00669   if ( !isMultiItem() ) {
00670     shortH = KGlobal::locale()->formatTime(mIncidence->dtStart().time());
00671     if (mIncidence->type() != "Todo")
00672       longH = i18n("%1 - %2").arg(shortH)
00673                .arg(KGlobal::locale()->formatTime(mIncidence->dtEnd().time()));
00674     else
00675       longH = shortH;
00676   } else if ( !mMultiItemInfo->mFirstMultiItem ) {
00677     shortH = KGlobal::locale()->formatTime(mIncidence->dtStart().time());
00678     longH = shortH;
00679   } else {
00680     shortH = KGlobal::locale()->formatTime(mIncidence->dtEnd().time());
00681     longH = i18n("- %1").arg(shortH);
00682   }
00683 
00684   int hlHeight = QMAX(fm.boundingRect(longH).height(),
00685      QMAX(alarmPxmp.height(), QMAX(recurPxmp.height(),
00686      QMAX(readonlyPxmp.height(), QMAX(replyPxmp.height(),
00687      QMAX(groupPxmp.height(), organizerPxmp.height()))))));
00688   bool completelyRenderable =
00689     th < (height() - 2 * ft - 2 - hlHeight);
00690   // case 3: enough for 2-5 lines, but not for the header.
00691   //         Also used for the middle days in multi-events
00692   //         or all-day events  
00693   if ( ((!completelyRenderable) && ((height() - (2 * margin)) <= (5 * singleLineHeight)) ) ||
00694        (isMultiItem() && mMultiItemInfo->mNextMultiItem && mMultiItemInfo->mFirstMultiItem) ||
00695        mIncidence->doesFloat() ) {
00696     int x = margin;
00697     int txtWidth = width() - margin - x;
00698     if (mIncidence->doesFloat() ) {
00699       x += visRect.left();
00700       txtWidth = visRect.right() - margin - x;
00701     }
00702     ww = KWordWrap::formatText( fm,
00703                                 QRect(x, 0, txtWidth,
00704                                 height() - (2 * margin)),
00705                                 0,
00706                                 mLabelText );
00707     p.eraseRect( 0, 0, width(), height() );
00708     paintTodoIcon( &p, x, ft );
00709     paintFrame( &p, frameColor );
00710     ww->drawText( &p, x, margin, Qt::AlignAuto | KWordWrap::FadeOut );
00711     delete ww;
00712     return;
00713   }
00714 
00715   // case 4: paint everything, with header:
00716   // consists of (vertically) ft + headline&icons + ft + text + margin
00717   int y = 2 * ft + hlHeight;
00718   if ( completelyRenderable )
00719     y += (height() - (2 * ft) - margin - hlHeight - th) / 2;
00720   ww = KWordWrap::formatText( fm,
00721                               QRect(0, 0, width() - (2 * margin),
00722                               height() - margin - y),
00723                               0,
00724                               mLabelText );
00725 
00726   p.eraseRect( 0, 0, width(), height() );
00727 
00728   // paint headline
00729   p.fillRect( 0, 0, width(), (ft/2) + margin + hlHeight,
00730               QBrush( frameColor ) );
00731 
00732   int x = margin;
00733   paintTodoIcon( &p, x, ft );
00734   conditionalPaint( &p, mIconAlarm, x, ft, alarmPxmp );
00735   conditionalPaint( &p, mIconRecur, x, ft, recurPxmp );
00736   conditionalPaint( &p, mIconReadonly, x, ft, readonlyPxmp );
00737   conditionalPaint( &p, mIconReply, x, ft, replyPxmp );
00738   conditionalPaint( &p, mIconGroup, x, ft, groupPxmp );
00739   conditionalPaint( &p, mIconOrganizer, x, ft, organizerPxmp );
00740 
00741   QString headline;
00742   int hw = fm.boundingRect( longH ).width();
00743   if ( hw > (width() - x - margin) ) {
00744     headline = shortH;
00745     hw = fm.boundingRect( shortH ).width();
00746     if ( hw < (width() - x - margin) )
00747       x += (width() - x - margin - hw) / 2;
00748     else
00749       headline = "";
00750   } else {
00751     headline = longH;
00752     x += (width() - x - margin - hw) / 2;
00753   }
00754   p.setBackgroundColor( frameColor );
00755   p.setPen( getTextColor( frameColor ) );
00756   KWordWrap::drawFadeoutText( &p, x, ft + fm.ascent(),
00757                               width() - margin - x, headline );
00758 
00759   // draw event text
00760   p.setBackgroundColor( bgColor );
00761   p.setPen( textColor );
00762   paintFrame( &p, frameColor );
00763   QString ws = ww->wrappedString();
00764   if ( ws.left( ws.length()-1 ).find( '\n' ) >= 0 )
00765     ww->drawText( &p, margin, y,
00766                   Qt::AlignAuto | KWordWrap::FadeOut );
00767   else
00768     ww->drawText( &p, margin + (width()-ww->boundingRect().width()-2*margin)/2,
00769                   y, Qt::AlignHCenter | KWordWrap::FadeOut );
00770   delete ww;
00771 }
00772 
00773 
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 Mon Apr 26 23:23:33 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003