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 ( KOPrefs::instance()->thatIsMe( mIncidence->organizer().email() ) ) {
00086       mIconReply = false;
00087       mIconGroup = false;
00088       mIconOrganizer = true;
00089     } else {
00090       Attendee *me = mIncidence->attendeeByMails( KOPrefs::instance()->allEmails() );
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 bool KOAgendaItem::setIncidence( Incidence *i )
00121 {
00122   mIncidence = i;
00123   updateIcons();
00124   return true;
00125 }
00126 
00127 
00128 /*
00129   Return height of item in units of agenda cells
00130 */
00131 int KOAgendaItem::cellHeight() const
00132 {
00133   return mCellYBottom - mCellYTop + 1;
00134 }
00135 
00136 /*
00137   Return height of item in units of agenda cells
00138 */
00139 int KOAgendaItem::cellWidth() const
00140 {
00141   return mCellXRight - mCellXLeft + 1;
00142 }
00143 
00144 void KOAgendaItem::setItemDate( QDate qd )
00145 {
00146   mDate = qd;
00147 }
00148 
00149 void KOAgendaItem::setCellXY( int X, int YTop, int YBottom )
00150 {
00151   mCellXLeft = X;
00152   mCellYTop = YTop;
00153   mCellYBottom = YBottom;
00154 }
00155 
00156 void KOAgendaItem::setCellXRight( int xright )
00157 {
00158   mCellXRight = xright;
00159 }
00160 
00161 void KOAgendaItem::setCellX( int XLeft, int XRight )
00162 {
00163   mCellXLeft = XLeft;
00164   mCellXRight = XRight;
00165 }
00166 
00167 void KOAgendaItem::setCellY( int YTop, int YBottom )
00168 {
00169   mCellYTop = YTop;
00170   mCellYBottom = YBottom;
00171 }
00172 
00173 void KOAgendaItem::setMultiItem(KOAgendaItem *first, KOAgendaItem *prev,
00174                                 KOAgendaItem *next, KOAgendaItem *last)
00175 {
00176   if (!mMultiItemInfo) mMultiItemInfo=new MultiItemInfo;
00177   mMultiItemInfo->mFirstMultiItem = first;
00178   mMultiItemInfo->mPrevMultiItem = prev;
00179   mMultiItemInfo->mNextMultiItem = next;
00180   mMultiItemInfo->mLastMultiItem = last;
00181 }
00182 bool KOAgendaItem::isMultiItem()
00183 {
00184   return mMultiItemInfo;
00185 }
00186 KOAgendaItem* KOAgendaItem::prependMoveItem(KOAgendaItem* e)
00187 {
00188   if (!e) return e;
00189 
00190   KOAgendaItem*first=0, *last=0;
00191   if (isMultiItem()) {
00192     first=mMultiItemInfo->mFirstMultiItem;
00193     last=mMultiItemInfo->mLastMultiItem;
00194   }
00195   if (!first) first=this;
00196   if (!last) last=this;
00197 
00198   e->setMultiItem(0, 0, first, last);
00199   first->setMultiItem(e, e, first->nextMultiItem(), first->lastMultiItem() );
00200 
00201   KOAgendaItem*tmp=first->nextMultiItem();
00202   while (tmp) {
00203     tmp->setMultiItem( e, tmp->prevMultiItem(), tmp->nextMultiItem(), tmp->lastMultiItem() );
00204     tmp = tmp->nextMultiItem();
00205   }
00206 
00207   if ( mStartMoveInfo && !e->moveInfo() ) {
00208     e->mStartMoveInfo=new MultiItemInfo( *mStartMoveInfo );
00209 //    e->moveInfo()->mFirstMultiItem = moveInfo()->mFirstMultiItem;
00210 //    e->moveInfo()->mLastMultiItem = moveInfo()->mLastMultiItem;
00211     e->moveInfo()->mPrevMultiItem = 0;
00212     e->moveInfo()->mNextMultiItem = first;
00213   }
00214 
00215   if (first && first->moveInfo()) {
00216     first->moveInfo()->mPrevMultiItem = e;
00217   }
00218   return e;
00219 }
00220 
00221 KOAgendaItem* KOAgendaItem::appendMoveItem(KOAgendaItem* e)
00222 {
00223   if (!e) return e;
00224 
00225   KOAgendaItem*first=0, *last=0;
00226   if (isMultiItem()) {
00227     first=mMultiItemInfo->mFirstMultiItem;
00228     last=mMultiItemInfo->mLastMultiItem;
00229   }
00230   if (!first) first=this;
00231   if (!last) last=this;
00232 
00233   e->setMultiItem( first, last, 0, 0 );
00234   KOAgendaItem*tmp=first;
00235 
00236   while (tmp) {
00237     tmp->setMultiItem(tmp->firstMultiItem(), tmp->prevMultiItem(), tmp->nextMultiItem(), e);
00238     tmp = tmp->nextMultiItem();
00239   }
00240   last->setMultiItem( last->firstMultiItem(), last->prevMultiItem(), e, e);
00241 
00242   if ( mStartMoveInfo && !e->moveInfo() ) {
00243     e->mStartMoveInfo=new MultiItemInfo( *mStartMoveInfo );
00244 //    e->moveInfo()->mFirstMultiItem = moveInfo()->mFirstMultiItem;
00245 //    e->moveInfo()->mLastMultiItem = moveInfo()->mLastMultiItem;
00246     e->moveInfo()->mPrevMultiItem = last;
00247     e->moveInfo()->mNextMultiItem = 0;
00248   }
00249   if (last && last->moveInfo()) {
00250     last->moveInfo()->mNextMultiItem = e;
00251   }
00252   return e;
00253 }
00254 
00255 KOAgendaItem* KOAgendaItem::removeMoveItem(KOAgendaItem* e)
00256 {
00257   if (isMultiItem()) {
00258     KOAgendaItem *first = mMultiItemInfo->mFirstMultiItem;
00259     KOAgendaItem *next, *prev;
00260     KOAgendaItem *last = mMultiItemInfo->mLastMultiItem;
00261     if (!first) first = this;
00262     if (!last) last = this;
00263     if ( first==e ) {
00264       first = first->nextMultiItem();
00265       first->setMultiItem( 0, 0, first->nextMultiItem(), first->lastMultiItem() );
00266     }
00267     if ( last==e ) {
00268       last=last->prevMultiItem();
00269       last->setMultiItem( last->firstMultiItem(), last->prevMultiItem(), 0, 0 );
00270     }
00271 
00272     KOAgendaItem *tmp =  first;
00273     if ( first==last ) {
00274       delete mMultiItemInfo;
00275       tmp = 0;
00276       mMultiItemInfo = 0;
00277     }
00278     while ( tmp ) {
00279       next = tmp->nextMultiItem();
00280       prev = tmp->prevMultiItem();
00281       if ( e==next ) {
00282         next = next->nextMultiItem();
00283       }
00284       if ( e==prev ) {
00285         prev = prev->prevMultiItem();
00286       }
00287       tmp->setMultiItem((tmp==first)?0:first, (tmp==prev)?0:prev, (tmp==next)?0:next, (tmp==last)?0:last);
00288       tmp = tmp->nextMultiItem();
00289     }
00290   }
00291 
00292   return e;
00293 }
00294 
00295 
00296 void KOAgendaItem::startMove()
00297 {
00298   KOAgendaItem* first = this;
00299   if ( isMultiItem() && mMultiItemInfo->mFirstMultiItem ) {
00300     first=mMultiItemInfo->mFirstMultiItem;
00301   }
00302   first->startMovePrivate();
00303 }
00304 
00305 void KOAgendaItem::startMovePrivate()
00306 {
00307   mStartMoveInfo = new MultiItemInfo;
00308   mStartMoveInfo->mStartCellXLeft = mCellXLeft;
00309   mStartMoveInfo->mStartCellXRight = mCellXRight;
00310   mStartMoveInfo->mStartCellYTop = mCellYTop;
00311   mStartMoveInfo->mStartCellYBottom = mCellYBottom;
00312   if (mMultiItemInfo) {
00313     mStartMoveInfo->mFirstMultiItem = mMultiItemInfo->mFirstMultiItem;
00314     mStartMoveInfo->mLastMultiItem = mMultiItemInfo->mLastMultiItem;
00315     mStartMoveInfo->mPrevMultiItem = mMultiItemInfo->mPrevMultiItem;
00316     mStartMoveInfo->mNextMultiItem = mMultiItemInfo->mNextMultiItem;
00317   } else {
00318     mStartMoveInfo->mFirstMultiItem = 0;
00319     mStartMoveInfo->mLastMultiItem = 0;
00320     mStartMoveInfo->mPrevMultiItem = 0;
00321     mStartMoveInfo->mNextMultiItem = 0;
00322   }
00323   if ( isMultiItem() && mMultiItemInfo->mNextMultiItem )
00324   {
00325     mMultiItemInfo->mNextMultiItem->startMovePrivate();
00326   }
00327 }
00328 
00329 void KOAgendaItem::resetMove()
00330 {
00331   if ( mStartMoveInfo ) {
00332     if ( mStartMoveInfo->mFirstMultiItem ) {
00333       mStartMoveInfo->mFirstMultiItem->resetMovePrivate();
00334     } else {
00335       resetMovePrivate();
00336     }
00337   }
00338 }
00339 
00340 void KOAgendaItem::resetMovePrivate()
00341 {
00342   if (mStartMoveInfo) {
00343     mCellXLeft = mStartMoveInfo->mStartCellXLeft;
00344     mCellXRight = mStartMoveInfo->mStartCellXRight;
00345     mCellYTop = mStartMoveInfo->mStartCellYTop;
00346     mCellYBottom = mStartMoveInfo->mStartCellYBottom;
00347 
00348     // if we don't have mMultiItemInfo, the item didn't span two days before,
00349     // and wasn't moved over midnight, either, so we don't have to reset
00350     // anything. Otherwise, restore from mMoveItemInfo
00351     if ( mMultiItemInfo ) {
00352       // It was already a multi-day info
00353       mMultiItemInfo->mFirstMultiItem = mStartMoveInfo->mFirstMultiItem;
00354       mMultiItemInfo->mPrevMultiItem = mStartMoveInfo->mPrevMultiItem;
00355       mMultiItemInfo->mNextMultiItem = mStartMoveInfo->mNextMultiItem;
00356       mMultiItemInfo->mLastMultiItem = mStartMoveInfo->mLastMultiItem;
00357 
00358       if ( !mStartMoveInfo->mFirstMultiItem ) {
00359         // This was the first multi-item when the move started, delete all previous
00360         KOAgendaItem*toDel=mStartMoveInfo->mPrevMultiItem;
00361         KOAgendaItem*nowDel=0L;
00362         while (toDel) {
00363           nowDel=toDel;
00364           if (nowDel->moveInfo()) {
00365             toDel=nowDel->moveInfo()->mPrevMultiItem;
00366           }
00367           emit removeAgendaItem( nowDel );
00368         }
00369         mMultiItemInfo->mFirstMultiItem = 0L;
00370         mMultiItemInfo->mPrevMultiItem = 0L;
00371       }
00372       if ( !mStartMoveInfo->mLastMultiItem ) {
00373         // This was the last multi-item when the move started, delete all next
00374         KOAgendaItem*toDel=mStartMoveInfo->mNextMultiItem;
00375         KOAgendaItem*nowDel=0L;
00376         while (toDel) {
00377           nowDel=toDel;
00378           if (nowDel->moveInfo()) {
00379             toDel=nowDel->moveInfo()->mNextMultiItem;
00380           }
00381           emit removeAgendaItem( nowDel );
00382         }
00383         mMultiItemInfo->mLastMultiItem = 0L;
00384         mMultiItemInfo->mNextMultiItem = 0L;
00385       }
00386 
00387       if ( mStartMoveInfo->mFirstMultiItem==0 && mStartMoveInfo->mLastMultiItem==0 ) {
00388         // it was a single-day event before we started the move.
00389         delete mMultiItemInfo;
00390         mMultiItemInfo = 0;
00391       }
00392     }
00393     delete mStartMoveInfo;
00394     mStartMoveInfo = 0;
00395   }
00396   emit showAgendaItem( this );
00397   if ( nextMultiItem() ) {
00398     nextMultiItem()->resetMovePrivate();
00399   }
00400 }
00401 
00402 void KOAgendaItem::endMove()
00403 {
00404   KOAgendaItem*first=firstMultiItem();
00405   if (!first) first=this;
00406   first->endMovePrivate();
00407 }
00408 
00409 void KOAgendaItem::endMovePrivate()
00410 {
00411   if ( mStartMoveInfo ) {
00412     // if first, delete all previous
00413     if ( !firstMultiItem() || firstMultiItem()==this ) {
00414       KOAgendaItem*toDel=mStartMoveInfo->mPrevMultiItem;
00415       KOAgendaItem*nowDel = 0;
00416       while (toDel) {
00417         nowDel=toDel;
00418         if (nowDel->moveInfo()) {
00419           toDel=nowDel->moveInfo()->mPrevMultiItem;
00420         }
00421         emit removeAgendaItem( nowDel );
00422       }
00423     }
00424     // if last, delete all next
00425     if ( !lastMultiItem() || lastMultiItem()==this ) {
00426       KOAgendaItem*toDel=mStartMoveInfo->mNextMultiItem;
00427       KOAgendaItem*nowDel = 0;
00428       while (toDel) {
00429         nowDel=toDel;
00430         if (nowDel->moveInfo()) {
00431           toDel=nowDel->moveInfo()->mNextMultiItem;
00432         }
00433         emit removeAgendaItem( nowDel );
00434       }
00435     }
00436     // also delete the moving info
00437     delete mStartMoveInfo;
00438     mStartMoveInfo=0;
00439     if ( nextMultiItem() )
00440       nextMultiItem()->endMovePrivate();
00441   }
00442 }
00443 
00444 void KOAgendaItem::moveRelative(int dx, int dy)
00445 {
00446   int newXLeft = cellXLeft() + dx;
00447   int newXRight = cellXRight() + dx;
00448   int newYTop = cellYTop() + dy;
00449   int newYBottom = cellYBottom() + dy;
00450   setCellXY(newXLeft,newYTop,newYBottom);
00451   setCellXRight(newXRight);
00452 }
00453 
00454 void KOAgendaItem::expandTop(int dy)
00455 {
00456   int newYTop = cellYTop() + dy;
00457   int newYBottom = cellYBottom();
00458   if (newYTop > newYBottom) newYTop = newYBottom;
00459   setCellY(newYTop, newYBottom);
00460 }
00461 
00462 void KOAgendaItem::expandBottom(int dy)
00463 {
00464   int newYTop = cellYTop();
00465   int newYBottom = cellYBottom() + dy;
00466   if (newYBottom < newYTop) newYBottom = newYTop;
00467   setCellY(newYTop, newYBottom);
00468 }
00469 
00470 void KOAgendaItem::expandLeft(int dx)
00471 {
00472   int newXLeft = cellXLeft() + dx;
00473   int newXRight = cellXRight();
00474   if ( newXLeft > newXRight ) newXLeft = newXRight;
00475   setCellX( newXLeft, newXRight );
00476 }
00477 
00478 void KOAgendaItem::expandRight(int dx)
00479 {
00480   int newXLeft = cellXLeft();
00481   int newXRight = cellXRight() + dx;
00482   if ( newXRight < newXLeft ) newXRight = newXLeft;
00483   setCellX( newXLeft, newXRight );
00484 }
00485 
00486 QToolTipGroup *KOAgendaItem::toolTipGroup()
00487 {
00488   if (!mToolTipGroup) mToolTipGroup = new QToolTipGroup(0);
00489   return mToolTipGroup;
00490 }
00491 
00492 void KOAgendaItem::dragEnterEvent( QDragEnterEvent *e )
00493 {
00494 #ifndef KORG_NODND
00495   if ( ICalDrag::canDecode( e ) || VCalDrag::canDecode( e ) ) {
00496     e->ignore();
00497     return;
00498   }
00499   if ( KVCardDrag::canDecode( e ) || QTextDrag::canDecode( e ) )
00500     e->accept();
00501   else
00502     e->ignore();
00503 #endif
00504 }
00505 
00506 void KOAgendaItem::addAttendee(QString newAttendee)
00507 {
00508   kdDebug(5850) << " Email: " << newAttendee << endl;
00509   int pos = newAttendee.find("<");
00510   QString name = newAttendee.left(pos);
00511   QString email = newAttendee.mid(pos);
00512   if (!email.isEmpty()) {
00513     mIncidence->addAttendee(new Attendee(name,email));
00514   } else if (name.contains("@")) {
00515     mIncidence->addAttendee(new Attendee(name,name));
00516   } else {
00517     mIncidence->addAttendee(new Attendee(name,QString::null));
00518   }
00519 }
00520 
00521 void KOAgendaItem::dropEvent( QDropEvent *e )
00522 {
00523 #ifndef KORG_NODND
00524   QString text;
00525   QString vcards;
00526 
00527 #ifndef KORG_NOKABC
00528   if ( KVCardDrag::decode( e, vcards ) ) {
00529     KABC::VCardConverter converter;
00530 
00531     KABC::Addressee::List list = converter.parseVCards( vcards );
00532     KABC::Addressee::List::Iterator it;
00533     for ( it = list.begin(); it != list.end(); ++it ) {
00534       QString em( (*it).fullEmail() );
00535       if (em.isEmpty()) {
00536         em=(*it).realName();
00537       }
00538       addAttendee( em );
00539     }
00540   } else
00541 #endif
00542   if( QTextDrag::decode( e, text ) ) {
00543     kdDebug(5850) << "Dropped : " << text << endl;
00544     QStringList emails = QStringList::split( ",", text );
00545     for( QStringList::ConstIterator it = emails.begin(); it != emails.end();
00546          ++it ) {
00547       addAttendee( *it );
00548     }
00549   }
00550 #endif
00551 }
00552 
00553 
00554 QPtrList<KOAgendaItem> KOAgendaItem::conflictItems()
00555 {
00556   return mConflictItems;
00557 }
00558 
00559 void KOAgendaItem::setConflictItems( QPtrList<KOAgendaItem> ci )
00560 {
00561   mConflictItems = ci;
00562   KOAgendaItem *item;
00563   for ( item = mConflictItems.first(); item != 0;
00564         item = mConflictItems.next() ) {
00565     item->addConflictItem( this );
00566   }
00567 }
00568 
00569 void KOAgendaItem::addConflictItem( KOAgendaItem *ci )
00570 {
00571   if ( mConflictItems.find( ci ) < 0 ) mConflictItems.append( ci );
00572 }
00573 
00574 QString KOAgendaItem::label() const
00575 {
00576   return mLabelText;
00577 }
00578 
00579 bool KOAgendaItem::overlaps( KOrg::CellItem *o ) const
00580 {
00581   KOAgendaItem *other = static_cast<KOAgendaItem *>( o );
00582 
00583   if ( cellXLeft() <= other->cellXRight() &&
00584        cellXRight() >= other->cellXLeft() ) {
00585     if ( ( cellYTop() <= other->cellYBottom() ) &&
00586          ( cellYBottom() >= other->cellYTop() ) ) {
00587       return true;
00588     }
00589   }
00590 
00591   return false;
00592 }
00593 
00594 void KOAgendaItem::paintFrame( QPainter *p, const QColor &color )
00595 {
00596   QColor oldpen(p->pen().color());
00597   p->setPen( color );
00598   p->drawRect( 0, 0, width(), height() );
00599   p->drawRect( 1, 1, width() - 2, height() - 2 );
00600   p->setPen( oldpen );
00601 }
00602 
00603 static void conditionalPaint( QPainter *p, bool cond, int &x, int ft,
00604                               const QPixmap &pxmp )
00605 {
00606   if ( !cond ) return;
00607 
00608   p->drawPixmap( x, ft, pxmp );
00609   x += pxmp.width() + ft;
00610 }
00611 
00612 void KOAgendaItem::paintTodoIcon( QPainter *p, int &x, int ft )
00613 {
00614   static const QPixmap todoPxmp = KOGlobals::self()->smallIcon("todo");
00615   static const QPixmap completedPxmp = KOGlobals::self()->smallIcon("checkedbox");
00616   if ( mIncidence->type() != "Todo" )
00617     return;
00618   bool b = ( static_cast<Todo *>( mIncidence ) )->isCompleted();
00619   conditionalPaint( p, !b, x, ft, todoPxmp );
00620   conditionalPaint( p, b, x, ft, completedPxmp );
00621 }
00622 
00623 void KOAgendaItem::paintEvent( QPaintEvent * )
00624 {
00625   QPainter p( this );
00626   const int ft = 2; // frame thickness for layout, see paintFrame()
00627   const int margin = 1 + ft; // frame + space between frame and content
00628   bool isTodoOverdue = false;
00629 
00630   static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon("bell");
00631   static const QPixmap recurPxmp = KOGlobals::self()->smallIcon("recur");
00632   static const QPixmap readonlyPxmp = KOGlobals::self()->smallIcon("readonlyevent");
00633   static const QPixmap replyPxmp = KOGlobals::self()->smallIcon("mail_reply");
00634   static const QPixmap groupPxmp = KOGlobals::self()->smallIcon("groupevent");
00635   static const QPixmap organizerPxmp = KOGlobals::self()->smallIcon("organizer");
00636 
00637   QColor bgColor;
00638   if ( (mIncidence->type() == "Todo") &&
00639        ( !((static_cast<Todo*>(mIncidence))->isCompleted()) &&
00640          ((static_cast<Todo*>(mIncidence))->dtDue() < QDate::currentDate()) ) ) {
00641     bgColor = KOPrefs::instance()->mTodoOverdueColor;
00642     isTodoOverdue = true;
00643   } else {
00644     QStringList categories = mIncidence->categories();
00645     QString cat = categories.first();
00646     if (cat.isEmpty())
00647       bgColor = KOPrefs::instance()->mEventColor;
00648     else
00649       bgColor = *(KOPrefs::instance()->categoryColor(cat));
00650   }
00651 
00652   QColor frameColor = mSelected ? QColor( 85 + bgColor.red()*2/3,
00653                                           85 + bgColor.green()*2/3,
00654                                           85 + bgColor.blue()*2/3 )
00655                                 : bgColor.dark(115);
00656   QColor textColor = getTextColor(bgColor);
00657   p.setPen( textColor );
00658   p.setBackgroundColor( bgColor );
00659   p.setFont(KOPrefs::instance()->mAgendaViewFont);
00660   QFontMetrics fm = p.fontMetrics();
00661 
00662   int singleLineHeight = fm.boundingRect( mLabelText ).height();
00663 
00664   // case 1: do not draw text when not even a single line fits
00665   // Don't do this any more, always try to print out the text. Even if
00666   // it's just a few pixel, one can still guess the whole text from just four pixels' height!
00667   if ( //( singleLineHeight > height()-4 ) || // ignore margin, be gentle.. Even ignore 2 pixel outside the item
00668        ( width() < 16 ) ) {
00669     p.eraseRect( 0, 0, width(), height() );
00670     int x = margin;
00671     paintTodoIcon( &p, x, ft );
00672     paintFrame( &p, frameColor );
00673     return;
00674   }
00675 
00676   // Used for multi-day events to make sure the summary is on screen
00677   QRect visRect=visibleRect();
00678 
00679   // case 2: draw a single line when no more space
00680   if ( (2 * singleLineHeight) > (height() - 2 * margin) ) {
00681     p.eraseRect( 0, 0, width(), height() );
00682     int x = margin;
00683     int txtWidth = width() - margin - x;
00684     if (mIncidence->doesFloat() ) {
00685       x += visRect.left();
00686       txtWidth = visRect.right() - margin - x;
00687     }
00688 
00689     paintTodoIcon( &p, x, ft );
00690     paintFrame( &p, frameColor );
00691     int y = ((height() - 2 * ft - singleLineHeight) / 2) + fm.ascent();
00692     KWordWrap::drawFadeoutText( &p, x, y,
00693                                 txtWidth, mLabelText );
00694     return;
00695   }
00696 
00697   KWordWrap *ww = KWordWrap::formatText( fm,
00698                                          QRect(0, 0,
00699                                          width() - (2 * margin), -1),
00700                                          0,
00701                                          mLabelText );
00702   int th = ww->boundingRect().height();
00703   delete ww;
00704 
00705   // calculate the height of the full version (case 4) to test whether it is
00706   // possible
00707   QString shortH;
00708   QString longH;
00709   if ( !isMultiItem() ) {
00710     shortH = KGlobal::locale()->formatTime(mIncidence->dtStart().time());
00711     if (mIncidence->type() != "Todo")
00712       longH = i18n("%1 - %2").arg(shortH)
00713                .arg(KGlobal::locale()->formatTime(mIncidence->dtEnd().time()));
00714     else
00715       longH = shortH;
00716   } else if ( !mMultiItemInfo->mFirstMultiItem ) {
00717     shortH = KGlobal::locale()->formatTime(mIncidence->dtStart().time());
00718     longH = shortH;
00719   } else {
00720     shortH = KGlobal::locale()->formatTime(mIncidence->dtEnd().time());
00721     longH = i18n("- %1").arg(shortH);
00722   }
00723 
00724   int hlHeight = QMAX(fm.boundingRect(longH).height(),
00725      QMAX(alarmPxmp.height(), QMAX(recurPxmp.height(),
00726      QMAX(readonlyPxmp.height(), QMAX(replyPxmp.height(),
00727      QMAX(groupPxmp.height(), organizerPxmp.height()))))));
00728   bool completelyRenderable =
00729     th < (height() - 2 * ft - 2 - hlHeight);
00730   // case 3: enough for 2-5 lines, but not for the header.
00731   //         Also used for the middle days in multi-events
00732   //         or all-day events, or overdue todo items
00733   if ( ((!completelyRenderable) && ((height() - (2 * margin)) <= (5 * singleLineHeight)) ) ||
00734        (isMultiItem() && mMultiItemInfo->mNextMultiItem && mMultiItemInfo->mFirstMultiItem) ||
00735        mIncidence->doesFloat() ||
00736        isTodoOverdue ) {
00737     int x = margin;
00738     int txtWidth = width() - margin - x;
00739     if (mIncidence->doesFloat() ) {
00740       x += visRect.left();
00741       txtWidth = visRect.right() - margin - x;
00742     }
00743     ww = KWordWrap::formatText( fm,
00744                                 QRect(x, 0, txtWidth,
00745                                 height() - (2 * margin)),
00746                                 0,
00747                                 mLabelText );
00748     p.eraseRect( 0, 0, width(), height() );
00749     paintTodoIcon( &p, x, ft );
00750     paintFrame( &p, frameColor );
00751     ww->drawText( &p, x, margin, Qt::AlignAuto | KWordWrap::FadeOut );
00752     delete ww;
00753     return;
00754   }
00755 
00756   // case 4: paint everything, with header:
00757   // consists of (vertically) ft + headline&icons + ft + text + margin
00758   int y = 2 * ft + hlHeight;
00759   if ( completelyRenderable )
00760     y += (height() - (2 * ft) - margin - hlHeight - th) / 2;
00761   ww = KWordWrap::formatText( fm,
00762                               QRect(0, 0, width() - (2 * margin),
00763                               height() - margin - y),
00764                               0,
00765                               mLabelText );
00766 
00767   p.eraseRect( 0, 0, width(), height() );
00768 
00769   // paint headline
00770   p.fillRect( 0, 0, width(), (ft/2) + margin + hlHeight,
00771               QBrush( frameColor ) );
00772 
00773   int x = margin;
00774   paintTodoIcon( &p, x, ft );
00775   conditionalPaint( &p, mIconAlarm, x, ft, alarmPxmp );
00776   conditionalPaint( &p, mIconRecur, x, ft, recurPxmp );
00777   conditionalPaint( &p, mIconReadonly, x, ft, readonlyPxmp );
00778   conditionalPaint( &p, mIconReply, x, ft, replyPxmp );
00779   conditionalPaint( &p, mIconGroup, x, ft, groupPxmp );
00780   conditionalPaint( &p, mIconOrganizer, x, ft, organizerPxmp );
00781 
00782   QString headline;
00783   int hw = fm.boundingRect( longH ).width();
00784   if ( hw > (width() - x - margin) ) {
00785     headline = shortH;
00786     hw = fm.boundingRect( shortH ).width();
00787     if ( hw < (width() - x - margin) )
00788       x += (width() - x - margin - hw) / 2;
00789   } else {
00790     headline = longH;
00791     x += (width() - x - margin - hw) / 2;
00792   }
00793   p.setBackgroundColor( frameColor );
00794   p.setPen( getTextColor( frameColor ) );
00795   KWordWrap::drawFadeoutText( &p, x, ft + fm.ascent(),
00796                               width() - margin - x, headline );
00797 
00798   // draw event text
00799   p.setBackgroundColor( bgColor );
00800   p.setPen( textColor );
00801   paintFrame( &p, frameColor );
00802   QString ws = ww->wrappedString();
00803   if ( ws.left( ws.length()-1 ).find( '\n' ) >= 0 )
00804     ww->drawText( &p, margin, y,
00805                   Qt::AlignAuto | KWordWrap::FadeOut );
00806   else
00807     ww->drawText( &p, margin + (width()-ww->boundingRect().width()-2*margin)/2,
00808                   y, Qt::AlignHCenter | KWordWrap::FadeOut );
00809   delete ww;
00810 }
00811 
KDE Logo
This file is part of the documentation for korganizer Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 22:45:23 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003