KD Chart 2  [rev.2.7]
KDChartLayoutItems.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
23 #include "KDChartLayoutItems.h"
24 #include "KDTextDocument.h"
25 #include "KDChartAbstractArea.h"
26 #include "KDChartAbstractDiagram.h"
28 #include "KDChartFrameAttributes.h"
29 #include "KDChartPaintContext.h"
30 #include "KDChartPainterSaver_p.h"
32 #include <QTextCursor>
33 #include <QTextBlockFormat>
34 #include <QTextDocumentFragment>
35 #include <QAbstractTextDocumentLayout>
36 #include <QLayout>
37 #include <QPainter>
38 #include <QDebug>
39 #include <QCoreApplication>
40 #include <QApplication>
41 #include <QStringList>
42 #include <QStyle>
43 
44 #include <KDABLibFakes>
45 
46 #include <math.h>
47 
48 
49 //#define DEBUG_ITEMS_PAINT
50 
60 {
61  mParent = widget;
62 }
63 
64 void KDChart::AbstractLayoutItem::paintAll( QPainter& painter )
65 {
66  paint( &painter );
67 }
68 
73 {
74  if ( context )
75  paint( context->painter() );
76 }
77 
82 {
83  // This is exactly like what QWidget::updateGeometry does.
84 // qDebug("KDChart::AbstractLayoutItem::sizeHintChanged() called");
85  if ( mParent ) {
86  if ( mParent->layout() )
87  mParent->layout()->invalidate();
88  else
89  QApplication::postEvent( mParent, new QEvent( QEvent::LayoutRequest ) );
90  }
91 }
92 
94  const KDChart::TextAttributes& attributes,
95  const QObject* area,
97  Qt::Alignment alignment )
98  : AbstractLayoutItem( alignment ),
99  m_text( new TextLayoutItem( text, attributes, area, orientation, alignment ) )
100 {
101 }
102 
104  : AbstractLayoutItem( Qt::AlignLeft ),
105  m_text( new TextLayoutItem() )
106 {
107 }
108 
110 {
111  delete m_text;
112 }
113 
115 {
116  m_text->setAutoReferenceArea( area );
117 }
118 
120 {
121  return m_text->autoReferenceArea();
122 }
123 
125 {
126  m_text->setText( text );
127 }
128 
130 {
131  return m_text->text();
132 }
133 
135 {
136  m_text->setTextAttributes( a );
137 }
138 
140 {
141  return m_text->textAttributes();
142 }
143 
145 {
146  return m_text->isEmpty();
147 }
148 
150 {
151  return m_text->expandingDirections();
152 }
153 
155 {
156  const int border = borderWidth();
157  return m_text->maximumSize() + QSize( 2 * border, 2 * border );
158 }
159 
161 {
162  const int border = borderWidth();
163  return m_text->minimumSize() + QSize( 2 * border, 2 * border );
164 }
165 
167 {
168  const int border = borderWidth();
169  return m_text->sizeHint() + QSize( 2 * border, 2 * border );
170 }
171 
173 {
174  const int border = borderWidth();
175  m_text->setGeometry( r.adjusted( border, border, -border, -border ) );
176 }
177 
179 {
180  const int border = borderWidth();
181  return m_text->geometry().adjusted( -border, -border, border, border );
182 }
183 
184 void KDChart::TextBubbleLayoutItem::paint( QPainter* painter )
185 {
186  const QPen oldPen = painter->pen();
187  const QBrush oldBrush = painter->brush();
188  painter->setPen( Qt::black );
189  painter->setBrush( QColor( 255, 255, 220 ) );
190  painter->drawRoundRect( geometry(), 10 );
191  painter->setPen( oldPen );
192  painter->setBrush( oldBrush );
193  m_text->paint( painter );
194 }
195 
197 {
198  return 1;
199 }
200 
202  const KDChart::TextAttributes& attributes,
203  const QObject* area,
205  Qt::Alignment alignment )
206  : AbstractLayoutItem( alignment )
207  , mText( text )
208  , mTextAlignment( alignment )
209  , mAttributes( attributes )
210  , mAutoReferenceArea( area )
211  , mAutoReferenceOrientation( orientation )
212  , cachedSizeHint() // default this to invalid to force just-in-time calculation before first use of sizeHint()
213  , cachedFontSize( 0.0 )
214  , cachedFont( mAttributes.font() )
215 {
216 }
217 
219  : AbstractLayoutItem( Qt::AlignLeft )
220  , mText()
221  , mTextAlignment( Qt::AlignLeft )
222  , mAttributes()
223  , mAutoReferenceArea( 0 )
224  , mAutoReferenceOrientation( KDChartEnums::MeasureOrientationHorizontal )
225  , cachedSizeHint() // default this to invalid to force just-in-time calculation before first use of sizeHint()
226  , cachedFontSize( 0.0 )
227  , cachedFont( mAttributes.font() )
228 {
229 
230 }
231 
233 {
234  mAutoReferenceArea = area;
235  cachedSizeHint = QSize();
236  sizeHint();
237 }
238 
240 {
241  return mAutoReferenceArea;
242 }
243 
245 {
246  mText = text;
247  cachedSizeHint = QSize();
248  sizeHint();
249  if ( mParent )
250  mParent->update();
251 }
252 
254 {
255  return mText;
256 }
257 
258 void KDChart::TextLayoutItem::setTextAlignment( Qt::Alignment alignment)
259 {
260  if ( mTextAlignment == alignment )
261  return;
262  mTextAlignment = alignment;
263  if ( mParent )
264  mParent->update();
265 }
266 
268 {
269  return mTextAlignment;
270 }
271 
278 {
279  mAttributes = a;
280  cachedFont = a.font();
281  cachedSizeHint = QSize(); // invalidate size hint
282  sizeHint();
283  if ( mParent )
284  mParent->update();
285 }
286 
293 {
294  return mAttributes;
295 }
296 
297 
299 {
300  return 0; // Grow neither vertically nor horizontally
301 }
302 
304 {
305  return mRect;
306 }
307 
309 {
310  return false; // never empty, otherwise the layout item would not exist
311 }
312 
314 {
315  return sizeHint(); // PENDING(kalle) Review, quite inflexible
316 }
317 
319 {
320  return sizeHint(); // PENDING(kalle) Review, quite inflexible
321 }
322 
324 {
325  mRect = r;
326 }
327 
328 // returns the bounding box of rect rotated around its center
329 QRectF rotatedRect( const QRectF& rect, qreal rotation )
330 {
331  QTransform t;
332  QPointF center = rect.center();
333  t.translate( center.x(), center.y() );
334  t.rotate( rotation );
335  t.translate( -center.x(), -center.y() );
336  return t.mapRect( rect );
337 }
338 
339 qreal KDChart::TextLayoutItem::fitFontSizeToGeometry() const
340 {
341  QFont f = realFont();
342  const qreal origResult = f.pointSizeF();
343  qreal result = origResult;
344  const qreal minSize = mAttributes.minimalFontSize().value();
345  const QSize mySize = geometry().size();
346  if ( mySize.isNull() ) {
347  return result;
348  }
349 
350  QFontMetrics fm( f );
351  while ( true ) {
352  const QSizeF textSize = rotatedRect( fm.boundingRect( mText ), mAttributes.rotation() ).normalized().size();
353 
354  if ( textSize.height() <= mySize.height() && textSize.width() <= mySize.width() ) {
355  return result;
356  }
357 
358  result -= 0.5;
359  if ( minSize > 0 && result < minSize ) {
360  return result + 0.5;
361  } else if ( result <= 0.0 ) {
362  return origResult;
363  }
364  f.setPointSizeF( result );
365  fm = QFontMetrics( f );
366  }
367 }
368 
370 {
371  return mAttributes.calculatedFontSize( mAutoReferenceArea, mAutoReferenceOrientation );
372 }
373 
374 bool KDChart::TextLayoutItem::maybeUpdateRealFont() const
375 {
376  const qreal fntSiz = realFontSize();
377  const bool doUpdate = !cachedSizeHint.isValid() || cachedFontSize != fntSiz;
378 
379  if ( doUpdate && fntSiz > 0.0 ) {
380  cachedFontSize = fntSiz;
381  cachedFont.setPointSizeF( fntSiz );
382  }
383  return doUpdate; // "didUpdate" by now
384 }
385 
387 {
388  maybeUpdateRealFont();
389  return cachedFont;
390 }
391 
393 {
394  // should probably call sizeHint() here, but that one is expensive (see TODO there)
395  return mCachedBoundingPolygon;
396 }
397 
398 bool KDChart::TextLayoutItem::intersects( const TextLayoutItem& other, const QPointF& myPos, const QPointF& otherPos ) const
399 {
400  return intersects( other, myPos.toPoint(), otherPos.toPoint() );
401 }
402 
403 bool KDChart::TextLayoutItem::intersects( const TextLayoutItem& other, const QPoint& myPos, const QPoint& otherPos ) const
404 {
405  QRegion myRegion( boundingPolygon().translated( myPos - otherPos ) );
406  QRegion otherRegion( other.boundingPolygon() );
407 
408  return myRegion.intersects( otherRegion );
409 }
410 
412 {
413  // ### we only really need to recalculate the size hint when mAttributes.rotation has *changed*
414  if ( maybeUpdateRealFont() || mAttributes.rotation() || !cachedSizeHint.isValid() ) {
415  const QSize newSizeHint( calcSizeHint( cachedFont ) );
416  Q_ASSERT( newSizeHint.isValid() );
417  if ( newSizeHint != cachedSizeHint ) {
418  cachedSizeHint = newSizeHint;
419  sizeHintChanged();
420  }
421  }
422  return cachedSizeHint;
423 }
424 
426 {
427  maybeUpdateRealFont(); // make sure the cached font is up to date
428  return unrotatedSizeHint( cachedFont );
429 }
430 
431 
432 // PENDING(kalle) Support auto shrink
433 
434 
435 QSize KDChart::TextLayoutItem::unrotatedTextSize( QFont fnt ) const
436 {
437  if ( fnt == QFont() ) {
438  fnt = realFont(); // this is the cached font in most cases
439  }
440 
441  const QFontMetricsF fm( fnt, GlobalMeasureScaling::paintDevice() );
442  QRect veryLarge( 0, 0, 100000, 100000 );
443  // this overload of boundingRect() interprets \n as line breaks, not as regular characters.
444  return fm.boundingRect( veryLarge, Qt::AlignLeft | Qt::AlignTop, mText ).size().toSize();
445 }
446 
448 {
449  return marginWidth( unrotatedTextSize() );
450 }
451 
452 int KDChart::TextLayoutItem::marginWidth( const QSize& textSize ) const
453 {
454  return qMin ( QApplication::style()->pixelMetric( QStyle::PM_ButtonMargin, 0, 0 ),
455  // decrease frame size if the text is small
456  textSize.height() * 2 / 3 );
457 }
458 
459 QSize KDChart::TextLayoutItem::unrotatedSizeHint( const QFont& fnt ) const
460 {
461  QSize ret = unrotatedTextSize( fnt );
462  const int margin = marginWidth( ret );
463  ret += QSize( margin, margin );
464  return ret;
465 }
466 
467 QSize KDChart::TextLayoutItem::calcSizeHint( const QFont& font ) const
468 {
469  const QSize size = unrotatedSizeHint( font );
470  QPoint topLeft( -size.width() * 0.5, -size.height() * 0.5 );
471  if ( !mAttributes.rotation() ) {
472  mCachedBoundingPolygon.resize( 4 );
473  // using the same winding order as returned by QPolygon QTransform::mapToPolygon(const QRect&),
474  // which is: 0-1: top edge, 1-2: right edge, 2-3: bottom edge, 3-0: left edge (of input rect)
475  mCachedBoundingPolygon[ 0 ] = topLeft;
476  mCachedBoundingPolygon[ 1 ] = topLeft + QPoint( size.width(), 0 ); // top right
477  mCachedBoundingPolygon[ 2 ] = topLeft + QPoint( size.width(), size.height() ); // bottom right
478  mCachedBoundingPolygon[ 3 ] = topLeft + QPoint( 0, size.height() ); // bottom left
479  return size;
480  }
481 
482  const QRect rect( topLeft, size );
483  QTransform t;
484  t.rotate( mAttributes.rotation() );
485  mCachedBoundingPolygon = t.mapToPolygon( rect );
486 
487  return mCachedBoundingPolygon.boundingRect().size();
488 }
489 
490 void KDChart::TextLayoutItem::paint( QPainter* painter )
491 {
492  if ( !mRect.isValid() ) {
493  return;
494  }
495  const PainterSaver painterSaver( painter );
496  QFont f = realFont();
497  if ( mAttributes.autoShrink() ) {
498  f.setPointSizeF( fitFontSizeToGeometry() );
499  }
500  painter->setFont( f );
501 
502  QSize innerSize = unrotatedTextSize();
503  QRectF rect = QRectF( QPointF( 0, 0 ), innerSize );
504  rect.translate( -rect.center() );
505  painter->translate( mRect.center() );
506  painter->rotate( mAttributes.rotation() );
507 #ifdef DEBUG_ITEMS_PAINT
508  painter->setPen( Qt::red );
509  painter->drawRect( rect );
510 #endif
511 
512  painter->setPen( PrintingParameters::scalePen( mAttributes.pen() ) );
513  QTextDocument* document = mAttributes.textDocument();
514  if ( document ) {
515  document->setPageSize( rect.size() );
516  document->setHtml( mText );
517  QAbstractTextDocumentLayout::PaintContext paintcontext;
518  // ### this doesn't work for rotated painting because clip does not translate the painting
519  // TODO translate the painting either using a QTransform or one of QPainter's transform stages
520  paintcontext.clip = rect;
521  document->documentLayout()->draw( painter, paintcontext );
522  } else {
523  painter->drawText( rect, mTextAlignment, mText );
524  }
525 }
526 
528  : AbstractLayoutItem( Qt::AlignCenter )
529 {
530 }
531 
533 {
534  return Qt::Horizontal;
535 }
536 
538 {
539  return mRect;
540 }
541 
543 {
544  return false; // never empty, otherwise the layout item would not exist
545 }
546 
548 {
549  return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
550 }
551 
553 {
554  return QSize( 0, 0 );
555 }
556 
558 {
559  mRect = r;
560 }
561 
563 {
564  return QSize( -1, 3 ); // see qframe.cpp
565 }
566 
567 
569 {
570  if ( !mRect.isValid() )
571  return;
572 
573  painter->drawLine( QPointF( mRect.left(), mRect.center().y() ),
574  QPointF( mRect.right(), mRect.center().y() ) );
575 }
576 
577 
579  : AbstractLayoutItem( Qt::AlignCenter )
580 {
581 }
582 
584 {
585  return Qt::Vertical;
586 }
587 
589 {
590  return mRect;
591 }
592 
594 {
595  return false; // never empty, otherwise the layout item would not exist
596 }
597 
599 {
600  return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
601 }
602 
604 {
605  return QSize( 0, 0 );
606 }
607 
609 {
610  mRect = r;
611 }
612 
614 {
615  return QSize( 3, -1 ); // see qframe.cpp
616 }
617 
618 
619 void KDChart::VerticalLineLayoutItem::paint( QPainter* painter )
620 {
621  if ( !mRect.isValid() )
622  return;
623 
624  painter->drawLine( QPointF( mRect.center().x(), mRect.top() ),
625  QPointF( mRect.center().x(), mRect.bottom() ) );
626 }
627 
628 
629 
631  const MarkerAttributes& marker,
632  const QBrush& brush, const QPen& pen,
633  Qt::Alignment alignment )
634  : AbstractLayoutItem( alignment )
635  , mDiagram( diagram )
636  , mMarker( marker )
637  , mBrush( brush )
638  , mPen( pen )
639 {
640 }
641 
643 {
644  return 0; // Grow neither vertically nor horizontally
645 }
646 
648 {
649  return mRect;
650 }
651 
653 {
654  return false; // never empty, otherwise the layout item would not exist
655 }
656 
658 {
659  return sizeHint(); // PENDING(kalle) Review, quite inflexible
660 }
661 
663 {
664  return sizeHint(); // PENDING(kalle) Review, quite inflexible
665 }
666 
668 {
669  mRect = r;
670 }
671 
673 {
674  //qDebug() << "KDChart::MarkerLayoutItem::sizeHint() returns:"<<mMarker.markerSize().toSize();
675  return mMarker.markerSize().toSize();
676 }
677 
678 void KDChart::MarkerLayoutItem::paint( QPainter* painter )
679 {
680  paintIntoRect( painter, mRect, mDiagram, mMarker, mBrush, mPen );
681 }
682 
684  QPainter* painter,
685  const QRect& rect,
686  AbstractDiagram* diagram,
687  const MarkerAttributes& marker,
688  const QBrush& brush,
689  const QPen& pen )
690 {
691  if ( !rect.isValid() )
692  return;
693 
694  // The layout management may assign a larger rect than what we
695  // wanted. We need to adjust the position.
696  const QSize siz = marker.markerSize().toSize();
697  QPointF pos = rect.topLeft();
698  pos += QPointF( static_cast<qreal>(( rect.width() - siz.width()) / 2.0 ),
699  static_cast<qreal>(( rect.height() - siz.height()) / 2.0 ) );
700 
701 #ifdef DEBUG_ITEMS_PAINT
702  QPointF oldPos = pos;
703 #endif
704 
705 // And finally, drawMarker() assumes the position to be the center
706  // of the marker, adjust again.
707  pos += QPointF( static_cast<qreal>( siz.width() ) / 2.0,
708  static_cast<qreal>( siz.height() )/ 2.0 );
709 
710  diagram->paintMarker( painter, marker, brush, pen, pos.toPoint(), siz );
711 
712 #ifdef DEBUG_ITEMS_PAINT
713  const QPen oldPen( painter->pen() );
714  painter->setPen( Qt::red );
715  painter->drawRect( QRect( oldPos.toPoint(), siz ) );
716  painter->setPen( oldPen );
717 #endif
718 }
719 
720 
722  int length,
723  const QPen& pen,
724  Qt::Alignment legendLineSymbolAlignment,
725  Qt::Alignment alignment )
726  : AbstractLayoutItem( alignment )
727  , mDiagram( diagram )
728  , mLength( length )
729  , mPen( pen )
730  , mLegendLineSymbolAlignment(legendLineSymbolAlignment)
731 {
732  // enforce a minimum pen width
733  if ( pen.width() < 2 )
734  mPen.setWidth( 2 );
735 }
736 
738 {
739  return 0; // Grow neither vertically nor horizontally
740 }
741 
743 {
744  return mRect;
745 }
746 
748 {
749  return false; // never empty, otherwise the layout item would not exist
750 }
751 
753 {
754  return sizeHint(); // PENDING(kalle) Review, quite inflexible
755 }
756 
758 {
759  return sizeHint(); // PENDING(kalle) Review, quite inflexible
760 }
761 
763 {
764  mRect = r;
765 }
766 
768 {
769  return QSize( mLength, mPen.width() + 2 );
770 }
771 
772 
774 {
775  if (mLegendLineSymbolAlignment == legendLineSymbolAlignment)
776  return;
777 
778  mLegendLineSymbolAlignment = legendLineSymbolAlignment;
779 }
780 
782 {
783  return mLegendLineSymbolAlignment;
784 }
785 
786 void KDChart::LineLayoutItem::paint( QPainter* painter )
787 {
788  paintIntoRect( painter, mRect, mPen, mLegendLineSymbolAlignment );
789 }
790 
792  QPainter* painter,
793  const QRect& rect,
794  const QPen& pen,
795  Qt::Alignment lineAlignment)
796 {
797  if ( ! rect.isValid() )
798  return;
799 
800  const QPen oldPen = painter->pen();
801  painter->setPen( PrintingParameters::scalePen( pen ) );
802  qreal y = 0;
803  if (lineAlignment == Qt::AlignTop)
804  y = rect.top();
805  else if (lineAlignment == Qt::AlignBottom)
806  y = rect.bottom();
807  else
808  y = rect.center().y();
809 
810  painter->drawLine( QPointF( rect.left(), y ),
811  QPointF( rect.right(), y ) );
812  painter->setPen( oldPen );
813 }
814 
815 
817  KDChart::AbstractDiagram* diagram,
818  int lineLength,
819  const QPen& linePen,
820  int markerOffs,
821  const MarkerAttributes& marker,
822  const QBrush& markerBrush,
823  const QPen& markerPen,
824  Qt::Alignment alignment )
825  : AbstractLayoutItem( alignment )
826  , mDiagram( diagram )
827  , mLineLength( lineLength )
828  , mLinePen( linePen )
829  , mMarkerOffs( markerOffs )
830  , mMarker( marker )
831  , mMarkerBrush( markerBrush )
832  , mMarkerPen( markerPen )
833 {
834 }
835 
837 {
838  return 0; // Grow neither vertically nor horizontally
839 }
840 
842 {
843  return mRect;
844 }
845 
847 {
848  return false; // never empty, otherwise the layout item would not exist
849 }
850 
852 {
853  return sizeHint(); // PENDING(kalle) Review, quite inflexible
854 }
855 
857 {
858  return sizeHint(); // PENDING(kalle) Review, quite inflexible
859 }
860 
862 {
863  mRect = r;
864 }
865 
867 {
868  const QSize lineSize( mLineLength, mLinePen.width() + 2 );
869  return lineSize.expandedTo( mMarker.markerSize().toSize() );
870 }
871 
873 {
874  // paint the line over the full width, into the vertical middle of the rect
875  LineLayoutItem::paintIntoRect( painter, mRect, mLinePen, Qt::AlignCenter );
876 
877  // paint the marker with the given offset from the left side of the line
878  const QRect r(
879  QPoint( mRect.x()+mMarkerOffs, mRect.y() ),
880  QSize( mMarker.markerSize().toSize().width(), mRect.height() ) );
882  painter, r, mDiagram, mMarker, mMarkerBrush, mMarkerPen );
883 }
884 
886  bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout,
887  bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout )
888  : AbstractLayoutItem( Qt::AlignCenter )
889  , mLayoutIsAtTopPosition( layoutIsAtTopPosition )
890  , mRightLeftLayout( rightLeftLayout )
891  , mLayoutIsAtLeftPosition( layoutIsAtLeftPosition )
892  , mTopBottomLayout( topBottomLayout )
893 {
894 }
895 
897 {
898  return 0; // Grow neither vertically nor horizontally
899 }
900 
902 {
903  return mRect;
904 }
905 
907 {
908  return true; // never empty, otherwise the layout item would not exist
909 }
910 
912 {
913  return sizeHint();
914 }
915 
917 {
918  return sizeHint();
919 }
920 
922 {
923  mRect = r;
924 }
925 
926 
927 static void updateCommonBrush( QBrush& commonBrush, bool& bStart, const KDChart::AbstractArea& area )
928 {
930  const bool hasSimpleBrush = (
931  ! area.frameAttributes().isVisible() &&
932  ba.isVisible() &&
934  ba.brush().gradient() == 0 );
935  if ( bStart ) {
936  bStart = false;
937  commonBrush = hasSimpleBrush ? ba.brush() : QBrush();
938  } else {
939  if ( ! hasSimpleBrush || ba.brush() != commonBrush )
940  {
941  commonBrush = QBrush();
942  }
943  }
944 }
945 
947 {
948  QBrush commonBrush;
949  bool bStart=true;
950  // calculate the maximal overlap of the top/bottom axes:
951  int topBottomOverlap = 0;
952  if ( mTopBottomLayout ) {
953  for (int i = 0; i < mTopBottomLayout->count(); ++i) {
954  AbstractArea* area = dynamic_cast<AbstractArea*>(mTopBottomLayout->itemAt(i));
955  if ( area ) {
956  //qDebug() << "AutoSpacerLayoutItem testing" << area;
957  topBottomOverlap = qMax( topBottomOverlap,
958  mLayoutIsAtLeftPosition ? area->rightOverlap()
959  : area->leftOverlap() );
960  updateCommonBrush( commonBrush, bStart, *area );
961  }
962  }
963  }
964  // calculate the maximal overlap of the left/right axes:
965  int leftRightOverlap = 0;
966  if ( mRightLeftLayout ) {
967  for (int i = 0; i < mRightLeftLayout->count(); ++i) {
968  AbstractArea* area = dynamic_cast<AbstractArea*>(mRightLeftLayout->itemAt(i));
969  if ( area ) {
970  //qDebug() << "AutoSpacerLayoutItem testing" << area;
971  leftRightOverlap = qMax( leftRightOverlap,
972  mLayoutIsAtTopPosition ? area->bottomOverlap()
973  : area->topOverlap() );
974  updateCommonBrush( commonBrush, bStart, *area );
975  }
976  }
977  }
978  if ( topBottomOverlap > 0 && leftRightOverlap > 0 )
979  mCommonBrush = commonBrush;
980  else
981  mCommonBrush = QBrush();
982  mCachedSize = QSize( topBottomOverlap, leftRightOverlap );
983  //qDebug() << mCachedSize;
984  return mCachedSize;
985 }
986 
987 
988 void KDChart::AutoSpacerLayoutItem::paint( QPainter* painter )
989 {
990  if ( mParentLayout && mRect.isValid() && mCachedSize.isValid() &&
991  mCommonBrush.style() != Qt::NoBrush )
992  {
993  QPoint p1( mRect.topLeft() );
994  QPoint p2( mRect.bottomRight() );
995  if ( mLayoutIsAtLeftPosition )
996  p1.rx() += mCachedSize.width() - mParentLayout->spacing();
997  else
998  p2.rx() -= mCachedSize.width() - mParentLayout->spacing();
999  if ( mLayoutIsAtTopPosition ) {
1000  p1.ry() += mCachedSize.height() - mParentLayout->spacing() - 1;
1001  p2.ry() -= 1;
1002  } else
1003  p2.ry() -= mCachedSize.height() - mParentLayout->spacing() - 1;
1004  //qDebug() << mLayoutIsAtTopPosition << mLayoutIsAtLeftPosition;
1005  //qDebug() << mRect;
1006  //qDebug() << mParentLayout->margin();
1007  //qDebug() << QRect( p1, p2 );
1008  const QPoint oldBrushOrigin( painter->brushOrigin() );
1009  const QBrush oldBrush( painter->brush() );
1010  const QPen oldPen( painter->pen() );
1011  const QPointF newTopLeft( painter->deviceMatrix().map( p1 ) );
1012  painter->setBrushOrigin( newTopLeft );
1013  painter->setBrush( mCommonBrush );
1014  painter->setPen( Qt::NoPen );
1015  painter->drawRect( QRect( p1, p2 ) );
1016  painter->setBrushOrigin( oldBrushOrigin );
1017  painter->setBrush( oldBrush );
1018  painter->setPen( oldPen );
1019  }
1020  // debug code:
1021 #if 0
1022  //qDebug() << "KDChart::AutoSpacerLayoutItem::paint()";
1023  if ( !mRect.isValid() )
1024  return;
1025 
1026  painter->drawRect( mRect );
1027  painter->drawLine( QPointF( mRect.topLeft(), mRect.bottomRight() ) );
1028  painter->drawLine( QPointF( mRect.topRight(), mRect.bottomLeft() ) );
1029 #endif
1030 }
MeasureOrientation
Measure orientation mode: the way how the absolute value of a KDChart::Measure is determined during K...
Definition: KDChartEnums.h:290
bool isEmpty() const override
Qt::Orientations expandingDirections() const override
pure virtual in QLayoutItem
Project global class providing some enums needed both by KDChartParams and by KDChartCustomBox.
Definition: KDChartEnums.h:40
LineLayoutItem(AbstractDiagram *diagram, int length, const QPen &pen, Qt::Alignment mLegendLineSymbolAlignment, Qt::Alignment alignment=0)
void setGeometry(const QRect &r) override
QSize minimumSize() const override
QSize maximumSize() const override
void setLegendLineSymbolAlignment(Qt::Alignment legendLineSymbolAlignment)
An area in the chart with a background, a frame, etc.
void setGeometry(const QRect &r) override
Qt::Orientations expandingDirections() const override
BackgroundAttributes backgroundAttributes() const
void setGeometry(const QRect &r) override
pure virtual in QLayoutItem
void setAutoReferenceArea(const QObject *area)
void setTextAlignment(Qt::Alignment)
QTextDocument * textDocument() const
QSize minimumSize() const override
QPainter * painter() const
void paint(QPainter *) override
QSize maximumSize() const override
LineWithMarkerLayoutItem(AbstractDiagram *diagram, int lineLength, const QPen &linePen, int markerOffs, const MarkerAttributes &marker, const QBrush &markerBrush, const QPen &markerPen, Qt::Alignment alignment=0)
Qt::Orientations expandingDirections() const override
Layout item showing a text.
TextAttributes textAttributes() const
Returns the text attributes to be used for this item.
QSize sizeHint() const override
pure virtual in QLayoutItem
virtual void setParentWidget(QWidget *widget)
Inform the item about its widget: This enables the item, to trigger that widget&#39;s update...
QSize maximumSize() const override
virtual int leftOverlap(bool doNotRecalculate=false) const
This is called at layout time by KDChart::AutoSpacerLayoutItem::sizeHint().
Qt::Orientations expandingDirections() const override
pure virtual in QLayoutItem
void paint(QPainter *) override
const QObject * autoReferenceArea() const
virtual QSize sizeHintUnrotated() const
QSize minimumSize() const override
pure virtual in QLayoutItem
Qt::Orientations expandingDirections() const override
AutoSpacerLayoutItem(bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout, bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout)
static QPaintDevice * paintDevice()
Return the paint device to use for calculating font metrics.
virtual int bottomOverlap(bool doNotRecalculate=false) const
This is called at layout time by KDChart:AutoSpacerLayoutItem::sizeHint().
QSize sizeHint() const override
QSize sizeHint() const override
pure virtual in QLayoutItem
QRect geometry() const override
QRectF rotatedRect(const QRectF &rect, qreal rotation)
virtual bool intersects(const TextLayoutItem &other, const QPointF &myPos, const QPointF &otherPos) const
AbstractDiagram defines the interface for diagram classes.
void setText(const QString &text)
Qt::Alignment textAlignment() const
void paint(QPainter *painter) override
QSize maximumSize() const override
pure virtual in QLayoutItem
void setAutoReferenceArea(const QObject *area)
virtual void paintMarker(QPainter *painter, const MarkerAttributes &markerAttributes, const QBrush &brush, const QPen &, const QPointF &point, const QSizeF &size)
virtual int rightOverlap(bool doNotRecalculate=false) const
This is called at layout time by KDChart::AutoSpacerLayoutItem::sizeHint().
virtual Qt::Alignment legendLineSymbolAlignment() const
void setGeometry(const QRect &r) override
virtual void paintAll(QPainter &painter)
Default impl: just call paint.
void setGeometry(const QRect &r) override
pure virtual in QLayoutItem
virtual QFont realFont() const
QRect geometry() const override
static void paintIntoRect(QPainter *painter, const QRect &rect, const QPen &pen, Qt::Alignment lineAlignment)
Base class for all layout items of KD Chart.
const QObject * autoReferenceArea() const
virtual void paint(QPainter *)=0
void setTextAttributes(const TextAttributes &a)
Use this to specify the text attributes to be used for this item.
void setGeometry(const QRect &r) override
static void updateCommonBrush(QBrush &commonBrush, bool &bStart, const KDChart::AbstractArea &area)
static void paintIntoRect(QPainter *painter, const QRect &rect, AbstractDiagram *diagram, const MarkerAttributes &marker, const QBrush &brush, const QPen &pen)
virtual qreal realFontSize() const
Stores information about painting diagrams.
QSize minimumSize() const override
MarkerLayoutItem(AbstractDiagram *diagram, const MarkerAttributes &marker, const QBrush &brush, const QPen &pen, Qt::Alignment alignment=0)
Class only listed here to document inheritance of some KDChart classes.
void paint(QPainter *) override
virtual int topOverlap(bool doNotRecalculate=false) const
This is called at layout time by KDChart::AutoSpacerLayoutItem::sizeHint().
virtual void sizeHintChanged() const
Report changed size hint: ask the parent widget to recalculate the layout.
void paint(QPainter *) override
A set of attributes controlling the appearance of data set markers.
void setText(const QString &text)
void setGeometry(const QRect &r) override
QSize minimumSize() const override
pure virtual in QLayoutItem
virtual int marginWidth() const
QSize maximumSize() const override
pure virtual in QLayoutItem
QRect geometry() const override
pure virtual in QLayoutItem
bool isEmpty() const override
Class only listed here to document inheritance of some KDChart classes.
static QPen scalePen(const QPen &pen)
Qt::Orientations expandingDirections() const override
TextAttributes textAttributes() const
bool isEmpty() const override
pure virtual in QLayoutItem
void setTextAttributes(const TextAttributes &a)
void paint(QPainter *) override
Class only listed here to document inheritance of some KDChart classes.
Qt::Orientations expandingDirections() const override
FrameAttributes frameAttributes() const
qreal calculatedFontSize(const QSizeF &referenceSize, KDChartEnums::MeasureOrientation autoReferenceOrientation) const
Returns the font size that is used at drawing time.
qreal value() const
bool isEmpty() const override
pure virtual in QLayoutItem
virtual void paintCtx(PaintContext *context)
Default impl: Paint the complete item using its layouted position and size.
QRect geometry() const override
pure virtual in QLayoutItem
void setGeometry(const QRect &r) override
QPolygon boundingPolygon() const
A set of text attributes.
QSize sizeHint() const override
Set of attributes usable for background pixmaps.
Qt::Orientations expandingDirections() const override

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/