00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <qpopupmenu.h>
00027 #include <qfont.h>
00028 #include <qfontmetrics.h>
00029 #include <qkeycode.h>
00030 #include <qhbox.h>
00031 #include <qvbox.h>
00032 #include <qpushbutton.h>
00033 #include <qtooltip.h>
00034 #include <qpainter.h>
00035 #include <qcursor.h>
00036 #include <qlistbox.h>
00037 #include <qlayout.h>
00038 #include <qlabel.h>
00039
00040 #include <kdebug.h>
00041 #include <klocale.h>
00042 #include <kglobal.h>
00043 #include <kconfig.h>
00044 #include <kiconloader.h>
00045 #include <kwordwrap.h>
00046
00047 #include <kcalendarsystem.h>
00048 #include <libkcal/calfilter.h>
00049 #include <libkcal/calendar.h>
00050 #include <libkcal/incidenceformatter.h>
00051 #include <libkcal/calendarresources.h>
00052
00053 #include "koprefs.h"
00054 #include "koglobals.h"
00055 #include "koincidencetooltip.h"
00056 #include "koeventpopupmenu.h"
00057 #include "kohelper.h"
00058
00059 #include "komonthview.h"
00060 #include "komonthview.moc"
00061
00062
00063
00064 KOMonthCellToolTip::KOMonthCellToolTip( QWidget *parent,
00065 Calendar *calendar,
00066 KNoScrollListBox *lv )
00067 : QToolTip( parent ), mCalendar( calendar )
00068 {
00069 eventlist = lv;
00070 }
00071
00072 void KOMonthCellToolTip::maybeTip( const QPoint &pos )
00073 {
00074 QRect r;
00075 QListBoxItem *it = eventlist->itemAt( pos );
00076 MonthViewItem *i = static_cast<MonthViewItem*>( it );
00077
00078 if( i && KOPrefs::instance()->mEnableToolTips ) {
00079
00080 r=eventlist->itemRect( it );
00081
00082 QString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->incidence() ) );
00083 if ( !tipText.isEmpty() ) {
00084 tip( r, tipText );
00085 }
00086 }
00087 }
00088
00089 KNoScrollListBox::KNoScrollListBox( QWidget *parent, const char *name )
00090 : QListBox( parent, name ),
00091 mSqueezing( false )
00092 {
00093 QPalette pal = palette();
00094 pal.setColor( QColorGroup::Foreground, KOPrefs::instance()->agendaBgColor().dark( 150 ) );
00095 pal.setColor( QColorGroup::Base, KOPrefs::instance()->agendaBgColor() );
00096 setPalette( pal );
00097 }
00098
00099 void KNoScrollListBox::setBackground( bool primary, bool workDay )
00100 {
00101 QColor color;
00102 if ( workDay ) {
00103 color = KOPrefs::instance()->workingHoursColor();
00104 } else {
00105 color = KOPrefs::instance()->agendaBgColor();
00106 }
00107
00108 QPalette pal = palette();
00109 if ( primary ) {
00110 pal.setColor( QColorGroup::Base, color );
00111 } else {
00112 pal.setColor( QColorGroup::Base, color.dark( 115 ) );
00113 }
00114 setPalette( pal );
00115 }
00116
00117 void KNoScrollListBox::keyPressEvent( QKeyEvent *e )
00118 {
00119 switch( e->key() ) {
00120 case Key_Right:
00121 scrollBy( 4, 0 );
00122 break;
00123 case Key_Left:
00124 scrollBy( -4, 0 );
00125 break;
00126 case Key_Up:
00127 if ( !count() ) break;
00128 setCurrentItem( ( currentItem() + count() - 1 ) % count() );
00129 if ( !itemVisible( currentItem() ) ) {
00130 if ( (unsigned int)currentItem() == ( count() - 1 ) ) {
00131 setTopItem( currentItem() - numItemsVisible() + 1 );
00132 } else {
00133 setTopItem( topItem() - 1 );
00134 }
00135 }
00136 break;
00137 case Key_Down:
00138 if ( !count() ) break;
00139 setCurrentItem( ( currentItem() + 1 ) % count() );
00140 if( !itemVisible( currentItem() ) ) {
00141 if( currentItem() == 0 ) {
00142 setTopItem( 0 );
00143 } else {
00144 setTopItem( topItem() + 1 );
00145 }
00146 }
00147 case Key_Shift:
00148 emit shiftDown();
00149 break;
00150 default:
00151 break;
00152 }
00153 }
00154
00155 void KNoScrollListBox::keyReleaseEvent( QKeyEvent *e )
00156 {
00157 switch( e->key() ) {
00158 case Key_Shift:
00159 emit shiftUp();
00160 break;
00161 default:
00162 break;
00163 }
00164 }
00165
00166 void KNoScrollListBox::mousePressEvent( QMouseEvent *e )
00167 {
00168 QListBox::mousePressEvent( e );
00169
00170 if ( e->button() == RightButton ) {
00171 emit rightClick();
00172 }
00173 }
00174
00175 void KNoScrollListBox::contentsMouseDoubleClickEvent ( QMouseEvent * e )
00176 {
00177 QListBox::contentsMouseDoubleClickEvent( e );
00178 QListBoxItem *item = itemAt( e->pos() );
00179 if ( !item ) {
00180 emit doubleClicked( item );
00181 }
00182 }
00183
00184 void KNoScrollListBox::resizeEvent( QResizeEvent *e )
00185 {
00186 bool s = count() && ( maxItemWidth() > e->size().width() );
00187 if ( mSqueezing || s )
00188 triggerUpdate( false );
00189
00190 mSqueezing = s;
00191 QListBox::resizeEvent( e );
00192 }
00193
00194 MonthViewItem::MonthViewItem( Incidence *incidence, const QDateTime &qd,
00195 const QString & s ) : QListBoxItem()
00196 {
00197 setText( s );
00198
00199 mIncidence = incidence;
00200 mDateTime = qd;
00201
00202 mEventPixmap = KOGlobals::self()->smallIcon( "appointment" );
00203 mTodoPixmap = KOGlobals::self()->smallIcon( "todo" );
00204 mTodoDonePixmap = KOGlobals::self()->smallIcon( "checkedbox" );
00205 mAlarmPixmap = KOGlobals::self()->smallIcon( "bell" );
00206 mRecurPixmap = KOGlobals::self()->smallIcon( "recur" );
00207 mReplyPixmap = KOGlobals::self()->smallIcon( "mail_reply" );
00208
00209 mEvent = false;
00210 mTodo = false;
00211 mTodoDone = false;
00212 mRecur = false;
00213 mAlarm = false;
00214 mReply = false;
00215 }
00216
00217 QColor MonthViewItem::catColor() const
00218 {
00219 QColor retColor;
00220 if ( !mIncidence ) {
00221 return retColor;
00222 }
00223
00224 QStringList categories = mIncidence->categories();
00225 QString cat;
00226 if ( !categories.isEmpty() ) {
00227 cat = categories.first();
00228 }
00229 if ( cat.isEmpty() ) {
00230 retColor = KOPrefs::instance()->unsetCategoryColor();
00231 } else {
00232 retColor = *( KOPrefs::instance()->categoryColor( cat ) );
00233 }
00234 return retColor;
00235 }
00236
00237 void MonthViewItem::paint( QPainter *p )
00238 {
00239 #if QT_VERSION >= 0x030000
00240 bool sel = isSelected();
00241 #else
00242 bool sel = selected();
00243 #endif
00244
00245 QColor bgColor = QColor();
00246 if ( mIncidence && mTodo ) {
00247 if ( static_cast<Todo*>( mIncidence )->isOverdue() ) {
00248 bgColor = KOPrefs::instance()->todoOverdueColor();
00249 } else if ( static_cast<Todo*>( mIncidence )->dtDue().date() == QDate::currentDate() ) {
00250 bgColor = KOPrefs::instance()->todoDueTodayColor();
00251 }
00252 }
00253
00254 if ( !bgColor.isValid() ) {
00255 if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceOnly ||
00256 KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceInsideCategoryOutside ) {
00257 bgColor = resourceColor();
00258 } else {
00259 bgColor = catColor();
00260 }
00261
00262 if ( !bgColor.isValid() ) {
00263 bgColor = palette().color( QPalette::Normal,
00264 sel ? QColorGroup::Highlight :
00265 QColorGroup::Background );
00266 }
00267 }
00268
00269 QColor frameColor;
00270 if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceOnly ||
00271 KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) {
00272 frameColor = resourceColor();
00273 } else {
00274 frameColor = catColor();
00275 }
00276
00277 if ( mIncidence ) {
00278 if ( mIncidence->categories().isEmpty() &&
00279 KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceInsideCategoryOutside ) {
00280 frameColor = bgColor;
00281 }
00282
00283 if ( mIncidence->categories().isEmpty() &&
00284 KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) {
00285 bgColor = frameColor;
00286 }
00287 }
00288
00289 if ( !frameColor.isValid() ) {
00290 frameColor = palette().color( QPalette::Normal,
00291 sel ? QColorGroup::Highlight :
00292 QColorGroup::Foreground );
00293 } else {
00294 frameColor = frameColor.dark( 115 );
00295 }
00296
00297
00298 p->setBackgroundColor( frameColor );
00299 p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) );
00300 int offset = 2;
00301 p->setBackgroundColor( bgColor );
00302 p->eraseRect( offset, offset, listBox()->maxItemWidth()-2*offset, height( listBox() )-2*offset );
00303
00304 int x = 3;
00305
00306
00307
00308
00309
00310 if ( mTodo ) {
00311 p->drawPixmap( x, 0, mTodoPixmap );
00312 x += mTodoPixmap.width() + 2;
00313 }
00314 if ( mTodoDone ) {
00315 p->drawPixmap( x, 0, mTodoDonePixmap );
00316 x += mTodoPixmap.width() + 2;
00317 }
00318 if ( mRecur ) {
00319 p->drawPixmap( x, 0, mRecurPixmap );
00320 x += mRecurPixmap.width() + 2;
00321 }
00322 if ( mAlarm ) {
00323 p->drawPixmap( x, 0, mAlarmPixmap );
00324 x += mAlarmPixmap.width() + 2;
00325 }
00326 if ( mReply ) {
00327 p->drawPixmap(x, 0, mReplyPixmap );
00328 x += mReplyPixmap.width() + 2;
00329 }
00330 QFontMetrics fm = p->fontMetrics();
00331 int yPos;
00332 int pmheight = QMAX( mRecurPixmap.height(),
00333 QMAX( mAlarmPixmap.height(), mReplyPixmap.height() ) );
00334 if( pmheight < fm.height() )
00335 yPos = fm.ascent() + fm.leading()/2;
00336 else
00337 yPos = pmheight/2 - fm.height()/2 + fm.ascent();
00338 QColor textColor = getTextColor( bgColor );
00339 p->setPen( textColor );
00340
00341 KWordWrap::drawFadeoutText( p, x, yPos, listBox()->width() - x, text() );
00342 }
00343
00344 int MonthViewItem::height( const QListBox *lb ) const
00345 {
00346 return QMAX( QMAX( mRecurPixmap.height(), mReplyPixmap.height() ),
00347 QMAX( mAlarmPixmap.height(), lb->fontMetrics().lineSpacing()+1) );
00348 }
00349
00350 int MonthViewItem::width( const QListBox *lb ) const
00351 {
00352 int x = 3;
00353 if( mRecur ) {
00354 x += mRecurPixmap.width()+2;
00355 }
00356 if( mAlarm ) {
00357 x += mAlarmPixmap.width()+2;
00358 }
00359 if( mReply ) {
00360 x += mReplyPixmap.width()+2;
00361 }
00362
00363 return( x + lb->fontMetrics().boundingRect( text() ).width() + 1 );
00364 }
00365
00366
00367 MonthViewCell::MonthViewCell( KOMonthView *parent)
00368 : QWidget( parent ),
00369 mMonthView( parent ), mPrimary( false ), mHoliday( false )
00370 {
00371 QVBoxLayout *topLayout = new QVBoxLayout( this );
00372
00373 mLabel = new QLabel( this );
00374 mLabel->setFrameStyle( QFrame::Panel | QFrame::Plain );
00375 mLabel->setLineWidth( 1 );
00376 mLabel->setAlignment( AlignCenter );
00377
00378 mItemList = new KNoScrollListBox( this );
00379 mItemList->setMinimumSize( 10, 10 );
00380 mItemList->setFrameStyle( QFrame::Panel | QFrame::Plain );
00381 mItemList->setLineWidth( 1 );
00382
00383 new KOMonthCellToolTip( mItemList->viewport(),
00384 mCalendar,
00385 static_cast<KNoScrollListBox *>( mItemList ) );
00386
00387 topLayout->addWidget( mItemList );
00388
00389 mLabel->raise();
00390
00391 mStandardPalette = palette();
00392
00393 enableScrollBars( false );
00394
00395 updateConfig();
00396
00397 connect( mItemList, SIGNAL( doubleClicked( QListBoxItem *) ),
00398 SLOT( defaultAction( QListBoxItem * ) ) );
00399 connect( mItemList, SIGNAL( rightButtonPressed( QListBoxItem *,
00400 const QPoint &) ),
00401 SLOT( contextMenu( QListBoxItem * ) ) );
00402 connect( mItemList, SIGNAL( clicked( QListBoxItem * ) ),
00403 SLOT( select() ) );
00404 }
00405
00406 void MonthViewCell::setDate( const QDate &date )
00407 {
00408
00409
00410 mDate = date;
00411
00412 setFrameWidth();
00413
00414 QString text;
00415 if ( KOGlobals::self()->calendarSystem()->day( date ) == 1 ) {
00416 text = i18n("'Month day' for month view cells", "%1 %2")
00417 .arg( KOGlobals::self()->calendarSystem()->monthName( date, true ) )
00418 .arg( KOGlobals::self()->calendarSystem()->day(mDate) );
00419 QFontMetrics fm( mLabel->font() );
00420 mLabel->resize( mLabelSize + QSize( fm.width( text ), 0 ) );
00421 } else {
00422 mLabel->resize( mLabelSize );
00423 text = QString::number( KOGlobals::self()->calendarSystem()->day(mDate) );
00424 }
00425 mLabel->setText( text );
00426
00427 resizeEvent( 0 );
00428 }
00429
00430 QDate MonthViewCell::date() const
00431 {
00432 return mDate;
00433 }
00434
00435 void MonthViewCell::setFrameWidth()
00436 {
00437
00438 if ( mDate == QDate::currentDate() )
00439 mItemList->setLineWidth( 3 );
00440 else
00441 mItemList->setLineWidth( 1 );
00442 }
00443
00444 void MonthViewCell::setPrimary( bool primary )
00445 {
00446 mPrimary = primary;
00447
00448 if ( mPrimary ) {
00449 mLabel->setBackgroundMode( PaletteBase );
00450 } else {
00451 mLabel->setBackgroundMode( PaletteBackground );
00452 }
00453
00454 mItemList->setBackground( mPrimary, KOGlobals::self()->isWorkDay( mDate ) );
00455 }
00456
00457 bool MonthViewCell::isPrimary() const
00458 {
00459 return mPrimary;
00460 }
00461
00462 void MonthViewCell::setHoliday( bool holiday )
00463 {
00464 mHoliday = holiday;
00465
00466 if ( holiday ) {
00467 setPalette( mHolidayPalette );
00468 } else {
00469 setPalette( mStandardPalette );
00470 }
00471 }
00472
00473 void MonthViewCell::setHolidayString( const QString &holiday )
00474 {
00475 mHolidayString = holiday;
00476 }
00477
00478 void MonthViewCell::updateCell()
00479 {
00480 setFrameWidth();
00481
00482 if ( mDate == QDate::currentDate() ) {
00483 setPalette( mTodayPalette );
00484
00485 QPalette pal = mItemList->palette();
00486 pal.setColor( QColorGroup::Foreground, KOPrefs::instance()->highlightColor() );
00487 mItemList->setPalette( pal );
00488 }
00489 else {
00490 if ( mHoliday )
00491 setPalette( mHolidayPalette );
00492 else
00493 setPalette( mStandardPalette );
00494
00495 QPalette pal = mItemList->palette();
00496 pal.setColor( QColorGroup::Foreground, KOPrefs::instance()->agendaBgColor().dark( 150 ) );
00497 mItemList->setPalette( pal );
00498 }
00499
00500 mItemList->clear();
00501
00502 if ( !mHolidayString.isEmpty() ) {
00503 MonthViewItem *item = new MonthViewItem( 0, QDateTime( mDate ), mHolidayString );
00504 item->setPalette( mHolidayPalette );
00505 mItemList->insertItem( item );
00506 }
00507 }
00508
00509 class MonthViewCell::CreateItemVisitor :
00510 public IncidenceBase::Visitor
00511 {
00512 public:
00513 CreateItemVisitor() : mItem(0) { emails = KOPrefs::instance()->allEmails(); }
00514
00515 bool act( IncidenceBase *incidence, QDate date, QPalette stdPal, int multiDay )
00516 {
00517 mItem = 0;
00518 mDate = date;
00519 mStandardPalette = stdPal;
00520 mMultiDay = multiDay;
00521 return incidence->accept( *this );
00522 }
00523 MonthViewItem *item() const { return mItem; }
00524 QStringList emails;
00525
00526 protected:
00527 bool visit( Event *event ) {
00528 QString text;
00529 QDateTime dt( mDate );
00530
00531 QDate dtEnd = event->dtEnd().addSecs( event->doesFloat() ? 0 : -1).date();
00532 int length = event->dtStart().daysTo( dtEnd );
00533 if ( event->isMultiDay() ) {
00534 if ( mDate == event->dtStart().date()
00535 || ( mMultiDay == 0 && event->recursOn( mDate ) ) ) {
00536 text = "(-- " + event->summary();
00537 dt = event->dtStart();
00538 } else if ( !event->doesRecur() && mDate == dtEnd
00539
00540 || ( mMultiDay == length && event->recursOn( mDate.addDays( -length ) ) ) ) {
00541 text = event->summary() + " --)";
00542 } else if (!(event->dtStart().date().daysTo(mDate) % 7) && length > 7 ) {
00543 text = "-- " + event->summary() + " --";
00544 } else {
00545 text = "----------------";
00546 dt = QDateTime( mDate );
00547 }
00548 } else {
00549 if (event->doesFloat())
00550 text = event->summary();
00551 else {
00552 text = KGlobal::locale()->formatTime(event->dtStart().time());
00553 dt.setTime( event->dtStart().time() );
00554 text += ' ' + event->summary();
00555 }
00556 }
00557
00558 mItem = new MonthViewItem( event, dt, text );
00559 mItem->setEvent( true );
00560 if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryOnly ||
00561 KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) {
00562 QStringList categories = event->categories();
00563 QString cat = categories.first();
00564 if (cat.isEmpty()) {
00565 mItem->setPalette(QPalette(KOPrefs::instance()->unsetCategoryColor(),
00566 KOPrefs::instance()->unsetCategoryColor()) );
00567 } else {
00568 mItem->setPalette(QPalette(*(KOPrefs::instance()->categoryColor(cat)),
00569 *(KOPrefs::instance()->categoryColor(cat))));
00570 }
00571 } else {
00572 mItem->setPalette( mStandardPalette );
00573 }
00574
00575 Attendee *me = event->attendeeByMails( emails );
00576 if ( me != 0 ) {
00577 mItem->setReply( me->status() == Attendee::NeedsAction && me->RSVP() );
00578 } else
00579 mItem->setReply(false);
00580 return true;
00581 }
00582 bool visit( Todo *todo ) {
00583 QString text;
00584 if ( !KOPrefs::instance()->showAllDayTodo() )
00585 return false;
00586 QDateTime dt( mDate );
00587 if ( todo->hasDueDate() && !todo->doesFloat() ) {
00588 text += KGlobal::locale()->formatTime( todo->dtDue().time() );
00589 text += ' ';
00590 dt.setTime( todo->dtDue().time() );
00591 }
00592 text += todo->summary();
00593
00594 mItem = new MonthViewItem( todo, dt, text );
00595 if ( todo->doesRecur() ) {
00596 mDate < todo->dtDue().date() ?
00597 mItem->setTodoDone( true ) : mItem->setTodo( true );
00598 }
00599 else
00600 todo->isCompleted() ? mItem->setTodoDone( true ) : mItem->setTodo( true );
00601 mItem->setPalette( mStandardPalette );
00602 return true;
00603 }
00604 protected:
00605 MonthViewItem *mItem;
00606 QDate mDate;
00607 QPalette mStandardPalette;
00608 int mMultiDay;
00609 };
00610
00611
00612 void MonthViewCell::addIncidence( Incidence *incidence, CreateItemVisitor& v, int multiDay )
00613 {
00614 if ( v.act( incidence, mDate, mStandardPalette, multiDay ) ) {
00615 MonthViewItem *item = v.item();
00616 if ( item ) {
00617 item->setAlarm( incidence->isAlarmEnabled() );
00618 item->setRecur( incidence->recurrenceType() );
00619
00620 QColor resourceColor = KOHelper::resourceColor( mCalendar, incidence );
00621 if ( !resourceColor.isValid() )
00622 resourceColor = KOPrefs::instance()->unsetCategoryColor();
00623 item->setResourceColor( resourceColor );
00624
00625
00626
00627
00628 uint i = 0;
00629 int pos = -1;
00630 QDateTime dt( item->incidenceDateTime() );
00631
00632 while ( i < mItemList->count() && pos<0 ) {
00633 QListBoxItem *item = mItemList->item( i );
00634 MonthViewItem *mvitem = dynamic_cast<MonthViewItem*>( item );
00635 if ( mvitem && mvitem->incidenceDateTime()>dt ) {
00636 pos = i;
00637 }
00638 ++i;
00639 }
00640 mItemList->insertItem( item, pos );
00641 }
00642 }
00643 }
00644
00645 void MonthViewCell::removeIncidence( Incidence *incidence )
00646 {
00647 for ( uint i = 0; i < mItemList->count(); ++i ) {
00648 MonthViewItem *item = static_cast<MonthViewItem *>(mItemList->item( i ) );
00649 if ( item && item->incidence() &&
00650 item->incidence()->uid() == incidence->uid() ) {
00651 mItemList->removeItem( i );
00652 --i;
00653 }
00654 }
00655 }
00656
00657 void MonthViewCell::updateConfig()
00658 {
00659 setFont( KOPrefs::instance()->mMonthViewFont );
00660
00661 QFontMetrics fm( font() );
00662 mLabelSize = fm.size( 0, "30" ) +
00663 QSize( mLabel->frameWidth() * 2, mLabel->frameWidth() * 2 ) +
00664 QSize( 2, 2 );
00665
00666 QColor bg = mStandardPalette.color( QPalette::Active, QColorGroup::Background );
00667 int h,s,v;
00668 bg.getHsv( &h, &s, &v );
00669 if ( date().month() %2 == 0 ) {
00670 if ( v < 128 ) {
00671 bg = bg.light( 125 );
00672 } else {
00673 bg = bg.dark( 125 );
00674 }
00675 }
00676 setPaletteBackgroundColor( bg );
00677
00678
00679 mHolidayPalette = mStandardPalette;
00680 mHolidayPalette.setColor( QColorGroup::Foreground,
00681 KOPrefs::instance()->holidayColor() );
00682 mHolidayPalette.setColor( QColorGroup::Text,
00683 KOPrefs::instance()->holidayColor() );
00684 mTodayPalette = mStandardPalette;
00685 mTodayPalette.setColor( QColorGroup::Foreground,
00686 KOPrefs::instance()->highlightColor() );
00687 mTodayPalette.setColor( QColorGroup::Text,
00688 KOPrefs::instance()->highlightColor() );
00689 updateCell();
00690
00691 mItemList->setBackground( mPrimary, KOGlobals::self()->isWorkDay( mDate ) );
00692 }
00693
00694 void MonthViewCell::enableScrollBars( bool enabled )
00695 {
00696 if ( enabled ) {
00697 mItemList->setVScrollBarMode( QScrollView::Auto );
00698 mItemList->setHScrollBarMode( QScrollView::Auto );
00699 } else {
00700 mItemList->setVScrollBarMode( QScrollView::AlwaysOff );
00701 mItemList->setHScrollBarMode( QScrollView::AlwaysOff );
00702 }
00703 }
00704
00705 Incidence *MonthViewCell::selectedIncidence()
00706 {
00707 int index = mItemList->currentItem();
00708 if ( index < 0 ) return 0;
00709
00710 MonthViewItem *item =
00711 static_cast<MonthViewItem *>( mItemList->item( index ) );
00712
00713 if ( !item ) return 0;
00714
00715 return item->incidence();
00716 }
00717
00718 QDate MonthViewCell::selectedIncidenceDate()
00719 {
00720 QDate qd;
00721 int index = mItemList->currentItem();
00722 if ( index < 0 ) return qd;
00723
00724 MonthViewItem *item =
00725 static_cast<MonthViewItem *>( mItemList->item( index ) );
00726
00727 if ( !item ) return qd;
00728
00729 return item->incidenceDateTime().date();
00730 }
00731
00732 void MonthViewCell::select()
00733 {
00734
00735 mMonthView->setSelectedCell( this );
00736
00737 if( KOPrefs::instance()->enableMonthScroll() )
00738 enableScrollBars( true );
00739
00740
00741 if( mDate != QDate::currentDate() ) {
00742 mItemList->setFrameStyle( QFrame::Sunken | QFrame::Panel );
00743 mItemList->setLineWidth( 3 );
00744 }
00745 }
00746
00747 void MonthViewCell::deselect()
00748 {
00749 mItemList->clearSelection();
00750 mItemList->setFrameStyle( QFrame::Plain | QFrame::Panel );
00751 setFrameWidth();
00752
00753 enableScrollBars( false );
00754 }
00755
00756 void MonthViewCell::resizeEvent ( QResizeEvent * )
00757 {
00758 mLabel->move( width() - mLabel->width(), height() - mLabel->height() );
00759 }
00760
00761 void MonthViewCell::defaultAction( QListBoxItem *item )
00762 {
00763 select();
00764
00765 if ( !item ) {
00766 emit newEventSignal( date() );
00767 } else {
00768 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
00769 Incidence *incidence = eventItem->incidence();
00770 if ( incidence ) mMonthView->defaultAction( incidence );
00771 }
00772 }
00773
00774 void MonthViewCell::contextMenu( QListBoxItem *item )
00775 {
00776 select();
00777
00778 if ( item ) {
00779 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
00780 Incidence *incidence = eventItem->incidence();
00781 if ( incidence ) mMonthView->showEventContextMenu( incidence, date() );
00782 }
00783 else {
00784 mMonthView->showGeneralContextMenu();
00785 }
00786 }
00787
00788
00789 KOMonthView::KOMonthView( Calendar *calendar, QWidget *parent, const char *name )
00790 : KOEventView( calendar, parent, name ),
00791 mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ),
00792 mShortDayLabels( false ), mWidthLongDayLabel( 0 ), mSelectedCell( 0 )
00793 {
00794 mCells.setAutoDelete( true );
00795
00796 QGridLayout *dayLayout = new QGridLayout( this );
00797
00798 QFont bfont = font();
00799 bfont.setBold( true );
00800
00801 QFont mfont = bfont;
00802 mfont.setPointSize( 20 );
00803
00804
00805 mLabel = new QLabel( this );
00806 mLabel->setFont( mfont );
00807 mLabel->setAlignment( AlignCenter );
00808 mLabel->setLineWidth( 0 );
00809 mLabel->setFrameStyle( QFrame::Plain );
00810
00811 dayLayout->addMultiCellWidget( mLabel, 0, 0, 0, mDaysPerWeek );
00812
00813
00814
00815 mDayLabels.resize( mDaysPerWeek );
00816 int i;
00817 for( i = 0; i < mDaysPerWeek; i++ ) {
00818 QLabel *label = new QLabel( this );
00819 label->setFont( bfont );
00820 label->setFrameStyle( QFrame::Panel | QFrame::Raised );
00821 label->setLineWidth( 1 );
00822 label->setAlignment( AlignCenter );
00823
00824 mDayLabels.insert( i, label );
00825
00826 dayLayout->addWidget( label, 1, i );
00827 dayLayout->addColSpacing( i, 10 );
00828 dayLayout->setColStretch( i, 1 );
00829 }
00830
00831 int row, col;
00832
00833 mCells.resize( mNumCells );
00834 for( row = 0; row < mNumWeeks; ++row ) {
00835 for( col = 0; col < mDaysPerWeek; ++col ) {
00836 MonthViewCell *cell = new MonthViewCell( this );
00837 cell->setCalendar(calendar);
00838 mCells.insert( row * mDaysPerWeek + col, cell );
00839 dayLayout->addWidget( cell, row + 2, col );
00840
00841 connect( cell, SIGNAL( defaultAction( Incidence * ) ),
00842 SLOT( defaultAction( Incidence * ) ) );
00843 connect( cell, SIGNAL( newEventSignal( const QDate & ) ),
00844 SIGNAL( newEventSignal( const QDate & ) ) );
00845 }
00846 dayLayout->setRowStretch( row + 2, 1 );
00847 }
00848
00849 mEventContextMenu = eventPopup();
00850
00851 updateConfig();
00852
00853 emit incidenceSelected( 0 );
00854 }
00855
00856 KOMonthView::~KOMonthView()
00857 {
00858 delete mEventContextMenu;
00859 }
00860
00861 int KOMonthView::maxDatesHint()
00862 {
00863 return mNumCells;
00864 }
00865
00866 int KOMonthView::currentDateCount()
00867 {
00868 return mNumCells;
00869 }
00870
00871 Incidence::List KOMonthView::selectedIncidences()
00872 {
00873 Incidence::List selected;
00874
00875 if ( mSelectedCell ) {
00876 Incidence *incidence = mSelectedCell->selectedIncidence();
00877 if ( incidence ) selected.append( incidence );
00878 }
00879
00880 return selected;
00881 }
00882
00883 DateList KOMonthView::selectedDates()
00884 {
00885 DateList selected;
00886
00887 if ( mSelectedCell ) {
00888 QDate qd = mSelectedCell->selectedIncidenceDate();
00889 if ( qd.isValid() ) selected.append( qd );
00890 }
00891
00892 return selected;
00893 }
00894
00895 bool KOMonthView::eventDurationHint( QDateTime &startDt, QDateTime &endDt, bool &allDay )
00896 {
00897 if ( mSelectedCell ) {
00898 startDt.setDate( mSelectedCell->date() );
00899 endDt.setDate( mSelectedCell->date() );
00900 allDay = true;
00901 return true;
00902 }
00903 return false;
00904 }
00905
00906 void KOMonthView::updateConfig()
00907 {
00908 mWeekStartDay = KGlobal::locale()->weekStartDay();
00909
00910 QFontMetrics fontmetric( mDayLabels[0]->font() );
00911 mWidthLongDayLabel = 0;
00912
00913 for ( int i = 0; i < 7; ++i ) {
00914 int width =
00915 fontmetric.width( KOGlobals::self()->calendarSystem()->weekDayName( i + 1 ) );
00916 if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
00917 }
00918
00919 updateDayLabels();
00920
00921 for ( uint i = 0; i < mCells.count(); ++i ) {
00922 mCells[i]->updateConfig();
00923 }
00924 }
00925
00926 void KOMonthView::updateDayLabels()
00927 {
00928 kdDebug(5850) << "KOMonthView::updateDayLabels()" << endl;
00929
00930 const KCalendarSystem*calsys=KOGlobals::self()->calendarSystem();
00931 int currDay;
00932 for ( int i = 0; i < 7; i++ ) {
00933 currDay = i+mWeekStartDay;
00934 if ( currDay > 7 ) currDay -= 7;
00935 mDayLabels[i]->setText( calsys->weekDayName( currDay, mShortDayLabels ) );
00936 }
00937 }
00938
00939 void KOMonthView::showDates( const QDate &start, const QDate & )
00940 {
00941
00942
00943 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00944
00945 mDateToCell.clear();
00946
00947
00948 mStartDate = start.addDays( -start.day() + 1 );
00949
00950 int weekdayCol=( mStartDate.dayOfWeek() + 7 - mWeekStartDay ) % 7;
00951 mStartDate = mStartDate.addDays( -weekdayCol );
00952
00953 mLabel->setText( i18n( "monthname year", "%1 %2" )
00954 .arg( calSys->monthName( start ) )
00955 .arg( calSys->year( start ) ) );
00956 if ( !KOPrefs::instance()->fullViewMonth() ) {
00957 mLabel->show();
00958 } else {
00959 mLabel->hide();
00960 }
00961
00962 bool primary = false;
00963 uint i;
00964 for( i = 0; i < mCells.size(); ++i ) {
00965 QDate date = mStartDate.addDays( i );
00966 if ( calSys->day( date ) == 1 ) {
00967 primary = !primary;
00968 }
00969
00970 mCells[i]->setDate( date );
00971 mDateToCell[ date ] = mCells[ i ];
00972 if( date == start )
00973 mCells[i]->select();
00974
00975 mCells[i]->setPrimary( primary );
00976
00977 bool isHoliday = calSys->dayOfWeek( date ) == calSys->weekDayOfPray()
00978 || !KOGlobals::self()->isWorkDay( date );
00979 mCells[i]->setHoliday( isHoliday );
00980
00981
00982 QStringList holidays( KOGlobals::self()->holiday( date ) );
00983 mCells[i]->setHolidayString( holidays.join( i18n("delimiter for joining holiday names", ", " ) ) );
00984 }
00985
00986 updateView();
00987 }
00988
00989 void KOMonthView::showIncidences( const Incidence::List & )
00990 {
00991 kdDebug(5850) << "KOMonthView::showIncidences( const Incidence::List & ) is not implemented yet." << endl;
00992 }
00993
00994 class KOMonthView::GetDateVisitor : public IncidenceBase::Visitor
00995 {
00996 public:
00997 GetDateVisitor() {}
00998
00999 bool act( IncidenceBase *incidence )
01000 {
01001 return incidence->accept( *this );
01002 }
01003 QDateTime startDate() const { return mStartDate; }
01004 QDateTime endDate() const { return mEndDate; }
01005
01006 protected:
01007 bool visit( Event *event ) {
01008 mStartDate = event->dtStart();
01009 mEndDate = event->dtEnd();
01010 return true;
01011 }
01012 bool visit( Todo *todo ) {
01013 if ( todo->hasDueDate() ) {
01014 mStartDate = todo->dtDue();
01015 mEndDate = todo->dtDue();
01016 }
01017
01018 return true;
01019 }
01020 bool visit( Journal *journal ) {
01021 mStartDate = journal->dtStart();
01022 mEndDate = journal->dtStart();
01023 return true;
01024 }
01025 protected:
01026 QDateTime mStartDate;
01027 QDateTime mEndDate;
01028 };
01029
01030 void KOMonthView::changeIncidenceDisplayAdded( Incidence *incidence, MonthViewCell::CreateItemVisitor& v)
01031 {
01032 GetDateVisitor gdv;
01033
01034 if ( !gdv.act( incidence ) ) {
01035 kdDebug(5850) << "Visiting GetDateVisitor failed." << endl;
01036 return;
01037 }
01038
01039 bool floats = incidence->doesFloat();
01040
01041 if ( incidence->doesRecur() ) {
01042 for ( uint i = 0; i < mCells.count(); ++i ) {
01043 if ( incidence->recursOn( mCells[i]->date() ) ) {
01044
01045
01046 int length = gdv.startDate().daysTo( gdv.endDate().addSecs( floats ? 0 : -1 ).date() );
01047 for ( int j = 0; j <= length && i+j < mCells.count(); ++j ) {
01048 mCells[i+j]->addIncidence( incidence, v, j );
01049 }
01050 }
01051 }
01052 } else {
01053
01054 if ( gdv.endDate().isValid() ) {
01055 QDate endDate = gdv.endDate().addSecs( floats ? 0 : -1).date();
01056 for ( QDate date = gdv.startDate().date();
01057 date <= endDate; date = date.addDays( 1 ) ) {
01058 MonthViewCell *mvc = mDateToCell[ date ];
01059 if ( mvc ) mvc->addIncidence( incidence, v );
01060 }
01061 }
01062 }
01063 }
01064
01065 void KOMonthView::changeIncidenceDisplay( Incidence *incidence, int action )
01066 {
01067 MonthViewCell::CreateItemVisitor v;
01068 switch ( action ) {
01069 case KOGlobals::INCIDENCEADDED:
01070 changeIncidenceDisplayAdded( incidence, v );
01071 break;
01072 case KOGlobals::INCIDENCEEDITED:
01073 for( uint i = 0; i < mCells.count(); i++ )
01074 mCells[i]->removeIncidence( incidence );
01075 changeIncidenceDisplayAdded( incidence, v );
01076 break;
01077 case KOGlobals::INCIDENCEDELETED:
01078 for( uint i = 0; i < mCells.count(); i++ )
01079 mCells[i]->removeIncidence( incidence );
01080 break;
01081 default:
01082 return;
01083 }
01084 }
01085
01086 void KOMonthView::updateView()
01087 {
01088 for( uint i = 0; i < mCells.count(); ++i ) {
01089 mCells[i]->updateCell();
01090 }
01091
01092 Incidence::List incidences = calendar()->incidences();
01093 Incidence::List::ConstIterator it;
01094
01095 MonthViewCell::CreateItemVisitor v;
01096 for ( it = incidences.begin(); it != incidences.end(); ++it )
01097 changeIncidenceDisplayAdded( *it, v );
01098
01099 processSelectionChange();
01100 }
01101
01102 void KOMonthView::resizeEvent( QResizeEvent * )
01103 {
01104
01105
01106
01107
01108 if( mDayLabels[0]->width() < mWidthLongDayLabel ) {
01109 if ( !mShortDayLabels ) {
01110 mShortDayLabels = true;
01111 updateDayLabels();
01112 }
01113 } else {
01114 if ( mShortDayLabels ) {
01115 mShortDayLabels = false;
01116 updateDayLabels();
01117 }
01118 }
01119 }
01120
01121 void KOMonthView::showEventContextMenu( Incidence *incidence, const QDate &qd )
01122 {
01123 mEventContextMenu->showIncidencePopup( incidence, qd );
01124 }
01125
01126 void KOMonthView::showGeneralContextMenu()
01127 {
01128 showNewEventPopup();
01129 }
01130
01131 void KOMonthView::setSelectedCell( MonthViewCell *cell )
01132 {
01133 if ( mSelectedCell && cell != mSelectedCell )
01134 mSelectedCell->deselect();
01135
01136 mSelectedCell = cell;
01137
01138 if ( !mSelectedCell )
01139 emit incidenceSelected( 0 );
01140 else
01141 emit incidenceSelected( mSelectedCell->selectedIncidence() );
01142 }
01143
01144 void KOMonthView::processSelectionChange()
01145 {
01146 Incidence::List incidences = selectedIncidences();
01147 if (incidences.count() > 0) {
01148 emit incidenceSelected( incidences.first() );
01149 } else {
01150 emit incidenceSelected( 0 );
01151 }
01152 }
01153
01154 void KOMonthView::clearSelection()
01155 {
01156 if ( mSelectedCell ) {
01157 mSelectedCell->deselect();
01158 mSelectedCell = 0;
01159 }
01160 }