KD Chart API Documentation  3.1
KDChartLayoutItems.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 "KDChartLayoutItems.h"
12 #include "KDChartAbstractArea.h"
13 #include "KDChartAbstractDiagram.h"
15 #include "KDChartFrameAttributes.h"
16 #include "KDChartPaintContext.h"
17 #include "KDChartPainterSaver_p.h"
19 #include "KDTextDocument.h"
20 #include <QAbstractTextDocumentLayout>
21 #include <QApplication>
22 #include <QCoreApplication>
23 #include <QDebug>
24 #include <QLayout>
25 #include <QPainter>
26 #include <QStringList>
27 #include <QStyle>
28 #include <QTextBlockFormat>
29 #include <QTextCursor>
30 #include <QTextDocumentFragment>
31 
32 #include <KDABLibFakes>
33 
34 #include <math.h>
35 
36 // #define DEBUG_ITEMS_PAINT
37 
47 {
48  mParent = widget;
49 }
50 
52 {
53  paint(&painter);
54 }
55 
60 {
61  if (context)
62  paint(context->painter());
63 }
64 
69 {
70  // This is exactly like what QWidget::updateGeometry does.
71  // qDebug("KDChart::AbstractLayoutItem::sizeHintChanged() called");
72  if (mParent) {
73  if (mParent->layout())
74  mParent->layout()->invalidate();
75  else
76  QApplication::postEvent(mParent, new QEvent(QEvent::LayoutRequest));
77  }
78 }
79 
81  const KDChart::TextAttributes &attributes,
82  const QObject *area,
84  Qt::Alignment alignment)
85  : AbstractLayoutItem(alignment)
86  , m_text(new TextLayoutItem(text, attributes, area, orientation, alignment))
87 {
88 }
89 
91  : AbstractLayoutItem(Qt::AlignLeft)
92  , m_text(new TextLayoutItem())
93 {
94 }
95 
97 {
98  delete m_text;
99 }
100 
102 {
103  m_text->setAutoReferenceArea(area);
104 }
105 
107 {
108  return m_text->autoReferenceArea();
109 }
110 
111 void KDChart::TextBubbleLayoutItem::setText(const QString &text)
112 {
113  m_text->setText(text);
114 }
115 
117 {
118  return m_text->text();
119 }
120 
122 {
123  m_text->setTextAttributes(a);
124 }
125 
127 {
128  return m_text->textAttributes();
129 }
130 
132 {
133  return m_text->isEmpty();
134 }
135 
137 {
138  return m_text->expandingDirections();
139 }
140 
142 {
143  const int border = borderWidth();
144  return m_text->maximumSize() + QSize(2 * border, 2 * border);
145 }
146 
148 {
149  const int border = borderWidth();
150  return m_text->minimumSize() + QSize(2 * border, 2 * border);
151 }
152 
154 {
155  const int border = borderWidth();
156  return m_text->sizeHint() + QSize(2 * border, 2 * border);
157 }
158 
160 {
161  const int border = borderWidth();
162  m_text->setGeometry(r.adjusted(border, border, -border, -border));
163 }
164 
166 {
167  const int border = borderWidth();
168  return m_text->geometry().adjusted(-border, -border, border, border);
169 }
170 
172 {
173  const QPen oldPen = painter->pen();
174  const QBrush oldBrush = painter->brush();
175  painter->setPen(Qt::black);
176  painter->setBrush(QColor(255, 255, 220));
177  painter->drawRoundedRect(geometry(), 10, 25, Qt::RelativeSize);
178  painter->setPen(oldPen);
179  painter->setBrush(oldBrush);
180  m_text->paint(painter);
181 }
182 
184 {
185  return 1;
186 }
187 
189  const KDChart::TextAttributes &attributes,
190  const QObject *area,
192  Qt::Alignment alignment)
193  : AbstractLayoutItem(alignment)
194  , mText(text)
195  , mTextAlignment(alignment)
196  , mAttributes(attributes)
197  , mAutoReferenceArea(area)
198  , mAutoReferenceOrientation(orientation)
199  , cachedSizeHint() // default this to invalid to force just-in-time calculation before first use of sizeHint()
200  , cachedFontSize(0.0)
201  , cachedFont(mAttributes.font())
202 {
203 }
204 
206  : AbstractLayoutItem(Qt::AlignLeft)
207  , mText()
208  , mTextAlignment(Qt::AlignLeft)
209  , mAttributes()
210  , cachedSizeHint() // default this to invalid to force just-in-time calculation before first use of sizeHint()
211  , cachedFont(mAttributes.font())
212 {
213 }
214 
216 {
217  mAutoReferenceArea = area;
218  cachedSizeHint = QSize();
219  sizeHint();
220 }
221 
223 {
224  return mAutoReferenceArea;
225 }
226 
227 void KDChart::TextLayoutItem::setText(const QString &text)
228 {
229  mText = text;
230  cachedSizeHint = QSize();
231  sizeHint();
232  if (mParent)
233  mParent->update();
234 }
235 
237 {
238  return mText;
239 }
240 
241 void KDChart::TextLayoutItem::setTextAlignment(Qt::Alignment alignment)
242 {
243  if (mTextAlignment == alignment)
244  return;
245  mTextAlignment = alignment;
246  if (mParent)
247  mParent->update();
248 }
249 
251 {
252  return mTextAlignment;
253 }
254 
261 {
262  mAttributes = a;
263  cachedFont = a.font();
264  cachedSizeHint = QSize(); // invalidate size hint
265  sizeHint();
266  if (mParent)
267  mParent->update();
268 }
269 
276 {
277  return mAttributes;
278 }
279 
281 {
282  return {}; // Grow neither vertically nor horizontally
283 }
284 
286 {
287  return mRect;
288 }
289 
291 {
292  return false; // never empty, otherwise the layout item would not exist
293 }
294 
296 {
297  return sizeHint(); // PENDING(kalle) Review, quite inflexible
298 }
299 
301 {
302  return sizeHint(); // PENDING(kalle) Review, quite inflexible
303 }
304 
306 {
307  mRect = r;
308 }
309 
310 // returns the bounding box of rect rotated around its center
311 QRectF rotatedRect(const QRectF &rect, qreal rotation)
312 {
313  QTransform t;
314  QPointF center = rect.center();
315  t.translate(center.x(), center.y());
316  t.rotate(rotation);
317  t.translate(-center.x(), -center.y());
318  return t.mapRect(rect);
319 }
320 
321 qreal KDChart::TextLayoutItem::fitFontSizeToGeometry() const
322 {
323  QFont f = realFont();
324  const qreal origResult = f.pointSizeF();
325  qreal result = origResult;
326  const qreal minSize = mAttributes.minimalFontSize().value();
327  const QSize mySize = geometry().size();
328  if (mySize.isNull()) {
329  return result;
330  }
331 
332  QFontMetrics fm(f);
333  while (true) {
334  const QSizeF textSize = rotatedRect(fm.boundingRect(mText), mAttributes.rotation()).normalized().size();
335 
336  if (textSize.height() <= mySize.height() && textSize.width() <= mySize.width()) {
337  return result;
338  }
339 
340  result -= 0.5;
341  if (minSize > 0 && result < minSize) {
342  return result + 0.5;
343  } else if (result <= 0.0) {
344  return origResult;
345  }
346  f.setPointSizeF(result);
347  fm = QFontMetrics(f);
348  }
349 }
350 
352 {
353  return mAttributes.calculatedFontSize(mAutoReferenceArea, mAutoReferenceOrientation);
354 }
355 
356 bool KDChart::TextLayoutItem::maybeUpdateRealFont() const
357 {
358  const qreal fntSiz = realFontSize();
359  const bool doUpdate = !cachedSizeHint.isValid() || cachedFontSize != fntSiz;
360 
361  if (doUpdate && fntSiz > 0.0) {
362  cachedFontSize = fntSiz;
363  cachedFont.setPointSizeF(fntSiz);
364  }
365  return doUpdate; // "didUpdate" by now
366 }
367 
369 {
370  maybeUpdateRealFont();
371  return cachedFont;
372 }
373 
375 {
376  // should probably call sizeHint() here, but that one is expensive (see TODO there)
377  return mCachedBoundingPolygon;
378 }
379 
380 bool KDChart::TextLayoutItem::intersects(const TextLayoutItem &other, const QPointF &myPos, const QPointF &otherPos) const
381 {
382  return intersects(other, myPos.toPoint(), otherPos.toPoint());
383 }
384 
385 bool KDChart::TextLayoutItem::intersects(const TextLayoutItem &other, const QPoint &myPos, const QPoint &otherPos) const
386 {
387  QRegion myRegion(boundingPolygon().translated(myPos - otherPos));
388  QRegion otherRegion(other.boundingPolygon());
389 
390  return myRegion.intersects(otherRegion);
391 }
392 
394 {
395  // ### we only really need to recalculate the size hint when mAttributes.rotation has *changed*
396  if (maybeUpdateRealFont() || mAttributes.rotation() || !cachedSizeHint.isValid()) {
397  const QSize newSizeHint(calcSizeHint(cachedFont));
398  Q_ASSERT(newSizeHint.isValid());
399  if (newSizeHint != cachedSizeHint) {
400  cachedSizeHint = newSizeHint;
401  sizeHintChanged();
402  }
403  }
404  return cachedSizeHint;
405 }
406 
408 {
409  maybeUpdateRealFont(); // make sure the cached font is up to date
410  return unrotatedSizeHint(cachedFont);
411 }
412 
413 // PENDING(kalle) Support auto shrink
414 
415 QSize KDChart::TextLayoutItem::unrotatedTextSize(QFont fnt) const
416 {
417  if (fnt == QFont()) {
418  fnt = realFont(); // this is the cached font in most cases
419  }
420 
421  const QFontMetricsF fm(fnt, GlobalMeasureScaling::paintDevice());
422  QRect veryLarge(0, 0, 100000, 100000);
423  // this overload of boundingRect() interprets \n as line breaks, not as regular characters.
424  return fm.boundingRect(veryLarge, Qt::AlignLeft | Qt::AlignTop, mText).size().toSize();
425 }
426 
428 {
429  return marginWidth(unrotatedTextSize());
430 }
431 
432 int KDChart::TextLayoutItem::marginWidth(const QSize &textSize) const
433 {
434  return qMin(QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin, nullptr, nullptr),
435  // decrease frame size if the text is small
436  textSize.height() * 2 / 3);
437 }
438 
439 QSize KDChart::TextLayoutItem::unrotatedSizeHint(const QFont &fnt) const
440 {
441  QSize ret = unrotatedTextSize(fnt);
442  const int margin = marginWidth(ret);
443  ret += QSize(margin, margin);
444  return ret;
445 }
446 
447 QSize KDChart::TextLayoutItem::calcSizeHint(const QFont &font) const
448 {
449  const QSize size = unrotatedSizeHint(font);
450  QPoint topLeft(-size.width() * 0.5, -size.height() * 0.5);
451  if (!mAttributes.rotation()) {
452  mCachedBoundingPolygon.resize(4);
453  // using the same winding order as returned by QPolygon QTransform::mapToPolygon(const QRect&),
454  // which is: 0-1: top edge, 1-2: right edge, 2-3: bottom edge, 3-0: left edge (of input rect)
455  mCachedBoundingPolygon[0] = topLeft;
456  mCachedBoundingPolygon[1] = topLeft + QPoint(size.width(), 0); // top right
457  mCachedBoundingPolygon[2] = topLeft + QPoint(size.width(), size.height()); // bottom right
458  mCachedBoundingPolygon[3] = topLeft + QPoint(0, size.height()); // bottom left
459  return size;
460  }
461 
462  const QRect rect(topLeft, size);
463  QTransform t;
464  t.rotate(mAttributes.rotation());
465  mCachedBoundingPolygon = t.mapToPolygon(rect);
466 
467  return mCachedBoundingPolygon.boundingRect().size();
468 }
469 
470 void KDChart::TextLayoutItem::paint(QPainter *painter)
471 {
472  if (!mRect.isValid()) {
473  return;
474  }
475  const PainterSaver painterSaver(painter);
476  QFont f = realFont();
477  if (mAttributes.autoShrink()) {
478  f.setPointSizeF(fitFontSizeToGeometry());
479  }
480  painter->setFont(f);
481 
482  QRectF rect = mRect;
483  rect.translate(-rect.center());
484  painter->translate(mRect.center());
485  painter->rotate(mAttributes.rotation());
486 #ifdef DEBUG_ITEMS_PAINT
487  painter->setPen(Qt::red);
488  painter->drawRect(rect);
489 #endif
490 
491  painter->setPen(PrintingParameters::scalePen(mAttributes.pen()));
492  QTextDocument *document = mAttributes.textDocument();
493  if (document) {
494  document->setPageSize(rect.size());
495  document->setHtml(mText);
496  QAbstractTextDocumentLayout::PaintContext paintcontext;
497  // ### this doesn't work for rotated painting because clip does not translate the painting
498  // TODO translate the painting either using a QTransform or one of QPainter's transform stages
499  paintcontext.clip = rect;
500  document->documentLayout()->draw(painter, paintcontext);
501  } else {
502  painter->drawText(rect, mTextAlignment, mText);
503  }
504 }
505 
507  : AbstractLayoutItem(Qt::AlignCenter)
508 {
509 }
510 
512 {
513  return Qt::Horizontal;
514 }
515 
517 {
518  return mRect;
519 }
520 
522 {
523  return false; // never empty, otherwise the layout item would not exist
524 }
525 
527 {
528  return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
529 }
530 
532 {
533  return QSize(0, 0);
534 }
535 
537 {
538  mRect = r;
539 }
540 
542 {
543  return QSize(-1, 3); // see qframe.cpp
544 }
545 
547 {
548  if (!mRect.isValid())
549  return;
550 
551  painter->drawLine(QPointF(mRect.left(), mRect.center().y()),
552  QPointF(mRect.right(), mRect.center().y()));
553 }
554 
556  : AbstractLayoutItem(Qt::AlignCenter)
557 {
558 }
559 
561 {
562  return Qt::Vertical;
563 }
564 
566 {
567  return mRect;
568 }
569 
571 {
572  return false; // never empty, otherwise the layout item would not exist
573 }
574 
576 {
577  return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
578 }
579 
581 {
582  return QSize(0, 0);
583 }
584 
586 {
587  mRect = r;
588 }
589 
591 {
592  return QSize(3, -1); // see qframe.cpp
593 }
594 
596 {
597  if (!mRect.isValid())
598  return;
599 
600  painter->drawLine(QPointF(mRect.center().x(), mRect.top()),
601  QPointF(mRect.center().x(), mRect.bottom()));
602 }
603 
605  const MarkerAttributes &marker,
606  const QBrush &brush, const QPen &pen,
607  Qt::Alignment alignment)
608  : AbstractLayoutItem(alignment)
609  , mDiagram(diagram)
610  , mMarker(marker)
611  , mBrush(brush)
612  , mPen(pen)
613 {
614 }
615 
617 {
618  return {}; // Grow neither vertically nor horizontally
619 }
620 
622 {
623  return mRect;
624 }
625 
627 {
628  return false; // never empty, otherwise the layout item would not exist
629 }
630 
632 {
633  return sizeHint(); // PENDING(kalle) Review, quite inflexible
634 }
635 
637 {
638  return sizeHint(); // PENDING(kalle) Review, quite inflexible
639 }
640 
642 {
643  mRect = r;
644 }
645 
647 {
648  // qDebug() << "KDChart::MarkerLayoutItem::sizeHint() returns:"<<mMarker.markerSize().toSize();
649  return mMarker.markerSize().toSize();
650 }
651 
652 void KDChart::MarkerLayoutItem::paint(QPainter *painter)
653 {
654  paintIntoRect(painter, mRect, mDiagram, mMarker, mBrush, mPen);
655 }
656 
658  QPainter *painter,
659  const QRect &rect,
660  AbstractDiagram *diagram,
661  const MarkerAttributes &marker,
662  const QBrush &brush,
663  const QPen &pen)
664 {
665  if (!rect.isValid())
666  return;
667 
668  // The layout management may assign a larger rect than what we
669  // wanted. We need to adjust the position.
670  const QSize siz = marker.markerSize().toSize();
671  QPointF pos = rect.topLeft();
672  pos += QPointF(static_cast<qreal>((rect.width() - siz.width()) / 2.0),
673  static_cast<qreal>((rect.height() - siz.height()) / 2.0));
674 
675 #ifdef DEBUG_ITEMS_PAINT
676  QPointF oldPos = pos;
677 #endif
678 
679  // And finally, drawMarker() assumes the position to be the center
680  // of the marker, adjust again.
681  pos += QPointF(static_cast<qreal>(siz.width()) / 2.0,
682  static_cast<qreal>(siz.height()) / 2.0);
683 
684  diagram->paintMarker(painter, marker, brush, pen, pos.toPoint(), siz);
685 
686 #ifdef DEBUG_ITEMS_PAINT
687  const QPen oldPen(painter->pen());
688  painter->setPen(Qt::red);
689  painter->drawRect(QRect(oldPos.toPoint(), siz));
690  painter->setPen(oldPen);
691 #endif
692 }
693 
695  int length,
696  const QPen &pen,
697  Qt::Alignment legendLineSymbolAlignment,
698  Qt::Alignment alignment)
699  : AbstractLayoutItem(alignment)
700  , mDiagram(diagram)
701  , mLength(length)
702  , mPen(pen)
703  , mLegendLineSymbolAlignment(legendLineSymbolAlignment)
704 {
705  // enforce a minimum pen width
706  if (pen.width() < 2)
707  mPen.setWidth(2);
708 }
709 
711 {
712  return {}; // Grow neither vertically nor horizontally
713 }
714 
716 {
717  return mRect;
718 }
719 
721 {
722  return false; // never empty, otherwise the layout item would not exist
723 }
724 
726 {
727  return sizeHint(); // PENDING(kalle) Review, quite inflexible
728 }
729 
731 {
732  return sizeHint(); // PENDING(kalle) Review, quite inflexible
733 }
734 
736 {
737  mRect = r;
738 }
739 
741 {
742  return QSize(mLength, mPen.width() + 2);
743 }
744 
745 void KDChart::LineLayoutItem::setLegendLineSymbolAlignment(Qt::Alignment legendLineSymbolAlignment)
746 {
747  if (mLegendLineSymbolAlignment == legendLineSymbolAlignment)
748  return;
749 
750  mLegendLineSymbolAlignment = legendLineSymbolAlignment;
751 }
752 
754 {
755  return mLegendLineSymbolAlignment;
756 }
757 
758 void KDChart::LineLayoutItem::paint(QPainter *painter)
759 {
760  paintIntoRect(painter, mRect, mPen, mLegendLineSymbolAlignment);
761 }
762 
764  QPainter *painter,
765  const QRect &rect,
766  const QPen &pen,
767  Qt::Alignment lineAlignment)
768 {
769  if (!rect.isValid())
770  return;
771 
772  const QPen oldPen = painter->pen();
773  painter->setPen(PrintingParameters::scalePen(pen));
774  qreal y = 0;
775  if (lineAlignment == Qt::AlignTop)
776  y = rect.top();
777  else if (lineAlignment == Qt::AlignBottom)
778  y = rect.bottom();
779  else
780  y = rect.center().y();
781 
782  painter->drawLine(QPointF(rect.left(), y),
783  QPointF(rect.right(), y));
784  painter->setPen(oldPen);
785 }
786 
788  KDChart::AbstractDiagram *diagram,
789  int lineLength,
790  const QPen &linePen,
791  int markerOffs,
792  const MarkerAttributes &marker,
793  const QBrush &markerBrush,
794  const QPen &markerPen,
795  Qt::Alignment alignment)
796  : AbstractLayoutItem(alignment)
797  , mDiagram(diagram)
798  , mLineLength(lineLength)
799  , mLinePen(linePen)
800  , mMarkerOffs(markerOffs)
801  , mMarker(marker)
802  , mMarkerBrush(markerBrush)
803  , mMarkerPen(markerPen)
804 {
805 }
806 
808 {
809  return {}; // Grow neither vertically nor horizontally
810 }
811 
813 {
814  return mRect;
815 }
816 
818 {
819  return false; // never empty, otherwise the layout item would not exist
820 }
821 
823 {
824  return sizeHint(); // PENDING(kalle) Review, quite inflexible
825 }
826 
828 {
829  return sizeHint(); // PENDING(kalle) Review, quite inflexible
830 }
831 
833 {
834  mRect = r;
835 }
836 
838 {
839  const QSize lineSize(mLineLength, mLinePen.width() + 2);
840  return lineSize.expandedTo(mMarker.markerSize().toSize());
841 }
842 
844 {
845  // paint the line over the full width, into the vertical middle of the rect
846  LineLayoutItem::paintIntoRect(painter, mRect, mLinePen, Qt::AlignCenter);
847 
848  // paint the marker with the given offset from the left side of the line
849  const QRect r(
850  QPoint(mRect.x() + mMarkerOffs, mRect.y()),
851  QSize(mMarker.markerSize().toSize().width(), mRect.height()));
853  painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen);
854 }
855 
857  bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
858  bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout)
859  : AbstractLayoutItem(Qt::AlignCenter)
860  , mLayoutIsAtTopPosition(layoutIsAtTopPosition)
861  , mRightLeftLayout(rightLeftLayout)
862  , mLayoutIsAtLeftPosition(layoutIsAtLeftPosition)
863  , mTopBottomLayout(topBottomLayout)
864 {
865 }
866 
868 {
869  return {}; // Grow neither vertically nor horizontally
870 }
871 
873 {
874  return mRect;
875 }
876 
878 {
879  return true; // never empty, otherwise the layout item would not exist
880 }
881 
883 {
884  return sizeHint();
885 }
886 
888 {
889  return sizeHint();
890 }
891 
893 {
894  mRect = r;
895 }
896 
897 static void updateCommonBrush(QBrush &commonBrush, bool &bStart, const KDChart::AbstractArea &area)
898 {
900  const bool hasSimpleBrush = (!area.frameAttributes().isVisible() && ba.isVisible() && ba.pixmapMode() == KDChart::BackgroundAttributes::BackgroundPixmapModeNone && ba.brush().gradient() == nullptr);
901  if (bStart) {
902  bStart = false;
903  commonBrush = hasSimpleBrush ? ba.brush() : QBrush();
904  } else {
905  if (!hasSimpleBrush || ba.brush() != commonBrush) {
906  commonBrush = QBrush();
907  }
908  }
909 }
910 
912 {
913  QBrush commonBrush;
914  bool bStart = true;
915  // calculate the maximal overlap of the top/bottom axes:
916  int topBottomOverlap = 0;
917  if (mTopBottomLayout) {
918  for (int i = 0; i < mTopBottomLayout->count(); ++i) {
919  auto *area = dynamic_cast<AbstractArea *>(mTopBottomLayout->itemAt(i));
920  if (area) {
921  // qDebug() << "AutoSpacerLayoutItem testing" << area;
922  topBottomOverlap = qMax(topBottomOverlap,
923  mLayoutIsAtLeftPosition ? area->rightOverlap()
924  : area->leftOverlap());
925  updateCommonBrush(commonBrush, bStart, *area);
926  }
927  }
928  }
929  // calculate the maximal overlap of the left/right axes:
930  int leftRightOverlap = 0;
931  if (mRightLeftLayout) {
932  for (int i = 0; i < mRightLeftLayout->count(); ++i) {
933  auto *area = dynamic_cast<AbstractArea *>(mRightLeftLayout->itemAt(i));
934  if (area) {
935  // qDebug() << "AutoSpacerLayoutItem testing" << area;
936  leftRightOverlap = qMax(leftRightOverlap,
937  mLayoutIsAtTopPosition ? area->bottomOverlap()
938  : area->topOverlap());
939  updateCommonBrush(commonBrush, bStart, *area);
940  }
941  }
942  }
943  if (topBottomOverlap > 0 && leftRightOverlap > 0)
944  mCommonBrush = commonBrush;
945  else
946  mCommonBrush = QBrush();
947  mCachedSize = QSize(topBottomOverlap, leftRightOverlap);
948  // qDebug() << mCachedSize;
949  return mCachedSize;
950 }
951 
953 {
954  if (mParentLayout && mRect.isValid() && mCachedSize.isValid() && mCommonBrush.style() != Qt::NoBrush) {
955  QPoint p1(mRect.topLeft());
956  QPoint p2(mRect.bottomRight());
957  if (mLayoutIsAtLeftPosition)
958  p1.rx() += mCachedSize.width() - mParentLayout->spacing();
959  else
960  p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
961  if (mLayoutIsAtTopPosition) {
962  p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
963  p2.ry() -= 1;
964  } else
965  p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
966  // qDebug() << mLayoutIsAtTopPosition << mLayoutIsAtLeftPosition;
967  // qDebug() << mRect;
968  // qDebug() << mParentLayout->margin();
969  // qDebug() << QRect( p1, p2 );
970  const QPoint oldBrushOrigin(painter->brushOrigin());
971  const QBrush oldBrush(painter->brush());
972  const QPen oldPen(painter->pen());
973  const QPointF newTopLeft(painter->deviceTransform().map(p1));
974  painter->setBrushOrigin(newTopLeft);
975  painter->setBrush(mCommonBrush);
976  painter->setPen(Qt::NoPen);
977  painter->drawRect(QRect(p1, p2));
978  painter->setBrushOrigin(oldBrushOrigin);
979  painter->setBrush(oldBrush);
980  painter->setPen(oldPen);
981  }
982  // debug code:
983 #if 0
984  //qDebug() << "KDChart::AutoSpacerLayoutItem::paint()";
985  if ( !mRect.isValid() )
986  return;
987 
988  painter->drawRect( mRect );
989  painter->drawLine( QPointF( mRect.topLeft(), mRect.bottomRight() ) );
990  painter->drawLine( QPointF( mRect.topRight(), mRect.bottomLeft() ) );
991 #endif
992 }
static void updateCommonBrush(QBrush &commonBrush, bool &bStart, const KDChart::AbstractArea &area)
QRectF rotatedRect(const QRectF &rect, qreal rotation)
static qreal fitFontSizeToGeometry(const QString &text, const QFont &font, const QRectF &geometry, const TextAttributes &ta)
BackgroundAttributes backgroundAttributes() const
FrameAttributes frameAttributes() const
An area in the chart with a background, a frame, etc.
AbstractDiagram defines the interface for diagram classes.
virtual void paintMarker(QPainter *painter, const MarkerAttributes &markerAttributes, const QBrush &brush, const QPen &, const QPointF &point, const QSizeF &size)
virtual void sizeHintChanged() const
virtual void paintCtx(PaintContext *context)
virtual void paintAll(QPainter &painter)
virtual void setParentWidget(QWidget *widget)
Qt::Orientations expandingDirections() const override
AutoSpacerLayoutItem(bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout, bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout)
void setGeometry(const QRect &r) override
QSize maximumSize() const override
void paint(QPainter *) override
QSize minimumSize() const override
BackgroundPixmapMode pixmapMode() const
static QPaintDevice * paintDevice()
Qt::Orientations expandingDirections() const override
void setGeometry(const QRect &r) override
virtual Qt::Alignment legendLineSymbolAlignment() const
bool isEmpty() const override
void setGeometry(const QRect &r) override
QSize maximumSize() const override
QSize minimumSize() const override
LineLayoutItem(AbstractDiagram *diagram, int length, const QPen &pen, Qt::Alignment mLegendLineSymbolAlignment, Qt::Alignment alignment={})
void setLegendLineSymbolAlignment(Qt::Alignment legendLineSymbolAlignment)
QRect geometry() const override
QSize sizeHint() const override
Qt::Orientations expandingDirections() const override
static void paintIntoRect(QPainter *painter, const QRect &rect, const QPen &pen, Qt::Alignment lineAlignment)
void paint(QPainter *) override
void setGeometry(const QRect &r) override
Qt::Orientations expandingDirections() const override
LineWithMarkerLayoutItem(AbstractDiagram *diagram, int lineLength, const QPen &linePen, int markerOffs, const MarkerAttributes &marker, const QBrush &markerBrush, const QPen &markerPen, Qt::Alignment alignment={})
A set of attributes controlling the appearance of data set markers.
QRect geometry() const override
QSize maximumSize() const override
bool isEmpty() const override
QSize minimumSize() const override
void setGeometry(const QRect &r) override
MarkerLayoutItem(AbstractDiagram *diagram, const MarkerAttributes &marker, const QBrush &brush, const QPen &pen, Qt::Alignment alignment={})
void paint(QPainter *) override
QSize sizeHint() const override
Qt::Orientations expandingDirections() const override
static void paintIntoRect(QPainter *painter, const QRect &rect, AbstractDiagram *diagram, const MarkerAttributes &marker, const QBrush &brush, const QPen &pen)
Stores information about painting diagrams.
QPainter * painter() const
static QPen scalePen(const QPen &pen)
A set of text attributes.
void setAutoReferenceArea(const QObject *area)
void setText(const QString &text)
void paint(QPainter *painter) override
void setGeometry(const QRect &r) override
QSize maximumSize() const override
TextAttributes textAttributes() const
QSize minimumSize() const override
void setTextAttributes(const TextAttributes &a)
Qt::Orientations expandingDirections() const override
const QObject * autoReferenceArea() const
virtual qreal realFontSize() const
QSize sizeHint() const override
Qt::Alignment textAlignment() const
void setTextAttributes(const TextAttributes &a)
Use this to specify the text attributes to be used for this item.
virtual QFont realFont() const
virtual QSize sizeHintUnrotated() const
QSize maximumSize() const override
TextAttributes textAttributes() const
void setTextAlignment(Qt::Alignment)
void setAutoReferenceArea(const QObject *area)
void paint(QPainter *) override
virtual bool intersects(const TextLayoutItem &other, const QPointF &myPos, const QPointF &otherPos) const
bool isEmpty() const override
virtual int marginWidth() const
const QObject * autoReferenceArea() const
QPolygon boundingPolygon() const
void setText(const QString &text)
void setGeometry(const QRect &r) override
Qt::Orientations expandingDirections() const override
QSize minimumSize() const override
QRect geometry() const override
Qt::Orientations expandingDirections() const override
void paint(QPainter *) override
void setGeometry(const QRect &r) override

© 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 by doxygen 1.9.1