summaryrefslogtreecommitdiffabout
path: root/korganizer/koagenda.cpp
Unidiff
Diffstat (limited to 'korganizer/koagenda.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/koagenda.cpp1932
1 files changed, 1932 insertions, 0 deletions
diff --git a/korganizer/koagenda.cpp b/korganizer/koagenda.cpp
new file mode 100644
index 0000000..607c250
--- a/dev/null
+++ b/korganizer/koagenda.cpp
@@ -0,0 +1,1932 @@
1/*
2 This file is part of KOrganizer.
3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4
5 Marcus Bains line.
6 Copyright (c) 2001 Ali Rahimi
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 As a special exception, permission is given to link this program
23 with any edition of Qt, and distribute the resulting executable,
24 without including the source code for Qt in the source distribution.
25*/
26
27#ifndef _WIN32_
28#define protected public
29#include <qwidget.h>
30#undef protected
31#endif
32#include <qintdict.h>
33#include <qdatetime.h>
34#include <qapplication.h>
35#include <qpopupmenu.h>
36#include <qcursor.h>
37#include <qpainter.h>
38
39#include <kdebug.h>
40#include <klocale.h>
41#include <kiconloader.h>
42#include <kglobal.h>
43
44#include "koagendaitem.h"
45#include "koprefs.h"
46#include "koglobals.h"
47
48#include "koagenda.h"
49#include "koagenda.moc"
50
51#include <libkcal/event.h>
52#include <libkcal/todo.h>
53
54#ifndef DESKTOP_VERSION
55#include <qpe/qpeapplication.h>
56#endif
57
58//extern bool globalFlagBlockPainting;
59extern int globalFlagBlockAgenda;
60extern int globalFlagBlockAgendaItemPaint;
61extern int globalFlagBlockAgendaItemUpdate;
62extern int globalFlagBlockStartup;
63
64////////////////////////////////////////////////////////////////////////////
65MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name)
66 : QFrame(_agenda->viewport(),name), agenda(_agenda)
67{
68 setLineWidth(0);
69 setMargin(0);
70 setBackgroundColor(Qt::red);
71 minutes = new QTimer(this);
72 connect(minutes, SIGNAL(timeout()), this, SLOT(updateLoc()));
73 minutes->start(0, true);
74
75 mTimeBox = new QLabel(this);
76 mTimeBox->setAlignment(Qt::AlignRight | Qt::AlignBottom);
77 QPalette pal = mTimeBox->palette();
78 pal.setColor(QColorGroup::Foreground, Qt::red);
79 mTimeBox->setPalette(pal);
80 //mTimeBox->setAutoMask(true);
81
82 agenda->addChild(mTimeBox);
83
84 oldToday = -1;
85}
86
87MarcusBains::~MarcusBains()
88{
89 delete minutes;
90}
91
92int MarcusBains::todayColumn()
93{
94 QDate currentDate = QDate::currentDate();
95
96 DateList dateList = agenda->dateList();
97 DateList::ConstIterator it;
98 int col = 0;
99 for(it = dateList.begin(); it != dateList.end(); ++it) {
100 if((*it) == currentDate)
101 return KOGlobals::self()->reverseLayout() ?
102 agenda->columns() - 1 - col : col;
103 ++col;
104 }
105
106 return -1;
107}
108void MarcusBains::updateLoc()
109{
110 updateLocation();
111}
112void MarcusBains::updateLocation(bool recalculate)
113{
114
115 QTime tim = QTime::currentTime();
116 //qDebug(" MarcusBains::updateLocation %s ", tim.toString().latin1());
117 if((tim.hour() == 0) && (oldTime.hour()==23))
118 recalculate = true;
119
120 int mins = tim.hour()*60 + tim.minute();
121 int minutesPerCell = 24 * 60 / agenda->rows();
122 int y = mins*agenda->gridSpacingY()/minutesPerCell;
123 int today = recalculate ? todayColumn() : oldToday;
124 int x = agenda->gridSpacingX()*today;
125 bool disabled = !(KOPrefs::instance()->mMarcusBainsEnabled);
126
127 oldTime = tim;
128 oldToday = today;
129
130 if(disabled || (today<0)) {
131 hide(); mTimeBox->hide();
132 return;
133 } else {
134 show(); mTimeBox->show();
135 }
136
137 if(recalculate)
138 setFixedSize(agenda->gridSpacingX(),1);
139 agenda->moveChild(this, x, y);
140 raise();
141
142 if(recalculate)
143 //mTimeBox->setFont(QFont("helvetica",10));
144 mTimeBox->setFont(KOPrefs::instance()->mMarcusBainsFont);
145
146 mTimeBox->setText(KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds));
147 mTimeBox->adjustSize();
148 // the -2 below is there because there is a bug in this program
149 // somewhere, where the last column of this widget is a few pixels
150 // narrower than the other columns.
151 int offs = (today==agenda->columns()-1) ? -4 : 0;
152 agenda->moveChild(mTimeBox,
153 x+agenda->gridSpacingX()-mTimeBox->width()+offs-1,
154 y-mTimeBox->height());
155
156 mTimeBox->raise();
157 //mTimeBox->setAutoMask(true);
158 minutes->start(5000,true);
159}
160
161
162////////////////////////////////////////////////////////////////////////////
163
164
165/*
166 Create an agenda widget with rows rows and columns columns.
167*/
168KOAgenda::KOAgenda(int columns,int rows,int rowSize,QWidget *parent,
169 const char *name,WFlags f) :
170 QScrollView(parent,name,f)
171{
172
173 mColumns = columns;
174 mRows = rows;
175 mGridSpacingY = rowSize;
176 mAllDayMode = false;
177#ifndef DESKTOP_VERSION
178 QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold );
179#endif
180 mHolidayMask = 0;
181 init();
182}
183
184/*
185 Create an agenda widget with columns columns and one row. This is used for
186 all-day events.
187*/
188KOAgenda::KOAgenda(int columns,QWidget *parent,const char *name,WFlags f) :
189 QScrollView(parent,name,f)
190{
191
192 blockResize = false;
193 mColumns = columns;
194 mRows = 1;
195 //qDebug("aaaaaaaaaaaaaaaaaaldays %d ", KOPrefs::instance()->mAllDaySize);
196 mGridSpacingY = KOPrefs::instance()->mAllDaySize;
197 mAllDayMode = true;
198#ifndef DESKTOP_VERSION
199 QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold );
200#endif
201 mHolidayMask = 0;
202 init();
203}
204
205
206KOAgenda::~KOAgenda()
207{
208 if(mMarcusBains) delete mMarcusBains;
209
210}
211
212Incidence *KOAgenda::selectedIncidence() const
213{
214 return (mSelectedItem ? mSelectedItem->incidence() : 0);
215}
216
217
218QDate KOAgenda::selectedIncidenceDate() const
219{
220 return (mSelectedItem ? mSelectedItem->itemDate() : QDate());
221}
222
223
224void KOAgenda::init()
225{
226#ifndef _WIN32_
227 int wflags = viewport()-> getWFlags() |WRepaintNoErase;//WResizeNoErase
228 viewport()->setWFlags ( wflags);
229#endif
230 mGridSpacingX = 80;
231 mResizeBorderWidth = 8;
232 mScrollBorderWidth = 8;
233 mScrollDelay = 30;
234 mScrollOffset = 10;
235 mPaintPixmap.resize( 20,20);
236 //enableClipper(true);
237
238 // Grab key strokes for keyboard navigation of agenda. Seems to have no
239 // effect. Has to be fixed.
240 setFocusPolicy(WheelFocus);
241
242 connect(&mScrollUpTimer,SIGNAL(timeout()),SLOT(scrollUp()));
243 connect(&mScrollDownTimer,SIGNAL(timeout()),SLOT(scrollDown()));
244 connect(&mResizeTimer,SIGNAL(timeout()),SLOT(finishResize()));
245
246 mStartCellX = 0;
247 mStartCellY = 0;
248 mCurrentCellX = 0;
249 mCurrentCellY = 0;
250
251 mSelectionCellX = 0;
252 mSelectionYTop = 0;
253 mSelectionHeight = 0;
254
255 mOldLowerScrollValue = -1;
256 mOldUpperScrollValue = -1;
257
258 mClickedItem = 0;
259
260 mActionItem = 0;
261 mActionType = NOP;
262 mItemMoved = false;
263
264 mSelectedItem = 0;
265
266 // mItems.setAutoDelete(true);
267
268 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
269
270 viewport()->update();
271
272 setMinimumSize(30, 1);
273// setMaximumHeight(mGridSpacingY * mRows + 5);
274
275 // Disable horizontal scrollbar. This is a hack. The geometry should be
276 // controlled in a way that the contents horizontally always fits. Then it is
277 // not necessary to turn off the scrollbar.
278 setHScrollBarMode(AlwaysOff);
279 if ( ! mAllDayMode )
280 setVScrollBarMode(AlwaysOn);
281 else
282 setVScrollBarMode(AlwaysOff);
283
284 setStartHour(KOPrefs::instance()->mDayBegins);
285
286 calculateWorkingHours();
287
288 connect(verticalScrollBar(),SIGNAL(valueChanged(int)),
289 SLOT(checkScrollBoundaries(int)));
290
291 // Create the Marcus Bains line.
292 if(mAllDayMode)
293 mMarcusBains = 0;
294 else {
295 mMarcusBains = new MarcusBains(this);
296 addChild(mMarcusBains);
297 }
298}
299
300void KOAgenda::clear()
301{
302 KOAgendaItem *item;
303 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
304 mUnusedItems.append( item );
305 //item->hide();
306 }
307 mItems.clear();
308 mSelectedItem = 0;
309 clearSelection();
310}
311
312void KOAgenda::clearSelection()
313{
314 mSelectionCellX = 0;
315 mSelectionYTop = 0;
316 mSelectionHeight = 0;
317}
318
319void KOAgenda::marcus_bains()
320{
321 if(mMarcusBains) mMarcusBains->updateLocation(true);
322}
323
324
325void KOAgenda::changeColumns(int columns)
326{
327 if (columns == 0) {
328 kdDebug() << "KOAgenda::changeColumns() called with argument 0" << endl;
329 return;
330 }
331
332 clear();
333
334 mColumns = columns;
335// setMinimumSize(mColumns * 10, mGridSpacingY + 1);
336// init();
337// update();
338 //qDebug("KOAgenda::changeColumns ");
339 computeSizes();
340 // QResizeEvent event( size(), size() );
341
342 //QApplication::sendEvent( this, &event );
343}
344
345/*
346 This is the eventFilter function, which gets all events from the KOAgendaItems
347 contained in the agenda. It has to handle moving and resizing for all items.
348*/
349bool KOAgenda::eventFilter ( QObject *object, QEvent *event )
350{
351// kdDebug() << "KOAgenda::eventFilter" << endl;
352 switch(event->type()) {
353 case QEvent::MouseButtonPress:
354 case QEvent::MouseButtonDblClick:
355 case QEvent::MouseButtonRelease:
356 case QEvent::MouseMove:
357 return eventFilter_mouse(object, static_cast<QMouseEvent *>(event));
358
359 case (QEvent::Leave):
360 if (!mActionItem)
361 setCursor(arrowCursor);
362 return true;
363
364 default:
365 return QScrollView::eventFilter(object,event);
366 }
367}
368
369
370bool KOAgenda::eventFilter_mouse(QObject *object, QMouseEvent *me)
371{
372 //qDebug("KOAgenda::eventFilter_mous ");
373 QPoint viewportPos;
374 if (object != viewport()) {
375 viewportPos = ((QWidget *)object)->mapToParent(me->pos());
376 } else {
377 viewportPos = me->pos();
378 }
379 static int startX = 0;
380 static int startY = 0;
381 static bool block = true;
382 switch (me->type()) {
383 case QEvent::MouseButtonPress:
384 //qDebug("QEvent::MouseButtonPress: ");
385 // kdDebug() << "koagenda: filtered button press" << endl;
386 if (object != viewport()) {
387 if (me->button() == RightButton) {
388
389 mClickedItem = (KOAgendaItem *)object;
390 if (mClickedItem) {
391 selectItem(mClickedItem);
392 // emit showIncidencePopupSignal(mClickedItem->incidence());
393 }
394 //mItemPopup->popup(QCursor::pos());
395 } else {
396 mActionItem = (KOAgendaItem *)object;
397 if (mActionItem) {
398 if ( mSelectionHeight > 0 ) {
399 int selectionCellX = mSelectionCellX * mGridSpacingX;
400 int selectionYTop = mSelectionYTop;
401 int gridSpacingX = mGridSpacingX;
402 int selectionHeight = mSelectionHeight;
403 clearSelection();
404 repaintContents( selectionCellX, selectionYTop,
405 gridSpacingX, selectionHeight,false );
406 }
407 selectItem(mActionItem);
408 Incidence *incidence = mActionItem->incidence();
409 if ( incidence->isReadOnly() /*|| incidence->recurrence()->doesRecur() */) {
410 mActionItem = 0;
411 } else {
412 startItemAction(viewportPos);
413 startX = viewportPos.x();
414 startY = viewportPos.y();
415 block = true;
416 }
417 }
418 }
419 } else {
420 selectItem(0);
421 mActionItem = 0;
422 setCursor(arrowCursor);
423 startSelectAction(viewportPos);
424 }
425 break;
426
427 case QEvent::MouseButtonRelease:
428 //qDebug("QEvent::MouseButtonRelease: ");
429 if (me->button() == RightButton && block ) {
430 if (object != viewport()) {
431 mClickedItem = (KOAgendaItem *)object;
432 if (mActionItem ) {
433 endItemAction();
434 }
435 if (mClickedItem) {
436 selectItem(mClickedItem);
437 emit showIncidencePopupSignal(mClickedItem->incidence());
438 }
439 }
440 break;
441 }
442 block = true;
443 if (mActionItem) {
444 QPoint clipperPos = clipper()->mapFromGlobal(viewport()->mapToGlobal(viewportPos));
445 //qDebug(" %d %d %d ",clipperPos.y(),visibleHeight() , 9 );
446 if ( mActionType == MOVE && (clipperPos.y() > visibleHeight()-2 ||clipperPos.y() < 0 ) ) {
447 mScrollUpTimer.stop();
448 mScrollDownTimer.stop();
449 mActionItem->resetMove();
450 placeSubCells( mActionItem );
451 // emit startDragSignal( mActionItem->incidence() );
452 setCursor( arrowCursor );
453 mActionItem = 0;
454 mActionType = NOP;
455 mItemMoved = 0;
456 return true;
457 }
458 endItemAction();
459 } else if ( mActionType == SELECT ) {
460 endSelectAction();
461 }
462 break;
463
464 case QEvent::MouseMove:
465 if (object != viewport()) {
466 KOAgendaItem *moveItem = (KOAgendaItem *)object;
467 //qDebug("moveItem %d ",moveItem );
468 if (!moveItem->incidence()->isReadOnly() /*&&
469 !moveItem->incidence()->recurrence()->doesRecur()*/ )
470 if (!mActionItem)
471 setNoActionCursor(moveItem,viewportPos);
472 else {
473 if ( block ) {
474 int dX, dY;
475 dX = startX - viewportPos.x();
476 if ( dX < 0 )
477 dX = -dX;
478 dY = viewportPos.y() - startY;
479 if ( dY < 0 )
480 dY = -dY;
481 int diff = 30;
482 if ( QApplication::desktop()->width() < 480 )
483 diff = 15;
484 // qDebug(" %d %d ",dX, dY );
485 if ( dX > diff || dY > diff ) {
486 block = false;
487 }
488 }
489 if ( !block )
490 performItemAction(viewportPos);
491 }
492 } else {
493 if ( mActionType == SELECT ) {
494 performSelectAction( viewportPos );
495 }
496 }
497 break;
498
499 case QEvent::MouseButtonDblClick:
500 if (object == viewport()) {
501 selectItem(0);
502 int x,y;
503 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
504 int gx,gy;
505 contentsToGrid(x,y,gx,gy);
506 emit newEventSignal(gx,gy);
507 } else {
508 KOAgendaItem *doubleClickedItem = (KOAgendaItem *)object;
509 selectItem(doubleClickedItem);
510 if ( KOPrefs::instance()->mEditOnDoubleClick )
511 emit editIncidenceSignal(doubleClickedItem->incidence());
512 else
513 emit showIncidenceSignal(doubleClickedItem->incidence());
514 }
515 break;
516
517 default:
518 break;
519 }
520
521 return true;
522}
523
524void KOAgenda::startSelectAction(QPoint viewportPos)
525{
526 //emit newStartSelectSignal();
527
528 mActionType = SELECT;
529
530 int x,y;
531 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
532 int gx,gy;
533 contentsToGrid(x,y,gx,gy);
534
535 mStartCellX = gx;
536 mStartCellY = gy;
537 mCurrentCellX = gx;
538 mCurrentCellY = gy;
539
540 // Store coordinates of old selection
541 int selectionX = mSelectionCellX * mGridSpacingX;
542 int selectionYTop = mSelectionYTop;
543 int selectionHeight = mSelectionHeight;
544
545 // Store new selection
546 mSelectionCellX = gx;
547 mSelectionYTop = gy * mGridSpacingY;
548 mSelectionHeight = mGridSpacingY;
549
550 // Clear old selection
551 repaintContents( selectionX, selectionYTop,
552 mGridSpacingX, selectionHeight,false );
553
554 // Paint new selection
555 // repaintContents( mSelectionCellX * mGridSpacingX, mSelectionYTop,
556 // mGridSpacingX, mSelectionHeight );
557}
558
559void KOAgenda::performSelectAction(QPoint viewportPos)
560{
561 int x,y;
562 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
563 int gx,gy;
564 contentsToGrid(x,y,gx,gy);
565
566 QPoint clipperPos = clipper()->
567 mapFromGlobal(viewport()->mapToGlobal(viewportPos));
568
569 // Scroll if cursor was moved to upper or lower end of agenda.
570 if (clipperPos.y() < mScrollBorderWidth) {
571 mScrollUpTimer.start(mScrollDelay);
572 } else if (visibleHeight() - clipperPos.y() <
573 mScrollBorderWidth) {
574 mScrollDownTimer.start(mScrollDelay);
575 } else {
576 mScrollUpTimer.stop();
577 mScrollDownTimer.stop();
578 }
579
580 if ( gy > mCurrentCellY ) {
581 mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop;
582
583#if 0
584 // FIXME: Repaint only the newly selected region
585 repaintContents( mSelectionCellX * mGridSpacingX,
586 mCurrentCellY + mGridSpacingY,
587 mGridSpacingX,
588 mSelectionHeight - ( gy - mCurrentCellY - 1 ) * mGridSpacingY );
589#else
590 repaintContents( (KOGlobals::self()->reverseLayout() ?
591 mColumns - 1 - mSelectionCellX : mSelectionCellX) *
592 mGridSpacingX, mSelectionYTop,
593 mGridSpacingX, mSelectionHeight , false);
594#endif
595
596 mCurrentCellY = gy;
597 } else if ( gy < mCurrentCellY ) {
598 if ( gy >= mStartCellY ) {
599 int selectionHeight = mSelectionHeight;
600 mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop;
601
602 repaintContents( (KOGlobals::self()->reverseLayout() ?
603 mColumns - 1 - mSelectionCellX : mSelectionCellX) *
604 mGridSpacingX, mSelectionYTop,
605 mGridSpacingX, selectionHeight,false );
606
607 mCurrentCellY = gy;
608 } else {
609 }
610 }
611}
612
613void KOAgenda::endSelectAction()
614{
615 mActionType = NOP;
616 mScrollUpTimer.stop();
617 mScrollDownTimer.stop();
618
619 emit newTimeSpanSignal(mStartCellX,mStartCellY,mCurrentCellX,mCurrentCellY);
620}
621
622void KOAgenda::startItemAction(QPoint viewportPos)
623{
624 int x,y;
625 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
626 int gx,gy;
627 contentsToGrid(x,y,gx,gy);
628
629 mStartCellX = gx;
630 mStartCellY = gy;
631 mCurrentCellX = gx;
632 mCurrentCellY = gy;
633
634 if (mAllDayMode) {
635 int gridDistanceX = (x - gx * mGridSpacingX);
636 if (gridDistanceX < mResizeBorderWidth &&
637 mActionItem->cellX() == mCurrentCellX) {
638 mActionType = RESIZELEFT;
639 setCursor(sizeHorCursor);
640 } else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
641 mActionItem->cellXWidth() == mCurrentCellX) {
642 mActionType = RESIZERIGHT;
643 setCursor(sizeHorCursor);
644 } else {
645 mActionType = MOVE;
646 mActionItem->startMove();
647 setCursor(sizeAllCursor);
648 }
649 } else {
650 int gridDistanceY = (y - gy * mGridSpacingY);
651 bool allowResize = ( mActionItem->incidence()->type() != "Todo" );
652 if (allowResize && gridDistanceY < mResizeBorderWidth &&
653 mActionItem->cellYTop() == mCurrentCellY &&
654 !mActionItem->firstMultiItem()) {
655 mActionType = RESIZETOP;
656 setCursor(sizeVerCursor);
657 } else if (allowResize &&(mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
658 mActionItem->cellYBottom() == mCurrentCellY &&
659 !mActionItem->lastMultiItem()) {
660 mActionType = RESIZEBOTTOM;
661 setCursor(sizeVerCursor);
662 } else {
663 mActionType = MOVE;
664 mActionItem->startMove();
665 setCursor(sizeAllCursor);
666 }
667 }
668}
669
670void KOAgenda::performItemAction(QPoint viewportPos)
671{
672// kdDebug() << "viewportPos: " << viewportPos.x() << "," << viewportPos.y() << endl;
673// QPoint point = viewport()->mapToGlobal(viewportPos);
674// kdDebug() << "Global: " << point.x() << "," << point.y() << endl;
675// point = clipper()->mapFromGlobal(point);
676// kdDebug() << "clipper: " << point.x() << "," << point.y() << endl;
677// kdDebug() << "visible height: " << visibleHeight() << endl;
678 int x,y;
679 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
680// kdDebug() << "contents: " << x << "," << y << "\n" << endl;
681 int gx,gy;
682 contentsToGrid(x,y,gx,gy);
683 QPoint clipperPos = clipper()->
684 mapFromGlobal(viewport()->mapToGlobal(viewportPos));
685
686 // Cursor left active agenda area.
687 // This starts a drag.
688 if ( /*clipperPos.y() < 0 || clipperPos.y() > visibleHeight() ||*/
689 clipperPos.x() < 0 || clipperPos.x() > visibleWidth() ) {
690 if ( mActionType == MOVE ) {
691 mScrollUpTimer.stop();
692 mScrollDownTimer.stop();
693 mActionItem->resetMove();
694 placeSubCells( mActionItem );
695 // emit startDragSignal( mActionItem->incidence() );
696 setCursor( arrowCursor );
697 mActionItem = 0;
698 mActionType = NOP;
699 mItemMoved = 0;
700 return;
701 }
702 } else {
703 switch ( mActionType ) {
704 case MOVE:
705 setCursor( sizeAllCursor );
706 break;
707 case RESIZETOP:
708 case RESIZEBOTTOM:
709 setCursor( sizeVerCursor );
710 break;
711 case RESIZELEFT:
712 case RESIZERIGHT:
713 setCursor( sizeHorCursor );
714 break;
715 default:
716 setCursor( arrowCursor );
717 }
718 }
719
720 // Scroll if item was moved to upper or lower end of agenda.
721 if (clipperPos.y() < mScrollBorderWidth) {
722 mScrollUpTimer.start(mScrollDelay);
723 } else if (visibleHeight() - clipperPos.y() <
724 mScrollBorderWidth) {
725 mScrollDownTimer.start(mScrollDelay);
726 } else {
727 mScrollUpTimer.stop();
728 mScrollDownTimer.stop();
729 }
730
731 // Move or resize item if necessary
732 if (mCurrentCellX != gx || mCurrentCellY != gy) {
733 mItemMoved = true;
734 mActionItem->raise();
735 if (mActionType == MOVE) {
736 // Move all items belonging to a multi item
737 KOAgendaItem *moveItem = mActionItem->firstMultiItem();
738 bool isMultiItem = (moveItem || mActionItem->lastMultiItem());
739 if (!moveItem) moveItem = mActionItem;
740 while (moveItem) {
741 int dy;
742 if (isMultiItem) dy = 0;
743 else dy = gy - mCurrentCellY;
744 moveItem->moveRelative(gx - mCurrentCellX,dy);
745 int x,y;
746 gridToContents(moveItem->cellX(),moveItem->cellYTop(),x,y);
747 moveItem->resize(mGridSpacingX * moveItem->cellWidth(),
748 mGridSpacingY * moveItem->cellHeight());
749 moveChild(moveItem,x,y);
750 moveItem = moveItem->nextMultiItem();
751 }
752 } else if (mActionType == RESIZETOP) {
753 if (mCurrentCellY <= mActionItem->cellYBottom()) {
754 mActionItem->expandTop(gy - mCurrentCellY);
755 mActionItem->resize(mActionItem->width(),
756 mGridSpacingY * mActionItem->cellHeight());
757 int x,y;
758 gridToContents(mCurrentCellX,mActionItem->cellYTop(),x,y);
759 //moveChild(mActionItem,childX(mActionItem),y);
760 QScrollView::moveChild( mActionItem,childX(mActionItem),y );
761 }
762 } else if (mActionType == RESIZEBOTTOM) {
763 if (mCurrentCellY >= mActionItem->cellYTop()) {
764 mActionItem->expandBottom(gy - mCurrentCellY);
765 mActionItem->resize(mActionItem->width(),
766 mGridSpacingY * mActionItem->cellHeight());
767 }
768 } else if (mActionType == RESIZELEFT) {
769 if (mCurrentCellX <= mActionItem->cellXWidth()) {
770 mActionItem->expandLeft(gx - mCurrentCellX);
771 mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(),
772 mActionItem->height());
773 int x,y;
774 gridToContents(mActionItem->cellX(),mActionItem->cellYTop(),x,y);
775 moveChild(mActionItem,x,childY(mActionItem));
776 }
777 } else if (mActionType == RESIZERIGHT) {
778 if (mCurrentCellX >= mActionItem->cellX()) {
779 mActionItem->expandRight(gx - mCurrentCellX);
780 mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(),
781 mActionItem->height());
782 }
783 }
784 mCurrentCellX = gx;
785 mCurrentCellY = gy;
786 }
787}
788
789void KOAgenda::endItemAction()
790{
791
792 if ( mItemMoved ) {
793 KOAgendaItem *placeItem = mActionItem->firstMultiItem();
794 if ( !placeItem ) {
795 placeItem = mActionItem;
796 }
797 if ( placeItem->incidence()->recurrence()->doesRecur() ) {
798 Incidence* oldInc = placeItem->incidence();
799 placeItem->recreateIncidence();
800 emit addToCalSignal(placeItem->incidence(), oldInc );
801 }
802 int type = mActionType;
803 if ( mAllDayMode )
804 type = -1;
805 KOAgendaItem *modifiedItem = placeItem;
806 //emit itemModified( placeItem, mActionType /*KOGlobals::EVENTEDITED */);
807 QPtrList<KOAgendaItem> oldconflictItems ;//= placeItem->conflictItems();
808 KOAgendaItem *item;
809
810 if ( placeItem->incidence()->type() == "Todo" ) {
811 mSelectedItem = 0;
812 //qDebug("todo %d %d %d ", mCurrentCellX, modifiedItem->cellX() ,modifiedItem->cellXWidth());
813 modifiedItem->mLastMoveXPos = mCurrentCellX;
814 emit itemModified( modifiedItem, mActionType );
815 }
816 else {
817#if 0
818 for ( item=oldconflictItems.first(); item != 0;
819 item=oldconflictItems.next() ) {
820 placeSubCells(item);
821 }
822 while ( placeItem ) {
823 //qDebug("placeItem %s ", placeItem->incidence()->summary().latin1());
824 placeSubCells( placeItem );
825 placeItem = placeItem->nextMultiItem();
826 }
827#endif
828
829 globalFlagBlockAgendaItemPaint = 1;
830 for ( item=oldconflictItems.first(); item != 0;
831 item=oldconflictItems.next() ) {
832 placeSubCells(item);
833 }
834 while ( placeItem ) {
835 //qDebug("placeItem %s ", placeItem->incidence()->summary().latin1());
836 oldconflictItems = placeItem->conflictItems();
837 for ( item=oldconflictItems.first(); item != 0;
838 item=oldconflictItems.next() ) {
839 placeSubCells(item);
840 }
841 placeSubCells( placeItem );
842 placeItem = placeItem->nextMultiItem();
843 }
844 globalFlagBlockAgendaItemPaint = 0;
845 for ( item=oldconflictItems.first(); item != 0;
846 item=oldconflictItems.next() ) {
847 globalFlagBlockAgendaItemUpdate = 0;
848 item->repaintMe();
849 globalFlagBlockAgendaItemUpdate = 1;
850 item->repaint( false );
851 }
852 placeItem = modifiedItem;
853
854 while ( placeItem ) {
855 //qDebug("placeItem %s ", placeItem->incidence()->summary().latin1());
856 globalFlagBlockAgendaItemUpdate = 0;
857 placeItem->repaintMe();
858 globalFlagBlockAgendaItemUpdate = 1;
859 placeItem->repaint(false);
860 placeItem = placeItem->nextMultiItem();
861 }
862 emit itemModified( modifiedItem, mActionType );
863
864
865 placeItem = modifiedItem;
866 while ( placeItem ) {
867 oldconflictItems = placeItem->conflictItems();
868 for ( item=oldconflictItems.first(); item != 0;
869 item=oldconflictItems.next() ) {
870 placeSubCells(item);
871 }
872 placeSubCells( placeItem );
873 placeItem = placeItem->nextMultiItem();
874
875 }
876 placeItem = modifiedItem;
877 while ( placeItem ) {
878 oldconflictItems = placeItem->conflictItems();
879 for ( item=oldconflictItems.first(); item != 0;
880 item=oldconflictItems.next() ) {
881 globalFlagBlockAgendaItemUpdate = 0;
882 item->repaintMe();
883 globalFlagBlockAgendaItemUpdate = 1;
884 item->repaint(false);
885 }
886 placeItem = placeItem->nextMultiItem();
887 }
888 /*
889
890 oldconflictItems = modifiedItem->conflictItems();
891 for ( item=oldconflictItems.first(); item != 0;
892 item=oldconflictItems.next() ) {
893 globalFlagBlockAgendaItemUpdate = 0;
894 item->paintMe(false);
895 globalFlagBlockAgendaItemUpdate = 1;
896 item->repaint(false);
897 }
898 */
899
900
901 }
902
903 }
904
905 mScrollUpTimer.stop();
906 mScrollDownTimer.stop();
907 setCursor( arrowCursor );
908 mActionItem = 0;
909 mActionType = NOP;
910 mItemMoved = 0;
911
912}
913
914void KOAgenda::setNoActionCursor(KOAgendaItem *moveItem,QPoint viewportPos)
915{
916// kdDebug() << "viewportPos: " << viewportPos.x() << "," << viewportPos.y() << endl;
917// QPoint point = viewport()->mapToGlobal(viewportPos);
918// kdDebug() << "Global: " << point.x() << "," << point.y() << endl;
919// point = clipper()->mapFromGlobal(point);
920// kdDebug() << "clipper: " << point.x() << "," << point.y() << endl;
921
922 int x,y;
923 viewportToContents(viewportPos.x(),viewportPos.y(),x,y);
924// kdDebug() << "contents: " << x << "," << y << "\n" << endl;
925 int gx,gy;
926 contentsToGrid(x,y,gx,gy);
927
928 // Change cursor to resize cursor if appropriate
929 if (mAllDayMode) {
930 int gridDistanceX = (x - gx * mGridSpacingX);
931 if (gridDistanceX < mResizeBorderWidth &&
932 moveItem->cellX() == gx) {
933 setCursor(sizeHorCursor);
934 } else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth &&
935 moveItem->cellXWidth() == gx) {
936 setCursor(sizeHorCursor);
937 } else {
938 setCursor(arrowCursor);
939 }
940 } else {
941 int gridDistanceY = (y - gy * mGridSpacingY);
942 if (gridDistanceY < mResizeBorderWidth &&
943 moveItem->cellYTop() == gy &&
944 !moveItem->firstMultiItem()) {
945 setCursor(sizeVerCursor);
946 } else if ((mGridSpacingY - gridDistanceY) < mResizeBorderWidth &&
947 moveItem->cellYBottom() == gy &&
948 !moveItem->lastMultiItem()) {
949 setCursor(sizeVerCursor);
950 } else {
951 setCursor(arrowCursor);
952 }
953 }
954}
955
956
957/*
958 Place item in cell and take care that multiple items using the same cell do
959 not overlap. This method is not yet optimal. It doesn´t use the maximum space
960 it can get in all cases.
961 At the moment the method has a bug: When an item is placed only the sub cell
962 widths of the items are changed, which are within the Y region the item to
963 place spans. When the sub cell width change of one of this items affects a
964 cell, where other items are, which do not overlap in Y with the item to place,
965 the display gets corrupted, although the corruption looks quite nice.
966*/
967void KOAgenda::placeSubCells(KOAgendaItem *placeItem)
968{
969
970 QPtrList<KOAgendaItem> conflictItems;
971 int maxSubCells = 0;
972 QIntDict<KOAgendaItem> subCellDict(5);
973
974 KOAgendaItem *item;
975 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
976 if (item != placeItem) {
977 if (placeItem->cellX() <= item->cellXWidth() &&
978 placeItem->cellXWidth() >= item->cellX()) {
979 if ((placeItem->cellYTop() <= item->cellYBottom()) &&
980 (placeItem->cellYBottom() >= item->cellYTop())) {
981 conflictItems.append(item);
982 if (item->subCells() > maxSubCells)
983 maxSubCells = item->subCells();
984 subCellDict.insert(item->subCell(),item);
985 }
986 }
987 }
988 }
989
990 if (conflictItems.count() > 0) {
991 // Look for unused sub cell and insert item
992 int i;
993 for(i=0;i<maxSubCells;++i) {
994 if (!subCellDict.find(i)) {
995 placeItem->setSubCell(i);
996 break;
997 }
998 }
999 if (i == maxSubCells) {
1000 placeItem->setSubCell(maxSubCells);
1001 maxSubCells++; // add new item to number of sub cells
1002 }
1003
1004 // Prepare for sub cell geometry adjustment
1005 int newSubCellWidth;
1006 if (mAllDayMode) newSubCellWidth = mGridSpacingY / maxSubCells;
1007 else newSubCellWidth = mGridSpacingX / maxSubCells;
1008 conflictItems.append(placeItem);
1009
1010
1011 // Adjust sub cell geometry of all items
1012 for ( item=conflictItems.first(); item != 0;
1013 item=conflictItems.next() ) {
1014 item->setSubCells(maxSubCells);
1015 if (mAllDayMode) {
1016 item->resize(item->cellWidth() * mGridSpacingX, newSubCellWidth);
1017 } else {
1018 item->resize(newSubCellWidth, item->cellHeight() * mGridSpacingY);
1019 }
1020 int x,y;
1021 gridToContents(item->cellX(),item->cellYTop(),x,y);
1022 if (mAllDayMode) {
1023 y += item->subCell() * newSubCellWidth;
1024 } else {
1025 x += item->subCell() * newSubCellWidth;
1026 }
1027 moveChild(item,x,y);
1028 // qDebug("moveChild %s %d %d ", item->incidence()->summary().latin1() ,x,y);
1029 //item->updateItem();
1030 }
1031
1032 } else {
1033 placeItem->setSubCell(0);
1034 placeItem->setSubCells(1);
1035 if (mAllDayMode) placeItem->resize(placeItem->width(),mGridSpacingY);
1036 else placeItem->resize(mGridSpacingX,placeItem->height());
1037 int x,y;
1038 gridToContents(placeItem->cellX(),placeItem->cellYTop(),x,y);
1039 moveChild(placeItem,x,y);
1040 }
1041 placeItem->setConflictItems(conflictItems);
1042 // for ( item=conflictItems.first(); item != 0;
1043// item=conflictItems.next() ) {
1044// //item->updateItem();
1045// //qDebug("xxx item->updateItem() %s %d %d", item->incidence()->summary().latin1(),item->x(), item->y() );
1046// }
1047// placeItem->updateItem();
1048}
1049
1050void KOAgenda::drawContents(QPainter* p, int cx, int cy, int cw, int ch)
1051{
1052 if ( globalFlagBlockAgenda )
1053 return;
1054 //qDebug("KOAgenda::drawContents ");
1055 if ( mCurPixWid != contentsWidth() || mCurPixHei != contentsHeight() )
1056 ;//drawContentsToPainter();
1057
1058 QPaintDevice* pd = p->device();
1059 p->end();
1060 int vx, vy;
1061 int selectionX = KOGlobals::self()->reverseLayout() ?
1062 (mColumns - 1 - mSelectionCellX) * mGridSpacingX :
1063 mSelectionCellX * mGridSpacingX;
1064 contentsToViewport ( cx, cy, vx,vy);
1065 // qDebug(" %d %d %d %d ", cx, cy, cw,ch) ;
1066 if ( !(selectionX == cx && cy == mSelectionYTop && cw ==mGridSpacingX && ch == mSelectionHeight ) )
1067 bitBlt ( pd, vx, vy, &mPaintPixmap, cx, cy, cw, ch ,CopyROP);
1068
1069 if ( mSelectionHeight > 0 ) {
1070 //qDebug("---- %d %d %d %d ", selectionX, mSelectionYTop, mGridSpacingX, mSelectionHeight );
1071 if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
1072 ( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) {
1073 contentsToViewport ( selectionX, mSelectionYTop, vx,vy);
1074 bitBlt ( pd, vx+1, vy, &mHighlightPixmap, 0, mSelectionYTop, mGridSpacingX-1, mSelectionHeight ,CopyROP);
1075 }
1076 }
1077 //qDebug("btbl ");
1078 p->begin( pd );
1079 //qDebug("end ");
1080}
1081
1082void KOAgenda::finishUpdate()
1083{
1084
1085 KOAgendaItem *item;
1086 globalFlagBlockAgendaItemPaint = 1;
1087 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1088 if ( !item->isVisible() )
1089 item->show();
1090
1091 }
1092 globalFlagBlockAgendaItemUpdate = 0;
1093 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1094 item->repaintMe( );
1095 }
1096 globalFlagBlockAgendaItemUpdate = 1;
1097 qApp->processEvents();
1098 globalFlagBlockAgendaItemPaint = 0;
1099 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1100 item->repaint( false );
1101 }
1102
1103}
1104
1105/*
1106 Draw grid in the background of the agenda.
1107*/
1108void KOAgenda::drawContentsToPainter( QPainter* paint, bool backgroundOnly )// int cx, int cy, int cw, int ch)
1109{
1110
1111
1112 if ( ! mGridSpacingX || ! mGridSpacingY ||! mHolidayMask )
1113 return;
1114 if ( globalFlagBlockAgenda > 1 && globalFlagBlockAgenda < 4 )
1115 return;
1116 int cx = 0, cy = 0, cw = contentsWidth(), ch = contentsHeight();
1117 if ( ch < 1 )
1118 ch = 1;
1119 if ( mPaintPixmap.width() < contentsWidth()+42 || mPaintPixmap.height() < ch ) {
1120 mPaintPixmap.resize( contentsWidth()+42, ch );
1121 }
1122 mCurPixWid = contentsWidth();
1123 mCurPixHei = ch;
1124 if ( mHighlightPixmap.width() < mGridSpacingX-1 || mHighlightPixmap.height() < ch ) {
1125 mHighlightPixmap.resize( mGridSpacingX-1, ch );
1126 mHighlightPixmap.fill ( KOPrefs::instance()->mHighlightColor );
1127 }
1128 mPixPainter.begin( &mPaintPixmap) ;
1129 //qDebug("wid %d hei %d ",mPaintPixmap.width(),mPaintPixmap.height() );
1130 QPainter * p ;
1131 if (paint == 0) {
1132 mPaintPixmap.fill(KOPrefs::instance()->mAgendaBgColor);
1133 p = &mPixPainter;
1134 }
1135 else
1136 p = paint ;
1137 // qDebug("++++++KOAgenda::drawContentsTo Painter %d %d %d %d ", cx, cy, cw, ch);
1138
1139 //--cx;++cw;
1140 int lGridSpacingY = mGridSpacingY*2;
1141 int selDay;
1142 if ( !backgroundOnly )
1143 for ( selDay = 0; selDay < mSelectedDates.count(); ++selDay)
1144 {
1145 if ( mSelectedDates[selDay] == QDateTime::currentDateTime ().date() && KOPrefs::instance()->mHighlightCurrentDay) {
1146 int x1 = cx;
1147 int y1 = 0;
1148 if (y1 < cy) y1 = cy;
1149 int x2 = cx+cw-1;
1150 int y2 = contentsHeight();
1151 if (y2 > cy+ch-1) y2=cy+ch-1;
1152 if (x2 >= x1 && y2 >= y1) {
1153 int gxStart = selDay;
1154 int gxEnd = gxStart ;
1155 int xStart = KOGlobals::self()->reverseLayout() ?
1156 (mColumns - 1 - gxStart)*mGridSpacingX :
1157 gxStart*mGridSpacingX;
1158 if (xStart < x1) xStart = x1;
1159 int xEnd = KOGlobals::self()->reverseLayout() ?
1160 (mColumns - gxStart)*mGridSpacingX-1 :
1161 (gxStart+1)*mGridSpacingX-1;
1162 if (xEnd > x2) xEnd = x2;
1163 if ( KOPrefs::instance()->mUseHighlightLightColor )
1164 p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
1165 KOPrefs::instance()->mAgendaBgColor.light());
1166 else
1167 p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
1168 KOPrefs::instance()->mAgendaBgColor.dark());
1169
1170 }
1171 }
1172 }
1173 // Highlight working hours
1174
1175 if ( !backgroundOnly )
1176 if (mWorkingHoursEnable) {
1177 int x1 = cx;
1178 int y1 = mWorkingHoursYTop;
1179 if (y1 < cy) y1 = cy;
1180 int x2 = cx+cw-1;
1181 // int x2 = mGridSpacingX * 5 - 1;
1182 // if (x2 > cx+cw-1) x2 = cx + cw - 1;
1183 int y2 = mWorkingHoursYBottom;
1184 if (y2 > cy+ch-1) y2=cy+ch-1;
1185
1186 if (x2 >= x1 && y2 >= y1) {
1187 // qDebug("x1 %d mGridSpacingX %d ", x1, mGridSpacingX );
1188 int gxStart = x1/mGridSpacingX;
1189 int gxEnd = x2/mGridSpacingX;
1190 while(gxStart <= gxEnd) {
1191 if (gxStart < int(mHolidayMask->count()) &&
1192 !mHolidayMask->at(gxStart)) {
1193 int xStart = KOGlobals::self()->reverseLayout() ?
1194 (mColumns - 1 - gxStart)*mGridSpacingX :
1195 gxStart*mGridSpacingX;
1196 if (xStart < x1) xStart = x1;
1197 int xEnd = KOGlobals::self()->reverseLayout() ?
1198 (mColumns - gxStart)*mGridSpacingX-1 :
1199 (gxStart+1)*mGridSpacingX-1;
1200 if (xEnd > x2) xEnd = x2;
1201 if ( mSelectedDates[gxStart] == QDateTime::currentDateTime ().date()&& KOPrefs::instance()->mHighlightCurrentDay ) {
1202 if ( KOPrefs::instance()->mUseHighlightLightColor )
1203 p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
1204 KOPrefs::instance()->mWorkingHoursColor.light());
1205 else
1206 p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
1207 KOPrefs::instance()->mWorkingHoursColor.dark());
1208 } else {
1209 p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1,
1210 KOPrefs::instance()->mWorkingHoursColor);
1211 }
1212 }
1213 ++gxStart;
1214 }
1215 }
1216 }
1217 /*
1218 int selectionX = KOGlobals::self()->reverseLayout() ?
1219 (mColumns - 1 - mSelectionCellX) * mGridSpacingX :
1220 mSelectionCellX * mGridSpacingX;
1221
1222 // Draw selection
1223 if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) &&
1224 ( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) {
1225 // TODO: paint only part within cx,cy,cw,ch
1226 p->fillRect( selectionX, mSelectionYTop, mGridSpacingX,
1227 mSelectionHeight, KOPrefs::instance()->mHighlightColor );
1228 }
1229 */
1230 // Draw vertical lines of grid
1231
1232 int x = ((int)(cx/mGridSpacingX))*mGridSpacingX;
1233 if ( mGridSpacingX > 0 ) {
1234 while (x < cx + cw) {
1235 p->drawLine(x,cy,x,cy+ch);
1236 x+=mGridSpacingX;
1237 }
1238 }
1239 // Draw horizontal lines of grid
1240 int y = ((int)(cy/lGridSpacingY))*lGridSpacingY;
1241 if ( lGridSpacingY > 0 ) {
1242 while (y < cy + ch) {
1243 p->drawLine(cx,y,cx+cw,y);
1244 y+=lGridSpacingY;
1245 }
1246 }
1247 mPixPainter.end() ;
1248}
1249
1250/*
1251 Convert srcollview contents coordinates to agenda grid coordinates.
1252*/
1253void KOAgenda::contentsToGrid (int x, int y, int& gx, int& gy)
1254{
1255 gx = KOGlobals::self()->reverseLayout() ? mColumns - 1 - x/mGridSpacingX :
1256 x/mGridSpacingX;
1257 gy = y/mGridSpacingY;
1258}
1259
1260/*
1261 Convert agenda grid coordinates to scrollview contents coordinates.
1262*/
1263void KOAgenda::gridToContents (int gx, int gy, int& x, int& y)
1264{
1265 x = KOGlobals::self()->reverseLayout() ? (mColumns - 1 - gx)*mGridSpacingX:
1266 gx*mGridSpacingX;
1267 y = gy*mGridSpacingY;
1268}
1269
1270
1271/*
1272 Return Y coordinate corresponding to time. Coordinates are rounded to fit into
1273 the grid.
1274*/
1275int KOAgenda::timeToY(const QTime &time)
1276{
1277 int minutesPerCell = 24 * 60 / mRows;
1278 int timeMinutes = time.hour() * 60 + time.minute();
1279 int Y = (timeMinutes + (minutesPerCell / 2)) / minutesPerCell;
1280 return Y;
1281}
1282
1283
1284/*
1285 Return time corresponding to cell y coordinate. Coordinates are rounded to
1286 fit into the grid.
1287*/
1288QTime KOAgenda::gyToTime(int gy)
1289{
1290
1291 int secondsPerCell = 24 * 60 * 60/ mRows;
1292
1293 int timeSeconds = secondsPerCell * gy;
1294
1295 QTime time( 0, 0, 0 );
1296 if ( timeSeconds < 24 * 60 * 60 ) {
1297 time = time.addSecs(timeSeconds);
1298 } else {
1299 time.setHMS( 23, 59, 59 );
1300 }
1301
1302 return time;
1303}
1304
1305void KOAgenda::setStartHour(int startHour)
1306{
1307 int startCell = startHour * mRows / 24;
1308 setContentsPos(0,startCell * gridSpacingY());
1309}
1310void KOAgenda::hideUnused()
1311{
1312 // experimental only
1313 // return;
1314 KOAgendaItem *item;
1315 for ( item=mUnusedItems.first(); item != 0; item=mUnusedItems.next() ) {
1316 item->hide();
1317 }
1318}
1319
1320
1321KOAgendaItem *KOAgenda::getNewItem(Incidence * event,QDate qd, QWidget* view)
1322{
1323
1324 KOAgendaItem *fi;
1325 for ( fi=mUnusedItems.first(); fi != 0; fi=mUnusedItems.next() ) {
1326 if ( fi->incidence() == event ) {
1327 mUnusedItems.remove();
1328 fi->init( event, qd );
1329 return fi;
1330 }
1331 }
1332 fi=mUnusedItems.first();
1333 if ( fi ) {
1334 mUnusedItems.remove();
1335 fi->init( event, qd );
1336 return fi;
1337 }
1338 // qDebug("new KOAgendaItem ");
1339
1340 KOAgendaItem* agendaItem = new KOAgendaItem( event, qd, view, mAllDayMode );
1341 agendaItem->installEventFilter(this);
1342 addChild(agendaItem,0,0);
1343 return agendaItem;
1344}
1345KOAgendaItem * KOAgenda::getItemForTodo ( Todo * todo )
1346{
1347 KOAgendaItem *item;
1348 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1349 if ( item->incidence() == todo ) {
1350 mItems.remove();
1351 return item;
1352 }
1353 }
1354 return 0;
1355}
1356
1357
1358void KOAgenda::updateTodo( Todo * todo, int days, bool remove)
1359{
1360
1361 KOAgendaItem *item;
1362 item = getItemForTodo ( todo );
1363 //qDebug("KOAgenda::updateTodo %d %d %d %d", this, todo, days, remove);
1364 if ( item ) {
1365 blockSignals( true );
1366 //qDebug("item found ");
1367 item->hide();
1368 item->setCellX(-2, -1 );
1369 item->select(false);
1370 mUnusedItems.append( item );
1371 mItems.remove( item );
1372 QPtrList<KOAgendaItem> oldconflictItems = item->conflictItems();
1373 KOAgendaItem *itemit;
1374 //globalFlagBlockAgendaItemPaint = 1;
1375 for ( itemit=oldconflictItems.first(); itemit != 0;
1376 itemit=oldconflictItems.next() ) {
1377 if ( itemit != item )
1378 placeSubCells(itemit);
1379 }
1380 qApp->processEvents();
1381 //globalFlagBlockAgendaItemPaint = 0;
1382 for ( itemit=oldconflictItems.first(); itemit != 0;
1383 itemit=oldconflictItems.next() ) {
1384 globalFlagBlockAgendaItemUpdate = 0;
1385 if ( itemit != item )
1386 itemit->repaintMe();
1387 globalFlagBlockAgendaItemUpdate = 1;
1388 itemit->repaint();
1389 }
1390 blockSignals( false );
1391 }
1392 if ( remove ) {
1393 //qDebug("remove****************************************** ");
1394 return;
1395 }
1396 //qDebug("updateTodo+++++++++++++++++++++++++++++++++++++ ");
1397 bool overdue = (!todo->isCompleted()) && (todo->dtDue() < QDate::currentDate())&& ( KOPrefs::instance()->mShowTodoInAgenda );
1398 QDate currentDate;
1399 if ( overdue ) {
1400 currentDate = QDate::currentDate();
1401 days += todo->dtDue().date().daysTo( currentDate );
1402 }
1403 else
1404 currentDate = todo->dtDue().date();
1405
1406 if ( todo->doesFloat() || overdue ) {
1407 if ( ! mAllDayMode ) return;
1408 // aldayagenda
1409 globalFlagBlockAgendaItemPaint = 1;
1410 item = insertAllDayItem(todo, currentDate,days, days);
1411 item->show();
1412
1413 }
1414 else {
1415 if ( mAllDayMode ) return;
1416 // mAgenda
1417 globalFlagBlockAgendaItemPaint = 1;
1418 int endY = timeToY(todo->dtDue().time()) - 1;
1419 int hi = 12/KOPrefs::instance()->mHourSize;
1420 int startY = endY - 1-hi;
1421 item = insertItem(todo,currentDate,days,startY,endY);
1422 item->show();
1423 }
1424 qApp->processEvents();
1425 globalFlagBlockAgendaItemPaint = 0;
1426 QPtrList<KOAgendaItem> oldconflictItems = item->conflictItems();
1427 KOAgendaItem *itemit;
1428 for ( itemit=oldconflictItems.first(); itemit != 0;
1429 itemit=oldconflictItems.next() ) {
1430 globalFlagBlockAgendaItemUpdate = 0;
1431 itemit->repaintMe();
1432 globalFlagBlockAgendaItemUpdate = 1;
1433 itemit->repaint();
1434 }
1435 globalFlagBlockAgendaItemUpdate = 0;
1436 item->repaintMe();
1437 globalFlagBlockAgendaItemUpdate = 1;
1438 item->repaint();
1439}
1440/*
1441 Insert KOAgendaItem into agenda.
1442*/
1443KOAgendaItem *KOAgenda::insertItem (Incidence *event,QDate qd,int X,int YTop,int YBottom)
1444{
1445 //kdDebug() << "KOAgenda::insertItem:" << event->summary() << "-" << qd.toString() << " ;top, bottom:" << YTop << "," << YBottom << endl;
1446
1447 if (mAllDayMode) {
1448 kdDebug() << "KOAgenda: calling insertItem in all-day mode is illegal." << endl;
1449 return 0;
1450 }
1451
1452 KOAgendaItem *agendaItem = getNewItem(event,qd,viewport());
1453 //agendaItem->setFrameStyle(WinPanel|Raised);
1454
1455 int YSize = YBottom - YTop + 1;
1456 if (YSize < 0) {
1457 kdDebug() << "KOAgenda::insertItem(): Text: " << agendaItem->text() << " YSize<0" << endl;
1458 YSize = 1;
1459 }
1460 int iheight = mGridSpacingY * YSize;
1461
1462 agendaItem->resize(mGridSpacingX,iheight );
1463 agendaItem->setCellXY(X,YTop,YBottom);
1464 agendaItem->setCellXWidth(X);
1465
1466 //addChild(agendaItem,X*mGridSpacingX,YTop*mGridSpacingY);
1467 mItems.append(agendaItem);
1468
1469 placeSubCells(agendaItem);
1470
1471 //agendaItem->show();
1472
1473 marcus_bains();
1474
1475 return agendaItem;
1476}
1477
1478
1479/*
1480 Insert all-day KOAgendaItem into agenda.
1481*/
1482KOAgendaItem *KOAgenda::insertAllDayItem (Incidence *event,QDate qd,int XBegin,int XEnd)
1483{
1484 if (!mAllDayMode) {
1485 return 0;
1486 }
1487
1488 KOAgendaItem *agendaItem = getNewItem(event,qd,viewport());
1489
1490 agendaItem->setCellXY(XBegin,0,0);
1491 agendaItem->setCellXWidth(XEnd);
1492 agendaItem->resize(mGridSpacingX * agendaItem->cellWidth(),mGridSpacingY);
1493
1494 //addChild(agendaItem,XBegin*mGridSpacingX,0);
1495 mItems.append(agendaItem);
1496
1497 placeSubCells(agendaItem);
1498
1499 //agendaItem->show();
1500
1501 return agendaItem;
1502}
1503
1504
1505void KOAgenda::insertMultiItem (Event *event,QDate qd,int XBegin,int XEnd,
1506 int YTop,int YBottom)
1507{
1508 if (mAllDayMode) {
1509 ;
1510 return;
1511 }
1512
1513 int cellX,cellYTop,cellYBottom;
1514 QString newtext;
1515 int width = XEnd - XBegin + 1;
1516 int count = 0;
1517 KOAgendaItem *current = 0;
1518 QPtrList<KOAgendaItem> multiItems;
1519 for (cellX = XBegin;cellX <= XEnd;++cellX) {
1520 if (cellX == XBegin) cellYTop = YTop;
1521 else cellYTop = 0;
1522 if (cellX == XEnd) cellYBottom = YBottom;
1523 else cellYBottom = rows() - 1;
1524 newtext = QString("(%1/%2): ").arg(++count).arg(width);
1525 newtext.append(event->summary());
1526 current = insertItem(event,qd,cellX,cellYTop,cellYBottom);
1527 current->setText(newtext);
1528 multiItems.append(current);
1529 }
1530
1531 KOAgendaItem *next = 0;
1532 KOAgendaItem *last = multiItems.last();
1533 KOAgendaItem *first = multiItems.first();
1534 KOAgendaItem *setFirst,*setLast;
1535 current = first;
1536 while (current) {
1537 next = multiItems.next();
1538 if (current == first) setFirst = 0;
1539 else setFirst = first;
1540 if (current == last) setLast = 0;
1541 else setLast = last;
1542
1543 current->setMultiItem(setFirst,next,setLast);
1544 current = next;
1545 }
1546
1547 marcus_bains();
1548}
1549
1550
1551//QSizePolicy KOAgenda::sizePolicy() const
1552//{
1553 // Thought this would make the all-day event agenda minimum size and the
1554 // normal agenda take the remaining space. But it doesn´t work. The QSplitter
1555 // don´t seem to think that an Expanding widget needs more space than a
1556 // Preferred one.
1557 // But it doesn´t hurt, so it stays.
1558// if (mAllDayMode) {
1559// return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred);
1560// } else {
1561// return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
1562// }
1563//}
1564void KOAgenda::finishResize ( )
1565{
1566 //qDebug("finishResize+++++++++++++++++++++++++++++++ ( ) ");
1567 if ( globalFlagBlockAgenda == 0 ) {
1568 finishUpdate();
1569 //qDebug("finishUpdate() called ");
1570 }
1571}
1572/*
1573 Overridden from QScrollView to provide proper resizing of KOAgendaItems.
1574*/
1575void KOAgenda::resizeEvent ( QResizeEvent *ev )
1576{
1577
1578 mResizeTimer.start( 150 , true );
1579 computeSizes();
1580 return;
1581
1582}
1583void KOAgenda::computeSizes()
1584{
1585 if ( globalFlagBlockStartup )
1586 return;
1587
1588 if (mAllDayMode) {
1589 mGridSpacingX = (width()-3) / mColumns;
1590 mGridSpacingY = height() - 2 * frameWidth() - 1;
1591 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY + 1);
1592// mGridSpacingY = height();
1593// resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
1594
1595 KOAgendaItem *item;
1596 int subCellWidth;
1597 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1598 subCellWidth = mGridSpacingY / item->subCells();
1599 item->resize(mGridSpacingX * item->cellWidth(),subCellWidth);
1600 moveChild(item,KOGlobals::self()->reverseLayout() ?
1601 (mColumns - 1 - item->cellX()) * mGridSpacingX :
1602 item->cellX() * mGridSpacingX,
1603 item->subCell() * subCellWidth);
1604 }
1605 KOPrefs::instance()->mAllDaySize = mGridSpacingY;
1606 } else {
1607 mGridSpacingX = (width() - verticalScrollBar()->width()-3)/mColumns;
1608 if (height() > mGridSpacingY * mRows + 1 ) {
1609 KOPrefs::instance()->mHourSize = ((height())/mRows)+1;
1610 mGridSpacingY = KOPrefs::instance()->mHourSize ;
1611 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
1612 emit resizedSignal();
1613 } else
1614 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 );
1615 KOAgendaItem *item;
1616 int subCellWidth;
1617
1618 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1619 subCellWidth = mGridSpacingX / item->subCells();
1620 item->resize(subCellWidth,item->height());
1621 moveChild(item,(KOGlobals::self()->reverseLayout() ?
1622 (mColumns - 1 - item->cellX()) * mGridSpacingX :
1623 item->cellX() * mGridSpacingX) +
1624 item->subCell() * subCellWidth,childY(item));
1625 }
1626 }
1627 int cw = contentsWidth();
1628 int ch = contentsHeight();
1629 if ( mAllDayMode ) {
1630 QPixmap* paintPixAll = KOAgendaItem::paintPixAllday();
1631 if ( paintPixAll->width() < cw || paintPixAll->height() < ch )
1632 paintPixAll->resize( cw, ch );
1633 } else {
1634 QPixmap* paintPix = KOAgendaItem::paintPix();
1635 if ( paintPix->width() < cw || paintPix->height() < ch )
1636 KOAgendaItem::resizePixmap( cw , ch );
1637 }
1638
1639 checkScrollBoundaries();
1640 marcus_bains();
1641 drawContentsToPainter();
1642 viewport()->repaint(false);
1643}
1644
1645void KOAgenda::scrollUp()
1646{
1647 scrollBy(0,-mScrollOffset);
1648}
1649
1650
1651void KOAgenda::scrollDown()
1652{
1653 scrollBy(0,mScrollOffset);
1654}
1655
1656void KOAgenda::popupAlarm()
1657{
1658 if (!mClickedItem) {
1659 kdDebug() << "KOAgenda::popupAlarm() called without having a clicked item" << endl;
1660 return;
1661 }
1662// TODO: deal correctly with multiple alarms
1663 Alarm* alarm;
1664 QPtrList<Alarm> list(mClickedItem->incidence()->alarms());
1665 for(alarm=list.first();alarm;alarm=list.next()) {
1666 alarm->toggleAlarm();
1667 }
1668 emit itemModified( mClickedItem , KOGlobals::EVENTEDITED );
1669 mClickedItem->paintMe( true );
1670 mClickedItem->repaint( false );
1671}
1672
1673/*
1674 Calculates the minimum width
1675*/
1676int KOAgenda::minimumWidth() const
1677{
1678 // TODO:: develop a way to dynamically determine the minimum width
1679 int min = 100;
1680
1681 return min;
1682}
1683
1684void KOAgenda::updateConfig()
1685{
1686 if ( viewport()->backgroundColor() != KOPrefs::instance()->mAgendaBgColor)
1687 viewport()->setBackgroundColor(KOPrefs::instance()->mAgendaBgColor);
1688 if ( mAllDayMode ) {
1689 mGridSpacingY = height() - 1 ;// KOPrefs::instance()->mAllDaySize;
1690 //mGridSpacingY = KOPrefs::instance()->mAllDaySize;
1691 resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY+1 );
1692 // setMaximumHeight( mGridSpacingY+1 );
1693 viewport()->repaint( false );
1694 //setFixedHeight( mGridSpacingY+1 );
1695 //qDebug("KOPrefs:aaaaa:instance()->mAllDaySize %d ", KOPrefs::instance()->mAllDaySize);
1696 }
1697 else {
1698 mGridSpacingY = KOPrefs::instance()->mHourSize;
1699 calculateWorkingHours();
1700 marcus_bains();
1701 }
1702}
1703
1704void KOAgenda::checkScrollBoundaries()
1705{
1706 // Invalidate old values to force update
1707 mOldLowerScrollValue = -1;
1708 mOldUpperScrollValue = -1;
1709
1710 checkScrollBoundaries(verticalScrollBar()->value());
1711}
1712
1713void KOAgenda::checkScrollBoundaries(int v)
1714{
1715 if ( mGridSpacingY == 0 )
1716 return;
1717 int yMin = v/mGridSpacingY;
1718 int yMax = (v+visibleHeight())/mGridSpacingY;
1719
1720// kdDebug() << "--- yMin: " << yMin << " yMax: " << yMax << endl;
1721
1722 if (yMin != mOldLowerScrollValue) {
1723 mOldLowerScrollValue = yMin;
1724 emit lowerYChanged(yMin);
1725 }
1726 if (yMax != mOldUpperScrollValue) {
1727 mOldUpperScrollValue = yMax;
1728 emit upperYChanged(yMax);
1729 }
1730}
1731
1732void KOAgenda::deselectItem()
1733{
1734 if (mSelectedItem.isNull()) return;
1735 mSelectedItem->select(false);
1736 mSelectedItem = 0;
1737}
1738
1739void KOAgenda::selectItem(KOAgendaItem *item)
1740{
1741 if ((KOAgendaItem *)mSelectedItem == item) return;
1742 deselectItem();
1743 if (item == 0) {
1744 emit incidenceSelected( 0 );
1745 return;
1746 }
1747 mSelectedItem = item;
1748 mSelectedItem->select();
1749 emit incidenceSelected( mSelectedItem->incidence() );
1750}
1751
1752// This function seems never be called.
1753void KOAgenda::keyPressEvent( QKeyEvent *kev )
1754{
1755 switch(kev->key()) {
1756 case Key_PageDown:
1757 verticalScrollBar()->addPage();
1758 break;
1759 case Key_PageUp:
1760 verticalScrollBar()->subtractPage();
1761 break;
1762 case Key_Down:
1763 verticalScrollBar()->addLine();
1764 break;
1765 case Key_Up:
1766 verticalScrollBar()->subtractLine();
1767 break;
1768 default:
1769 ;
1770 }
1771}
1772
1773void KOAgenda::calculateWorkingHours()
1774{
1775// mWorkingHoursEnable = KOPrefs::instance()->mEnableWorkingHours;
1776 mWorkingHoursEnable = !mAllDayMode;
1777
1778 mWorkingHoursYTop = mGridSpacingY *
1779 KOPrefs::instance()->mWorkingHoursStart * 4;
1780 mWorkingHoursYBottom = mGridSpacingY *
1781 KOPrefs::instance()->mWorkingHoursEnd * 4 - 1;
1782}
1783
1784
1785DateList KOAgenda::dateList() const
1786{
1787 return mSelectedDates;
1788}
1789
1790void KOAgenda::setDateList(const DateList &selectedDates)
1791{
1792 mSelectedDates = selectedDates;
1793 marcus_bains();
1794}
1795
1796void KOAgenda::setHolidayMask(QMemArray<bool> *mask)
1797{
1798 mHolidayMask = mask;
1799
1800/*
1801 kdDebug() << "HolidayMask: ";
1802 for(uint i=0;i<mask->count();++i) {
1803 kdDebug() << (mask->at(i) ? "*" : "o");
1804 }
1805 kdDebug() << endl;
1806*/
1807}
1808
1809void KOAgenda::contentsMousePressEvent ( QMouseEvent *event )
1810{
1811
1812 QScrollView::contentsMousePressEvent(event);
1813}
1814
1815void KOAgenda::storePosition()
1816{
1817 //mContentPosition
1818 int max = mGridSpacingY*4*24;
1819 if ( contentsY() < 5 && max > viewport()->height()*3/2 )
1820 mContentPosition = 0;
1821 else if ( contentsY() + viewport()->height() > max - 5 && max > viewport()->height()*3/2)
1822 mContentPosition = -1.0;
1823 else
1824 mContentPosition = ((float) max)/ ((float)(contentsY()+ ( viewport()->height()/2)));
1825 //qDebug("mContentPosition %f %d %d %d",mContentPosition , max, contentsY() ,viewport()->height());
1826
1827}
1828void KOAgenda::restorePosition()
1829{
1830 int posY;
1831 int max = mGridSpacingY*4*24;
1832 if ( mContentPosition < 0 )
1833 posY = max-viewport()->height();
1834 else
1835 if ( mContentPosition == 0 )
1836 posY = 0;
1837 else
1838 posY = (max/mContentPosition)-(viewport()->height()/2);
1839 setContentsPos (0, posY );
1840 //qDebug("posY %d hei %d", posY, max);
1841
1842}
1843void KOAgenda::moveChild( QWidget *w, int x , int y )
1844{
1845 ++x;
1846 QScrollView::moveChild( w, x , y );
1847}
1848#include <qmessagebox.h>
1849#ifdef DESKTOP_VERSION
1850#include <qprinter.h>
1851#include <qpainter.h>
1852#include <qpaintdevicemetrics.h>
1853
1854#endif
1855void KOAgenda::printSelection()
1856{
1857#ifdef DESKTOP_VERSION
1858 if ( mStartCellY == mCurrentCellY ) {
1859 int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),
1860 i18n("Nothing selected!\n\nThis prints the full width of the Agenda view as you see it!\n\nTo determine the vertical range of the printing, please select\na vertical range (with the left mouse button down) in one column. "),
1861 i18n("OK"), 0, 0,
1862 0, 1 );
1863 return;
1864 }
1865
1866 float dx, dy;
1867 int x,y,w,h;
1868 x= 0;
1869 w= contentsWidth()+2;
1870 // h= contentsHeight();
1871 y = mGridSpacingY*mStartCellY;
1872 h = mGridSpacingY*(mCurrentCellY+1)-y+2;
1873
1874 //return;
1875 QPrinter* printer = new QPrinter();
1876 if ( !printer->setup()) {
1877 delete printer;
1878 return;
1879 }
1880 QPainter p( printer );
1881 QPaintDeviceMetrics m = QPaintDeviceMetrics ( printer );
1882 QString date = i18n("Date range: ")+KGlobal::locale()->formatDate( mSelectedDates.first() )+" - "+KGlobal::locale()->formatDate( mSelectedDates.last() );
1883 date += " --- printing time: " + KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), true );
1884 int hei = p.boundingRect(0,0, 5, 5, Qt::AlignLeft, date ).height();
1885 // p.drawText( 0, 0, date );
1886 int offset = m.width()/8;
1887 // compute the scale
1888 dx = ((float) m.width()-offset) / (float)w;
1889 dy = (float)(m.height() - ( 2 * hei )-offset ) / (float)h;
1890 float scale;
1891 // scale to fit the width or height of the paper
1892 if ( dx < dy )
1893 scale = dx;
1894 else
1895 scale = dy;
1896 // set the scale
1897 p.drawText( offset* scale, offset* scale*3/4, date );
1898
1899 int selDay;
1900 float widOffset = ((float) m.width()-offset) / ((float)(mSelectedDates.count()));
1901 float startX = 1;
1902 for ( selDay = 0; selDay < mSelectedDates.count(); ++selDay)
1903 {
1904 QString text = KGlobal::locale()->formatDate( mSelectedDates[selDay],true );
1905 p.setClipRect(offset* scale+startX , 0, widOffset-4, offset* scale+(2*hei* scale) );
1906 p.drawText( offset* scale+startX, (offset+hei)* scale, text );
1907 startX += widOffset;
1908
1909 }
1910 p.translate( offset* scale,offset* scale+ (-y * scale)+(2*hei* scale));
1911 p.scale( scale, scale );
1912 p.setClipRect( offset* scale, offset* scale+(2*hei* scale), w*scale, h*scale );
1913 // now printing with y offset: 2 hei
1914 // p.translate( 0, -y*scale);
1915
1916 drawContentsToPainter(&p, true );
1917 globalFlagBlockAgendaItemUpdate = false;
1918 KOAgendaItem *item;
1919 for ( item=mItems.first(); item != 0; item=mItems.next() ) {
1920 item->select(false);
1921 item->paintMe( false, &p );
1922 }
1923 globalFlagBlockAgendaItemUpdate = true;
1924 p.end();
1925 delete printer;
1926#else
1927 int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),
1928 i18n("Not supported \non PDA!\n"),
1929 i18n("OK"), 0, 0,
1930 0, 1 );
1931#endif
1932}