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 #include <qhbox.h>
00026 #include <qvbox.h>
00027 #include <qlabel.h>
00028 #include <qframe.h>
00029 #include <qlayout.h>
00030 #ifndef KORG_NOSPLITTER
00031 #include <qsplitter.h>
00032 #endif
00033 #include <qfont.h>
00034 #include <qfontmetrics.h>
00035 #include <qpopupmenu.h>
00036 #include <qtooltip.h>
00037 #include <qpainter.h>
00038 #include <qpushbutton.h>
00039 #include <qcursor.h>
00040 #include <qbitarray.h>
00041
00042 #include <kapplication.h>
00043 #include <kdebug.h>
00044 #include <kstandarddirs.h>
00045 #include <kiconloader.h>
00046 #include <klocale.h>
00047 #include <kconfig.h>
00048 #include <kglobal.h>
00049 #include <kglobalsettings.h>
00050 #include <kholidays.h>
00051
00052 #include <libkcal/calendar.h>
00053 #include <libkcal/icaldrag.h>
00054 #include <libkcal/dndfactory.h>
00055 #include <libkcal/calfilter.h>
00056
00057 #include <kcalendarsystem.h>
00058
00059 #include "koglobals.h"
00060 #ifndef KORG_NOPLUGINS
00061 #include "kocore.h"
00062 #endif
00063 #include "koprefs.h"
00064 #include "koagenda.h"
00065 #include "koagendaitem.h"
00066 #include "timelabels.h"
00067
00068 #include "koincidencetooltip.h"
00069 #include "kogroupware.h"
00070 #include "kodialogmanager.h"
00071 #include "koeventpopupmenu.h"
00072
00073 #include "koagendaview.h"
00074 #include "koagendaview.moc"
00075
00076 using namespace KOrg;
00077
00078
00079 EventIndicator::EventIndicator(Location loc,QWidget *parent,const char *name)
00080 : QFrame(parent,name)
00081 {
00082 mColumns = 1;
00083 mEnabled.resize( mColumns );
00084 mLocation = loc;
00085
00086 if (mLocation == Top) mPixmap = KOGlobals::self()->smallIcon("upindicator");
00087 else mPixmap = KOGlobals::self()->smallIcon("downindicator");
00088
00089 setMinimumHeight(mPixmap.height());
00090 }
00091
00092 EventIndicator::~EventIndicator()
00093 {
00094 }
00095
00096 void EventIndicator::drawContents(QPainter *p)
00097 {
00098
00099
00100
00101
00102 int i;
00103 for(i=0;i<mColumns;++i) {
00104 if (mEnabled[i]) {
00105 int cellWidth = contentsRect().right()/mColumns;
00106 int xOffset = KOGlobals::self()->reverseLayout() ?
00107 (mColumns - 1 - i)*cellWidth + cellWidth/2 -mPixmap.width()/2 :
00108 i*cellWidth + cellWidth/2 -mPixmap.width()/2;
00109 p->drawPixmap(QPoint(xOffset,0),mPixmap);
00110 }
00111 }
00112 }
00113
00114 void EventIndicator::changeColumns(int columns)
00115 {
00116 mColumns = columns;
00117 mEnabled.resize(mColumns);
00118
00119 update();
00120 }
00121
00122 void EventIndicator::enableColumn(int column, bool enable)
00123 {
00124 mEnabled[column] = enable;
00125 }
00126
00127
00128 #include <libkcal/incidence.h>
00129
00133
00134
00135 KOAlternateLabel::KOAlternateLabel(const QString &shortlabel, const QString &longlabel,
00136 const QString &extensivelabel, QWidget *parent, const char *name )
00137 : QLabel(parent, name), mTextTypeFixed(false), mShortText(shortlabel),
00138 mLongText(longlabel), mExtensiveText(extensivelabel)
00139 {
00140 setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ));
00141 if (mExtensiveText.isEmpty()) mExtensiveText = mLongText;
00142 squeezeTextToLabel();
00143 }
00144
00145 KOAlternateLabel::~KOAlternateLabel()
00146 {
00147 }
00148
00149 void KOAlternateLabel::useShortText()
00150 {
00151 mTextTypeFixed = true;
00152 QLabel::setText( mShortText );
00153 QToolTip::remove( this );
00154 QToolTip::add( this, mExtensiveText );
00155 }
00156
00157 void KOAlternateLabel::useLongText()
00158 {
00159 mTextTypeFixed = true;
00160 QLabel::setText( mLongText );
00161 QToolTip::remove( this );
00162 QToolTip::add( this, mExtensiveText );
00163 }
00164
00165 void KOAlternateLabel::useExtensiveText()
00166 {
00167 mTextTypeFixed = true;
00168 QLabel::setText( mExtensiveText );
00169 QToolTip::remove( this );
00170 QToolTip::add( this, "" );
00171 }
00172
00173 void KOAlternateLabel::useDefaultText()
00174 {
00175 mTextTypeFixed = false;
00176 squeezeTextToLabel();
00177 }
00178
00179 KOAlternateLabel::TextType KOAlternateLabel::largestFittingTextType() const
00180 {
00181 QFontMetrics fm( fontMetrics() );
00182 const int labelWidth = size().width();
00183 const int longTextWidth = fm.width( mLongText );
00184 const int extensiveTextWidth = fm.width( mExtensiveText );
00185 if ( extensiveTextWidth <= labelWidth )
00186 return Extensive;
00187 else if ( longTextWidth <= labelWidth )
00188 return Long;
00189 else
00190 return Short;
00191 }
00192
00193 void KOAlternateLabel::setFixedType( TextType type )
00194 {
00195 switch ( type )
00196 {
00197 case Extensive: useExtensiveText(); break;
00198 case Long: useLongText(); break;
00199 case Short: useShortText(); break;
00200 }
00201 }
00202
00203 void KOAlternateLabel::squeezeTextToLabel()
00204 {
00205 if ( mTextTypeFixed )
00206 return;
00207
00208 const TextType type = largestFittingTextType();
00209 switch ( type )
00210 {
00211 case Extensive:
00212 QLabel::setText( mExtensiveText );
00213 QToolTip::remove( this );
00214 QToolTip::add( this, "" );
00215 break;
00216 case Long:
00217 QLabel::setText( mLongText );
00218 QToolTip::remove( this );
00219 QToolTip::add( this, mExtensiveText );
00220 break;
00221 case Short:
00222 QLabel::setText( mShortText );
00223 QToolTip::remove( this );
00224 QToolTip::add( this, mExtensiveText );
00225 break;
00226 }
00227 }
00228
00229 void KOAlternateLabel::resizeEvent( QResizeEvent * )
00230 {
00231 squeezeTextToLabel();
00232 }
00233
00234 QSize KOAlternateLabel::minimumSizeHint() const
00235 {
00236 QSize sh = QLabel::minimumSizeHint();
00237 sh.setWidth(-1);
00238 return sh;
00239 }
00240
00244
00245 KOAgendaView::KOAgendaView( Calendar *cal,
00246 CalendarView *calendarView,
00247 QWidget *parent,
00248 const char *name,
00249 bool isSideBySide ) :
00250 KOrg::AgendaView (cal, parent,name), mExpandButton( 0 ),
00251 mAllowAgendaUpdate( true ),
00252 mUpdateItem( 0 ),
00253 mIsSideBySide( isSideBySide ),
00254 mPendingChanges( true )
00255 {
00256 mSelectedDates.append(QDate::currentDate());
00257
00258 mLayoutDayLabels = 0;
00259 mDayLabelsFrame = 0;
00260 mDayLabels = 0;
00261
00262 bool isRTL = KOGlobals::self()->reverseLayout();
00263
00264 if ( KOPrefs::instance()->compactDialogs() ) {
00265 if ( KOPrefs::instance()->mVerticalScreen ) {
00266 mExpandedPixmap = KOGlobals::self()->smallIcon( "1downarrow" );
00267 mNotExpandedPixmap = KOGlobals::self()->smallIcon( "1uparrow" );
00268 } else {
00269 mExpandedPixmap = KOGlobals::self()->smallIcon( isRTL ? "1leftarrow" : "1rightarrow" );
00270 mNotExpandedPixmap = KOGlobals::self()->smallIcon( isRTL ? "1rightarrow" : "1leftarrow" );
00271 }
00272 }
00273
00274 QBoxLayout *topLayout = new QVBoxLayout(this);
00275
00276
00277 mDayLabelsFrame = new QHBox(this);
00278 topLayout->addWidget(mDayLabelsFrame);
00279
00280
00281 #ifndef KORG_NOSPLITTER
00282 mSplitterAgenda = new QSplitter(Vertical,this);
00283 topLayout->addWidget(mSplitterAgenda);
00284
00285 #if KDE_IS_VERSION( 3, 1, 93 )
00286 mSplitterAgenda->setOpaqueResize( KGlobalSettings::opaqueResize() );
00287 #else
00288 mSplitterAgenda->setOpaqueResize();
00289 #endif
00290
00291 mAllDayFrame = new QHBox(mSplitterAgenda);
00292
00293 QWidget *agendaFrame = new QWidget(mSplitterAgenda);
00294 #else
00295 QVBox *mainBox = new QVBox( this );
00296 topLayout->addWidget( mainBox );
00297
00298 mAllDayFrame = new QHBox(mainBox);
00299
00300 QWidget *agendaFrame = new QWidget(mainBox);
00301 #endif
00302
00303
00304 mDummyAllDayLeft = new QVBox( mAllDayFrame );
00305 if ( isSideBySide )
00306 mDummyAllDayLeft->hide();
00307
00308 if ( KOPrefs::instance()->compactDialogs() ) {
00309 mExpandButton = new QPushButton(mDummyAllDayLeft);
00310 mExpandButton->setPixmap( mNotExpandedPixmap );
00311 mExpandButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed,
00312 QSizePolicy::Fixed ) );
00313 connect( mExpandButton, SIGNAL( clicked() ), SIGNAL( toggleExpand() ) );
00314 } else {
00315 QLabel *label = new QLabel( i18n("All Day"), mDummyAllDayLeft );
00316 label->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::WordBreak );
00317 }
00318
00319 mAllDayAgenda = new KOAgenda( 1, calendarView, mAllDayFrame );
00320 mAllDayAgenda->setCalendar( calendar() );
00321 QWidget *dummyAllDayRight = new QWidget(mAllDayFrame);
00322
00323
00324 QGridLayout *agendaLayout = new QGridLayout(agendaFrame,3,3);
00325
00326
00327
00328 mEventIndicatorTop = new EventIndicator(EventIndicator::Top,agendaFrame);
00329 agendaLayout->addWidget(mEventIndicatorTop,0,1);
00330 mEventIndicatorBottom = new EventIndicator(EventIndicator::Bottom,
00331 agendaFrame);
00332 agendaLayout->addWidget(mEventIndicatorBottom,2,1);
00333 QWidget *dummyAgendaRight = new QWidget(agendaFrame);
00334 agendaLayout->addWidget(dummyAgendaRight,0,2);
00335
00336
00337 mTimeLabels = new TimeLabels(24,agendaFrame);
00338 agendaLayout->addWidget(mTimeLabels,1,0);
00339
00340
00341 mAgenda = new KOAgenda( 1, 96, KOPrefs::instance()->mHourSize, calendarView, agendaFrame );
00342 mAgenda->setCalendar( calendar() );
00343 agendaLayout->addMultiCellWidget(mAgenda,1,1,1,2);
00344 agendaLayout->setColStretch(1,1);
00345
00346
00347 mAgendaPopup = eventPopup();
00348
00349
00350 mAllDayAgendaPopup = eventPopup();
00351
00352
00353 mTimeLabels->setAgenda(mAgenda);
00354 if ( isSideBySide )
00355 mTimeLabels->hide();
00356
00357
00358
00359
00360 createDayLabels( true );
00361
00362 if ( !isSideBySide ) {
00363
00364 dummyAllDayRight->setFixedWidth(mAgenda->verticalScrollBar()->width());
00365 dummyAgendaRight->setFixedWidth(mAgenda->verticalScrollBar()->width());
00366 }
00367
00368 updateTimeBarWidth();
00369
00370
00371 connect(mAgenda->verticalScrollBar(),SIGNAL(valueChanged(int)),
00372 mTimeLabels, SLOT(positionChanged()));
00373
00374 connect( mAgenda,
00375 SIGNAL( zoomView( const int, const QPoint & ,const Qt::Orientation ) ),
00376 SLOT( zoomView( const int, const QPoint &, const Qt::Orientation ) ) );
00377
00378 connect(mTimeLabels->verticalScrollBar(),SIGNAL(valueChanged(int)),
00379 SLOT(setContentsPos(int)));
00380
00381
00382 connect( mAgenda, SIGNAL(newTimeSpanSignal(const QPoint &, const QPoint &)),
00383 SLOT(newTimeSpanSelected(const QPoint &, const QPoint &)));
00384 connect( mAllDayAgenda, SIGNAL(newTimeSpanSignal(const QPoint &, const QPoint &)),
00385 SLOT(newTimeSpanSelectedAllDay(const QPoint &, const QPoint &)));
00386
00387
00388 connect( mAgenda, SIGNAL(lowerYChanged(int)),
00389 SLOT(updateEventIndicatorTop(int)));
00390 connect( mAgenda, SIGNAL(upperYChanged(int)),
00391 SLOT(updateEventIndicatorBottom(int)));
00392
00393 if ( !readOnly() ) {
00394 connectAgenda( mAgenda, mAgendaPopup, mAllDayAgenda );
00395 connectAgenda( mAllDayAgenda, mAllDayAgendaPopup, mAgenda);
00396 }
00397
00398 if ( cal ) {
00399 cal->registerObserver( this );
00400 }
00401 }
00402
00403
00404 KOAgendaView::~KOAgendaView()
00405 {
00406 if ( calendar() )
00407 calendar()->unregisterObserver( this );
00408 delete mAgendaPopup;
00409 delete mAllDayAgendaPopup;
00410 }
00411
00412 void KOAgendaView::connectAgenda( KOAgenda *agenda, QPopupMenu *popup,
00413 KOAgenda *otherAgenda )
00414 {
00415 connect( agenda, SIGNAL(showIncidencePopupSignal(Calendar *,Incidence *,const QDate &)),
00416 popup, SLOT(showIncidencePopup(Calendar *,Incidence *,const QDate &)) );
00417
00418 connect( agenda, SIGNAL(showNewEventPopupSignal()),
00419 SLOT(showNewEventPopup()) );
00420
00421
00422
00423 connect( agenda, SIGNAL(newEventSignal(ResourceCalendar *,const QString &)),
00424 SIGNAL(newEventSignal(ResourceCalendar *,const QString &)) );
00425
00426 connect( agenda, SIGNAL(newStartSelectSignal()),
00427 otherAgenda, SLOT(clearSelection()) );
00428 connect( agenda, SIGNAL(newStartSelectSignal()),
00429 SIGNAL(timeSpanSelectionChanged()) );
00430
00431 connect( agenda, SIGNAL(editIncidenceSignal(Incidence *,const QDate &)),
00432 SIGNAL(editIncidenceSignal(Incidence *,const QDate &)) );
00433 connect( agenda, SIGNAL(showIncidenceSignal(Incidence *,const QDate &)),
00434 SIGNAL(showIncidenceSignal(Incidence *,const QDate &)) );
00435 connect( agenda, SIGNAL(deleteIncidenceSignal(Incidence *)),
00436 SIGNAL(deleteIncidenceSignal(Incidence *)) );
00437
00438 connect( agenda, SIGNAL(startMultiModify(const QString &)),
00439 SIGNAL(startMultiModify(const QString &)) );
00440 connect( agenda, SIGNAL(endMultiModify()),
00441 SIGNAL(endMultiModify()) );
00442
00443 connect( agenda, SIGNAL(itemModified(KOAgendaItem *)),
00444 SLOT(updateEventDates(KOAgendaItem *)) );
00445
00446 connect( agenda, SIGNAL(enableAgendaUpdate(bool)),
00447 SLOT(enableAgendaUpdate(bool)) );
00448
00449
00450 connect( agenda, SIGNAL(startDragSignal(Incidence *)),
00451 SLOT(startDrag(Incidence *)) );
00452
00453
00454 connect( agenda, SIGNAL(incidenceSelected(Incidence *,const QDate &)),
00455 otherAgenda, SLOT(deselectItem()) );
00456 connect( agenda, SIGNAL(incidenceSelected(Incidence *,const QDate &)),
00457 SIGNAL(incidenceSelected(Incidence *,const QDate &)) );
00458
00459
00460 connect( agenda, SIGNAL(droppedToDo(Todo *,const QPoint &,bool)),
00461 SLOT(slotTodoDropped(Todo *,const QPoint &,bool)) );
00462
00463 }
00464
00465 void KOAgendaView::zoomInVertically( )
00466 {
00467 if ( !mIsSideBySide )
00468 KOPrefs::instance()->mHourSize++;
00469 mAgenda->updateConfig();
00470 mAgenda->checkScrollBoundaries();
00471
00472 mTimeLabels->updateConfig();
00473 mTimeLabels->positionChanged();
00474 mTimeLabels->repaint();
00475
00476 updateView();
00477 }
00478
00479 void KOAgendaView::zoomOutVertically( )
00480 {
00481
00482 if ( KOPrefs::instance()->mHourSize > 4 || mIsSideBySide ) {
00483
00484 if ( !mIsSideBySide )
00485 KOPrefs::instance()->mHourSize--;
00486 mAgenda->updateConfig();
00487 mAgenda->checkScrollBoundaries();
00488
00489 mTimeLabels->updateConfig();
00490 mTimeLabels->positionChanged();
00491 mTimeLabels->repaint();
00492
00493 updateView();
00494 }
00495 }
00496
00497 void KOAgendaView::zoomInHorizontally( const QDate &date)
00498 {
00499 QDate begin;
00500 QDate newBegin;
00501 QDate dateToZoom = date;
00502 int ndays,count;
00503
00504 begin = mSelectedDates.first();
00505 ndays = begin.daysTo( mSelectedDates.last() );
00506
00507
00508 if ( ! dateToZoom.isValid () )
00509 dateToZoom=mAgenda->selectedIncidenceDate();
00510
00511 if( !dateToZoom.isValid() ) {
00512 if ( ndays > 1 ) {
00513 newBegin=begin.addDays(1);
00514 count = ndays-1;
00515 emit zoomViewHorizontally ( newBegin , count );
00516 }
00517 } else {
00518 if ( ndays <= 2 ) {
00519 newBegin = dateToZoom;
00520 count = 1;
00521 } else {
00522 newBegin = dateToZoom.addDays( -ndays/2 +1 );
00523 count = ndays -1 ;
00524 }
00525 emit zoomViewHorizontally ( newBegin , count );
00526 }
00527 }
00528
00529 void KOAgendaView::zoomOutHorizontally( const QDate &date )
00530 {
00531 QDate begin;
00532 QDate newBegin;
00533 QDate dateToZoom = date;
00534 int ndays,count;
00535
00536 begin = mSelectedDates.first();
00537 ndays = begin.daysTo( mSelectedDates.last() );
00538
00539
00540 if ( ! dateToZoom.isValid () )
00541 dateToZoom=mAgenda->selectedIncidenceDate();
00542
00543 if ( !dateToZoom.isValid() ) {
00544 newBegin = begin.addDays(-1);
00545 count = ndays+3 ;
00546 } else {
00547 newBegin = dateToZoom.addDays( -ndays/2-1 );
00548 count = ndays+3;
00549 }
00550
00551 if ( abs( count ) >= 31 )
00552 kdDebug(5850) << "change to the mounth view?"<<endl;
00553 else
00554
00555 emit zoomViewHorizontally( newBegin, count );
00556 }
00557
00558 void KOAgendaView::zoomView( const int delta, const QPoint &pos,
00559 const Qt::Orientation orient )
00560 {
00561 static QDate zoomDate;
00562 static QTimer *t = new QTimer( this );
00563
00564
00565
00566
00567 if ( orient == Qt::Horizontal ) {
00568 QDate date=mAgenda->selectedIncidenceDate();
00569 if ( date.isValid() )
00570 zoomDate=date;
00571 else{
00572 if ( !t->isActive() ) {
00573 zoomDate= mSelectedDates[pos.x()];
00574 }
00575 t->start ( 1000,true );
00576 }
00577 if ( delta > 0 )
00578 zoomOutHorizontally( zoomDate );
00579 else
00580 zoomInHorizontally( zoomDate );
00581 } else {
00582
00583 QPoint posConstentsOld = mAgenda->gridToContents(pos);
00584 if ( delta > 0 ) {
00585 zoomOutVertically();
00586 } else {
00587 zoomInVertically();
00588 }
00589 QPoint posConstentsNew = mAgenda->gridToContents(pos);
00590 mAgenda->scrollBy( 0, posConstentsNew.y() - posConstentsOld.y() );
00591 }
00592 }
00593
00594 void KOAgendaView::createDayLabels( bool force )
00595 {
00596
00597
00598
00599
00600 if ( !force && mSaveSelectedDates == mSelectedDates ) {
00601 return;
00602 }
00603 mSaveSelectedDates = mSelectedDates;
00604
00605 delete mDayLabels;
00606 mDateDayLabels.clear();
00607
00608 mDayLabels = new QFrame (mDayLabelsFrame);
00609 mLayoutDayLabels = new QHBoxLayout(mDayLabels);
00610 if ( !mIsSideBySide )
00611 mLayoutDayLabels->addSpacing(mTimeLabels->width());
00612
00613 const KCalendarSystem*calsys=KOGlobals::self()->calendarSystem();
00614
00615 DateList::ConstIterator dit;
00616 for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) {
00617 QDate date = *dit;
00618 QBoxLayout *dayLayout = new QVBoxLayout(mLayoutDayLabels);
00619 mLayoutDayLabels->setStretchFactor(dayLayout, 1);
00620
00621
00622 int dW = calsys->dayOfWeek(date);
00623 QString veryLongStr = KGlobal::locale()->formatDate( date );
00624 QString longstr = i18n( "short_weekday date (e.g. Mon 13)","%1 %2" )
00625 .arg( calsys->weekDayName( dW, true ) )
00626 .arg( calsys->day(date) );
00627 QString shortstr = QString::number(calsys->day(date));
00628
00629 KOAlternateLabel *dayLabel = new KOAlternateLabel(shortstr,
00630 longstr, veryLongStr, mDayLabels);
00631 dayLabel->useShortText();
00632 dayLabel->setMinimumWidth(1);
00633 dayLabel->setAlignment(QLabel::AlignHCenter);
00634 if (date == QDate::currentDate()) {
00635 QFont font = dayLabel->font();
00636 font.setBold(true);
00637 dayLabel->setFont(font);
00638 }
00639 dayLayout->addWidget(dayLabel);
00640 mDateDayLabels.append( dayLabel );
00641
00642
00643 QStringList texts = KOGlobals::self()->holiday( date );
00644 QStringList::ConstIterator textit = texts.begin();
00645 for ( ; textit != texts.end(); ++textit ) {
00646
00647 KOAlternateLabel*label = new KOAlternateLabel( (*textit), (*textit), QString::null, mDayLabels );
00648 label->setMinimumWidth(1);
00649 label->setAlignment(AlignCenter);
00650 dayLayout->addWidget(label);
00651 }
00652
00653 #ifndef KORG_NOPLUGINS
00654 CalendarDecoration::List cds = KOCore::self()->calendarDecorations();
00655 CalendarDecoration *it;
00656 for(it = cds.first(); it; it = cds.next()) {
00657 QString text = it->shortText( date );
00658 if ( !text.isEmpty() ) {
00659
00660 KOAlternateLabel*label = new KOAlternateLabel( text, text, QString::null, mDayLabels );
00661 label->setMinimumWidth(1);
00662 label->setAlignment(AlignCenter);
00663 dayLayout->addWidget(label);
00664 }
00665 }
00666
00667 for(it = cds.first(); it; it = cds.next()) {
00668 QWidget *wid = it->smallWidget(mDayLabels,date);
00669 if ( wid ) {
00670
00671 dayLayout->addWidget(wid);
00672 }
00673 }
00674 #endif
00675 }
00676
00677 if ( !mIsSideBySide )
00678 mLayoutDayLabels->addSpacing(mAgenda->verticalScrollBar()->width());
00679 mDayLabels->show();
00680 QTimer::singleShot( 0, this, SLOT( updateDayLabelSizes() ) );
00681 }
00682
00683 void KOAgendaView::enableAgendaUpdate( bool enable )
00684 {
00685 mAllowAgendaUpdate = enable;
00686 }
00687
00688 int KOAgendaView::maxDatesHint()
00689 {
00690
00691 return 0;
00692 }
00693
00694 int KOAgendaView::currentDateCount()
00695 {
00696 return mSelectedDates.count();
00697 }
00698
00699 Incidence::List KOAgendaView::selectedIncidences()
00700 {
00701 Incidence::List selected;
00702 Incidence *incidence;
00703
00704 incidence = mAgenda->selectedIncidence();
00705 if (incidence) selected.append(incidence);
00706
00707 incidence = mAllDayAgenda->selectedIncidence();
00708 if (incidence) selected.append(incidence);
00709
00710 return selected;
00711 }
00712
00713 DateList KOAgendaView::selectedIncidenceDates()
00714 {
00715 DateList selected;
00716 QDate qd;
00717
00718 qd = mAgenda->selectedIncidenceDate();
00719 if (qd.isValid()) selected.append(qd);
00720
00721 qd = mAllDayAgenda->selectedIncidenceDate();
00722 if (qd.isValid()) selected.append(qd);
00723
00724 return selected;
00725 }
00726
00727 bool KOAgendaView::eventDurationHint( QDateTime &startDt, QDateTime &endDt,
00728 bool &allDay )
00729 {
00730 if ( selectionStart().isValid() ) {
00731 QDateTime start = selectionStart();
00732 QDateTime end = selectionEnd();
00733
00734 if ( start.secsTo( end ) == 15*60 ) {
00735
00736
00737 QTime defaultDuration( KOPrefs::instance()->mDefaultDuration.time() );
00738 int addSecs = ( defaultDuration.hour()*3600 ) +
00739 ( defaultDuration.minute()*60 );
00740 end = start.addSecs( addSecs );
00741 }
00742
00743 startDt = start;
00744 endDt = end;
00745 allDay = selectedIsAllDay();
00746 return true;
00747 }
00748 return false;
00749 }
00750
00752 bool KOAgendaView::selectedIsSingleCell()
00753 {
00754 if ( !selectionStart().isValid() || !selectionEnd().isValid() ) return false;
00755
00756 if (selectedIsAllDay()) {
00757 int days = selectionStart().daysTo(selectionEnd());
00758 return ( days < 1 );
00759 } else {
00760 int secs = selectionStart().secsTo(selectionEnd());
00761 return ( secs <= 24*60*60/mAgenda->rows() );
00762 }
00763 }
00764
00765
00766 void KOAgendaView::updateView()
00767 {
00768
00769 fillAgenda();
00770 }
00771
00772
00773
00774
00775
00776
00777 void KOAgendaView::updateConfig()
00778 {
00779
00780
00781
00782 mTimeLabels->updateConfig();
00783 mAgenda->updateConfig();
00784 mAllDayAgenda->updateConfig();
00785
00786
00787
00788 mTimeLabels->positionChanged();
00789
00790
00791 mTimeLabels->repaint();
00792
00793 updateTimeBarWidth();
00794
00795
00796 KOAgendaItem::toolTipGroup()->setEnabled(KOPrefs::instance()
00797 ->mEnableToolTips);
00798
00799 setHolidayMasks();
00800
00801 createDayLabels( true );
00802
00803 updateView();
00804 }
00805
00806 void KOAgendaView::updateTimeBarWidth()
00807 {
00808 int width;
00809
00810 width = mDummyAllDayLeft->fontMetrics().width( i18n("All Day") );
00811 width = QMAX( width, mTimeLabels->width() );
00812
00813 mDummyAllDayLeft->setFixedWidth( width );
00814 mTimeLabels->setFixedWidth( width );
00815 }
00816
00817 void KOAgendaView::updateDayLabelSizes()
00818 {
00819
00820 KOAlternateLabel::TextType overallType = KOAlternateLabel::Extensive;
00821 QPtrList<KOAlternateLabel>::const_iterator it = mDateDayLabels.constBegin();
00822 for( ; it != mDateDayLabels.constEnd(); it++ ) {
00823 KOAlternateLabel::TextType type = (*it)->largestFittingTextType();
00824 if ( type < overallType )
00825 overallType = type;
00826 }
00827
00828
00829 it = mDateDayLabels.constBegin();
00830 for( ; it != mDateDayLabels.constEnd(); it++ ) {
00831 (*it)->setFixedType( overallType );
00832 }
00833 }
00834
00835 void KOAgendaView::resizeEvent( QResizeEvent *resizeEvent )
00836 {
00837 updateDayLabelSizes();
00838 KOrg::AgendaView::resizeEvent( resizeEvent );
00839 }
00840
00841 void KOAgendaView::updateEventDates( KOAgendaItem *item )
00842 {
00843 kdDebug(5850) << "KOAgendaView::updateEventDates(): " << item->text() << endl;
00844
00845 QDateTime startDt,endDt;
00846
00847
00848
00849
00850
00851 QDate thisDate;
00852 if ( item->cellXLeft() < 0 ) {
00853 thisDate = ( mSelectedDates.first() ).addDays( item->cellXLeft() );
00854 } else {
00855 thisDate = mSelectedDates[ item->cellXLeft() ];
00856 }
00857 QDate oldThisDate( item->itemDate() );
00858 int daysOffset = oldThisDate.daysTo( thisDate );
00859 int daysLength = 0;
00860
00861
00862
00863 Incidence *incidence = item->incidence();
00864 if ( !incidence ) return;
00865 if ( !mChanger ||
00866 !mChanger->beginChange( incidence, resourceCalendar(), subResourceCalendar() ) ) {
00867 return;
00868 }
00869 Incidence *oldIncidence = incidence->clone();
00870
00871 QTime startTime(0,0,0), endTime(0,0,0);
00872 if ( incidence->doesFloat() ) {
00873 daysLength = item->cellWidth() - 1;
00874 } else {
00875 startTime = mAgenda->gyToTime( item->cellYTop() );
00876 if ( item->lastMultiItem() ) {
00877 endTime = mAgenda->gyToTime( item->lastMultiItem()->cellYBottom() + 1 );
00878 daysLength = item->lastMultiItem()->cellXLeft() - item->cellXLeft();
00879 } else {
00880 endTime = mAgenda->gyToTime( item->cellYBottom() + 1 );
00881 }
00882 }
00883
00884
00885
00886 if ( incidence->type() == "Event" ) {
00887 startDt = incidence->dtStart();
00888 startDt = startDt.addDays( daysOffset );
00889 startDt.setTime( startTime );
00890 endDt = startDt.addDays( daysLength );
00891 endDt.setTime( endTime );
00892 Event*ev = static_cast<Event*>(incidence);
00893 if( incidence->dtStart() == startDt && ev->dtEnd() == endDt ) {
00894
00895 delete oldIncidence;
00896 return;
00897 }
00898 incidence->setDtStart( startDt );
00899 ev->setDtEnd( endDt );
00900 } else if ( incidence->type() == "Todo" ) {
00901 Todo *td = static_cast<Todo*>(incidence);
00902 startDt = td->hasStartDate() ? td->dtStart() : td->dtDue();
00903 startDt = thisDate.addDays( td->dtDue().daysTo( startDt ) );
00904 startDt.setTime( startTime );
00905 endDt.setDate( thisDate );
00906 endDt.setTime( endTime );
00907
00908 if( td->dtDue() == endDt ) {
00909
00910 delete oldIncidence;
00911 return;
00912 }
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 if ( incidence->type() == "Event" ) {
01062 incidence->setDtStart( startDt );
01063 (static_cast<Event*>( incidence ) )->setDtEnd( endDt );
01064 } else if ( incidence->type() == "Todo" ) {
01065 Todo *td = static_cast<Todo*>( incidence );
01066 if ( td->hasStartDate() )
01067 td->setDtStart( startDt );
01068 td->setDtDue( endDt );
01069 }
01070
01071 item->setItemDate( startDt.date() );
01072
01073 KOIncidenceToolTip::remove( item );
01074 KOIncidenceToolTip::add( item, calendar(), incidence, thisDate, KOAgendaItem::toolTipGroup() );
01075
01076 const bool result = mChanger->changeIncidence( oldIncidence, incidence,
01077 KOGlobals::DATE_MODIFIED, this );
01078 mChanger->endChange( incidence, resourceCalendar(), subResourceCalendar() );
01079 delete oldIncidence;
01080
01081 if ( !result ) {
01082 mPendingChanges = true;
01083 QTimer::singleShot( 0, this, SLOT(updateView()) );
01084 return;
01085 }
01086
01087
01088
01089
01090 enableAgendaUpdate( false );
01091
01092
01093
01094
01095 if ( incidence->doesRecur() ) {
01096 mUpdateItem = incidence;
01097 QTimer::singleShot( 0, this, SLOT( doUpdateItem() ) );
01098 }
01099
01100 enableAgendaUpdate( true );
01101
01102
01103 }
01104
01105 void KOAgendaView::doUpdateItem()
01106 {
01107 if ( mUpdateItem ) {
01108 changeIncidenceDisplay( mUpdateItem, KOGlobals::INCIDENCEEDITED );
01109 mUpdateItem = 0;
01110 }
01111 }
01112
01113
01114
01115 void KOAgendaView::showDates( const QDate &start, const QDate &end )
01116 {
01117
01118 if ( !mSelectedDates.isEmpty() && mSelectedDates.first() == start
01119 && mSelectedDates.last() == end && !mPendingChanges )
01120 return;
01121
01122 mSelectedDates.clear();
01123
01124 QDate d = start;
01125 while (d <= end) {
01126 mSelectedDates.append(d);
01127 d = d.addDays( 1 );
01128 }
01129
01130
01131 fillAgenda();
01132 }
01133
01134
01135 void KOAgendaView::showIncidences( const Incidence::List &, const QDate & )
01136 {
01137 kdDebug(5850) << "KOAgendaView::showIncidences( const Incidence::List & ) is not yet implemented" << endl;
01138 }
01139
01140 void KOAgendaView::insertIncidence( Incidence *incidence, const QDate &curDate )
01141 {
01142 if ( !filterByResource( incidence ) ) {
01143 return;
01144 }
01145
01146
01147 Event *event = dynamic_cast<Event *>( incidence );
01148 Todo *todo = dynamic_cast<Todo *>( incidence );
01149
01150 int curCol = mSelectedDates.first().daysTo( curDate );
01151
01152
01153 if ( curCol < 0 ) {
01154 curCol = 0;
01155 }
01156
01157
01158 if ( curCol >= int( mSelectedDates.count() ) ) {
01159 return;
01160 }
01161
01162
01163 mMinY[curCol] = mAgenda->timeToY( QTime( 23, 59 ) ) + 1;
01164 mMaxY[curCol] = mAgenda->timeToY( QTime( 0, 0 ) ) - 1;
01165
01166 int beginX;
01167 int endX;
01168 QDate columnDate;
01169 if ( event ) {
01170 QDate firstVisibleDate = mSelectedDates.first();
01171
01172 if ( curDate < firstVisibleDate ) {
01173 beginX = curCol + firstVisibleDate.daysTo( curDate );
01174 endX = beginX + event->dtStart().daysTo( event->dtEnd() );
01175 columnDate = firstVisibleDate;
01176 } else {
01177 beginX = curCol;
01178 endX = beginX + event->dtStart().daysTo( event->dtEnd() );
01179 columnDate = curDate;
01180 }
01181 } else if ( todo ) {
01182 if ( !todo->hasDueDate() ) {
01183 return;
01184 }
01185 columnDate = curDate;
01186 beginX = endX = curCol;
01187
01188 } else {
01189 return;
01190 }
01191 if ( todo && todo->isOverdue() ) {
01192 mAllDayAgenda->insertAllDayItem( incidence, columnDate, curCol, curCol );
01193 } else if ( incidence->doesFloat() ||
01194 ( todo &&
01195 !todo->dtDue().isValid() ) ) {
01196 mAllDayAgenda->insertAllDayItem( incidence, columnDate, beginX, endX );
01197 } else if ( event && event->isMultiDay() ) {
01198 int startY = mAgenda->timeToY( event->dtStart().time() );
01199 QTime endtime = event->dtEnd().time();
01200 if ( endtime == QTime( 0, 0, 0 ) ) {
01201 endtime = QTime( 23, 59, 59 );
01202 }
01203 int endY = mAgenda->timeToY( endtime ) - 1;
01204 if ( ( beginX <= 0 && curCol == 0 ) || beginX == curCol ) {
01205 mAgenda->insertMultiItem( event, columnDate, beginX, endX, startY, endY );
01206
01207 }
01208 if ( beginX == curCol ) {
01209 mMaxY[curCol] = mAgenda->timeToY( QTime( 23, 59 ) );
01210 if ( startY < mMinY[curCol] ) {
01211 mMinY[curCol] = startY;
01212 }
01213 } else if ( endX == curCol ) {
01214 mMinY[curCol] = mAgenda->timeToY( QTime( 0, 0 ) );
01215 if ( endY > mMaxY[curCol] ) {
01216 mMaxY[curCol] = endY;
01217 }
01218 } else {
01219 mMinY[curCol] = mAgenda->timeToY( QTime( 0, 0 ) );
01220 mMaxY[curCol] = mAgenda->timeToY( QTime( 23, 59 ) );
01221 }
01222 } else {
01223 int startY = 0, endY = 0;
01224 if ( event ) {
01225 startY = mAgenda->timeToY( incidence->dtStart().time() );
01226 QTime endtime = event->dtEnd().time();
01227 if ( endtime == QTime( 0, 0, 0 ) ) {
01228 endtime = QTime( 23, 59, 59 );
01229 }
01230 endY = mAgenda->timeToY( endtime ) - 1;
01231 }
01232 if ( todo ) {
01233 QTime t = todo->dtDue().time();
01234
01235 if ( t == QTime( 0, 0 ) ) {
01236 t = QTime( 23, 59 );
01237 }
01238
01239 int halfHour = 1800;
01240 if ( t.addSecs( -halfHour ) < t ) {
01241 startY = mAgenda->timeToY( t.addSecs( -halfHour ) );
01242 endY = mAgenda->timeToY( t ) - 1;
01243 } else {
01244 startY = 0;
01245 endY = mAgenda->timeToY( t.addSecs( halfHour ) ) - 1;
01246 }
01247 }
01248 if ( endY < startY ) {
01249 endY = startY;
01250 }
01251 mAgenda->insertItem( incidence, columnDate, curCol, startY, endY );
01252 if ( startY < mMinY[curCol] ) {
01253 mMinY[curCol] = startY;
01254 }
01255 if ( endY > mMaxY[curCol] ) {
01256 mMaxY[curCol] = endY;
01257 }
01258 }
01259 }
01260
01261 void KOAgendaView::changeIncidenceDisplayAdded( Incidence *incidence )
01262 {
01263 Todo *todo = dynamic_cast<Todo *>(incidence);
01264 CalFilter *filter = calendar()->filter();
01265 if ( ( filter && !filter->filterIncidence( incidence ) ) ||
01266 ( ( todo && !KOPrefs::instance()->showAllDayTodo() ) ) ) {
01267 return;
01268 }
01269
01270 displayIncidence( incidence );
01271 }
01272
01273 void KOAgendaView::changeIncidenceDisplay( Incidence *incidence, int mode )
01274 {
01275 switch ( mode ) {
01276 case KOGlobals::INCIDENCEADDED:
01277 {
01278
01279
01280
01281
01282
01283 changeIncidenceDisplayAdded( incidence );
01284 updateEventIndicators();
01285 break;
01286 }
01287 case KOGlobals::INCIDENCEEDITED:
01288 {
01289 if ( mAllowAgendaUpdate ) {
01290 removeIncidence( incidence );
01291 changeIncidenceDisplayAdded( incidence );
01292 }
01293 updateEventIndicators();
01294 break;
01295 }
01296 case KOGlobals::INCIDENCEDELETED:
01297 {
01298 removeIncidence( incidence );
01299 updateEventIndicators();
01300 break;
01301 }
01302 default:
01303 return;
01304 }
01305
01306
01307
01308
01309
01310 if ( incidence->doesFloat() ) {
01311 updateView();
01312 }
01313 }
01314
01315 void KOAgendaView::fillAgenda( const QDate & )
01316 {
01317 fillAgenda();
01318 }
01319
01320 void KOAgendaView::fillAgenda()
01321 {
01322 mPendingChanges = false;
01323
01324
01325
01326 const QString &selectedAgendaUid = mAgenda->lastSelectedUid();
01327 const QString &selectedAllDayAgendaUid = mAllDayAgenda->lastSelectedUid();
01328
01329 enableAgendaUpdate( true );
01330 clearView();
01331
01332 mAllDayAgenda->changeColumns( mSelectedDates.count() );
01333 mAgenda->changeColumns( mSelectedDates.count() );
01334 mEventIndicatorTop->changeColumns( mSelectedDates.count() );
01335 mEventIndicatorBottom->changeColumns( mSelectedDates.count() );
01336
01337 createDayLabels( false );
01338 setHolidayMasks();
01339
01340 mMinY.resize( mSelectedDates.count() );
01341 mMaxY.resize( mSelectedDates.count() );
01342
01343 mAgenda->setDateList( mSelectedDates );
01344
01345 bool somethingReselected = false;
01346 Incidence::List incidences = calendar()->incidences();
01347
01348 for ( Incidence::List::ConstIterator it = incidences.begin(); it!=incidences.constEnd(); ++it ) {
01349 Incidence *incidence = (*it);
01350 displayIncidence( incidence );
01351
01352 if( incidence->uid() == selectedAgendaUid && !selectedAgendaUid.isNull() ) {
01353 mAgenda->selectItemByUID( incidence->uid() );
01354 somethingReselected = true;
01355 }
01356
01357 if( incidence->uid() == selectedAllDayAgendaUid && !selectedAllDayAgendaUid.isNull() ) {
01358 mAllDayAgenda->selectItemByUID( incidence->uid() );
01359 somethingReselected = true;
01360 }
01361
01362 }
01363
01364 mAgenda->checkScrollBoundaries();
01365 updateEventIndicators();
01366
01367
01368
01369
01370
01371 deleteSelectedDateTime();
01372
01373 if( !somethingReselected ) {
01374 emit incidenceSelected( 0, QDate() );
01375 }
01376 }
01377
01378 void KOAgendaView::displayIncidence( Incidence *incidence )
01379 {
01380 QDate today = QDate::currentDate();
01381 DateTimeList::iterator t;
01382
01383
01384 Todo *todo = dynamic_cast<Todo *>( incidence );
01385 Event *event = dynamic_cast<Event *>( incidence );
01386
01387 QDateTime firstVisibleDateTime = mSelectedDates.first();
01388 QDateTime lastVisibleDateTime = mSelectedDates.last();
01389
01390 lastVisibleDateTime.setTime( QTime( 23, 59, 59, 59 ) );
01391 firstVisibleDateTime.setTime( QTime( 0, 0 ) );
01392 DateTimeList dateTimeList;
01393
01394 QDateTime incDtStart = incidence->dtStart();
01395 QDateTime incDtEnd = incidence->dtEnd();
01396
01397 if ( todo &&
01398 ( !KOPrefs::instance()->showAllDayTodo() || !todo->hasDueDate() ) ) {
01399 return;
01400 }
01401
01402 if ( incidence->doesRecur() ) {
01403 int eventDuration = event ? incDtStart.daysTo( incDtEnd ) : 0;
01404
01405
01406
01407
01408 QDateTime startDateTimeWithOffset = firstVisibleDateTime.addDays( -eventDuration );
01409 dateTimeList =
01410 incidence->recurrence()->timesInInterval( startDateTimeWithOffset,
01411 lastVisibleDateTime );
01412 } else {
01413 QDateTime dateToAdd;
01414 QDateTime incidenceStart;
01415 QDateTime incidenceEnd;
01416
01417 if ( todo && todo->hasDueDate() && !todo->isOverdue() ) {
01418
01419 dateToAdd = todo->dtDue();
01420
01421
01422
01423 if ( !todo->doesFloat() && dateToAdd.time() == QTime( 0, 0 ) ) {
01424 dateToAdd = dateToAdd.addSecs( -1 );
01425 }
01426
01427 incidenceEnd = dateToAdd;
01428 } else if ( event ) {
01429 dateToAdd = incDtStart;
01430 incidenceEnd = incDtEnd;
01431 }
01432
01433 if ( incidence->doesFloat() ) {
01434
01435 dateToAdd.setTime( QTime( 0, 0 ) );
01436 incidenceEnd.setTime( QTime( 23, 59, 59, 59 ) );
01437 }
01438
01439 if ( dateToAdd <= lastVisibleDateTime && incidenceEnd > firstVisibleDateTime ) {
01440 dateTimeList += dateToAdd;
01441 }
01442 }
01443
01444
01445 QDateTime dateTimeToday = today;
01446 if ( todo &&
01447 todo->isOverdue() &&
01448 dateTimeToday >= firstVisibleDateTime &&
01449 dateTimeToday <= lastVisibleDateTime ) {
01450
01451 bool doAdd = true;
01452
01453 if ( todo->doesRecur() ) {
01454
01455
01456 for ( t = dateTimeList.begin(); t != dateTimeList.end(); ++t ) {
01457 if ( (*t).date() == today ) {
01458 doAdd = false;
01459 break;
01460 }
01461 }
01462 }
01463
01464 if ( doAdd ) {
01465 dateTimeList += dateTimeToday;
01466 }
01467 }
01468
01469 for ( t = dateTimeList.begin(); t != dateTimeList.end(); ++t ) {
01470 insertIncidence( incidence, (*t).date() );
01471 }
01472 }
01473
01474 void KOAgendaView::clearView()
01475 {
01476
01477 mAllDayAgenda->clear();
01478 mAgenda->clear();
01479 }
01480
01481 CalPrinterBase::PrintType KOAgendaView::printType()
01482 {
01483 if ( currentDateCount() == 1 ) return CalPrinterBase::Day;
01484 else return CalPrinterBase::Week;
01485 }
01486
01487 void KOAgendaView::updateEventIndicatorTop( int newY )
01488 {
01489 uint i;
01490 for( i = 0; i < mMinY.size(); ++i ) {
01491 mEventIndicatorTop->enableColumn( i, newY > mMinY[i] );
01492 }
01493 mEventIndicatorTop->update();
01494 }
01495
01496 void KOAgendaView::updateEventIndicatorBottom( int newY )
01497 {
01498 uint i;
01499 for( i = 0; i < mMaxY.size(); ++i ) {
01500 mEventIndicatorBottom->enableColumn( i, newY <= mMaxY[i] );
01501 }
01502 mEventIndicatorBottom->update();
01503 }
01504
01505 void KOAgendaView::slotTodoDropped( Todo *todo, const QPoint &gpos, bool allDay )
01506 {
01507 if ( gpos.x()<0 || gpos.y()<0 ) return;
01508 QDate day = mSelectedDates[gpos.x()];
01509 QTime time = mAgenda->gyToTime( gpos.y() );
01510 QDateTime newTime( day, time );
01511
01512 if ( todo ) {
01513 Todo *existingTodo = calendar()->todo( todo->uid() );
01514 if ( existingTodo ) {
01515 kdDebug(5850) << "Drop existing Todo" << endl;
01516 Todo *oldTodo = existingTodo->clone();
01517 if ( mChanger &&
01518 mChanger->beginChange( existingTodo, resourceCalendar(), subResourceCalendar() ) ) {
01519 existingTodo->setDtDue( newTime );
01520 existingTodo->setFloats( allDay );
01521 existingTodo->setHasDueDate( true );
01522 mChanger->changeIncidence( oldTodo, existingTodo,
01523 KOGlobals::DATE_MODIFIED, this );
01524 mChanger->endChange( existingTodo, resourceCalendar(), subResourceCalendar() );
01525 } else {
01526 KMessageBox::sorry( this, i18n("Unable to modify this to-do, "
01527 "because it cannot be locked.") );
01528 }
01529 delete oldTodo;
01530 } else {
01531 kdDebug(5850) << "Drop new Todo" << endl;
01532 todo->setDtDue( newTime );
01533 todo->setFloats( allDay );
01534 todo->setHasDueDate( true );
01535 if ( !mChanger->addIncidence( todo, 0, QString(), this ) ) {
01536 KODialogManager::errorSaveIncidence( this, todo );
01537 }
01538 }
01539 }
01540 }
01541
01542 void KOAgendaView::startDrag( Incidence *incidence )
01543 {
01544 #ifndef KORG_NODND
01545 DndFactory factory( calendar() );
01546 ICalDrag *vd = factory.createDrag( incidence, this );
01547 if ( vd->drag() ) {
01548 kdDebug(5850) << "KOAgendaView::startDrag(): Delete drag source" << endl;
01549 }
01550 #endif
01551 }
01552
01553 void KOAgendaView::readSettings()
01554 {
01555 readSettings(KOGlobals::self()->config());
01556 }
01557
01558 void KOAgendaView::readSettings(KConfig *config)
01559 {
01560
01561
01562 config->setGroup("Views");
01563
01564 #ifndef KORG_NOSPLITTER
01565 QValueList<int> sizes = config->readIntListEntry("Separator AgendaView");
01566 if (sizes.count() == 2) {
01567 mSplitterAgenda->setSizes(sizes);
01568 }
01569 #endif
01570
01571 updateConfig();
01572 }
01573
01574 void KOAgendaView::writeSettings(KConfig *config)
01575 {
01576
01577
01578 config->setGroup("Views");
01579
01580 #ifndef KORG_NOSPLITTER
01581 QValueList<int> list = mSplitterAgenda->sizes();
01582 config->writeEntry("Separator AgendaView",list);
01583 #endif
01584 }
01585
01586 void KOAgendaView::setHolidayMasks()
01587 {
01588 if ( mSelectedDates.isEmpty() || !mSelectedDates[0].isValid() ) {
01589 return;
01590 }
01591
01592 mHolidayMask.resize( mSelectedDates.count() + 1 );
01593
01594 for( uint i = 0; i < mSelectedDates.count(); ++i ) {
01595 mHolidayMask[i] = !KOGlobals::self()->isWorkDay( mSelectedDates[ i ] );
01596 }
01597
01598
01599
01600 bool showDay = !KOGlobals::self()->isWorkDay( mSelectedDates[ 0 ].addDays( -1 ) );
01601 mHolidayMask[ mSelectedDates.count() ] = showDay;
01602
01603 mAgenda->setHolidayMask( &mHolidayMask );
01604 mAllDayAgenda->setHolidayMask( &mHolidayMask );
01605 }
01606
01607 void KOAgendaView::setContentsPos( int y )
01608 {
01609 mAgenda->setContentsPos( 0, y );
01610 }
01611
01612 void KOAgendaView::setExpandedButton( bool expanded )
01613 {
01614 if ( !mExpandButton ) return;
01615
01616 if ( expanded ) {
01617 mExpandButton->setPixmap( mExpandedPixmap );
01618 } else {
01619 mExpandButton->setPixmap( mNotExpandedPixmap );
01620 }
01621 }
01622
01623 void KOAgendaView::clearSelection()
01624 {
01625 mAgenda->deselectItem();
01626 mAllDayAgenda->deselectItem();
01627 }
01628
01629 void KOAgendaView::newTimeSpanSelectedAllDay( const QPoint &start, const QPoint &end )
01630 {
01631 newTimeSpanSelected( start, end );
01632 mTimeSpanInAllDay = true;
01633 }
01634
01635 void KOAgendaView::newTimeSpanSelected( const QPoint &start, const QPoint &end )
01636 {
01637 if (!mSelectedDates.count()) return;
01638
01639 mTimeSpanInAllDay = false;
01640
01641 QDate dayStart = mSelectedDates[ kClamp( start.x(), 0, (int)mSelectedDates.size() - 1 ) ];
01642 QDate dayEnd = mSelectedDates[ kClamp( end.x(), 0, (int)mSelectedDates.size() - 1 ) ];
01643
01644 QTime timeStart = mAgenda->gyToTime(start.y());
01645 QTime timeEnd = mAgenda->gyToTime( end.y() + 1 );
01646
01647 QDateTime dtStart(dayStart,timeStart);
01648 QDateTime dtEnd(dayEnd,timeEnd);
01649
01650 mTimeSpanBegin = dtStart;
01651 mTimeSpanEnd = dtEnd;
01652 }
01653
01654 void KOAgendaView::deleteSelectedDateTime()
01655 {
01656 mTimeSpanBegin.setDate(QDate());
01657 mTimeSpanEnd.setDate(QDate());
01658 mTimeSpanInAllDay = false;
01659 }
01660
01661 void KOAgendaView::setTypeAheadReceiver( QObject *o )
01662 {
01663 mAgenda->setTypeAheadReceiver( o );
01664 mAllDayAgenda->setTypeAheadReceiver( o );
01665 }
01666
01667 void KOAgendaView::finishTypeAhead()
01668 {
01669 mAgenda->finishTypeAhead();
01670 mAllDayAgenda->finishTypeAhead();
01671 }
01672
01673 void KOAgendaView::removeIncidence( Incidence *incidence )
01674 {
01675 mAgenda->removeIncidence( incidence );
01676 mAllDayAgenda->removeIncidence( incidence );
01677 }
01678
01679 void KOAgendaView::updateEventIndicators()
01680 {
01681 mMinY = mAgenda->minContentsY();
01682 mMaxY = mAgenda->maxContentsY();
01683
01684 mAgenda->checkScrollBoundaries();
01685 updateEventIndicatorTop( mAgenda->visibleContentsYMin() );
01686 updateEventIndicatorBottom( mAgenda->visibleContentsYMax() );
01687 }
01688
01689 void KOAgendaView::setIncidenceChanger( IncidenceChangerBase *changer )
01690 {
01691 mChanger = changer;
01692 mAgenda->setIncidenceChanger( changer );
01693 mAllDayAgenda->setIncidenceChanger( changer );
01694 }
01695
01696 void KOAgendaView::clearTimeSpanSelection()
01697 {
01698 mAgenda->clearSelection();
01699 mAllDayAgenda->clearSelection();
01700 deleteSelectedDateTime();
01701 }
01702
01703 bool KOAgendaView::filterByResource( Incidence *incidence )
01704 {
01705
01706
01707
01708
01709 if ( resourceCalendar() && incidence->type() == "Todo" ) {
01710 QString subRes = resourceCalendar()->subresourceIdentifier( incidence );
01711 if ( resourceCalendar()->subresourceType( subRes ) == "todo" ) {
01712 QString calmatch = "/.INBOX.directory/Calendar";
01713 QString i18nmatch = "/.INBOX.directory/" + i18n( "Calendar" );
01714 if ( subResourceCalendar().contains( calmatch ) ||
01715 subResourceCalendar().contains( i18nmatch ) ) {
01716 return true;
01717 }
01718 }
01719 }
01720
01721
01722 if ( !resourceCalendar() )
01723 return true;
01724 CalendarResources *calRes = dynamic_cast<CalendarResources*>( calendar() );
01725 if ( !calRes )
01726 return true;
01727 if ( calRes->resource( incidence ) != resourceCalendar() )
01728 return false;
01729 if ( !subResourceCalendar().isEmpty() ) {
01730 if ( resourceCalendar()->subresourceIdentifier( incidence ) != subResourceCalendar() )
01731 return false;
01732 }
01733 return true;
01734 }
01735
01736 void KOAgendaView::resourcesChanged()
01737 {
01738 mPendingChanges = true;
01739 }
01740
01741 void KOAgendaView::calendarIncidenceAdded(Incidence * incidence)
01742 {
01743 Q_UNUSED( incidence );
01744 mPendingChanges = true;
01745 }
01746
01747 void KOAgendaView::calendarIncidenceChanged(Incidence * incidence)
01748 {
01749 Q_UNUSED( incidence );
01750 mPendingChanges = true;
01751 }
01752
01753 void KOAgendaView::calendarIncidenceDeleted(Incidence * incidence)
01754 {
01755 Q_UNUSED( incidence );
01756 mPendingChanges = true;
01757 }