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
#include <qlabel.h>
00034
00035
#include <kdebug.h>
00036
#include <klocale.h>
00037
#include <kiconloader.h>
00038
#include <kglobal.h>
00039
#include <kmessagebox.h>
00040
00041
#include "koagendaitem.h"
00042
#include "koprefs.h"
00043
#include "koglobals.h"
00044
00045
#include "koagenda.h"
00046
#include "koagenda.moc"
00047
00048
#include <libkcal/event.h>
00049
#include <libkcal/todo.h>
00050
#include <libkcal/dndfactory.h>
00051
#include <libkcal/icaldrag.h>
00052
#include <libkcal/vcaldrag.h>
00053
#include <libkcal/calendar.h>
00054
00056 MarcusBains::MarcusBains(KOAgenda *_agenda,
const char *name)
00057 :
QFrame(_agenda->viewport(),name), agenda(_agenda)
00058 {
00059 setLineWidth(0);
00060 setMargin(0);
00061 setBackgroundColor(Qt::red);
00062 minutes =
new QTimer(
this);
00063 connect(minutes, SIGNAL(timeout()),
this, SLOT(updateLocation()));
00064 minutes->start(0,
true);
00065
00066 mTimeBox =
new QLabel(
this);
00067 mTimeBox->setAlignment(Qt::AlignRight | Qt::AlignBottom);
00068
QPalette pal = mTimeBox->palette();
00069 pal.setColor(QColorGroup::Foreground, Qt::red);
00070 mTimeBox->setPalette(pal);
00071 mTimeBox->setAutoMask(
true);
00072
00073 agenda->addChild(mTimeBox);
00074
00075 oldToday = -1;
00076 }
00077
00078 MarcusBains::~MarcusBains()
00079 {
00080
delete minutes;
00081 }
00082
00083
int MarcusBains::todayColumn()
00084 {
00085
QDate currentDate = QDate::currentDate();
00086
00087 DateList dateList = agenda->dateList();
00088 DateList::ConstIterator it;
00089
int col = 0;
00090
for(it = dateList.begin(); it != dateList.end(); ++it) {
00091
if((*it) == currentDate)
00092
return KOGlobals::self()->reverseLayout() ?
00093 agenda->columns() - 1 - col : col;
00094 ++col;
00095 }
00096
00097
return -1;
00098 }
00099
00100
void MarcusBains::updateLocation(
bool recalculate)
00101 {
00102
QTime tim = QTime::currentTime();
00103
if((tim.hour() == 0) && (oldTime.hour()==23))
00104 recalculate =
true;
00105
00106
int mins = tim.hour()*60 + tim.minute();
00107
int minutesPerCell = 24 * 60 / agenda->rows();
00108
int y = int( mins * agenda->gridSpacingY() / minutesPerCell );
00109
int today = recalculate ? todayColumn() : oldToday;
00110
int x = int( agenda->gridSpacingX() * today );
00111
bool disabled = !(KOPrefs::instance()->mMarcusBainsEnabled);
00112
00113 oldTime = tim;
00114 oldToday = today;
00115
00116
if(disabled || (today<0)) {
00117 hide();
00118 mTimeBox->hide();
00119
return;
00120 }
else {
00121 show();
00122 mTimeBox->show();
00123 }
00124
00125
if ( recalculate ) setFixedSize(
int( agenda->gridSpacingX() ), 1 );
00126 agenda->moveChild(
this, x, y );
00127 raise();
00128
00129
if(recalculate)
00130 mTimeBox->setFont(KOPrefs::instance()->mMarcusBainsFont);
00131
00132 mTimeBox->setText(KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds));
00133 mTimeBox->adjustSize();
00134
if (y-mTimeBox->height()>=0) y-=mTimeBox->height();
else y++;
00135
if (x-mTimeBox->width()+agenda->gridSpacingX() > 0)
00136 x += int( agenda->gridSpacingX() - mTimeBox->width() - 1 );
00137
else x++;
00138 agenda->moveChild(mTimeBox,x,y);
00139 mTimeBox->raise();
00140 mTimeBox->setAutoMask(
true);
00141
00142 minutes->start(1000,
true);
00143 }
00144
00145
00147
00148
00149
00150
00151
00152 KOAgenda::KOAgenda(
int columns,
int rows,
int rowSize,
QWidget *parent,
00153
const char *name, WFlags f )
00154 :
QScrollView( parent, name, f )
00155 {
00156 mColumns = columns;
00157 mRows = rows;
00158 mGridSpacingY = rowSize;
00159 mAllDayMode =
false;
00160
00161 init();
00162 }
00163
00164
00165
00166
00167
00168 KOAgenda::KOAgenda(
int columns,
QWidget *parent,
const char *name, WFlags f )
00169 :
QScrollView( parent, name, f )
00170 {
00171 mColumns = columns;
00172 mRows = 1;
00173 mGridSpacingY = 24;
00174 mAllDayMode =
true;
00175
00176 init();
00177 }
00178
00179
00180 KOAgenda::~KOAgenda()
00181 {
00182
delete mMarcusBains;
00183 }
00184
00185
00186 Incidence *KOAgenda::selectedIncidence()
const
00187
{
00188
return ( mSelectedItem ? mSelectedItem->incidence() : 0 );
00189 }
00190
00191
00192
QDate KOAgenda::selectedIncidenceDate()
const
00193
{
00194
return ( mSelectedItem ? mSelectedItem->itemDate() :
QDate() );
00195 }
00196
00197
00198
void KOAgenda::init()
00199 {
00200 mGridSpacingX = 100;
00201
00202 mResizeBorderWidth = 8;
00203 mScrollBorderWidth = 8;
00204 mScrollDelay = 30;
00205 mScrollOffset = 10;
00206
00207 enableClipper(
true );
00208
00209
00210
00211 setFocusPolicy( WheelFocus );
00212
00213 connect( &mScrollUpTimer, SIGNAL( timeout() ), SLOT( scrollUp() ) );
00214 connect( &mScrollDownTimer, SIGNAL( timeout() ), SLOT( scrollDown() ) );
00215
00216 mStartCell =
QPoint( 0, 0 );
00217 mEndCell = QPoint( 0, 0 );
00218
00219 mHasSelection =
false;
00220 mSelectionStartPoint = QPoint( 0, 0 );
00221 mSelectionStartCell = QPoint( 0, 0 );
00222 mSelectionEndCell = QPoint( 0, 0 );
00223
00224 mOldLowerScrollValue = -1;
00225 mOldUpperScrollValue = -1;
00226
00227 mClickedItem = 0;
00228
00229 mActionItem = 0;
00230 mActionType = NOP;
00231 mItemMoved =
false;
00232
00233 mSelectedItem = 0;
00234
00235 setAcceptDrops(
true );
00236 installEventFilter(
this );
00237 mItems.setAutoDelete(
true );
00238 mItemsToDelete.setAutoDelete(
true );
00239
00240
00241 resizeContents(
int( mGridSpacingX * mColumns ),
00242
int( mGridSpacingY * mRows ) );
00243
00244 viewport()->update();
00245 viewport()->setBackgroundMode( NoBackground );
00246 viewport()->setFocusPolicy( WheelFocus );
00247
00248 setMinimumSize( 30,
int( mGridSpacingY + 1 ) );
00249
00250
00251
00252
00253
00254 setHScrollBarMode( AlwaysOff );
00255
00256 setStartTime( KOPrefs::instance()->mDayBegins.time() );
00257
00258 calculateWorkingHours();
00259
00260 connect( verticalScrollBar(), SIGNAL( valueChanged(
int ) ),
00261 SLOT( checkScrollBoundaries(
int ) ) );
00262
00263
00264
if( mAllDayMode ) {
00265 mMarcusBains = 0;
00266 }
else {
00267 mMarcusBains =
new MarcusBains(
this );
00268 addChild( mMarcusBains );
00269 }
00270
00271 mTypeAhead =
false;
00272 mTypeAheadReceiver = 0;
00273
00274 mReturnPressed =
false;
00275 }
00276
00277
00278
void KOAgenda::clear()
00279 {
00280
00281
00282 KOAgendaItem *item;
00283
for ( item = mItems.first(); item != 0; item = mItems.next() ) {
00284 removeChild( item );
00285 }
00286 mItems.clear();
00287 mItemsToDelete.clear();
00288
00289 mSelectedItem = 0;
00290
00291 clearSelection();
00292 }
00293
00294
00295
void KOAgenda::clearSelection()
00296 {
00297 mHasSelection =
false;
00298 mActionType = NOP;
00299 updateContents();
00300 }
00301
00302
void KOAgenda::marcus_bains()
00303 {
00304
if(mMarcusBains) mMarcusBains->updateLocation(
true);
00305 }
00306
00307
00308
void KOAgenda::changeColumns(
int columns)
00309 {
00310
if (columns == 0) {
00311 kdDebug(5850) <<
"KOAgenda::changeColumns() called with argument 0" << endl;
00312
return;
00313 }
00314
00315 clear();
00316 mColumns = columns;
00317
00318
00319
00320
00321
QResizeEvent event( size(), size() );
00322
00323 QApplication::sendEvent(
this, &event );
00324 }
00325
00326
00327
00328
00329
00330
bool KOAgenda::eventFilter (
QObject *object,
QEvent *event )
00331 {
00332
00333
00334
switch( event->type() ) {
00335
case QEvent::MouseButtonPress:
00336
case QEvent::MouseButtonDblClick:
00337
case QEvent::MouseButtonRelease:
00338
case QEvent::MouseMove:
00339
return eventFilter_mouse( object, static_cast<QMouseEvent *>( event ) );
00340
00341
case QEvent::KeyPress:
00342
case QEvent::KeyRelease:
00343
return eventFilter_key( object, static_cast<QKeyEvent *>( event ) );
00344
00345
case ( QEvent::Leave ):
00346
if ( !mActionItem )
00347 setCursor( arrowCursor );
00348
return true;
00349
00350
#ifndef KORG_NODND
00351
case QEvent::DragEnter:
00352
case QEvent::DragMove:
00353
case QEvent::DragLeave:
00354
case QEvent::Drop:
00355
00356
return eventFilter_drag(object, static_cast<QDropEvent*>(event));
00357
#endif
00358
00359
default:
00360
return QScrollView::eventFilter( object, event );
00361 }
00362 }
00363
00364
bool KOAgenda::eventFilter_drag(
QObject *object,
QDropEvent *de )
00365 {
00366
#ifndef KORG_NODND
00367
QPoint viewportPos;
00368
if ( object != viewport() && object !=
this ) {
00369 viewportPos = static_cast<QWidget *>( object )->mapToParent( de->pos() );
00370 }
else {
00371 viewportPos = de->pos();
00372 }
00373
00374
switch ( de->type() ) {
00375
case QEvent::DragEnter:
00376
case QEvent::DragMove:
00377
if ( ICalDrag::canDecode( de ) || VCalDrag::canDecode( de ) ) {
00378
00379 DndFactory factory( mCalendar );
00380 Todo *todo = factory.createDropTodo( de );
00381
if ( todo ) {
00382 de->accept();
00383
delete todo;
00384 }
else {
00385 de->ignore();
00386 }
00387
return true;
00388 }
else return false;
00389
break;
00390
case QEvent::DragLeave:
00391
return false;
00392
break;
00393
case QEvent::Drop:
00394 {
00395
if ( !ICalDrag::canDecode( de ) && !VCalDrag::canDecode( de ) ) {
00396
return false;
00397 }
00398
00399 DndFactory factory( mCalendar );
00400 Todo *todo = factory.createDropTodo( de );
00401
00402
if ( todo ) {
00403 de->acceptAction();
00404 QPoint pos;
00405
00406
00407
00408
if ( object ==
this ) {
00409 pos = viewportPos + QPoint( contentsX(), contentsY() );
00410 }
else {
00411 pos = viewportToContents( viewportPos );
00412 }
00413 QPoint gpos = contentsToGrid( pos );
00414 emit droppedToDo( todo, gpos, mAllDayMode );
00415
return true;
00416 }
00417 }
00418
break;
00419
00420
case QEvent::DragResponse:
00421
default:
00422
break;
00423 }
00424
#endif
00425
00426
return false;
00427 }
00428
00429
bool KOAgenda::eventFilter_key(
QObject *,
QKeyEvent *ke )
00430 {
00431
00432
00433
00434
if ( ke->key() == Key_Return ) {
00435
if ( ke->type() == QEvent::KeyPress ) mReturnPressed =
true;
00436
else if ( ke->type() == QEvent::KeyRelease ) {
00437
if ( mReturnPressed ) {
00438 emitNewEventForSelection();
00439 mReturnPressed =
false;
00440
return true;
00441 }
else {
00442 mReturnPressed =
false;
00443 }
00444 }
00445 }
00446
00447
00448
if ( ke->text().isEmpty() )
return false;
00449
00450
if ( ke->type() == QEvent::KeyPress || ke->type() == QEvent::KeyRelease ) {
00451
switch ( ke->key() ) {
00452
case Key_Escape:
00453
case Key_Return:
00454
case Key_Enter:
00455
case Key_Tab:
00456
case Key_Backtab:
00457
case Key_Left:
00458
case Key_Right:
00459
case Key_Up:
00460
case Key_Down:
00461
case Key_Backspace:
00462
case Key_Delete:
00463
case Key_Prior:
00464
case Key_Next:
00465
case Key_Home:
00466
case Key_End:
00467
case Key_Control:
00468
case Key_Meta:
00469
case Key_Alt:
00470
break;
00471
default:
00472 mTypeAheadEvents.append(
new QKeyEvent( ke->type(), ke->key(),
00473 ke->ascii(), ke->state(),
00474 ke->text(), ke->isAutoRepeat(),
00475 ke->count() ) );
00476
if ( !mTypeAhead ) {
00477 mTypeAhead =
true;
00478 emitNewEventForSelection();
00479 }
00480
return true;
00481 }
00482 }
00483
return false;
00484 }
00485
00486
void KOAgenda::emitNewEventForSelection()
00487 {
00488 emit newEventSignal();
00489 }
00490
00491
void KOAgenda::finishTypeAhead()
00492 {
00493
00494
if ( typeAheadReceiver() ) {
00495
for(
QEvent *e = mTypeAheadEvents.first(); e;
00496 e = mTypeAheadEvents.next() ) {
00497
00498 QApplication::sendEvent( typeAheadReceiver(), e );
00499 }
00500 }
00501 mTypeAheadEvents.clear();
00502 mTypeAhead =
false;
00503 }
00504
00505
bool KOAgenda::eventFilter_mouse(
QObject *object,
QMouseEvent *me)
00506 {
00507 QPoint viewportPos;
00508
if (object != viewport()) {
00509 viewportPos = ((
QWidget *)object)->mapToParent(me->pos());
00510 }
else {
00511 viewportPos = me->pos();
00512 }
00513
00514
switch (me->type()) {
00515
case QEvent::MouseButtonPress:
00516
00517
if (object != viewport()) {
00518
if (me->button() == RightButton) {
00519 mClickedItem = dynamic_cast<KOAgendaItem *>(object);
00520
if (mClickedItem) {
00521 selectItem(mClickedItem);
00522 emit showIncidencePopupSignal( mClickedItem->incidence(),
00523 mClickedItem->itemDate() );
00524 }
00525 }
else {
00526 mActionItem = dynamic_cast<KOAgendaItem *>(object);
00527
if (mActionItem) {
00528 selectItem(mActionItem);
00529 Incidence *incidence = mActionItem->incidence();
00530
00531
if ( incidence->isReadOnly() ) {
00532 mActionItem = 0;
00533 }
else {
00534 startItemAction(viewportPos);
00535 }
00536 }
00537 }
00538 }
else {
00539
if (me->button() == RightButton)
00540 {
00541
00542 QPoint gpos = contentsToGrid( viewportToContents( viewportPos ) );
00543
if ( !ptInSelection( gpos ) ) {
00544 mSelectionStartCell = gpos;
00545 mSelectionEndCell = gpos;
00546 mHasSelection =
true;
00547 emit newStartSelectSignal();
00548 emit newTimeSpanSignal( mSelectionStartCell, mSelectionEndCell );
00549 updateContents();
00550 }
00551 showNewEventPopupSignal();
00552 }
00553
else
00554 {
00555
00556 QPoint gpos = contentsToGrid( viewportToContents( viewportPos ) );
00557
if ( !ptInSelection( gpos ) ) {
00558 selectItem(0);
00559 mActionItem = 0;
00560 setCursor(arrowCursor);
00561 startSelectAction(viewportPos);
00562 }
00563 }
00564 }
00565
break;
00566
00567
case QEvent::MouseButtonRelease:
00568
if (mActionItem) {
00569 endItemAction();
00570 }
else if ( mActionType == SELECT ) {
00571 endSelectAction( viewportPos );
00572 }
00573
break;
00574
00575
case QEvent::MouseMove:
00576
if (object != viewport()) {
00577 KOAgendaItem *moveItem = dynamic_cast<KOAgendaItem *>(object);
00578
00579
00580
if (moveItem && !moveItem->incidence()->isReadOnly() )
00581
if (!mActionItem)
00582 setNoActionCursor(moveItem,viewportPos);
00583
else
00584 performItemAction(viewportPos);
00585 }
else {
00586
if ( mActionType == SELECT ) {
00587 performSelectAction( viewportPos );
00588 }
00589 }
00590
break;
00591
00592
case QEvent::MouseButtonDblClick:
00593
if (object == viewport()) {
00594 selectItem(0);
00595 QPoint pos = viewportToContents( viewportPos );
00596 QPoint gpos = contentsToGrid( pos );
00597 emit newEventSignal( gpos );
00598 }
else {
00599 KOAgendaItem *doubleClickedItem = dynamic_cast<KOAgendaItem *>(object);
00600
if (doubleClickedItem) {
00601 selectItem(doubleClickedItem);
00602 emit editIncidenceSignal(doubleClickedItem->incidence());
00603 }
00604 }
00605
break;
00606
00607
default:
00608
break;
00609 }
00610
00611
return true;
00612 }
00613
00614
bool KOAgenda::ptInSelection( QPoint gpos )
const
00615
{
00616
if ( !mHasSelection ) {
00617
return false;
00618 }
else if ( gpos.x()<mSelectionStartCell.x() || gpos.x()>mSelectionEndCell.x() ) {
00619
return false;
00620 }
else if ( (gpos.x()==mSelectionStartCell.x()) && (gpos.y()<mSelectionStartCell.y()) ) {
00621
return false;
00622 }
else if ( (gpos.x()==mSelectionEndCell.x()) && (gpos.y()>mSelectionEndCell.y()) ) {
00623
return false;
00624 }
00625
return true;
00626 }
00627
00628
void KOAgenda::startSelectAction(
const QPoint &viewportPos )
00629 {
00630 emit newStartSelectSignal();
00631
00632 mActionType = SELECT;
00633 mSelectionStartPoint = viewportPos;
00634 mHasSelection =
true;
00635
00636 QPoint pos = viewportToContents( viewportPos );
00637 QPoint gpos = contentsToGrid( pos );
00638
00639
00640 mStartCell = gpos;
00641 mEndCell = gpos;
00642 mSelectionStartCell = gpos;
00643 mSelectionEndCell = gpos;
00644
00645 updateContents();
00646 }
00647
00648
void KOAgenda::performSelectAction(
const QPoint& viewportPos)
00649 {
00650 QPoint pos = viewportToContents( viewportPos );
00651 QPoint gpos = contentsToGrid( pos );
00652
00653 QPoint clipperPos = clipper()->
00654 mapFromGlobal(viewport()->mapToGlobal(viewportPos));
00655
00656
00657
if (clipperPos.y() < mScrollBorderWidth) {
00658 mScrollUpTimer.start(mScrollDelay);
00659 }
else if (visibleHeight() - clipperPos.y() <
00660 mScrollBorderWidth) {
00661 mScrollDownTimer.start(mScrollDelay);
00662 }
else {
00663 mScrollUpTimer.stop();
00664 mScrollDownTimer.stop();
00665 }
00666
00667
if ( gpos != mEndCell ) {
00668 mEndCell = gpos;
00669
if ( mStartCell.x()>mEndCell.x() ||
00670 ( mStartCell.x()==mEndCell.x() && mStartCell.y()>mEndCell.y() ) ) {
00671
00672 mSelectionStartCell = mEndCell;
00673 mSelectionEndCell = mStartCell;
00674 }
else {
00675 mSelectionStartCell = mStartCell;
00676 mSelectionEndCell = mEndCell;
00677 }
00678
00679 updateContents();
00680 }
00681 }
00682
00683
void KOAgenda::endSelectAction(
const QPoint ¤tPos )
00684 {
00685 mScrollUpTimer.stop();
00686 mScrollDownTimer.stop();
00687
00688 emit newTimeSpanSignal( mSelectionStartCell, mSelectionEndCell );
00689
00690
if ( KOPrefs::instance()->mSelectionStartsEditor ) {
00691
if ( ( mSelectionStartPoint - currentPos ).manhattanLength() >
00692 QApplication::startDragDistance() ) {
00693 emitNewEventForSelection();
00694 }
00695 }
00696 }
00697
00698 KOAgenda::MouseActionType KOAgenda::isInResizeArea(
bool horizontal,
00699
const QPoint &pos, KOAgendaItem*item )
00700 {
00701
if (!item)
return NOP;
00702 QPoint gridpos = contentsToGrid( pos );
00703 QPoint contpos = gridToContents( gridpos +
00704 QPoint( (KOGlobals::self()->reverseLayout())?1:0, 0 ) );
00705
00706
00707
00708
00709
if ( horizontal ) {
00710
int clXLeft = item->cellXLeft();
00711
int clXRight = item->cellXRight();
00712
if ( KOGlobals::self()->reverseLayout() ) {
00713
int tmp = clXLeft;
00714 clXLeft = clXRight;
00715 clXRight = tmp;
00716 }
00717
int gridDistanceX = int( pos.x() - contpos.x() );
00718
if (gridDistanceX < mResizeBorderWidth && clXLeft == gridpos.x() ) {
00719
if ( KOGlobals::self()->reverseLayout() )
return RESIZERIGHT;
00720
else return RESIZELEFT;
00721 }
else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
00722 clXRight == gridpos.x() ) {
00723
if ( KOGlobals::self()->reverseLayout() )
return RESIZELEFT;
00724
else return RESIZERIGHT;
00725 }
else {
00726
return MOVE;
00727 }
00728 }
else {
00729
int gridDistanceY = int( pos.y() - contpos.y() );
00730
if (gridDistanceY < mResizeBorderWidth &&
00731 item->cellYTop() == gridpos.y() &&
00732 !item->firstMultiItem() ) {
00733
return RESIZETOP;
00734 }
else if ((mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
00735 item->cellYBottom() == gridpos.y() &&
00736 !item->lastMultiItem() ) {
00737
return RESIZEBOTTOM;
00738 }
else {
00739
return MOVE;
00740 }
00741 }
00742 }
00743
00744
void KOAgenda::startItemAction(
const QPoint& viewportPos)
00745 {
00746 QPoint pos = viewportToContents( viewportPos );
00747 mStartCell = contentsToGrid( pos );
00748 mEndCell = mStartCell;
00749
00750
bool noResize = ( mActionItem->incidence()->type() ==
"Todo");
00751
00752 mActionType = MOVE;
00753
if ( !noResize ) {
00754 mActionType = isInResizeArea( mAllDayMode, pos, mActionItem );
00755 }
00756
00757 mActionItem->startMove();
00758 setActionCursor( mActionType,
true );
00759 }
00760
00761
void KOAgenda::performItemAction(
const QPoint& viewportPos)
00762 {
00763
00764
00765
00766
00767
00768
00769 QPoint pos = viewportToContents( viewportPos );
00770
00771 QPoint gpos = contentsToGrid( pos );
00772 QPoint clipperPos = clipper()->
00773 mapFromGlobal(viewport()->mapToGlobal(viewportPos));
00774
00775
00776
00777
if ( clipperPos.y() < 0 || clipperPos.y() > visibleHeight() ||
00778 clipperPos.x() < 0 || clipperPos.x() > visibleWidth() ) {
00779
if ( mActionType == MOVE ) {
00780 mScrollUpTimer.stop();
00781 mScrollDownTimer.stop();
00782 mActionItem->resetMove();
00783 placeSubCells( mActionItem );
00784 emit startDragSignal( mActionItem->incidence() );
00785 setCursor( arrowCursor );
00786 mActionItem = 0;
00787 mActionType = NOP;
00788 mItemMoved =
false;
00789
return;
00790 }
00791 }
else {
00792 setActionCursor( mActionType );
00793 }
00794
00795
00796
if (clipperPos.y() < mScrollBorderWidth) {
00797 mScrollUpTimer.start(mScrollDelay);
00798 }
else if (visibleHeight() - clipperPos.y() <
00799 mScrollBorderWidth) {
00800 mScrollDownTimer.start(mScrollDelay);
00801 }
else {
00802 mScrollUpTimer.stop();
00803 mScrollDownTimer.stop();
00804 }
00805
00806
00807
if ( mEndCell != gpos ) {
00808 mItemMoved =
true;
00809 mActionItem->raise();
00810
if (mActionType == MOVE) {
00811
00812 KOAgendaItem *firstItem = mActionItem->firstMultiItem();
00813
if (!firstItem) firstItem = mActionItem;
00814 KOAgendaItem *lastItem = mActionItem->lastMultiItem();
00815
if (!lastItem) lastItem = mActionItem;
00816 QPoint deltapos = gpos - mEndCell;
00817 KOAgendaItem *moveItem = firstItem;
00818
while (moveItem) {
00819
bool changed=
false;
00820
if ( deltapos.x()!=0 ) {
00821 moveItem->moveRelative( deltapos.x(), 0 );
00822 changed=
true;
00823 }
00824
00825
if ( moveItem==firstItem && !mAllDayMode ) {
00826
int newY = deltapos.y() + moveItem->cellYTop();
00827
00828
if ( newY<0 ) {
00829 moveItem->expandTop( -moveItem->cellYTop() );
00830
00831 KOAgendaItem *newFirst = firstItem->prevMoveItem();
00832
00833
if (newFirst) {
00834 newFirst->setCellXY(moveItem->cellXLeft()-1, rows()+newY, rows()-1);
00835 mItems.append( newFirst );
00836 moveItem->resize(
int( mGridSpacingX * newFirst->cellWidth() ),
00837 int( mGridSpacingY * newFirst->cellHeight() ));
00838 QPoint cpos = gridToContents( QPoint( newFirst->cellXLeft(), newFirst->cellYTop() ) );
00839 addChild( newFirst, cpos.x(), cpos.y() );
00840 }
else {
00841 newFirst = insertItem( moveItem->incidence(), moveItem->itemDate(),
00842 moveItem->cellXLeft()-1, rows()+newY, rows()-1 ) ;
00843 }
00844
if (newFirst) newFirst->show();
00845 moveItem->prependMoveItem(newFirst);
00846 firstItem=newFirst;
00847 }
else if ( newY>=rows() ) {
00848
00849
00850 firstItem = moveItem->nextMultiItem();
00851 moveItem->hide();
00852 mItems.take( mItems.find( moveItem ) );
00853 removeChild( moveItem );
00854 mActionItem->removeMoveItem(moveItem);
00855 moveItem=firstItem;
00856
00857
if (moveItem) moveItem->expandTop( rows()-newY );
00858 }
else {
00859 moveItem->expandTop(deltapos.y());
00860 }
00861 changed=
true;
00862 }
00863
if ( !moveItem->lastMultiItem() && !mAllDayMode ) {
00864
int newY = deltapos.y()+moveItem->cellYBottom();
00865
if (newY<0) {
00866
00867 lastItem = moveItem->prevMultiItem();
00868 moveItem->hide();
00869 mItems.take( mItems.find(moveItem) );
00870 removeChild( moveItem );
00871 moveItem->removeMoveItem( moveItem );
00872 moveItem = lastItem;
00873 moveItem->expandBottom(newY+1);
00874 }
else if (newY>=rows()) {
00875 moveItem->expandBottom( rows()-moveItem->cellYBottom()-1 );
00876
00877 KOAgendaItem *newLast = lastItem->nextMoveItem();
00878
if (newLast) {
00879 newLast->setCellXY( moveItem->cellXLeft()+1, 0, newY-rows()-1 );
00880 mItems.append(newLast);
00881 moveItem->resize(
int( mGridSpacingX * newLast->cellWidth() ),
00882 int( mGridSpacingY * newLast->cellHeight() ));
00883 QPoint cpos = gridToContents( QPoint( newLast->cellXLeft(), newLast->cellYTop() ) ) ;
00884 addChild( newLast, cpos.x(), cpos.y() );
00885 }
else {
00886 newLast = insertItem( moveItem->incidence(), moveItem->itemDate(),
00887 moveItem->cellXLeft()+1, 0, newY-rows()-1 ) ;
00888 }
00889 moveItem->appendMoveItem( newLast );
00890 newLast->show();
00891 lastItem = newLast;
00892 }
else {
00893 moveItem->expandBottom( deltapos.y() );
00894 }
00895 changed=
true;
00896 }
00897
if (changed) {
00898 adjustItemPosition( moveItem );
00899 }
00900 moveItem = moveItem->nextMultiItem();
00901 }
00902 }
else if (mActionType == RESIZETOP) {
00903
if (mEndCell.y() <= mActionItem->cellYBottom()) {
00904 mActionItem->expandTop(gpos.y() - mEndCell.y());
00905 adjustItemPosition( mActionItem );
00906 }
00907 }
else if (mActionType == RESIZEBOTTOM) {
00908
if (mEndCell.y() >= mActionItem->cellYTop()) {
00909 mActionItem->expandBottom(gpos.y() - mEndCell.y());
00910 adjustItemPosition( mActionItem );
00911 }
00912 }
else if (mActionType == RESIZELEFT) {
00913
if (mEndCell.x() <= mActionItem->cellXRight()) {
00914 mActionItem->expandLeft( gpos.x() - mEndCell.x() );
00915 adjustItemPosition( mActionItem );
00916 }
00917 }
else if (mActionType == RESIZERIGHT) {
00918
if (mEndCell.x() >= mActionItem->cellXLeft()) {
00919 mActionItem->expandRight(gpos.x() - mEndCell.x());
00920 adjustItemPosition( mActionItem );
00921 }
00922 }
00923 mEndCell = gpos;
00924 }
00925 }
00926
00927
void KOAgenda::endItemAction()
00928 {
00929
00930 mScrollUpTimer.stop();
00931 mScrollDownTimer.stop();
00932 setCursor( arrowCursor );
00933
bool multiModify =
false;
00934
00935
if ( mItemMoved ) {
00936
bool modify =
true;
00937
if ( mActionItem->incidence()->doesRecur() ) {
00938
int res = KMessageBox::questionYesNoCancel(
this,
00939 i18n(
"The item you try to change is a recurring item. Shall the changes "
00940
"be applied to all items in the recurrence, "
00941
"or just to this single occurrence?"),
00942 i18n(
"Changing a recurring item"),
00943 i18n(
"&All occurrences"), i18n(
"Only &this item") );
00944
switch ( res ) {
00945
case KMessageBox::Yes:
00946
00947 modify =
true;
00948
break;
00949
case KMessageBox::No: {
00950
00951
00952
00953
00954
00955
00956 modify =
true;
00957 multiModify =
true;
00958 emit startMultiModify( i18n(
"Dissociate event from recurrence") );
00959 Incidence* oldInc = mActionItem->incidence()->clone();
00960 Incidence* newInc = mCalendar->dissociateOccurrence(
00961 mActionItem->incidence(), mActionItem->itemDate() );
00962
if ( newInc ) {
00963
00964 emit enableAgendaUpdate(
false );
00965 emit incidenceChanged( oldInc, mActionItem->incidence() );
00966 mActionItem->setIncidence( newInc );
00967 emit incidenceAdded( newInc );
00968 emit enableAgendaUpdate(
true );
00969 }
else {
00970 KMessageBox::sorry(
this, i18n(
"Unable to add the exception item to the "
00971
"calendar. No change will be done."), i18n(
"Error Occurred") );
00972 }
00973
delete oldInc;
00974
break; }
00975
case KMessageBox::Continue: {
00976
00977
00978
00979
00980
00981
00982 modify =
true;
00983 multiModify =
true;
00984 emit startMultiModify( i18n(
"Split future recurrences") );
00985 Incidence* oldInc = mActionItem->incidence()->clone();
00986 Incidence* newInc = mCalendar->dissociateOccurrence(
00987 mActionItem->incidence(), mActionItem->itemDate(),
true );
00988
if ( newInc ) {
00989 emit incidenceChanged( oldInc, mActionItem->incidence() );
00990 emit enableAgendaUpdate(
false );
00991 mActionItem->setIncidence( newInc );
00992 emit incidenceAdded( newInc );
00993 emit enableAgendaUpdate(
true );
00994 }
else {
00995 KMessageBox::sorry(
this, i18n(
"Unable to add the future items to the "
00996
"calendar. No change will be done."), i18n(
"Error Occurred") );
00997 }
00998
delete oldInc;
00999
break; }
01000
default:
01001 modify =
false;
01002 mActionItem->resetMove();
01003 placeSubCells( mActionItem );
01004 }
01005 }
01006
01007
if ( modify ) {
01008 mActionItem->endMove();
01009 KOAgendaItem *placeItem = mActionItem->firstMultiItem();
01010
if ( !placeItem ) {
01011 placeItem = mActionItem;
01012 }
01013
01014 KOAgendaItem *modif = placeItem;
01015
01016
QPtrList<KOAgendaItem> oldconflictItems = placeItem->conflictItems();
01017 KOAgendaItem *item;
01018
for ( item = oldconflictItems.first(); item != 0;
01019 item = oldconflictItems.next() ) {
01020 placeSubCells( item );
01021 }
01022
while ( placeItem ) {
01023 placeSubCells( placeItem );
01024 placeItem = placeItem->nextMultiItem();
01025 }
01026
01027
01028 emit itemModified( modif );
01029 }
01030 }
01031
01032 mActionItem = 0;
01033 mActionType = NOP;
01034 mItemMoved =
false;
01035
01036
if ( multiModify ) emit endMultiModify();
01037
01038 kdDebug(5850) <<
"KOAgenda::endItemAction() done" << endl;
01039 }
01040
01041
void KOAgenda::setActionCursor(
int actionType,
bool acting )
01042 {
01043
switch ( actionType ) {
01044
case MOVE:
01045
if (acting) setCursor( sizeAllCursor );
01046
else setCursor( arrowCursor );
01047
break;
01048
case RESIZETOP:
01049
case RESIZEBOTTOM:
01050 setCursor( sizeVerCursor );
01051
break;
01052
case RESIZELEFT:
01053
case RESIZERIGHT:
01054 setCursor( sizeHorCursor );
01055
break;
01056
default:
01057 setCursor( arrowCursor );
01058 }
01059 }
01060
01061
void KOAgenda::setNoActionCursor( KOAgendaItem *moveItem,
const QPoint& viewportPos )
01062 {
01063
01064
01065
01066
01067
01068
01069 QPoint pos = viewportToContents( viewportPos );
01070
bool noResize = (moveItem && moveItem->incidence() &&
01071 moveItem->incidence()->type() ==
"Todo");
01072
01073 KOAgenda::MouseActionType resizeType = MOVE;
01074
if ( !noResize ) resizeType = isInResizeArea( mAllDayMode, pos , moveItem);
01075 setActionCursor( resizeType );
01076 }
01077
01078
01081
double KOAgenda::calcSubCellWidth( KOAgendaItem *item )
01082 {
01083 QPoint pt, pt1;
01084 pt = gridToContents( QPoint( item->cellXLeft(), item->cellYTop() ) );
01085 pt1 = gridToContents( QPoint( item->cellXLeft(), item->cellYTop() ) +
01086 QPoint( 1, 1 ) );
01087 pt1 -= pt;
01088
int maxSubCells = item->subCells();
01089
double newSubCellWidth;
01090
if ( mAllDayMode ) {
01091 newSubCellWidth = double( pt1.y() ) / maxSubCells;
01092 }
else {
01093 newSubCellWidth = double( pt1.x() ) / maxSubCells;
01094 }
01095
return newSubCellWidth;
01096 }
01097
01098
void KOAgenda::adjustItemPosition( KOAgendaItem *item )
01099 {
01100
if (!item)
return;
01101 item->resize(
int( mGridSpacingX * item->cellWidth() ),
01102 int( mGridSpacingY * item->cellHeight() ) );
01103
int clXLeft = item->cellXLeft();
01104
if ( KOGlobals::self()->reverseLayout() )
01105 clXLeft = item->cellXRight() + 1;
01106 QPoint cpos = gridToContents( QPoint( clXLeft, item->cellYTop() ) );
01107 moveChild( item, cpos.x(), cpos.y() );
01108 }
01109
01110
void KOAgenda::placeAgendaItem( KOAgendaItem *item,
double subCellWidth )
01111 {
01112
01113
01114
01115
01116 QPoint pt = gridToContents( QPoint( item->cellXLeft(), item->cellYTop() ) );
01117
01118 QPoint pt1 = gridToContents( QPoint( item->cellXLeft() + item->cellWidth(),
01119 item->cellYBottom()+1 ) );
01120
01121
double subCellPos = item->subCell() * subCellWidth;
01122
01123
01124
01125
double delta=0.01;
01126
if (subCellWidth<0) delta=-delta;
01127
int height, width, xpos, ypos;
01128
if (mAllDayMode) {
01129 width = pt1.x()-pt.x();
01130 height = int( subCellPos + subCellWidth + delta ) - int( subCellPos );
01131 xpos = pt.x();
01132 ypos = pt.y() + int( subCellPos );
01133 }
else {
01134 width = int( subCellPos + subCellWidth + delta ) - int( subCellPos );
01135 height = pt1.y()-pt.y();
01136 xpos = pt.x() + int( subCellPos );
01137 ypos = pt.y();
01138 }
01139
if ( KOGlobals::self()->reverseLayout() ) {
01140 xpos += width;
01141 width = -width;
01142 }
01143
if ( height<0 ) {
01144 ypos += height;
01145 height = -height;
01146 }
01147 item->resize( width, height );
01148 moveChild( item, xpos, ypos );
01149 }
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
void KOAgenda::placeSubCells( KOAgendaItem *placeItem )
01162 {
01163
#if 0
01164
kdDebug(5850) <<
"KOAgenda::placeSubCells()" << endl;
01165
if ( placeItem ) {
01166 Incidence *event = placeItem->incidence();
01167
if ( !event ) {
01168 kdDebug(5850) <<
" event is 0" << endl;
01169 }
else {
01170 kdDebug(5850) <<
" event: " << event->summary() << endl;
01171 }
01172 }
else {
01173 kdDebug(5850) <<
" placeItem is 0" << endl;
01174 }
01175 kdDebug(5850) <<
"KOAgenda::placeSubCells()..." << endl;
01176
#endif
01177
01178
QPtrList<KOrg::CellItem> cells;
01179 KOAgendaItem *item;
01180
for ( item = mItems.first(); item != 0; item = mItems.next() ) {
01181 cells.append( item );
01182 }
01183
01184
QPtrList<KOrg::CellItem> items = KOrg::CellItem::placeItem( cells,
01185 placeItem );
01186
01187 placeItem->setConflictItems(
QPtrList<KOAgendaItem>() );
01188
double newSubCellWidth = calcSubCellWidth( placeItem );
01189 KOrg::CellItem *i;
01190
for ( i = items.first(); i; i = items.next() ) {
01191 item = static_cast<KOAgendaItem *>( i );
01192 placeAgendaItem( item, newSubCellWidth );
01193 item->addConflictItem( placeItem );
01194 placeItem->addConflictItem( item );
01195 }
01196
if ( items.isEmpty() ) {
01197 placeAgendaItem( placeItem, newSubCellWidth );
01198 }
01199 placeItem->update();
01200 }
01201
01202
int KOAgenda::columnWidth(
int column )
01203 {
01204
int start = gridToContents( QPoint( column, 0 ) ).x();
01205
if (KOGlobals::self()->reverseLayout() )
01206 column--;
01207
else
01208 column++;
01209
int end = gridToContents( QPoint( column, 0 ) ).x();
01210
return end - start;
01211 }
01212
01213
01214
01215
void KOAgenda::drawContents(
QPainter* p,
int cx,
int cy,
int cw,
int ch)
01216 {
01217
QPixmap db(cw, ch);
01218 db.fill(KOPrefs::instance()->mAgendaBgColor);
01219
QPainter dbp(&db);
01220 dbp.
translate(-cx,-cy);
01221
01222
01223
double lGridSpacingY = mGridSpacingY*2;
01224
01225
01226
if (mWorkingHoursEnable) {
01227 QPoint pt1( cx, mWorkingHoursYTop );
01228 QPoint pt2( cx+cw, mWorkingHoursYBottom );
01229
if ( pt2.x() >= pt1.x() ) {
01230
int gxStart = contentsToGrid( pt1 ).x();
01231
int gxEnd = contentsToGrid( pt2 ).x();
01232
01233
if ( gxStart > gxEnd ) {
01234
int tmp = gxStart;
01235 gxStart = gxEnd;
01236 gxEnd = tmp;
01237 }
01238
int xoffset = ( KOGlobals::self()->reverseLayout()?1:0 );
01239
while( gxStart <= gxEnd ) {
01240
int xStart = gridToContents( QPoint( gxStart+xoffset, 0 ) ).x();
01241
int xWidth = columnWidth( gxStart ) + 1;
01242
if ( pt2.y() < pt1.y() ) {
01243
01244
if ( ( (gxStart==0) && !mHolidayMask->at(mHolidayMask->count()-1) ) ||
01245 ( (gxStart>0) && (gxStart<int(mHolidayMask->count())) && (!mHolidayMask->at(gxStart-1) ) ) ) {
01246
if ( pt2.y() > cy ) {
01247 dbp.fillRect( xStart, cy, xWidth, pt2.y() - cy + 1,
01248 KOPrefs::instance()->mWorkingHoursColor);
01249 }
01250 }
01251
if ( (gxStart < int(mHolidayMask->count()-1)) && (!mHolidayMask->at(gxStart)) ) {
01252
if ( pt1.y() < cy + ch - 1 ) {
01253 dbp.fillRect( xStart, pt1.y(), xWidth, cy + ch - pt1.y() + 1,
01254 KOPrefs::instance()->mWorkingHoursColor);
01255 }
01256 }
01257 }
else {
01258
01259
if ( gxStart < int(mHolidayMask->count()-1) && !mHolidayMask->at(gxStart)) {
01260 dbp.fillRect( xStart, pt1.y(), xWidth, pt2.y() - pt1.y() + 1,
01261 KOPrefs::instance()->mWorkingHoursColor );
01262 }
01263 }
01264 ++gxStart;
01265 }
01266 }
01267 }
01268
01269
01270
if ( mHasSelection ) {
01271 QPoint pt, pt1;
01272
01273
if ( mSelectionEndCell.x() > mSelectionStartCell.x() ) {
01274
01275 pt = gridToContents( mSelectionStartCell );
01276 pt1 = gridToContents( QPoint( mSelectionStartCell.x() + 1, mRows + 1 ) );
01277 dbp.fillRect(
QRect( pt, pt1 ), KOPrefs::instance()->mHighlightColor );
01278
01279
for (
int c = mSelectionStartCell.x() + 1; c < mSelectionEndCell.x(); ++c ) {
01280 pt = gridToContents( QPoint( c, 0 ) );
01281 pt1 = gridToContents( QPoint( c + 1, mRows + 1 ) );
01282 dbp.fillRect(
QRect( pt, pt1 ), KOPrefs::instance()->mHighlightColor );
01283 }
01284
01285 pt = gridToContents( QPoint( mSelectionEndCell.x(), 0 ) );
01286 pt1 = gridToContents( mSelectionEndCell + QPoint(1,1) );
01287 dbp.fillRect(
QRect( pt, pt1), KOPrefs::instance()->mHighlightColor );
01288 }
else {
01289 pt = gridToContents( mSelectionStartCell );
01290 pt1 = gridToContents( mSelectionEndCell + QPoint(1,1) );
01291 dbp.fillRect(
QRect( pt, pt1 ), KOPrefs::instance()->mHighlightColor );
01292 }
01293 }
01294
01295 dbp.setPen( KOPrefs::instance()->mAgendaBgColor.dark(150) );
01296
01297
01298
01299
double x = ( int( cx / mGridSpacingX ) ) * mGridSpacingX;
01300
while (x < cx + cw) {
01301 dbp.drawLine(
int( x ), cy,
int( x ), cy + ch );
01302 x+=mGridSpacingX;
01303 }
01304
01305
01306
double y = ( int( cy / lGridSpacingY ) ) * lGridSpacingY;
01307
while (y < cy + ch) {
01308
01309 dbp.drawLine( cx,
int( y ), cx + cw,
int( y ) );
01310 y+=lGridSpacingY;
01311 }
01312 p->drawPixmap(cx,cy, db);
01313 }
01314
01315
01316
01317
01318 QPoint KOAgenda::contentsToGrid (
const QPoint &pos )
const
01319
{
01320
int gx = int( KOGlobals::self()->reverseLayout() ?
01321 mColumns - pos.x()/mGridSpacingX : pos.x()/mGridSpacingX );
01322
int gy = int( pos.y()/mGridSpacingY );
01323
return QPoint( gx, gy );
01324 }
01325
01326
01327
01328
01329 QPoint KOAgenda::gridToContents(
const QPoint &gpos )
const
01330
{
01331
int x = int( KOGlobals::self()->reverseLayout() ?
01332 (mColumns - gpos.x())*mGridSpacingX : gpos.x()*mGridSpacingX );
01333
int y = int( gpos.y()*mGridSpacingY );
01334
return QPoint( x, y );
01335 }
01336
01337
01338
01339
01340
01341
01342
int KOAgenda::timeToY(
const QTime &time)
01343 {
01344
01345
int minutesPerCell = 24 * 60 / mRows;
01346
01347
int timeMinutes = time.hour() * 60 + time.minute();
01348
01349
int Y = (timeMinutes + (minutesPerCell / 2)) / minutesPerCell;
01350
01351
01352
return Y;
01353 }
01354
01355
01356
01357
01358
01359
01360
QTime KOAgenda::gyToTime(
int gy)
01361 {
01362
01363
int secondsPerCell = 24 * 60 * 60/ mRows;
01364
01365
int timeSeconds = secondsPerCell * gy;
01366
01367
QTime time( 0, 0, 0 );
01368
if ( timeSeconds < 24 * 60 * 60 ) {
01369 time = time.addSecs(timeSeconds);
01370 }
else {
01371 time.setHMS( 23, 59, 59 );
01372 }
01373
01374
01375
return time;
01376 }
01377
01378
QMemArray<int> KOAgenda::minContentsY()
01379 {
01380
QMemArray<int> minArray;
01381 minArray.fill( timeToY(
QTime(23, 59) ), mSelectedDates.count() );
01382
for ( KOAgendaItem *item = mItems.first();
01383 item != 0;
01384 item = mItems.next() ) {
01385
int timeY = timeToY( item->incidence()->dtStart().time() );
01386
int index = mSelectedDates.findIndex( item->incidence()->dtStart().date() );
01387
if( timeY < minArray[index] && mItemsToDelete.findRef( item ) == -1 )
01388 minArray[index] = timeY;
01389 }
01390
01391
return minArray;
01392 }
01393
01394
QMemArray<int> KOAgenda::maxContentsY()
01395 {
01396
QMemArray<int> maxArray;
01397 maxArray.fill( timeToY(
QTime(0, 0) ), mSelectedDates.count() );
01398
for ( KOAgendaItem *item = mItems.first();
01399 item != 0;
01400 item = mItems.next() ) {
01401
QDateTime dtEnd;
01402
if ( item->incidence()->type() ==
"Todo" )
01403 dtEnd = static_cast<Todo *>( item->incidence() )->dtDue();
01404
else
01405 dtEnd = item->incidence()->dtEnd();
01406
int timeY = timeToY( dtEnd.time() );
01407
int index = mSelectedDates.findIndex( dtEnd.date() );
01408
if( timeY > maxArray[index] && mItemsToDelete.findRef( item ) == -1 )
01409 maxArray[index] = timeY - 1;
01410 }
01411
01412
return maxArray;
01413 }
01414
01415
void KOAgenda::setStartTime(
QTime startHour )
01416 {
01417
double startPos = ( startHour.hour()/24. + startHour.minute()/1440. +
01418 startHour.second()/86400. ) * mRows * gridSpacingY();
01419 setContentsPos( 0,
int( startPos ) );
01420 }
01421
01422
01423
01424
01425
01426 KOAgendaItem *KOAgenda::insertItem( Incidence *incidence,
QDate qd,
int X,
01427
int YTop,
int YBottom )
01428 {
01429
#if 0
01430
kdDebug(5850) <<
"KOAgenda::insertItem:" << event->summary() <<
"-"
01431 << qd.toString() <<
" ;top, bottom:" << YTop <<
"," << YBottom
01432 << endl;
01433
#endif
01434
01435
if ( mAllDayMode ) {
01436 kdDebug(5850) <<
"KOAgenda: calling insertItem in all-day mode is illegal." << endl;
01437
return 0;
01438 }
01439 mActionType = NOP;
01440
01441 KOAgendaItem *agendaItem =
new KOAgendaItem( incidence, qd, viewport() );
01442 connect( agendaItem, SIGNAL( removeAgendaItem( KOAgendaItem * ) ),
01443 SLOT( removeAgendaItem( KOAgendaItem * ) ) );
01444 connect( agendaItem, SIGNAL( showAgendaItem( KOAgendaItem * ) ),
01445 SLOT( showAgendaItem( KOAgendaItem * ) ) );
01446
01447
if ( YBottom <= YTop ) {
01448 kdDebug(5850) <<
"KOAgenda::insertItem(): Text: " << agendaItem->text() <<
" YSize<0" << endl;
01449 YBottom = YTop;
01450 }
01451
01452 agendaItem->resize(
int( ( X + 1 ) * mGridSpacingX ) -
01453
int( X * mGridSpacingX ),
01454
int( YTop * mGridSpacingY ) -
01455
int( ( YBottom + 1 ) * mGridSpacingY ) );
01456 agendaItem->setCellXY( X, YTop, YBottom );
01457 agendaItem->setCellXRight( X );
01458
01459 agendaItem->installEventFilter(
this );
01460
01461 addChild( agendaItem,
int( X * mGridSpacingX ),
int( YTop * mGridSpacingY ) );
01462 mItems.append( agendaItem );
01463
01464 placeSubCells( agendaItem );
01465
01466 agendaItem->show();
01467
01468 marcus_bains();
01469
01470
return agendaItem;
01471 }
01472
01473
01474
01475
01476 KOAgendaItem *KOAgenda::insertAllDayItem( Incidence *event,
QDate qd,
01477
int XBegin,
int XEnd )
01478 {
01479
if ( !mAllDayMode ) {
01480 kdDebug(5850) <<
"KOAgenda: calling insertAllDayItem in non all-day mode is illegal." << endl;
01481
return 0;
01482 }
01483 mActionType = NOP;
01484
01485 KOAgendaItem *agendaItem =
new KOAgendaItem( event, qd, viewport() );
01486 connect( agendaItem, SIGNAL( removeAgendaItem( KOAgendaItem* ) ),
01487 SLOT( removeAgendaItem( KOAgendaItem* ) ) );
01488 connect( agendaItem, SIGNAL( showAgendaItem( KOAgendaItem* ) ),
01489 SLOT( showAgendaItem( KOAgendaItem* ) ) );
01490
01491 agendaItem->setCellXY( XBegin, 0, 0 );
01492 agendaItem->setCellXRight( XEnd );
01493
01494
double startIt = mGridSpacingX * ( agendaItem->cellXLeft() );
01495
double endIt = mGridSpacingX * ( agendaItem->cellWidth() +
01496 agendaItem->cellXLeft() );
01497
01498 agendaItem->resize(
int( endIt ) -
int( startIt ),
int( mGridSpacingY ) );
01499
01500 agendaItem->installEventFilter(
this );
01501
01502 addChild( agendaItem,
int( XBegin * mGridSpacingX ), 0 );
01503 mItems.append( agendaItem );
01504
01505 placeSubCells( agendaItem );
01506
01507 agendaItem->show();
01508
01509
return agendaItem;
01510 }
01511
01512
01513
void KOAgenda::insertMultiItem (Event *event,
QDate qd,
int XBegin,
int XEnd,
01514
int YTop,
int YBottom)
01515 {
01516
if (mAllDayMode) {
01517 kdDebug(5850) <<
"KOAgenda: calling insertMultiItem in all-day mode is illegal." << endl;
01518
return;
01519 }
01520 mActionType = NOP;
01521
01522
int cellX,cellYTop,cellYBottom;
01523
QString newtext;
01524
int width = XEnd - XBegin + 1;
01525
int count = 0;
01526 KOAgendaItem *current = 0;
01527
QPtrList<KOAgendaItem> multiItems;
01528
for ( cellX = XBegin; cellX <= XEnd; ++cellX ) {
01529
if ( cellX == XBegin ) cellYTop = YTop;
01530
else cellYTop = 0;
01531
if ( cellX == XEnd ) cellYBottom = YBottom;
01532
else cellYBottom = rows() - 1;
01533 newtext =
QString(
"(%1/%2): ").arg( ++count ).arg( width );
01534 newtext.append( event->summary() );
01535 current = insertItem( event, qd, cellX, cellYTop, cellYBottom );
01536 current->setText( newtext );
01537 multiItems.append( current );
01538 }
01539
01540 KOAgendaItem *next = 0;
01541 KOAgendaItem *prev = 0;
01542 KOAgendaItem *last = multiItems.last();
01543 KOAgendaItem *first = multiItems.first();
01544 KOAgendaItem *setFirst,*setLast;
01545 current = first;
01546
while (current) {
01547 next = multiItems.next();
01548
if (current == first) setFirst = 0;
01549
else setFirst = first;
01550
if (current == last) setLast = 0;
01551
else setLast = last;
01552
01553 current->setMultiItem(setFirst, prev, next, setLast);
01554 prev=current;
01555 current = next;
01556 }
01557
01558 marcus_bains();
01559 }
01560
01561
void KOAgenda::removeIncidence( Incidence *incidence )
01562 {
01563
01564
01565
01566
QPtrList<KOAgendaItem> itemsToRemove;
01567
01568 KOAgendaItem *item = mItems.first();
01569
while ( item ) {
01570
if ( item->incidence() == incidence ) {
01571 itemsToRemove.append( item );
01572 }
01573 item = mItems.next();
01574 }
01575 item = itemsToRemove.first();
01576
while ( item ) {
01577 removeAgendaItem( item );
01578 item = itemsToRemove.next();
01579 }
01580 }
01581
01582
void KOAgenda::showAgendaItem( KOAgendaItem *agendaItem )
01583 {
01584
if ( !agendaItem )
return;
01585 agendaItem->hide();
01586 addChild( agendaItem );
01587
if ( !mItems.containsRef( agendaItem ) )
01588 mItems.append( agendaItem );
01589 placeSubCells( agendaItem );
01590 agendaItem->show();
01591 }
01592
01593
bool KOAgenda::removeAgendaItem( KOAgendaItem *item )
01594 {
01595
01596
bool taken =
false;
01597 KOAgendaItem *thisItem = item;
01598
QPtrList<KOAgendaItem> conflictItems = thisItem->conflictItems();
01599 removeChild( thisItem );
01600
int pos = mItems.find( thisItem );
01601
if ( pos>=0 ) {
01602 mItems.take( pos );
01603 taken =
true;
01604 }
01605
01606 KOAgendaItem *confitem;
01607
for ( confitem = conflictItems.first(); confitem != 0;
01608 confitem = conflictItems.next() ) {
01609
01610
if ( confitem != thisItem ) placeSubCells(confitem);
01611
01612 }
01613 mItemsToDelete.append( thisItem );
01614 QTimer::singleShot( 0,
this, SLOT( deleteItemsToDelete() ) );
01615
return taken;
01616 }
01617
01618
void KOAgenda::deleteItemsToDelete()
01619 {
01620 mItemsToDelete.clear();
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
void KOAgenda::resizeEvent (
QResizeEvent *ev )
01642 {
01643
01644
double subCellWidth;
01645 KOAgendaItem *item;
01646
if (mAllDayMode) {
01647 mGridSpacingX = double( width() - 2 * frameWidth() ) / (
double)mColumns;
01648
01649 mGridSpacingY = height() - 2 * frameWidth();
01650 resizeContents(
int( mGridSpacingX * mColumns ),
int( mGridSpacingY ) );
01651
01652
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
01653 subCellWidth = calcSubCellWidth( item );
01654 placeAgendaItem( item, subCellWidth );
01655 }
01656 }
else {
01657 mGridSpacingX = double(width() - verticalScrollBar()->width() - 2 * frameWidth()) / double(mColumns);
01658
01659 mGridSpacingY = double(height() - 2 * frameWidth()) / double(mRows);
01660
if ( mGridSpacingY < mDesiredGridSpacingY ) mGridSpacingY = mDesiredGridSpacingY;
01661
01662 resizeContents(
int( mGridSpacingX * mColumns ),
int( mGridSpacingY * mRows ));
01663
01664
for ( item=mItems.first(); item != 0; item=mItems.next() ) {
01665 subCellWidth = calcSubCellWidth( item );
01666 placeAgendaItem( item, subCellWidth );
01667 }
01668 }
01669
01670 checkScrollBoundaries();
01671 calculateWorkingHours();
01672
01673 marcus_bains();
01674
01675 QScrollView::resizeEvent(ev);
01676 viewport()->update();
01677 }
01678
01679
01680
void KOAgenda::scrollUp()
01681 {
01682 scrollBy(0,-mScrollOffset);
01683 }
01684
01685
01686
void KOAgenda::scrollDown()
01687 {
01688 scrollBy(0,mScrollOffset);
01689 }
01690
01691
01692
01693
01694
01695
int KOAgenda::minimumWidth()
const
01696
{
01697
01698
int min = 100;
01699
01700
return min;
01701 }
01702
01703
void KOAgenda::updateConfig()
01704 {
01705 mDesiredGridSpacingY = KOPrefs::instance()->mHourSize;
01706
01707 mGridSpacingY = (
double)height()/(
double)mRows;
01708
if (mGridSpacingY<mDesiredGridSpacingY) mGridSpacingY=mDesiredGridSpacingY;
01709
01710 calculateWorkingHours();
01711
01712 marcus_bains();
01713 }
01714
01715
void KOAgenda::checkScrollBoundaries()
01716 {
01717
01718 mOldLowerScrollValue = -1;
01719 mOldUpperScrollValue = -1;
01720
01721 checkScrollBoundaries(verticalScrollBar()->value());
01722 }
01723
01724
void KOAgenda::checkScrollBoundaries(
int v)
01725 {
01726
int yMin = int( v / mGridSpacingY );
01727
int yMax = int( ( v + visibleHeight() ) / mGridSpacingY );
01728
01729
01730
01731
if (yMin != mOldLowerScrollValue) {
01732 mOldLowerScrollValue = yMin;
01733 emit lowerYChanged(yMin);
01734 }
01735
if (yMax != mOldUpperScrollValue) {
01736 mOldUpperScrollValue = yMax;
01737 emit upperYChanged(yMax);
01738 }
01739 }
01740
01741
void KOAgenda::deselectItem()
01742 {
01743
if (mSelectedItem.isNull())
return;
01744 mSelectedItem->select(
false);
01745 mSelectedItem = 0;
01746 }
01747
01748
void KOAgenda::selectItem(KOAgendaItem *item)
01749 {
01750
if ((KOAgendaItem *)mSelectedItem == item)
return;
01751 deselectItem();
01752
if (item == 0) {
01753 emit incidenceSelected( 0 );
01754
return;
01755 }
01756 mSelectedItem = item;
01757 mSelectedItem->select();
01758 emit incidenceSelected( mSelectedItem->incidence() );
01759 }
01760
01761
void KOAgenda::selectItemByUID(
const QString& uid )
01762 {
01763 KOAgendaItem *item;
01764
for ( item = mItems.first(); item != 0; item = mItems.next() ) {
01765
if( item->incidence() && item->incidence()->uid() == uid ) {
01766 selectItem( item );
01767
break;
01768 }
01769 }
01770 }
01771
01772
01773
void KOAgenda::keyPressEvent(
QKeyEvent *kev )
01774 {
01775
switch(kev->key()) {
01776
case Key_PageDown:
01777 verticalScrollBar()->addPage();
01778
break;
01779
case Key_PageUp:
01780 verticalScrollBar()->subtractPage();
01781
break;
01782
case Key_Down:
01783 verticalScrollBar()->addLine();
01784
break;
01785
case Key_Up:
01786 verticalScrollBar()->subtractLine();
01787
break;
01788
default:
01789 ;
01790 }
01791 }
01792
01793
void KOAgenda::calculateWorkingHours()
01794 {
01795 mWorkingHoursEnable = !mAllDayMode;
01796
01797
QTime tmp = KOPrefs::instance()->mWorkingHoursStart.time();
01798 mWorkingHoursYTop = int( 4 * mGridSpacingY *
01799 ( tmp.hour() + tmp.minute() / 60. +
01800 tmp.second() / 3600. ) );
01801 tmp = KOPrefs::instance()->mWorkingHoursEnd.time();
01802 mWorkingHoursYBottom = int( 4 * mGridSpacingY *
01803 ( tmp.hour() + tmp.minute() / 60. +
01804 tmp.second() / 3600. ) - 1 );
01805 }
01806
01807
01808 DateList KOAgenda::dateList()
const
01809
{
01810
return mSelectedDates;
01811 }
01812
01813
void KOAgenda::setDateList(
const DateList &selectedDates)
01814 {
01815 mSelectedDates = selectedDates;
01816 marcus_bains();
01817 }
01818
01819
void KOAgenda::setHolidayMask(
QMemArray<bool> *mask)
01820 {
01821 mHolidayMask = mask;
01822
01823 }
01824
01825
void KOAgenda::contentsMousePressEvent (
QMouseEvent *event )
01826 {
01827 kdDebug(5850) <<
"KOagenda::contentsMousePressEvent(): type: " << event->type() << endl;
01828 QScrollView::contentsMousePressEvent(event);
01829 }
01830
01831
void KOAgenda::setTypeAheadReceiver(
QObject *o )
01832 {
01833 mTypeAheadReceiver = o;
01834 }
01835
01836
QObject *KOAgenda::typeAheadReceiver()
const
01837
{
01838
return mTypeAheadReceiver;
01839 }