00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <qintdict.h>
00028 #include <qdatetime.h>
00029 #include <qapplication.h>
00030 #include <qpopupmenu.h>
00031 #include <qcursor.h>
00032 #include <qpainter.h>
00033
00034 #include <kdebug.h>
00035 #include <klocale.h>
00036 #include <kiconloader.h>
00037 #include <kglobal.h>
00038
00039 #include "koagendaitem.h"
00040 #include "koprefs.h"
00041
00042 #include "koagenda.h"
00043 #include "koagenda.moc"
00044
00046 MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name)
00047 : QFrame(_agenda->viewport(),name), agenda(_agenda)
00048 {
00049 setLineWidth(0);
00050 setMargin(0);
00051 setBackgroundColor(Qt::red);
00052 minutes = new QTimer(this);
00053 connect(minutes, SIGNAL(timeout()), this, SLOT(updateLocation()));
00054 minutes->start(0, true);
00055
00056 mTimeBox = new QLabel(this);
00057 mTimeBox->setAlignment(Qt::AlignRight | Qt::AlignBottom);
00058 QPalette pal = mTimeBox->palette();
00059 pal.setColor(QColorGroup::Foreground, Qt::red);
00060 mTimeBox->setPalette(pal);
00061 mTimeBox->setAutoMask(true);
00062
00063 agenda->addChild(mTimeBox);
00064
00065 oldToday = -1;
00066 }
00067
00068 MarcusBains::~MarcusBains()
00069 {
00070 delete minutes;
00071 }
00072
00073 int MarcusBains::todayColumn()
00074 {
00075 QDate currentDate = QDate::currentDate();
00076
00077 DateList dateList = agenda->dateList();
00078 DateList::ConstIterator it;
00079 int col = 0;
00080 for(it = dateList.begin(); it != dateList.end(); ++it) {
00081 if((*it) == currentDate)
00082 return QApplication::reverseLayout() ?
00083 agenda->columns() - 1 - col : col;
00084 ++col;
00085 }
00086
00087 return -1;
00088 }
00089
00090 void MarcusBains::updateLocation(bool recalculate)
00091 {
00092 QTime tim = QTime::currentTime();
00093 if((tim.hour() == 0) && (oldTime.hour()==23))
00094 recalculate = true;
00095
00096 int mins = tim.hour()*60 + tim.minute();
00097 int minutesPerCell = 24 * 60 / agenda->rows();
00098 int y = mins*agenda->gridSpacingY()/minutesPerCell;
00099 int today = recalculate ? todayColumn() : oldToday;
00100 int x = agenda->gridSpacingX()*today;
00101 bool disabled = !(KOPrefs::instance()->mMarcusBainsEnabled);
00102
00103 oldTime = tim;
00104 oldToday = today;
00105
00106 if(disabled || (today<0)) {
00107 hide(); mTimeBox->hide();
00108 return;
00109 } else {
00110 show(); mTimeBox->show();
00111 }
00112
00113 if(recalculate)
00114 setFixedSize(agenda->gridSpacingX(),1);
00115 agenda->moveChild(this, x, y);
00116 raise();
00117
00118 if(recalculate)
00119 mTimeBox->setFont(KOPrefs::instance()->mMarcusBainsFont);
00120
00121 mTimeBox->setText(KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds));
00122 mTimeBox->adjustSize();
00123
00124
00125
00126 int offs = (today==agenda->columns()-1) ? -4 : 0;
00127 agenda->moveChild(mTimeBox,
00128 x+agenda->gridSpacingX()-mTimeBox->width()+offs,
00129 y-mTimeBox->height());
00130 mTimeBox->raise();
00131 mTimeBox->setAutoMask(true);
00132
00133 minutes->start(1000,true);
00134 }
00135
00136
00138
00139
00140
00141
00142
00143 KOAgenda::KOAgenda(int columns,int rows,int rowSize,QWidget *parent,
00144 const char *name,WFlags f) :
00145 QScrollView(parent,name,f)
00146 {
00147 mColumns = columns;
00148 mRows = rows;
00149 mGridSpacingY = rowSize;
00150 mAllDayMode = false;
00151
00152 init();
00153 }
00154
00155
00156
00157
00158
00159 KOAgenda::KOAgenda(int columns,QWidget *parent,const char *name,WFlags f) :
00160 QScrollView(parent,name,f)
00161 {
00162 mColumns = columns;
00163 mRows = 1;
00164 mGridSpacingY = 24;
00165 mAllDayMode = true;
00166
00167 init();
00168 }
00169
00170
00171 KOAgenda::~KOAgenda()
00172 {
00173 if(mMarcusBains) delete mMarcusBains;
00174 }
00175
00176
00177 void KOAgenda::init()
00178 {
00179 mGridSpacingX = 100;
00180
00181 mResizeBorderWidth = 8;
00182 mScrollBorderWidth = 8;
00183 mScrollDelay = 30;
00184 mScrollOffset = 10;
00185
00186 enableClipper(true);
00187
00188
00189
00190 setFocusPolicy(WheelFocus);
00191
00192 connect(&mScrollUpTimer,SIGNAL(timeout()),SLOT(scrollUp()));
00193 connect(&mScrollDownTimer,SIGNAL(timeout()),SLOT(scrollDown()));
00194
00195 mStartCellX = 0;
00196 mStartCellY = 0;
00197 mCurrentCellX = 0;
00198 mCurrentCellY = 0;
00199
00200 mSelectionCellX = 0;
00201 mSelectionYTop = 0;
00202 mSelectionHeight = 0;
00203
00204 mOldLowerScrollValue = -1;
00205 mOldUpperScrollValue = -1;
00206
00207 mClickedItem = 0;
00208
00209 mActionItem = 0;
00210 mActionType = NOP;
00211 mItemMoved = false;
00212
00213 mSelectedItem = 0;
00214
00215 mItems.setAutoDelete(true);
00216
00217 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
00218
00219 viewport()->update();
00220
00221 setMinimumSize(30, mGridSpacingY + 1);
00222
00223
00224
00225
00226
00227 setHScrollBarMode(AlwaysOff);
00228
00229 setStartHour(KOPrefs::instance()->mDayBegins);
00230
00231 calculateWorkingHours();
00232
00233 connect(verticalScrollBar(),SIGNAL(valueChanged(int)),
00234 SLOT(checkScrollBoundaries(int)));
00235
00236
00237 if(mAllDayMode)
00238 mMarcusBains = 0;
00239 else {
00240 mMarcusBains = new MarcusBains(this);
00241 addChild(mMarcusBains);
00242 }
00243 }
00244
00245
00246 void KOAgenda::clear()
00247 {
00248
00249
00250 KOAgendaItem *item;
00251 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
00252 removeChild(item);
00253 }
00254 mItems.clear();
00255
00256 mSelectedItem = 0;
00257
00258 clearSelection();
00259 }
00260
00261
00262 void KOAgenda::clearSelection()
00263 {
00264 mSelectionCellX = 0;
00265 mSelectionYTop = 0;
00266 mSelectionHeight = 0;
00267 }
00268
00269 void KOAgenda::marcus_bains()
00270 {
00271 if(mMarcusBains) mMarcusBains->updateLocation(true);
00272 }
00273
00274
00275 void KOAgenda::changeColumns(int columns)
00276 {
00277 if (columns == 0) {
00278 kdDebug() << "KOAgenda::changeColumns() called with argument 0" << endl;
00279 return;
00280 }
00281
00282 clear();
00283 mColumns = columns;
00284
00285
00286
00287
00288 QResizeEvent event( size(), size() );
00289
00290 QApplication::sendEvent( this, &event );
00291 }
00292
00293
00294 Event *KOAgenda::selectedEvent()
00295 {
00296 if (mSelectedItem) {
00297 return mSelectedItem->itemEvent();
00298 } else {
00299 return 0;
00300 }
00301 }
00302
00303 QDate KOAgenda::selectedEventDate()
00304 {
00305 QDate qd;
00306 if (mSelectedItem) {
00307 qd = mSelectedItem->itemDate();
00308 }
00309 return qd;
00310 }
00311
00312
00313
00314
00315
00316 bool KOAgenda::eventFilter ( QObject *object, QEvent *event )
00317 {
00318
00319
00320 switch(event->type()) {
00321 case QEvent::MouseButtonPress:
00322 case QEvent::MouseButtonDblClick:
00323 case QEvent::MouseButtonRelease:
00324 case QEvent::MouseMove:
00325 return eventFilter_mouse(object, static_cast<QMouseEvent *>(event));
00326
00327 case (QEvent::Leave):
00328 if (!mActionItem)
00329 setCursor(arrowCursor);
00330 return true;
00331
00332 default:
00333 return QScrollView::eventFilter(object,event);
00334 }
00335 }
00336
00337
00338 bool KOAgenda::eventFilter_mouse(QObject *object, QMouseEvent *me)
00339 {
00340 QPoint viewportPos;
00341 if (object != viewport()) {
00342 viewportPos = ((QWidget *)object)->mapToParent(me->pos());
00343 } else {
00344 viewportPos = me->pos();
00345 }
00346
00347 switch (me->type()) {
00348 case QEvent::MouseButtonPress:
00349
00350 if (object != viewport()) {
00351 if (me->button() == RightButton) {
00352 mClickedItem = (KOAgendaItem *)object;
00353 if (mClickedItem) {
00354 selectItem(mClickedItem);
00355 emit showEventPopupSignal(mClickedItem->itemEvent());
00356 }
00357
00358 } else {
00359 mActionItem = (KOAgendaItem *)object;
00360 if (mActionItem) {
00361 selectItem(mActionItem);
00362 Event *event = mActionItem->itemEvent();
00363 if ( event->isReadOnly() || event->recurrence()->doesRecur() ) {
00364 mActionItem = 0;
00365 } else {
00366 startItemAction(viewportPos);
00367 }
00368 }
00369 }
00370 } else {
00371 selectItem(0);
00372 mActionItem = 0;
00373 setCursor(arrowCursor);
00374 startSelectAction(viewportPos);
00375 }
00376 break;
00377
00378 case QEvent::MouseButtonRelease:
00379 if (mActionItem) {
00380 endItemAction();
00381 } else if ( mActionType == SELECT ) {
00382 endSelectAction();
00383 }
00384 break;
00385
00386 case QEvent::MouseMove:
00387 if (object != viewport()) {
00388 KOAgendaItem *moveItem = (KOAgendaItem *)object;
00389 if (!moveItem->itemEvent()->isReadOnly() &&
00390 !moveItem->itemEvent()->recurrence()->doesRecur() )
00391 if (!mActionItem)
00392 setNoActionCursor(moveItem,viewportPos);
00393 else
00394 performItemAction(viewportPos);
00395 } else {
00396 if ( mActionType == SELECT ) {
00397 performSelectAction( viewportPos );
00398 }
00399 }
00400 break;
00401
00402 case QEvent::MouseButtonDblClick:
00403 if (object == viewport()) {
00404 selectItem(0);
00405 int x,y;
00406 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
00407 int gx,gy;
00408 contentsToGrid(x,y,gx,gy);
00409 emit newEventSignal(gx,gy);
00410 } else {
00411 KOAgendaItem *doubleClickedItem = (KOAgendaItem *)object;
00412 selectItem(doubleClickedItem);
00413 emit editEventSignal(doubleClickedItem->itemEvent());
00414 }
00415 break;
00416
00417 default:
00418 break;
00419 }
00420
00421 return true;
00422 }
00423
00424 void KOAgenda::startSelectAction(QPoint viewportPos)
00425 {
00426 emit newStartSelectSignal();
00427
00428 mActionType = SELECT;
00429
00430 int x,y;
00431 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
00432 int gx,gy;
00433 contentsToGrid(x,y,gx,gy);
00434
00435 mStartCellX = gx;
00436 mStartCellY = gy;
00437 mCurrentCellX = gx;
00438 mCurrentCellY = gy;
00439
00440
00441 int selectionX = mSelectionCellX * mGridSpacingX;
00442 int selectionYTop = mSelectionYTop;
00443 int selectionHeight = mSelectionHeight;
00444
00445
00446 mSelectionCellX = gx;
00447 mSelectionYTop = gy * mGridSpacingY;
00448 mSelectionHeight = mGridSpacingY;
00449
00450
00451 repaintContents( selectionX, selectionYTop,
00452 mGridSpacingX, selectionHeight );
00453
00454
00455 repaintContents( mSelectionCellX * mGridSpacingX, mSelectionYTop,
00456 mGridSpacingX, mSelectionHeight );
00457 }
00458
00459 void KOAgenda::performSelectAction(QPoint viewportPos)
00460 {
00461 int x,y;
00462 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
00463 int gx,gy;
00464 contentsToGrid(x,y,gx,gy);
00465
00466 QPoint clipperPos = clipper()->
00467 mapFromGlobal(viewport()->mapToGlobal(viewportPos));
00468
00469
00470 if (clipperPos.y() < mScrollBorderWidth) {
00471 mScrollUpTimer.start(mScrollDelay);
00472 } else if (visibleHeight() - clipperPos.y() <
00473 mScrollBorderWidth) {
00474 mScrollDownTimer.start(mScrollDelay);
00475 } else {
00476 mScrollUpTimer.stop();
00477 mScrollDownTimer.stop();
00478 }
00479
00480 if ( gy > mCurrentCellY ) {
00481 mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop;
00482
00483 #if 0
00484
00485 repaintContents( mSelectionCellX * mGridSpacingX,
00486 mCurrentCellY + mGridSpacingY,
00487 mGridSpacingX,
00488 mSelectionHeight - ( gy - mCurrentCellY - 1 ) * mGridSpacingY );
00489 #else
00490 repaintContents( (QApplication::reverseLayout() ?
00491 mColumns - 1 - mSelectionCellX : mSelectionCellX) *
00492 mGridSpacingX, mSelectionYTop,
00493 mGridSpacingX, mSelectionHeight );
00494 #endif
00495
00496 mCurrentCellY = gy;
00497 } else if ( gy < mCurrentCellY ) {
00498 if ( gy >= mStartCellY ) {
00499 int selectionHeight = mSelectionHeight;
00500 mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop;
00501
00502 repaintContents( (QApplication::reverseLayout() ?
00503 mColumns - 1 - mSelectionCellX : mSelectionCellX) *
00504 mGridSpacingX, mSelectionYTop,
00505 mGridSpacingX, selectionHeight );
00506
00507 mCurrentCellY = gy;
00508 } else {
00509 }
00510 }
00511 }
00512
00513 void KOAgenda::endSelectAction()
00514 {
00515 mActionType = NOP;
00516 mScrollUpTimer.stop();
00517 mScrollDownTimer.stop();
00518
00519 emit newTimeSpanSignal(mStartCellX,mStartCellY,mCurrentCellX,mCurrentCellY);
00520 }
00521
00522 void KOAgenda::startItemAction(QPoint viewportPos)
00523 {
00524 int x,y;
00525 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
00526 int gx,gy;
00527 contentsToGrid(x,y,gx,gy);
00528
00529 mStartCellX = gx;
00530 mStartCellY = gy;
00531 mCurrentCellX = gx;
00532 mCurrentCellY = gy;
00533
00534 if (mAllDayMode) {
00535 int gridDistanceX = (x - gx * mGridSpacingX);
00536 if (gridDistanceX < mResizeBorderWidth &&
00537 mActionItem->cellX() == mCurrentCellX) {
00538 mActionType = RESIZELEFT;
00539 setCursor(sizeHorCursor);
00540 } else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
00541 mActionItem->cellXWidth() == mCurrentCellX) {
00542 mActionType = RESIZERIGHT;
00543 setCursor(sizeHorCursor);
00544 } else {
00545 mActionType = MOVE;
00546 mActionItem->startMove();
00547 setCursor(sizeAllCursor);
00548 }
00549 } else {
00550 int gridDistanceY = (y - gy * mGridSpacingY);
00551 if (gridDistanceY < mResizeBorderWidth &&
00552 mActionItem->cellYTop() == mCurrentCellY &&
00553 !mActionItem->firstMultiItem()) {
00554 mActionType = RESIZETOP;
00555 setCursor(sizeVerCursor);
00556 } else if ((mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
00557 mActionItem->cellYBottom() == mCurrentCellY &&
00558 !mActionItem->lastMultiItem()) {
00559 mActionType = RESIZEBOTTOM;
00560 setCursor(sizeVerCursor);
00561 } else {
00562 mActionType = MOVE;
00563 mActionItem->startMove();
00564 setCursor(sizeAllCursor);
00565 }
00566 }
00567 }
00568
00569 void KOAgenda::performItemAction(QPoint viewportPos)
00570 {
00571
00572
00573
00574
00575
00576
00577 int x,y;
00578 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
00579
00580 int gx,gy;
00581 contentsToGrid(x,y,gx,gy);
00582 QPoint clipperPos = clipper()->
00583 mapFromGlobal(viewport()->mapToGlobal(viewportPos));
00584
00585
00586
00587 if ( clipperPos.y() < 0 || clipperPos.y() > visibleHeight() ||
00588 clipperPos.x() < 0 || clipperPos.x() > visibleWidth() ) {
00589 if ( mActionType == MOVE ) {
00590 mScrollUpTimer.stop();
00591 mScrollDownTimer.stop();
00592 mActionItem->resetMove();
00593 placeSubCells( mActionItem );
00594 emit startDragSignal( mActionItem->itemEvent() );
00595 setCursor( arrowCursor );
00596 mActionItem = 0;
00597 mActionType = NOP;
00598 mItemMoved = 0;
00599 return;
00600 }
00601 } else {
00602 switch ( mActionType ) {
00603 case MOVE:
00604 setCursor( sizeAllCursor );
00605 break;
00606 case RESIZETOP:
00607 case RESIZEBOTTOM:
00608 setCursor( sizeVerCursor );
00609 break;
00610 case RESIZELEFT:
00611 case RESIZERIGHT:
00612 setCursor( sizeHorCursor );
00613 break;
00614 default:
00615 setCursor( arrowCursor );
00616 }
00617 }
00618
00619
00620 if (clipperPos.y() < mScrollBorderWidth) {
00621 mScrollUpTimer.start(mScrollDelay);
00622 } else if (visibleHeight() - clipperPos.y() <
00623 mScrollBorderWidth) {
00624 mScrollDownTimer.start(mScrollDelay);
00625 } else {
00626 mScrollUpTimer.stop();
00627 mScrollDownTimer.stop();
00628 }
00629
00630
00631 if (mCurrentCellX != gx || mCurrentCellY != gy) {
00632 mItemMoved = true;
00633 mActionItem->raise();
00634 if (mActionType == MOVE) {
00635
00636 KOAgendaItem *moveItem = mActionItem->firstMultiItem();
00637 bool isMultiItem = (moveItem || mActionItem->lastMultiItem());
00638 if (!moveItem) moveItem = mActionItem;
00639 while (moveItem) {
00640 int dy;
00641 if (isMultiItem) dy = 0;
00642 else dy = gy - mCurrentCellY;
00643 moveItem->moveRelative(gx - mCurrentCellX,dy);
00644 int x,y;
00645 gridToContents(moveItem->cellX(),moveItem->cellYTop(),x,y);
00646 moveItem->resize(mGridSpacingX * moveItem->cellWidth(),
00647 mGridSpacingY * moveItem->cellHeight());
00648 moveChild(moveItem,x,y);
00649 moveItem = moveItem->nextMultiItem();
00650 }
00651 } else if (mActionType == RESIZETOP) {
00652 if (mCurrentCellY <= mActionItem->cellYBottom()) {
00653 mActionItem->expandTop(gy - mCurrentCellY);
00654 mActionItem->resize(mActionItem->width(),
00655 mGridSpacingY * mActionItem->cellHeight());
00656 int x,y;
00657 gridToContents(mCurrentCellX,mActionItem->cellYTop(),x,y);
00658 moveChild(mActionItem,childX(mActionItem),y);
00659 }
00660 } else if (mActionType == RESIZEBOTTOM) {
00661 if (mCurrentCellY >= mActionItem->cellYTop()) {
00662 mActionItem->expandBottom(gy - mCurrentCellY);
00663 mActionItem->resize(mActionItem->width(),
00664 mGridSpacingY * mActionItem->cellHeight());
00665 }
00666 } else if (mActionType == RESIZELEFT) {
00667 if (mCurrentCellX <= mActionItem->cellXWidth()) {
00668 mActionItem->expandLeft(gx - mCurrentCellX);
00669 mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(),
00670 mActionItem->height());
00671 int x,y;
00672 gridToContents(mActionItem->cellX(),mActionItem->cellYTop(),x,y);
00673 moveChild(mActionItem,x,childY(mActionItem));
00674 }
00675 } else if (mActionType == RESIZERIGHT) {
00676 if (mCurrentCellX >= mActionItem->cellX()) {
00677 mActionItem->expandRight(gx - mCurrentCellX);
00678 mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(),
00679 mActionItem->height());
00680 }
00681 }
00682 mCurrentCellX = gx;
00683 mCurrentCellY = gy;
00684 }
00685 }
00686
00687 void KOAgenda::endItemAction()
00688 {
00689
00690
00691 if ( mItemMoved ) {
00692 KOAgendaItem *placeItem = mActionItem->firstMultiItem();
00693 if ( !placeItem ) {
00694 placeItem = mActionItem;
00695 }
00696 emit itemModified( placeItem );
00697 QPtrList<KOAgendaItem> oldconflictItems = placeItem->conflictItems();
00698 KOAgendaItem *item;
00699 for ( item=oldconflictItems.first(); item != 0;
00700 item=oldconflictItems.next() ) {
00701 placeSubCells(item);
00702 }
00703 while ( placeItem ) {
00704 placeSubCells( placeItem );
00705 placeItem = placeItem->nextMultiItem();
00706 }
00707 }
00708
00709 mScrollUpTimer.stop();
00710 mScrollDownTimer.stop();
00711 setCursor( arrowCursor );
00712 mActionItem = 0;
00713 mActionType = NOP;
00714 mItemMoved = 0;
00715
00716
00717 }
00718
00719 void KOAgenda::setNoActionCursor(KOAgendaItem *moveItem,QPoint viewportPos)
00720 {
00721
00722
00723
00724
00725
00726
00727 int x,y;
00728 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
00729
00730 int gx,gy;
00731 contentsToGrid(x,y,gx,gy);
00732
00733
00734 if (mAllDayMode) {
00735 int gridDistanceX = (x - gx * mGridSpacingX);
00736 if (gridDistanceX < mResizeBorderWidth &&
00737 moveItem->cellX() == gx) {
00738 setCursor(sizeHorCursor);
00739 } else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
00740 moveItem->cellXWidth() == gx) {
00741 setCursor(sizeHorCursor);
00742 } else {
00743 setCursor(arrowCursor);
00744 }
00745 } else {
00746 int gridDistanceY = (y - gy * mGridSpacingY);
00747 if (gridDistanceY < mResizeBorderWidth &&
00748 moveItem->cellYTop() == gy &&
00749 !moveItem->firstMultiItem()) {
00750 setCursor(sizeVerCursor);
00751 } else if ((mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
00752 moveItem->cellYBottom() == gy &&
00753 !moveItem->lastMultiItem()) {
00754 setCursor(sizeVerCursor);
00755 } else {
00756 setCursor(arrowCursor);
00757 }
00758 }
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 void KOAgenda::placeSubCells(KOAgendaItem *placeItem)
00773 {
00774 #if 0
00775 kdDebug() << "KOAgenda::placeSubCells()" << endl;
00776 if ( placeItem ) {
00777 Event *event = placeItem->itemEvent();
00778 if ( !event ) {
00779 kdDebug() << " event is 0" << endl;
00780 } else {
00781 kdDebug() << " event: " << event->summary() << endl;
00782 }
00783 } else {
00784 kdDebug() << " placeItem is 0" << endl;
00785 }
00786 kdDebug() << "KOAgenda::placeSubCells()..." << endl;
00787 #endif
00788
00789 QPtrList<KOAgendaItem> conflictItems;
00790 int maxSubCells = 0;
00791 QIntDict<KOAgendaItem> subCellDict(5);
00792
00793 KOAgendaItem *item;
00794 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
00795 if (item != placeItem) {
00796 if (placeItem->cellX() <= item->cellXWidth() &&
00797 placeItem->cellXWidth() >= item->cellX()) {
00798 if ((placeItem->cellYTop() <= item->cellYBottom()) &&
00799 (placeItem->cellYBottom() >= item->cellYTop())) {
00800 conflictItems.append(item);
00801 if (item->subCells() > maxSubCells)
00802 maxSubCells = item->subCells();
00803 subCellDict.insert(item->subCell(),item);
00804 }
00805 }
00806 }
00807 }
00808
00809 if (conflictItems.count() > 0) {
00810
00811 int i;
00812 for(i=0;i<maxSubCells;++i) {
00813 if (!subCellDict.find(i)) {
00814 placeItem->setSubCell(i);
00815 break;
00816 }
00817 }
00818 if (i == maxSubCells) {
00819 placeItem->setSubCell(maxSubCells);
00820 maxSubCells++;
00821 }
00822
00823
00824 int newSubCellWidth;
00825 if (mAllDayMode) newSubCellWidth = mGridSpacingY / maxSubCells;
00826 else newSubCellWidth = mGridSpacingX / maxSubCells;
00827 conflictItems.append(placeItem);
00828
00829
00830
00831
00832 for ( item=conflictItems.first(); item != 0;
00833 item=conflictItems.next() ) {
00834
00835 item->setSubCells(maxSubCells);
00836 if (mAllDayMode) {
00837 item->resize(item->cellWidth() * mGridSpacingX, newSubCellWidth);
00838 } else {
00839 item->resize(newSubCellWidth, item->cellHeight() * mGridSpacingY);
00840 }
00841 int x,y;
00842 gridToContents(item->cellX(),item->cellYTop(),x,y);
00843 if (mAllDayMode) {
00844 y += item->subCell() * newSubCellWidth;
00845 } else {
00846 x += item->subCell() * newSubCellWidth;
00847 }
00848 moveChild(item,x,y);
00849 }
00850 } else {
00851 placeItem->setSubCell(0);
00852 placeItem->setSubCells(1);
00853 if (mAllDayMode) placeItem->resize(placeItem->width(),mGridSpacingY);
00854 else placeItem->resize(mGridSpacingX,placeItem->height());
00855 int x,y;
00856 gridToContents(placeItem->cellX(),placeItem->cellYTop(),x,y);
00857 moveChild(placeItem,x,y);
00858 }
00859 placeItem->setConflictItems(conflictItems);
00860 }
00861
00862
00863
00864
00865 void KOAgenda::drawContents(QPainter* p, int cx, int cy, int cw, int ch)
00866 {
00867
00868 int lGridSpacingY = mGridSpacingY*2;
00869
00870
00871 if (mWorkingHoursEnable) {
00872 int x1 = cx;
00873 int y1 = mWorkingHoursYTop;
00874 if (y1 < cy) y1 = cy;
00875 int x2 = cx+cw-1;
00876
00877
00878 int y2 = mWorkingHoursYBottom;
00879 if (y2 > cy+ch-1) y2=cy+ch-1;
00880
00881 if (x2 >= x1 && y2 >= y1) {
00882 int gxStart = x1/mGridSpacingX;
00883 int gxEnd = x2/mGridSpacingX;
00884 while(gxStart <= gxEnd) {
00885 if (gxStart < int(mHolidayMask->count()) &&
00886 !mHolidayMask->at(gxStart)) {
00887 int xStart = QApplication::reverseLayout() ?
00888 (mColumns - 1 - gxStart)*mGridSpacingX :
00889 gxStart*mGridSpacingX;
00890 if (xStart < x1) xStart = x1;
00891 int xEnd = QApplication::reverseLayout() ?
00892 (mColumns - gxStart)*mGridSpacingX-1 :
00893 (gxStart+1)*mGridSpacingX-1;
00894 if (xEnd > x2) xEnd = x2;
00895 p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
00896 KOPrefs::instance()->mWorkingHoursColor);
00897 }
00898 ++gxStart;
00899 }
00900 }
00901 }
00902
00903 int selectionX = QApplication::reverseLayout() ?
00904 (mColumns - 1 - mSelectionCellX) * mGridSpacingX :
00905 mSelectionCellX * mGridSpacingX;
00906
00907
00908 if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
00909 ( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) {
00910
00911 p->fillRect( selectionX, mSelectionYTop, mGridSpacingX,
00912 mSelectionHeight, KOPrefs::instance()->mHighlightColor );
00913 }
00914
00915
00916
00917 int x = ((int)(cx/mGridSpacingX))*mGridSpacingX;
00918 while (x < cx + cw) {
00919 p->drawLine(x,cy,x,cy+ch);
00920 x+=mGridSpacingX;
00921 }
00922
00923
00924 int y = ((int)(cy/lGridSpacingY))*lGridSpacingY;
00925 while (y < cy + ch) {
00926
00927 p->drawLine(cx,y,cx+cw,y);
00928 y+=lGridSpacingY;
00929 }
00930 }
00931
00932
00933
00934
00935 void KOAgenda::contentsToGrid (int x, int y, int& gx, int& gy)
00936 {
00937 gx = QApplication::reverseLayout() ? mColumns - 1 - x/mGridSpacingX :
00938 x/mGridSpacingX;
00939 gy = y/mGridSpacingY;
00940 }
00941
00942
00943
00944
00945 void KOAgenda::gridToContents (int gx, int gy, int& x, int& y)
00946 {
00947 x = QApplication::reverseLayout() ? (mColumns - 1 - gx)*mGridSpacingX:
00948 gx*mGridSpacingX;
00949 y = gy*mGridSpacingY;
00950 }
00951
00952
00953
00954
00955
00956
00957 int KOAgenda::timeToY(const QTime &time)
00958 {
00959
00960 int minutesPerCell = 24 * 60 / mRows;
00961
00962 int timeMinutes = time.hour() * 60 + time.minute();
00963
00964 int Y = (timeMinutes + (minutesPerCell / 2)) / minutesPerCell;
00965
00966
00967 return Y;
00968 }
00969
00970
00971
00972
00973
00974
00975 QTime KOAgenda::gyToTime(int gy)
00976 {
00977
00978 int secondsPerCell = 24 * 60 * 60/ mRows;
00979
00980 int timeSeconds = secondsPerCell * gy;
00981
00982 QTime time( 0, 0, 0 );
00983 if ( timeSeconds < 24 * 60 * 60 ) {
00984 time = time.addSecs(timeSeconds);
00985 } else {
00986 time.setHMS( 23, 59, 59 );
00987 }
00988
00989
00990 return time;
00991 }
00992
00993 void KOAgenda::setStartHour(int startHour)
00994 {
00995 int startCell = startHour * mRows / 24;
00996 setContentsPos(0,startCell * gridSpacingY());
00997 }
00998
00999
01000
01001
01002
01003 KOAgendaItem *KOAgenda::insertItem (Event *event,QDate qd,int X,int YTop,int YBottom)
01004 {
01005
01006
01007 if (mAllDayMode) {
01008 kdDebug() << "KOAgenda: calling insertItem in all-day mode is illegal." << endl;
01009 return 0;
01010 }
01011
01012 KOAgendaItem *agendaItem = new KOAgendaItem (event,qd,viewport());
01013 agendaItem->setFrameStyle(WinPanel|Raised);
01014
01015 int YSize = YBottom - YTop + 1;
01016 if (YSize < 0) {
01017 kdDebug() << "KOAgenda::insertItem(): Text: " << agendaItem->text() << " YSize<0" << endl;
01018 YSize = 1;
01019 }
01020
01021 agendaItem->resize(mGridSpacingX,mGridSpacingY * YSize);
01022 agendaItem->setCellXY(X,YTop,YBottom);
01023 agendaItem->setCellXWidth(X);
01024
01025 agendaItem->installEventFilter(this);
01026
01027 addChild(agendaItem,X*mGridSpacingX,YTop*mGridSpacingY);
01028 mItems.append(agendaItem);
01029
01030 placeSubCells(agendaItem);
01031
01032 agendaItem->show();
01033
01034 marcus_bains();
01035
01036 return agendaItem;
01037 }
01038
01039
01040
01041
01042
01043 KOAgendaItem *KOAgenda::insertAllDayItem (Event *event,QDate qd,int XBegin,int XEnd)
01044 {
01045 if (!mAllDayMode) {
01046 kdDebug() << "KOAgenda: calling insertAllDayItem in non all-day mode is illegal." << endl;
01047 return 0;
01048 }
01049
01050 KOAgendaItem *agendaItem = new KOAgendaItem (event,qd,viewport());
01051 agendaItem->setFrameStyle(WinPanel|Raised);
01052
01053 agendaItem->setCellXY(XBegin,0,0);
01054 agendaItem->setCellXWidth(XEnd);
01055 agendaItem->resize(mGridSpacingX * agendaItem->cellWidth(),mGridSpacingY);
01056
01057 agendaItem->installEventFilter(this);
01058
01059 addChild(agendaItem,XBegin*mGridSpacingX,0);
01060 mItems.append(agendaItem);
01061
01062 placeSubCells(agendaItem);
01063
01064 agendaItem->show();
01065
01066 return agendaItem;
01067 }
01068
01069
01070 void KOAgenda::insertMultiItem (Event *event,QDate qd,int XBegin,int XEnd,
01071 int YTop,int YBottom)
01072 {
01073 if (mAllDayMode) {
01074 kdDebug() << "KOAgenda: calling insertMultiItem in all-day mode is illegal." << endl;
01075 return;
01076 }
01077
01078 int cellX,cellYTop,cellYBottom;
01079 QString newtext;
01080 int width = XEnd - XBegin + 1;
01081 int count = 0;
01082 KOAgendaItem *current = 0;
01083 QPtrList<KOAgendaItem> multiItems;
01084 for (cellX = XBegin;cellX <= XEnd;++cellX) {
01085 if (cellX == XBegin) cellYTop = YTop;
01086 else cellYTop = 0;
01087 if (cellX == XEnd) cellYBottom = YBottom;
01088 else cellYBottom = rows() - 1;
01089 newtext = QString("(%1/%2): ").arg(++count).arg(width);
01090 newtext.append(event->summary());
01091 current = insertItem(event,qd,cellX,cellYTop,cellYBottom);
01092 current->setText(newtext);
01093 multiItems.append(current);
01094 }
01095
01096 KOAgendaItem *next = 0;
01097 KOAgendaItem *last = multiItems.last();
01098 KOAgendaItem *first = multiItems.first();
01099 KOAgendaItem *setFirst,*setLast;
01100 current = first;
01101 while (current) {
01102 next = multiItems.next();
01103 if (current == first) setFirst = 0;
01104 else setFirst = first;
01105 if (current == last) setLast = 0;
01106 else setLast = last;
01107
01108 current->setMultiItem(setFirst,next,setLast);
01109 current = next;
01110 }
01111
01112 marcus_bains();
01113 }
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 void KOAgenda::resizeEvent ( QResizeEvent *ev )
01135 {
01136
01137 if (mAllDayMode) {
01138 mGridSpacingX = width() / mColumns;
01139
01140 mGridSpacingY = height() - 2 * frameWidth() - 1;
01141 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY + 1);
01142
01143
01144
01145 KOAgendaItem *item;
01146 int subCellWidth;
01147 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
01148 subCellWidth = mGridSpacingY / item->subCells();
01149 item->resize(mGridSpacingX * item->cellWidth(),subCellWidth);
01150 moveChild(item,QApplication::reverseLayout() ?
01151 (mColumns - 1 - item->cellX()) * mGridSpacingX :
01152 item->cellX() * mGridSpacingX,
01153 item->subCell() * subCellWidth);
01154 }
01155 } else {
01156 mGridSpacingX = (width() - verticalScrollBar()->width())/mColumns;
01157 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
01158
01159 KOAgendaItem *item;
01160 int subCellWidth;
01161 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
01162 subCellWidth = mGridSpacingX / item->subCells();
01163 item->resize(subCellWidth,item->height());
01164 moveChild(item,(QApplication::reverseLayout() ?
01165 (mColumns - 1 - item->cellX()) * mGridSpacingX :
01166 item->cellX() * mGridSpacingX) +
01167 item->subCell() * subCellWidth,childY(item));
01168 }
01169 }
01170
01171 checkScrollBoundaries();
01172
01173 marcus_bains();
01174
01175 viewport()->update();
01176 QScrollView::resizeEvent(ev);
01177 }
01178
01179
01180 void KOAgenda::scrollUp()
01181 {
01182 scrollBy(0,-mScrollOffset);
01183 }
01184
01185
01186 void KOAgenda::scrollDown()
01187 {
01188 scrollBy(0,mScrollOffset);
01189 }
01190
01191 void KOAgenda::popupAlarm()
01192 {
01193 if (!mClickedItem) {
01194 kdDebug() << "KOAgenda::itemPopup() called without having a clicked item" << endl;
01195 return;
01196 }
01197
01198 Alarm* alarm;
01199 QPtrList<Alarm> list(mClickedItem->itemEvent()->alarms());
01200 for(alarm=list.first();alarm;alarm=list.next())
01201 alarm->toggleAlarm();
01202
01203 mClickedItem->updateIcons();
01204 }
01205
01206
01207
01208
01209 int KOAgenda::minimumWidth() const
01210 {
01211
01212 int min = 100;
01213
01214 return min;
01215 }
01216
01217 void KOAgenda::updateConfig()
01218 {
01219 viewport()->setBackgroundColor(KOPrefs::instance()->mAgendaBgColor);
01220
01221 mGridSpacingY = KOPrefs::instance()->mHourSize;
01222
01223 calculateWorkingHours();
01224
01225 marcus_bains();
01226 }
01227
01228 void KOAgenda::checkScrollBoundaries()
01229 {
01230
01231 mOldLowerScrollValue = -1;
01232 mOldUpperScrollValue = -1;
01233
01234 checkScrollBoundaries(verticalScrollBar()->value());
01235 }
01236
01237 void KOAgenda::checkScrollBoundaries(int v)
01238 {
01239 int yMin = v/mGridSpacingY;
01240 int yMax = (v+visibleHeight())/mGridSpacingY;
01241
01242
01243
01244 if (yMin != mOldLowerScrollValue) {
01245 mOldLowerScrollValue = yMin;
01246 emit lowerYChanged(yMin);
01247 }
01248 if (yMax != mOldUpperScrollValue) {
01249 mOldUpperScrollValue = yMax;
01250 emit upperYChanged(yMax);
01251 }
01252 }
01253
01254 void KOAgenda::deselectItem()
01255 {
01256 if (mSelectedItem == 0) return;
01257 mSelectedItem->select(false);
01258 mSelectedItem = 0;
01259 }
01260
01261 void KOAgenda::selectItem(KOAgendaItem *item)
01262 {
01263 if (mSelectedItem == item) return;
01264 deselectItem();
01265 if (item == 0) {
01266 emit incidenceSelected( 0 );
01267 return;
01268 }
01269 mSelectedItem = item;
01270 mSelectedItem->select();
01271 emit incidenceSelected( mSelectedItem->itemEvent() );
01272 }
01273
01274
01275 void KOAgenda::keyPressEvent( QKeyEvent *kev )
01276 {
01277 switch(kev->key()) {
01278 case Key_PageDown:
01279 verticalScrollBar()->addPage();
01280 break;
01281 case Key_PageUp:
01282 verticalScrollBar()->subtractPage();
01283 break;
01284 case Key_Down:
01285 verticalScrollBar()->addLine();
01286 break;
01287 case Key_Up:
01288 verticalScrollBar()->subtractLine();
01289 break;
01290 default:
01291 ;
01292 }
01293 }
01294
01295 void KOAgenda::calculateWorkingHours()
01296 {
01297
01298 mWorkingHoursEnable = !mAllDayMode;
01299
01300 mWorkingHoursYTop = mGridSpacingY *
01301 KOPrefs::instance()->mWorkingHoursStart * 4;
01302 mWorkingHoursYBottom = mGridSpacingY *
01303 KOPrefs::instance()->mWorkingHoursEnd * 4 - 1;
01304 }
01305
01306
01307 DateList KOAgenda::dateList() const
01308 {
01309 return mSelectedDates;
01310 }
01311
01312 void KOAgenda::setDateList(const DateList &selectedDates)
01313 {
01314 mSelectedDates = selectedDates;
01315 marcus_bains();
01316 }
01317
01318 void KOAgenda::setHolidayMask(QMemArray<bool> *mask)
01319 {
01320 mHolidayMask = mask;
01321
01322
01323
01324
01325
01326
01327
01328
01329 }
01330
01331 void KOAgenda::contentsMousePressEvent ( QMouseEvent *event )
01332 {
01333 kdDebug() << "KOagenda::contentsMousePressEvent(): type: " << event->type() << endl;
01334 QScrollView::contentsMousePressEvent(event);
01335 }