00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021 #include "datebookmonth.h"
00022 #include "datebookdb.h"
00023 #include <qtopia/private/event.h>
00024 #include "resource.h"
00025 #include <qpe/qpeapplication.h>
00026 #include "timestring.h"
00027
00028 #include <qtoolbutton.h>
00029 #include <qspinbox.h>
00030 #include <qcombobox.h>
00031 #include <qdatetime.h>
00032 #include <qpainter.h>
00033 #include <qpopupmenu.h>
00034 #include <qvaluestack.h>
00035 #include <qwhatsthis.h>
00036
00037
00038 DateBookMonthHeader::DateBookMonthHeader( QWidget *parent, const char *name )
00039 : QHBox( parent, name )
00040 {
00041 setBackgroundMode( PaletteButton );
00042
00043 begin = new QToolButton( this );
00044 begin->setFocusPolicy(NoFocus);
00045 begin->setPixmap( Resource::loadPixmap( "start" ) );
00046 begin->setAutoRaise( TRUE );
00047 begin->setFixedSize( begin->sizeHint() );
00048 QWhatsThis::add( begin, tr("Show January in the selected year") );
00049
00050 back = new QToolButton( this );
00051 back->setFocusPolicy(NoFocus);
00052 back->setPixmap( Resource::loadPixmap( "back" ) );
00053 back->setAutoRaise( TRUE );
00054 back->setFixedSize( back->sizeHint() );
00055 QWhatsThis::add( back, tr("Show the previous month") );
00056
00057 month = new QComboBox( FALSE, this );
00058 for ( int i = 0; i < 12; ++i )
00059 month->insertItem( Calendar::nameOfMonth( i + 1 ) );
00060
00061 year = new QSpinBox( 1752, 8000, 1, this );
00062
00063 next = new QToolButton( this );
00064 next->setFocusPolicy(NoFocus);
00065 next->setPixmap( Resource::loadPixmap( "forward" ) );
00066 next->setAutoRaise( TRUE );
00067 next->setFixedSize( next->sizeHint() );
00068 QWhatsThis::add( next, tr("Show the next month") );
00069
00070 end = new QToolButton( this );
00071 end->setFocusPolicy(NoFocus);
00072 end->setPixmap( Resource::loadPixmap( "finish" ) );
00073 end->setAutoRaise( TRUE );
00074 end->setFixedSize( end->sizeHint() );
00075 QWhatsThis::add( end, tr("Show December in the selected year") );
00076
00077 connect( month, SIGNAL( activated( int ) ),
00078 this, SLOT( updateDate() ) );
00079 connect( year, SIGNAL( valueChanged( int ) ),
00080 this, SLOT( updateDate() ) );
00081 connect( begin, SIGNAL( clicked() ),
00082 this, SLOT( firstMonth() ) );
00083 connect( end, SIGNAL( clicked() ),
00084 this, SLOT( lastMonth() ) );
00085 connect( back, SIGNAL( clicked() ),
00086 this, SLOT( monthBack() ) );
00087 connect( next, SIGNAL( clicked() ),
00088 this, SLOT( monthForward() ) );
00089 back->setAutoRepeat( TRUE );
00090 next->setAutoRepeat( TRUE );
00091 }
00092
00093
00094 DateBookMonthHeader::~DateBookMonthHeader()
00095 {
00096
00097 }
00098
00099 void DateBookMonthHeader::updateDate()
00100 {
00101 emit dateChanged( year->value(), month->currentItem() + 1 );
00102 }
00103
00104 void DateBookMonthHeader::firstMonth()
00105 {
00106 emit dateChanged( year->value(), 1 );
00107 month->setCurrentItem( 0 );
00108 }
00109
00110 void DateBookMonthHeader::lastMonth()
00111 {
00112 emit dateChanged( year->value(), 12 );
00113 month->setCurrentItem( 11 );
00114 }
00115
00116 void DateBookMonthHeader::monthBack()
00117 {
00118 if ( month->currentItem() > 0 ) {
00119 emit dateChanged( year->value(), month->currentItem() );
00120 month->setCurrentItem( month->currentItem() - 1 );
00121 } else {
00122 emit dateChanged( year->value() - 1, 12 );
00123
00124
00125 month->setCurrentItem( 11 );
00126 year->setValue( year->value() - 1 );
00127 }
00128 }
00129
00130 void DateBookMonthHeader::monthForward()
00131 {
00132 if ( month->currentItem() < 11 ) {
00133 emit dateChanged( year->value(), month->currentItem() + 2 );
00134 month->setCurrentItem( month->currentItem() + 1 );
00135 } else {
00136
00137
00138 month->setCurrentItem( 0 );
00139 year->setValue( year->value() + 1 );
00140 }
00141 }
00142
00143 void DateBookMonthHeader::setDate( int y, int m )
00144 {
00145 year->setValue( y );
00146 month->setCurrentItem( m - 1 );
00147 }
00148
00149
00150
00151 class DateBookMonthTablePrivate
00152 {
00153 public:
00154 DateBookMonthTablePrivate() {};
00155 ~DateBookMonthTablePrivate() { mMonthEvents.clear(); };
00156
00157 QValueList<EffectiveEvent> mMonthEvents;
00158 bool onMonday;
00159 };
00160
00161 DateBookMonthTable::DateBookMonthTable( QWidget *parent, const char *name,
00162 DateBookDB *newDb )
00163 : QTable( 6, 7, parent, name ),
00164 db( newDb )
00165 {
00166 d = new DateBookMonthTablePrivate();
00167 selYear = -1;
00168 selMonth = -1;
00169 selDay = -1;
00170
00171
00172 year = -1;
00173 month = -1;
00174 day = -1;
00175
00176 Config cfg( "qpe" );
00177 cfg.setGroup( "Time" );
00178 d->onMonday = cfg.readBoolEntry( "MONDAY" );
00179
00180 horizontalHeader()->setResizeEnabled( FALSE );
00181
00182 for ( int i = 0; i < 7; i++ ){
00183 horizontalHeader()->resizeSection( i, 30 );
00184 setColumnStretchable( i, TRUE );
00185 }
00186 setupLabels();
00187
00188 verticalHeader()->hide();
00189 setLeftMargin( 0 );
00190 for ( int i = 0; i < 6; ++i )
00191 setRowStretchable( i, TRUE );
00192
00193 setSelectionMode( NoSelection );
00194
00195 connect( this, SIGNAL( clicked( int, int, int, const QPoint & ) ),
00196 this, SLOT( dayClicked( int, int ) ) );
00197 connect( this, SIGNAL( currentChanged( int, int ) ),
00198 this, SLOT( dragDay( int, int ) ) );
00199 setVScrollBarMode( AlwaysOff );
00200 setHScrollBarMode( AlwaysOff );
00201 }
00202
00203 DateBookMonthTable::~DateBookMonthTable()
00204 {
00205 monthsEvents.clear();
00206 delete d;
00207 }
00208
00209 void DateBookMonthTable::setDate(int y, int m, int d)
00210 {
00211 if (month == m && year == y) {
00212 if ( selYear == -1 )
00213 year = selYear;
00214 if ( selMonth == -1 )
00215 month = selMonth;
00216 int r1, c1, r2, c2;
00217 findDay(selDay, r1, c1);
00218 selDay = day = d;
00219 findDay(selDay, r2, c2);
00220 setCurrentCell( r2, c2 );
00221
00222
00223 } else {
00224 selYear = year = y;
00225 selMonth = month = m;
00226 selDay = day = d;
00227 setupTable();
00228 }
00229 }
00230
00231 void DateBookMonthTable::redraw()
00232 {
00233 setupLabels();
00234 setupTable();
00235 }
00236
00237 void DateBookMonthTable::setWeekStart( bool onMonday )
00238 {
00239 d->onMonday = onMonday;
00240 setupLabels();
00241 setupTable();
00242 }
00243
00244 void DateBookMonthTable::setupTable()
00245 {
00246 QValueList<Calendar::Day> days = Calendar::daysOfMonth( year, month, d->onMonday );
00247 QValueList<Calendar::Day>::Iterator it = days.begin();
00248 int row = 0, col = 0;
00249 int crow = 0;
00250 int ccol = 0;
00251 for ( ; it != days.end(); ++it ) {
00252 DayItemMonth *i = (DayItemMonth *)item( row, col );
00253 if ( !i ) {
00254 i = new DayItemMonth( this, QTableItem::Never, "" );
00255 setItem( row, col, i );
00256 }
00257 Calendar::Day calDay = *it;
00258 i->clearEffEvents();
00259 i->setDay( calDay.date );
00260 i->setType( calDay.type );
00261 if ( i->day() == day && calDay.type == Calendar::Day::ThisMonth ) {
00262 crow = row;
00263 ccol = col;
00264 }
00265
00266 updateCell( row, col );
00267
00268 if ( col == 6 ) {
00269 ++row;
00270 col = 0;
00271 } else {
00272 ++col;
00273 }
00274 }
00275 setCurrentCell( crow, ccol );
00276 getEvents();
00277 }
00278
00279 void DateBookMonthTable::findDay( int day, int &row, int &col )
00280 {
00281 QDate dtBegin( year, month, 1 );
00282 int skips = dtBegin.dayOfWeek();
00283 int effective_day = day + skips - 1;
00284
00285 if ( d->onMonday )
00286 effective_day--;
00287 row = effective_day / 7;
00288 col = effective_day % 7;
00289 }
00290
00291 void DateBookMonthTable::dayClicked( int row, int col )
00292 {
00293 changeDaySelection( row, col );
00294 emit dateClicked( selYear, selMonth, selDay );
00295 }
00296
00297 void DateBookMonthTable::dragDay( int row, int col )
00298 {
00299 changeDaySelection( row, col );
00300 }
00301
00302 void DateBookMonthTable::changeDaySelection( int row, int col )
00303 {
00304 DayItemMonth *i = (DayItemMonth*)item( row, col );
00305 if ( !i )
00306 return;
00307 switch ( i->type() ) {
00308 case Calendar::Day::ThisMonth:
00309 selMonth = month;
00310 break;
00311 case Calendar::Day::PrevMonth:
00312 selMonth = month-1;
00313 break;
00314 default:
00315 selMonth = month+1;
00316 }
00317
00318 selYear = year;
00319 if ( selMonth <= 0 ) {
00320 selMonth = 12;
00321 selYear--;
00322 } else if ( selMonth > 12 ) {
00323 selMonth = 1;
00324 selYear++;
00325 }
00326 selDay = i->day();
00327 }
00328
00329
00330 void DateBookMonthTable::viewportMouseReleaseEvent( QMouseEvent * )
00331 {
00332 dayClicked( currentRow(), currentColumn() );
00333 }
00334
00335 void DateBookMonthTable::getEvents()
00336 {
00337 if ( !db )
00338 return;
00339
00340 QDate dtStart( year, month, 1 );
00341 d->mMonthEvents = db->getEffectiveEvents( dtStart,
00342 QDate( year, month,
00343 dtStart.daysInMonth() ) );
00344 QValueListIterator<EffectiveEvent> it = d->mMonthEvents.begin();
00345
00346
00347
00348 while ( it != d->mMonthEvents.end() ) {
00349 QValueList<EffectiveEvent> dayEvent;
00350 EffectiveEvent e = *it;
00351 ++it;
00352 dayEvent.append( e );
00353 while ( it != d->mMonthEvents.end()
00354 && e.date() == (*it).date() ) {
00355 dayEvent.append( *it );
00356 ++it;
00357 }
00358 int row, col;
00359 findDay( e.date().day(), row, col );
00360 DayItemMonth* w = static_cast<DayItemMonth*>( item( row, col ) );
00361 w->setEvents( dayEvent );
00362 updateCell( row, col );
00363 dayEvent.clear();
00364 }
00365 }
00366
00367
00368 void DateBookMonthTable::setupLabels()
00369 {
00370 for ( int i = 0; i < 7; ++i ) {
00371
00372
00373 if ( d->onMonday )
00374 horizontalHeader()->setLabel( i, Calendar::nameOfDay( i + 1 ) );
00375 else {
00376 if ( i == 0 )
00377 horizontalHeader()->setLabel( i, Calendar::nameOfDay( 7 ) );
00378 else
00379 horizontalHeader()->setLabel( i, Calendar::nameOfDay( i ) );
00380 }
00381 }
00382 }
00383
00384
00385
00386
00387 DateBookMonth::DateBookMonth( QWidget *parent, const char *name, bool ac,
00388 DateBookDB *data )
00389 : QVBox( parent, name ),
00390 autoClose( ac )
00391 {
00392 setFocusPolicy(StrongFocus);
00393 year = QDate::currentDate().year();
00394 month = QDate::currentDate().month();
00395 day = QDate::currentDate().day();
00396 header = new DateBookMonthHeader( this, "DateBookMonthHeader" );
00397 table = new DateBookMonthTable( this, "DateBookMonthTable", data );
00398 header->setDate( year, month );
00399 table->setDate( year, month, QDate::currentDate().day() );
00400 header->setFocusPolicy(NoFocus);
00401 table->setFocusPolicy(NoFocus);
00402 connect( header, SIGNAL( dateChanged( int, int ) ),
00403 this, SLOT( setDate( int, int ) ) );
00404 connect( table, SIGNAL( dateClicked( int, int, int ) ),
00405 this, SLOT( finalDate(int, int, int) ) );
00406 connect( qApp, SIGNAL(weekChanged(bool)), this,
00407 SLOT(slotWeekChange(bool)) );
00408 table->setFocus();
00409 }
00410
00411 DateBookMonth::~DateBookMonth()
00412 {
00413
00414 }
00415
00416 void DateBookMonth::setDate( int y, int m )
00417 {
00418
00419
00420 if ( (y != year) || (m != month) ) {
00421 year = y;
00422 month = m;
00423 QDate nd( y, m, 1 );
00424 if ( nd.daysInMonth() < day )
00425 day = nd.daysInMonth();
00426 table->setDate( year, month, day );
00427 }
00428 }
00429
00430 void DateBookMonth::setDate( int y, int m, int d )
00431 {
00432 header->setDate( y, m);
00433 table->setDate( y, m, d);
00434 year = y;
00435 month = m;
00436 day = d;
00437 }
00438
00439
00440 void DateBookMonth::finalDate(int y, int m, int d)
00441 {
00442 setDate( y, m, d );
00443
00444 emit dateClicked(y, m, d);
00445
00446
00447 if ( autoClose && parentWidget() )
00448 parentWidget()->close();
00449 }
00450
00451 void DateBookMonth::setDate( QDate d)
00452 {
00453 setDate(d.year(), d.month(), d.day());
00454 }
00455
00456 void DateBookMonth::redraw()
00457 {
00458 table->setDate( year, month, day );
00459 table->redraw();
00460 }
00461
00462 QDate DateBookMonth::selectedDate() const
00463 {
00464 if ( !table )
00465 return QDate::currentDate();
00466 int y, m, d;
00467 table->getDate( y, m, d );
00468 return QDate( y, m, d );
00469 }
00470
00471 void DateBookMonth::slotWeekChange( bool startOnMonday )
00472 {
00473 table->setWeekStart( startOnMonday );
00474 }
00475
00476 void DateBookMonth::keyPressEvent( QKeyEvent *e )
00477 {
00478 switch(e->key()) {
00479 case Key_Up:
00480 setDate(QDate(year, month, day).addDays(-7));
00481 break;
00482 case Key_Down:
00483 setDate(QDate(year, month, day).addDays(7));
00484 break;
00485 case Key_Left:
00486 setDate(QDate(year, month, day).addDays(-1));
00487 break;
00488 case Key_Right:
00489 setDate(QDate(year, month, day).addDays(1));
00490 break;
00491 case Key_Space:
00492 qWarning("space");
00493 emit dateClicked(year, month, day);
00494 if ( autoClose && parentWidget() )
00495 parentWidget()->close();
00496 break;
00497 default:
00498 qWarning("ignore");
00499 e->ignore();
00500 break;
00501 }
00502 }
00503
00504
00505 class DayItemMonthPrivate
00506 {
00507 public:
00508 DayItemMonthPrivate() {};
00509 ~DayItemMonthPrivate() { mDayEvents.clear(); };
00510 QValueList<EffectiveEvent> mDayEvents;
00511 };
00512
00513 DayItemMonth::DayItemMonth( QTable *table, EditType et, const QString &t )
00514 : QTableItem( table, et, t )
00515 {
00516 d = new DayItemMonthPrivate();
00517 }
00518
00519 DayItemMonth::~DayItemMonth()
00520 {
00521 daysEvents.clear();
00522 delete d;
00523 }
00524
00525 void DayItemMonth::setEvents( const QValueList<EffectiveEvent> &effEv )
00526 {
00527 d->mDayEvents = effEv;
00528 }
00529
00530 void DayItemMonth::clearEffEvents()
00531 {
00532 d->mDayEvents.clear();
00533 }
00534
00535 void DayItemMonth::paint( QPainter *p, const QColorGroup &cg,
00536 const QRect &cr, bool selected )
00537 {
00538 p->save();
00539
00540 QColorGroup g( cg );
00541 g.setBrush( QColorGroup::Base, back );
00542 g.setColor( QColorGroup::Text, forg );
00543 if ( selected )
00544 p->setPen( g.highlightedText() );
00545 else
00546 p->setPen( g.text() );
00547
00548 QValueStack<int> normalLine;
00549 QValueStack<int> repeatLine;
00550 QValueStack<int> travelLine;
00551
00552 bool normalAllDay = FALSE;
00553 bool repeatAllDay = FALSE;
00554 bool travelAllDay = FALSE;
00555
00556 QValueListIterator<EffectiveEvent> itDays = d->mDayEvents.begin();
00557
00558 for ( ; itDays != d->mDayEvents.end(); ++itDays ) {
00559 int w = cr.width();
00560 Event ev = (*itDays).event();
00561
00562 int f = (*itDays).start().hour();
00563 int t = (*itDays).end().hour();
00564
00565 if (ev.isAllDay()) {
00566 if (!ev.hasRepeat())
00567 normalAllDay = TRUE;
00568 else
00569 repeatAllDay = TRUE;
00570 } else {
00571 int sLine, eLine;
00572 if (f == 0)
00573 sLine = 0;
00574 else if (f < 8 )
00575 sLine = 1;
00576 else if (f >= 17)
00577 sLine = w - 4;
00578 else {
00579 sLine = (f - 8) * (w - 8);
00580 if (sLine)
00581 sLine /= 8;
00582 sLine += 4;
00583 }
00584 if (t == 23)
00585 eLine = w;
00586 else if (t < 8)
00587 eLine = 4;
00588 else if (t >= 17)
00589 eLine = w - 1;
00590 else {
00591 eLine = (t - 8) * (w - 8);
00592 if (eLine)
00593 eLine /= 8;
00594 eLine += 4;
00595 }
00596 if (!ev.hasRepeat()) {
00597 normalLine.push(sLine);
00598 normalLine.push(eLine);
00599 } else {
00600 repeatLine.push(sLine);
00601 repeatLine.push(eLine);
00602 }
00603 }
00604 }
00605
00606
00607 if (normalAllDay || repeatAllDay || travelAllDay) {
00608 p->save();
00609
00610 if (normalAllDay)
00611 if (repeatAllDay) {
00612 p->fillRect( 0, 0, cr.width(), cr.height() / 2,
00613 colorNormalLight );
00614 p->fillRect( 0, cr.height() / 2, cr.width(), cr.height() / 2,
00615 colorRepeatLight );
00616 } else
00617 p->fillRect( 0, 0, cr.width(), cr.height(),
00618 colorNormalLight );
00619 else if (repeatAllDay)
00620 p->fillRect( 0, 0, cr.width(), cr.height(),
00621 colorRepeatLight );
00622 } else {
00623 p->fillRect( 0, 0, cr.width(),
00624 cr.height(), selected
00625 ? g.brush( QColorGroup::Highlight )
00626 : g.brush( QColorGroup::Base ) );
00627 }
00628
00629
00630
00631 int h = 5;
00632 int y = cr.height() / 2 - h;
00633
00634 while(normalLine.count() >= 2) {
00635 int x2 = normalLine.pop();
00636 int x1 = normalLine.pop();
00637 if (x2 < x1 + 2)
00638 x2 = x1 + 2;
00639 p->fillRect(x1, y, x2 - x1, h, colorNormal);
00640 }
00641
00642 y += h;
00643
00644 while(repeatLine.count() >= 2) {
00645 int x2 = repeatLine.pop();
00646 int x1 = repeatLine.pop();
00647 if (x2 < x1 + 2)
00648 x2 = x1 + 2;
00649 p->fillRect(x1, y, x2 - x1, h, colorRepeat);
00650 }
00651
00652
00653
00654 QFont f = p->font();
00655 f.setPointSize( ( f.pointSize() / 3 ) * 2 );
00656 p->setFont( f );
00657 QFontMetrics fm( f );
00658 p->drawText( 1, 1 + fm.ascent(), QString::number( day() ) );
00659
00660 p->restore();
00661 }
00662
00663
00664
00665 void DayItemMonth::setType( Calendar::Day::Type t )
00666 {
00667 switch ( t ) {
00668 case Calendar::Day::PrevMonth:
00669 case Calendar::Day::NextMonth:
00670 back = QBrush( QColor( 224, 224, 224 ) );
00671 forg = black;
00672 break;
00673 case Calendar::Day::ThisMonth:
00674 back = QBrush( white );
00675 forg = black;
00676 break;
00677 }
00678 typ = t;
00679 }
00680
00681
00682
00683 DateButton::DateButton( bool longDate, QWidget *parent, const char * name )
00684 :QPushButton( parent, name )
00685 {
00686 longFormat = longDate;
00687 df = DateFormat('/', DateFormat::MonthDayYear, DateFormat::MonthDayYear);
00688 setDate( QDate::currentDate() );
00689
00690 connect(this,SIGNAL(pressed()),this,SLOT(pickDate()));
00691
00692
00693 }
00694
00695
00696 void DateButton::pickDate()
00697 {
00698 static QPopupMenu *m1 = 0;
00699 static DateBookMonth *picker = 0;
00700 if ( !m1 ) {
00701 m1 = new QPopupMenu( this );
00702 picker = new DateBookMonth( m1, 0, TRUE );
00703 m1->insertItem( picker );
00704 connect( picker, SIGNAL( dateClicked( int, int, int ) ),
00705 this, SLOT( setDate( int, int, int ) ) );
00706 connect( picker, SIGNAL( dateClicked( int, int, int ) ),
00707 this, SIGNAL( dateSelected( int, int, int ) ) );
00708 connect( m1, SIGNAL( aboutToHide() ),
00709 this, SLOT( gotHide() ) );
00710 }
00711 picker->slotWeekChange( weekStartsMonday );
00712 picker->setDate( currDate.year(), currDate.month(), currDate.day() );
00713 m1->popup(mapToGlobal(QPoint(0,height())));
00714 picker->setFocus();
00715 }
00716
00717
00718 void DateButton::gotHide()
00719 {
00720
00721 setDown( false );
00722 }
00723
00724
00725
00726
00727 void DateButton::setWeekStartsMonday( int b )
00728 {
00729 weekStartsMonday = b;
00730 }
00731
00732 void DateButton::setDate( int y, int m, int d )
00733 {
00734 setDate( QDate( y,m,d) );
00735 }
00736
00737 void DateButton::setDate( QDate d )
00738 {
00739 currDate = d;
00740 setText( longFormat ? TimeString::longDateString( d, df ) :
00741 TimeString::shortDate( d, df ) );
00742
00743 }
00744
00745 void DateButton::setDateFormat( DateFormat f )
00746 {
00747 df = f;
00748 setDate( currDate );
00749 }
00750
00751 bool DateButton::customWhatsThis() const
00752 {
00753 return TRUE;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762 DateBookMonthPopup::DateBookMonthPopup ( QWidget *w )
00763 : QPopupMenu ( w )
00764 {
00765 m_dbm = new DateBookMonth( this, 0, TRUE );
00766 insertItem( m_dbm );
00767 }