korganizer Library API Documentation

koagendaview.cpp

00001 /* 00002 This file is part of KOrganizer. 00003 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 00019 As a special exception, permission is given to link this program 00020 with any edition of Qt, and distribute the resulting executable, 00021 without including the source code for Qt in the source distribution. 00022 */ 00023 00024 #include <qhbox.h> 00025 #include <qvbox.h> 00026 #include <qlabel.h> 00027 #include <qframe.h> 00028 #include <qlayout.h> 00029 #ifndef KORG_NOSPLITTER 00030 #include <qsplitter.h> 00031 #endif 00032 #include <qfont.h> 00033 #include <qfontmetrics.h> 00034 #include <qpopupmenu.h> 00035 #include <qtooltip.h> 00036 #include <qpainter.h> 00037 #include <qpushbutton.h> 00038 #include <qcursor.h> 00039 #include <qbitarray.h> 00040 00041 #include <kapplication.h> 00042 #include <kdebug.h> 00043 #include <kstandarddirs.h> 00044 #include <kiconloader.h> 00045 #include <klocale.h> 00046 #include <kconfig.h> 00047 #include <kglobal.h> 00048 #include <kglobalsettings.h> 00049 00050 #include <libkcal/calendar.h> 00051 #include <libkcal/icaldrag.h> 00052 #include <libkcal/dndfactory.h> 00053 #include <libkcal/calfilter.h> 00054 00055 #include <kcalendarsystem.h> 00056 00057 #include "koglobals.h" 00058 #ifndef KORG_NOPLUGINS 00059 #include "kocore.h" 00060 #endif 00061 #include "koprefs.h" 00062 #include "koagenda.h" 00063 #include "koagendaitem.h" 00064 #ifndef KORG_NOPRINTER 00065 #include "calprinter.h" 00066 #endif 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 TimeLabels::TimeLabels(int rows,QWidget *parent,const char *name,WFlags f) : 00079 QScrollView(parent,name,f) 00080 { 00081 mRows = rows; 00082 00083 mCellHeight = KOPrefs::instance()->mHourSize*4; 00084 00085 enableClipper(true); 00086 00087 setHScrollBarMode(AlwaysOff); 00088 setVScrollBarMode(AlwaysOff); 00089 00090 resizeContents(50,mRows * mCellHeight); 00091 00092 viewport()->setBackgroundMode( PaletteBackground ); 00093 } 00094 00095 void TimeLabels::setCellHeight(int height) 00096 { 00097 mCellHeight = height; 00098 } 00099 00100 /* 00101 Optimization so that only the "dirty" portion of the scroll view 00102 is redrawn. Unfortunately, this is not called by default paintEvent() method. 00103 */ 00104 void TimeLabels::drawContents(QPainter *p,int cx, int cy, int cw, int ch) 00105 { 00106 // bug: the parameters cx, cy, cw, ch are the areas that need to be 00107 // redrawn, not the area of the widget. unfortunately, this 00108 // code assumes the latter... 00109 00110 // now, for a workaround... 00111 // these two assignments fix the weird redraw bug 00112 cx = contentsX() + 2; 00113 cw = contentsWidth() - 2; 00114 int visWidth = visibleWidth(); 00115 double cellHeight=mCellHeight; 00116 if (mAgenda) cellHeight=(4*mAgenda->gridSpacingY()); 00117 // end of workaround 00118 00119 int cell = ((int)(cy/cellHeight)); 00120 double y = (cell * cellHeight); 00121 QFontMetrics fm = fontMetrics(); 00122 QString hour; 00123 QString suffix; 00124 QString fullTime; 00125 00126 while (y < cy + ch) { 00127 p->drawLine(cx,(int)y,cx+cw,(int)y); 00128 hour.setNum(cell); 00129 suffix = "am"; 00130 00131 // handle 24h and am/pm time formats 00132 if (KGlobal::locale()->use12Clock()) { 00133 if (cell > 11) suffix = "pm"; 00134 if (cell == 0) hour.setNum(12); 00135 if (cell > 12) hour.setNum(cell - 12); 00136 } else { 00137 suffix = ":00"; 00138 } 00139 00140 // create string in format of "XX:XX" or "XXpm/am" 00141 fullTime = hour + suffix; 00142 00143 // center and draw the time label 00144 QRect r( cx, (int)y+3, visWidth-4, (int)(y+cellHeight-3) ); 00145 p->drawText ( r, Qt::AlignHCenter | Qt::AlignTop | Qt::SingleLine, fullTime ); 00146 00147 // increment indices 00148 y += cellHeight; 00149 cell++; 00150 } 00151 } 00152 00156 int TimeLabels::minimumWidth() const 00157 { 00158 QFontMetrics fm = fontMetrics(); 00159 00160 int borderWidth = 4; 00161 00162 // the maximum width possible 00163 int width = fm.width("88:88") + 2*borderWidth; 00164 00165 return width; 00166 } 00167 00169 void TimeLabels::updateConfig() 00170 { 00171 // set the font 00172 // config->setGroup("Fonts"); 00173 // QFont font = config->readFontEntry("TimeBar Font"); 00174 setFont(KOPrefs::instance()->mTimeBarFont); 00175 00176 // update geometry restrictions based on new settings 00177 setFixedWidth(minimumWidth()); 00178 00179 // update HourSize 00180 mCellHeight = KOPrefs::instance()->mHourSize*4; 00181 if (mCellHeight>mAgenda->gridSpacingY()) 00182 mCellHeight=(int)(4*mAgenda->gridSpacingY()); 00183 // FIXME: Why the heck do we set the width to 50??? 00184 resizeContents(50,mRows * mCellHeight); 00185 } 00186 00188 void TimeLabels::positionChanged() 00189 { 00190 int adjustment = mAgenda->contentsY(); 00191 setContentsPos(0, adjustment); 00192 } 00193 00195 void TimeLabels::setAgenda(KOAgenda* agenda) 00196 { 00197 mAgenda = agenda; 00198 } 00199 00200 00202 void TimeLabels::paintEvent(QPaintEvent*) 00203 { 00204 // kdDebug(5850) << "paintevent..." << endl; 00205 // this is another hack! 00206 // QPainter painter(this); 00207 //QString c 00208 repaintContents(contentsX(), contentsY(), visibleWidth(), visibleHeight()); 00209 } 00210 00212 00213 EventIndicator::EventIndicator(Location loc,QWidget *parent,const char *name) 00214 : QFrame(parent,name) 00215 { 00216 mColumns = 1; 00217 mTopBox = 0; 00218 mLocation = loc; 00219 mTopLayout = 0; 00220 00221 if (mLocation == Top) mPixmap = KOGlobals::self()->smallIcon("1uparrow"); 00222 else mPixmap = KOGlobals::self()->smallIcon("1downarrow"); 00223 00224 setMinimumHeight(mPixmap.height()); 00225 } 00226 00227 EventIndicator::~EventIndicator() 00228 { 00229 } 00230 00231 void EventIndicator::drawContents(QPainter *p) 00232 { 00233 // kdDebug(5850) << "======== top: " << contentsRect().top() << " bottom " 00234 // << contentsRect().bottom() << " left " << contentsRect().left() 00235 // << " right " << contentsRect().right() << endl; 00236 00237 int i; 00238 for(i=0;i<mColumns;++i) { 00239 if (mEnabled[i]) { 00240 int cellWidth = contentsRect().right()/mColumns; 00241 int xOffset = KOGlobals::self()->reverseLayout() ? 00242 (mColumns - 1 - i)*cellWidth + cellWidth/2 -mPixmap.width()/2 : 00243 i*cellWidth + cellWidth/2 -mPixmap.width()/2; 00244 p->drawPixmap(QPoint(xOffset,0),mPixmap); 00245 } 00246 } 00247 } 00248 00249 void EventIndicator::changeColumns(int columns) 00250 { 00251 mColumns = columns; 00252 mEnabled.resize(mColumns); 00253 00254 update(); 00255 } 00256 00257 void EventIndicator::enableColumn(int column, bool enable) 00258 { 00259 mEnabled[column] = enable; 00260 } 00261 00262 00263 #include <libkcal/incidence.h> 00264 00268 00269 00270 KOAlternateLabel::KOAlternateLabel(QString shortlabel, QString longlabel, 00271 QString extensivelabel, QWidget *parent, const char *name ) 00272 : QLabel(parent, name), mTextTypeFixed(false), mShortText(shortlabel), 00273 mLongText(longlabel), mExtensiveText(extensivelabel) 00274 { 00275 setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); 00276 if (mExtensiveText.isEmpty()) mExtensiveText = mLongText; 00277 squeezeTextToLabel(); 00278 } 00279 00280 KOAlternateLabel::~KOAlternateLabel() 00281 { 00282 } 00283 00284 void KOAlternateLabel::useShortText() 00285 { 00286 mTextTypeFixed = true; 00287 QLabel::setText( mShortText ); 00288 QToolTip::remove( this ); 00289 QToolTip::add( this, mExtensiveText ); 00290 } 00291 00292 void KOAlternateLabel::useLongText() 00293 { 00294 mTextTypeFixed = true; 00295 QLabel::setText( mLongText ); 00296 QToolTip::remove( this ); 00297 QToolTip::add( this, mExtensiveText ); 00298 } 00299 00300 void KOAlternateLabel::useExtensiveText() 00301 { 00302 mTextTypeFixed = true; 00303 QLabel::setText( mExtensiveText ); 00304 QToolTip::remove( this ); 00305 QToolTip::hide(); 00306 } 00307 00308 void KOAlternateLabel::useDefaultText() 00309 { 00310 mTextTypeFixed = false; 00311 squeezeTextToLabel(); 00312 } 00313 00314 void KOAlternateLabel::squeezeTextToLabel() 00315 { 00316 if (mTextTypeFixed) return; 00317 00318 QFontMetrics fm(fontMetrics()); 00319 int labelWidth = size().width(); 00320 int textWidth = fm.width(mLongText); 00321 int longTextWidth = fm.width(mExtensiveText); 00322 if (longTextWidth <= labelWidth) { 00323 QLabel::setText( mExtensiveText ); 00324 QToolTip::remove( this ); 00325 QToolTip::hide(); 00326 } else if (textWidth <= labelWidth) { 00327 QLabel::setText( mLongText ); 00328 QToolTip::remove( this ); 00329 QToolTip::add( this, mExtensiveText ); 00330 } else { 00331 QLabel::setText( mShortText ); 00332 QToolTip::remove( this ); 00333 QToolTip::add( this, mExtensiveText ); 00334 } 00335 } 00336 00337 void KOAlternateLabel::resizeEvent( QResizeEvent * ) 00338 { 00339 squeezeTextToLabel(); 00340 } 00341 00342 QSize KOAlternateLabel::minimumSizeHint() const 00343 { 00344 QSize sh = QLabel::minimumSizeHint(); 00345 sh.setWidth(-1); 00346 return sh; 00347 } 00348 00349 void KOAlternateLabel::setText( const QString &text ) { 00350 mLongText = text; 00351 squeezeTextToLabel(); 00352 } 00353 00354 00358 00359 KOAgendaView::KOAgendaView(Calendar *cal,QWidget *parent,const char *name) : 00360 KOEventView (cal,parent,name), mAllowAgendaUpdate( true ), mUpdateItem( 0 ) 00361 { 00362 mSelectedDates.append(QDate::currentDate()); 00363 00364 mLayoutDayLabels = 0; 00365 mDayLabelsFrame = 0; 00366 mDayLabels = 0; 00367 00368 bool isRTL = KOGlobals::self()->reverseLayout(); 00369 00370 if ( KOPrefs::instance()->mVerticalScreen ) { 00371 mExpandedPixmap = KOGlobals::self()->smallIcon( "1downarrow" ); 00372 mNotExpandedPixmap = KOGlobals::self()->smallIcon( "1uparrow" ); 00373 } else { 00374 mExpandedPixmap = KOGlobals::self()->smallIcon( isRTL ? "1leftarrow" : "1rightarrow" ); 00375 mNotExpandedPixmap = KOGlobals::self()->smallIcon( isRTL ? "1rightarrow" : "1leftarrow" ); 00376 } 00377 00378 QBoxLayout *topLayout = new QVBoxLayout(this); 00379 00380 // Create day name labels for agenda columns 00381 mDayLabelsFrame = new QHBox(this); 00382 topLayout->addWidget(mDayLabelsFrame); 00383 00384 // Create agenda splitter 00385 #ifndef KORG_NOSPLITTER 00386 mSplitterAgenda = new QSplitter(Vertical,this); 00387 topLayout->addWidget(mSplitterAgenda); 00388 00389 #if KDE_IS_VERSION( 3, 1, 93 ) 00390 mSplitterAgenda->setOpaqueResize( KGlobalSettings::opaqueResize() ); 00391 #else 00392 mSplitterAgenda->setOpaqueResize(); 00393 #endif 00394 00395 mAllDayFrame = new QHBox(mSplitterAgenda); 00396 00397 QWidget *agendaFrame = new QWidget(mSplitterAgenda); 00398 #else 00399 QVBox *mainBox = new QVBox( this ); 00400 topLayout->addWidget( mainBox ); 00401 00402 mAllDayFrame = new QHBox(mainBox); 00403 00404 QWidget *agendaFrame = new QWidget(mainBox); 00405 #endif 00406 00407 // Create all-day agenda widget 00408 mDummyAllDayLeft = new QVBox( mAllDayFrame ); 00409 00410 mExpandButton = new QPushButton(mDummyAllDayLeft); 00411 mExpandButton->setPixmap( mNotExpandedPixmap ); 00412 mExpandButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, 00413 QSizePolicy::Fixed ) ); 00414 connect( mExpandButton, SIGNAL( clicked() ), SIGNAL( toggleExpand() ) ); 00415 00416 mAllDayAgenda = new KOAgenda(1,mAllDayFrame); 00417 QWidget *dummyAllDayRight = new QWidget(mAllDayFrame); 00418 00419 // Create agenda frame 00420 QGridLayout *agendaLayout = new QGridLayout(agendaFrame,3,3); 00421 // QHBox *agendaFrame = new QHBox(splitterAgenda); 00422 00423 // create event indicator bars 00424 mEventIndicatorTop = new EventIndicator(EventIndicator::Top,agendaFrame); 00425 agendaLayout->addWidget(mEventIndicatorTop,0,1); 00426 mEventIndicatorBottom = new EventIndicator(EventIndicator::Bottom, 00427 agendaFrame); 00428 agendaLayout->addWidget(mEventIndicatorBottom,2,1); 00429 QWidget *dummyAgendaRight = new QWidget(agendaFrame); 00430 agendaLayout->addWidget(dummyAgendaRight,0,2); 00431 00432 // Create time labels 00433 mTimeLabels = new TimeLabels(24,agendaFrame); 00434 agendaLayout->addWidget(mTimeLabels,1,0); 00435 00436 // Create agenda 00437 mAgenda = new KOAgenda(1,96,KOPrefs::instance()->mHourSize,agendaFrame); 00438 agendaLayout->addMultiCellWidget(mAgenda,1,1,1,2); 00439 agendaLayout->setColStretch(1,1); 00440 00441 // Create event context menu for agenda 00442 mAgendaPopup = eventPopup(); 00443 00444 // Create event context menu for all day agenda 00445 mAllDayAgendaPopup = eventPopup(); 00446 00447 // make connections between dependent widgets 00448 mTimeLabels->setAgenda(mAgenda); 00449 00450 // Update widgets to reflect user preferences 00451 // updateConfig(); 00452 00453 createDayLabels(); 00454 00455 // these blank widgets make the All Day Event box line up with the agenda 00456 dummyAllDayRight->setFixedWidth(mAgenda->verticalScrollBar()->width()); 00457 dummyAgendaRight->setFixedWidth(mAgenda->verticalScrollBar()->width()); 00458 mDummyAllDayLeft->setFixedWidth(mTimeLabels->width()); 00459 00460 // Scrolling 00461 connect(mAgenda->verticalScrollBar(),SIGNAL(valueChanged(int)), 00462 mTimeLabels, SLOT(positionChanged())); 00463 connect(mTimeLabels->verticalScrollBar(),SIGNAL(valueChanged(int)), 00464 SLOT(setContentsPos(int))); 00465 00466 // Create Events, depends on type of agenda 00467 connect( mAgenda, SIGNAL(newEventSignal(const QPoint &)), 00468 SLOT(newEvent(const QPoint &))); 00469 connect( mAllDayAgenda, SIGNAL(newEventSignal(const QPoint &)), 00470 SLOT(newEventAllDay(const QPoint &))); 00471 connect( mAgenda, SIGNAL(newEventSignal(const QPoint &, const QPoint &)), 00472 SLOT(newEvent(const QPoint &, const QPoint &))); 00473 connect( mAllDayAgenda, SIGNAL(newEventSignal(const QPoint &, const QPoint &)), 00474 SLOT(newEventAllDay(const QPoint &))); 00475 connect( mAgenda, SIGNAL(newTimeSpanSignal(const QPoint &, const QPoint &)), 00476 SLOT(newTimeSpanSelected(const QPoint &, const QPoint &))); 00477 connect( mAllDayAgenda, SIGNAL(newTimeSpanSignal(const QPoint &, const QPoint &)), 00478 SLOT(newTimeSpanSelectedAllDay(const QPoint &, const QPoint &))); 00479 00480 // event indicator update 00481 connect( mAgenda, SIGNAL(lowerYChanged(int)), 00482 SLOT(updateEventIndicatorTop(int))); 00483 connect( mAgenda, SIGNAL(upperYChanged(int)), 00484 SLOT(updateEventIndicatorBottom(int))); 00485 00486 connectAgenda( mAgenda, mAgendaPopup, mAllDayAgenda ); 00487 connectAgenda( mAllDayAgenda, mAllDayAgendaPopup, mAgenda); 00488 } 00489 00490 00491 KOAgendaView::~KOAgendaView() 00492 { 00493 delete mAgendaPopup; 00494 delete mAllDayAgendaPopup; 00495 } 00496 00497 void KOAgendaView::connectAgenda( KOAgenda *agenda, QPopupMenu *popup, 00498 KOAgenda *otherAgenda ) 00499 { 00500 connect( agenda, SIGNAL( showIncidencePopupSignal( Incidence *, const QDate & ) ), 00501 popup, SLOT( showIncidencePopup( Incidence *, const QDate & ) ) ); 00502 00503 connect( agenda, SIGNAL( showNewEventPopupSignal() ), 00504 SLOT( showNewEventPopup() ) ); 00505 00506 agenda->setCalendar( calendar() ); 00507 00508 // Create/Show/Edit/Delete Event 00509 connect( agenda, SIGNAL( newEventSignal() ), SIGNAL( newEventSignal() ) ); 00510 00511 connect( agenda, SIGNAL( newStartSelectSignal() ), 00512 otherAgenda, SLOT( clearSelection() ) ); 00513 00514 connect( agenda, SIGNAL( editIncidenceSignal( Incidence * ) ), 00515 SIGNAL( editIncidenceSignal( Incidence * ) ) ); 00516 connect( agenda, SIGNAL( showIncidenceSignal( Incidence * ) ), 00517 SIGNAL( showIncidenceSignal( Incidence * ) ) ); 00518 connect( agenda, SIGNAL( deleteIncidenceSignal( Incidence * ) ), 00519 SIGNAL( deleteIncidenceSignal( Incidence * ) ) ); 00520 00521 connect( agenda, SIGNAL( incidenceChanged( Incidence *, Incidence * ) ), 00522 SIGNAL( incidenceChanged( Incidence *, Incidence * ) ) ); 00523 connect( agenda, SIGNAL( incidenceAdded( Incidence * ) ), 00524 SIGNAL( incidenceAdded( Incidence * ) ) ); 00525 00526 connect( agenda, SIGNAL( startMultiModify( const QString & ) ), 00527 SIGNAL( startMultiModify( const QString & ) ) ); 00528 connect( agenda, SIGNAL( endMultiModify() ), 00529 SIGNAL( endMultiModify() ) ); 00530 00531 connect( agenda, SIGNAL( itemModified( KOAgendaItem * ) ), 00532 SLOT( updateEventDates( KOAgendaItem * ) ) ); 00533 connect( agenda, SIGNAL( enableAgendaUpdate( bool ) ), 00534 SLOT( enableAgendaUpdate( bool ) ) ); 00535 00536 // drag signals 00537 connect( agenda, SIGNAL( startDragSignal( Incidence * ) ), 00538 SLOT( startDrag( Incidence * ) ) ); 00539 00540 // synchronize selections 00541 connect( agenda, SIGNAL( incidenceSelected( Incidence * ) ), 00542 otherAgenda, SLOT( deselectItem() ) ); 00543 connect( agenda, SIGNAL( incidenceSelected( Incidence * ) ), 00544 SIGNAL( incidenceSelected( Incidence * ) ) ); 00545 00546 // rescheduling of todos by d'n'd 00547 connect( agenda, SIGNAL( droppedToDo( Todo *, const QPoint &, bool ) ), 00548 SLOT( slotTodoDropped( Todo *, const QPoint &, bool ) ) ); 00549 00550 } 00551 00552 void KOAgendaView::createDayLabels() 00553 { 00554 // kdDebug(5850) << "KOAgendaView::createDayLabels()" << endl; 00555 00556 // ### Before deleting and recreating we could check if mSelectedDates changed... 00557 // It would remove some flickering and gain speed (since this is called by 00558 // each updateView() call) 00559 delete mDayLabels; 00560 00561 mDayLabels = new QFrame (mDayLabelsFrame); 00562 mLayoutDayLabels = new QHBoxLayout(mDayLabels); 00563 mLayoutDayLabels->addSpacing(mTimeLabels->width()); 00564 00565 const KCalendarSystem*calsys=KOGlobals::self()->calendarSystem(); 00566 00567 DateList::ConstIterator dit; 00568 for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { 00569 QDate date = *dit; 00570 QBoxLayout *dayLayout = new QVBoxLayout(mLayoutDayLabels); 00571 mLayoutDayLabels->setStretchFactor(dayLayout, 1); 00572 // dayLayout->setMinimumWidth(1); 00573 00574 int dW = calsys->dayOfWeek(date); 00575 QString veryLongStr = KGlobal::locale()->formatDate( date ); 00576 QString longstr = i18n( "short_weekday date (e.g. Mon 13)","%1 %2" ) 00577 .arg( calsys->weekDayName( dW, true ) ) 00578 .arg( calsys->day(date) ); 00579 QString shortstr = QString::number(calsys->day(date)); 00580 00581 KOAlternateLabel *dayLabel = new KOAlternateLabel(shortstr, 00582 longstr, veryLongStr, mDayLabels); 00583 dayLabel->setMinimumWidth(1); 00584 dayLabel->setAlignment(QLabel::AlignHCenter); 00585 if (date == QDate::currentDate()) { 00586 QFont font = dayLabel->font(); 00587 font.setBold(true); 00588 dayLabel->setFont(font); 00589 } 00590 dayLayout->addWidget(dayLabel); 00591 00592 #ifndef KORG_NOPLUGINS 00593 CalendarDecoration::List cds = KOCore::self()->calendarDecorations(); 00594 CalendarDecoration *it; 00595 for(it = cds.first(); it; it = cds.next()) { 00596 QString text = it->shortText( date ); 00597 if ( !text.isEmpty() ) { 00598 // use a KOAlternateLabel so when the text doesn't fit any more a tooltip is used 00599 KOAlternateLabel*label = new KOAlternateLabel( text, text, QString::null, mDayLabels ); 00600 label->setMinimumWidth(1); 00601 label->setAlignment(AlignCenter); 00602 dayLayout->addWidget(label); 00603 } 00604 } 00605 00606 for(it = cds.first(); it; it = cds.next()) { 00607 QWidget *wid = it->smallWidget(mDayLabels,date); 00608 if ( wid ) { 00609 // wid->setHeight(20); 00610 dayLayout->addWidget(wid); 00611 } 00612 } 00613 #endif 00614 } 00615 00616 mLayoutDayLabels->addSpacing(mAgenda->verticalScrollBar()->width()); 00617 mDayLabels->show(); 00618 } 00619 00620 void KOAgendaView::enableAgendaUpdate( bool enable ) 00621 { 00622 mAllowAgendaUpdate = enable; 00623 } 00624 00625 int KOAgendaView::maxDatesHint() 00626 { 00627 // Not sure about the max number of events, so return 0 for now. 00628 return 0; 00629 } 00630 00631 int KOAgendaView::currentDateCount() 00632 { 00633 return mSelectedDates.count(); 00634 } 00635 00636 Incidence::List KOAgendaView::selectedIncidences() 00637 { 00638 Incidence::List selected; 00639 Incidence *incidence; 00640 00641 incidence = mAgenda->selectedIncidence(); 00642 if (incidence) selected.append(incidence); 00643 00644 incidence = mAllDayAgenda->selectedIncidence(); 00645 if (incidence) selected.append(incidence); 00646 00647 return selected; 00648 } 00649 00650 DateList KOAgendaView::selectedDates() 00651 { 00652 DateList selected; 00653 QDate qd; 00654 00655 qd = mAgenda->selectedIncidenceDate(); 00656 if (qd.isValid()) selected.append(qd); 00657 00658 qd = mAllDayAgenda->selectedIncidenceDate(); 00659 if (qd.isValid()) selected.append(qd); 00660 00661 return selected; 00662 } 00663 00664 bool KOAgendaView::eventDurationHint( QDateTime &startDt, QDateTime &endDt, 00665 bool &allDay ) 00666 { 00667 if ( selectionStart().isValid() ) { 00668 startDt = selectionStart(); 00669 endDt = selectionEnd(); 00670 allDay = selectedIsAllDay(); 00671 return true; 00672 } 00673 return false; 00674 } 00675 00677 bool KOAgendaView::selectedIsSingleCell() 00678 { 00679 if ( !selectionStart().isValid() || !selectionEnd().isValid() ) return false; 00680 00681 if (selectedIsAllDay()) { 00682 int days = selectionStart().daysTo(selectionEnd()); 00683 return ( days < 1 ); 00684 } else { 00685 int secs = selectionStart().secsTo(selectionEnd()); 00686 return ( secs <= 24*60*60/mAgenda->rows() ); 00687 } 00688 } 00689 00690 00691 void KOAgendaView::updateView() 00692 { 00693 // kdDebug(5850) << "KOAgendaView::updateView()" << endl; 00694 fillAgenda(); 00695 } 00696 00697 00698 /* 00699 Update configuration settings for the agenda view. This method is not 00700 complete. 00701 */ 00702 void KOAgendaView::updateConfig() 00703 { 00704 // kdDebug(5850) << "KOAgendaView::updateConfig()" << endl; 00705 00706 // update config for children 00707 mTimeLabels->updateConfig(); 00708 mAgenda->updateConfig(); 00709 mAllDayAgenda->updateConfig(); 00710 00711 // widget synchronization 00712 //TODO: find a better way, maybe signal/slot 00713 mTimeLabels->positionChanged(); 00714 00715 // for some reason, this needs to be called explicitly 00716 mTimeLabels->repaint(); 00717 00718 mDummyAllDayLeft->setFixedWidth(mTimeLabels->width()); 00719 00720 // ToolTips displaying summary of events 00721 KOAgendaItem::toolTipGroup()->setEnabled(KOPrefs::instance() 00722 ->mEnableToolTips); 00723 00724 setHolidayMasks(); 00725 00726 createDayLabels(); 00727 00728 updateView(); 00729 } 00730 00731 00732 void KOAgendaView::updateEventDates( KOAgendaItem *item ) 00733 { 00734 // kdDebug(5850) << "KOAgendaView::updateEventDates(): " << item->text() << endl; 00735 00736 QDateTime startDt,endDt; 00737 00738 // Start date of this incidence, calculate the offset from it (so recurring and 00739 // non-recurring items can be treated exactly the same, we never need to check 00740 // for doesRecur(), because we only move the start day by the number of days the 00741 // agenda item was really moved. Smart, isn't it?) 00742 QDate thisDate; 00743 if ( item->cellXLeft() < 0 ) { 00744 thisDate = ( mSelectedDates.first() ).addDays( item->cellXLeft() ); 00745 } else { 00746 thisDate = mSelectedDates[ item->cellXLeft() ]; 00747 } 00748 QDate oldThisDate( item->itemDate() ); 00749 int daysOffset = oldThisDate.daysTo( thisDate ); 00750 int daysLength = 0; 00751 00752 // startDt.setDate( startDate ); 00753 00754 Incidence *incidence = item->incidence(); 00755 if ( !incidence ) return; 00756 Incidence *oldIncidence = incidence->clone(); 00757 00758 QTime startTime(0,0,0), endTime(0,0,0); 00759 if ( incidence->doesFloat() ) { 00760 daysLength = item->cellWidth() - 1; 00761 } else { 00762 startTime = mAgenda->gyToTime( item->cellYTop() ); 00763 if ( item->lastMultiItem() ) { 00764 endTime = mAgenda->gyToTime( item->lastMultiItem()->cellYBottom() + 1 ); 00765 daysLength = item->lastMultiItem()->cellXLeft() - item->cellXLeft(); 00766 } else { 00767 endTime = mAgenda->gyToTime( item->cellYBottom() + 1 ); 00768 } 00769 } 00770 00771 // kdDebug(5850) << "KOAgendaView::updateEventDates(): now setting dates" << endl; 00772 Incidence *i = incidence->clone(); 00773 if ( i->type() == "Event" ) { 00774 startDt = i->dtStart(); 00775 startDt = startDt.addDays( daysOffset ); 00776 startDt.setTime( startTime ); 00777 endDt = startDt.addDays( daysLength ); 00778 endDt.setTime( endTime ); 00779 Event*ev = static_cast<Event*>(i); 00780 if( i->dtStart() == startDt && ev->dtEnd() == endDt ) { 00781 // No change 00782 delete i; 00783 return; 00784 } 00785 i->setDtStart( startDt ); 00786 ev->setDtEnd( endDt ); 00787 } else if ( i->type() == "Todo" ) { 00788 Todo *td = static_cast<Todo*>(i); 00789 endDt = td->dtDue(); 00790 endDt = endDt.addDays( daysOffset ); 00791 endDt.setTime( endTime ); 00792 00793 if( td->dtDue() == endDt ) { 00794 // No change 00795 delete i; 00796 return; 00797 } 00798 td->setDtDue( endDt ); 00799 } 00800 // TODO: Adjusting the recurrence should really go to CalendarView so this 00801 // functionality will also be available in other views! 00802 Recurrence *recur = incidence->recurrence(); 00803 if ( recur && (recur->doesRecur()!=Recurrence::rNone) && (daysOffset!=0) ) { 00804 switch ( recur->doesRecur() ) { 00805 case Recurrence::rYearlyPos: { 00806 int freq = recur->frequency(); 00807 int duration = recur->duration(); 00808 QDate endDt( recur->endDate() ); 00809 bool negative = false; 00810 00811 QPtrList<Recurrence::rMonthPos> monthPos( recur->yearMonthPositions() ); 00812 if ( monthPos.first() ) { 00813 negative = monthPos.first()->negative; 00814 } 00815 QBitArray days( 7 ); 00816 int pos = 0; 00817 days.fill( false ); 00818 days.setBit( thisDate.dayOfWeek() - 1 ); 00819 if ( negative ) { 00820 pos = - ( thisDate.daysInMonth() - thisDate.day() - 1 ) / 7 - 1; 00821 } else { 00822 pos = ( thisDate.day()-1 ) / 7 + 1; 00823 } 00824 // Terrible hack: to change the month days, I have to unset the recurrence, and set all days manually again 00825 recur->unsetRecurs(); 00826 if ( duration != 0 ) { 00827 recur->setYearly( Recurrence::rYearlyPos, freq, duration ); 00828 } else { 00829 recur->setYearly( Recurrence::rYearlyPos, freq, endDt ); 00830 } 00831 recur->addYearlyMonthPos( pos, days ); 00832 recur->addYearlyNum( thisDate.month() ); 00833 00834 break; } 00835 case Recurrence::rYearlyDay: { 00836 int freq = recur->frequency(); 00837 int duration = recur->duration(); 00838 QDate endDt( recur->endDate() ); 00839 // Terrible hack: to change the month days, I have to unset the recurrence, and set all days manually again 00840 recur->unsetRecurs(); 00841 if ( duration == 0 ) { // end by date 00842 recur->setYearly( Recurrence::rYearlyDay, freq, endDt ); 00843 } else { 00844 recur->setYearly( Recurrence::rYearlyDay, freq, duration ); 00845 } 00846 recur->addYearlyNum( thisDate.dayOfYear() ); 00847 break; } 00848 case Recurrence::rYearlyMonth: { 00849 int freq = recur->frequency(); 00850 int duration = recur->duration(); 00851 QDate endDt( recur->endDate() ); 00852 // Terrible hack: to change the month days, I have to unset the recurrence, and set all days manually again 00853 recur->unsetRecurs(); 00854 if ( duration != 0 ) { 00855 recur->setYearlyByDate( thisDate.day(), recur->feb29YearlyType(), freq, duration ); 00856 } else { 00857 recur->setYearlyByDate( thisDate.day(), recur->feb29YearlyType(), freq, endDt ); 00858 } 00859 recur->addYearlyNum( thisDate.month() ); 00860 break; } 00861 case Recurrence::rMonthlyPos: { 00862 int freq = recur->frequency(); 00863 int duration = recur->duration(); 00864 QDate endDt( recur->endDate() ); 00865 QPtrList<Recurrence::rMonthPos> monthPos( recur->monthPositions() ); 00866 if ( !monthPos.isEmpty() ) { 00867 // TODO: How shall I adapt the day x of week Y if we move the date across month borders??? 00868 // for now, just use the date of the moved item and assume the recurrence only occurs on that day. 00869 // That's fine for korganizer, but might mess up other organizers. 00870 QBitArray rDays( 7 ); 00871 rDays = monthPos.first()->rDays; 00872 bool negative = monthPos.first()->negative; 00873 int newPos; 00874 rDays.fill( false ); 00875 rDays.setBit( thisDate.dayOfWeek() - 1 ); 00876 if ( negative ) { 00877 newPos = - ( thisDate.daysInMonth() - thisDate.day() - 1 ) / 7 - 1; 00878 } else { 00879 newPos = ( thisDate.day()-1 ) / 7 + 1; 00880 } 00881 00882 // Terrible hack: to change the month days, I have to unset the recurrence, and set all days manually again 00883 recur->unsetRecurs(); 00884 if ( duration == 0 ) { // end by date 00885 recur->setMonthly( Recurrence::rMonthlyPos, freq, endDt ); 00886 } else { 00887 recur->setMonthly( Recurrence::rMonthlyPos, freq, duration ); 00888 } 00889 recur->addMonthlyPos( newPos, rDays ); 00890 } 00891 break;} 00892 case Recurrence::rMonthlyDay: { 00893 int freq = recur->frequency(); 00894 int duration = recur->duration(); 00895 QDate endDt( recur->endDate() ); 00896 QPtrList<int> monthDays( recur->monthDays() ); 00897 // Terrible hack: to change the month days, I have to unset the recurrence, and set all days manually again 00898 recur->unsetRecurs(); 00899 if ( duration == 0 ) { // end by date 00900 recur->setMonthly( Recurrence::rMonthlyDay, freq, endDt ); 00901 } else { 00902 recur->setMonthly( Recurrence::rMonthlyDay, freq, duration ); 00903 } 00904 // TODO: How shall I adapt the n-th day if we move the date across month borders??? 00905 // for now, just use the date of the moved item and assume the recurrence only occurs on that day. 00906 // That's fine for korganizer, but might mess up other organizers. 00907 recur->addMonthlyDay( thisDate.day() ); 00908 00909 break;} 00910 case Recurrence::rWeekly: { 00911 QBitArray days(7), oldDays( recur->days() ); 00912 int offset = daysOffset % 7; 00913 if ( offset<0 ) offset = (offset+7) % 7; 00914 // rotate the days 00915 for (int d=0; d<7; d++ ) { 00916 days.setBit( (d+offset) % 7, oldDays.at(d) ); 00917 } 00918 if ( recur->duration() == 0 ) { // end by date 00919 recur->setWeekly( recur->frequency(), days, recur->endDate(), recur->weekStart() ); 00920 } else { // duration or no end 00921 recur->setWeekly( recur->frequency(), days, recur->duration(), recur->weekStart() ); 00922 } 00923 break;} 00924 // nothing to be done for the following: 00925 case Recurrence::rDaily: 00926 case Recurrence::rHourly: 00927 case Recurrence::rMinutely: 00928 case Recurrence::rNone: 00929 default: 00930 break; 00931 } 00932 if ( recur->duration()==0 ) { // end by date 00933 recur->setEndDate( recur->endDate().addDays( daysOffset ) ); 00934 } 00935 KMessageBox::information( this, i18n("A recurring incidence was moved to a different day. The recurrence settings have been updated with that move. Please check them in the incidence editor."), i18n("Recurrence Moved"), "RecurrenceMoveInAgendaWarning" ); 00936 } 00937 00938 i->setRevision( i->revision() + 1 ); 00939 if( !KOPrefs::instance()->mUseGroupwareCommunication || 00940 KOGroupware::instance()->sendICalMessage( this, KCal::Scheduler::Request, 00941 i ) ) { 00942 if ( i->type() == "Event" ) { 00943 incidence->setDtStart( startDt ); 00944 (static_cast<Event*>( incidence ) )->setDtEnd( endDt ); 00945 } else if ( i->type() == "Todo" ) { 00946 (static_cast<Todo*>( incidence ) )->setDtDue( endDt ); 00947 } 00948 incidence->setRevision( i->revision() ); 00949 item->setItemDate( startDt.date() ); 00950 00951 KOIncidenceToolTip::remove( item ); 00952 KOIncidenceToolTip::add( item, incidence, KOAgendaItem::toolTipGroup() ); 00953 00954 // don't update the agenda as the item already has the correct coordinates. 00955 // an update would delete the current item and recreate it, but we are still 00956 // using a pointer to that item! => CRASH 00957 enableAgendaUpdate( false ); 00958 // We need to do this in a timer to make sure we are not deleting the item 00959 // we are currently working on, which would lead to crashes 00960 // Only the actually moved agenda item is already at the correct position and mustn't be 00961 // recreated. All others have to!!! 00962 if ( incidence->doesRecur() ) { 00963 mUpdateItem = incidence; 00964 QTimer::singleShot( 0, this, SLOT( doUpdateItem() ) ); 00965 } 00966 00967 emit incidenceChanged( oldIncidence, incidence ); 00968 enableAgendaUpdate( true ); 00969 } else { 00970 updateView(); 00971 } 00972 00973 delete i; 00974 delete oldIncidence; 00975 // kdDebug(5850) << "KOAgendaView::updateEventDates() done " << endl; 00976 } 00977 00978 void KOAgendaView::doUpdateItem() 00979 { 00980 if ( mUpdateItem ) { 00981 changeIncidenceDisplay( mUpdateItem, KOGlobals::INCIDENCEEDITED ); 00982 mUpdateItem = 0; 00983 } 00984 } 00985 00986 00987 00988 void KOAgendaView::showDates( const QDate &start, const QDate &end ) 00989 { 00990 // kdDebug(5850) << "KOAgendaView::selectDates" << endl; 00991 00992 mSelectedDates.clear(); 00993 00994 QDate d = start; 00995 while (d <= end) { 00996 mSelectedDates.append(d); 00997 d = d.addDays( 1 ); 00998 } 00999 01000 // and update the view 01001 fillAgenda(); 01002 } 01003 01004 01005 void KOAgendaView::showIncidences( const Incidence::List & ) 01006 { 01007 kdDebug(5850) << "KOAgendaView::showIncidences( const Incidence::List & ) is not yet implemented" << endl; 01008 } 01009 01010 void KOAgendaView::insertIncidence( Incidence *incidence, QDate curDate, 01011 int curCol ) 01012 { 01013 Event *event = dynamic_cast<Event *>( incidence ); 01014 Todo *todo = dynamic_cast<Todo *>( incidence ); 01015 01016 if ( curCol < 0 ) { 01017 curCol = mSelectedDates.findIndex( curDate ); 01018 } 01019 // The date for the event is not displayed, just ignore it 01020 if ( curCol < 0 || curCol > int( mSelectedDates.size() ) ) 01021 return; 01022 01023 int beginX; 01024 int endX; 01025 if ( event ) { 01026 beginX = curDate.daysTo( incidence->dtStart().date() ) + curCol; 01027 endX = curDate.daysTo( event->dtEnd().date() ) + curCol; 01028 } else if ( todo ) { 01029 beginX = curDate.daysTo( todo->dtDue().date() ) + curCol; 01030 endX = beginX; 01031 } else { 01032 return; 01033 } 01034 01035 if ( incidence->doesFloat() ) { 01036 if ( incidence->recurrence()->doesRecur() ) { 01037 mAllDayAgenda->insertAllDayItem( incidence, curDate, curCol, curCol ); 01038 } else { 01039 if ( ( beginX <= 0 && curCol == 0 ) || beginX == curCol ) { 01040 mAllDayAgenda->insertAllDayItem( incidence, curDate, beginX, endX ); 01041 } 01042 } 01043 } else if ( event && event->isMultiDay() ) { 01044 int startY = mAgenda->timeToY( event->dtStart().time() ); 01045 int endY = mAgenda->timeToY( event->dtEnd().time() ) - 1; 01046 if ( (beginX <= 0 && curCol == 0) || beginX == curCol ) { 01047 mAgenda->insertMultiItem( event, curDate, beginX, endX, startY, endY ); 01048 } 01049 if ( beginX == curCol ) { 01050 mMaxY[curCol] = mAgenda->timeToY( QTime(23,59) ); 01051 if ( startY < mMinY[curCol] ) mMinY[curCol] = startY; 01052 } else if ( endX == curCol ) { 01053 mMinY[curCol] = mAgenda->timeToY( QTime(0,0) ); 01054 if ( endY > mMaxY[curCol] ) mMaxY[curCol] = endY; 01055 } else { 01056 mMinY[curCol] = mAgenda->timeToY( QTime(0,0) ); 01057 mMaxY[curCol] = mAgenda->timeToY( QTime(23,59) ); 01058 } 01059 } else { 01060 int startY = 0, endY = 0; 01061 if ( event ) { 01062 startY = mAgenda->timeToY( incidence->dtStart().time() ); 01063 endY = mAgenda->timeToY( event->dtEnd().time() ) - 1; 01064 } 01065 if ( todo ) { 01066 QTime t = todo->dtDue().time(); 01067 endY = mAgenda->timeToY( t ) - 1; 01068 startY = mAgenda->timeToY( t.addSecs( -1800 ) ); 01069 } 01070 if ( endY < startY ) endY = startY; 01071 mAgenda->insertItem( incidence, curDate, curCol, startY, endY ); 01072 if ( startY < mMinY[curCol] ) mMinY[curCol] = startY; 01073 if ( endY > mMaxY[curCol] ) mMaxY[curCol] = endY; 01074 } 01075 } 01076 01077 void KOAgendaView::changeIncidenceDisplayAdded( Incidence *incidence ) 01078 { 01079 Todo *todo = dynamic_cast<Todo *>(incidence); 01080 if ( !calendar()->filter()->filterIncidence( incidence ) || 01081 ( todo && !KOPrefs::instance()->showAllDayTodo() ) ) 01082 return; 01083 01084 QDate f = mSelectedDates.first(); 01085 QDate l = mSelectedDates.last(); 01086 QDate startDt = incidence->dtStart().date(); 01087 01088 if ( incidence->doesRecur() ) { 01089 DateList::ConstIterator dit; 01090 QDate curDate; 01091 for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { 01092 curDate = *dit; 01093 if ( incidence->recursOn( curDate ) ) { 01094 insertIncidence( incidence, curDate ); 01095 } 01096 } 01097 return; 01098 } 01099 01100 QDate endDt; 01101 if ( incidence->type() == "Event" ) 01102 endDt = (static_cast<Event *>(incidence))->dtEnd().date(); 01103 if ( todo ) { 01104 bool overdue = (!todo->isCompleted()) && 01105 (todo->dtDue() < QDate::currentDate() ); 01106 endDt = overdue ? QDate::currentDate() 01107 : todo->dtDue().date(); 01108 if ( endDt >= f && endDt <= l ) { 01109 insertIncidence( incidence, endDt ); 01110 return; 01111 } 01112 } 01113 01114 if ( startDt <= l ) { 01115 if ( startDt >= f ) { 01116 insertIncidence( incidence, startDt ); 01117 } else if ( endDt >= f ) { 01118 insertIncidence( incidence, endDt ); 01119 } 01120 } 01121 } 01122 01123 void KOAgendaView::changeIncidenceDisplay( Incidence *incidence, int mode ) 01124 { 01125 switch ( mode ) { 01126 case KOGlobals::INCIDENCEADDED: { 01127 // Add an event. No need to recreate the whole view! 01128 // recreating everything even causes troubles: dropping to the day matrix 01129 // recreates the agenda items, but the evaluation is still in an agendaItems' code, 01130 // which was deleted in the mean time. Thus KOrg crashes... 01131 changeIncidenceDisplayAdded( incidence ); 01132 break; 01133 } 01134 case KOGlobals::INCIDENCEEDITED: { 01135 if ( !mAllowAgendaUpdate ) { 01136 updateEventIndicators(); 01137 } else { 01138 removeIncidence( incidence ); 01139 updateEventIndicators(); 01140 changeIncidenceDisplayAdded( incidence ); 01141 } 01142 break; 01143 } 01144 case KOGlobals::INCIDENCEDELETED: { 01145 mAgenda->removeIncidence( incidence ); 01146 mAllDayAgenda->removeIncidence( incidence ); 01147 updateEventIndicators(); 01148 break; 01149 } 01150 default: 01151 updateView(); 01152 } 01153 } 01154 01155 void KOAgendaView::fillAgenda( const QDate & ) 01156 { 01157 fillAgenda(); 01158 } 01159 01160 void KOAgendaView::fillAgenda() 01161 { 01162 enableAgendaUpdate( true ); 01163 clearView(); 01164 01165 mAllDayAgenda->changeColumns(mSelectedDates.count()); 01166 mAgenda->changeColumns(mSelectedDates.count()); 01167 mEventIndicatorTop->changeColumns(mSelectedDates.count()); 01168 mEventIndicatorBottom->changeColumns(mSelectedDates.count()); 01169 01170 createDayLabels(); 01171 setHolidayMasks(); 01172 01173 mMinY.resize(mSelectedDates.count()); 01174 mMaxY.resize(mSelectedDates.count()); 01175 01176 Event::List dayEvents; 01177 01178 // ToDo items shall be displayed for the day they are due, but only shown today if they are already overdue. 01179 // Therefore, get all of them. 01180 Todo::List todos = calendar()->todos(); 01181 01182 mAgenda->setDateList(mSelectedDates); 01183 01184 QDate today = QDate::currentDate(); 01185 01186 DateList::ConstIterator dit; 01187 int curCol = 0; 01188 for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { 01189 QDate currentDate = *dit; 01190 // kdDebug(5850) << "KOAgendaView::fillAgenda(): " << currentDate.toString() 01191 // << endl; 01192 01193 dayEvents = calendar()->events(currentDate,true); 01194 01195 // Default values, which can never be reached 01196 mMinY[curCol] = mAgenda->timeToY(QTime(23,59)) + 1; 01197 mMaxY[curCol] = mAgenda->timeToY(QTime(0,0)) - 1; 01198 01199 unsigned int numEvent; 01200 for(numEvent=0;numEvent<dayEvents.count();++numEvent) { 01201 Event *event = *dayEvents.at(numEvent); 01202 // kdDebug(5850) << " Event: " << event->summary() << endl; 01203 insertIncidence( event, currentDate, curCol ); 01204 } 01205 // if (numEvent == 0) kdDebug(5850) << " No events" << endl; 01206 01207 01208 // ---------- [display Todos -------------- 01209 if ( KOPrefs::instance()->showAllDayTodo() ) { 01210 unsigned int numTodo; 01211 for (numTodo = 0; numTodo < todos.count(); ++numTodo) { 01212 Todo *todo = *todos.at(numTodo); 01213 01214 if ( ! todo->hasDueDate() ) continue; // todo shall not be displayed if it has no date 01215 01216 // ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue. 01217 // Already completed items can be displayed on their original due date 01218 bool overdue = (!todo->isCompleted()) && (todo->dtDue() < today); 01219 01220 if ( (( todo->dtDue().date() == currentDate) && !overdue) || 01221 (( currentDate == today) && overdue) || 01222 ( todo->recursOn( currentDate ) ) ) { 01223 if ( todo->doesFloat() || overdue ) { // Todo has no due-time set or is already overdue 01224 //kdDebug(5850) << "todo without time:" << todo->dtDueDateStr() << ";" << todo->summary() << endl; 01225 01226 mAllDayAgenda->insertAllDayItem(todo, currentDate, curCol, curCol); 01227 } else { 01228 //kdDebug(5850) << "todo with time:" << todo->dtDueStr() << ";" << todo->summary() << endl; 01229 01230 int endY = mAgenda->timeToY(todo->dtDue().time()) - 1; 01231 int startY = endY - 1; 01232 01233 mAgenda->insertItem(todo,currentDate,curCol,startY,endY); 01234 01235 if (startY < mMinY[curCol]) mMinY[curCol] = startY; 01236 if (endY > mMaxY[curCol]) mMaxY[curCol] = endY; 01237 } 01238 } 01239 } 01240 } 01241 // ---------- display Todos] -------------- 01242 01243 ++curCol; 01244 } 01245 01246 mAgenda->checkScrollBoundaries(); 01247 01248 // mAgenda->viewport()->update(); 01249 // mAllDayAgenda->viewport()->update(); 01250 01251 // make invalid 01252 deleteSelectedDateTime(); 01253 01254 emit incidenceSelected( 0 ); 01255 01256 // kdDebug(5850) << "Fill Agenda done" << endl; 01257 } 01258 01259 void KOAgendaView::clearView() 01260 { 01261 // kdDebug(5850) << "ClearView" << endl; 01262 mAllDayAgenda->clear(); 01263 mAgenda->clear(); 01264 } 01265 01266 void KOAgendaView::printPreview(CalPrinter *calPrinter, const QDate &fd, 01267 const QDate &td) 01268 { 01269 #ifndef KORG_NOPRINTER 01270 if (fd == td) 01271 calPrinter->preview(CalPrinter::Day, fd, td); 01272 else 01273 calPrinter->preview(CalPrinter::Week, fd, td); 01274 #endif 01275 } 01276 01277 CalPrinter::PrintType KOAgendaView::printType() 01278 { 01279 if ( currentDateCount() == 1 ) return CalPrinter::Day; 01280 else return CalPrinter::Week; 01281 } 01282 01283 void KOAgendaView::newEvent( const QPoint &pos) 01284 { 01285 if (!mSelectedDates.count()) return; 01286 01287 QDate day = mSelectedDates[pos.x()]; 01288 01289 QTime time = mAgenda->gyToTime(pos.y()); 01290 QDateTime dt(day,time); 01291 01292 emit newEventSignal(dt); 01293 } 01294 01295 void KOAgendaView::newEvent(const QPoint &start, const QPoint &end) 01296 { 01297 if (!mSelectedDates.count()) return; 01298 01299 QDate dayStart = mSelectedDates[start.x()]; 01300 QDate dayEnd = mSelectedDates[end.x()]; 01301 01302 QTime timeStart = mAgenda->gyToTime( start.y() ); 01303 QTime timeEnd = mAgenda->gyToTime( end.y() + 1 ); 01304 01305 QDateTime dtStart(dayStart,timeStart); 01306 QDateTime dtEnd(dayEnd,timeEnd); 01307 01308 emit newEventSignal(dtStart,dtEnd); 01309 } 01310 01311 void KOAgendaView::newEventAllDay( const QPoint &start ) 01312 { 01313 if (!mSelectedDates.count()) return; 01314 01315 QDate day = mSelectedDates[start.x()]; 01316 01317 emit newEventSignal(day); 01318 } 01319 01320 void KOAgendaView::updateEventIndicatorTop(int newY) 01321 { 01322 uint i; 01323 for(i=0;i<mMinY.size();++i) { 01324 if (newY >= mMinY[i]) mEventIndicatorTop->enableColumn(i,true); 01325 else mEventIndicatorTop->enableColumn(i,false); 01326 } 01327 01328 mEventIndicatorTop->update(); 01329 } 01330 01331 void KOAgendaView::updateEventIndicatorBottom(int newY) 01332 { 01333 uint i; 01334 for(i=0;i<mMaxY.size();++i) { 01335 if (newY <= mMaxY[i]) mEventIndicatorBottom->enableColumn(i,true); 01336 else mEventIndicatorBottom->enableColumn(i,false); 01337 } 01338 01339 mEventIndicatorBottom->update(); 01340 } 01341 01342 void KOAgendaView::slotTodoDropped( Todo *todo, const QPoint &gpos, bool allDay ) 01343 { 01344 if (gpos.x()<0 || gpos.y()<0) return; 01345 QDate day = mSelectedDates[gpos.x()]; 01346 QTime time = mAgenda->gyToTime(gpos.y()); 01347 QDateTime newTime(day, time); 01348 01349 if (todo) { 01350 Todo *existingTodo = calendar()->todo(todo->uid()); 01351 if(existingTodo) { 01352 kdDebug(5850) << "Drop existing Todo" << endl; 01353 Todo *oldTodo = existingTodo->clone(); 01354 existingTodo->setDtDue( newTime ); 01355 existingTodo->setFloats( allDay ); 01356 existingTodo->setHasDueDate( true ); 01357 existingTodo->setRevision( existingTodo->revision() + 1 ); 01358 emit incidenceChanged( oldTodo, existingTodo ); 01359 delete oldTodo; 01360 } else { 01361 kdDebug(5850) << "Drop new Todo" << endl; 01362 todo->setDtDue( newTime ); 01363 todo->setFloats( allDay ); 01364 existingTodo->setHasDueDate( true ); 01365 if ( calendar()->addTodo( todo ) ) { 01366 emit incidenceAdded(todo); 01367 } else { 01368 KODialogManager::errorSaveTodo( this ); 01369 } 01370 } 01371 } 01372 } 01373 01374 void KOAgendaView::startDrag( Incidence *incidence ) 01375 { 01376 #ifndef KORG_NODND 01377 DndFactory factory( calendar() ); 01378 ICalDrag *vd = factory.createDrag( incidence, this ); 01379 if ( vd->drag() ) { 01380 kdDebug(5850) << "KOAgendaView::startDrag(): Delete drag source" << endl; 01381 } 01382 #endif 01383 } 01384 01385 void KOAgendaView::readSettings() 01386 { 01387 readSettings(KOGlobals::self()->config()); 01388 } 01389 01390 void KOAgendaView::readSettings(KConfig *config) 01391 { 01392 // kdDebug(5850) << "KOAgendaView::readSettings()" << endl; 01393 01394 config->setGroup("Views"); 01395 01396 #ifndef KORG_NOSPLITTER 01397 QValueList<int> sizes = config->readIntListEntry("Separator AgendaView"); 01398 if (sizes.count() == 2) { 01399 mSplitterAgenda->setSizes(sizes); 01400 } 01401 #endif 01402 01403 updateConfig(); 01404 } 01405 01406 void KOAgendaView::writeSettings(KConfig *config) 01407 { 01408 // kdDebug(5850) << "KOAgendaView::writeSettings()" << endl; 01409 01410 config->setGroup("Views"); 01411 01412 #ifndef KORG_NOSPLITTER 01413 QValueList<int> list = mSplitterAgenda->sizes(); 01414 config->writeEntry("Separator AgendaView",list); 01415 #endif 01416 } 01417 01418 void KOAgendaView::setHolidayMasks() 01419 { 01420 mHolidayMask.resize( mSelectedDates.count() + 1 ); 01421 01422 for( uint i = 0; i < mSelectedDates.count(); ++i ) { 01423 mHolidayMask[i] = !KOCore::self()->isWorkDay( mSelectedDates[ i ] ); 01424 } 01425 01426 // Store the information about the day before the visible area (needed for 01427 // overnight working hours) in the last bit of the mask: 01428 bool showDay = !KOCore::self()->isWorkDay( mSelectedDates[ 0 ].addDays( -1 ) ); 01429 mHolidayMask[ mSelectedDates.count() ] = showDay; 01430 01431 mAgenda->setHolidayMask( &mHolidayMask ); 01432 mAllDayAgenda->setHolidayMask( &mHolidayMask ); 01433 } 01434 01435 void KOAgendaView::setContentsPos( int y ) 01436 { 01437 mAgenda->setContentsPos( 0, y ); 01438 } 01439 01440 void KOAgendaView::setExpandedButton( bool expanded ) 01441 { 01442 if ( expanded ) { 01443 mExpandButton->setPixmap( mExpandedPixmap ); 01444 } else { 01445 mExpandButton->setPixmap( mNotExpandedPixmap ); 01446 } 01447 } 01448 01449 void KOAgendaView::clearSelection() 01450 { 01451 mAgenda->deselectItem(); 01452 mAllDayAgenda->deselectItem(); 01453 } 01454 01455 void KOAgendaView::newTimeSpanSelectedAllDay( const QPoint &start, const QPoint &end ) 01456 { 01457 newTimeSpanSelected( start, end ); 01458 mTimeSpanInAllDay = true; 01459 } 01460 01461 void KOAgendaView::newTimeSpanSelected( const QPoint &start, const QPoint &end ) 01462 { 01463 if (!mSelectedDates.count()) return; 01464 01465 mTimeSpanInAllDay = false; 01466 01467 QDate dayStart = mSelectedDates[start.x()]; 01468 QDate dayEnd = mSelectedDates[end.x()]; 01469 01470 QTime timeStart = mAgenda->gyToTime(start.y()); 01471 QTime timeEnd = mAgenda->gyToTime( end.y() + 1 ); 01472 01473 QDateTime dtStart(dayStart,timeStart); 01474 QDateTime dtEnd(dayEnd,timeEnd); 01475 01476 mTimeSpanBegin = dtStart; 01477 mTimeSpanEnd = dtEnd; 01478 } 01479 01480 void KOAgendaView::deleteSelectedDateTime() 01481 { 01482 mTimeSpanBegin.setDate(QDate()); 01483 mTimeSpanEnd.setDate(QDate()); 01484 mTimeSpanInAllDay = false; 01485 } 01486 01487 void KOAgendaView::setTypeAheadReceiver( QObject *o ) 01488 { 01489 mAgenda->setTypeAheadReceiver( o ); 01490 mAllDayAgenda->setTypeAheadReceiver( o ); 01491 } 01492 01493 void KOAgendaView::finishTypeAhead() 01494 { 01495 mAgenda->finishTypeAhead(); 01496 mAllDayAgenda->finishTypeAhead(); 01497 } 01498 01499 void KOAgendaView::removeIncidence( Incidence *incidence ) 01500 { 01501 mAgenda->removeIncidence( incidence ); 01502 mAllDayAgenda->removeIncidence( incidence ); 01503 } 01504 01505 void KOAgendaView::updateEventIndicators() 01506 { 01507 mMinY = mAgenda->minContentsY(); 01508 mMaxY = mAgenda->maxContentsY(); 01509 01510 mAgenda->checkScrollBoundaries(); 01511 }
KDE Logo
This file is part of the documentation for korganizer Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 27 12:53:21 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003