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