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 /* Remember the uids of the selected items. In case one of the 01163 * items was deleted and re-added, we want to reselect it. */ 01164 const QString &selectedAgendaUid = 01165 mAgenda->selectedIncidence()? mAgenda->selectedIncidence()->uid():QString::null; 01166 const QString &selectedAllDayAgendaUid = 01167 mAllDayAgenda->selectedIncidence()? mAllDayAgenda->selectedIncidence()->uid():QString::null; 01168 01169 enableAgendaUpdate( true ); 01170 clearView(); 01171 01172 mAllDayAgenda->changeColumns(mSelectedDates.count()); 01173 mAgenda->changeColumns(mSelectedDates.count()); 01174 mEventIndicatorTop->changeColumns(mSelectedDates.count()); 01175 mEventIndicatorBottom->changeColumns(mSelectedDates.count()); 01176 01177 createDayLabels(); 01178 setHolidayMasks(); 01179 01180 mMinY.resize(mSelectedDates.count()); 01181 mMaxY.resize(mSelectedDates.count()); 01182 01183 Event::List dayEvents; 01184 01185 // ToDo items shall be displayed for the day they are due, but only shown today if they are already overdue. 01186 // Therefore, get all of them. 01187 Todo::List todos = calendar()->todos(); 01188 01189 mAgenda->setDateList(mSelectedDates); 01190 01191 QDate today = QDate::currentDate(); 01192 01193 bool somethingReselected = false; 01194 DateList::ConstIterator dit; 01195 int curCol = 0; 01196 for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { 01197 QDate currentDate = *dit; 01198 // kdDebug(5850) << "KOAgendaView::fillAgenda(): " << currentDate.toString() 01199 // << endl; 01200 01201 dayEvents = calendar()->events(currentDate,true); 01202 01203 // Default values, which can never be reached 01204 mMinY[curCol] = mAgenda->timeToY(QTime(23,59)) + 1; 01205 mMaxY[curCol] = mAgenda->timeToY(QTime(0,0)) - 1; 01206 01207 unsigned int numEvent; 01208 for(numEvent=0;numEvent<dayEvents.count();++numEvent) { 01209 Event *event = *dayEvents.at(numEvent); 01210 // kdDebug(5850) << " Event: " << event->summary() << endl; 01211 insertIncidence( event, currentDate, curCol ); 01212 if( event->uid() == selectedAgendaUid && !selectedAgendaUid.isEmpty() ) { 01213 mAgenda->selectItemByUID( event->uid() ); 01214 somethingReselected = true; 01215 } 01216 if( event->uid() == selectedAllDayAgendaUid && !selectedAllDayAgendaUid.isEmpty() ) { 01217 mAllDayAgenda->selectItemByUID( event->uid() ); 01218 somethingReselected = true; 01219 } 01220 01221 } 01222 // if (numEvent == 0) kdDebug(5850) << " No events" << endl; 01223 01224 01225 // ---------- [display Todos -------------- 01226 if ( KOPrefs::instance()->showAllDayTodo() ) { 01227 unsigned int numTodo; 01228 for (numTodo = 0; numTodo < todos.count(); ++numTodo) { 01229 Todo *todo = *todos.at(numTodo); 01230 01231 if ( ! todo->hasDueDate() ) continue; // todo shall not be displayed if it has no date 01232 01233 // ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue. 01234 // Already completed items can be displayed on their original due date 01235 bool overdue = (!todo->isCompleted()) && (todo->dtDue() < today); 01236 01237 if ( (( todo->dtDue().date() == currentDate) && !overdue) || 01238 (( currentDate == today) && overdue) || 01239 ( todo->recursOn( currentDate ) ) ) { 01240 if ( todo->doesFloat() || overdue ) { // Todo has no due-time set or is already overdue 01241 //kdDebug(5850) << "todo without time:" << todo->dtDueDateStr() << ";" << todo->summary() << endl; 01242 01243 mAllDayAgenda->insertAllDayItem(todo, currentDate, curCol, curCol); 01244 } else { 01245 //kdDebug(5850) << "todo with time:" << todo->dtDueStr() << ";" << todo->summary() << endl; 01246 01247 int endY = mAgenda->timeToY(todo->dtDue().time()) - 1; 01248 int startY = endY - 1; 01249 01250 mAgenda->insertItem(todo,currentDate,curCol,startY,endY); 01251 01252 if (startY < mMinY[curCol]) mMinY[curCol] = startY; 01253 if (endY > mMaxY[curCol]) mMaxY[curCol] = endY; 01254 } 01255 } 01256 } 01257 } 01258 // ---------- display Todos] -------------- 01259 01260 ++curCol; 01261 } 01262 01263 mAgenda->checkScrollBoundaries(); 01264 01265 // mAgenda->viewport()->update(); 01266 // mAllDayAgenda->viewport()->update(); 01267 01268 // make invalid 01269 deleteSelectedDateTime(); 01270 01271 if( !somethingReselected ) { 01272 emit incidenceSelected( 0 ); 01273 } 01274 01275 // kdDebug(5850) << "Fill Agenda done" << endl; 01276 } 01277 01278 void KOAgendaView::clearView() 01279 { 01280 // kdDebug(5850) << "ClearView" << endl; 01281 mAllDayAgenda->clear(); 01282 mAgenda->clear(); 01283 } 01284 01285 void KOAgendaView::printPreview(CalPrinter *calPrinter, const QDate &fd, 01286 const QDate &td) 01287 { 01288 #ifndef KORG_NOPRINTER 01289 if (fd == td) 01290 calPrinter->preview(CalPrinter::Day, fd, td); 01291 else 01292 calPrinter->preview(CalPrinter::Week, fd, td); 01293 #endif 01294 } 01295 01296 CalPrinter::PrintType KOAgendaView::printType() 01297 { 01298 if ( currentDateCount() == 1 ) return CalPrinter::Day; 01299 else return CalPrinter::Week; 01300 } 01301 01302 void KOAgendaView::newEvent( const QPoint &pos) 01303 { 01304 if (!mSelectedDates.count()) return; 01305 01306 QDate day = mSelectedDates[pos.x()]; 01307 01308 QTime time = mAgenda->gyToTime(pos.y()); 01309 QDateTime dt(day,time); 01310 01311 emit newEventSignal(dt); 01312 } 01313 01314 void KOAgendaView::newEvent(const QPoint &start, const QPoint &end) 01315 { 01316 if (!mSelectedDates.count()) return; 01317 01318 QDate dayStart = mSelectedDates[start.x()]; 01319 QDate dayEnd = mSelectedDates[end.x()]; 01320 01321 QTime timeStart = mAgenda->gyToTime( start.y() ); 01322 QTime timeEnd = mAgenda->gyToTime( end.y() + 1 ); 01323 01324 QDateTime dtStart(dayStart,timeStart); 01325 QDateTime dtEnd(dayEnd,timeEnd); 01326 01327 emit newEventSignal(dtStart,dtEnd); 01328 } 01329 01330 void KOAgendaView::newEventAllDay( const QPoint &start ) 01331 { 01332 if (!mSelectedDates.count()) return; 01333 01334 QDate day = mSelectedDates[start.x()]; 01335 01336 emit newEventSignal(day); 01337 } 01338 01339 void KOAgendaView::updateEventIndicatorTop(int newY) 01340 { 01341 uint i; 01342 for(i=0;i<mMinY.size();++i) { 01343 if (newY >= mMinY[i]) mEventIndicatorTop->enableColumn(i,true); 01344 else mEventIndicatorTop->enableColumn(i,false); 01345 } 01346 01347 mEventIndicatorTop->update(); 01348 } 01349 01350 void KOAgendaView::updateEventIndicatorBottom(int newY) 01351 { 01352 uint i; 01353 for(i=0;i<mMaxY.size();++i) { 01354 if (newY <= mMaxY[i]) mEventIndicatorBottom->enableColumn(i,true); 01355 else mEventIndicatorBottom->enableColumn(i,false); 01356 } 01357 01358 mEventIndicatorBottom->update(); 01359 } 01360 01361 void KOAgendaView::slotTodoDropped( Todo *todo, const QPoint &gpos, bool allDay ) 01362 { 01363 if (gpos.x()<0 || gpos.y()<0) return; 01364 QDate day = mSelectedDates[gpos.x()]; 01365 QTime time = mAgenda->gyToTime(gpos.y()); 01366 QDateTime newTime(day, time); 01367 01368 if (todo) { 01369 Todo *existingTodo = calendar()->todo(todo->uid()); 01370 if(existingTodo) { 01371 kdDebug(5850) << "Drop existing Todo" << endl; 01372 Todo *oldTodo = existingTodo->clone(); 01373 existingTodo->setDtDue( newTime ); 01374 existingTodo->setFloats( allDay ); 01375 existingTodo->setHasDueDate( true ); 01376 existingTodo->setRevision( existingTodo->revision() + 1 ); 01377 emit incidenceChanged( oldTodo, existingTodo ); 01378 delete oldTodo; 01379 } else { 01380 kdDebug(5850) << "Drop new Todo" << endl; 01381 todo->setDtDue( newTime ); 01382 todo->setFloats( allDay ); 01383 existingTodo->setHasDueDate( true ); 01384 if ( calendar()->addTodo( todo ) ) { 01385 emit incidenceAdded(todo); 01386 } else { 01387 KODialogManager::errorSaveTodo( this ); 01388 } 01389 } 01390 } 01391 } 01392 01393 void KOAgendaView::startDrag( Incidence *incidence ) 01394 { 01395 #ifndef KORG_NODND 01396 DndFactory factory( calendar() ); 01397 ICalDrag *vd = factory.createDrag( incidence, this ); 01398 if ( vd->drag() ) { 01399 kdDebug(5850) << "KOAgendaView::startDrag(): Delete drag source" << endl; 01400 } 01401 #endif 01402 } 01403 01404 void KOAgendaView::readSettings() 01405 { 01406 readSettings(KOGlobals::self()->config()); 01407 } 01408 01409 void KOAgendaView::readSettings(KConfig *config) 01410 { 01411 // kdDebug(5850) << "KOAgendaView::readSettings()" << endl; 01412 01413 config->setGroup("Views"); 01414 01415 #ifndef KORG_NOSPLITTER 01416 QValueList<int> sizes = config->readIntListEntry("Separator AgendaView"); 01417 if (sizes.count() == 2) { 01418 mSplitterAgenda->setSizes(sizes); 01419 } 01420 #endif 01421 01422 updateConfig(); 01423 } 01424 01425 void KOAgendaView::writeSettings(KConfig *config) 01426 { 01427 // kdDebug(5850) << "KOAgendaView::writeSettings()" << endl; 01428 01429 config->setGroup("Views"); 01430 01431 #ifndef KORG_NOSPLITTER 01432 QValueList<int> list = mSplitterAgenda->sizes(); 01433 config->writeEntry("Separator AgendaView",list); 01434 #endif 01435 } 01436 01437 void KOAgendaView::setHolidayMasks() 01438 { 01439 mHolidayMask.resize( mSelectedDates.count() + 1 ); 01440 01441 for( uint i = 0; i < mSelectedDates.count(); ++i ) { 01442 mHolidayMask[i] = !KOCore::self()->isWorkDay( mSelectedDates[ i ] ); 01443 } 01444 01445 // Store the information about the day before the visible area (needed for 01446 // overnight working hours) in the last bit of the mask: 01447 bool showDay = !KOCore::self()->isWorkDay( mSelectedDates[ 0 ].addDays( -1 ) ); 01448 mHolidayMask[ mSelectedDates.count() ] = showDay; 01449 01450 mAgenda->setHolidayMask( &mHolidayMask ); 01451 mAllDayAgenda->setHolidayMask( &mHolidayMask ); 01452 } 01453 01454 void KOAgendaView::setContentsPos( int y ) 01455 { 01456 mAgenda->setContentsPos( 0, y ); 01457 } 01458 01459 void KOAgendaView::setExpandedButton( bool expanded ) 01460 { 01461 if ( expanded ) { 01462 mExpandButton->setPixmap( mExpandedPixmap ); 01463 } else { 01464 mExpandButton->setPixmap( mNotExpandedPixmap ); 01465 } 01466 } 01467 01468 void KOAgendaView::clearSelection() 01469 { 01470 mAgenda->deselectItem(); 01471 mAllDayAgenda->deselectItem(); 01472 } 01473 01474 void KOAgendaView::newTimeSpanSelectedAllDay( const QPoint &start, const QPoint &end ) 01475 { 01476 newTimeSpanSelected( start, end ); 01477 mTimeSpanInAllDay = true; 01478 } 01479 01480 void KOAgendaView::newTimeSpanSelected( const QPoint &start, const QPoint &end ) 01481 { 01482 if (!mSelectedDates.count()) return; 01483 01484 mTimeSpanInAllDay = false; 01485 01486 QDate dayStart = mSelectedDates[start.x()]; 01487 QDate dayEnd = mSelectedDates[end.x()]; 01488 01489 QTime timeStart = mAgenda->gyToTime(start.y()); 01490 QTime timeEnd = mAgenda->gyToTime( end.y() + 1 ); 01491 01492 QDateTime dtStart(dayStart,timeStart); 01493 QDateTime dtEnd(dayEnd,timeEnd); 01494 01495 mTimeSpanBegin = dtStart; 01496 mTimeSpanEnd = dtEnd; 01497 } 01498 01499 void KOAgendaView::deleteSelectedDateTime() 01500 { 01501 mTimeSpanBegin.setDate(QDate()); 01502 mTimeSpanEnd.setDate(QDate()); 01503 mTimeSpanInAllDay = false; 01504 } 01505 01506 void KOAgendaView::setTypeAheadReceiver( QObject *o ) 01507 { 01508 mAgenda->setTypeAheadReceiver( o ); 01509 mAllDayAgenda->setTypeAheadReceiver( o ); 01510 } 01511 01512 void KOAgendaView::finishTypeAhead() 01513 { 01514 mAgenda->finishTypeAhead(); 01515 mAllDayAgenda->finishTypeAhead(); 01516 } 01517 01518 void KOAgendaView::removeIncidence( Incidence *incidence ) 01519 { 01520 mAgenda->removeIncidence( incidence ); 01521 mAllDayAgenda->removeIncidence( incidence ); 01522 } 01523 01524 void KOAgendaView::updateEventIndicators() 01525 { 01526 mMinY = mAgenda->minContentsY(); 01527 mMaxY = mAgenda->maxContentsY(); 01528 01529 mAgenda->checkScrollBoundaries(); 01530 }
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 Thu Oct 21 19:46:56 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003