KGantt

kganttdatetimegrid.cpp
1 /*
2  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3  *
4  * This file is part of the KGantt library.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "kganttdatetimegrid.h"
10 #include "kganttdatetimegrid_p.h"
11 
12 #include "kganttabstractrowcontroller.h"
13 
14 #include <QApplication>
15 #include <QDateTime>
16 #include <QPainter>
17 #include <QPainterPath>
18 #include <QStyle>
19 #include <QStyleOptionHeader>
20 #include <QWidget>
21 #include <QString>
22 #include <QDebug>
23 #include <QList>
24 #include <QPainterPath>
25 
26 #include <cassert>
27 
28 using namespace KGantt;
29 
30 QDebug operator<<( QDebug dbg, KGantt::DateTimeScaleFormatter::Range range )
31 {
32  switch ( range ) {
33  case KGantt::DateTimeScaleFormatter::Second: dbg << "KGantt::DateTimeScaleFormatter::Second"; break;
34  case KGantt::DateTimeScaleFormatter::Minute: dbg << "KGantt::DateTimeScaleFormatter::Minute"; break;
35  case KGantt::DateTimeScaleFormatter::Hour: dbg << "KGantt::DateTimeScaleFormatter::Hour"; break;
36  case KGantt::DateTimeScaleFormatter::Day: dbg << "KGantt::DateTimeScaleFormatter::Day"; break;
37  case KGantt::DateTimeScaleFormatter::Week: dbg << "KGantt::DateTimeScaleFormatter::Week"; break;
38  case KGantt::DateTimeScaleFormatter::Month: dbg << "KGantt::DateTimeScaleFormatter::Month"; break;
39  case KGantt::DateTimeScaleFormatter::Year: dbg << "KGantt::DateTimeScaleFormatter::Year"; break;
40  }
41  return dbg;
42 }
43 
44 
45 
46 
47 qreal DateTimeGrid::Private::dateTimeToChartX( const QDateTime& dt ) const
48 {
49  assert( startDateTime.isValid() );
50  qreal result = startDateTime.date().daysTo(dt.date())*24.*60.*60.;
51  result += startDateTime.time().msecsTo(dt.time())/1000.;
52  result *= dayWidth/( 24.*60.*60. );
53 
54  return result;
55 }
56 
57 QDateTime DateTimeGrid::Private::chartXtoDateTime( qreal x ) const
58 {
59  assert( startDateTime.isValid() );
60  int days = static_cast<int>( x/dayWidth );
61  qreal secs = x*( 24.*60.*60. )/dayWidth;
63  QDateTime result = dt.addDays( days )
64  .addSecs( static_cast<int>(secs-(days*24.*60.*60.) ) )
65  .addMSecs( qRound( ( secs-static_cast<int>( secs ) )*1000. ) );
66  return result;
67 }
68 
69 #define d d_func()
70 
71 
72 
73 
75  const QString& templ, Qt::Alignment alignment )
76  : _d( new Private( range, format, templ, alignment ) )
77 {
78 }
79 
81  : _d( new Private( range, format, QString::fromLatin1( "%1" ), alignment ) )
82 {
83 }
84 
86  : _d( new Private( other.range(), other.format(), other.d->templ, other.alignment() ) )
87 {
88 }
89 
90 DateTimeScaleFormatter::~DateTimeScaleFormatter()
91 {
92  delete _d;
93 }
94 
95 DateTimeScaleFormatter& DateTimeScaleFormatter::operator=( const DateTimeScaleFormatter& other )
96 {
97  if ( this == &other )
98  return *this;
99 
100  delete _d;
101  _d = new Private( other.range(), other.format(), other.d->templ, other.alignment() );
102  return *this;
103 }
104 
105 
107 {
108  return d->format;
109 }
110 
111 
113 {
114  QString result = d->format;
115  // additional feature: Weeknumber
116  const QString shortWeekNumber = QString::number( datetime.date().weekNumber()) + QLatin1String("/")
117  + QString::number( datetime.date().year());
118  const QString longWeekNumber = ( shortWeekNumber.length() == 1 ? QString::fromLatin1( "0" ) : QString() ) + shortWeekNumber;
119  result.replace( QString::fromLatin1( "ww" ), longWeekNumber );
120  result.replace( QString::fromLatin1( "w" ), shortWeekNumber );
121  result = datetime.toLocalTime().toString( result );
122  return result;
123 }
124 
125 QString DateTimeScaleFormatter::text( const QDateTime& datetime ) const
126 {
127  return d->templ.arg( format( datetime ) );
128 }
129 
130 
131 DateTimeScaleFormatter::Range DateTimeScaleFormatter::range() const
132 {
133  return d->range;
134 }
135 
136 Qt::Alignment DateTimeScaleFormatter::alignment() const
137 {
138  return d->alignment;
139 }
140 
141 
143 {
144  QDateTime result = datetime;
145  switch ( d->range )
146  {
147  case Second:
148  result = result.addSecs( 60 );
149  break;
150  case Minute:
151  // set it to the begin of the next minute
152  result.setTime( QTime( result.time().hour(), result.time().minute() ) );
153  result = result.addSecs( 60 );
154  break;
155  case Hour:
156  // set it to the begin of the next hour
157  result.setTime( QTime( result.time().hour(), 0 ) );
158  result = result.addSecs( 60 * 60 );
159  break;
160  case Day:
161  // set it to midnight the next day
162  result.setTime( QTime( 0, 0 ) );
163  result = result.addDays( 1 );
164  break;
165  case Week:
166  // set it to midnight
167  result.setTime( QTime( 0, 0 ) );
168  // iterate day-wise, until weekNumber changes
169  {
170  const int weekNumber = result.date().weekNumber();
171  while ( weekNumber == result.date().weekNumber() )
172  result = result.addDays( 1 );
173  }
174  break;
175  case Month:
176  // set it to midnight
177  result.setTime( QTime( 0, 0 ) );
178  // set it to the first of the next month
179  result.setDate( QDate( result.date().year(), result.date().month(), 1 ).addMonths( 1 ) );
180  break;
181  case Year:
182  // set it to midnight
183  result.setTime( QTime( 0, 0 ) );
184  // set it to the first of the next year
185  result.setDate( QDate( result.date().year(), 1, 1 ).addYears( 1 ) );
186  break;
187  }
188  //result = result.toLocalTime();
189  assert( result != datetime );
190  //qDebug() << "DateTimeScaleFormatter::nextRangeBegin("<<datetime<<")="<<d->range<<result;
191  return result;
192 }
193 
194 
196 {
197  QDateTime result = datetime;
198  switch ( d->range )
199  {
200  case Second:
201  break; // nothing
202  case Minute:
203  // set it to the begin of the current minute
204  result.setTime( QTime( result.time().hour(), result.time().minute() ) );
205  break;
206  case Hour:
207  // set it to the begin of the current hour
208  result.setTime( QTime( result.time().hour(), 0 ) );
209  break;
210  case Day:
211  // set it to midnight the current day
212  result.setTime( QTime( 0, 0 ) );
213  break;
214  case Week:
215  // set it to midnight
216  result.setTime( QTime( 0, 0 ) );
217  // iterate day-wise, as long weekNumber is the same
218  {
219  const int weekNumber = result.date().weekNumber();
220  while ( weekNumber == result.date().addDays( -1 ).weekNumber() )
221  result = result.addDays( -1 );
222  }
223  break;
224  case Month:
225  // set it to midnight
226  result.setTime( QTime( 0, 0 ) );
227  // set it to the first of the current month
228  result.setDate( QDate( result.date().year(), result.date().month(), 1 ) );
229  break;
230  case Year:
231  // set it to midnight
232  result.setTime( QTime( 0, 0 ) );
233  // set it to the first of the current year
234  result.setDate( QDate( result.date().year(), 1, 1 ) );
235  break;
236  }
237  return result;
238 }
239 
240 DateTimeGrid::DateTimeGrid() : AbstractGrid( new Private )
241 {
242 }
243 
244 DateTimeGrid::~DateTimeGrid()
245 {
246 }
247 
248 
250 {
251  return d->startDateTime;
252 }
253 
254 
256 {
257  d->startDateTime = dt;
258  Q_EMIT gridChanged();
259 }
260 
261 
263 {
264  return d->dayWidth;
265 }
266 
267 
269 {
270  return d->dateTimeToChartX( dt );
271 }
272 
273 
275 {
276  return d->chartXtoDateTime( x );
277 }
278 
279 
281 {
282  assert( w>0 );
283  d->dayWidth = w;
284  Q_EMIT gridChanged();
285 }
286 
287 
288 void DateTimeGrid::setScale( Scale s )
289 {
290  d->scale = s;
291  Q_EMIT gridChanged();
292 }
293 
294 
295 DateTimeGrid::Scale DateTimeGrid::scale() const
296 {
297  return d->scale;
298 }
299 
300 
302 {
303  delete d->lower;
304  d->lower = lower;
305  Q_EMIT gridChanged();
306 }
307 
308 
310 {
311  delete d->upper;
312  d->upper = upper;
313  Q_EMIT gridChanged();
314 }
315 
316 
318 {
319  return d->lower;
320 }
321 
322 
324 {
325  return d->upper;
326 }
327 
328 
330 {
331  d->weekStart = ws;
332  Q_EMIT gridChanged();
333 }
334 
335 
337 {
338  return d->weekStart;
339 }
340 
341 
343 {
344  d->freeDays = fd;
345  Q_EMIT gridChanged();
346 }
347 
348 
350 {
351  return d->freeDays;
352 }
353 
354 
356 {
357  d->freeDaysBrush = brush;
358 }
359 
360 
362 {
363  return d->freeDaysBrush;
364 }
365 
366 
368 {
369  return d->rowSeparators;
370 }
371 
373 {
374  d->rowSeparators = enable;
375 }
376 
377 
379 {
380  d->noInformationBrush = brush;
381  Q_EMIT gridChanged();
382 }
383 
384 
386 {
387  return d->noInformationBrush;
388 }
389 
390 
391 qreal DateTimeGrid::mapToChart( const QVariant& value ) const
392 {
393  if ( ! value.canConvert( QVariant::DateTime ) ||
394  ( value.type() == QVariant::String && value.toString().isEmpty() ) )
395  {
396  return -1.0;
397  }
398  return d->dateTimeToChartX( value.toDateTime() );
399 }
400 
401 
403 {
404  return d->chartXtoDateTime( x );
405 }
406 
407 
409 {
410  assert( model() );
411  if ( !idx.isValid() ) return Span();
412  assert( idx.model()==model() );
413  const QVariant sv = model()->data( idx, StartTimeRole );
414  const QVariant ev = model()->data( idx, EndTimeRole );
415  if ( sv.canConvert( QVariant::DateTime ) &&
417  !(sv.type() == QVariant::String && sv.toString().isEmpty()) &&
418  !(ev.type() == QVariant::String && ev.toString().isEmpty())
419  ) {
420  QDateTime st = sv.toDateTime();
421  QDateTime et = ev.toDateTime();
422  if ( et.isValid() && st.isValid() ) {
423  qreal sx = d->dateTimeToChartX( st );
424  qreal ex = d->dateTimeToChartX( et )-sx;
425  //qDebug() << "DateTimeGrid::mapToChart("<<st<<et<<") => "<< Span( sx, ex );
426  return Span( sx, ex);
427  }
428  }
429  // Special case for Events with only a start date
430  if ( sv.canConvert( QVariant::DateTime ) && !(sv.type() == QVariant::String && sv.toString().isEmpty()) ) {
431  QDateTime st = sv.toDateTime();
432  if ( st.isValid() ) {
433  qreal sx = d->dateTimeToChartX( st );
434  return Span( sx, 0 );
435  }
436  }
437  return Span();
438 }
439 
440 #if 0
441 static void debug_print_idx( const QModelIndex& idx )
442 {
443  if ( !idx.isValid() ) {
444  qDebug() << "[Invalid]";
445  return;
446  }
447  QDateTime st = idx.data( StartTimeRole ).toDateTime();
448  QDateTime et = idx.data( EndTimeRole ).toDateTime();
449  qDebug() << idx << "["<<st<<et<<"]";
450 }
451 #endif
452 
453 
454 bool DateTimeGrid::mapFromChart( const Span& span, const QModelIndex& idx,
455  const QList<Constraint>& constraints ) const
456 {
457  assert( model() );
458  if ( !idx.isValid() ) return false;
459  assert( idx.model()==model() );
460 
461  QDateTime st = d->chartXtoDateTime(span.start());
462  QDateTime et = d->chartXtoDateTime(span.start()+span.length());
463  //qDebug() << "DateTimeGrid::mapFromChart("<<span<<") => "<< st << et;
464  for ( const Constraint& c : constraints ) {
465  if ( c.type() != Constraint::TypeHard || !isSatisfiedConstraint( c )) continue;
466  if ( c.startIndex() == idx ) {
467  QDateTime tmpst = model()->data( c.endIndex(), StartTimeRole ).toDateTime();
468  //qDebug() << tmpst << "<" << et <<"?";
469  if ( tmpst<et ) return false;
470  } else if ( c.endIndex() == idx ) {
471  QDateTime tmpet = model()->data( c.startIndex(), EndTimeRole ).toDateTime();
472  //qDebug() << tmpet << ">" << st <<"?";
473  if ( tmpet>st ) return false;
474  }
475  }
476 
477  return model()->setData( idx, QVariant::fromValue(st), StartTimeRole )
478  && model()->setData( idx, QVariant::fromValue(et), EndTimeRole );
479 }
480 
481 Qt::PenStyle DateTimeGrid::Private::gridLinePenStyle( QDateTime dt, Private::HeaderType headerType ) const
482 {
483  switch ( headerType ) {
484  case Private::HeaderHour:
485  // Midnight
486  if ( dt.time().hour() == 0 )
487  return Qt::SolidLine;
488  return Qt::DashLine;
489  case Private::HeaderDay:
490  // First day of the week
491  if ( dt.date().dayOfWeek() == weekStart )
492  return Qt::SolidLine;
493  return Qt::DashLine;
494  case Private::HeaderWeek:
495  // First day of the month
496  if ( dt.date().day() == 1 )
497  return Qt::SolidLine;
498  // First day of the week
499  if ( dt.date().dayOfWeek() == weekStart )
500  return Qt::DashLine;
501  return Qt::NoPen;
502  case Private::HeaderMonth:
503  // First day of the year
504  if ( dt.date().dayOfYear() == 1 )
505  return Qt::SolidLine;
506  // First day of the month
507  if ( dt.date().day() == 1 )
508  return Qt::DashLine;
509  return Qt::NoPen;
510  default:
511  // Nothing to do here
512  break;
513  }
514 
515  // Default
516  return Qt::NoPen;
517 }
518 
519 QDateTime DateTimeGrid::Private::adjustDateTimeForHeader( QDateTime dt, Private::HeaderType headerType ) const
520 {
521  // In any case, set time to 00:00:00:00
522  dt.setTime( QTime( 0, 0, 0, 0 ) );
523 
524  switch ( headerType ) {
525  case Private::HeaderWeek:
526  // Set day to beginning of the week
527  while ( dt.date().dayOfWeek() != weekStart )
528  dt = dt.addDays( -1 );
529  break;
530  case Private::HeaderMonth:
531  // Set day to beginning of the month
532  dt = dt.addDays( 1 - dt.date().day() );
533  break;
534  case Private::HeaderYear:
535  // Set day to first day of the year
536  dt = dt.addDays( 1 - dt.date().dayOfYear() );
537  break;
538  default:
539  // In any other case, we don't need to adjust the date time
540  break;
541  }
542 
543  return dt;
544 }
545 
546 void DateTimeGrid::Private::paintVerticalLines( QPainter* painter,
547  const QRectF& sceneRect,
548  const QRectF& exposedRect,
549  QWidget* widget,
550  Private::HeaderType headerType )
551 {
552  QDateTime dt = chartXtoDateTime( exposedRect.left() );
553  dt = adjustDateTimeForHeader( dt, headerType );
554 
555  int offsetSeconds = 0;
556  int offsetDays = 0;
557  // Determine the time step per grid line
558  if ( headerType == Private::HeaderHour )
559  offsetSeconds = 60*60;
560  else
561  offsetDays = 1;
562 
563  for ( qreal x = dateTimeToChartX( dt ); x < exposedRect.right();
564  dt = dt.addSecs( offsetSeconds ), dt = dt.addDays( offsetDays ), x = dateTimeToChartX( dt ) ) {
565  //TODO not the best solution as it might be one paint too much, but i don't know what
566  //causes the test to fail yet, i think it might be a rounding error
567  //if ( x >= exposedRect.left() ) {
568  QPen pen = painter->pen();
569  pen.setBrush( QApplication::palette().dark() );
570  pen.setStyle( gridLinePenStyle( dt, headerType ) );
571  painter->setPen( pen );
572  if ( freeDays.contains( static_cast<Qt::DayOfWeek>( dt.date().dayOfWeek() ) ) ) {
573  if (freeDaysBrush.style() == Qt::NoBrush)
574  painter->setBrush( widget?widget->palette().midlight()
576  else
577  painter->setBrush(freeDaysBrush);
578 
579  painter->fillRect( QRectF( x, exposedRect.top(), dayWidth, exposedRect.height() ), painter->brush() );
580  }
581  painter->drawLine( QPointF( x, sceneRect.top() ), QPointF( x, sceneRect.bottom() ) );
582  //}
583  }
584 }
585 
586 void DateTimeGrid::Private::paintVerticalUserDefinedLines( QPainter* painter,
587  const QRectF& sceneRect,
588  const QRectF& exposedRect,
589  QWidget* widget )
590 {
591  Q_UNUSED( widget );
592  DateTimeScaleFormatter *lowerFormatter, *upperFormatter;
593  switch ( scale ) {
594  case ScaleUserDefined:
595  lowerFormatter = lower;
596  upperFormatter = upper;
597  break;
598  default:
599  getAutomaticFormatters( &lowerFormatter, &upperFormatter );
600  break;
601  }
602  QPen pen = painter->pen();
603  pen.setBrush( QApplication::palette().dark() );
604 
605  // Do freeDays, we need to iterate over all dates
606  QDateTime dtLeft = chartXtoDateTime( exposedRect.left() );
607  if ( ! freeDays.isEmpty() ) {
608  QDate lastDate = chartXtoDateTime( exposedRect.right() ).date();
609  for (QDateTime date(dtLeft.date(), QTime()); date.date() <= lastDate; date = date.addDays(1)) {
610  if ( freeDays.contains( static_cast<Qt::DayOfWeek>( date.date().dayOfWeek() ) ) ) {
611  if (freeDaysBrush.style() == Qt::NoBrush) {
612  painter->setBrush( widget?widget->palette().midlight():QApplication::palette().midlight() );
613  } else {
614  painter->setBrush(freeDaysBrush);
615  }
616  qreal x = dateTimeToChartX( date );
617  painter->fillRect( QRectF( x, exposedRect.top(), dayWidth, exposedRect.height() ), painter->brush() );
618  }
619  }
620  }
621  QDateTime dt = upperFormatter->currentRangeBegin( dtLeft );
622  // Get all upper scale gridline x values to avoid mixing with lower scale gridlines
623  QList<qreal> upperXList;
624  for ( qreal x = dateTimeToChartX( dt ); x < exposedRect.right(); dt = upperFormatter->nextRangeBegin( dt ), x=dateTimeToChartX( dt ) ) {
625  upperXList.append(x);
626  }
627  dt = lowerFormatter->currentRangeBegin( dtLeft );
628  for ( qreal x = dateTimeToChartX( dt ); x < exposedRect.right();
629  dt = lowerFormatter->nextRangeBegin( dt ),x=dateTimeToChartX( dt ) )
630  {
631  if (!upperXList.contains(x)) {
632  pen.setStyle( Qt::DashLine );
633  painter->setPen( pen );
634  painter->drawLine( QPointF( x, sceneRect.top() ), QPointF( x, sceneRect.bottom() ) );
635  }
636  }
637  dt = upperFormatter->currentRangeBegin( dtLeft );
638  for ( qreal x : upperXList )
639  {
640  pen.setStyle( Qt::SolidLine );
641  painter->setPen( pen );
642  painter->drawLine( QPointF( x, sceneRect.top() ), QPointF( x, sceneRect.bottom() ) );
643  }
644 }
645 
646 DateTimeGrid::Private::HeaderType DateTimeGrid::Private::headerTypeForScale( DateTimeGrid::Scale scale )
647 {
648  switch ( scale ) {
649  case ScaleHour:
650  return Private::HeaderHour;
651  case ScaleDay:
652  return Private::HeaderDay;
653  case ScaleWeek:
654  return Private::HeaderWeek;
655  case ScaleMonth:
656  return Private::HeaderMonth;
657  default:
658  // There are no specific header types for any other scale!
659  assert( false );
660  break;
661  }
662  return Private::HeaderDay;
663 }
664 
666  const QRectF& sceneRect,
667  const QRectF& exposedRect,
668  AbstractRowController* rowController,
669  QWidget* widget )
670 {
671  switch ( scale() ) {
672  case ScaleHour:
673  case ScaleDay:
674  case ScaleWeek:
675  case ScaleMonth:
676  d->paintVerticalLines( painter, sceneRect, exposedRect, widget, d->headerTypeForScale( scale() ) );
677  break;
678  case ScaleAuto:
679  case ScaleUserDefined:
680  d->paintVerticalUserDefinedLines( painter, sceneRect, exposedRect, widget );
681  break;
682  }
683  if ( rowController ) {
684  // First draw the rows
685  QPen pen = painter->pen();
686  pen.setBrush( QApplication::palette().dark() );
687  pen.setStyle( Qt::DashLine );
688  painter->setPen( pen );
689  QModelIndex idx = rowController->indexAt( qRound( exposedRect.top() ) );
690  if ( rowController->indexAbove( idx ).isValid() ) idx = rowController->indexAbove( idx );
691  qreal y = 0;
692  while ( y < exposedRect.bottom() && idx.isValid() ) {
693  const Span s = rowController->rowGeometry( idx );
694  y = s.start()+s.length();
695  if ( d->rowSeparators ) {
696  painter->drawLine( QPointF( sceneRect.left(), y ),
697  QPointF( sceneRect.right(), y ) );
698  }
699  if ( !idx.data( ItemTypeRole ).isValid() && d->noInformationBrush.style() != Qt::NoBrush ) {
700  painter->fillRect( QRectF( exposedRect.left(), s.start(), exposedRect.width(), s.length() ), d->noInformationBrush );
701  }
702  // Is alternating background better?
703  //if ( idx.row()%2 ) painter->fillRect( QRectF( exposedRect.x(), s.start(), exposedRect.width(), s.length() ), QApplication::palette().alternateBase() );
704  idx = rowController->indexBelow( idx );
705  }
706  }
707 }
708 
709 int DateTimeGrid::Private::tabHeight( const QString& txt, QWidget* widget ) const
710 {
711  QStyleOptionHeader opt;
712  if ( widget ) opt.initFrom( widget );
713  else opt.palette = QApplication::palette();
714  opt.text = txt;
715  QStyle* style;
716  if ( widget ) style = widget->style();
717  else style = QApplication::style();
718  QSize s = style->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), widget);
719  return s.height();
720 }
721 
722 void DateTimeGrid::Private::getAutomaticFormatters( DateTimeScaleFormatter** lower, DateTimeScaleFormatter** upper)
723 {
724  const qreal tabw = QApplication::fontMetrics().boundingRect( QLatin1String( "XXXXX" ) ).width();
725  const qreal dayw = dayWidth;
726  if ( dayw > 24*60*60*tabw ) {
727  *lower = &minute_lower;
728  *upper = &minute_upper;
729  } else if ( dayw > 24*60*tabw ) {
730  *lower = &hour_lower;
731  *upper = &hour_upper;
732  } else if ( dayw > 24*tabw ) {
733  *lower = &day_lower;
734  *upper = &day_upper;
735  } else if ( dayw > tabw ) {
736  *lower = &week_lower;
737  *upper = &week_upper;
738  } else if ( 4*dayw > tabw ) {
739  *lower = &month_lower;
740  *upper = &month_upper;
741  } else {
742  *lower = &year_lower;
743  *upper = &year_upper;
744  }
745 }
746 
747 void DateTimeGrid::Private::getFormatters( DateTimeScaleFormatter** lower, DateTimeScaleFormatter** upper)
748 {
749  switch ( scale ) {
750  case DateTimeGrid::ScaleHour:
751  *lower = &hour_lower;
752  *upper = &hour_upper;
753  break;
754  case DateTimeGrid::ScaleDay:
755  *lower = &day_lower;
756  *upper = &day_upper;
757  break;
758  case DateTimeGrid::ScaleWeek:
759  *lower = &week_lower;
760  *upper = &week_upper;
761  break;
762  case DateTimeGrid::ScaleMonth:
763  *lower = &month_lower;
764  *upper = &month_upper;
765  break;
766  case DateTimeGrid::ScaleUserDefined:
767  *lower = this->lower;
768  *upper = this->upper;
769  break;
770  default: /*ScaleAuto:*/
771  getAutomaticFormatters( lower, upper );
772  break;
773  }
774 }
775 
776 DateTimeGrid::HeaderType DateTimeGrid::sectionHandleAtPos(int x, int y, const QRect &headerRect) const
777 {
778  QDateTime dt1 = d->chartXtoDateTime( x );
779  QDateTime dt2 = d->chartXtoDateTime( x + 5 );
780 
781  DateTimeScaleFormatter *lower, *upper;
782  const_cast<Private*>(d)->getFormatters( &lower, &upper );
783 
784  const qreal lowerHeight = d->tabHeight( lower->text( dt1 ) );
785  const qreal upperHeight = d->tabHeight( upper->text( dt1 ) );
786  const qreal upperRatio = upperHeight/( lowerHeight+upperHeight );
787 
788  const QRectF upperHeaderRect( x, headerRect.top(), 5, headerRect.height() * upperRatio );
789  const QRectF lowerHeaderRect( x, upperHeaderRect.bottom()+1, 5, headerRect.height()-upperHeaderRect.height()-1 );
790  if ( upperHeaderRect.contains( QPoint( x , y ) ) ) {
791  return upper->currentRangeBegin(dt2) == upper->nextRangeBegin(dt1) ? UpperHeader : NoHeader;
792  }
793  if (lowerHeaderRect.contains( QPoint( x , y ) ) ) {
794  return lower->currentRangeBegin(dt2)==lower->nextRangeBegin(dt1) ? LowerHeader : NoHeader;
795  }
796  return NoHeader;
797 }
798 
799 void DateTimeGrid::paintHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
800  qreal offset, QWidget* widget )
801 {
802  painter->save();
803  QPainterPath clipPath;
804  clipPath.addRect( headerRect );
805  painter->setClipPath( clipPath, Qt::IntersectClip );
806  switch ( scale() )
807  {
808  case ScaleHour:
809  paintHourScaleHeader( painter, headerRect, exposedRect, offset, widget );
810  break;
811  case ScaleDay:
812  paintDayScaleHeader( painter, headerRect, exposedRect, offset, widget );
813  break;
814  case ScaleWeek:
815  paintWeekScaleHeader( painter, headerRect, exposedRect, offset, widget );
816  break;
817  case ScaleMonth:
818  paintMonthScaleHeader( painter, headerRect, exposedRect, offset, widget );
819  break;
820  case ScaleAuto:
821  {
822  DateTimeScaleFormatter *lower, *upper;
823  d->getAutomaticFormatters( &lower, &upper );
824  const qreal lowerHeight = d->tabHeight( lower->text( startDateTime() ) );
825  const qreal upperHeight = d->tabHeight( upper->text( startDateTime() ) );
826  const qreal upperRatio = upperHeight/( lowerHeight+upperHeight );
827 
828  const QRectF upperHeaderRect( headerRect.x(), headerRect.top(), headerRect.width()-1, headerRect.height() * upperRatio );
829  const QRectF lowerHeaderRect( headerRect.x(), upperHeaderRect.bottom()+1, headerRect.width()-1, headerRect.height()-upperHeaderRect.height()-1 );
830 
831  paintUserDefinedHeader( painter, lowerHeaderRect, exposedRect, offset, lower, widget );
832  paintUserDefinedHeader( painter, upperHeaderRect, exposedRect, offset, upper, widget );
833  break;
834  }
835  case ScaleUserDefined:
836  {
837  const qreal lowerHeight = d->tabHeight( d->lower->text( startDateTime() ) );
838  const qreal upperHeight = d->tabHeight( d->upper->text( startDateTime() ) );
839  const qreal upperRatio = upperHeight/( lowerHeight+upperHeight );
840 
841  const QRectF upperHeaderRect( headerRect.x(), headerRect.top(), headerRect.width()-1, headerRect.height() * upperRatio );
842  const QRectF lowerHeaderRect( headerRect.x(), upperHeaderRect.bottom()+1, headerRect.width()-1, headerRect.height()-upperHeaderRect.height()-1 );
843 
844  paintUserDefinedHeader( painter, lowerHeaderRect, exposedRect, offset, d->lower, widget );
845  paintUserDefinedHeader( painter, upperHeaderRect, exposedRect, offset, d->upper, widget );
846  }
847  break;
848  }
849  painter->restore();
850 }
851 
852 void DateTimeGrid::paintUserDefinedHeader( QPainter* painter,
853  const QRectF& headerRect, const QRectF& exposedRect,
854  qreal offset, const DateTimeScaleFormatter* formatter,
855  QWidget* widget )
856 {
857  const QStyle* const style = widget ? widget->style() : QApplication::style();
858 
859  QDateTime dt = formatter->currentRangeBegin( d->chartXtoDateTime( offset + exposedRect.left() ));
860  qreal x = d->dateTimeToChartX( dt );
861 
862  while ( x < exposedRect.right() + offset ) {
863  const QDateTime next = formatter->nextRangeBegin( dt );
864  const qreal nextx = d->dateTimeToChartX( next );
865 
866  QStyleOptionHeader opt;
867  if ( widget ) opt.init( widget );
868  else opt.palette = QApplication::palette();
869  opt.rect = QRectF( x - offset+1, headerRect.top(), qMax<qreal>( 1., nextx-x-1 ), headerRect.height() ).toAlignedRect();
870  opt.textAlignment = formatter->alignment();
871  opt.text = formatter->text( dt );
872  style->drawControl( QStyle::CE_Header, &opt, painter, widget );
873 
874  dt = next;
875  x = nextx;
876  }
877 }
878 
879 void DateTimeGrid::Private::paintHeader( QPainter* painter,
880  const QRectF& headerRect, const QRectF& exposedRect,
881  qreal offset, QWidget* widget,
882  Private::HeaderType headerType,
883  DateTextFormatter *formatter )
884 {
885  QStyle* style = widget?widget->style():QApplication::style();
886 
887  const qreal left = exposedRect.left() + offset;
888  const qreal right = exposedRect.right() + offset;
889 
890  // Paint a section for each hour
891  QDateTime dt = chartXtoDateTime( left );
892  dt = adjustDateTimeForHeader( dt, headerType );
893  // Determine the time step per grid line
894  int offsetSeconds = 0;
895  int offsetDays = 0;
896  int offsetMonths = 0;
897 
898  switch ( headerType ) {
899  case Private::HeaderHour:
900  offsetSeconds = 60*60;
901  break;
902  case Private::HeaderDay:
903  offsetDays = 1;
904  break;
905  case Private::HeaderWeek:
906  offsetDays = 7;
907  break;
908  case Private::HeaderMonth:
909  offsetMonths = 1;
910  break;
911  case Private::HeaderYear:
912  offsetMonths = 12;
913  break;
914  default:
915  // Other scales cannot be painted with this method!
916  assert( false );
917  break;
918  }
919 
920  for ( qreal x = dateTimeToChartX( dt ); x < right;
921  dt = dt.addSecs( offsetSeconds ), dt = dt.addDays( offsetDays ), dt = dt.addMonths( offsetMonths ),
922  x = dateTimeToChartX( dt ) ) {
923  QStyleOptionHeader opt;
924  if ( widget ) opt.init( widget );
925  else opt.palette = QApplication::palette();
926  opt.rect = formatter->textRect( x, offset, dayWidth, headerRect, dt );
927  opt.text = formatter->format( dt );
928  opt.textAlignment = Qt::AlignCenter;
929  style->drawControl(QStyle::CE_Header, &opt, painter, widget);
930  }
931  delete formatter;
932  formatter = nullptr;
933 }
934 
935 
937  const QRectF& headerRect, const QRectF& exposedRect,
938  qreal offset, QWidget* widget )
939 {
940  class HourFormatter : public Private::DateTextFormatter {
941  public:
942  ~HourFormatter() override {}
943 
944  QString format( const QDateTime& dt ) override {
945  return dt.time().toString( QString::fromLatin1( "hh" ) );
946  }
947  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
948  Q_UNUSED(dt);
949 
950  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset + 1.0, headerRect.height() / 2.0 ),
951  QSizeF( dayWidth / 24.0, headerRect.height() / 2.0 ) ).toAlignedRect();
952  }
953  };
954  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
955  Private::HeaderHour, new HourFormatter ); // Custom parameters
956 
957  class DayFormatter : public Private::DateTextFormatter {
958  public:
959  ~DayFormatter() override {}
960  QString format( const QDateTime& dt ) override {
961  return dt.date().toString();
962  }
963  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
964  Q_UNUSED(dt);
965 
966  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset, 0.0 ),
967  QSizeF( dayWidth, headerRect.height() / 2.0 ) ).toRect();
968  }
969  };
970  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
971  Private::HeaderDay, new DayFormatter ); // Custom parameters
972 }
973 
974 
975 void DateTimeGrid::paintDayScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
976  qreal offset, QWidget* widget )
977 {
978  class DayFormatter : public Private::DateTextFormatter {
979  public:
980  ~DayFormatter() override {}
981 
982  QString format( const QDateTime& dt ) override {
983  return dt.toString( QString::fromLatin1( "ddd" ) ).left( 1 );
984  }
985  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
986  Q_UNUSED(dt);
987 
988  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset + 1.0, headerRect.height() / 2.0 ),
989  QSizeF( dayWidth, headerRect.height() / 2.0 ) ).toAlignedRect();
990  }
991  };
992  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
993  Private::HeaderDay, new DayFormatter ); // Custom parameters
994 
995  class WeekFormatter : public Private::DateTextFormatter {
996  public:
997  ~WeekFormatter() override {}
998  QString format( const QDateTime& dt ) override {
999  return QString::number(dt.date().weekNumber()) + QLatin1String("/") + QString::number(dt.date().year());
1000  }
1001  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
1002  Q_UNUSED(dt);
1003 
1004  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset, 0.0 ),
1005  QSizeF( dayWidth * 7, headerRect.height() / 2.0 ) ).toRect();
1006  }
1007  };
1008  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
1009  Private::HeaderWeek, new WeekFormatter ); // Custom parameters
1010 }
1011 
1012 
1013 void DateTimeGrid::paintWeekScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
1014  qreal offset, QWidget* widget )
1015 {
1016  class WeekFormatter : public Private::DateTextFormatter {
1017  public:
1018  ~WeekFormatter() override {}
1019 
1020  QString format( const QDateTime& dt ) override {
1021  return QString::number( dt.date().weekNumber() );
1022  }
1023  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
1024  Q_UNUSED(dt);
1025 
1026  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset, headerRect.height() / 2.0 ),
1027  QSizeF( dayWidth * 7, headerRect.height() / 2.0 ) ).toRect();
1028  }
1029  };
1030  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
1031  Private::HeaderWeek, new WeekFormatter ); // Custom parameters
1032 
1033  class MonthFormatter : public Private::DateTextFormatter {
1034  public:
1035  ~MonthFormatter() override {}
1036 
1037  QString format( const QDateTime& dt ) override {
1039  }
1040  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
1041  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset, 0.0 ),
1042  QSizeF( dayWidth * dt.date().daysInMonth(), headerRect.height() / 2.0 ) ).toRect();
1043  }
1044  };
1045  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
1046  Private::HeaderMonth, new MonthFormatter ); // Custom parameters
1047 }
1048 
1049 
1050 void DateTimeGrid::paintMonthScaleHeader( QPainter* painter, const QRectF& headerRect, const QRectF& exposedRect,
1051  qreal offset, QWidget* widget )
1052 {
1053  class MonthFormatter : public Private::DateTextFormatter {
1054  public:
1055  ~MonthFormatter() override {}
1056 
1057  QString format( const QDateTime& dt ) override {
1059  }
1060  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
1061  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset, headerRect.height() / 2.0 ),
1062  QSizeF( dayWidth * dt.date().daysInMonth(), headerRect.height() / 2.0 ) ).toRect();
1063  }
1064  };
1065  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
1066  Private::HeaderMonth, new MonthFormatter ); // Custom parameters
1067 
1068  class YearFormatter : public Private::DateTextFormatter {
1069  public:
1070  ~YearFormatter() override {}
1071 
1072  QString format( const QDateTime& dt ) override {
1073  return QString::number( dt.date().year() );
1074  }
1075  QRect textRect( qreal x, qreal offset, qreal dayWidth, const QRectF& headerRect, const QDateTime& dt ) override {
1076  return QRectF( QPointF( x, headerRect.top() ) + QPointF( -offset, 0.0 ),
1077  QSizeF( dayWidth * dt.date().daysInYear(), headerRect.height() / 2.0 ) ).toRect();
1078  }
1079  };
1080  d->paintHeader( painter, headerRect, exposedRect, offset, widget, // General parameters
1081  Private::HeaderYear, new YearFormatter ); // Custom parameters
1082 }
1083 
1084 
1085 void DateTimeGrid::drawDayBackground(QPainter* painter, const QRectF& rect, const QDate& date)
1086 {
1087  Q_UNUSED(date);
1088  if (d->timeLine->options() & DateTimeTimeLine::Background) {
1089  d->drawTimeLine(painter, rect);
1090  }
1091 }
1092 
1093 
1094 void DateTimeGrid::drawDayForeground(QPainter* painter, const QRectF& rect, const QDate& date)
1095 {
1096  Q_UNUSED(date);
1097  if (d->timeLine->options() & DateTimeTimeLine::Foreground) {
1098  d->drawTimeLine(painter, rect);
1099  }
1100 }
1101 
1102 
1103 QRectF DateTimeGrid::computeRect(const QDateTime& from, const QDateTime& to, const QRectF& rect) const
1104 {
1105  qreal topLeft = d->dateTimeToChartX(from);
1106  qreal topRight = d->dateTimeToChartX(to);
1107 
1108  return QRectF(topLeft, rect.top(), topRight - topLeft, rect.height());
1109 }
1110 
1111 
1113 {
1114  QDateTime start;
1115  QDateTime end;
1116 
1117  start = d->chartXtoDateTime(rect.left());
1118  end = d->chartXtoDateTime(rect.right());
1119 
1120  return qMakePair(start, end);
1121 }
1122 
1124 {
1125  int offset = (int)dayWidth();
1126 
1127  assert( offset>0 );
1128 
1129  // Figure out the date at the extreme left
1130  QDate date = d->chartXtoDateTime(rect.left()).date();
1131 
1132  // We need to paint from one end to the other
1133  int startx = rect.left();
1134  int endx = rect.right();
1135 
1136  // Save the painter state
1137  paint->save();
1138 
1139  // Paint the first date column
1140  while (1)
1141  {
1142  QDate nextDate = d->chartXtoDateTime(startx+1).date();
1143  if (date != nextDate)
1144  {
1145  QRectF dayRect(startx-dayWidth(), rect.top(), dayWidth(), rect.height());
1146  dayRect = dayRect.adjusted(1, 0, 0, 0);
1147  drawDayBackground(paint, dayRect, date);
1148  break;
1149  }
1150 
1151  ++startx;
1152  }
1153 
1154  // Paint the remaining dates
1155  for (int i=startx; i<endx; i+=offset)
1156  {
1157  date = d->chartXtoDateTime(i+1).date();
1158 
1159  QRectF dayRect(i, rect.top(), dayWidth(), rect.height());
1160  dayRect = dayRect.adjusted(1, 0, 0, 0);
1161  drawDayBackground(paint, dayRect, date);
1162  }
1163 
1164  // Restore the painter state
1165  paint->restore();
1166 }
1167 
1169 {
1170  int offset = (int)dayWidth();
1171 
1172  // Figure out the date at the extreme left
1173  QDate date = d->chartXtoDateTime(rect.left()).date();
1174 
1175  // We need to paint from one end to the other
1176  int startx = rect.left();
1177  int endx = rect.right();
1178 
1179  // Save the painter state
1180  paint->save();
1181 
1182  // Paint the first date column
1183  while (1)
1184  {
1185  QDate nextDate = d->chartXtoDateTime(startx+1).date();
1186  if (date != nextDate)
1187  {
1188  QRectF dayRect(startx-dayWidth(), rect.top(), dayWidth(), rect.height());
1189  dayRect = dayRect.adjusted(1, 0, 0, 0);
1190  drawDayForeground(paint, dayRect, date);
1191  break;
1192  }
1193 
1194  ++startx;
1195  }
1196 
1197  // Paint the remaining dates
1198  for (int i=startx; i<endx; i+=offset)
1199  {
1200  date = d->chartXtoDateTime(i+1).date();
1201 
1202  QRectF dayRect(i, rect.top(), dayWidth(), rect.height());
1203  dayRect = dayRect.adjusted(1, 0, 0, 0);
1204  drawDayForeground(paint, dayRect, date);
1205  }
1206 
1207  // Restore the painter state
1208  paint->restore();
1209 }
1210 
1211 
1213 {
1214  return d->timeLine;
1215 }
1216 
1217 void DateTimeGrid::Private::drawTimeLine(QPainter* painter, const QRectF& rect)
1218 {
1219  qreal x = dateTimeToChartX(timeLine->dateTime());
1220  if (rect.contains(x, rect.top())) {
1221  painter->save();
1222  painter->setPen(timeLine->pen());
1223  painter->drawLine(x, rect.top(), x, rect.bottom());
1224  painter->restore();
1225  }
1226 }
1227 
1228 #undef d
1229 
1230 #ifndef KDAB_NO_UNIT_TESTS
1231 
1232 #include <QStandardItemModel>
1233 #include "unittest/test.h"
1234 
1235 static std::ostream& operator<<( std::ostream& os, const QDateTime& dt )
1236 {
1237 #ifdef QT_NO_STL
1238  os << dt.toString().toLatin1().constData();
1239 #else
1240  os << dt.toString().toStdString();
1241 #endif
1242  return os;
1243 }
1244 
1245 KDAB_SCOPED_UNITTEST_SIMPLE( KGantt, DateTimeGrid, "test" ) {
1246  QStandardItemModel model( 3, 2 );
1247  DateTimeGrid grid;
1249  grid.setModel( &model );
1250  QDateTime startdt = dt.addDays( -10 );
1251  grid.setStartDateTime( startdt );
1252 
1253  model.setData( model.index( 0, 0 ), dt, StartTimeRole );
1254  model.setData( model.index( 0, 0 ), dt.addDays( 17 ), EndTimeRole );
1255 
1256  model.setData( model.index( 2, 0 ), dt.addDays( 18 ), StartTimeRole );
1257  model.setData( model.index( 2, 0 ), dt.addDays( 19 ), EndTimeRole );
1258 
1259  Span s = grid.mapToChart( model.index( 0, 0 ) );
1260  //qDebug() << "span="<<s;
1261 
1262  assertTrue( s.start()>0 );
1263  assertTrue( s.length()>0 );
1264 
1265  assertTrue( startdt == grid.mapToDateTime( grid.mapFromDateTime( startdt ) ) );
1266 
1267  grid.mapFromChart( s, model.index( 1, 0 ) );
1268 
1269  QDateTime s1 = model.data( model.index( 0, 0 ), StartTimeRole ).toDateTime();
1270  QDateTime e1 = model.data( model.index( 0, 0 ), EndTimeRole ).toDateTime();
1271  QDateTime s2 = model.data( model.index( 1, 0 ), StartTimeRole ).toDateTime();
1272  QDateTime e2 = model.data( model.index( 1, 0 ), EndTimeRole ).toDateTime();
1273 
1274  assertTrue( s1.isValid() );
1275  assertTrue( e1.isValid() );
1276  assertTrue( s2.isValid() );
1277  assertTrue( e2.isValid() );
1278 
1279  assertEqual( s1, s2 );
1280  assertEqual( e1, e2 );
1281 
1282  assertTrue( grid.isSatisfiedConstraint( Constraint( model.index( 0, 0 ), model.index( 2, 0 ) ) ) );
1283  assertFalse( grid.isSatisfiedConstraint( Constraint( model.index( 2, 0 ), model.index( 0, 0 ) ) ) );
1284 
1285  s = grid.mapToChart( model.index( 0, 0 ) );
1286  s.setEnd( s.end()+100000. );
1287  bool rc = grid.mapFromChart( s, model.index( 0, 0 ) );
1288  assertTrue( rc );
1289  assertEqual( s1, model.data( model.index( 0, 0 ), StartTimeRole ).toDateTime() );
1290  Span newspan = grid.mapToChart( model.index( 0, 0 ) );
1291  assertEqual( newspan.start(), s.start() );
1292  assertEqual( newspan.length(), s.length() );
1293 
1294  {
1295  QDateTime startDateTime = QDateTime::currentDateTime();
1296  qreal dayWidth = 100;
1297  QDate currentDate = QDate::currentDate();
1298  QDateTime dt( QDate(currentDate.year(), 1, 1), QTime( 0, 0, 0, 0 ) );
1299  assert( dt.isValid() );
1300  qreal result = startDateTime.date().daysTo(dt.date())*24.*60.*60.;
1301  result += startDateTime.time().msecsTo(dt.time())/1000.;
1302  result *= dayWidth/( 24.*60.*60. );
1303 
1304  int days = static_cast<int>( result/dayWidth );
1305  qreal secs = result*( 24.*60.*60. )/dayWidth;
1306  QDateTime dt2 = startDateTime;
1307  QDateTime result2 = dt2.addDays( days ).addSecs( static_cast<int>(secs-(days*24.*60.*60.) ) ).addMSecs( qRound( ( secs-static_cast<int>( secs ) )*1000. ) );
1308 
1309  assertEqual( dt, result2 );
1310  }
1311 }
1312 
1313 #endif /* KDAB_NO_UNIT_TESTS */
1314 
1315 #include "moc_kganttdatetimegrid.cpp"
QString monthName(int month, QLocale::FormatType type) const const
bool canConvert(int targetTypeId) const const
std::string toStdString() const const
qint64 daysTo(const QDate &d) const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
QSet< Qt::DayOfWeek > freeDays() const
QString toString(Qt::DateFormat format) const const
int minute() const const
The item type.
Definition: kganttglobal.h:217
QDateTime addMonths(int nmonths) const const
void setNoInformationBrush(const QBrush &brush)
bool isSatisfiedConstraint(const Constraint &c) const
void setStyle(Qt::PenStyle style)
virtual void paintMonthScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
QRect toRect() const const
Display the timeline in the background.
void setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
void fillRect(const QRectF &rectangle, const QBrush &brush)
virtual void drawDayForeground(QPainter *painter, const QRectF &rect, const QDate &date)
PenStyle
virtual QVariant data(const QModelIndex &index, int role) const const override
QString toString(Qt::DateFormat format) const const
virtual QModelIndex indexAbove(const QModelIndex &idx) const =0
QString toString(Qt::DateFormat format) const const
qreal x() const const
const QBrush & midlight() const const
QDateTime toDateTime() const const
QStyle * style() const const
Abstract baseclass for row controllers. A row controller is used by the GraphicsView to nagivate the ...
Start time (or other start value) for a gantt item.
Definition: kganttglobal.h:214
void setStartDateTime(const QDateTime &dt)
void setTime(const QTime &time)
int daysInYear() const const
bool contains(const QRectF &rectangle) const const
void save()
QRectF computeRect(const QDateTime &from, const QDateTime &to, const QRectF &rect) const
Return the rectangle that represents the date-range.
QTime time() const const
int msecsTo(const QTime &t) const const
qreal top() const const
int height() const const
DateTimeScaleFormatter * userDefinedLowerScale() const
int day() const const
virtual QModelIndex indexBelow(const QModelIndex &idx) const =0
void drawBackground(QPainter *paint, const QRectF &rect) override
QBrush freeDaysBrush() const
void drawLine(const QLineF &line)
void setUserDefinedUpperScale(DateTimeScaleFormatter *upper)
void setBrush(const QBrush &brush)
void drawForeground(QPainter *paint, const QRectF &rect) override
int weekNumber(int *yearNumber) const const
virtual QDateTime nextRangeBegin(const QDateTime &datetime) const
qreal left() const const
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override
typedef Alignment
void initFrom(const QWidget *widget)
Span mapToChart(const QModelIndex &idx) const override
qreal bottom() const const
A class used to represent a dependency.
qreal mapFromDateTime(const QDateTime &dt) const
bool isValid() const const
int dayOfWeek() const const
QRect boundingRect(QChar ch) const const
IntersectClip
QString number(int n, int base)
void append(const T &value)
DayOfWeek
int top() const const
virtual QDateTime currentRangeBegin(const QDateTime &datetime) const
void setPen(const QColor &color)
QPalette palette()
void paintHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr) override
bool isEmpty() const const
End time (or other end value) for a gantt item.
Definition: kganttglobal.h:215
void addRect(const QRectF &rectangle)
const char * constData() const const
int daysInMonth() const const
void setDate(const QDate &date)
void setBrush(const QBrush &brush)
QDateTime mapToDateTime(qreal x) const
Global namespace.
QPair< QDateTime, QDateTime > dateTimeRange(const QRectF &rect) const
Return a date-range represented by the rectangle.
DateTimeTimeLine * timeLine() const
CT_HeaderSection
virtual void paintWeekScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
int hour() const const
void setWeekStart(Qt::DayOfWeek)
DateTimeScaleFormatter * userDefinedUpperScale() const
qreal right() const const
const QBrush & brush() const const
bool contains(const T &value) const const
QVariant fromValue(const T &value)
Abstract baseclass for grids. A grid is used to convert between QModelIndex&#39;es and gantt chart values...
Display the timeline in the foreground.
bool isValid() const const
void restore()
QString & replace(int position, int n, QChar after)
QDataStream & operator<<(QDataStream &out, const KDateTime::Spec &spec)
QDateTime currentDateTime()
QByteArray toLatin1() const const
int width() const const
qreal width() const const
const QAbstractItemModel * model() const const
QDate date() const const
QVariant data(int role) const const
QStyle * style()
QDateTime startDateTime() const
virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const =0
QDate currentDate()
virtual void drawDayBackground(QPainter *painter, const QRectF &rect, const QDate &date)
int height() const const
int length() const const
QRect toAlignedRect() const const
QFontMetrics fontMetrics()
void init(const QWidget *widget)
virtual void paintDayScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
int dayOfYear() const const
QString left(int n) const const
QString fromLatin1(const char *str, int size)
bool isValid() const const
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
qreal height() const const
virtual void paintHourScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
void setUserDefinedLowerScale(DateTimeScaleFormatter *lower)
QDateTime toLocalTime() const const
QDate addDays(qint64 ndays) const const
void setFreeDays(const QSet< Qt::DayOfWeek > &fd)
virtual Span rowGeometry(const QModelIndex &idx) const =0
QDateTime addSecs(qint64 s) const const
QVariant::Type type() const const
virtual void setModel(QAbstractItemModel *model)
int year() const const
QDateTime addDays(qint64 ndays) const const
QDateTime startDateTime(const QVariant &elem)
const QPen & pen() const const
QString toString() const const
int month() const const
Qt::DayOfWeek weekStart() const
virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const =0
DateTimeScaleFormatter(Range range, const QString &formatString, Qt::Alignment alignment=Qt::AlignCenter)
A class representing a start point and a length.
Definition: kganttglobal.h:240
void setFreeDaysBrush(const QBrush brush)
void paintGrid(QPainter *painter, const QRectF &sceneRect, const QRectF &exposedRect, AbstractRowController *rowController=nullptr, QWidget *widget=nullptr) override
QBrush noInformationBrush() const
void setRowSeparators(bool enable)
QDateTime addMSecs(qint64 msecs) const const
bool mapFromChart(const Span &span, const QModelIndex &idx, const QList< Constraint > &constraints=QList< Constraint >()) const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Dec 5 2021 22:32:42 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.