00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kdganttdatetimegrid.h"
00024 #include "kdganttdatetimegrid_p.h"
00025
00026 #include "kdganttabstractrowcontroller.h"
00027
00028 #include <QApplication>
00029 #include <QDateTime>
00030 #include <QPainter>
00031 #include <QStyle>
00032 #include <QStyleOptionHeader>
00033 #include <QWidget>
00034 #include <QDebug>
00035
00036 #include <cassert>
00037
00038 using namespace KDGantt;
00039
00049
00050
00051
00052 qreal DateTimeGrid::Private::dateTimeToChartX( const QDateTime& dt ) const
00053 {
00054 assert( startDateTime.isValid() );
00055 qreal result = startDateTime.date().daysTo(dt.date())*24.*60.*60.;
00056 result += startDateTime.time().msecsTo(dt.time())/1000.;
00057 result *= dayWidth/( 24.*60.*60. );
00058
00059 return result;
00060 }
00061
00062 QDateTime DateTimeGrid::Private::chartXtoDateTime( qreal x ) const
00063 {
00064 assert( startDateTime.isValid() );
00065 int days = static_cast<int>( x/dayWidth );
00066 qreal secs = x*( 24.*60.*60. )/dayWidth;
00067 QDateTime dt = startDateTime;
00068 QDateTime result = dt.addDays( days )
00069 .addSecs( static_cast<int>(secs-(days*24.*60.*60.) ) )
00070 .addMSecs( qRound( ( secs-static_cast<int>( secs ) )*1000. ) );
00071 return result;
00072 }
00073
00074 #define d d_func()
00075
00076 DateTimeGrid::DateTimeGrid() : AbstractGrid( new Private )
00077 {
00078 }
00079
00080 DateTimeGrid::~DateTimeGrid()
00081 {
00082 }
00083
00088 QDateTime DateTimeGrid::startDateTime() const
00089 {
00090 return d->startDateTime;
00091 }
00092
00098 void DateTimeGrid::setStartDateTime( const QDateTime& dt )
00099 {
00100 d->startDateTime = dt;
00101 emit gridChanged();
00102 }
00103
00108 qreal DateTimeGrid::dayWidth() const
00109 {
00110 return d->dayWidth;
00111 }
00112
00118 void DateTimeGrid::setDayWidth( qreal w )
00119 {
00120 qDebug()<<"DateTimeGrid::setDayWidth"<<w;
00121 d->dayWidth = qMax( w, qreal(1.0) );
00122 emit gridChanged();
00123 }
00124
00130 void DateTimeGrid::setScale( Scale s )
00131 {
00132 d->scale = s;
00133 emit gridChanged();
00134 }
00135
00142 DateTimeGrid::Scale DateTimeGrid::scale() const
00143 {
00144 return d->scale;
00145 }
00146
00152 void DateTimeGrid::setWeekStart( Qt::DayOfWeek ws )
00153 {
00154 d->weekStart = ws;
00155 emit gridChanged();
00156 }
00157
00159 Qt::DayOfWeek DateTimeGrid::weekStart() const
00160 {
00161 return d->weekStart;
00162 }
00163
00170 void DateTimeGrid::setFreeDays( const QSet<Qt::DayOfWeek>& fd )
00171 {
00172 d->freeDays = fd;
00173 emit gridChanged();
00174 }
00175
00177 bool DateTimeGrid::rowSeparators() const
00178 {
00179 return d->rowSeparators;
00180 }
00182 void DateTimeGrid::setRowSeparators( bool enable )
00183 {
00184 d->rowSeparators = enable;
00185 }
00186
00188 QSet<Qt::DayOfWeek> DateTimeGrid::freeDays() const
00189 {
00190 return d->freeDays;
00191 }
00192
00196 Span DateTimeGrid::mapToChart( const QModelIndex& idx ) const
00197 {
00198 assert( model() );
00199 if ( !idx.isValid() ) return Span();
00200 assert( idx.model()==model() );
00201 const QVariant sv = model()->data( idx, StartTimeRole );
00202 const QVariant ev = model()->data( idx, EndTimeRole );
00203 if( qVariantCanConvert<QDateTime>(sv) &&
00204 qVariantCanConvert<QDateTime>(ev) &&
00205 !(sv.type() == QVariant::String && qVariantValue<QString>(sv).isEmpty()) &&
00206 !(ev.type() == QVariant::String && qVariantValue<QString>(ev).isEmpty())
00207 ) {
00208 QDateTime st = sv.toDateTime();
00209 QDateTime et = ev.toDateTime();
00210 if ( et.isValid() && st.isValid() ) {
00211 qreal sx = d->dateTimeToChartX( st );
00212 qreal ex = d->dateTimeToChartX( et )-sx;
00213
00214 return Span( sx, ex);
00215 }
00216 }
00217
00218 if( qVariantCanConvert<QDateTime>(sv) && !(sv.type() == QVariant::String && qVariantValue<QString>(sv).isEmpty()) ) {
00219 QDateTime st = sv.toDateTime();
00220 if ( st.isValid() ) {
00221 qreal sx = d->dateTimeToChartX( st );
00222 return Span( sx, 0 );
00223 }
00224 }
00225 return Span();
00226 }
00227
00228 #if 0
00229 static void debug_print_idx( const QModelIndex& idx )
00230 {
00231 if ( !idx.isValid() ) {
00232 qDebug() << "[Invalid]";
00233 return;
00234 }
00235 QDateTime st = idx.data( StartTimeRole ).toDateTime();
00236 QDateTime et = idx.data( StartTimeRole ).toDateTime();
00237 qDebug() << idx << "["<<st<<et<<"]";
00238 }
00239 #endif
00240
00255 bool DateTimeGrid::mapFromChart( const Span& span, const QModelIndex& idx,
00256 const QList<Constraint>& constraints ) const
00257 {
00258 assert( model() );
00259 if ( !idx.isValid() ) return false;
00260 assert( idx.model()==model() );
00261
00262 QDateTime st = d->chartXtoDateTime(span.start());
00263 QDateTime et = d->chartXtoDateTime(span.start()+span.length());
00264
00265 Q_FOREACH( const Constraint& c, constraints ) {
00266 if ( c.type() != Constraint::TypeHard || !isSatisfiedConstraint( c )) continue;
00267 if ( c.startIndex() == idx ) {
00268 QDateTime tmpst = model()->data( c.endIndex(), StartTimeRole ).toDateTime();
00269
00270 if ( tmpst<et ) return false;
00271 } else if ( c.endIndex() == idx ) {
00272 QDateTime tmpet = model()->data( c.startIndex(), EndTimeRole ).toDateTime();
00273
00274 if ( tmpet>st ) return false;
00275 }
00276 }
00277 return model()->setData( idx, qVariantFromValue(st), StartTimeRole )
00278 && model()->setData( idx, qVariantFromValue(et), EndTimeRole );
00279 }
00280
00281 int DateTimeGrid::autoScale() const
00282 {
00283 int scale = ScaleDay;
00284 if ( dayWidth() > 450) {
00285 scale = ScaleHour;
00286 } else if (dayWidth() * 7 < 20) {
00287 scale = ScaleMonth;
00288 } else if (dayWidth() < 12) {
00289 scale = ScaleWeek;
00290 }
00291 return scale;
00292 }
00293
00294 void DateTimeGrid::paintGrid( QPainter* painter,
00295 const QRectF& sceneRect,
00296 const QRectF& exposedRect,
00297 AbstractRowController* rowController,
00298 QWidget* widget )
00299 {
00300
00301
00302 paintRowGrid(painter,sceneRect,exposedRect,rowController,widget);
00303
00304 switch(scale()) {
00305 case ScaleHour:
00306 paintHourGrid(painter,sceneRect,exposedRect,rowController,widget);
00307 break;
00308 case ScaleDay:
00309 paintDayGrid(painter,sceneRect,exposedRect,rowController,widget);
00310 break;
00311 case ScaleWeek:
00312 paintWeekGrid(painter,sceneRect,exposedRect,rowController,widget);
00313 break;
00314 case ScaleMonth:
00315 paintMonthGrid(painter,sceneRect,exposedRect,rowController,widget);
00316 break;
00317 case ScaleAuto:
00318 switch(autoScale()) {
00319 case ScaleHour:
00320 paintHourGrid(painter,sceneRect,exposedRect,rowController,widget);
00321 break;
00322 case ScaleDay:
00323 paintDayGrid(painter,sceneRect,exposedRect,rowController,widget);
00324 break;
00325 case ScaleWeek:
00326 paintWeekGrid(painter,sceneRect,exposedRect,rowController,widget);
00327 break;
00328 case ScaleMonth:
00329 paintMonthGrid(painter,sceneRect,exposedRect,rowController,widget);
00330 break;
00331 }
00332 break;
00333 }
00334 }
00335
00336 void DateTimeGrid::paintHourGrid( QPainter* painter,
00337 const QRectF& sceneRect,
00338 const QRectF& exposedRect,
00339 AbstractRowController* rowController,
00340 QWidget* widget )
00341 {
00342
00343 QDateTime dt = d->chartXtoDateTime( exposedRect.left() );
00344 dt.setTime( QTime( dt.time().hour(), 0, 0, 0 ) );
00345 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right(); dt = dt.addSecs( 60*60 ),x=d->dateTimeToChartX( dt ) ) {
00346 QPen pen = painter->pen();
00347 pen.setBrush( QApplication::palette().dark() );
00348 if ( dt.time() == QTime( 23, 0, 0 ) ) {
00349 pen.setStyle( Qt::SolidLine );
00350 } else {
00351 pen.setStyle( Qt::DashLine );
00352 }
00353 painter->setPen( pen );
00354 x += ( dayWidth() / 24.0 ) - 1;
00355 painter->drawLine( QPointF( x, exposedRect.top() ), QPointF( x, exposedRect.bottom() ) );
00356 }
00357 }
00358
00359 void DateTimeGrid::paintDayGrid( QPainter* painter,
00360 const QRectF& sceneRect,
00361 const QRectF& exposedRect,
00362 AbstractRowController* rowController,
00363 QWidget* widget )
00364 {
00365
00366 QDateTime dt = d->chartXtoDateTime( exposedRect.left() );
00367 dt.setTime( QTime( 0, 0, 0, 0 ) );
00368 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right(); dt = dt.addDays( 1 ),x=d->dateTimeToChartX( dt ) ) {
00369 QPen pen = painter->pen();
00370 pen.setBrush( QApplication::palette().dark() );
00371 if ( dt.date().addDays( 1 ).dayOfWeek() == d->weekStart ) {
00372 pen.setStyle( Qt::SolidLine );
00373 } else {
00374 pen.setStyle( Qt::DashLine );
00375 }
00376 painter->setPen( pen );
00377 paintFreeDay( painter, x, exposedRect, dt.date(), widget );
00378 x += dayWidth() - 1;
00379 painter->drawLine( QPointF( x, exposedRect.top() ), QPointF( x, exposedRect.bottom() ) );
00380 }
00381 }
00382
00383 void DateTimeGrid::paintWeekGrid( QPainter* painter,
00384 const QRectF& sceneRect,
00385 const QRectF& exposedRect,
00386 AbstractRowController* rowController,
00387 QWidget* widget )
00388 {
00389
00390 QDateTime dt = d->chartXtoDateTime( exposedRect.left() );
00391 dt.setTime( QTime( 0, 0, 0, 0 ) );
00392 while ( dt.date().dayOfWeek() != d->weekStart ) dt = dt.addDays( -1 );
00393 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right(); dt = dt.addDays( 1 ),x=d->dateTimeToChartX( dt ) ) {
00394 QPen pen = painter->pen();
00395 pen.setBrush( QApplication::palette().dark() );
00396 if ( dt.date().addDays( 1 ).day() == 1 ) {
00397 pen.setStyle( Qt::SolidLine );
00398 } else if ( dt.date().addDays( 1 ).dayOfWeek() == d->weekStart ) {
00399 pen.setStyle( Qt::DashLine );
00400 } else {
00401 pen.setStyle( Qt::NoPen );
00402 }
00403 painter->setPen( pen );
00404 paintFreeDay( painter, x, exposedRect, dt.date(), widget );
00405 if ( pen.style() != Qt::NoPen ) {
00406
00407 x += dayWidth() - 1;
00408 painter->drawLine( QPointF( x, exposedRect.top() ), QPointF( x, exposedRect.bottom() ) );
00409 }
00410 }
00411 }
00412
00413 void DateTimeGrid::paintMonthGrid( QPainter* painter,
00414 const QRectF& sceneRect,
00415 const QRectF& exposedRect,
00416 AbstractRowController* rowController,
00417 QWidget* widget )
00418 {
00419
00420 QDateTime dt = d->chartXtoDateTime( exposedRect.left() );
00421 dt.setTime( QTime( 0, 0, 0, 0 ) );
00422 dt = dt.addDays( 1 - dt.date().day() );
00423 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right(); dt = dt.addDays( 1 ),x=d->dateTimeToChartX( dt ) ) {
00424 QPen pen = painter->pen();
00425 pen.setBrush( QApplication::palette().dark() );
00426 if ( dt.date().addMonths( 1 ).month() == 1 && dt.date().addDays( 1 ).day() == 1 ) {
00427 pen.setStyle( Qt::SolidLine );
00428 } else if ( dt.date().addDays( 1 ).day() == 1 ) {
00429 pen.setStyle( Qt::DashLine );
00430 } else {
00431 pen.setStyle( Qt::NoPen );
00432 }
00433 painter->setPen( pen );
00434 paintFreeDay( painter, x, exposedRect, dt.date(), widget );
00435 if ( pen.style() != Qt::NoPen ) {
00436
00437 x += dayWidth() - 1;
00438 painter->drawLine( QPointF( x, exposedRect.top() ), QPointF( x, exposedRect.bottom() ) );
00439 }
00440 }
00441 }
00442
00443 void DateTimeGrid::paintFreeDay( QPainter* painter, qreal x, const QRectF& exposedRect, const QDate &dt, QWidget* widget )
00444 {
00445 if ( d->freeDays.contains( static_cast<Qt::DayOfWeek>( dt.dayOfWeek() ) ) ) {
00446
00447 painter->setBrush( widget ? widget->palette().alternateBase() : QApplication::palette().alternateBase() );
00448 painter->fillRect( QRectF( x, exposedRect.top(), dayWidth(), exposedRect.height() ), painter->brush() );
00449 }
00450 }
00451
00452 void DateTimeGrid::paintRowGrid( QPainter* painter,
00453 const QRectF& sceneRect,
00454 const QRectF& exposedRect,
00455 AbstractRowController* rowController,
00456 QWidget* widget )
00457 {
00458 if ( rowController && rowSeparators() ) {
00459
00460 QPen pen = painter->pen();
00461 pen.setBrush( QApplication::palette().dark() );
00462 pen.setStyle( Qt::DashLine );
00463 painter->setPen( pen );
00464 QModelIndex idx = rowController->indexAt( qRound( exposedRect.top() ) );
00465 qreal y = 0;
00466 while ( y < exposedRect.bottom() && idx.isValid() ) {
00467 const Span s = rowController->rowGeometry( idx );
00468 y = s.start()+s.length();
00469
00470
00471 if ( idx.row()%2 ) painter->fillRect( QRectF( exposedRect.x(), s.start(), exposedRect.width(), s.length() ), QApplication::palette().alternateBase() );
00472 idx = rowController->indexBelow( idx );
00473 }
00474 }
00475 }
00476
00477 void DateTimeGrid::render( QPainter* painter, const QRectF &target, const QRectF& headerRect, const QRectF& exposedRect, QWidget *widget, Qt::AspectRatioMode aspectRatioMode )
00478 {
00479 painter->save();
00480
00481 qreal xratio = target.width() / exposedRect.width();
00482 qreal yratio = target.height() / exposedRect.height();
00483
00484
00485 switch (aspectRatioMode) {
00486 case Qt::KeepAspectRatio:
00487 xratio = yratio = qMin(xratio, yratio);
00488 break;
00489 case Qt::KeepAspectRatioByExpanding:
00490 xratio = yratio = qMax(xratio, yratio);
00491 break;
00492 case Qt::IgnoreAspectRatio:
00493 break;
00494 }
00495
00496
00497
00498 painter->setClipRect( target );
00499 QTransform painterTransform;
00500 painterTransform *= QTransform()
00501 .translate(target.left(), target.top())
00502 .scale(xratio, yratio)
00503 .translate(-exposedRect.left(), -exposedRect.top());
00504 painter->setWorldTransform(painterTransform, true);
00505
00506 paintHeader( painter, headerRect, exposedRect, 0.0, widget );
00507 painter->restore();
00508 }
00509
00510 void DateTimeGrid::paintHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
00511 qreal offset, QWidget* widget )
00512 {
00513 switch(scale()) {
00514 case ScaleHour: paintHourScaleHeader(painter,headerRect,exposedRect,offset,widget); break;
00515 case ScaleDay: paintDayScaleHeader(painter,headerRect,exposedRect,offset,widget); break;
00516 case ScaleWeek: paintWeekScaleHeader(painter,headerRect,exposedRect,offset,widget); break;
00517 case ScaleMonth: paintMonthScaleHeader(painter,headerRect,exposedRect,offset,widget); break;
00518 case ScaleAuto:
00519 switch(autoScale()) {
00520 case ScaleHour:
00521 paintHourScaleHeader(painter,headerRect,exposedRect,offset,widget);
00522 break;
00523 case ScaleDay:
00524 paintDayScaleHeader(painter,headerRect,exposedRect,offset,widget);
00525 break;
00526 case ScaleWeek:
00527 paintWeekScaleHeader(painter,headerRect,exposedRect,offset,widget);
00528 break;
00529 case ScaleMonth:
00530 paintMonthScaleHeader(painter,headerRect,exposedRect,offset,widget);
00531 break;
00532 }
00533 break;
00534 }
00535 }
00536
00540 void DateTimeGrid::paintHourScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
00541 qreal offset, QWidget* widget )
00542 {
00543 QStyle* style = widget?widget->style():QApplication::style();
00544
00545
00546 QDateTime dt = d->chartXtoDateTime( offset+exposedRect.left() );
00547 dt.setTime( QTime( dt.time().hour(), 0, 0, 0 ) );
00548 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right()+offset;
00549 dt = dt.addSecs( 60*60 ),x=d->dateTimeToChartX( dt ) ) {
00550 QStyleOptionHeader opt;
00551 opt.init( widget );
00552 opt.rect = QRectF( x-offset, headerRect.top()+headerRect.height()/2., dayWidth()/24., headerRect.height()/2. ).toRect();
00553 opt.text = dt.time().toString( QString::fromAscii( "hh" ) );
00554 opt.textAlignment = Qt::AlignCenter;
00555 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00556 }
00557
00558 dt = d->chartXtoDateTime( offset+exposedRect.left() );
00559 dt.setTime( QTime( 0, 0, 0, 0 ) );
00560
00561 for ( qreal x2 = d->dateTimeToChartX( dt ); x2 < exposedRect.right()+offset;
00562 dt = dt.addDays( 1 ),x2=d->dateTimeToChartX( dt ) ) {
00563 QStyleOptionHeader opt;
00564 opt.init( widget );
00565 opt.rect = QRectF( x2-offset, headerRect.top(), dayWidth(), headerRect.height()/2. ).toRect();
00566 opt.text = QDate::longDayName( dt.date().dayOfWeek() );
00567 opt.textAlignment = Qt::AlignCenter;
00568 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00569 }
00570 }
00571
00575 void DateTimeGrid::paintDayScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
00576 qreal offset, QWidget* widget )
00577 {
00578
00579 QStyle* style = widget?widget->style():QApplication::style();
00580
00581
00582 QDateTime dt = d->chartXtoDateTime( offset+exposedRect.left() );
00583 dt.setTime( QTime( 0, 0, 0, 0 ) );
00584 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right()+offset;
00585 dt = dt.addDays( 1 ),x=d->dateTimeToChartX( dt ) ) {
00586 QStyleOptionHeader opt;
00587 opt.init( widget );
00588 opt.rect = QRectF( x-offset, headerRect.top()+headerRect.height()/2., dayWidth(), headerRect.height()/2. ).toRect();
00589 opt.text = dt.toString( QString::fromAscii( "ddd" ) ).left( 1 );
00590 opt.textAlignment = Qt::AlignCenter;
00591 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00592 }
00593
00594 dt = d->chartXtoDateTime( offset+exposedRect.left() );
00595 dt.setTime( QTime( 0, 0, 0, 0 ) );
00596
00597 while ( dt.date().dayOfWeek() != d->weekStart ) dt = dt.addDays( -1 );
00598
00599 for ( qreal x2 = d->dateTimeToChartX( dt ); x2 < exposedRect.right()+offset;
00600 dt = dt.addDays( 7 ),x2=d->dateTimeToChartX( dt ) ) {
00601 QStyleOptionHeader opt;
00602 opt.init( widget );
00603 opt.rect = QRectF( x2-offset, headerRect.top(), dayWidth()*7., headerRect.height()/2. ).toRect();
00604 opt.text = QString::number( dt.date().weekNumber() );
00605 opt.textAlignment = Qt::AlignCenter;
00606 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00607 }
00608 }
00609
00613 void DateTimeGrid::paintWeekScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
00614 qreal offset, QWidget* widget )
00615 {
00616 QStyle* style = widget?widget->style():QApplication::style();
00617
00618
00619 QDateTime sdt = d->chartXtoDateTime( offset+exposedRect.left() );
00620 sdt.setTime( QTime( 0, 0, 0, 0 ) );
00621
00622 while ( sdt.date().dayOfWeek() != d->weekStart ) sdt = sdt.addDays( -1 );
00623 QDateTime dt = sdt;
00624 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right()+offset;
00625 dt = dt.addDays( 7 ),x=d->dateTimeToChartX( dt ) ) {
00626 QStyleOptionHeader opt;
00627 opt.init( widget );
00628 opt.rect = QRectF( x-offset, headerRect.top()+headerRect.height()/2., dayWidth()*7, headerRect.height()/2. ).toRect();
00629 opt.text = QString::number( dt.date().weekNumber() );
00630 opt.textAlignment = Qt::AlignCenter;
00631 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00632 }
00633
00634
00635 dt = sdt;
00636 for ( qreal x2 = d->dateTimeToChartX( dt ); x2 < exposedRect.right()+offset; x2=d->dateTimeToChartX( dt ) ) {
00637
00638 QDate next = dt.date().addMonths( 1 );
00639 next = next.addDays( 1 - next.day() );
00640
00641 QStyleOptionHeader opt;
00642 opt.init( widget );
00643 opt.rect = QRectF( x2-offset, headerRect.top(), dayWidth()*dt.date().daysTo( next ), headerRect.height()/2. ).toRect();
00644 opt.text = QDate::longMonthName( dt.date().month() );
00645 opt.textAlignment = Qt::AlignCenter;
00646 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00647
00648 dt.setDate( next );
00649 }
00650 }
00651
00655 void DateTimeGrid::paintMonthScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
00656 qreal offset, QWidget* widget )
00657 {
00658 QStyle* style = widget?widget->style():QApplication::style();
00659
00660
00661 QDateTime sdt = d->chartXtoDateTime( offset+exposedRect.left() );
00662 sdt.setTime( QTime( 0, 0, 0, 0 ) );
00663 sdt = sdt.addDays( 1 - sdt.date().day() );
00664 QDateTime dt = sdt;
00665 for ( qreal x = d->dateTimeToChartX( dt ); x < exposedRect.right()+offset;
00666 dt = dt.addMonths( 1 ),x=d->dateTimeToChartX( dt ) ) {
00667 QStyleOptionHeader opt;
00668 opt.init( widget );
00669 opt.rect = QRectF( x-offset, headerRect.top()+headerRect.height()/2., dayWidth()*dt.date().daysInMonth(), headerRect.height()/2. ).toRect();
00670 opt.text = QDate::shortMonthName( dt.date().month() );
00671 opt.textAlignment = Qt::AlignCenter;
00672 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00673 }
00674
00675
00676 dt = sdt;
00677 for ( qreal x2 = d->dateTimeToChartX( dt ); x2 < exposedRect.right()+offset; x2=d->dateTimeToChartX( dt ) ) {
00678
00679 QDate next = dt.date().addYears( 1 );
00680 next = next.addMonths( 1 - next.month() );
00681
00682 QStyleOptionHeader opt;
00683 opt.init( widget );
00684 opt.rect = QRectF( x2-offset, headerRect.top(), dayWidth()*dt.date().daysTo( next ), headerRect.height()/2. ).toRect();
00685 opt.text = QString::number( dt.date().year() );
00686 opt.textAlignment = Qt::AlignCenter;
00687 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
00688
00689 dt.setDate( next );
00690 }
00691 }
00692
00693 #undef d
00694
00695 #ifndef KDAB_NO_UNIT_TESTS
00696
00697 #include <QStandardItemModel>
00698 #include "unittest/test.h"
00699
00700 namespace {
00701 std::ostream& operator<<( std::ostream& os, const QDateTime& dt )
00702 {
00703 os << dt.toString().toStdString();
00704 return os;
00705 }
00706 }
00707
00708 KDAB_SCOPED_UNITTEST_SIMPLE( KDGantt, DateTimeGrid, "test" ) {
00709 QStandardItemModel model( 3, 2 );
00710 DateTimeGrid grid;
00711 QDateTime dt = QDateTime::currentDateTime();
00712 grid.setModel( &model );
00713 grid.setStartDateTime( dt.addDays( -10 ) );
00714
00715 model.setData( model.index( 0, 0 ), dt, StartTimeRole );
00716 model.setData( model.index( 0, 0 ), dt.addDays( 17 ), EndTimeRole );
00717
00718 model.setData( model.index( 2, 0 ), dt.addDays( 18 ), StartTimeRole );
00719 model.setData( model.index( 2, 0 ), dt.addDays( 19 ), EndTimeRole );
00720
00721 Span s = grid.mapToChart( model.index( 0, 0 ) );
00722
00723
00724 assertTrue( s.start()>0 );
00725 assertTrue( s.length()>0 );
00726
00727 grid.mapFromChart( s, model.index( 1, 0 ) );
00728
00729 QDateTime s1 = model.data( model.index( 0, 0 ), StartTimeRole ).toDateTime();
00730 QDateTime e1 = model.data( model.index( 0, 0 ), EndTimeRole ).toDateTime();
00731 QDateTime s2 = model.data( model.index( 1, 0 ), StartTimeRole ).toDateTime();
00732 QDateTime e2 = model.data( model.index( 1, 0 ), EndTimeRole ).toDateTime();
00733
00734 assertTrue( s1.isValid() );
00735 assertTrue( e1.isValid() );
00736 assertTrue( s2.isValid() );
00737 assertTrue( e2.isValid() );
00738
00739 assertEqual( s1, s2 );
00740 assertEqual( e1, e2 );
00741
00742 assertTrue( grid.