00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qpopupmenu.h>
00021 #include <qfont.h>
00022 #include <qfontmetrics.h>
00023 #include <qkeycode.h>
00024 #include <qhbox.h>
00025 #include <qvbox.h>
00026 #include <qpushbutton.h>
00027 #include <qtooltip.h>
00028 #include <qpainter.h>
00029
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kglobal.h>
00033 #include <kconfig.h>
00034 #include <kiconloader.h>
00035
00036 #ifndef KORG_NOPRINTER
00037 #include "calprinter.h"
00038 #endif
00039 #include "koprefs.h"
00040 #ifndef KORG_NOPLUGINS
00041 #include "kocore.h"
00042 #endif
00043
00044 #include "komonthview.h"
00045 #include "komonthview.moc"
00046
00047 KNoScrollListBox::KNoScrollListBox(QWidget *parent,const char *name)
00048 : QListBox(parent, name)
00049 {
00050 }
00051
00052 void KNoScrollListBox::keyPressEvent(QKeyEvent *e)
00053 {
00054 switch(e->key()) {
00055 case Key_Right:
00056 scrollBy(4,0);
00057 break;
00058 case Key_Left:
00059 scrollBy(-4,0);
00060 break;
00061 case Key_Up:
00062 if(!count()) break;
00063 setCurrentItem((currentItem()+count()-1)%count());
00064 if(!itemVisible(currentItem())) {
00065 if((unsigned int) currentItem() == (count()-1)) {
00066 setTopItem(currentItem()-numItemsVisible()+1);
00067 } else {
00068 setTopItem(topItem()-1);
00069 }
00070 }
00071 break;
00072 case Key_Down:
00073 if(!count()) break;
00074 setCurrentItem((currentItem()+1)%count());
00075 if(!itemVisible(currentItem())) {
00076 if(currentItem() == 0) {
00077 setTopItem(0);
00078 } else {
00079 setTopItem(topItem()+1);
00080 }
00081 }
00082 case Key_Shift:
00083 emit shiftDown();
00084 break;
00085 default:
00086 break;
00087 }
00088 }
00089
00090 void KNoScrollListBox::keyReleaseEvent(QKeyEvent *e)
00091 {
00092 switch(e->key()) {
00093 case Key_Shift:
00094 emit shiftUp();
00095 break;
00096 default:
00097 break;
00098 }
00099 }
00100
00101 void KNoScrollListBox::mousePressEvent(QMouseEvent *e)
00102 {
00103 QListBox::mousePressEvent(e);
00104
00105 if(e->button() == RightButton) {
00106 emit rightClick();
00107 }
00108 }
00109
00110
00111 MonthViewItem::MonthViewItem( Incidence *incidence, QDate qd, const QString & s)
00112 : QListBoxItem()
00113 {
00114 setText( s );
00115
00116 mIncidence = incidence;
00117 mDate = qd;
00118
00119 mAlarmPixmap = SmallIcon("bell");
00120 mRecurPixmap = SmallIcon("recur");
00121 mReplyPixmap = SmallIcon("mail_reply");
00122
00123 mRecur = false;
00124 mAlarm = false;
00125 mReply = false;
00126 }
00127
00128 void MonthViewItem::paint(QPainter *p)
00129 {
00130 if (KOPrefs::instance()->mMonthViewUsesCategoryColor)
00131 {
00132 p->setBackgroundColor( palette().color( QPalette::Normal, \
00133 isSelected() ? QColorGroup::Highlight : QColorGroup::Background ) );
00134 p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) );
00135 }
00136 int x = 3;
00137 if ( mRecur ) {
00138 p->drawPixmap( x, 0, mRecurPixmap );
00139 x += mRecurPixmap.width() + 2;
00140 }
00141 if ( mAlarm ) {
00142 p->drawPixmap( x, 0, mAlarmPixmap );
00143 x += mAlarmPixmap.width() + 2;
00144 }
00145 if ( mReply ) {
00146 p->drawPixmap(x, 0, mReplyPixmap );
00147 x += mReplyPixmap.width() + 2;
00148 }
00149 QFontMetrics fm = p->fontMetrics();
00150 int yPos;
00151 int pmheight = QMAX( mRecurPixmap.height(),
00152 QMAX( mAlarmPixmap.height(), mReplyPixmap.height() ) );
00153 if( pmheight < fm.height() )
00154 yPos = fm.ascent() + fm.leading()/2;
00155 else
00156 yPos = pmheight/2 - fm.height()/2 + fm.ascent();
00157 p->setPen( palette().color( QPalette::Normal, isSelected() ? \
00158 QColorGroup::HighlightedText : QColorGroup::Foreground ) );
00159 p->drawText( x, yPos, text() );
00160 }
00161
00162 int MonthViewItem::height(const QListBox *lb) const
00163 {
00164 return QMAX( QMAX( mRecurPixmap.height(), mReplyPixmap.height() ),
00165 QMAX( mAlarmPixmap.height(), lb->fontMetrics().lineSpacing()+1) );
00166 }
00167
00168 int MonthViewItem::width(const QListBox *lb) const
00169 {
00170 int x = 3;
00171 if( mRecur ) {
00172 x += mRecurPixmap.width()+2;
00173 }
00174 if( mAlarm ) {
00175 x += mAlarmPixmap.width()+2;
00176 }
00177 if( mReply ) {
00178 x += mReplyPixmap.width()+2;
00179 }
00180
00181 return( x + lb->fontMetrics().width( text() ) + 1 );
00182 }
00183
00184
00185 MonthViewCell::MonthViewCell( KOMonthView *parent)
00186 : QWidget( parent ),
00187 mMonthView( parent )
00188 {
00189
00190 QVBoxLayout *topLayout = new QVBoxLayout( this );
00191
00192 mLabel = new QLabel( this );
00193 mLabel->setFrameStyle( QFrame::Panel | QFrame::Plain );
00194 mLabel->setLineWidth( 1 );
00195 mLabel->setAlignment( AlignCenter );
00196
00197 mItemList = new KNoScrollListBox( this );
00198 mItemList->setMinimumSize( 10, 10 );
00199 mItemList->setFrameStyle( QFrame::Panel | QFrame::Plain );
00200 mItemList->setLineWidth( 1 );
00201 topLayout->addWidget( mItemList );
00202
00203 mLabel->raise();
00204
00205 mStandardPalette = palette();
00206
00207 enableScrollBars( false );
00208
00209 updateConfig();
00210
00211 connect( mItemList, SIGNAL( doubleClicked( QListBoxItem *) ),
00212 SLOT( defaultAction( QListBoxItem * ) ) );
00213 connect( mItemList, SIGNAL( rightButtonPressed( QListBoxItem *,
00214 const QPoint &) ),
00215 SLOT( contextMenu( QListBoxItem * ) ) );
00216 connect( mItemList, SIGNAL( highlighted( QListBoxItem *) ),
00217 SLOT( selection( QListBoxItem * ) ) );
00218 connect( mItemList, SIGNAL( clicked( QListBoxItem * ) ),
00219 SLOT( cellClicked( QListBoxItem * ) ) );
00220 }
00221
00222 void MonthViewCell::setDate( const QDate &date )
00223 {
00224
00225
00226 mDate = date;
00227
00228 QString text;
00229 if ( KOCore::self()->calendarSystem()->day( date ) == 1 ) {
00230 text = KOCore::self()->calendarSystem()->monthName( date, true ) + " ";
00231 QFontMetrics fm( mLabel->font() );
00232 mLabel->resize( mLabelSize + QSize( fm.width( text ), 0 ) );
00233 } else {
00234 mLabel->resize( mLabelSize );
00235 }
00236 text += QString::number( KOCore::self()->calendarSystem()->day(mDate) );
00237 mLabel->setText( text );
00238
00239 resizeEvent( 0 );
00240 }
00241
00242 QDate MonthViewCell::date() const
00243 {
00244 return mDate;
00245 }
00246
00247 void MonthViewCell::setPrimary( bool primary )
00248 {
00249 mPrimary = primary;
00250
00251 if ( mPrimary ) {
00252 mLabel->setBackgroundMode( PaletteBase );
00253 } else {
00254 mLabel->setBackgroundMode( PaletteBackground );
00255 }
00256 }
00257
00258 bool MonthViewCell::isPrimary() const
00259 {
00260 return mPrimary;
00261 }
00262
00263 void MonthViewCell::setHoliday( bool holiday )
00264 {
00265 mHoliday = holiday;
00266
00267 if ( holiday ) {
00268 setPalette( mHolidayPalette );
00269 } else {
00270 setPalette( mStandardPalette );
00271 }
00272 }
00273
00274 void MonthViewCell::setHoliday( const QString &holiday )
00275 {
00276 mHolidayString = holiday;
00277
00278 if ( !holiday.isEmpty() ) {
00279 setHoliday( true );
00280 }
00281 }
00282
00283 void MonthViewCell::updateCell()
00284 {
00285 if ( mDate == QDate::currentDate() ) {
00286 mItemList->setLineWidth( 3 );
00287 } else {
00288 mItemList->setLineWidth( 1 );
00289 }
00290
00291 mItemList->clear();
00292
00293 if ( !mHolidayString.isEmpty() ) {
00294 MonthViewItem *item = new MonthViewItem( 0, mDate, mHolidayString );
00295 item->setPalette( mHolidayPalette );
00296 mItemList->insertItem( item );
00297 }
00298
00299 QPtrList<Event> events = mMonthView->calendar()->events( mDate, true );
00300 Event *event;
00301 for( event = events.first(); event; event = events.next() ) {
00302 QString text;
00303 if (event->isMultiDay()) {
00304 if (mDate == event->dtStart().date()) {
00305 text = "(-- " + event->summary();
00306 } else if (mDate == event->dtEnd().date()) {
00307 text = event->summary() + " --)";
00308 } else if (!(event->dtStart().date().daysTo(mDate) % 7)) {
00309 text = "-- " + event->summary() + " --";
00310 } else {
00311 text = "----------------";
00312 }
00313 } else {
00314 if (event->doesFloat())
00315 text = event->summary();
00316 else {
00317 text = KGlobal::locale()->formatTime(event->dtStart().time());
00318 text += " " + event->summary();
00319 }
00320 }
00321
00322 MonthViewItem *item = new MonthViewItem( event, mDate, text );
00323 if (KOPrefs::instance()->mMonthViewUsesCategoryColor) {
00324 QStringList categories = event->categories();
00325 QString cat = categories.first();
00326 if (cat.isEmpty()) {
00327 item->setPalette(QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor));
00328 } else {
00329 item->setPalette(QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat))));
00330 }
00331 } else {
00332 item->setPalette( mStandardPalette );
00333 }
00334 item->setRecur( event->recurrence()->doesRecur() );
00335 item->setAlarm( event->isAlarmEnabled() );
00336
00337 Attendee *me = event->attendeeByMails(KOPrefs::instance()->mAdditionalMails,
00338 KOPrefs::instance()->email());
00339 if ( me != 0 ) {
00340 if ( me->status() == Attendee::NeedsAction && me->RSVP())
00341 item->setReply(true);
00342 else
00343 item->setReply(false);
00344 } else
00345 item->setReply(false);
00346
00347 mItemList->insertItem( item );
00348 }
00349
00350
00351 QPtrList<Todo> todos = mMonthView->calendar()->todos( mDate );
00352 Todo *todo;
00353 for(todo = todos.first(); todo; todo = todos.next()) {
00354 QString text;
00355 if (todo->hasDueDate()) {
00356 if (!todo->doesFloat()) {
00357 text += KGlobal::locale()->formatTime(todo->dtDue().time());
00358 text += " ";
00359 }
00360 }
00361 text += i18n("To-Do: %1").arg(todo->summary());
00362
00363 MonthViewItem *item = new MonthViewItem( todo, mDate, text );
00364 item->setPalette( mStandardPalette );
00365
00366 mItemList->insertItem( item );
00367 }
00368 }
00369
00370 void MonthViewCell::updateConfig()
00371 {
00372 setFont( KOPrefs::instance()->mMonthViewFont );
00373
00374 QFontMetrics fm( font() );
00375 mLabelSize = fm.size( 0, "30" ) +
00376 QSize( mLabel->frameWidth() * 2, mLabel->frameWidth() * 2 ) +
00377 QSize( 2, 2 );
00378
00379 mHolidayPalette = mStandardPalette;
00380 mHolidayPalette.setColor(QColorGroup::Foreground,
00381 KOPrefs::instance()->mHolidayColor);
00382 mHolidayPalette.setColor(QColorGroup::Text,
00383 KOPrefs::instance()->mHolidayColor);
00384 updateCell();
00385 }
00386
00387 void MonthViewCell::enableScrollBars( bool enabled )
00388 {
00389 if ( enabled ) {
00390 mItemList->setVScrollBarMode(QScrollView::Auto);
00391 mItemList->setHScrollBarMode(QScrollView::Auto);
00392 } else {
00393 mItemList->setVScrollBarMode(QScrollView::AlwaysOff);
00394 mItemList->setHScrollBarMode(QScrollView::AlwaysOff);
00395 }
00396 }
00397
00398 Incidence *MonthViewCell::selectedIncidence()
00399 {
00400 int index = mItemList->currentItem();
00401 if ( index < 0 ) return 0;
00402
00403 MonthViewItem *item =
00404 static_cast<MonthViewItem *>( mItemList->item( index ) );
00405
00406 if ( !item ) return 0;
00407
00408 return item->incidence();
00409 }
00410
00411 QDate MonthViewCell::selectedIncidenceDate()
00412 {
00413 QDate qd;
00414 int index = mItemList->currentItem();
00415 if ( index < 0 ) return qd;
00416
00417 MonthViewItem *item =
00418 static_cast<MonthViewItem *>( mItemList->item( index ) );
00419
00420 if ( !item ) return qd;
00421
00422 return item->incidenceDate();
00423 }
00424
00425 void MonthViewCell::deselect()
00426 {
00427 mItemList->clearSelection();
00428
00429 enableScrollBars( false );
00430 }
00431
00432 void MonthViewCell::resizeEvent ( QResizeEvent * )
00433 {
00434 mLabel->move( width() - mLabel->width(), height() - mLabel->height() );
00435 }
00436
00437 void MonthViewCell::defaultAction( QListBoxItem *item )
00438 {
00439 if ( !item ) return;
00440
00441 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
00442 Incidence *incidence = eventItem->incidence();
00443 if ( incidence ) mMonthView->defaultAction( incidence );
00444 }
00445
00446 void MonthViewCell::cellClicked( QListBoxItem *item )
00447 {
00448 if ( item == 0 ) {
00449 QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
00450 emit newEventSignal( dt );
00451 }
00452
00453 if( KOPrefs::instance()->mEnableMonthScroll ) enableScrollBars( true );
00454 }
00455
00456 void MonthViewCell::contextMenu( QListBoxItem *item )
00457 {
00458 if ( !item ) return;
00459
00460 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
00461 Incidence *incidence = eventItem->incidence();
00462 if ( incidence ) mMonthView->showContextMenu( incidence );
00463 }
00464
00465 void MonthViewCell::selection( QListBoxItem *item )
00466 {
00467 if ( !item ) return;
00468
00469 mMonthView->setSelectedCell( this );
00470 }
00471
00472 KOMonthView::KOMonthView(Calendar *calendar, QWidget *parent, const char *name)
00473 : KOEventView( calendar, parent, name ),
00474 mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ),
00475 mShortDayLabels( false ), mWidthLongDayLabel( 0 ), mSelectedCell( 0 )
00476 {
00477 mCells.setAutoDelete( true );
00478
00479 QGridLayout *dayLayout = new QGridLayout( this );
00480
00481
00482
00483 mDayLabels.resize( mDaysPerWeek );
00484 QFont bfont = font();
00485 bfont.setBold( true );
00486 int i;
00487 for( i = 0; i < mDaysPerWeek; i++ ) {
00488 QLabel *label = new QLabel( this );
00489 label->setFont(bfont);
00490 label->setFrameStyle(QFrame::Panel|QFrame::Raised);
00491 label->setLineWidth(1);
00492 label->setAlignment(AlignCenter);
00493
00494 mDayLabels.insert( i, label );
00495
00496 dayLayout->addWidget( label, 0, i );
00497 }
00498
00499 int row, col;
00500
00501 mCells.resize( mNumCells );
00502 for( row = 0; row < mNumWeeks; ++row ) {
00503 for( col = 0; col < mDaysPerWeek; ++col ) {
00504 MonthViewCell *cell = new MonthViewCell( this );
00505 mCells.insert( row * mDaysPerWeek + col, cell );
00506 dayLayout->addWidget( cell, row + 1, col );
00507
00508 connect( cell, SIGNAL( defaultAction( Incidence * ) ),
00509 SLOT( defaultAction( Incidence * ) ) );
00510 connect( cell, SIGNAL( newEventSignal( QDateTime ) ),
00511 SIGNAL( newEventSignal( QDateTime ) ) );
00512 }
00513 dayLayout->setRowStretch( row + 1, 1 );
00514 }
00515
00516 mContextMenu = eventPopup();
00517
00518 updateConfig();
00519
00520 emit incidenceSelected( 0 );
00521 }
00522
00523 KOMonthView::~KOMonthView()
00524 {
00525 delete mContextMenu;
00526 }
00527
00528 int KOMonthView::maxDatesHint()
00529 {
00530 return mNumCells;
00531 }
00532
00533 int KOMonthView::currentDateCount()
00534 {
00535 return mNumCells;
00536 }
00537
00538 QPtrList<Incidence> KOMonthView::selectedIncidences()
00539 {
00540 QPtrList<Incidence> selected;
00541
00542 if ( mSelectedCell ) {
00543 Incidence *incidence = mSelectedCell->selectedIncidence();
00544 if ( incidence ) selected.append( incidence );
00545 }
00546
00547 return selected;
00548 }
00549
00550 DateList KOMonthView::selectedDates()
00551 {
00552 DateList selected;
00553
00554 if ( mSelectedCell ) {
00555 QDate qd = mSelectedCell->selectedIncidenceDate();
00556 if ( qd.isValid() ) selected.append( qd );
00557 }
00558
00559 return selected;
00560 }
00561
00562 void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd,
00563 const QDate &td)
00564 {
00565 #ifndef KORG_NOPRINTER
00566 calPrinter->preview(CalPrinter::Month, fd, td);
00567 #endif
00568 }
00569
00570 void KOMonthView::updateConfig()
00571 {
00572 mWeekStartsMonday = KGlobal::locale()->weekStartsMonday();
00573
00574 QFontMetrics fontmetric(mDayLabels[0]->font());
00575 mWidthLongDayLabel = 0;
00576
00577 for (int i = 0; i < 7; i++) {
00578 int width = fontmetric.width(KOCore::self()->calendarSystem()->weekDayName(i+1));
00579 if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
00580 }
00581
00582 updateDayLabels();
00583
00584 for (uint i = 0; i < mCells.count(); ++i) {
00585 mCells[i]->updateConfig();
00586 }
00587 }
00588
00589 void KOMonthView::updateDayLabels()
00590 {
00591 kdDebug() << "KOMonthView::updateDayLabels()" << endl;
00592
00593 for (int i = 0; i < 7; i++) {
00594 if (mWeekStartsMonday) {
00595 mDayLabels[i]->setText(KOCore::self()->calendarSystem()->weekDayName(i+1,mShortDayLabels));
00596 } else {
00597 if (i==0) mDayLabels[i]->setText(KOCore::self()->calendarSystem()->weekDayName(7,mShortDayLabels));
00598 else mDayLabels[i]->setText(KOCore::self()->calendarSystem()->weekDayName(i,mShortDayLabels));
00599
00600 }
00601 }
00602 }
00603
00604 void KOMonthView::showDates(const QDate &start, const QDate &)
00605 {
00606
00607
00608 mStartDate = start;
00609
00610 int startWeekDay = mWeekStartsMonday ? 1 : 7;
00611
00612 while( KOCore::self()->calendarSystem()->dayOfTheWeek(mStartDate) != startWeekDay ) {
00613 mStartDate = mStartDate.addDays( -1 );
00614 }
00615
00616 bool primary = false;
00617 uint i;
00618 for( i = 0; i < mCells.size(); ++i ) {
00619 QDate date = mStartDate.addDays( i );
00620 if ( KOCore::self()->calendarSystem()->day(date) == 1 ) {
00621 primary = !primary;
00622 }
00623 mCells[i]->setPrimary( primary );
00624
00625 if ( KOCore::self()->calendarSystem()->dayOfTheWeek(date) == KOCore::self()->calendarSystem()->weekDayOfPray() ) {
00626 mCells[i]->setHoliday( true );
00627 } else {
00628 mCells[i]->setHoliday( false );
00629 }
00630
00631 #ifndef KORG_NOPLUGINS
00632
00633 QString hstring(KOCore::self()->holiday(date));
00634 mCells[i]->setHoliday( hstring );
00635 #endif
00636
00637 mCells[i]->setDate( date );
00638 }
00639
00640 updateView();
00641 }
00642
00643 void KOMonthView::showEvents(QPtrList<Event>)
00644 {
00645 kdDebug() << "KOMonthView::selectEvents is not implemented yet." << endl;
00646 }
00647
00648 void KOMonthView::changeEventDisplay(Event *, int)
00649 {
00650
00651
00652 updateView();
00653 }
00654
00655 void KOMonthView::updateView()
00656 {
00657 uint i;
00658 for( i = 0; i < mCells.count(); ++i ) {
00659 mCells[i]->updateCell();
00660 }
00661
00662 processSelectionChange();
00663 }
00664
00665 void KOMonthView::resizeEvent(QResizeEvent *)
00666 {
00667
00668
00669
00670
00671 if( mDayLabels[0]->width() < mWidthLongDayLabel ) {
00672 if ( !mShortDayLabels ) {
00673 mShortDayLabels = true;
00674 updateDayLabels();
00675 }
00676 } else {
00677 if ( mShortDayLabels ) {
00678 mShortDayLabels = false;
00679 updateDayLabels();
00680 }
00681 }
00682 }
00683
00684 void KOMonthView::showContextMenu( Incidence *incidence )
00685 {
00686 if( incidence && incidence->type() == "Event" ) {
00687 Event *event = static_cast<Event *>(incidence);
00688 mContextMenu->showEventPopup(event);
00689 } else {
00690 kdDebug() << "MonthView::showContextMenu(): cast failed." << endl;
00691 }
00692 }
00693
00694 void KOMonthView::setSelectedCell( MonthViewCell *cell )
00695 {
00696 if ( cell == mSelectedCell ) return;
00697
00698 if ( mSelectedCell ) mSelectedCell->deselect();
00699
00700 mSelectedCell = cell;
00701
00702 if ( !mSelectedCell )
00703 emit incidenceSelected( 0 );
00704 else
00705 emit incidenceSelected( mSelectedCell->selectedIncidence() );
00706 }
00707
00708 void KOMonthView::processSelectionChange()
00709 {
00710 QPtrList<Incidence> incidences = selectedIncidences();
00711 if (incidences.count() > 0) {
00712 emit incidenceSelected( incidences.first() );
00713 } else {
00714 emit incidenceSelected( 0 );
00715 }
00716 }
00717
00718 void KOMonthView::clearSelection()
00719 {
00720 if ( mSelectedCell ) {
00721 mSelectedCell->deselect();
00722 mSelectedCell = 0;
00723 }
00724 }