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