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