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 *oldIncidence = incidence->clone();
00880
00881 QTime startTime( 0, 0, 0 ), endTime( 0, 0, 0 );
00882 if ( incidence->doesFloat() ) {
00883 daysLength = item->cellWidth() - 1;
00884 } else {
00885 startTime = mAgenda->gyToTime( item->cellYTop() );
00886 if ( item->lastMultiItem() ) {
00887 endTime = mAgenda->gyToTime( item->lastMultiItem()->cellYBottom() + 1 );
00888 daysLength = item->lastMultiItem()->cellXLeft() - item->cellXLeft();
00889 kdDebug(5850) << "item->lastMultiItem()->cellXLeft(): " << item->lastMultiItem()->cellXLeft()
00890 << endl;
00891 } else if ( item->itemPos() == item->itemCount() && item->itemCount() > 1 ) {
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 endTime = mAgenda->gyToTime( item->cellYBottom() + 1 );
00903 daysLength = item->itemCount() - 1;
00904 startTime = incidence->dtStart().time();
00905 } else if ( item->itemPos() == 1 && item->itemCount() > 1 ) {
00906
00907 endTime = incidence->dtEnd().time();
00908 daysLength = item->itemCount() - 1;
00909 } else {
00910 endTime = mAgenda->gyToTime( item->cellYBottom() + 1 );
00911 }
00912 }
00913
00914 kdDebug(5850) << "daysLength: " << daysLength << "; startTime: " << startTime
00915 << "; endTime: " << endTime << "; thisDate: " << thisDate
00916 << "; incidence->dtStart(): " << incidence->dtStart() << endl;
00917
00918 if ( incidence->type() == "Event" ) {
00919 startDt = incidence->dtStart();
00920 startDt = startDt.addDays( daysOffset );
00921 startDt.setTime( startTime );
00922 endDt = startDt.addDays( daysLength );
00923 endDt.setTime( endTime );
00924 Event* ev = static_cast<Event*>( incidence );
00925 if ( incidence->dtStart() == startDt && ev->dtEnd() == endDt ) {
00926
00927 delete oldIncidence;
00928 return;
00929 }
00930 incidence->setDtStart( startDt );
00931 ev->setDtEnd( endDt );
00932 } else if ( incidence->type() == "Todo" ) {
00933
00934
00935
00936 Todo *td = static_cast<Todo*>( incidence );
00937 startDt = td->hasStartDate() ? td->dtStart() : td->dtDue();
00938 startDt = thisDate.addDays( td->dtDue().daysTo( startDt ) );
00939 startDt.setTime( startTime );
00940 endDt.setDate( thisDate );
00941 endDt.setTime( endTime );
00942
00943 if ( td->dtDue() == endDt ) {
00944
00945 delete oldIncidence;
00946 return;
00947 }
00948
00949 if ( td->hasStartDate() ) {
00950 td->setDtStart( startDt );
00951 }
00952 td->setDtDue( endDt );
00953 }
00954
00955 item->setItemDate( startDt.date() );
00956
00957 KOIncidenceToolTip::remove( item );
00958 KOIncidenceToolTip::add( item, calendar(), incidence, thisDate, KOAgendaItem::toolTipGroup() );
00959
00960
00961 bool result;
00962 kdDebug() << "New date is " << incidence->dtStart() << endl;
00963 if ( addIncidence ) {
00964 result = mChanger->addIncidence( incidence, res, subRes, this, useLastGroupwareDialogAnswer );
00965 } else {
00966 result = mChanger->changeIncidence( oldIncidence, incidence,
00967 KOGlobals::DATE_MODIFIED, this, useLastGroupwareDialogAnswer );
00968 mChanger->endChange( incidence, resourceCalendar(), subResourceCalendar() );
00969 }
00970
00971 delete oldIncidence;
00972
00973 if ( !result ) {
00974 mPendingChanges = true;
00975 QTimer::singleShot( 0, this, SLOT(updateView()) );
00976 return;
00977 }
00978
00979
00980
00981
00982 enableAgendaUpdate( false );
00983
00984
00985
00986
00987
00988 if ( incidence->doesRecur() ) {
00989 mUpdateItem = incidence;
00990 QTimer::singleShot( 0, this, SLOT( doUpdateItem() ) );
00991 }
00992
00993 enableAgendaUpdate( true );
00994 }
00995
00996 void KOAgendaView::doUpdateItem()
00997 {
00998 if ( mUpdateItem ) {
00999 changeIncidenceDisplay( mUpdateItem, KOGlobals::INCIDENCEEDITED );
01000 mUpdateItem = 0;
01001 }
01002 }
01003
01004
01005
01006 void KOAgendaView::showDates( const QDate &start, const QDate &end )
01007 {
01008
01009 if ( !mSelectedDates.isEmpty() && mSelectedDates.first() == start
01010 && mSelectedDates.last() == end && !mPendingChanges )
01011 return;
01012
01013 mSelectedDates.clear();
01014
01015 QDate d = start;
01016 while ( d <= end ) {
01017 mSelectedDates.append( d );
01018 d = d.addDays( 1 );
01019 }
01020
01021 mAreDatesInitialized = true;
01022
01023
01024 fillAgenda();
01025 }
01026
01027
01028 void KOAgendaView::showIncidences( const Incidence::List &, const QDate & )
01029 {
01030 kdDebug(5850) << "KOAgendaView::showIncidences( const Incidence::List & ) is not yet implemented" << endl;
01031 }
01032
01033 void KOAgendaView::insertIncidence( Incidence *incidence, const QDate &curDate )
01034 {
01035 if ( !filterByResource( incidence ) ) {
01036 return;
01037 }
01038
01039
01040 Event *event = dynamic_cast<Event *>( incidence );
01041 Todo *todo = dynamic_cast<Todo *>( incidence );
01042
01043 int curCol = mSelectedDates.first().daysTo( curDate );
01044
01045
01046 if ( curCol < 0 ) {
01047 curCol = 0;
01048 }
01049
01050
01051 if ( curCol >= static_cast<int>( mSelectedDates.count() ) ) {
01052 return;
01053 }
01054
01055
01056 mMinY[curCol] = mAgenda->timeToY( QTime( 23, 59 ) ) + 1;
01057 mMaxY[curCol] = mAgenda->timeToY( QTime( 0, 0 ) ) - 1;
01058
01059 int beginX;
01060 int endX;
01061 QDate columnDate;
01062 if ( event ) {
01063 QDate firstVisibleDate = mSelectedDates.first();
01064
01065 if ( curDate < firstVisibleDate ) {
01066 beginX = curCol + firstVisibleDate.daysTo( curDate );
01067 endX = beginX + event->dtStart().daysTo( event->dtEnd() );
01068 columnDate = firstVisibleDate;
01069 } else {
01070 beginX = curCol;
01071 endX = beginX + event->dtStart().daysTo( event->dtEnd() );
01072 columnDate = curDate;
01073 }
01074 } else if ( todo ) {
01075 if ( !todo->hasDueDate() ) {
01076 return;
01077 }
01078 columnDate = curDate;
01079 beginX = endX = curCol;
01080
01081 } else {
01082 return;
01083 }
01084 if ( todo && todo->isOverdue() ) {
01085 mAllDayAgenda->insertAllDayItem( incidence, columnDate, curCol, curCol );
01086 } else if ( incidence->doesFloat() ||
01087 ( todo &&
01088 !todo->dtDue().isValid() ) ) {
01089 mAllDayAgenda->insertAllDayItem( incidence, columnDate, beginX, endX );
01090 } else if ( event && event->isMultiDay() ) {
01091 int startY = mAgenda->timeToY( event->dtStart().time() );
01092 QTime endtime = event->dtEnd().time();
01093 if ( endtime == QTime( 0, 0, 0 ) ) {
01094 endtime = QTime( 23, 59, 59 );
01095 }
01096 int endY = mAgenda->timeToY( endtime ) - 1;
01097 if ( ( beginX <= 0 && curCol == 0 ) || beginX == curCol ) {
01098 mAgenda->insertMultiItem( event, columnDate, beginX, endX, startY, endY );
01099
01100 }
01101 if ( beginX == curCol ) {
01102 mMaxY[curCol] = mAgenda->timeToY( QTime( 23, 59 ) );
01103 if ( startY < mMinY[curCol] ) {
01104 mMinY[curCol] = startY;
01105 }
01106 } else if ( endX == curCol ) {
01107 mMinY[curCol] = mAgenda->timeToY( QTime( 0, 0 ) );
01108 if ( endY > mMaxY[curCol] ) {
01109 mMaxY[curCol] = endY;
01110 }
01111 } else {
01112 mMinY[curCol] = mAgenda->timeToY( QTime( 0, 0 ) );
01113 mMaxY[curCol] = mAgenda->timeToY( QTime( 23, 59 ) );
01114 }
01115 } else {
01116 int startY = 0, endY = 0;
01117 if ( event ) {
01118 startY = mAgenda->timeToY( incidence->dtStart().time() );
01119 QTime endtime = event->dtEnd().time();
01120 if ( endtime == QTime( 0, 0, 0 ) ) {
01121 endtime = QTime( 23, 59, 59 );
01122 }
01123 endY = mAgenda->timeToY( endtime ) - 1;
01124 }
01125 if ( todo ) {
01126 QTime t = todo->dtDue().time();
01127
01128 if ( t == QTime( 0, 0 ) ) {
01129 t = QTime( 23, 59 );
01130 }
01131
01132 int halfHour = 1800;
01133 if ( t.addSecs( -halfHour ) < t ) {
01134 startY = mAgenda->timeToY( t.addSecs( -halfHour ) );
01135 endY = mAgenda->timeToY( t ) - 1;
01136 } else {
01137 startY = 0;
01138 endY = mAgenda->timeToY( t.addSecs( halfHour ) ) - 1;
01139 }
01140 }
01141 if ( endY < startY ) {
01142 endY = startY;
01143 }
01144 mAgenda->insertItem( incidence, columnDate, curCol, startY, endY, 1, 1 );
01145 if ( startY < mMinY[curCol] ) {
01146 mMinY[curCol] = startY;
01147 }
01148 if ( endY > mMaxY[curCol] ) {
01149 mMaxY[curCol] = endY;
01150 }
01151 }
01152 }
01153
01154 void KOAgendaView::changeIncidenceDisplayAdded( Incidence *incidence )
01155 {
01156 Todo *todo = dynamic_cast<Todo *>(incidence);
01157 CalFilter *filter = calendar()->filter();
01158 if ( ( filter && !filter->filterIncidence( incidence ) ) ||
01159 ( ( todo && !KOPrefs::instance()->showAllDayTodo() ) ) ) {
01160 return;
01161 }
01162
01163 displayIncidence( incidence );
01164 }
01165
01166 void KOAgendaView::changeIncidenceDisplay( Incidence *incidence, int mode )
01167 {
01168 switch ( mode ) {
01169 case KOGlobals::INCIDENCEADDED:
01170 {
01171
01172
01173
01174
01175
01176 changeIncidenceDisplayAdded( incidence );
01177 updateEventIndicators();
01178 break;
01179 }
01180 case KOGlobals::INCIDENCEEDITED:
01181 {
01182 if ( mAllowAgendaUpdate ) {
01189 removeIncidence( incidence, false );
01190 changeIncidenceDisplayAdded( incidence );
01191 }
01192 updateEventIndicators();
01193 break;
01194 }
01195 case KOGlobals::INCIDENCEDELETED:
01196 {
01197 removeIncidence( incidence );
01198 updateEventIndicators();
01199 break;
01200 }
01201 default:
01202 return;
01203 }
01204
01205
01206
01207
01208
01209 if ( incidence->doesFloat() ) {
01210 updateView();
01211 }
01212 }
01213
01214 void KOAgendaView::fillAgenda( const QDate & )
01215 {
01216 fillAgenda();
01217 }
01218
01219 void KOAgendaView::fillAgenda()
01220 {
01221 if ( !mAreDatesInitialized ) {
01222 return;
01223 }
01224
01225 mPendingChanges = false;
01226
01227
01228
01229 const QString &selectedAgendaUid = mAgenda->lastSelectedUid();
01230 const QString &selectedAllDayAgendaUid = mAllDayAgenda->lastSelectedUid();
01231
01232 enableAgendaUpdate( true );
01233 clearView();
01234
01235 mAllDayAgenda->changeColumns( mSelectedDates.count() );
01236 mAgenda->changeColumns( mSelectedDates.count() );
01237 mEventIndicatorTop->changeColumns( mSelectedDates.count() );
01238 mEventIndicatorBottom->changeColumns( mSelectedDates.count() );
01239
01240 createDayLabels( false );
01241 setHolidayMasks();
01242
01243 mMinY.resize( mSelectedDates.count() );
01244 mMaxY.resize( mSelectedDates.count() );
01245
01246 mAgenda->setDateList( mSelectedDates );
01247
01248 bool somethingReselected = false;
01249 Incidence::List incidences = calendar()->incidences();
01250
01251 for ( Incidence::List::ConstIterator it = incidences.begin(); it!=incidences.constEnd(); ++it ) {
01252 Incidence *incidence = (*it);
01253 displayIncidence( incidence );
01254
01255 if( incidence->uid() == selectedAgendaUid && !selectedAgendaUid.isNull() ) {
01256 mAgenda->selectItemByUID( incidence->uid() );
01257 somethingReselected = true;
01258 }
01259
01260 if( incidence->uid() == selectedAllDayAgendaUid && !selectedAllDayAgendaUid.isNull() ) {
01261 mAllDayAgenda->selectItemByUID( incidence->uid() );
01262 somethingReselected = true;
01263 }
01264
01265 }
01266
01267 mAgenda->checkScrollBoundaries();
01268 updateEventIndicators();
01269
01270
01271
01272
01273
01274 deleteSelectedDateTime();
01275
01276 if( !somethingReselected ) {
01277 emit incidenceSelected( 0, QDate() );
01278 }
01279 }
01280
01281 void KOAgendaView::displayIncidence( Incidence *incidence )
01282 {
01283 QDate today = QDate::currentDate();
01284 DateTimeList::iterator t;
01285
01286
01287 Todo *todo = dynamic_cast<Todo *>( incidence );
01288 Event *event = dynamic_cast<Event *>( incidence );
01289
01290 QDateTime firstVisibleDateTime = mSelectedDates.first();
01291 QDateTime lastVisibleDateTime = mSelectedDates.last();
01292
01293 lastVisibleDateTime.setTime( QTime( 23, 59, 59, 59 ) );
01294 firstVisibleDateTime.setTime( QTime( 0, 0 ) );
01295 DateTimeList dateTimeList;
01296
01297 QDateTime incDtStart = incidence->dtStart();
01298 QDateTime incDtEnd = incidence->dtEnd();
01299
01300 if ( todo &&
01301 ( !KOPrefs::instance()->showAllDayTodo() || !todo->hasDueDate() ) ) {
01302 return;
01303 }
01304
01305 if ( incidence->doesRecur() ) {
01306 int eventDuration = event ? incDtStart.daysTo( incDtEnd ) : 0;
01307
01308
01309
01310
01311 QDateTime startDateTimeWithOffset = firstVisibleDateTime.addDays( -eventDuration );
01312 dateTimeList =
01313 incidence->recurrence()->timesInInterval( startDateTimeWithOffset,
01314 lastVisibleDateTime );
01315 } else {
01316 QDateTime dateToAdd;
01317 QDateTime incidenceStart;
01318 QDateTime incidenceEnd;
01319
01320 if ( todo && todo->hasDueDate() && !todo->isOverdue() ) {
01321
01322 dateToAdd = todo->dtDue();
01323
01324
01325
01326 if ( !todo->doesFloat() && dateToAdd.time() == QTime( 0, 0 ) ) {
01327 dateToAdd = dateToAdd.addSecs( -1 );
01328 }
01329
01330 incidenceEnd = dateToAdd;
01331 } else if ( event ) {
01332 dateToAdd = incDtStart;
01333 incidenceEnd = incDtEnd;
01334 }
01335
01336 if ( incidence->doesFloat() ) {
01337
01338 dateToAdd.setTime( QTime( 0, 0 ) );
01339 incidenceEnd.setTime( QTime( 23, 59, 59, 59 ) );
01340 }
01341
01342 if ( dateToAdd <= lastVisibleDateTime && incidenceEnd > firstVisibleDateTime ) {
01343 dateTimeList += dateToAdd;
01344 }
01345 }
01346
01347
01348 QDateTime dateTimeToday = today;
01349 if ( todo &&
01350 todo->isOverdue() &&
01351 dateTimeToday >= firstVisibleDateTime &&
01352 dateTimeToday <= lastVisibleDateTime ) {
01353
01354 bool doAdd = true;
01355
01356 if ( todo->doesRecur() ) {
01357
01358
01359 for ( t = dateTimeList.begin(); t != dateTimeList.end(); ++t ) {
01360 if ( (*t).date() == today ) {
01361 doAdd = false;
01362 break;
01363 }
01364 }
01365 }
01366
01367 if ( doAdd ) {
01368 dateTimeList += dateTimeToday;
01369 }
01370 }
01371
01372 const bool makesDayBusy = KOEventView::makesWholeDayBusy( incidence );
01373 for ( t = dateTimeList.begin(); t != dateTimeList.end(); ++t ) {
01374 if ( makesDayBusy ) {
01375 Event::List &busyEvents = mBusyDays[(*t).date()];
01376 busyEvents.append( event );
01377 }
01378 insertIncidence( incidence, (*t).date() );
01379 }
01380
01381
01382 if ( event && makesDayBusy && event->isMultiDay() ) {
01383 const QDate lastVisibleDate = mSelectedDates.last();
01384 for ( QDate date = event->dtStart().date();
01385 date <= event->dtEnd().date() && date <= lastVisibleDate ;
01386 date = date.addDays( 1 ) ) {
01387 Event::List &busyEvents = mBusyDays[date];
01388 busyEvents.append( event );
01389 }
01390 }
01391 }
01392
01393 void KOAgendaView::clearView()
01394 {
01395
01396 mAllDayAgenda->clear();
01397 mAgenda->clear();
01398 mBusyDays.clear();
01399 }
01400
01401 CalPrinterBase::PrintType KOAgendaView::printType()
01402 {
01403 if ( currentDateCount() == 1 ) return CalPrinterBase::Day;
01404 else return CalPrinterBase::Week;
01405 }
01406
01407 void KOAgendaView::updateEventIndicatorTop( int newY )
01408 {
01409 uint i;
01410 for( i = 0; i < mMinY.size(); ++i ) {
01411 mEventIndicatorTop->enableColumn( i, newY > mMinY[i] );
01412 }
01413 mEventIndicatorTop->update();
01414 }
01415
01416 void KOAgendaView::updateEventIndicatorBottom( int newY )
01417 {
01418 uint i;
01419 for( i = 0; i < mMaxY.size(); ++i ) {
01420 mEventIndicatorBottom->enableColumn( i, newY <= mMaxY[i] );
01421 }
01422 mEventIndicatorBottom->update();
01423 }
01424
01425 void KOAgendaView::slotTodoDropped( Todo *todo, const QPoint &gpos, bool allDay )
01426 {
01427 if ( gpos.x()<0 || gpos.y()<0 ) return;
01428 QDate day = mSelectedDates[gpos.x()];
01429 QTime time = mAgenda->gyToTime( gpos.y() );
01430 QDateTime newTime( day, time );
01431
01432 if ( todo ) {
01433 Todo *existingTodo = calendar()->todo( todo->uid() );
01434 if ( existingTodo ) {
01435 kdDebug(5850) << "Drop existing Todo" << endl;
01436 Todo *oldTodo = existingTodo->clone();
01437 if ( mChanger &&
01438 mChanger->beginChange( existingTodo, resourceCalendar(), subResourceCalendar() ) ) {
01439 existingTodo->setDtDue( newTime );
01440 existingTodo->setFloats( allDay );
01441 existingTodo->setHasDueDate( true );
01442 mChanger->changeIncidence( oldTodo, existingTodo,
01443 KOGlobals::DATE_MODIFIED, this );
01444 mChanger->endChange( existingTodo, resourceCalendar(), subResourceCalendar() );
01445 } else {
01446 KMessageBox::sorry( this, i18n("Unable to modify this to-do, "
01447 "because it cannot be locked.") );
01448 }
01449 delete oldTodo;
01450 } else {
01451 kdDebug(5850) << "Drop new Todo" << endl;
01452 todo->setDtDue( newTime );
01453 todo->setFloats( allDay );
01454 todo->setHasDueDate( true );
01455 if ( !mChanger->addIncidence( todo, 0, QString(), this ) ) {
01456 KODialogManager::errorSaveIncidence( this, todo );
01457 }
01458 }
01459 }
01460 }
01461
01462 void KOAgendaView::startDrag( Incidence *incidence )
01463 {
01464 #ifndef KORG_NODND
01465 DndFactory factory( calendar() );
01466 ICalDrag *vd = factory.createDrag( incidence, this );
01467 if ( vd->drag() ) {
01468 kdDebug(5850) << "KOAgendaView::startDrag(): Delete drag source" << endl;
01469 }
01470 #endif
01471 }
01472
01473 void KOAgendaView::readSettings()
01474 {
01475 readSettings(KOGlobals::self()->config());
01476 }
01477
01478 void KOAgendaView::readSettings(KConfig *config)
01479 {
01480
01481
01482 config->setGroup("Views");
01483
01484 #ifndef KORG_NOSPLITTER
01485 QValueList<int> sizes = config->readIntListEntry("Separator AgendaView");
01486 if (sizes.count() == 2) {
01487 mSplitterAgenda->setSizes(sizes);
01488 }
01489 #endif
01490
01491 updateConfig();
01492 }
01493
01494 void KOAgendaView::writeSettings(KConfig *config)
01495 {
01496
01497
01498 config->setGroup("Views");
01499
01500 #ifndef KORG_NOSPLITTER
01501 QValueList<int> list = mSplitterAgenda->sizes();
01502 config->writeEntry("Separator AgendaView",list);
01503 #endif
01504 }
01505
01506 void KOAgendaView::setHolidayMasks()
01507 {
01508 if ( mSelectedDates.isEmpty() || !mSelectedDates[0].isValid() ) {
01509 return;
01510 }
01511
01512 mHolidayMask.resize( mSelectedDates.count() + 1 );
01513
01514 for( uint i = 0; i < mSelectedDates.count(); ++i ) {
01515 mHolidayMask[i] = !KOGlobals::self()->isWorkDay( mSelectedDates[ i ] );
01516 }
01517
01518
01519
01520 bool showDay = !KOGlobals::self()->isWorkDay( mSelectedDates[ 0 ].addDays( -1 ) );
01521 mHolidayMask[ mSelectedDates.count() ] = showDay;
01522
01523 mAgenda->setHolidayMask( &mHolidayMask );
01524 mAllDayAgenda->setHolidayMask( &mHolidayMask );
01525 }
01526
01527 QMemArray<bool> KOAgendaView::busyDayMask()
01528 {
01529 if ( mSelectedDates.isEmpty() || !mSelectedDates[0].isValid() ) {
01530 return QMemArray<bool>();
01531 }
01532
01533 QMemArray<bool> busyDayMask;
01534 busyDayMask.resize( mSelectedDates.count() );
01535
01536 for( uint i = 0; i < mSelectedDates.count(); ++i ) {
01537 busyDayMask[i] = !mBusyDays[mSelectedDates[i]].isEmpty();
01538 }
01539
01540 return busyDayMask;
01541 }
01542
01543 void KOAgendaView::setContentsPos( int y )
01544 {
01545 mAgenda->setContentsPos( 0, y );
01546 }
01547
01548 void KOAgendaView::setExpandedButton( bool expanded )
01549 {
01550 if ( !mExpandButton ) return;
01551
01552 if ( expanded ) {
01553 mExpandButton->setPixmap( mExpandedPixmap );
01554 } else {
01555 mExpandButton->setPixmap( mNotExpandedPixmap );
01556 }
01557 }
01558
01559 void KOAgendaView::clearSelection()
01560 {
01561 mAgenda->deselectItem();
01562 mAllDayAgenda->deselectItem();
01563 }
01564
01565 void KOAgendaView::newTimeSpanSelectedAllDay( const QPoint &start, const QPoint &end )
01566 {
01567 newTimeSpanSelected( start, end );
01568 mTimeSpanInAllDay = true;
01569 }
01570
01571 void KOAgendaView::newTimeSpanSelected( const QPoint &start, const QPoint &end )
01572 {
01573 if (!mSelectedDates.count()) return;
01574
01575 mTimeSpanInAllDay = false;
01576
01577 QDate dayStart = mSelectedDates[ kClamp( start.x(), 0, (int)mSelectedDates.size() - 1 ) ];
01578 QDate dayEnd = mSelectedDates[ kClamp( end.x(), 0, (int)mSelectedDates.size() - 1 ) ];
01579
01580 QTime timeStart = mAgenda->gyToTime(start.y());
01581 QTime timeEnd = mAgenda->gyToTime( end.y() + 1 );
01582
01583 QDateTime dtStart(dayStart,timeStart);
01584 QDateTime dtEnd(dayEnd,timeEnd);
01585
01586 mTimeSpanBegin = dtStart;
01587 mTimeSpanEnd = dtEnd;
01588 }
01589
01590 void KOAgendaView::deleteSelectedDateTime()
01591 {
01592 mTimeSpanBegin.setDate(QDate());
01593 mTimeSpanEnd.setDate(QDate());
01594 mTimeSpanInAllDay = false;
01595 }
01596
01597 void KOAgendaView::setTypeAheadReceiver( QObject *o )
01598 {
01599 mAgenda->setTypeAheadReceiver( o );
01600 mAllDayAgenda->setTypeAheadReceiver( o );
01601 }
01602
01603 void KOAgendaView::finishTypeAhead()
01604 {
01605 mAgenda->finishTypeAhead();
01606 mAllDayAgenda->finishTypeAhead();
01607 }
01608
01609 void KOAgendaView::removeIncidence( Incidence *incidence, bool relayoutNeighbours )
01610 {
01611 mAgenda->removeIncidence( incidence, relayoutNeighbours );
01612 mAllDayAgenda->removeIncidence( incidence, relayoutNeighbours );
01613 }
01614
01615 void KOAgendaView::updateEventIndicators()
01616 {
01617 mMinY = mAgenda->minContentsY();
01618 mMaxY = mAgenda->maxContentsY();
01619
01620 mAgenda->checkScrollBoundaries();
01621 updateEventIndicatorTop( mAgenda->visibleContentsYMin() );
01622 updateEventIndicatorBottom( mAgenda->visibleContentsYMax() );
01623 }
01624
01625 void KOAgendaView::setIncidenceChanger( IncidenceChangerBase *changer )
01626 {
01627 mChanger = changer;
01628 mAgenda->setIncidenceChanger( changer );
01629 mAllDayAgenda->setIncidenceChanger( changer );
01630 }
01631
01632 void KOAgendaView::clearTimeSpanSelection()
01633 {
01634 mAgenda->clearSelection();
01635 mAllDayAgenda->clearSelection();
01636 deleteSelectedDateTime();
01637 }
01638
01639 bool KOAgendaView::filterByResource( Incidence *incidence )
01640 {
01641
01642
01643
01644
01645 if ( resourceCalendar() && incidence->type() == "Todo" ) {
01646 QString subRes = resourceCalendar()->subresourceIdentifier( incidence );
01647 if ( resourceCalendar()->subresourceType( subRes ) == "todo" ) {
01648 QString calmatch = "/.INBOX.directory/Calendar";
01649 QString i18nmatch = "/.INBOX.directory/" + i18n( "Calendar" );
01650 if ( subResourceCalendar().contains( calmatch ) ||
01651 subResourceCalendar().contains( i18nmatch ) ) {
01652 return true;
01653 }
01654 }
01655 }
01656
01657
01658 if ( !resourceCalendar() )
01659 return true;
01660 CalendarResources *calRes = dynamic_cast<CalendarResources*>( calendar() );
01661 if ( !calRes )
01662 return true;
01663 if ( calRes->resource( incidence ) != resourceCalendar() )
01664 return false;
01665 if ( !subResourceCalendar().isEmpty() ) {
01666 if ( resourceCalendar()->subresourceIdentifier( incidence ) != subResourceCalendar() )
01667 return false;
01668 }
01669 return true;
01670 }
01671
01672 void KOAgendaView::resourcesChanged()
01673 {
01674 mPendingChanges = true;
01675 }
01676
01677 void KOAgendaView::calendarIncidenceAdded(Incidence * incidence)
01678 {
01679 Q_UNUSED( incidence );
01680 mPendingChanges = true;
01681 }
01682
01683 void KOAgendaView::calendarIncidenceChanged(Incidence * incidence)
01684 {
01685 Q_UNUSED( incidence );
01686 mPendingChanges = true;
01687 }
01688
01689 void KOAgendaView::calendarIncidenceDeleted(Incidence * incidence)
01690 {
01691 Q_UNUSED( incidence );
01692 mPendingChanges = true;
01693 }