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
00028
#include <qevent.h>
00029
#include <qpainter.h>
00030
#include <qptrlist.h>
00031
00032
#include <kglobal.h>
00033
#include <kdebug.h>
00034
#include <klocale.h>
00035
#include <kiconloader.h>
00036
00037
#include <libkcal/vcaldrag.h>
00038
#include <libkcal/icaldrag.h>
00039
#include <libkcal/dndfactory.h>
00040
#include <libkcal/calendarresources.h>
00041
#include <libkcal/resourcecalendar.h>
00042
00043
#include <kcalendarsystem.h>
00044
00045
#ifndef KORG_NOPLUGINS
00046
#include "kocore.h"
00047
#endif
00048
#include "koprefs.h"
00049
#include "koglobals.h"
00050
#include "kodialogmanager.h"
00051
00052
#include "kodaymatrix.h"
00053
#include "kodaymatrix.moc"
00054
00055
#ifndef NODND
00056
#include <qcursor.h>
00057
#include <kpopupmenu.h>
00058
#include <X11/Xlib.h>
00059
#undef KeyPress
00060
#undef None
00061
#undef Status
00062
#endif
00063
00064
00065
00066
00067
00068 DynamicTip::DynamicTip(
QWidget * parent )
00069 :
QToolTip( parent )
00070 {
00071 mMatrix = static_cast<KODayMatrix *>( parent );
00072 }
00073
00074
00075 void DynamicTip::maybeTip(
const QPoint &pos )
00076 {
00077
00078
QRect sz = mMatrix->frameRect();
00079
int dheight = sz.height() * 7 / 42;
00080
int dwidth = sz.width() / 7;
00081
int row = pos.y() / dheight;
00082
int col = pos.x() / dwidth;
00083
00084
QRect rct( col * dwidth, row * dheight, dwidth, dheight );
00085
00086
00087
00088
00089
00090
QString str = mMatrix->
getHolidayLabel( col + row * 7 );
00091
if ( str.isEmpty() )
return;
00092 tip( rct, str );
00093 }
00094
00095
00096
00097
00098
00099
00100
const int KODayMatrix::NOSELECTION = -1000;
00101
const int KODayMatrix::NUMDAYS = 42;
00102
00103 KODayMatrix::KODayMatrix(
QWidget *parent,
const char *name )
00104 :
QFrame( parent, name ), mCalendar( 0 )
00105 {
00106
00107 mDays =
new QDate[ NUMDAYS ];
00108 mDayLabels =
new QString[ NUMDAYS ];
00109 mEvents =
new int[ NUMDAYS ];
00110 mToolTip =
new DynamicTip(
this );
00111
00112
00113 mDefaultBackColor = palette().active().base();
00114 mDefaultTextColor = palette().active().foreground();
00115 mDefaultTextColorShaded = getShadedColor( mDefaultTextColor );
00116 mHolidayColorShaded = getShadedColor( KOPrefs::instance()->mHolidayColor );
00117 mSelectedDaysColor =
QColor(
"white" );
00118 mTodayMarginWidth = 2;
00119 mSelEnd = mSelStart = NOSELECTION;
00120 }
00121
00122 void KODayMatrix::setCalendar( Calendar *cal )
00123 {
00124 mCalendar = cal;
00125
00126 setAcceptDrops( mCalendar );
00127
00128
updateEvents();
00129 }
00130
00131
QColor KODayMatrix::getShadedColor(
QColor color )
00132 {
00133
QColor shaded;
00134
int h = 0;
00135
int s = 0;
00136
int v = 0;
00137 color.hsv( &h, &s, &v );
00138 s = s / 4;
00139 v = 192 + v / 4;
00140 shaded.setHsv( h, s, v );
00141
00142
return shaded;
00143 }
00144
00145 KODayMatrix::~KODayMatrix()
00146 {
00147
delete [] mDays;
00148
delete [] mDayLabels;
00149
delete [] mEvents;
00150
delete mToolTip;
00151 }
00152
00153 void KODayMatrix::addSelectedDaysTo( DateList &selDays )
00154 {
00155 kdDebug(5850) <<
"KODayMatrix::addSelectedDaysTo() - " <<
"mSelStart:" << mSelStart << endl;
00156
00157
if ( mSelStart == NOSELECTION ) {
00158
return;
00159 }
00160
00161
00162
int i0 = mSelStart;
00163
if ( i0 < 0 ) {
00164
for (
int i = i0; i < 0; i++ ) {
00165 selDays.append( mDays[ 0 ].addDays( i ) );
00166 }
00167 i0 = 0;
00168 }
00169
00170
00171
if ( mSelEnd > NUMDAYS-1 ) {
00172
for (
int i = i0; i <= NUMDAYS - 1; i++ ) {
00173 selDays.append( mDays[ i ] );
00174 }
00175
for (
int i = NUMDAYS; i < mSelEnd; i++ ) {
00176 selDays.append( mDays[ 0 ].addDays( i ) );
00177 }
00178 }
else {
00179
00180
for (
int i = i0; i <= mSelEnd; i++ ) {
00181 selDays.append( mDays[ i ] );
00182 }
00183 }
00184 }
00185
00186 void KODayMatrix::setSelectedDaysFrom(
const QDate &start,
const QDate &end )
00187 {
00188 mSelStart = mStartDate.daysTo( start );
00189 mSelEnd = mStartDate.daysTo( end );
00190 }
00191
00192 void KODayMatrix::clearSelection()
00193 {
00194 mSelEnd = mSelStart = NOSELECTION;
00195 }
00196
00197 void KODayMatrix::recalculateToday()
00198 {
00199 mToday = -1;
00200
for (
int i = 0; i < NUMDAYS; i++ ) {
00201 mDays[ i ] = mStartDate.addDays( i );
00202 mDayLabels[ i ] = QString::number( KOGlobals::self()->calendarSystem()->day( mDays[i] ));
00203
00204
00205
if ( mDays[ i ].year() == QDate::currentDate().year() &&
00206 mDays[ i ].month() == QDate::currentDate().month() &&
00207 mDays[ i ].day() == QDate::currentDate().day() ) {
00208 mToday = i;
00209 }
00210 }
00211
00212 }
00213
00214 void KODayMatrix::updateView()
00215 {
00216
updateView( mStartDate );
00217 }
00218
00219 void KODayMatrix::updateView(
QDate actdate )
00220 {
00221
00222
00223
00224
bool daychanged =
false;
00225
00226
00227
00228
if ( actdate != mStartDate ) {
00229
00230
if ( mSelStart != NOSELECTION ) {
00231
int tmp = actdate.daysTo( mStartDate );
00232
00233
00234
00235
if ( mSelStart + tmp < NUMDAYS && mSelEnd + tmp >= 0 ) {
00236
00237
00238
if( mSelStart > NUMDAYS || mSelStart < 0 )
00239 mSelStart = mSelStart + tmp;
00240
if( mSelEnd > NUMDAYS || mSelEnd < 0 )
00241 mSelEnd = mSelEnd + tmp;
00242 }
00243 }
00244
00245 mStartDate = actdate;
00246 daychanged =
true;
00247 }
00248
00249
if ( daychanged ) {
00250
recalculateToday();
00251 }
00252
00253
updateEvents();
00254
for(
int i = 0; i < NUMDAYS; i++ ) {
00255
00256
#ifndef KORG_NOPLUGINS
00257
QString holiStr = KOCore::self()->holiday( mDays[ i ] );
00258
#else
00259
QString holiStr = QString::null;
00260
#endif
00261
if ( ( KOGlobals::self()->calendarSystem()->dayOfWeek( mDays[ i ] ) ==
00262 KOGlobals::self()->calendarSystem()->weekDayOfPray() ) ||
00263 !holiStr.isEmpty() ) {
00264
if ( holiStr.isNull() ) holiStr =
"";
00265 mHolidays[ i ] = holiStr;
00266 }
else {
00267 mHolidays[ i ] = QString::null;
00268 }
00269 }
00270 }
00271
00272 void KODayMatrix::updateEvents()
00273 {
00274
if ( !mCalendar )
return;
00275
00276
for(
int i = 0; i < NUMDAYS; i++ ) {
00277
00278 Event::List eventlist = mCalendar->events( mDays[ i ] );
00279
int numEvents = eventlist.count();
00280 Event::List::ConstIterator it;
00281
for( it = eventlist.begin(); it != eventlist.end(); ++it ) {
00282 Event *event = *it;
00283 ushort recurType = event->doesRecur();
00284
00285
if ( ( recurType == Recurrence::rDaily &&
00286 !KOPrefs::instance()->mDailyRecur ) ||
00287 ( recurType == Recurrence::rWeekly &&
00288 !KOPrefs::instance()->mWeeklyRecur ) ) {
00289 numEvents--;
00290 }
00291 }
00292 mEvents[ i ] = numEvents;
00293 }
00294 }
00295
00296 const QDate&
KODayMatrix::getDate(
int offset )
00297 {
00298
if ( offset < 0 || offset > NUMDAYS - 1 ) {
00299 kdDebug(5850) <<
"Wrong offset (" << offset <<
") in KODayMatrix::getDate(int)" << endl;
00300
return mDays[ 0 ];
00301 }
00302
return mDays[ offset ];
00303 }
00304
00305 QString KODayMatrix::getHolidayLabel(
int offset )
00306 {
00307
if ( offset < 0 || offset > NUMDAYS - 1 ) {
00308 kdDebug(5850) <<
"Wrong offset (" << offset <<
") in KODayMatrix::getHolidayLabel(int)" << endl;
00309
return 0;
00310 }
00311
return mHolidays[ offset ];
00312 }
00313
00314
int KODayMatrix::getDayIndexFrom(
int x,
int y )
00315 {
00316
return 7 * ( y / mDaySize.height() ) +
00317 ( KOGlobals::self()->reverseLayout() ?
00318 6 - x / mDaySize.width() : x / mDaySize.width() );
00319 }
00320
00321
00322
00323
00324
00325
void KODayMatrix::mousePressEvent(
QMouseEvent *e )
00326 {
00327 mSelStart = getDayIndexFrom(e->x(), e->y());
00328
if (mSelStart > NUMDAYS-1) mSelStart=NUMDAYS-1;
00329 mSelInit = mSelStart;
00330 }
00331
00332
void KODayMatrix::mouseReleaseEvent(
QMouseEvent *e )
00333 {
00334
int tmp = getDayIndexFrom(e->x(), e->y());
00335
if (tmp > NUMDAYS-1) tmp=NUMDAYS-1;
00336
00337
if (mSelInit > tmp) {
00338 mSelEnd = mSelInit;
00339
if (tmp != mSelStart) {
00340 mSelStart = tmp;
00341 repaint();
00342 }
00343 }
else {
00344 mSelStart = mSelInit;
00345
00346
00347
if (tmp != mSelEnd) {
00348 mSelEnd = tmp;
00349 repaint();
00350 }
00351 }
00352
00353 DateList daylist;
00354
if ( mSelStart < 0 ) mSelStart = 0;
00355
for (
int i = mSelStart; i <= mSelEnd; i++) {
00356 daylist.append(mDays[i]);
00357 }
00358 emit
selected((
const DateList)daylist);
00359 }
00360
00361
void KODayMatrix::mouseMoveEvent(
QMouseEvent *e )
00362 {
00363
int tmp = getDayIndexFrom(e->x(), e->y());
00364
if (tmp > NUMDAYS-1) tmp=NUMDAYS-1;
00365
00366
if (mSelInit > tmp) {
00367 mSelEnd = mSelInit;
00368
if (tmp != mSelStart) {
00369 mSelStart = tmp;
00370 repaint();
00371 }
00372 }
else {
00373 mSelStart = mSelInit;
00374
00375
00376
if (tmp != mSelEnd) {
00377 mSelEnd = tmp;
00378 repaint();
00379 }
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
enum {
00391 DRAG_COPY = 0,
00392 DRAG_MOVE = 1,
00393 DRAG_CANCEL = 2
00394 };
00395
00396
void KODayMatrix::dragEnterEvent(
QDragEnterEvent *e )
00397 {
00398
#ifndef KORG_NODND
00399
if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) {
00400 e->ignore();
00401
return;
00402 }
00403
00404
00405
00406
00407
00408
#endif
00409
}
00410
00411
void KODayMatrix::dragMoveEvent(
QDragMoveEvent *e )
00412 {
00413
#ifndef KORG_NODND
00414
if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) {
00415 e->ignore();
00416
return;
00417 }
00418
00419 e->accept();
00420
#endif
00421
}
00422
00423
void KODayMatrix::dragLeaveEvent(
QDragLeaveEvent * )
00424 {
00425
#ifndef KORG_NODND
00426
00427
00428
#endif
00429
}
00430
00431
void KODayMatrix::dropEvent(
QDropEvent *e )
00432 {
00433
#ifndef KORG_NODND
00434
kdDebug(5850) <<
"KODayMatrix::dropEvent(e) begin" << endl;
00435
00436
if ( !mCalendar ||
00437 ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) ) {
00438 e->ignore();
00439
return;
00440 }
00441
00442 DndFactory factory( mCalendar );
00443 Event *event = factory.createDrop( e );
00444 Todo *todo = factory.createDropTodo( e );
00445
if ( !event && !todo ) {
00446 e->ignore();
00447
return;
00448 }
00449
00450 Todo *existingTodo = 0, *oldTodo = 0;
00451 Event *existingEvent = 0, *oldEvent = 0;
00452
00453
00454
if ( event ) existingEvent = mCalendar->event( event->uid() );
00455
if ( todo ) existingTodo = mCalendar->todo( todo->uid() );
00456
00457
int action = DRAG_CANCEL;
00458
00459
int root_x, root_y, win_x, win_y;
00460 uint keybstate;
00461 Window rootw, childw;
00462 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &rootw, &childw,
00463 &root_x, &root_y, &win_x, &win_y, &keybstate );
00464
00465
if ( keybstate & ControlMask ) {
00466 action = DRAG_COPY;
00467 }
else if ( keybstate & ShiftMask ) {
00468 action = DRAG_MOVE;
00469 }
else {
00470 KPopupMenu *menu =
new KPopupMenu(
this );
00471
if ( existingEvent || existingTodo ) {
00472 menu->insertItem( i18n(
"Move"), DRAG_MOVE, 0 );
00473
if (existingEvent)
00474 menu->insertItem( KOGlobals::self()->smallIcon(
"editcopy"), i18n(
"Copy"), DRAG_COPY, 1 );
00475 }
else {
00476 menu->insertItem( i18n(
"Add"), DRAG_MOVE, 0 );
00477 }
00478 menu->insertSeparator();
00479 menu->insertItem( KOGlobals::self()->smallIcon(
"cancel"), i18n(
"Cancel"), DRAG_CANCEL, 3 );
00480 action = menu->exec( QCursor::pos(), 0 );
00481 }
00482
00483
if ( action == DRAG_COPY || action == DRAG_MOVE ) {
00484
00485
00486
if ( action == DRAG_COPY ) {
00487
if ( todo ) todo->recreate();
00488
if ( event ) event->recreate();
00489 }
else {
00490
if ( existingEvent ) oldEvent = existingEvent->clone();
00491
if ( event )
delete event;
00492 event = existingEvent;
00493
if ( existingTodo ) oldTodo = existingTodo->clone();
00494
if ( todo )
delete todo;
00495 todo = existingTodo;
00496 }
00497
00498 e->accept();
00499
if ( event ) {
00500
00501
QDateTime start = event->dtStart();
00502
QDateTime end = event->dtEnd();
00503
int duration = start.daysTo( end );
00504
int idx = getDayIndexFrom( e->pos().x(), e->pos().y() );
00505
00506 start.setDate( mDays[idx] );
00507 end.setDate( mDays[idx].addDays( duration ) );
00508
00509 event->setDtStart( start );
00510 event->setDtEnd( end );
00511
00512
if ( action != DRAG_MOVE ) {
00513
if ( !mCalendar->addEvent( event ) ) {
00514 KODialogManager::errorSaveEvent(
this );
00515
return;
00516 }
00517 }
00518
00519
if ( oldEvent ) {
00520 emit
incidenceDroppedMove( oldEvent, event );
00521 }
else {
00522 emit
incidenceDropped( event );
00523 }
00524 }
00525
if ( todo ) {
00526
00527
QDateTime due = todo->dtDue();
00528
int idx = getDayIndexFrom( e->pos().x(), e->pos().y() );
00529 due.setDate( mDays[idx] );
00530
00531 todo->setDtDue( due );
00532 todo->setHasDueDate(
true );
00533
00534
00535
if ( action != DRAG_MOVE ) {
00536
if ( !mCalendar->addTodo( todo ) ) {
00537 KODialogManager::errorSaveTodo(
this );
00538 }
00539 }
00540
00541
if ( oldTodo ) {
00542 emit
incidenceDroppedMove( oldTodo, todo );
00543 }
else {
00544 emit
incidenceDropped( todo );
00545 }
00546 }
00547 }
else {
00548
if ( todo )
delete todo;
00549
if ( event )
delete event;
00550 e->ignore();
00551 }
00552
#endif
00553
}
00554
00555
00556
00557
00558
00559
void KODayMatrix::paintEvent(
QPaintEvent *pevent )
00560 {
00561
00562
00563
QPainter p(
this);
00564
00565
QRect sz = frameRect();
00566
int dheight = mDaySize.height();
00567
int dwidth = mDaySize.width();
00568
int row,col;
00569
int selw, selh;
00570
bool isRTL = KOGlobals::self()->reverseLayout();
00571
00572
00573 p.fillRect(pevent->rect(), mDefaultBackColor);
00574 p.setPen(mDefaultTextColor);
00575 p.drawRect(0, 0, sz.width()+1, sz.height()+1);
00576
00577 p.
translate(1,1);
00578
00579
00580
if (mSelStart != NOSELECTION) {
00581
00582 row = mSelStart/7;
00583 col = mSelStart -row*7;
00584
QColor selcol = KOPrefs::instance()->mHighlightColor;
00585
00586
if (row == mSelEnd/7) {
00587
00588 p.fillRect(isRTL ? (7 - (mSelEnd-mSelStart+1) - col)*dwidth : col*dwidth,
00589 row*dheight, (mSelEnd-mSelStart+1)*dwidth, dheight, selcol);
00590 }
else {
00591
00592 p.fillRect(isRTL ? 0 : col*dwidth, row*dheight, (7-col)*dwidth,
00593 dheight, selcol);
00594
00595 selh = mSelEnd/7-row;
00596
if (selh > 1) {
00597 p.fillRect(0, (row+1)*dheight, 7*dwidth, (selh-1)*dheight,selcol);
00598 }
00599
00600 selw = mSelEnd-7*(mSelEnd/7)+1;
00601 p.fillRect(isRTL ? (7-selw)*dwidth : 0, (row+selh)*dheight,
00602 selw*dwidth, dheight, selcol);
00603 }
00604 }
00605
00606
00607
QColor actcol = mDefaultTextColorShaded;
00608 p.setPen(actcol);
00609
QPen tmppen;
00610
for(
int i = 0; i < NUMDAYS; i++) {
00611 row = i/7;
00612 col = isRTL ? 6-(i-row*7) : i-row*7;
00613
00614
00615
if ( KOGlobals::self()->calendarSystem()->day( mDays[i] ) == 1) {
00616
if (actcol == mDefaultTextColorShaded) {
00617 actcol = mDefaultTextColor;
00618 }
else {
00619 actcol = mDefaultTextColorShaded;
00620 }
00621 p.setPen(actcol);
00622 }
00623
00624
00625
if (i == mSelEnd+1) {
00626 p.setPen(actcol);
00627 }
00628
00629
00630
if (mToday == i) {
00631 tmppen = p.pen();
00632
QPen mTodayPen(p.pen());
00633
00634 mTodayPen.setWidth(mTodayMarginWidth);
00635
00636
if (!mHolidays[i].isNull()) {
00637
if (actcol == mDefaultTextColor) {
00638 mTodayPen.setColor(KOPrefs::instance()->mHolidayColor);
00639 }
else {
00640 mTodayPen.setColor(mHolidayColorShaded);
00641 }
00642 }
00643
00644
if (i >= mSelStart && i <= mSelEnd) {
00645
QColor grey(
"grey");
00646 mTodayPen.setColor(grey);
00647 }
00648 p.setPen(mTodayPen);
00649 p.drawRect(col*dwidth, row*dheight, dwidth, dheight);
00650 p.setPen(tmppen);
00651 }
00652
00653
00654
if (mEvents[i] > 0) {
00655
QFont myFont = font();
00656 myFont.setBold(
true);
00657 p.setFont(myFont);
00658 }
00659
00660
00661
if (!mHolidays[i].isNull()) {
00662
if (actcol == mDefaultTextColor) {
00663 p.setPen(KOPrefs::instance()->mHolidayColor);
00664 }
else {
00665 p.setPen(mHolidayColorShaded);
00666 }
00667 }
00668
00669
00670
00671
if (i >= mSelStart && i <= mSelEnd) {
00672 p.setPen(mSelectedDaysColor);
00673 }
00674
00675 p.drawText(col*dwidth, row*dheight, dwidth, dheight,
00676 Qt::AlignHCenter | Qt::AlignVCenter, mDayLabels[i]);
00677
00678
00679
if (!mHolidays[i].isNull()) {
00680 p.setPen(actcol);
00681 }
00682
00683
if (mEvents[i] > 0) {
00684
QFont myFont = font();
00685 myFont.setBold(
false);
00686 p.setFont(myFont);
00687 }
00688 }
00689 }
00690
00691
00692
00693
00694
00695
void KODayMatrix::resizeEvent(
QResizeEvent * )
00696 {
00697
QRect sz = frameRect();
00698 mDaySize.setHeight( sz.height() * 7 / NUMDAYS );
00699 mDaySize.setWidth( sz.width() / 7 );
00700 }