17 #include "KDChartPainterSaver_p.h"
20 #include <QAbstractTextDocumentLayout>
21 #include <QApplication>
22 #include <QCoreApplication>
26 #include <QStringList>
28 #include <QTextBlockFormat>
29 #include <QTextCursor>
30 #include <QTextDocumentFragment>
32 #include <KDABLibFakes>
73 if (mParent->layout())
74 mParent->layout()->invalidate();
76 QApplication::postEvent(mParent,
new QEvent(QEvent::LayoutRequest));
84 Qt::Alignment alignment)
86 , m_text(new
TextLayoutItem(text, attributes, area, orientation, alignment))
103 m_text->setAutoReferenceArea(area);
108 return m_text->autoReferenceArea();
113 m_text->setText(text);
118 return m_text->text();
123 m_text->setTextAttributes(a);
128 return m_text->textAttributes();
133 return m_text->isEmpty();
138 return m_text->expandingDirections();
143 const int border = borderWidth();
144 return m_text->maximumSize() + QSize(2 * border, 2 * border);
149 const int border = borderWidth();
150 return m_text->minimumSize() + QSize(2 * border, 2 * border);
155 const int border = borderWidth();
156 return m_text->sizeHint() + QSize(2 * border, 2 * border);
161 const int border = borderWidth();
162 m_text->setGeometry(r.adjusted(border, border, -border, -border));
167 const int border = borderWidth();
168 return m_text->geometry().adjusted(-border, -border, border, border);
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);
192 Qt::Alignment alignment)
195 , mTextAlignment(alignment)
196 , mAttributes(attributes)
197 , mAutoReferenceArea(area)
198 , mAutoReferenceOrientation(orientation)
200 , cachedFontSize(0.0)
201 , cachedFont(mAttributes.font())
208 , mTextAlignment(Qt::AlignLeft)
211 , cachedFont(mAttributes.font())
217 mAutoReferenceArea = area;
218 cachedSizeHint = QSize();
224 return mAutoReferenceArea;
230 cachedSizeHint = QSize();
243 if (mTextAlignment == alignment)
245 mTextAlignment = alignment;
252 return mTextAlignment;
263 cachedFont = a.
font();
264 cachedSizeHint = QSize();
314 QPointF center = rect.center();
315 t.translate(center.x(), center.y());
317 t.translate(-center.x(), -center.y());
318 return t.mapRect(rect);
321 qreal KDChart::TextLayoutItem::fitFontSizeToGeometry()
const
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()) {
334 const QSizeF textSize =
rotatedRect(fm.boundingRect(mText), mAttributes.rotation()).normalized().size();
336 if (textSize.height() <= mySize.height() && textSize.width() <= mySize.width()) {
341 if (minSize > 0 && result < minSize) {
343 }
else if (result <= 0.0) {
346 f.setPointSizeF(result);
347 fm = QFontMetrics(f);
353 return mAttributes.calculatedFontSize(mAutoReferenceArea, mAutoReferenceOrientation);
356 bool KDChart::TextLayoutItem::maybeUpdateRealFont()
const
358 const qreal fntSiz = realFontSize();
359 const bool doUpdate = !cachedSizeHint.isValid() || cachedFontSize != fntSiz;
361 if (doUpdate && fntSiz > 0.0) {
362 cachedFontSize = fntSiz;
363 cachedFont.setPointSizeF(fntSiz);
370 maybeUpdateRealFont();
377 return mCachedBoundingPolygon;
382 return intersects(other, myPos.toPoint(), otherPos.toPoint());
387 QRegion myRegion(boundingPolygon().translated(myPos - otherPos));
390 return myRegion.intersects(otherRegion);
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;
404 return cachedSizeHint;
409 maybeUpdateRealFont();
410 return unrotatedSizeHint(cachedFont);
415 QSize KDChart::TextLayoutItem::unrotatedTextSize(QFont fnt)
const
417 if (fnt == QFont()) {
422 QRect veryLarge(0, 0, 100000, 100000);
424 return fm.boundingRect(veryLarge, Qt::AlignLeft | Qt::AlignTop, mText).size().toSize();
429 return marginWidth(unrotatedTextSize());
434 return qMin(QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin,
nullptr,
nullptr),
436 textSize.height() * 2 / 3);
439 QSize KDChart::TextLayoutItem::unrotatedSizeHint(
const QFont &fnt)
const
441 QSize ret = unrotatedTextSize(fnt);
442 const int margin = marginWidth(ret);
443 ret += QSize(margin, margin);
447 QSize KDChart::TextLayoutItem::calcSizeHint(
const QFont &font)
const
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);
455 mCachedBoundingPolygon[0] = topLeft;
456 mCachedBoundingPolygon[1] = topLeft + QPoint(size.width(), 0);
457 mCachedBoundingPolygon[2] = topLeft + QPoint(size.width(), size.height());
458 mCachedBoundingPolygon[3] = topLeft + QPoint(0, size.height());
462 const QRect rect(topLeft, size);
464 t.rotate(mAttributes.rotation());
465 mCachedBoundingPolygon = t.mapToPolygon(rect);
467 return mCachedBoundingPolygon.boundingRect().size();
472 if (!mRect.isValid()) {
475 const PainterSaver painterSaver(painter);
476 QFont f = realFont();
477 if (mAttributes.autoShrink()) {
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);
492 QTextDocument *document = mAttributes.textDocument();
494 document->setPageSize(rect.size());
495 document->setHtml(mText);
496 QAbstractTextDocumentLayout::PaintContext paintcontext;
499 paintcontext.clip = rect;
500 document->documentLayout()->draw(painter, paintcontext);
502 painter->drawText(rect, mTextAlignment, mText);
513 return Qt::Horizontal;
528 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
548 if (!mRect.isValid())
551 painter->drawLine(QPointF(mRect.left(), mRect.center().y()),
552 QPointF(mRect.right(), mRect.center().y()));
577 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
597 if (!mRect.isValid())
600 painter->drawLine(QPointF(mRect.center().x(), mRect.top()),
601 QPointF(mRect.center().x(), mRect.bottom()));
606 const QBrush &brush,
const QPen &pen,
607 Qt::Alignment alignment)
649 return mMarker.markerSize().toSize();
654 paintIntoRect(painter, mRect, mDiagram, mMarker, mBrush, mPen);
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));
675 #ifdef DEBUG_ITEMS_PAINT
676 QPointF oldPos = pos;
681 pos += QPointF(
static_cast<qreal
>(siz.width()) / 2.0,
682 static_cast<qreal
>(siz.height()) / 2.0);
684 diagram->
paintMarker(painter, marker, brush, pen, pos.toPoint(), siz);
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);
697 Qt::Alignment legendLineSymbolAlignment,
698 Qt::Alignment alignment)
703 , mLegendLineSymbolAlignment(legendLineSymbolAlignment)
742 return QSize(mLength, mPen.width() + 2);
747 if (mLegendLineSymbolAlignment == legendLineSymbolAlignment)
750 mLegendLineSymbolAlignment = legendLineSymbolAlignment;
755 return mLegendLineSymbolAlignment;
760 paintIntoRect(painter, mRect, mPen, mLegendLineSymbolAlignment);
767 Qt::Alignment lineAlignment)
772 const QPen oldPen = painter->pen();
775 if (lineAlignment == Qt::AlignTop)
777 else if (lineAlignment == Qt::AlignBottom)
780 y = rect.center().y();
782 painter->drawLine(QPointF(rect.left(), y),
783 QPointF(rect.right(), y));
784 painter->setPen(oldPen);
793 const QBrush &markerBrush,
794 const QPen &markerPen,
795 Qt::Alignment alignment)
798 , mLineLength(lineLength)
800 , mMarkerOffs(markerOffs)
802 , mMarkerBrush(markerBrush)
803 , mMarkerPen(markerPen)
839 const QSize lineSize(mLineLength, mLinePen.width() + 2);
840 return lineSize.expandedTo(mMarker.markerSize().toSize());
850 QPoint(mRect.x() + mMarkerOffs, mRect.y()),
851 QSize(mMarker.markerSize().toSize().width(), mRect.height()));
853 painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen);
857 bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
858 bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout)
860 , mLayoutIsAtTopPosition(layoutIsAtTopPosition)
861 , mRightLeftLayout(rightLeftLayout)
862 , mLayoutIsAtLeftPosition(layoutIsAtLeftPosition)
863 , mTopBottomLayout(topBottomLayout)
903 commonBrush = hasSimpleBrush ? ba.
brush() : QBrush();
905 if (!hasSimpleBrush || ba.
brush() != commonBrush) {
906 commonBrush = QBrush();
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));
922 topBottomOverlap = qMax(topBottomOverlap,
923 mLayoutIsAtLeftPosition ? area->rightOverlap()
924 : area->leftOverlap());
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));
936 leftRightOverlap = qMax(leftRightOverlap,
937 mLayoutIsAtTopPosition ? area->bottomOverlap()
938 : area->topOverlap());
943 if (topBottomOverlap > 0 && leftRightOverlap > 0)
944 mCommonBrush = commonBrush;
946 mCommonBrush = QBrush();
947 mCachedSize = QSize(topBottomOverlap, leftRightOverlap);
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();
960 p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
961 if (mLayoutIsAtTopPosition) {
962 p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
965 p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
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);
985 if ( !mRect.isValid() )
988 painter->drawRect( mRect );
989 painter->drawLine( QPointF( mRect.topLeft(), mRect.bottomRight() ) );
990 painter->drawLine( QPointF( mRect.topRight(), mRect.bottomLeft() ) );
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)
QSize sizeHint() const override
bool isEmpty() const override
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
QRect geometry() const override
BackgroundPixmapMode pixmapMode() const
@ BackgroundPixmapModeNone
static QPaintDevice * paintDevice()
QSize maximumSize() const override
QSize minimumSize() const override
QSize sizeHint() const override
QRect geometry() const override
void paint(QPainter *) override
HorizontalLineLayoutItem()
Qt::Orientations expandingDirections() const override
void setGeometry(const QRect &r) override
bool isEmpty() const 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
QSize maximumSize() const override
void setGeometry(const QRect &r) override
Qt::Orientations expandingDirections() const override
QRect geometry() const override
bool isEmpty() const override
QSize minimumSize() const override
LineWithMarkerLayoutItem(AbstractDiagram *diagram, int lineLength, const QPen &linePen, int markerOffs, const MarkerAttributes &marker, const QBrush &markerBrush, const QPen &markerPen, Qt::Alignment alignment={})
QSize sizeHint() const override
void paint(QPainter *) override
A set of attributes controlling the appearance of data set markers.
QSizeF markerSize() const
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)
bool isEmpty() const override
void setText(const QString &text)
void paint(QPainter *painter) override
~TextBubbleLayoutItem() override
QRect geometry() const override
void setGeometry(const QRect &r) override
QSize maximumSize() const override
TextAttributes textAttributes() const
QSize sizeHint() const override
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
QSize sizeHint() const override
QSize maximumSize() const override
Qt::Orientations expandingDirections() const override
void paint(QPainter *) override
QSize minimumSize() const override
QRect geometry() const override
bool isEmpty() const override
void setGeometry(const QRect &r) override