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
00484
if ( action == DRAG_COPY ) {
00485
if ( todo ) todo->recreate();
00486
if ( event ) event->recreate();
00487 }
else {
00488
if ( existingEvent ) oldEvent = existingEvent->clone();
00489
if ( event )
delete event;
00490 event = existingEvent;
00491
if ( existingTodo ) oldTodo = existingTodo->clone();
00492
if ( todo )
delete todo;
00493 todo = existingTodo;
00494 }
00495
00496
if ( action == DRAG_COPY || action == DRAG_MOVE ) {
00497 e->accept();
00498
if ( event ) {
00499
00500
QDateTime start = event->dtStart();
00501
QDateTime end = event->dtEnd();
00502
int duration = start.daysTo( end );
00503
int idx = getDayIndexFrom( e->pos().x(), e->pos().y() );
00504
00505 start.setDate( mDays[idx] );
00506 end.setDate( mDays[idx].addDays( duration ) );
00507
00508 event->setDtStart( start );
00509 event->setDtEnd( end );
00510
00511
if ( action != DRAG_MOVE ) {
00512
if ( !mCalendar->addEvent( event ) ) {
00513 KODialogManager::errorSaveEvent(
this );
00514
return;
00515 }
00516 }
00517
00518
if ( oldEvent ) {
00519 emit
incidenceDroppedMove( oldEvent, event );
00520 }
else {
00521 emit
incidenceDropped( event );
00522 }
00523 }
00524
if ( todo ) {
00525
00526
QDateTime due = todo->dtDue();
00527
int idx = getDayIndexFrom( e->pos().x(), e->pos().y() );
00528 due.setDate( mDays[idx] );
00529
00530 todo->setDtDue( due );
00531 todo->setHasDueDate(
true );
00532
00533
00534
if ( action != DRAG_MOVE ) {
00535
if ( !mCalendar->addTodo( todo ) ) {
00536 KODialogManager::errorSaveTodo(
this );
00537 }
00538 }
00539
00540
if ( oldTodo ) {
00541 emit
incidenceDroppedMove( oldTodo, todo );
00542 }
else {
00543 emit
incidenceDropped( todo );
00544 }
00545 }
00546 }
else {
00547
if ( todo )
delete todo;
00548
if ( event )
delete event;
00549 e->ignore();
00550 }
00551
#endif
00552
}
00553
00554
00555
00556
00557
00558
void KODayMatrix::paintEvent(
QPaintEvent *pevent )
00559 {
00560
00561
00562
QPainter p(
this);
00563
00564
QRect sz = frameRect();
00565
int dheight = mDaySize.height();
00566
int dwidth = mDaySize.width();
00567
int row,col;
00568
int selw, selh;
00569
bool isRTL = KOGlobals::self()->reverseLayout();
00570
00571
00572 p.fillRect(pevent->rect(), mDefaultBackColor);
00573 p.setPen(mDefaultTextColor);
00574 p.drawRect(0, 0, sz.width()+1, sz.height()+1);
00575
00576 p.translate(1,1);
00577
00578
00579
if (mSelStart != NOSELECTION) {
00580
00581 row = mSelStart/7;
00582 col = mSelStart -row*7;
00583
QColor selcol = KOPrefs::instance()->mHighlightColor;
00584
00585
if (row == mSelEnd/7) {
00586
00587 p.fillRect(isRTL ? (7 - (mSelEnd-mSelStart+1) - col)*dwidth : col*dwidth,
00588 row*dheight, (mSelEnd-mSelStart+1)*dwidth, dheight, selcol);
00589 }
else {
00590
00591 p.fillRect(isRTL ? 0 : col*dwidth, row*dheight, (7-col)*dwidth,
00592 dheight, selcol);
00593
00594 selh = mSelEnd/7-row;
00595
if (selh > 1) {
00596 p.fillRect(0, (row+1)*dheight, 7*dwidth, (selh-1)*dheight,selcol);
00597 }
00598
00599 selw = mSelEnd-7*(mSelEnd/7)+1;
00600 p.fillRect(isRTL ? (7-selw)*dwidth : 0, (row+selh)*dheight,
00601 selw*dwidth, dheight, selcol);
00602 }
00603 }
00604
00605
00606
QColor actcol = mDefaultTextColorShaded;
00607 p.setPen(actcol);
00608
QPen tmppen;
00609
for(
int i = 0; i < NUMDAYS; i++) {
00610 row = i/7;
00611 col = isRTL ? 6-(i-row*7) : i-row*7;
00612
00613
00614
if ( KOGlobals::self()->calendarSystem()->day( mDays[i] ) == 1) {
00615
if (actcol == mDefaultTextColorShaded) {
00616 actcol = mDefaultTextColor;
00617 }
else {
00618 actcol = mDefaultTextColorShaded;
00619 }
00620 p.setPen(actcol);
00621 }
00622
00623
00624
if (i == mSelEnd+1) {
00625 p.setPen(actcol);
00626 }
00627
00628
00629
if (mToday == i) {
00630 tmppen = p.pen();
00631
QPen mTodayPen(p.pen());
00632
00633 mTodayPen.setWidth(mTodayMarginWidth);
00634
00635
if (!mHolidays[i].isNull()) {
00636
if (actcol == mDefaultTextColor) {
00637 mTodayPen.setColor(KOPrefs::instance()->mHolidayColor);
00638 }
else {
00639 mTodayPen.setColor(mHolidayColorShaded);
00640 }
00641 }
00642
00643
if (i >= mSelStart && i <= mSelEnd) {
00644
QColor grey(
"grey");
00645 mTodayPen.setColor(grey);
00646 }
00647 p.setPen(mTodayPen);
00648 p.drawRect(col*dwidth, row*dheight, dwidth, dheight);
00649 p.setPen(tmppen);
00650 }
00651
00652
00653
if (mEvents[i] > 0) {
00654
QFont myFont = font();
00655 myFont.setBold(
true);
00656 p.setFont(myFont);
00657 }
00658
00659
00660
if (!mHolidays[i].isNull()) {
00661
if (actcol == mDefaultTextColor) {
00662 p.setPen(KOPrefs::instance()->mHolidayColor);
00663 }
else {
00664 p.setPen(mHolidayColorShaded);
00665 }
00666 }
00667
00668
00669
00670
if (i >= mSelStart && i <= mSelEnd) {
00671 p.setPen(mSelectedDaysColor);
00672 }
00673
00674 p.drawText(col*dwidth, row*dheight, dwidth, dheight,
00675 Qt::AlignHCenter | Qt::AlignVCenter, mDayLabels[i]);
00676
00677
00678
if (!mHolidays[i].isNull()) {
00679 p.setPen(actcol);
00680 }
00681
00682
if (mEvents[i] > 0) {
00683
QFont myFont = font();
00684 myFont.setBold(
false);
00685 p.setFont(myFont);
00686 }
00687 }
00688 }
00689
00690
00691
00692
00693
00694
void KODayMatrix::resizeEvent(
QResizeEvent * )
00695 {
00696
QRect sz = frameRect();
00697 mDaySize.setHeight( sz.height() * 7 / NUMDAYS );
00698 mDaySize.setWidth( sz.width() / 7 );
00699 }