KD Chart API Documentation 3.1
Loading...
Searching...
No Matches
kdganttitemdelegate.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 "kdganttconstraint.h"
12#include "kdganttglobal.h"
13#include "kdganttitemdelegate_p.h"
15
16#include <QAbstractItemModel>
17#include <QApplication>
18#include <QModelIndex>
19#include <QPainter>
20#include <QPainterPath>
21#include <QPen>
22
23#ifndef QT_NO_DEBUG_STREAM
24
25#define PRINT_INTERACTIONSTATE(x) \
26 case x: \
27 dbg << #x; \
28 break;
29
42
43#undef PRINT_INTERACTIONSTATE
44
45#endif /* QT_NO_DEBUG_STREAM */
46
47using namespace KDGantt;
48
62ItemDelegate::Private::Private()
63{
64 // Brushes
65 QLinearGradient taskgrad(0., 0., 0., QApplication::fontMetrics().height());
66 taskgrad.setColorAt(0., Qt::green);
67 taskgrad.setColorAt(1., Qt::darkGreen);
68
69 QLinearGradient summarygrad(0., 0., 0., QApplication::fontMetrics().height());
70 summarygrad.setColorAt(0., Qt::blue);
71 summarygrad.setColorAt(1., Qt::darkBlue);
72
73 QLinearGradient eventgrad(0., 0., 0., QApplication::fontMetrics().height());
74 eventgrad.setColorAt(0., Qt::red);
75 eventgrad.setColorAt(1., Qt::darkRed);
76
77 defaultbrush[TypeTask] = taskgrad;
78 defaultbrush[TypeSummary] = summarygrad;
79 defaultbrush[TypeEvent] = eventgrad;
80
81 // Pens
82 QPen pen(Qt::black, 1.);
83
84 defaultpen[TypeTask] = pen;
85 defaultpen[TypeSummary] = pen;
86 defaultpen[TypeEvent] = pen;
87}
88
89QPen ItemDelegate::Private::constraintPen(const QPointF &start, const QPointF &end, const Constraint &constraint)
90{
91 QPen pen;
92 QVariant dataPen;
93
94 // Use default pens...
95 if (start.x() < end.x()) {
96 pen = QPen(Qt::black);
97 dataPen = constraint.data(Constraint::ValidConstraintPen);
98 } else {
99 pen = QPen(Qt::red);
100 dataPen = constraint.data(Constraint::InvalidConstraintPen);
101 }
102
103 // ... unless constraint.data() returned a valid pen for this case
104 if (dataPen.canConvert(QVariant::Pen)) {
105 pen = dataPen.value<QPen>();
106 }
107
108 return pen;
109}
110
113 : QItemDelegate(parent)
114 , _d(new Private)
115{
116}
117
120{
121 delete _d;
122}
123
124#define d d_func()
125
133{
134 d->defaultbrush[type] = brush;
135}
136
142{
143 return d->defaultbrush[type];
144}
145
153{
154 d->defaultpen[type] = pen;
155}
156
162{
163 return d->defaultpen[type];
164}
165
169{
170 if (!idx.isValid())
171 return QString();
172
173 const QAbstractItemModel *model = idx.model();
174 if (!model)
175 return QString();
176 QString tip = model->data(idx, Qt::ToolTipRole).toString();
177 if (!tip.isNull())
178 return tip;
179 else
180 return tr("%1 -> %2: %3")
181 .arg(model->data(idx, StartTimeRole).toString())
182 .arg(model->data(idx, EndTimeRole).toString())
183 .arg(model->data(idx, Qt::DisplayRole).toString());
184}
185
195 const QModelIndex &idx) const
196{
197 if (!idx.isValid())
198 return Span();
199
200 const QString txt = idx.model()->data(idx, Qt::DisplayRole).toString();
201 const int typ = idx.model()->data(idx, ItemTypeRole).toInt();
202 QRectF itemRect = opt.itemRect;
203
204 if (typ == TypeEvent) {
205 itemRect = QRectF(itemRect.left() - itemRect.height() / 2.,
206 itemRect.top(),
207 itemRect.height(),
208 itemRect.height());
209 }
210
211 int tw = opt.fontMetrics.horizontalAdvance(txt);
212 tw += static_cast<int>(itemRect.height() / 2.);
213 Span s;
214 switch (opt.displayPosition) {
216 s = Span(itemRect.left() - tw, itemRect.width() + tw);
217 break;
219 s = Span(itemRect.left(), itemRect.width() + tw);
220 break;
221 case StyleOptionGanttItem::Hidden: // fall through
223 s = Span(itemRect.left(), itemRect.width());
224 break;
225 }
226 return s;
227}
228
236 const StyleOptionGanttItem &opt,
237 const QModelIndex &idx) const
238{
239 if (!idx.isValid())
240 return State_None;
241 if (!(idx.model()->flags(idx) & Qt::ItemIsEditable))
242 return State_None;
243
244 const int typ = static_cast<ItemType>(idx.model()->data(idx, ItemTypeRole).toInt());
245
246 QRectF itemRect(opt.itemRect);
247
248 // An event item is infinitely thin, basically just a line, because it has only one date instead of two.
249 // It is painted with an offset of -height/2, which is taken into account here.
250 if (typ == TypeEvent)
251 itemRect = QRectF(itemRect.topLeft() - QPointF(itemRect.height() / 2.0, 0), QSizeF(itemRect.height(), itemRect.height()));
252
253 if (typ == TypeNone || typ == TypeSummary)
254 return State_None;
255 if (!itemRect.contains(pos))
256 return State_None;
257 if (typ == TypeEvent)
258 return State_Move;
259
260 qreal delta = 5.;
261 if (itemRect.width() < 15)
262 delta = 1.;
263 if (pos.x() >= itemRect.left() && pos.x() < itemRect.left() + delta) {
264 return State_ExtendLeft;
265 } else if (pos.x() <= itemRect.right() && pos.x() > itemRect.right() - delta) {
266 return State_ExtendRight;
267 } else {
268 return State_Move;
269 }
270}
271
275 const StyleOptionGanttItem &opt,
276 const QModelIndex &idx)
277{
278 if (!idx.isValid())
279 return;
280 const ItemType typ = static_cast<ItemType>(idx.model()->data(idx, ItemTypeRole).toInt());
281 const QString &txt = opt.text;
282 QRectF itemRect = opt.itemRect;
283 QRectF boundingRect = opt.boundingRect;
284 boundingRect.setY(itemRect.y());
285 boundingRect.setHeight(itemRect.height());
286
287 // qDebug() << "itemRect="<<itemRect<<", boundingRect="<<boundingRect;
288 // qDebug() << painter->font() << opt.fontMetrics.height() << painter->device()->width() << painter->device()->height();
289
290 painter->save();
291
292 QPen pen = defaultPen(typ);
293 if (opt.state & QStyle::State_Selected)
294 pen.setWidth(2 * pen.width());
295 painter->setPen(pen);
296 painter->setBrush(defaultBrush(typ));
297
298 bool drawText = true;
299 qreal pw = painter->pen().width() / 2.;
300 switch (typ) {
301 case TypeTask:
302 if (itemRect.isValid()) {
303 // TODO
304 qreal pw = painter->pen().width() / 2.;
305 pw -= 1;
306 QRectF r = itemRect;
307 r.translate(0., r.height() / 6.);
308 r.setHeight(2. * r.height() / 3.);
309 painter->setBrushOrigin(itemRect.topLeft());
310 painter->save();
311 painter->translate(0.5, 0.5);
312 painter->drawRect(r);
313 bool ok;
314 qreal completion = idx.model()->data(idx, KDGantt::TaskCompletionRole).toReal(&ok);
315 if (ok) {
316 qreal h = r.height();
317 QRectF cr(r.x(), r.y() + h / 4.,
318 r.width() * completion / 100., h / 2. + 1 /*??*/);
319 QColor compcolor(painter->pen().color());
320 compcolor.setAlpha(150);
321 painter->fillRect(cr, compcolor);
322 }
323 painter->restore();
324 }
325 break;
326 case TypeSummary:
327 if (opt.itemRect.isValid()) {
328 // TODO
329 pw -= 1;
330 const QRectF r = QRectF(opt.itemRect).adjusted(-pw, -pw, pw, pw);
331 QPainterPath path;
332 const qreal deltaY = r.height() / 2.;
333 const qreal deltaXBezierControl = .25 * qMin(r.width(), r.height());
334 const qreal deltaX = qMin(r.width() / ( qreal )2., r.height());
335 path.moveTo(r.topLeft());
336 path.lineTo(r.topRight());
337 path.lineTo(QPointF(r.right(), r.top() + 2. * deltaY));
338 // path.lineTo( QPointF( r.right()-3./2.*delta, r.top() + delta ) );
339 path.quadTo(QPointF(r.right() - deltaXBezierControl, r.top() + deltaY), QPointF(r.right() - deltaX, r.top() + deltaY));
340 // path.lineTo( QPointF( r.left()+3./2.*delta, r.top() + delta ) );
341 path.lineTo(QPointF(r.left() + deltaX, r.top() + deltaY));
342 path.quadTo(QPointF(r.left() + deltaXBezierControl, r.top() + deltaY), QPointF(r.left(), r.top() + 2. * deltaY));
343 path.closeSubpath();
344 painter->setBrushOrigin(itemRect.topLeft());
345 painter->save();
346 painter->translate(0.5, 0.5);
347 painter->drawPath(path);
348 painter->restore();
349 }
350 break;
351 case TypeEvent: /* TODO */
352 // qDebug() << opt.boundingRect << opt.itemRect;
353 if (opt.boundingRect.isValid()) {
354 const qreal pw = painter->pen().width() / 2. - 1;
355 const QRectF r = QRectF(opt.itemRect).adjusted(-pw, -pw, pw, pw).translated(-opt.itemRect.height() / 2, 0);
356 QPainterPath path;
357 const qreal delta = static_cast<int>(r.height() / 2);
358 path.moveTo(delta, 0.);
359 path.lineTo(2. * delta, delta);
360 path.lineTo(delta, 2. * delta);
361 path.lineTo(0., delta);
362 path.closeSubpath();
363 painter->save();
364 painter->translate(r.topLeft());
365 painter->translate(0, 0.5);
366 painter->drawPath(path);
367 painter->restore();
368#if 0
369 painter->setBrush( Qt::NoBrush );
370 painter->setPen( Qt::black );
371 painter->drawRect( opt.boundingRect );
372 painter->setPen( Qt::red );
373 painter->drawRect( r );
374#endif
375 }
376 break;
377 default:
378 drawText = false;
379 break;
380 }
381
383 switch (opt.displayPosition) {
386 break;
389 break;
392 break;
394 drawText = false;
395 break;
396 }
397 if (drawText) {
398 painter->drawText(boundingRect, ta | Qt::AlignVCenter, txt);
399 }
400
401 painter->restore();
402}
403
404static const qreal TURN = 10.;
405static const qreal PW = 1.5;
406
411QRectF ItemDelegate::constraintBoundingRect(const QPointF &start, const QPointF &end, const Constraint &constraint) const
412{
414 switch (constraint.relationType()) {
416 poly = finishStartLine(start, end) + finishStartArrow(start, end);
417 break;
419 poly = finishFinishLine(start, end) + finishFinishArrow(start, end);
420 break;
422 poly = startStartLine(start, end) + startStartArrow(start, end);
423 break;
425 poly = startFinishLine(start, end) + startFinishArrow(start, end);
426 break;
427 }
428 return poly.boundingRect().adjusted(-PW, -PW, PW, PW);
429}
430
437 const QPointF &start, const QPointF &end, const Constraint &constraint)
438{
439 // qDebug()<<"ItemDelegate::paintConstraintItem"<<start<<end<<constraint;
440 switch (constraint.relationType()) {
442 paintFinishStartConstraint(painter, opt, start, end, constraint);
443 break;
445 paintFinishFinishConstraint(painter, opt, start, end, constraint);
446 break;
448 paintStartStartConstraint(painter, opt, start, end, constraint);
449 break;
451 paintStartFinishConstraint(painter, opt, start, end, constraint);
452 break;
453 }
454}
455
456void ItemDelegate::paintFinishStartConstraint(QPainter *painter, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
457{
458 Q_UNUSED(opt);
459
460 const QPen pen = d->constraintPen(start, end, constraint);
461
462 painter->setPen(pen);
463 painter->setBrush(pen.color());
464
465 painter->drawPolyline(finishStartLine(start, end));
466 painter->drawPolygon(finishStartArrow(start, end));
467}
468
470{
472 qreal midx = end.x() - TURN;
473 qreal midy = (end.y() - start.y()) / 2. + start.y();
474
475 if (start.x() > end.x() - TURN) {
476 poly << start
477 << QPointF(start.x() + TURN, start.y())
478 << QPointF(start.x() + TURN, midy)
479 << QPointF(end.x() - TURN, midy)
480 << QPointF(end.x() - TURN, end.y())
481 << end;
482 } else {
483 poly << start
484 << QPointF(midx, start.y())
485 << QPointF(midx, end.y())
486 << end;
487 }
488 return poly;
489}
490
492{
493 Q_UNUSED(start);
494
496 poly << end
497 << QPointF(end.x() - TURN / 2., end.y() - TURN / 2.)
498 << QPointF(end.x() - TURN / 2., end.y() + TURN / 2.);
499 return poly;
500}
501
502void ItemDelegate::paintFinishFinishConstraint(QPainter *painter, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
503{
504 Q_UNUSED(opt);
505
506 const QPen pen = d->constraintPen(start, end, constraint);
507
508 painter->setPen(pen);
509 painter->setBrush(pen.color());
510
511 painter->drawPolyline(finishFinishLine(start, end));
512 painter->drawPolygon(finishFinishArrow(start, end));
513}
514
516{
518 qreal midx = end.x() + TURN;
519 qreal midy = (end.y() - start.y()) / 2. + start.y();
520
521 if (start.x() > end.x() + TURN) {
522 poly << start
523 << QPointF(start.x() + TURN, start.y())
524 << QPointF(start.x() + TURN, end.y())
525 << end;
526 } else {
527 poly << start
528 << QPointF(midx, start.y())
529 << QPointF(midx, midy)
530 << QPointF(end.x() + TURN, midy)
531 << QPointF(end.x() + TURN, end.y())
532 << end;
533 }
534 return poly;
535}
536
538{
539 Q_UNUSED(start);
540
542 poly << end
543 << QPointF(end.x() + TURN / 2., end.y() - TURN / 2.)
544 << QPointF(end.x() + TURN / 2., end.y() + TURN / 2.);
545 return poly;
546}
547
548void ItemDelegate::paintStartStartConstraint(QPainter *painter, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
549{
550 Q_UNUSED(opt);
551
552 const QPen pen = d->constraintPen(start, end, constraint);
553
554 painter->setPen(pen);
555 painter->setBrush(pen.color());
556
557 painter->drawPolyline(startStartLine(start, end));
558 painter->drawPolygon(startStartArrow(start, end));
559}
560
562{
563 Q_UNUSED(start);
564
566
567 if (start.x() > end.x()) {
568 poly << start
569 << QPointF(end.x() - TURN, start.y())
570 << QPointF(end.x() - TURN, end.y())
571 << end;
572 } else {
573 poly << start
574 << QPointF(start.x() - TURN, start.y())
575 << QPointF(start.x() - TURN, end.y())
576 << QPointF(end.x() - TURN, end.y())
577 << end;
578 }
579 return poly;
580}
581
583{
584 Q_UNUSED(start);
585
587 poly << end
588 << QPointF(end.x() - TURN / 2., end.y() - TURN / 2.)
589 << QPointF(end.x() - TURN / 2., end.y() + TURN / 2.);
590 return poly;
591}
592
593void ItemDelegate::paintStartFinishConstraint(QPainter *painter, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
594{
595 Q_UNUSED(opt);
596
597 const QPen pen = d->constraintPen(start, end, constraint);
598
599 painter->setPen(pen);
600 painter->setBrush(pen.color());
601
602 painter->drawPolyline(startFinishLine(start, end));
603 painter->drawPolygon(startFinishArrow(start, end));
604}
605
607{
608 Q_UNUSED(start);
609
611 qreal midx = end.x() + TURN;
612 qreal midy = (end.y() - start.y()) / 2. + start.y();
613
614 if (start.x() - TURN > end.x() + TURN) {
615 poly << start
616 << QPointF(midx, start.y())
617 << QPointF(midx, end.y())
618 << end;
619 } else {
620 poly << start
621 << QPointF(start.x() - TURN, start.y())
622 << QPointF(start.x() - TURN, midy)
623 << QPointF(midx, midy)
624 << QPointF(end.x() + TURN, end.y())
625 << end;
626 }
627 return poly;
628}
629
631{
632 Q_UNUSED(start);
633
635 poly << end
636 << QPointF(end.x() + TURN / 2., end.y() - TURN / 2.)
637 << QPointF(end.x() + TURN / 2., end.y() + TURN / 2.);
638 return poly;
639}
640
641#include "moc_kdganttitemdelegate.cpp"
A class used to represent a dependency.
QVariant data(int role) const
RelationType relationType() const
This is unused for now.
virtual void paintConstraintItem(QPainter *p, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
Paints the constraint between points start and end using painter and opt.
void paintFinishStartConstraint(QPainter *p, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
QPen defaultPen(ItemType type) const
QPolygonF startFinishArrow(const QPointF &start, const QPointF &end) const
virtual QString toolTip(const QModelIndex &idx) const
QPolygonF startStartLine(const QPointF &start, const QPointF &end) const
~ItemDelegate() override
Destructor.
virtual Span itemBoundingSpan(const StyleOptionGanttItem &opt, const QModelIndex &idx) const
virtual InteractionState interactionStateFor(const QPointF &pos, const StyleOptionGanttItem &opt, const QModelIndex &idx) const
void paintStartStartConstraint(QPainter *p, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
void setDefaultBrush(ItemType type, const QBrush &brush)
Sets the default brush used for items of type type to brush.
void paintStartFinishConstraint(QPainter *p, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
QPolygonF finishFinishLine(const QPointF &start, const QPointF &end) const
InteractionState
This enum is used for communication between the view and the delegate about user interaction with gan...
void setDefaultPen(ItemType type, const QPen &pen)
Sets the default pen used for items of type type to pen.
QPolygonF startFinishLine(const QPointF &start, const QPointF &end) const
QPolygonF finishStartArrow(const QPointF &start, const QPointF &end) const
virtual void paintGanttItem(QPainter *p, const StyleOptionGanttItem &opt, const QModelIndex &idx)
Paints the gantt item idx using painter and opt.
QPolygonF finishFinishArrow(const QPointF &start, const QPointF &end) const
QBrush defaultBrush(ItemType type) const
void paintFinishFinishConstraint(QPainter *p, const QStyleOptionGraphicsItem &opt, const QPointF &start, const QPointF &end, const Constraint &constraint)
virtual QRectF constraintBoundingRect(const QPointF &start, const QPointF &end, const Constraint &constraint) const
ItemDelegate(QObject *parent=nullptr)
Constructor.
QPolygonF startStartArrow(const QPointF &start, const QPointF &end) const
QPolygonF finishStartLine(const QPointF &start, const QPointF &end) const
A class representing a start point and a length.
QStyleOption subclass for gantt items.
Contains KDGantt macros.
static const qreal PW
static const qreal TURN
#define PRINT_INTERACTIONSTATE(x)
QDebug operator<<(QDebug dbg, KDGantt::ItemDelegate::InteractionState state)
@ TaskCompletionRole
virtual QVariant data(const QModelIndex &index, int role) const const=0
QFontMetrics fontMetrics()
T qobject_cast(QObject *object)
QString tr(const char *sourceText, const char *disambiguation, int n)
void drawPath(const QPainterPath &path)
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
void drawPolyline(const QPointF *points, int pointCount)
void drawRect(const QRectF &rectangle)
void drawText(const QPointF &position, const QString &text)
void fillRect(const QRectF &rectangle, const QBrush &brush)
const QPen & pen() const const
void restore()
void save()
void setBrush(const QBrush &brush)
void setBrushOrigin(int x, int y)
void setPen(const QColor &color)
void translate(const QPointF &offset)
void closeSubpath()
void lineTo(const QPointF &endPoint)
void moveTo(const QPointF &point)
void quadTo(const QPointF &c, const QPointF &endPoint)
QColor color() const const
void setWidth(int width)
int width() const const
qreal x() const const
qreal y() const const
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
bool contains(const QRectF &rectangle) const const
qreal height() const const
bool isValid() const const
qreal left() const const
qreal right() const const
void setHeight(qreal height)
void setY(qreal y)
qreal top() const const
QPointF topLeft() const const
QPointF topRight() const const
void translate(qreal dx, qreal dy)
QRectF translated(qreal dx, qreal dy) const const
qreal width() const const
qreal x() const const
qreal y() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QChar * data()
bool isNull() const const
typedef Alignment
ToolTipRole
ItemIsEditable
bool canConvert(int targetTypeId) const const
QString toString() const const
T value() 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