KD Chart API Documentation 3.1
Loading...
Searching...
No Matches
kdganttdatetimegrid.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Chart library.
4**
5** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10
11#include "kdganttdatetimegrid.h"
12#include "kdganttdatetimegrid_p.h"
13
15
16#include <QApplication>
17#include <QDateTime>
18#include <QDebug>
19#include <QList>
20#include <QPainter>
21#include <QPainterPath>
22#include <QString>
23#include <QStyle>
24#include <QStyleOptionHeader>
25#include <QWidget>
26
27#include <cassert>
28
29using namespace KDGantt;
30
32{
33 switch (range) {
35 dbg << "KDGantt::DateTimeScaleFormatter::Second";
36 break;
38 dbg << "KDGantt::DateTimeScaleFormatter::Minute";
39 break;
41 dbg << "KDGantt::DateTimeScaleFormatter::Hour";
42 break;
44 dbg << "KDGantt::DateTimeScaleFormatter::Day";
45 break;
47 dbg << "KDGantt::DateTimeScaleFormatter::Week";
48 break;
50 dbg << "KDGantt::DateTimeScaleFormatter::Month";
51 break;
53 dbg << "KDGantt::DateTimeScaleFormatter::Year";
54 break;
55 }
56 return dbg;
57}
58
66qreal DateTimeGrid::Private::dateTimeToChartX(const QDateTime &dt) const
67{
68 assert(startDateTime.isValid());
69 qreal result = startDateTime.date().daysTo(dt.date()) * 24. * 60. * 60.;
70 result += startDateTime.time().msecsTo(dt.time()) / 1000.;
71 result *= dayWidth / (24. * 60. * 60.);
72
73 return result;
74}
75
76QDateTime DateTimeGrid::Private::chartXtoDateTime(qreal x) const
77{
78 assert(startDateTime.isValid());
79 int days = static_cast<int>(x / dayWidth);
80 qreal secs = x * (24. * 60. * 60.) / dayWidth;
81 QDateTime dt = startDateTime;
82 QDateTime result = dt.addDays(days)
83 .addSecs(static_cast<int>(secs - (days * 24. * 60. * 60.)))
84 .addMSecs(qRound((secs - static_cast<int>(secs)) * 1000.));
85 return result;
86}
87
88#define d d_func()
89
118 const QString &templ, Qt::Alignment alignment)
119 : _d(new Private(range, format, templ, alignment))
120{
121}
122
124 : _d(new Private(range, format, QString::fromLatin1("%1"), alignment))
125{
126}
127
129 : _d(new Private(other.range(), other.format(), other.d->templ, other.alignment()))
130{
131}
132
137
139{
140 if (this == &other)
141 return *this;
142
143 delete _d;
144 _d = new Private(other.range(), other.format(), other.d->templ, other.alignment());
145 return *this;
146}
147
151{
152 return d->format;
153}
154
158{
159 QString result = d->format;
160 // additional feature: Weeknumber
161 const QString shortWeekNumber = QString::number(datetime.date().weekNumber()) + QLatin1String("/")
162 + QString::number(datetime.date().year());
163 const QString longWeekNumber = (shortWeekNumber.length() == 1 ? QString::fromLatin1("0") : QString()) + shortWeekNumber;
164 result.replace(QString::fromLatin1("ww"), longWeekNumber);
165 result.replace(QString::fromLatin1("w"), shortWeekNumber);
166 result = datetime.toLocalTime().toString(result);
167 return result;
168}
169
171{
172 return d->templ.arg(format(datetime));
173}
174
181
183{
184 return d->alignment;
185}
186
191{
192 QDateTime result = datetime;
193 switch (d->range) {
194 case Second:
195 result = result.addSecs(60);
196 break;
197 case Minute:
198 // set it to the begin of the next minute
199 result.setTime(QTime(result.time().hour(), result.time().minute()));
200 result = result.addSecs(60);
201 break;
202 case Hour:
203 // set it to the begin of the next hour
204 result.setTime(QTime(result.time().hour(), 0));
205 result = result.addSecs(60 * 60);
206 break;
207 case Day:
208 // set it to midnight the next day
209 result.setTime(QTime(0, 0));
210 result = result.addDays(1);
211 break;
212 case Week:
213 // set it to midnight
214 result.setTime(QTime(0, 0));
215 // iterate day-wise, until weekNumber changes
216 {
217 const int weekNumber = result.date().weekNumber();
218 while (weekNumber == result.date().weekNumber())
219 result = result.addDays(1);
220 }
221 break;
222 case Month:
223 // set it to midnight
224 result.setTime(QTime(0, 0));
225 // set it to the first of the next month
226 result.setDate(QDate(result.date().year(), result.date().month(), 1).addMonths(1));
227 break;
228 case Year:
229 // set it to midnight
230 result.setTime(QTime(0, 0));
231 // set it to the first of the next year
232 result.setDate(QDate(result.date().year(), 1, 1).addYears(1));
233 break;
234 }
235 // result = result.toLocalTime();
236 assert(result != datetime);
237 // qDebug() << "DateTimeScaleFormatter::nextRangeBegin("<<datetime<<")="<<d->range<<result;
238 return result;
239}
240
245{
246 QDateTime result = datetime;
247 switch (d->range) {
248 case Second:
249 break; // nothing
250 case Minute:
251 // set it to the begin of the current minute
252 result.setTime(QTime(result.time().hour(), result.time().minute()));
253 break;
254 case Hour:
255 // set it to the begin of the current hour
256 result.setTime(QTime(result.time().hour(), 0));
257 break;
258 case Day:
259 // set it to midnight the current day
260 result.setTime(QTime(0, 0));
261 break;
262 case Week:
263 // set it to midnight
264 result.setTime(QTime(0, 0));
265 // iterate day-wise, as long weekNumber is the same
266 {
267 const int weekNumber = result.date().weekNumber();
268 while (weekNumber == result.date().addDays(-1).weekNumber())
269 result = result.addDays(-1);
270 }
271 break;
272 case Month:
273 // set it to midnight
274 result.setTime(QTime(0, 0));
275 // set it to the first of the current month
276 result.setDate(QDate(result.date().year(), result.date().month(), 1));
277 break;
278 case Year:
279 // set it to midnight
280 result.setTime(QTime(0, 0));
281 // set it to the first of the current year
282 result.setDate(QDate(result.date().year(), 1, 1));
283 break;
284 }
285 return result;
286}
287
289 : AbstractGrid(new Private)
290{
291}
292
296
302{
303 return d->startDateTime;
304}
305
312{
313 d->startDateTime = dt;
315}
316
322{
323 return d->dayWidth;
324}
325
329{
330 return d->dateTimeToChartX(dt);
331}
332
336{
337 return d->chartXtoDateTime(x);
338}
339
345{
346 assert(w > 0);
347 d->dayWidth = w;
349}
350
366{
367 d->scale = s;
369}
370
378{
379 return d->scale;
380}
381
390{
391 delete d->lower;
392 d->lower = lower;
394}
395
404{
405 delete d->upper;
406 d->upper = upper;
408}
409
416
423
430{
431 d->weekStart = ws;
433}
434
437{
438 return d->weekStart;
439}
440
448{
449 d->freeDays = fd;
451}
452
455{
456 return d->freeDays;
457}
458
462{
463 d->freeDaysBrush = brush;
464}
465
470{
471 return d->freeDaysBrush;
472}
473
476{
477 return d->rowSeparators;
478}
481{
482 d->rowSeparators = enable;
483}
484
490{
491 d->noInformationBrush = brush;
493}
494
498{
499 return d->noInformationBrush;
500}
501
506qreal DateTimeGrid::mapToChart(const QVariant &value) const
507{
508 if (!value.canConvert(QVariant::DateTime) || (value.type() == QVariant::String && value.toString().isEmpty())) {
509 return -1.0;
510 }
511 return d->dateTimeToChartX(value.toDateTime());
512}
513
519{
520 return d->chartXtoDateTime(x);
521}
522
527{
528 assert(model());
529 if (!idx.isValid())
530 return Span();
531 assert(idx.model() == model());
532 const QVariant sv = model()->data(idx, StartTimeRole);
533 const QVariant ev = model()->data(idx, EndTimeRole);
534 if (sv.canConvert(QVariant::DateTime) && ev.canConvert(QVariant::DateTime) && !(sv.type() == QVariant::String && sv.toString().isEmpty()) && !(ev.type() == QVariant::String && ev.toString().isEmpty())) {
535 QDateTime st = sv.toDateTime();
536 QDateTime et = ev.toDateTime();
537 if (et.isValid() && st.isValid()) {
538 qreal sx = d->dateTimeToChartX(st);
539 qreal ex = d->dateTimeToChartX(et) - sx;
540 // qDebug() << "DateTimeGrid::mapToChart("<<st<<et<<") => "<< Span( sx, ex );
541 return Span(sx, ex);
542 }
543 }
544 // Special case for Events with only a start date
545 if (sv.canConvert(QVariant::DateTime) && !(sv.type() == QVariant::String && sv.toString().isEmpty())) {
546 QDateTime st = sv.toDateTime();
547 if (st.isValid()) {
548 qreal sx = d->dateTimeToChartX(st);
549 return Span(sx, 0);
550 }
551 }
552 return Span();
553}
554
555#if 0
556static void debug_print_idx( const QModelIndex& idx )
557{
558 if ( !idx.isValid() ) {
559 qDebug() << "[Invalid]";
560 return;
561 }
563 QDateTime et = idx.data( EndTimeRole ).toDateTime();
564 qDebug() << idx << "["<<st<<et<<"]";
565}
566#endif
567
582bool DateTimeGrid::mapFromChart(const Span &span, const QModelIndex &idx,
583 const QList<Constraint> &constraints) const
584{
585 assert(model());
586 if (!idx.isValid())
587 return false;
588 assert(idx.model() == model());
589
590 QDateTime st = d->chartXtoDateTime(span.start());
591 QDateTime et = d->chartXtoDateTime(span.start() + span.length());
592 // qDebug() << "DateTimeGrid::mapFromChart("<<span<<") => "<< st << et;
593 for (const Constraint &c : constraints) {
594 if (c.type() != Constraint::TypeHard || !isSatisfiedConstraint(c))
595 continue;
596 if (c.startIndex() == idx) {
597 QDateTime tmpst = model()->data(c.endIndex(), StartTimeRole).toDateTime();
598 // qDebug() << tmpst << "<" << et <<"?";
599 if (tmpst < et)
600 return false;
601 } else if (c.endIndex() == idx) {
602 QDateTime tmpet = model()->data(c.startIndex(), EndTimeRole).toDateTime();
603 // qDebug() << tmpet << ">" << st <<"?";
604 if (tmpet > st)
605 return false;
606 }
607 }
608
611}
612
613Qt::PenStyle DateTimeGrid::Private::gridLinePenStyle(QDateTime dt, Private::HeaderType headerType) const
614{
615 switch (headerType) {
616 case Private::HeaderHour:
617 // Midnight
618 if (dt.time().hour() == 0)
619 return Qt::SolidLine;
620 return Qt::DashLine;
621 case Private::HeaderDay:
622 // First day of the week
623 if (dt.date().dayOfWeek() == weekStart)
624 return Qt::SolidLine;
625 return Qt::DashLine;
626 case Private::HeaderWeek:
627 // First day of the month
628 if (dt.date().day() == 1)
629 return Qt::SolidLine;
630 // First day of the week
631 if (dt.date().dayOfWeek() == weekStart)
632 return Qt::DashLine;
633 return Qt::NoPen;
634 case Private::HeaderMonth:
635 // First day of the year
636 if (dt.date().dayOfYear() == 1)
637 return Qt::SolidLine;
638 // First day of the month
639 if (dt.date().day() == 1)
640 return Qt::DashLine;
641 return Qt::NoPen;
642 default:
643 // Nothing to do here
644 break;
645 }
646
647 // Default
648 return Qt::NoPen;
649}
650
651QDateTime DateTimeGrid::Private::adjustDateTimeForHeader(QDateTime dt, Private::HeaderType headerType) const
652{
653 // In any case, set time to 00:00:00:00
654 dt.setTime(QTime(0, 0, 0, 0));
655
656 switch (headerType) {
657 case Private::HeaderWeek:
658 // Set day to beginning of the week
659 while (dt.date().dayOfWeek() != weekStart)
660 dt = dt.addDays(-1);
661 break;
662 case Private::HeaderMonth:
663 // Set day to beginning of the month
664 dt = dt.addDays(1 - dt.date().day());
665 break;
666 case Private::HeaderYear:
667 // Set day to first day of the year
668 dt = dt.addDays(1 - dt.date().dayOfYear());
669 break;
670 default:
671 // In any other case, we don't need to adjust the date time
672 break;
673 }
674
675 return dt;
676}
677
678void DateTimeGrid::Private::paintVerticalLines(QPainter *painter,
679 const QRectF &sceneRect,
680 const QRectF &exposedRect,
681 QWidget *widget,
682 Private::HeaderType headerType)
683{
684 QDateTime dt = chartXtoDateTime(exposedRect.left());
685 dt = adjustDateTimeForHeader(dt, headerType);
686
687 int offsetSeconds = 0;
688 int offsetDays = 0;
689 // Determine the time step per grid line
690 if (headerType == Private::HeaderHour)
691 offsetSeconds = 60 * 60;
692 else
693 offsetDays = 1;
694
695 for (qreal x = dateTimeToChartX(dt); x < exposedRect.right();
696 dt = dt.addSecs(offsetSeconds), dt = dt.addDays(offsetDays), x = dateTimeToChartX(dt)) {
697 // TODO not the best solution as it might be one paint too much, but i don't know what
698 // causes the test to fail yet, i think it might be a rounding error
699 // if ( x >= exposedRect.left() ) {
700 QPen pen = painter->pen();
701 pen.setBrush(QApplication::palette().dark());
702 pen.setStyle(gridLinePenStyle(dt, headerType));
703 painter->setPen(pen);
704 if (freeDays.contains(static_cast<Qt::DayOfWeek>(dt.date().dayOfWeek()))) {
705 if (freeDaysBrush.style() == Qt::NoBrush)
706 painter->setBrush(widget ? widget->palette().midlight()
707 : QApplication::palette().midlight());
708 else
709 painter->setBrush(freeDaysBrush);
710
711 painter->fillRect(QRectF(x, exposedRect.top(), dayWidth, exposedRect.height()), painter->brush());
712 }
713 painter->drawLine(QPointF(x, sceneRect.top()), QPointF(x, sceneRect.bottom()));
714 //}
715 }
716}
717
718void DateTimeGrid::Private::paintVerticalUserDefinedLines(QPainter *painter,
719 const QRectF &sceneRect,
720 const QRectF &exposedRect,
721 const DateTimeScaleFormatter *formatter,
722 QWidget *widget)
723{
724 Q_UNUSED(widget);
725 QDateTime dt = chartXtoDateTime(exposedRect.left());
726 dt = formatter->currentRangeBegin(dt);
727 QPen pen = painter->pen();
728 pen.setBrush(QApplication::palette().dark());
730 painter->setPen(pen);
731 for (qreal x = dateTimeToChartX(dt); x < exposedRect.right();
732 dt = formatter->nextRangeBegin(dt), x = dateTimeToChartX(dt)) {
733 if (freeDays.contains(static_cast<Qt::DayOfWeek>(dt.date().dayOfWeek()))) {
734 QBrush oldBrush = painter->brush();
735 if (freeDaysBrush.style() == Qt::NoBrush)
736 painter->setBrush(widget ? widget->palette().midlight()
737 : QApplication::palette().midlight());
738 else
739 painter->setBrush(freeDaysBrush);
740
741 painter->fillRect(QRectF(x, exposedRect.top(), dayWidth, exposedRect.height()), painter->brush());
742 painter->setBrush(oldBrush);
743 }
744 // TODO not the best solution as it might be one paint too much, but i don't know what
745 // causes the test to fail yet, i think it might be a rounding error
746 // if ( x >= exposedRect.left() ) {
747 // FIXME: Also fill area between this and the next vertical line to indicate free days? (Johannes)
748 painter->drawLine(QPointF(x, sceneRect.top()), QPointF(x, sceneRect.bottom()));
749 //}
750 }
751}
752
753DateTimeGrid::Private::HeaderType DateTimeGrid::Private::headerTypeForScale(DateTimeGrid::Scale scale)
754{
755 switch (scale) {
756 case ScaleHour:
757 return Private::HeaderHour;
758 case ScaleDay:
759 return Private::HeaderDay;
760 case ScaleWeek:
761 return Private::HeaderWeek;
762 case ScaleMonth:
763 return Private::HeaderMonth;
764 default:
765 // There are no specific header types for any other scale!
766 assert(false);
767 break;
768 }
769 return Private::HeaderDay;
770}
771
773 const QRectF &sceneRect,
774 const QRectF &exposedRect,
775 AbstractRowController *rowController,
776 QWidget *widget)
777{
778 // TODO: Support hours and weeks
779 switch (scale()) {
780 case ScaleHour:
781 case ScaleDay:
782 case ScaleWeek:
783 case ScaleMonth:
784 d->paintVerticalLines(painter, sceneRect, exposedRect, widget, d->headerTypeForScale(scale()));
785 break;
786 case ScaleAuto: {
788 const qreal dayw = dayWidth();
789 if (dayw > 24 * 60 * 60 * tabw) {
790
791 d->paintVerticalUserDefinedLines(painter, sceneRect, exposedRect, &d->minute_lower, widget);
792 } else if (dayw > 24 * 60 * tabw) {
793 d->paintVerticalLines(painter, sceneRect, exposedRect, widget, Private::HeaderHour);
794 } else if (dayw > 24 * tabw) {
795 d->paintVerticalLines(painter, sceneRect, exposedRect, widget, Private::HeaderDay);
796 } else if (dayw > tabw) {
797 d->paintVerticalUserDefinedLines(painter, sceneRect, exposedRect, &d->week_lower, widget);
798 } else if (4 * dayw > tabw) {
799 d->paintVerticalUserDefinedLines(painter, sceneRect, exposedRect, &d->month_lower, widget);
800 } else {
801 d->paintVerticalUserDefinedLines(painter, sceneRect, exposedRect, &d->year_lower, widget);
802 }
803 break;
804 }
805 case ScaleUserDefined:
806 d->paintVerticalUserDefinedLines(painter, sceneRect, exposedRect, d->lower, widget);
807 break;
808 }
809 if (rowController) {
810 // First draw the rows
811 QPen pen = painter->pen();
812 pen.setBrush(QApplication::palette().dark());
814 painter->setPen(pen);
815 QModelIndex idx = rowController->indexAt(qRound(exposedRect.top()));
816 if (rowController->indexAbove(idx).isValid())
817 idx = rowController->indexAbove(idx);
818 qreal y = 0;
819 while (y < exposedRect.bottom() && idx.isValid()) {
820 const Span s = rowController->rowGeometry(idx);
821 y = s.start() + s.length();
822 if (d->rowSeparators) {
823 painter->drawLine(QPointF(sceneRect.left(), y),
824 QPointF(sceneRect.right(), y));
825 }
826 if (!idx.data(ItemTypeRole).isValid() && d->noInformationBrush.style() != Qt::NoBrush) {
827 painter->fillRect(QRectF(exposedRect.left(), s.start(), exposedRect.width(), s.length()), d->noInformationBrush);
828 }
829 // Is alternating background better?
830 // if ( idx.row()%2 ) painter->fillRect( QRectF( exposedRect.x(), s.start(), exposedRect.width(), s.length() ), QApplication::palette().alternateBase() );
831 idx = rowController->indexBelow(idx);
832 }
833 }
834}
835
836int DateTimeGrid::Private::tabHeight(const QString &txt, QWidget *widget) const
837{
839 if (widget)
840 opt.initFrom(widget);
841 opt.text = txt;
842 QStyle *style;
843 if (widget)
844 style = widget->style();
845 else
846 style = QApplication::style();
847 QSize s = style->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), widget);
848 return s.height();
849}
850
851void DateTimeGrid::Private::getAutomaticFormatters(DateTimeScaleFormatter **lower, DateTimeScaleFormatter **upper)
852{
853 const qreal tabw = QApplication::fontMetrics().horizontalAdvance(QLatin1String("XXXXX"));
854 const qreal dayw = dayWidth;
855 if (dayw > 24 * 60 * 60 * tabw) {
856 *lower = &minute_lower;
857 *upper = &minute_upper;
858 } else if (dayw > 24 * 60 * tabw) {
859 *lower = &hour_lower;
860 *upper = &hour_upper;
861 } else if (dayw > 24 * tabw) {
862 *lower = &day_lower;
863 *upper = &day_upper;
864 } else if (dayw > tabw) {
865 *lower = &week_lower;
866 *upper = &week_upper;
867 } else if (4 * dayw > tabw) {
868 *lower = &month_lower;
869 *upper = &month_upper;
870 } else {
871 *lower = &year_lower;
872 *upper = &year_upper;
873 }
874}
875
876void DateTimeGrid::paintHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect,
877 qreal offset, QWidget *widget)
878{
879 painter->save();
880 QPainterPath clipPath;
881 clipPath.addRect(headerRect);
882 painter->setClipPath(clipPath, Qt::IntersectClip);
883 switch (scale()) {
884 case ScaleHour:
885 paintHourScaleHeader(painter, headerRect, exposedRect, offset, widget);
886 break;
887 case ScaleDay:
888 paintDayScaleHeader(painter, headerRect, exposedRect, offset, widget);
889 break;
890 case ScaleWeek:
891 paintWeekScaleHeader(painter, headerRect, exposedRect, offset, widget);
892 break;
893 case ScaleMonth:
894 paintMonthScaleHeader(painter, headerRect, exposedRect, offset, widget);
895 break;
896 case ScaleAuto: {
898 d->getAutomaticFormatters(&lower, &upper);
899 const qreal lowerHeight = d->tabHeight(lower->text(startDateTime()));
900 const qreal upperHeight = d->tabHeight(upper->text(startDateTime()));
902
903 const QRectF upperHeaderRect(headerRect.x(), headerRect.top(), headerRect.width() - 1, headerRect.height() * upperRatio);
904 const QRectF lowerHeaderRect(headerRect.x(), upperHeaderRect.bottom() + 1, headerRect.width() - 1, headerRect.height() - upperHeaderRect.height() - 1);
905
906 paintUserDefinedHeader(painter, lowerHeaderRect, exposedRect, offset, lower, widget);
907 paintUserDefinedHeader(painter, upperHeaderRect, exposedRect, offset, upper, widget);
908 break;
909 }
910 case ScaleUserDefined: {
911 const qreal lowerHeight = d->tabHeight(d->lower->text(startDateTime()));
912 const qreal upperHeight = d->tabHeight(d->upper->text(startDateTime()));
914
915 const QRectF upperHeaderRect(headerRect.x(), headerRect.top(), headerRect.width() - 1, headerRect.height() * upperRatio);
916 const QRectF lowerHeaderRect(headerRect.x(), upperHeaderRect.bottom() + 1, headerRect.width() - 1, headerRect.height() - upperHeaderRect.height() - 1);
917
918 paintUserDefinedHeader(painter, lowerHeaderRect, exposedRect, offset, d->lower, widget);
919 paintUserDefinedHeader(painter, upperHeaderRect, exposedRect, offset, d->upper, widget);
920 } break;
921 }
922 painter->restore();
923}
924
926 const QRectF &headerRect, const QRectF &exposedRect,
927 qreal offset, const DateTimeScaleFormatter *formatter,
928 QWidget *widget)
929{
930 const QStyle *const style = widget ? widget->style() : QApplication::style();
931
932 QDateTime dt = formatter->currentRangeBegin(d->chartXtoDateTime(offset + exposedRect.left()));
933 qreal x = d->dateTimeToChartX(dt);
934
935 while (x < exposedRect.right() + offset) {
936 const QDateTime next = formatter->nextRangeBegin(dt);
937 const qreal nextx = d->dateTimeToChartX(next);
938
940 if (widget)
941 opt.initFrom(widget);
942 opt.rect = QRectF(x - offset + 1, headerRect.top(), qMax<qreal>(1., nextx - x - 1), headerRect.height()).toAlignedRect();
943 opt.textAlignment = formatter->alignment();
944 opt.text = formatter->text(dt);
945 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
946
947 dt = next;
948 x = nextx;
949 }
950}
951
952void DateTimeGrid::Private::paintHeader(QPainter *painter,
953 const QRectF &headerRect, const QRectF &exposedRect,
954 qreal offset, QWidget *widget,
955 Private::HeaderType headerType,
956 DateTextFormatter *formatter)
957{
958 QStyle *style = widget ? widget->style() : QApplication::style();
959
960 const qreal left = exposedRect.left() + offset;
961 const qreal right = exposedRect.right() + offset;
962
963 // Paint a section for each hour
964 QDateTime dt = chartXtoDateTime(left);
965 dt = adjustDateTimeForHeader(dt, headerType);
966 // Determine the time step per grid line
967 int offsetSeconds = 0;
968 int offsetDays = 0;
969 int offsetMonths = 0;
970
971 switch (headerType) {
972 case Private::HeaderHour:
973 offsetSeconds = 60 * 60;
974 break;
975 case Private::HeaderDay:
976 offsetDays = 1;
977 break;
978 case Private::HeaderWeek:
979 offsetDays = 7;
980 break;
981 case Private::HeaderMonth:
982 offsetMonths = 1;
983 break;
984 case Private::HeaderYear:
985 offsetMonths = 12;
986 break;
987 default:
988 // Other scales cannot be painted with this method!
989 assert(false);
990 break;
991 }
992
993 for (qreal x = dateTimeToChartX(dt); x < right;
994 dt = dt.addSecs(offsetSeconds), dt = dt.addDays(offsetDays), dt = dt.addMonths(offsetMonths),
995 x = dateTimeToChartX(dt)) {
997 if (widget)
998 opt.initFrom(widget);
999 opt.rect = formatter->textRect(x, offset, dayWidth, headerRect, dt);
1000 opt.text = formatter->format(dt);
1001 opt.textAlignment = Qt::AlignCenter;
1002 style->drawControl(QStyle::CE_Header, &opt, painter, widget);
1003 }
1004}
1005
1010 const QRectF &headerRect, const QRectF &exposedRect,
1011 qreal offset, QWidget *widget)
1012{
1013 class HourFormatter : public Private::DateTextFormatter
1014 {
1015 public:
1016 ~HourFormatter() override
1017 {
1018 }
1019
1020 QString format(const QDateTime &dt) override
1021 {
1022 return dt.time().toString(QString::fromLatin1("hh"));
1023 }
1024 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1025 {
1026 Q_UNUSED(dt);
1027
1028 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset + 1.0, headerRect.height() / 2.0),
1029 QSizeF(dayWidth / 24.0, headerRect.height() / 2.0))
1030 .toAlignedRect();
1031 }
1032 };
1033 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1034 Private::HeaderHour, new HourFormatter); // Custom parameters
1035
1036 class DayFormatter : public Private::DateTextFormatter
1037 {
1038 public:
1039 ~DayFormatter() override
1040 {
1041 }
1042 QString format(const QDateTime &dt) override
1043 {
1044 return dt.date().toString();
1045 }
1046 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1047 {
1048 Q_UNUSED(dt);
1049
1050 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset, 0.0),
1051 QSizeF(dayWidth, headerRect.height() / 2.0))
1052 .toRect();
1053 }
1054 };
1055 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1056 Private::HeaderDay, new DayFormatter); // Custom parameters
1057}
1058
1062void DateTimeGrid::paintDayScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect,
1063 qreal offset, QWidget *widget)
1064{
1065 class DayFormatter : public Private::DateTextFormatter
1066 {
1067 public:
1068 DayFormatter()
1069 : Private::DateTextFormatter()
1070 , m_formatter(DateTimeScaleFormatter::Range::Day, QString::fromLatin1("ddd"))
1071 {
1072 }
1073 ~DayFormatter() override
1074 {
1075 }
1076
1077 QString format(const QDateTime &dt) override
1078 {
1079 return m_formatter.format(dt);
1080 }
1081 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1082 {
1083 Q_UNUSED(dt);
1084
1085 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset + 1.0, headerRect.height() / 2.0),
1086 QSizeF(dayWidth, headerRect.height() / 2.0))
1087 .toAlignedRect();
1088 }
1090 };
1091 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1092 Private::HeaderDay, new DayFormatter); // Custom parameters
1093
1094 class WeekFormatter : public Private::DateTextFormatter
1095 {
1096 public:
1097 ~WeekFormatter() override
1098 {
1099 }
1100 QString format(const QDateTime &dt) override
1101 {
1102 return QString::number(dt.date().weekNumber()) + QLatin1String("/") + QString::number(dt.date().year());
1103 }
1104 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1105 {
1106 Q_UNUSED(dt);
1107
1108 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset, 0.0),
1109 QSizeF(dayWidth * 7, headerRect.height() / 2.0))
1110 .toRect();
1111 }
1112 };
1113 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1114 Private::HeaderWeek, new WeekFormatter); // Custom parameters
1115}
1116
1120void DateTimeGrid::paintWeekScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect,
1121 qreal offset, QWidget *widget)
1122{
1123 class WeekFormatter : public Private::DateTextFormatter
1124 {
1125 public:
1126 ~WeekFormatter() override
1127 {
1128 }
1129
1130 QString format(const QDateTime &dt) override
1131 {
1132 return QString::number(dt.date().weekNumber());
1133 }
1134 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1135 {
1136 Q_UNUSED(dt);
1137
1138 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset, headerRect.height() / 2.0),
1139 QSizeF(dayWidth * 7, headerRect.height() / 2.0))
1140 .toRect();
1141 }
1142 };
1143 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1144 Private::HeaderWeek, new WeekFormatter); // Custom parameters
1145
1146 class MonthFormatter : public Private::DateTextFormatter
1147 {
1148 public:
1149 ~MonthFormatter() override
1150 {
1151 }
1152
1153 QString format(const QDateTime &dt) override
1154 {
1155 return QLocale().monthName(dt.date().month(), QLocale::LongFormat) + QLatin1String("/") + QString::number(dt.date().year());
1156 }
1157 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1158 {
1159 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset, 0.0),
1160 QSizeF(dayWidth * dt.date().daysInMonth(), headerRect.height() / 2.0))
1161 .toRect();
1162 }
1163 };
1164 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1165 Private::HeaderMonth, new MonthFormatter); // Custom parameters
1166}
1167
1171void DateTimeGrid::paintMonthScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect,
1172 qreal offset, QWidget *widget)
1173{
1174 class MonthFormatter : public Private::DateTextFormatter
1175 {
1176 public:
1177 ~MonthFormatter() override
1178 {
1179 }
1180
1181 QString format(const QDateTime &dt) override
1182 {
1183 return QLocale().monthName(dt.date().month(), QLocale::ShortFormat) + QLatin1String("/") + QString::number(dt.date().year());
1184 }
1185 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1186 {
1187 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset, headerRect.height() / 2.0),
1188 QSizeF(dayWidth * dt.date().daysInMonth(), headerRect.height() / 2.0))
1189 .toRect();
1190 }
1191 };
1192 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1193 Private::HeaderMonth, new MonthFormatter); // Custom parameters
1194
1195 class YearFormatter : public Private::DateTextFormatter
1196 {
1197 public:
1198 ~YearFormatter() override
1199 {
1200 }
1201
1202 QString format(const QDateTime &dt) override
1203 {
1204 return QString::number(dt.date().year());
1205 }
1206 QRect textRect(qreal x, qreal offset, qreal dayWidth, const QRectF &headerRect, const QDateTime &dt) override
1207 {
1208 return QRectF(QPointF(x, headerRect.top()) + QPointF(-offset, 0.0),
1209 QSizeF(dayWidth * dt.date().daysInYear(), headerRect.height() / 2.0))
1210 .toRect();
1211 }
1212 };
1213 d->paintHeader(painter, headerRect, exposedRect, offset, widget, // General parameters
1214 Private::HeaderYear, new YearFormatter); // Custom parameters
1215}
1216
1219void DateTimeGrid::drawDayBackground(QPainter *painter, const QRectF &rect, const QDate &date)
1220{
1221 Q_UNUSED(painter);
1222 Q_UNUSED(rect);
1223 Q_UNUSED(date);
1224}
1225
1228void DateTimeGrid::drawDayForeground(QPainter *painter, const QRectF &rect, const QDate &date)
1229{
1230 Q_UNUSED(painter);
1231 Q_UNUSED(rect);
1232 Q_UNUSED(date);
1233}
1234
1237QRectF DateTimeGrid::computeRect(const QDateTime &from, const QDateTime &to, const QRectF &rect) const
1238{
1239 qreal topLeft = d->dateTimeToChartX(from);
1240 qreal topRight = d->dateTimeToChartX(to);
1241
1242 return QRectF(topLeft, rect.top(), topRight - topLeft, rect.height());
1243}
1244
1248{
1249 QDateTime start;
1250 QDateTime end;
1251
1252 start = d->chartXtoDateTime(rect.left());
1253 end = d->chartXtoDateTime(rect.right());
1254
1255 return qMakePair(start, end);
1256}
1257
1259{
1260 int offset = ( int )dayWidth();
1261
1262 // Figure out the date at the extreme left
1263 QDate date = d->chartXtoDateTime(rect.left()).date();
1264
1265 // We need to paint from one end to the other
1266 int startx = rect.left();
1267 int endx = rect.right();
1268
1269 // Save the painter state
1270 paint->save();
1271
1272 // Paint the first date column
1273 while (1) {
1274 QDate nextDate = d->chartXtoDateTime(startx + 1).date();
1275 if (date != nextDate) {
1276 QRectF dayRect(startx - dayWidth(), rect.top(), dayWidth(), rect.height());
1277 dayRect = dayRect.adjusted(1, 0, 0, 0);
1278 drawDayBackground(paint, dayRect, date);
1279 break;
1280 }
1281
1282 ++startx;
1283 }
1284
1285 // Paint the remaining dates
1286 for (int i = startx; i < endx; i += offset) {
1287 date = d->chartXtoDateTime(i + 1).date();
1288
1289 QRectF dayRect(i, rect.top(), dayWidth(), rect.height());
1290 dayRect = dayRect.adjusted(1, 0, 0, 0);
1291 drawDayBackground(paint, dayRect, date);
1292 }
1293
1294 // Restore the painter state
1295 paint->restore();
1296}
1297
1299{
1300 int offset = ( int )dayWidth();
1301
1302 // Figure out the date at the extreme left
1303 QDate date = d->chartXtoDateTime(rect.left()).date();
1304
1305 // We need to paint from one end to the other
1306 int startx = rect.left();
1307 int endx = rect.right();
1308
1309 // Save the painter state
1310 paint->save();
1311
1312 // Paint the first date column
1313 while (1) {
1314 QDate nextDate = d->chartXtoDateTime(startx + 1).date();
1315 if (date != nextDate) {
1316 QRectF dayRect(startx - dayWidth(), rect.top(), dayWidth(), rect.height());
1317 dayRect = dayRect.adjusted(1, 0, 0, 0);
1318 drawDayForeground(paint, dayRect, date);
1319 break;
1320 }
1321
1322 ++startx;
1323 }
1324
1325 // Paint the remaining dates
1326 for (int i = startx; i < endx; i += offset) {
1327 date = d->chartXtoDateTime(i + 1).date();
1328
1329 QRectF dayRect(i, rect.top(), dayWidth(), rect.height());
1330 dayRect = dayRect.adjusted(1, 0, 0, 0);
1331 drawDayForeground(paint, dayRect, date);
1332 }
1333
1334 // Restore the painter state
1335 paint->restore();
1336}
1337
1338#undef d
1339
1340#ifndef KDAB_NO_UNIT_TESTS
1341
1342#include "unittest/test.h"
1343#include <QStandardItemModel>
1344
1345static std::ostream &operator<<(std::ostream &os, const QDateTime &dt)
1346{
1347#ifdef QT_NO_STL
1348 os << dt.toString().toLatin1().constData();
1349#else
1350 os << dt.toString().toStdString();
1351#endif
1352 return os;
1353}
1354
1356{
1357 QStandardItemModel model(3, 2);
1358 DateTimeGrid grid;
1360 grid.setModel(&model);
1361 QDateTime startdt = dt.addDays(-10);
1362 grid.setStartDateTime(startdt);
1363
1364 model.setData(model.index(0, 0), dt, StartTimeRole);
1365 model.setData(model.index(0, 0), dt.addDays(17), EndTimeRole);
1366
1367 model.setData(model.index(2, 0), dt.addDays(18), StartTimeRole);
1368 model.setData(model.index(2, 0), dt.addDays(19), EndTimeRole);
1369
1370 Span s = grid.mapToChart(model.index(0, 0));
1371 // qDebug() << "span="<<s;
1372
1373 assertTrue(s.start() > 0);
1374 assertTrue(s.length() > 0);
1375
1376 assertTrue(startdt == grid.mapToDateTime(grid.mapFromDateTime(startdt)));
1377
1378 grid.mapFromChart(s, model.index(1, 0));
1379
1380 QDateTime s1 = model.data(model.index(0, 0), StartTimeRole).toDateTime();
1381 QDateTime e1 = model.data(model.index(0, 0), EndTimeRole).toDateTime();
1382 QDateTime s2 = model.data(model.index(1, 0), StartTimeRole).toDateTime();
1383 QDateTime e2 = model.data(model.index(1, 0), EndTimeRole).toDateTime();
1384
1385 assertTrue(s1.isValid());
1386 assertTrue(e1.isValid());
1387 assertTrue(s2.isValid());
1388 assertTrue(e2.isValid());
1389
1390 assertEqual(s1, s2);
1391 assertEqual(e1, e2);
1392
1393 assertTrue(grid.isSatisfiedConstraint(Constraint(model.index(0, 0), model.index(2, 0))));
1394 assertFalse(grid.isSatisfiedConstraint(Constraint(model.index(2, 0), model.index(0, 0))));
1395
1396 s = grid.mapToChart(model.index(0, 0));
1397 s.setEnd(s.end() + 100000.);
1398 bool rc = grid.mapFromChart(s, model.index(0, 0));
1399 assertTrue(rc);
1400 assertEqual(s1, model.data(model.index(0, 0), StartTimeRole).toDateTime());
1401 Span newspan = grid.mapToChart(model.index(0, 0));
1402 assertEqual(newspan.start(), s.start());
1403 assertEqual(newspan.length(), s.length());
1404
1405 {
1406 QDateTime startDateTime = QDateTime::currentDateTime();
1407 qreal dayWidth = 100;
1408 QDate currentDate = QDate::currentDate();
1409 QDateTime dt(QDate(currentDate.year(), 1, 1), QTime(0, 0, 0, 0));
1410 assert(dt.isValid());
1411 qreal result = startDateTime.date().daysTo(dt.date()) * 24. * 60. * 60.;
1412 result += startDateTime.time().msecsTo(dt.time()) / 1000.;
1413 result *= dayWidth / (24. * 60. * 60.);
1414
1415 int days = static_cast<int>(result / dayWidth);
1416 qreal secs = result * (24. * 60. * 60.) / dayWidth;
1417 QDateTime dt2 = startDateTime;
1418 QDateTime result2 = dt2.addDays(days).addSecs(static_cast<int>(secs - (days * 24. * 60. * 60.))).addMSecs(qRound((secs - static_cast<int>(secs)) * 1000.));
1419
1420 assertEqual(dt, result2);
1421 }
1422}
1423
1424#endif /* KDAB_NO_UNIT_TESTS */
1425
1426#include "moc_kdganttdatetimegrid.cpp"
QDebug operator<<(QDebug dbg, const KDChart::ThreeDBarAttributes &a)
Abstract baseclass for grids.
QAbstractItemModel * model() const
bool isSatisfiedConstraint(const Constraint &c) const
virtual void setModel(QAbstractItemModel *model)
Sets the QAbstractItemModel used by this grid implementation.
Abstract baseclass for row controllers.
virtual QModelIndex indexAbove(const QModelIndex &idx) const =0
virtual QModelIndex indexBelow(const QModelIndex &idx) const =0
virtual Span rowGeometry(const QModelIndex &idx) const =0
virtual QModelIndex indexAt(int height) const =0
A class used to represent a dependency.
This implementation of AbstractGrid works with QDateTime and shows days and week numbers in the heade...
virtual void paintHourScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
Paints the hour scale header.
virtual void drawDayForeground(QPainter *painter, const QRectF &rect, const QDate &date)
Draw the foreground for a day.
bool mapFromChart(const Span &span, const QModelIndex &idx, const QList< Constraint > &constraints=QList< Constraint >()) const override
Maps the supplied Span to QDateTimes, and puts them as start time and end time for the supplied index...
virtual void paintDayScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
Paints the day scale header.
void paintHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr) override
Implement this to paint the header part of the view.
DateTimeScaleFormatter * userDefinedUpperScale() const
QDateTime startDateTime() const
void setStartDateTime(const QDateTime &dt)
virtual void drawDayBackground(QPainter *painter, const QRectF &rect, const QDate &date)
Draw the background for a day.
void drawForeground(QPainter *paint, const QRectF &rect) override
void setRowSeparators(bool enable)
DateTimeScaleFormatter * userDefinedLowerScale() const
qreal mapFromDateTime(const QDateTime &dt) const
Maps a given point in time dt to an X value in the scene.
void setWeekStart(Qt::DayOfWeek)
Span mapToChart(const QModelIndex &idx) const override
QRectF computeRect(const QDateTime &from, const QDateTime &to, const QRectF &rect) const
void setNoInformationBrush(const QBrush &brush)
Sets the brush used to display rows where no data is found.
void drawBackground(QPainter *paint, const QRectF &rect) override
QPair< QDateTime, QDateTime > dateTimeRange(const QRectF &rect) const
QDateTime mapToDateTime(qreal x) const
Maps a given X value x in scene coordinates to a point in time.
virtual void paintWeekScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
Paints the week scale header.
Qt::DayOfWeek weekStart() const
void setUserDefinedLowerScale(DateTimeScaleFormatter *lower)
Sets the scale formatter for the lower part of the header to the user defined formatter to lower.
virtual void paintMonthScaleHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, QWidget *widget=nullptr)
Paints the week scale header.
void paintGrid(QPainter *painter, const QRectF &sceneRect, const QRectF &exposedRect, AbstractRowController *rowController=nullptr, QWidget *widget=nullptr) override
Implement this to paint the background of the view – typically with some grid lines.
QSet< Qt::DayOfWeek > freeDays() const
virtual void paintUserDefinedHeader(QPainter *painter, const QRectF &headerRect, const QRectF &exposedRect, qreal offset, const DateTimeScaleFormatter *formatter, QWidget *widget=nullptr)
void setUserDefinedUpperScale(DateTimeScaleFormatter *upper)
Sets the scale formatter for the upper part of the header to the user defined formatter to upper.
void setFreeDaysBrush(const QBrush brush)
Sets the brush to use to paint free days.
void setFreeDays(const QSet< Qt::DayOfWeek > &fd)
This class formats dates and times used in DateTimeGrid follawing a given format.
virtual QDateTime nextRangeBegin(const QDateTime &datetime) const
virtual QString text(const QDateTime &datetime) const
virtual QDateTime currentRangeBegin(const QDateTime &datetime) const
DateTimeScaleFormatter(Range range, const QString &formatString, Qt::Alignment alignment=Qt::AlignCenter)
DateTimeScaleFormatter & operator=(const DateTimeScaleFormatter &other)
A class representing a start point and a length.
qreal length() const
qreal end() const
void setEnd(qreal end)
qreal start() const
KDAB_SCOPED_UNITTEST_SIMPLE(KDGantt, Constraint, "test")
QDebug operator<<(QDebug dbg, KDGantt::DateTimeScaleFormatter::Range range)
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
QFontMetrics fontMetrics()
QStyle * style()
const char * constData() const const
QDate addDays(qint64 ndays) const const
QDate addMonths(int nmonths) const const
QDate addYears(int nyears) const const
QDate currentDate()
int day() const const
int dayOfWeek() const const
int dayOfYear() const const
qint64 daysTo(const QDate &d) const const
int month() const const
int weekNumber(int *yearNumber) const const
int year() const const
QDateTime addDays(qint64 ndays) const const
QDateTime addMSecs(qint64 msecs) const const
QDateTime addMonths(int nmonths) const const
QDateTime addSecs(qint64 s) const const
QDateTime currentDateTime()
QDate date() const const
bool isValid() const const
void setDate(const QDate &date)
void setTime(const QTime &time)
QTime time() const const
QDateTime toLocalTime() const const
QString toString(Qt::DateFormat format) const const
int horizontalAdvance(const QString &text, int len) const const
QPalette palette()
QString monthName(int month, QLocale::FormatType type) const const
QVariant data(int role) const const
bool isValid() const const
Q_EMITQ_EMIT
T qobject_cast(QObject *object)
const QBrush & brush() const const
void drawLine(const QLineF &line)
void fillRect(const QRectF &rectangle, const QBrush &brush)
const QPen & pen() const const
void restore()
void save()
void setBrush(const QBrush &brush)
void setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
void setPen(const QColor &color)
void addRect(const QRectF &rectangle)
void setBrush(const QBrush &brush)
void setStyle(Qt::PenStyle style)
qreal bottom() const const
qreal height() const const
qreal left() const const
qreal right() const const
QRect toAlignedRect() const const
QRect toRect() const const
qreal top() const const
int height() const const
virtual QVariant data(const QModelIndex &index, int role) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromLatin1(const char *str, int size)
bool isEmpty() const const
int length() const const
QString number(int n, int base)
QString & replace(int position, int n, QChar after)
QByteArray toLatin1() const const
std::string toStdString() const const
CT_HeaderSection
virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const=0
void initFrom(const QWidget *widget)
typedef Alignment
IntersectClip
DayOfWeek
PenStyle
int hour() const const
int minute() const const
int msecsTo(const QTime &t) const const
bool canConvert(int targetTypeId) const const
QVariant fromValue(const T &value)
QDateTime toDateTime() const const
QString toString() const const
QVariant::Type type() const const
QStyle * style() const const

© 2001 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-chart/
Generated on Thu Apr 11 2024 00:04:50 for KD Chart API Documentation by doxygen 1.9.8