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