/* This file is part of KOrganizer. Copyright (c) 2000,2001 Cornelius Schumacher Copyright (C) 2003-2004 Reinhold Kainhofer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "koprefs.h" #include "koglobals.h" #include "koincidencetooltip.h" #include "koeventpopupmenu.h" #include "kohelper.h" #include "komonthview.h" #include "komonthview.moc" //-------------------------------------------------------------------------- KOMonthCellToolTip::KOMonthCellToolTip( TQWidget *parent, Calendar *calendar, const TQDate &date, KNoScrollListBox *lv ) : TQToolTip( parent ), mCalendar( calendar ), mDate( date ) { eventlist = lv; } void KOMonthCellToolTip::maybeTip( const TQPoint &pos ) { TQRect r; TQListBoxItem *it = eventlist->itemAt( pos ); MonthViewItem *i = static_cast( it ); if( i && KOPrefs::instance()->mEnableToolTips ) { /* Calculate the rectangle. */ r=eventlist->itemRect( it ); /* Show the tip */ TQString tipText( IncidenceFormatter::toolTipStr( mCalendar, i->incidence(), mDate ) ); if ( !tipText.isEmpty() ) { tip( r, tipText ); } } } KNoScrollListBox::KNoScrollListBox( TQWidget *parent, const char *name ) : TQListBox( parent, name ), mSqueezing( false ) { TQPalette pal = palette(); pal.setColor( TQColorGroup::Foreground, KOPrefs::instance()->agendaBgColor().dark( 150 ) ); pal.setColor( TQColorGroup::Base, KOPrefs::instance()->agendaBgColor() ); setPalette( pal ); } void KNoScrollListBox::setBackground( bool primary, bool workDay ) { TQColor color; if ( workDay ) { color = KOPrefs::instance()->workingHoursColor(); } else { color = KOPrefs::instance()->agendaBgColor(); } TQPalette pal = palette(); if ( primary ) { pal.setColor( TQColorGroup::Base, color ); } else { pal.setColor( TQColorGroup::Base, color.dark( 115 ) ); } setPalette( pal ); } void KNoScrollListBox::keyPressEvent( TQKeyEvent *e ) { switch( e->key() ) { case Key_Right: scrollBy( 4, 0 ); break; case Key_Left: scrollBy( -4, 0 ); break; case Key_Up: if ( !count() ) break; setCurrentItem( ( currentItem() + count() - 1 ) % count() ); if ( !itemVisible( currentItem() ) ) { if ( (unsigned int)currentItem() == ( count() - 1 ) ) { setTopItem( currentItem() - numItemsVisible() + 1 ); } else { setTopItem( topItem() - 1 ); } } break; case Key_Down: if ( !count() ) break; setCurrentItem( ( currentItem() + 1 ) % count() ); if( !itemVisible( currentItem() ) ) { if( currentItem() == 0 ) { setTopItem( 0 ); } else { setTopItem( topItem() + 1 ); } } case Key_Shift: emit shiftDown(); break; default: break; } } void KNoScrollListBox::keyReleaseEvent( TQKeyEvent *e ) { switch( e->key() ) { case Key_Shift: emit shiftUp(); break; default: break; } } void KNoScrollListBox::mousePressEvent( TQMouseEvent *e ) { TQListBox::mousePressEvent( e ); if ( e->button() == TQt::RightButton ) { emit rightClick(); } } void KNoScrollListBox::contentsMouseDoubleClickEvent ( TQMouseEvent * e ) { TQListBox::contentsMouseDoubleClickEvent( e ); TQListBoxItem *item = itemAt( e->pos() ); if ( !item ) { emit doubleClicked( item ); } } void KNoScrollListBox::resizeEvent( TQResizeEvent *e ) { bool s = count() && ( maxItemWidth() > e->size().width() ); if ( mSqueezing || s ) triggerUpdate( false ); mSqueezing = s; TQListBox::resizeEvent( e ); } MonthViewItem::MonthViewItem( Incidence *incidence, const TQDateTime &qd, const TQString & s ) : TQListBoxItem() { setText( s ); mIncidence = incidence; mDateTime = qd; mEventPixmap = KOGlobals::self()->smallIcon( "appointment" ); mBirthdayPixmap = KOGlobals::self()->smallIcon( "calendarbirthday" ); mAnniversaryPixmap= KOGlobals::self()->smallIcon( "calendaranniversary" ); mTodoPixmap = KOGlobals::self()->smallIcon( "todo" ); mTodoDonePixmap = KOGlobals::self()->smallIcon( "checkedbox" ); mAlarmPixmap = KOGlobals::self()->smallIcon( "bell" ); mRecurPixmap = KOGlobals::self()->smallIcon( "recur" ); mReplyPixmap = KOGlobals::self()->smallIcon( "mail-reply-sender" ); mEvent = false; mTodo = false; mTodoDone = false; mRecur = false; mAlarm = false; mReply = false; } TQColor MonthViewItem::catColor() const { TQColor retColor; if ( !mIncidence ) { return retColor; } TQStringList categories = mIncidence->categories(); TQString cat; if ( !categories.isEmpty() ) { cat = categories.first(); } if ( cat.isEmpty() ) { retColor = KOPrefs::instance()->unsetCategoryColor(); } else { retColor = *( KOPrefs::instance()->categoryColor( cat ) ); } return retColor; } void MonthViewItem::paint( TQPainter *p ) { bool sel = isSelected(); TQColor bgColor = TQColor(); // Default invalid color; if ( mIncidence && mTodo ) { if ( static_cast( mIncidence )->isOverdue() ) { bgColor = KOPrefs::instance()->todoOverdueColor(); } else if ( static_cast( mIncidence )->dtDue().date() == TQDate::currentDate() ) { bgColor = KOPrefs::instance()->todoDueTodayColor(); } } if ( !bgColor.isValid() ) { if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceOnly || KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceInsideCategoryOutside ) { bgColor = resourceColor(); } else { bgColor = catColor(); } if ( !bgColor.isValid() ) { bgColor = palette().color( TQPalette::Normal, sel ? TQColorGroup::Highlight : TQColorGroup::Background ); } } TQColor frameColor; if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceOnly || KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) { frameColor = resourceColor(); } else { frameColor = catColor(); } if ( mIncidence ) { if ( mIncidence->categories().isEmpty() && KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemResourceInsideCategoryOutside ) { frameColor = bgColor; } if ( mIncidence->categories().isEmpty() && KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) { bgColor = frameColor; } } if ( !frameColor.isValid() ) { frameColor = palette().color( TQPalette::Normal, sel ? TQColorGroup::Highlight : TQColorGroup::Foreground ); } else { frameColor = frameColor.dark( 115 ); } // draw the box for the item p->setBackgroundColor( frameColor ); p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) ); int offset = 2; p->setBackgroundColor( bgColor ); p->eraseRect( offset, offset, listBox()->maxItemWidth()-2*offset, height( listBox() )-2*offset ); int x = 3; bool specialEvent = false; if ( mEvent ) { if ( mIncidence->customProperty( "KABC", "BIRTHDAY" ) == "YES" ) { specialEvent = true; if ( mIncidence->customProperty( "KABC", "ANNIVERSARY" ) == "YES" ) { p->drawPixmap( x, 0, mAnniversaryPixmap ); x += mAnniversaryPixmap.width() + 2; } else { p->drawPixmap( x, 0, mBirthdayPixmap ); x += mBirthdayPixmap.width() + 2; } // Do NOT put on the event pixmap because it takes up too much space //} else { // p->drawPixmap( x, 0, mEventPixmap ); // x += mEventPixmap.width() + 2; // } } if ( mTodo ) { p->drawPixmap( x, 0, mTodoPixmap ); x += mTodoPixmap.width() + 2; } if ( mTodoDone ) { p->drawPixmap( x, 0, mTodoDonePixmap ); x += mTodoPixmap.width() + 2; } if ( mRecur && !specialEvent ) { p->drawPixmap( x, 0, mRecurPixmap ); x += mRecurPixmap.width() + 2; } if ( mAlarm && !specialEvent ) { p->drawPixmap( x, 0, mAlarmPixmap ); x += mAlarmPixmap.width() + 2; } if ( mReply ) { p->drawPixmap(x, 0, mReplyPixmap ); x += mReplyPixmap.width() + 2; } TQFontMetrics fm = p->fontMetrics(); int yPos; int pmheight = TQMAX( mRecurPixmap.height(), TQMAX( mAlarmPixmap.height(), mReplyPixmap.height() ) ); if( pmheight < fm.height() ) yPos = fm.ascent() + fm.leading()/2; else yPos = pmheight/2 - fm.height()/2 + fm.ascent(); TQColor textColor = getTextColor( bgColor ); p->setPen( textColor ); KWordWrap::drawFadeoutText( p, x, yPos, listBox()->width() - x, text() ); } int MonthViewItem::height( const TQListBox *lb ) const { return TQMAX( TQMAX( mRecurPixmap.height(), mReplyPixmap.height() ), TQMAX( mAlarmPixmap.height(), lb->fontMetrics().lineSpacing()+1) ); } int MonthViewItem::width( const TQListBox *lb ) const { int x = 3; if( mRecur ) { x += mRecurPixmap.width()+2; } if( mAlarm ) { x += mAlarmPixmap.width()+2; } if( mReply ) { x += mReplyPixmap.width()+2; } return( x + lb->fontMetrics().boundingRect( text() ).width() + 1 ); } MonthViewCell::MonthViewCell( KOMonthView *parent) : TQWidget( parent ), mMonthView( parent ), mPrimary( false ), mHoliday( false ), isSelected( false ) { TQVBoxLayout *topLayout = new TQVBoxLayout( this ); mLabel = new TQLabel( this ); mLabel->setFrameStyle( TQFrame::Panel | TQFrame::Plain ); mLabel->setLineWidth( 1 ); mLabel->setAlignment( AlignCenter ); mItemList = new KNoScrollListBox( this ); mItemList->setMinimumSize( 10, 10 ); mItemList->setFrameStyle( TQFrame::Panel | TQFrame::Plain ); mItemList->setLineWidth( 1 ); topLayout->addWidget( mItemList ); mLabel->raise(); mStandardPalette = palette(); enableScrollBars( false ); updateConfig(); connect( mItemList, TQ_SIGNAL( doubleClicked( TQListBoxItem *) ), TQ_SLOT( defaultAction( TQListBoxItem * ) ) ); connect( mItemList, TQ_SIGNAL( rightButtonPressed( TQListBoxItem *, const TQPoint &) ), TQ_SLOT( contextMenu( TQListBoxItem * ) ) ); connect( mItemList, TQ_SIGNAL( clicked( TQListBoxItem * ) ), TQ_SLOT( select() ) ); } void MonthViewCell::setDate( const TQDate &date ) { // kdDebug(5850) << "MonthViewCell::setDate(): " << date.toString() << endl; mDate = date; setFrameWidth(); TQString text; if ( KOGlobals::self()->calendarSystem()->day( date ) == 1 ) { text = i18n("'Month day' for month view cells", "%1 %2") .arg( KOGlobals::self()->calendarSystem()->monthName( date, true ) ) .arg( KOGlobals::self()->calendarSystem()->day(mDate) ); TQFontMetrics fm( mLabel->font() ); mLabel->resize( mLabelSize + TQSize( fm.width( text ), 0 ) ); } else { mLabel->resize( mLabelSize ); text = TQString::number( KOGlobals::self()->calendarSystem()->day(mDate) ); } mLabel->setText( text ); new KOMonthCellToolTip( mItemList->viewport(), monthView()->calendar(), mDate, static_cast( mItemList ) ); resizeEvent( 0 ); } TQDate MonthViewCell::date() const { return mDate; } void MonthViewCell::setFrameWidth() { // show current day with a thicker frame if ( mDate == TQDate::currentDate() ) { mItemList->setLineWidth( 3 ); } else if ( !isSelected ) { mItemList->setLineWidth( 1 ); } } void MonthViewCell::setPrimary( bool primary ) { mPrimary = primary; if ( mPrimary ) { mLabel->setBackgroundMode( PaletteBase ); } else { mLabel->setBackgroundMode( PaletteBackground ); } mItemList->setBackground( mPrimary, KOGlobals::self()->isWorkDay( mDate ) ); } bool MonthViewCell::isPrimary() const { return mPrimary; } void MonthViewCell::setHoliday( bool holiday ) { mHoliday = holiday; if ( holiday ) { setPalette( mHolidayPalette ); } else { setPalette( mStandardPalette ); } } void MonthViewCell::setHolidayString( const TQString &holiday ) { mHolidayString = holiday; } void MonthViewCell::updateCell() { setFrameWidth(); if ( mDate == TQDate::currentDate() ) { setPalette( mTodayPalette ); TQPalette pal = mItemList->palette(); pal.setColor( TQColorGroup::Foreground, KOPrefs::instance()->highlightColor() ); mItemList->setPalette( pal ); } else { if ( mHoliday ) setPalette( mHolidayPalette ); else setPalette( mStandardPalette ); TQPalette pal = mItemList->palette(); pal.setColor( TQColorGroup::Foreground, KOPrefs::instance()->agendaBgColor().dark( 150 ) ); mItemList->setPalette( pal ); } mItemList->clear(); if ( !mHolidayString.isEmpty() ) { MonthViewItem *item = new MonthViewItem( 0, TQDateTime( mDate ), mHolidayString ); item->setPalette( mHolidayPalette ); mItemList->insertItem( item ); } } class MonthViewCell::CreateItemVisitor : public IncidenceBase::Visitor { public: CreateItemVisitor() : mItem(0) { emails = KOPrefs::instance()->allEmails(); } bool act( IncidenceBase *incidence, TQDate date, TQPalette stdPal, int multiDay ) { mItem = 0; mDate = date; mStandardPalette = stdPal; mMultiDay = multiDay; return incidence->accept( *this ); } MonthViewItem *item() const { return mItem; } TQStringList emails; protected: bool visit( Event *event ) { TQString text; TQDateTime dt( mDate ); // take the time 0:00 into account, which is non-inclusive TQDate dtEnd = event->dtEnd().addSecs( event->doesFloat() ? 0 : -1).date(); int length = event->dtStart().daysTo( TQDateTime(dtEnd) ); if ( event->isMultiDay() ) { if ( mDate == event->dtStart().date() || ( mMultiDay == 0 && event->recursOn( mDate ) ) ) { text = "(-- " + event->summary(); dt = event->dtStart(); } else if ( !event->doesRecur() && mDate == dtEnd // last day of a recurring multi-day event? || ( mMultiDay == length && event->recursOn( mDate.addDays( -length ) ) ) ) { text = event->summary() + " --)"; } else if (!(event->dtStart().date().daysTo(mDate) % 7) && length > 7 ) { text = "-- " + event->summary() + " --"; } else { text = "----------------"; dt = TQDateTime( mDate ); } } else { if (event->doesFloat()) text = event->summary(); else { text = TDEGlobal::locale()->formatTime(event->dtStart().time()); dt.setTime( event->dtStart().time() ); text += ' ' + event->summary(); } } mItem = new MonthViewItem( event, dt, text ); mItem->setEvent( true ); if ( KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryOnly || KOPrefs::instance()->monthItemColors() == KOPrefs::MonthItemCategoryInsideResourceOutside ) { TQStringList categories = event->categories(); TQString cat = categories.first(); if (cat.isEmpty()) { mItem->setPalette(TQPalette(KOPrefs::instance()->unsetCategoryColor(), KOPrefs::instance()->unsetCategoryColor()) ); } else { mItem->setPalette(TQPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat)))); } } else { mItem->setPalette( mStandardPalette ); } Attendee *me = event->attendeeByMails( emails ); if ( me != 0 ) { mItem->setReply( me->status() == Attendee::NeedsAction && me->RSVP() ); } else mItem->setReply(false); return true; } bool visit( Todo *todo ) { TQString text; if ( !KOPrefs::instance()->showAllDayTodo() ) return false; TQDateTime dt( mDate ); if ( todo->hasDueDate() && !todo->doesFloat() && todo->dtDue().time() != TQTime( 0,0 ) && todo->dtDue().time().isValid() ) { text += TDEGlobal::locale()->formatTime( todo->dtDue().time() ); text += ' '; dt.setTime( todo->dtDue().time() ); } text += todo->summary(); mItem = new MonthViewItem( todo, dt, text ); if ( todo->doesRecur() ) { mDate < todo->dtDue().date() ? mItem->setTodoDone( true ) : mItem->setTodo( true ); } else todo->isCompleted() ? mItem->setTodoDone( true ) : mItem->setTodo( true ); mItem->setPalette( mStandardPalette ); return true; } protected: MonthViewItem *mItem; TQDate mDate; TQPalette mStandardPalette; int mMultiDay; }; void MonthViewCell::addIncidence( Incidence *incidence, CreateItemVisitor& v, int multiDay ) { if ( v.act( incidence, mDate, mStandardPalette, multiDay ) ) { MonthViewItem *item = v.item(); if ( item ) { item->setAlarm( incidence->isAlarmEnabled() ); item->setRecur( incidence->recurrenceType() ); TQColor resourceColor = KOHelper::resourceColor( monthView()->calendar(), incidence ); if ( !resourceColor.isValid() ) resourceColor = KOPrefs::instance()->unsetCategoryColor(); item->setResourceColor( resourceColor ); // FIXME: Find the correct position (time-wise) to insert the item. // Currently, the items are displayed in "random" order instead of // chronologically sorted. uint i = 0; int pos = -1; TQDateTime dt( item->incidenceDateTime() ); while ( i < mItemList->count() && pos<0 ) { TQListBoxItem *item = mItemList->item( i ); MonthViewItem *mvitem = dynamic_cast( item ); if ( mvitem && mvitem->incidenceDateTime()>dt ) { pos = i; } ++i; } mItemList->insertItem( item, pos ); } } } void MonthViewCell::removeIncidence( Incidence *incidence ) { for ( uint i = 0; i < mItemList->count(); ++i ) { MonthViewItem *item = static_cast(mItemList->item( i ) ); if ( item && item->incidence() && item->incidence()->uid() == incidence->uid() ) { mItemList->removeItem( i ); --i; } } } void MonthViewCell::updateConfig() { setFont( KOPrefs::instance()->mMonthViewFont ); TQFontMetrics fm( font() ); mLabelSize = fm.size( 0, "30" ) + TQSize( mLabel->frameWidth() * 2, mLabel->frameWidth() * 2 ) + TQSize( 2, 2 ); // mStandardPalette = mOriginalPalette; TQColor bg = mStandardPalette.color( TQPalette::Active, TQColorGroup::Background ); int h,s,v; bg.getHsv( &h, &s, &v ); if ( date().month() %2 == 0 ) { if ( v < 128 ) { bg = bg.light( 125 ); } else { bg = bg.dark( 125 ); } } setPaletteBackgroundColor( bg ); // mStandardPalette.setColor( TQColorGroup::Background, bg);*/ mHolidayPalette = mStandardPalette; mHolidayPalette.setColor( TQColorGroup::Foreground, KOPrefs::instance()->holidayColor() ); mHolidayPalette.setColor( TQColorGroup::Text, KOPrefs::instance()->holidayColor() ); mTodayPalette = mStandardPalette; mTodayPalette.setColor( TQColorGroup::Foreground, KOPrefs::instance()->highlightColor() ); mTodayPalette.setColor( TQColorGroup::Text, KOPrefs::instance()->highlightColor() ); updateCell(); mItemList->setBackground( mPrimary, KOGlobals::self()->isWorkDay( mDate ) ); } void MonthViewCell::enableScrollBars( bool enabled ) { if ( enabled ) { mItemList->setVScrollBarMode( TQScrollView::Auto ); mItemList->setHScrollBarMode( TQScrollView::Auto ); } else { mItemList->setVScrollBarMode( TQScrollView::AlwaysOff ); mItemList->setHScrollBarMode( TQScrollView::AlwaysOff ); } } Incidence *MonthViewCell::selectedIncidence() { int index = mItemList->currentItem(); if ( index < 0 ) return 0; MonthViewItem *item = static_cast( mItemList->item( index ) ); if ( !item ) return 0; return item->incidence(); } TQDate MonthViewCell::selectedIncidenceDate() { TQDate qd; int index = mItemList->currentItem(); if ( index < 0 ) return qd; MonthViewItem *item = static_cast( mItemList->item( index ) ); if ( !item ) return qd; return item->incidenceDateTime().date(); } void MonthViewCell::select() { isSelected = true; // setSelectedCell will deselect currently selected cells mMonthView->setSelectedCell( this ); if( KOPrefs::instance()->enableMonthScroll() ) enableScrollBars( true ); // don't mess up the cell when it represents today if( mDate != TQDate::currentDate() ) { mItemList->setFrameStyle( TQFrame::Sunken | TQFrame::Panel ); mItemList->setLineWidth( 3 ); } } void MonthViewCell::deselect() { isSelected = false; mItemList->clearSelection(); mItemList->setFrameStyle( TQFrame::Plain | TQFrame::Panel ); setFrameWidth(); enableScrollBars( false ); } void MonthViewCell::resizeEvent ( TQResizeEvent * ) { mLabel->move( width() - mLabel->width(), height() - mLabel->height() ); } void MonthViewCell::defaultAction( TQListBoxItem *item ) { select(); if ( !item ) { emit newEventSignal( 0/*ResourceCalendar*/, TQString()/*subResource*/, date() ); } else { MonthViewItem *eventItem = static_cast( item ); Incidence *incidence = eventItem->incidence(); if ( incidence ) mMonthView->defaultAction( incidence ); } } void MonthViewCell::contextMenu( TQListBoxItem *item ) { select(); if ( item ) { MonthViewItem *eventItem = static_cast( item ); Incidence *incidence = eventItem->incidence(); if ( incidence ) { mMonthView->showEventContextMenu( monthView()->calendar(), incidence, mDate ); } } else { mMonthView->showGeneralContextMenu(); } } KOMonthView::KOMonthView( Calendar *calendar, TQWidget *parent, const char *name ) : KOEventView( calendar, parent, name ), mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ), mShortDayLabels( false ), mWidthLongDayLabel( 0 ), mSelectedCell( 0 ) { mCells.setAutoDelete( true ); TQGridLayout *dayLayout = new TQGridLayout( this ); TQFont bfont = font(); bfont.setBold( true ); TQFont mfont = bfont; mfont.setPointSize( 20 ); // month name on top mLabel = new TQLabel( this ); mLabel->setFont( mfont ); mLabel->setAlignment( AlignCenter ); mLabel->setLineWidth( 0 ); mLabel->setFrameStyle( TQFrame::Plain ); dayLayout->addMultiCellWidget( mLabel, 0, 0, 0, mDaysPerWeek ); // create the day of the week labels (Sun, Mon, etc) and add them to // the layout. mDayLabels.resize( mDaysPerWeek ); int i; for( i = 0; i < mDaysPerWeek; i++ ) { TQLabel *label = new TQLabel( this ); label->setFont( bfont ); label->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); label->setLineWidth( 1 ); label->setAlignment( AlignCenter ); mDayLabels.insert( i, label ); dayLayout->addWidget( label, 1, i ); dayLayout->addColSpacing( i, 10 ); dayLayout->setColStretch( i, 1 ); } int row, col; mCells.resize( mNumCells ); for( row = 0; row < mNumWeeks; ++row ) { for( col = 0; col < mDaysPerWeek; ++col ) { MonthViewCell *cell = new MonthViewCell( this ); mCells.insert( row * mDaysPerWeek + col, cell ); dayLayout->addWidget( cell, row + 2, col ); connect( cell, TQ_SIGNAL(defaultAction(Incidence *)), TQ_SLOT(defaultAction(Incidence *)) ); connect( cell, TQ_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)), TQ_SIGNAL(newEventSignal(ResourceCalendar *,const TQString &,const TQDate &)) ); } dayLayout->setRowStretch( row + 2, 1 ); } mEventContextMenu = eventPopup(); updateConfig(); emit incidenceSelected( 0, TQDate() ); } KOMonthView::~KOMonthView() { delete mEventContextMenu; } int KOMonthView::maxDatesHint() { return mNumCells; } int KOMonthView::currentDateCount() { return mNumCells; } Incidence::List KOMonthView::selectedIncidences() { Incidence::List selected; if ( mSelectedCell ) { Incidence *incidence = mSelectedCell->selectedIncidence(); if ( incidence ) selected.append( incidence ); } return selected; } DateList KOMonthView::selectedIncidenceDates() { DateList selected; if ( mSelectedCell ) { TQDate qd = mSelectedCell->selectedIncidenceDate(); if ( qd.isValid() ) selected.append( qd ); } return selected; } bool KOMonthView::eventDurationHint( TQDateTime &startDt, TQDateTime &endDt, bool &allDay ) { if ( mSelectedCell ) { startDt.setDate( mSelectedCell->date() ); endDt.setDate( mSelectedCell->date() ); allDay = true; return true; } return false; } void KOMonthView::updateConfig() { mWeekStartDay = TDEGlobal::locale()->weekStartDay(); TQFontMetrics fontmetric( mDayLabels[0]->font() ); mWidthLongDayLabel = 0; for ( int i = 0; i < 7; ++i ) { int width = fontmetric.width( KOGlobals::self()->calendarSystem()->weekDayName( i + 1 ) ); if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width; } updateDayLabels(); for ( uint i = 0; i < mCells.count(); ++i ) { mCells[i]->updateConfig(); } showLabel( !KOPrefs::instance()->fullViewMonth() ); } void KOMonthView::updateDayLabels() { kdDebug(5850) << "KOMonthView::updateDayLabels()" << endl; const KCalendarSystem*calsys=KOGlobals::self()->calendarSystem(); int currDay; for ( int i = 0; i < 7; i++ ) { currDay = i+mWeekStartDay; if ( currDay > 7 ) currDay -= 7; mDayLabels[i]->setText( calsys->weekDayName( currDay, mShortDayLabels ) ); } } void KOMonthView::showDates( const TQDate &start, const TQDate & ) { // kdDebug(5850) << "KOMonthView::showDates(): " << start.toString() << endl; const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); mDateToCell.clear(); // show first day of month on top for readability issues mStartDate = start.addDays( -start.day() + 1 ); // correct begin of week int weekdayCol=( mStartDate.dayOfWeek() + 7 - mWeekStartDay ) % 7; mStartDate = mStartDate.addDays( -weekdayCol ); mLabel->setText( i18n( "monthname year", "%1 %2" ) .arg( calSys->monthName( start ) ) .arg( calSys->year( start ) ) ); showLabel( !KOPrefs::instance()->fullViewMonth() ); bool primary = false; uint i; for( i = 0; i < mCells.size(); ++i ) { TQDate date = mStartDate.addDays( i ); if ( calSys->day( date ) == 1 ) { primary = !primary; } mCells[i]->setDate( date ); mDateToCell[ date ] = mCells[ i ]; if( date == start ) { mCells[i]->select(); } mCells[i]->setPrimary( primary ); bool isHoliday = calSys->dayOfWeek( date ) == calSys->weekDayOfPray() || !KOGlobals::self()->isWorkDay( date ); mCells[i]->setHoliday( isHoliday ); // add holiday, if present TQStringList holidays( KOGlobals::self()->holiday( date ) ); mCells[i]->setHolidayString( holidays.join( i18n("delimiter for joining holiday names", ", " ) ) ); } updateView(); } TQDateTime KOMonthView::selectionStart() { if ( mSelectedCell) { return TQDateTime( mSelectedCell->date() ); } else { return TQDateTime(); } } TQDateTime KOMonthView::selectionEnd() { // Only one cell can be selected (for now) return selectionStart(); } void KOMonthView::showIncidences( const Incidence::List &, const TQDate & ) { kdDebug(5850) << "KOMonthView::showIncidences( const Incidence::List & ) is not implemented yet." << endl; } class KOMonthView::GetDateVisitor : public IncidenceBase::Visitor { public: GetDateVisitor() {} bool act( IncidenceBase *incidence ) { return incidence->accept( *this ); } TQDateTime startDate() const { return mStartDate; } TQDateTime endDate() const { return mEndDate; } protected: bool visit( Event *event ) { mStartDate = event->dtStart(); mEndDate = event->dtEnd(); return true; } bool visit( Todo *todo ) { if ( todo->hasDueDate() ) { if ( todo->dtDue().time() != TQTime( 0, 0 ) && todo->dtDue().time().isValid() ) { mStartDate = todo->dtDue(); mEndDate = todo->dtDue(); } else { mStartDate = TQDateTime( todo->dtDue().date(), TQTime( 23,59 ) ); mEndDate = mStartDate; } }// else // return false; return true; } bool visit( Journal *journal ) { mStartDate = journal->dtStart(); mEndDate = journal->dtStart(); return true; } protected: TQDateTime mStartDate; TQDateTime mEndDate; }; void KOMonthView::changeIncidenceDisplayAdded( Incidence *incidence, MonthViewCell::CreateItemVisitor& v) { GetDateVisitor gdv; if ( !gdv.act( incidence ) ) { kdDebug(5850) << "Visiting GetDateVisitor failed." << endl; return; } bool floats = incidence->doesFloat(); if ( incidence->doesRecur() ) { for ( uint i = 0; i < mCells.count(); ++i ) { if ( incidence->recursOn( mCells[i]->date(), calendar() ) ) { // handle multiday events int length = gdv.startDate().daysTo( TQDateTime(gdv.endDate().addSecs( floats ? 0 : -1 ).date()) ); for ( int j = 0; j <= length && i+j < mCells.count(); ++j ) { mCells[i+j]->addIncidence( incidence, v, j ); } } } } else { // addSecs(-1) is added to handle 0:00 cases (because it's non-inclusive according to rfc) if ( gdv.endDate().isValid() ) { TQDate endDate = gdv.endDate().addSecs( floats ? 0 : -1).date(); for ( TQDate date = gdv.startDate().date(); date <= endDate; date = date.addDays( 1 ) ) { MonthViewCell *mvc = mDateToCell[ date ]; if ( mvc ) mvc->addIncidence( incidence, v ); } } } } void KOMonthView::changeIncidenceDisplay( Incidence *incidence, int action ) { MonthViewCell::CreateItemVisitor v; switch ( action ) { case KOGlobals::INCIDENCEADDED: changeIncidenceDisplayAdded( incidence, v ); break; case KOGlobals::INCIDENCEEDITED: for( uint i = 0; i < mCells.count(); i++ ) mCells[i]->removeIncidence( incidence ); changeIncidenceDisplayAdded( incidence, v ); break; case KOGlobals::INCIDENCEDELETED: for( uint i = 0; i < mCells.count(); i++ ) mCells[i]->removeIncidence( incidence ); break; default: return; } } void KOMonthView::updateView() { for( uint i = 0; i < mCells.count(); ++i ) { mCells[i]->updateCell(); } Incidence::List incidences = calendar()->incidences(); Incidence::List::ConstIterator it; MonthViewCell::CreateItemVisitor v; for ( it = incidences.begin(); it != incidences.end(); ++it ) changeIncidenceDisplayAdded( *it, v ); processSelectionChange(); } void KOMonthView::resizeEvent( TQResizeEvent * ) { // select the appropriate heading string size. E.g. "Wednesday" or "Wed". // note this only changes the text if the requested size crosses the // threshold between big enough to support the full name and not big // enough. if( mDayLabels[0]->width() < mWidthLongDayLabel ) { if ( !mShortDayLabels ) { mShortDayLabels = true; updateDayLabels(); } } else { if ( mShortDayLabels ) { mShortDayLabels = false; updateDayLabels(); } } } void KOMonthView::showEventContextMenu( Calendar *cal, Incidence *incidence, const TQDate &qd ) { mEventContextMenu->showIncidencePopup( cal, incidence, qd ); } void KOMonthView::showGeneralContextMenu() { showNewEventPopup(); } void KOMonthView::setSelectedCell( MonthViewCell *cell ) { if ( mSelectedCell && cell != mSelectedCell ) mSelectedCell->deselect(); mSelectedCell = cell; if ( !mSelectedCell ) emit incidenceSelected( 0, TQDate() ); else if ( selectedIncidenceDates().isEmpty() ) { emit incidenceSelected( mSelectedCell->selectedIncidence(), TQDate() ); } else { emit incidenceSelected( mSelectedCell->selectedIncidence(), selectedIncidenceDates().first() ); } } void KOMonthView::processSelectionChange() { Incidence::List incidences = selectedIncidences(); if (incidences.count() > 0) { if ( selectedIncidenceDates().isEmpty() ) { emit incidenceSelected( incidences.first(), TQDate() ); } else { emit incidenceSelected( incidences.first(), selectedIncidenceDates().first() ); } } else { emit incidenceSelected( 0, TQDate() ); } } void KOMonthView::clearSelection() { if ( mSelectedCell ) { mSelectedCell->deselect(); mSelectedCell = 0; } } void KOMonthView::showLabel( bool show ) { if ( show ) { mLabel->show(); } else { mLabel->hide(); } }