KD Chart 2  [rev.2.6]
KDChartLayoutItems.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2018 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
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)
virtual void setGeometry(const QRect &r)
pure virtual in QLayoutItem
void setLegendLineSymbolAlignment(Qt::Alignment legendLineSymbolAlignment)
An area in the chart with a background, a frame, etc.
virtual Qt::Orientations expandingDirections() const
BackgroundAttributes backgroundAttributes() const
void setAutoReferenceArea(const QObject *area)
virtual void paint(QPainter *painter)
virtual Qt::Orientations expandingDirections() const
void setTextAlignment(Qt::Alignment)
QTextDocument * textDocument() const
QPainter * painter() const
virtual void setGeometry(const QRect &r)
pure virtual in QLayoutItem
LineWithMarkerLayoutItem(AbstractDiagram *diagram, int lineLength, const QPen &linePen, int markerOffs, const MarkerAttributes &marker, const QBrush &markerBrush, const QPen &markerPen, Qt::Alignment alignment=0)
Layout item showing a text.
TextAttributes textAttributes() const
Returns the text attributes to be used for this item.
virtual Qt::Orientations expandingDirections() const
pure virtual in QLayoutItem
virtual void paint(QPainter *)
virtual bool isEmpty() const
virtual void setParentWidget(QWidget *widget)
Inform the item about its widget: This enables the item, to trigger that widget&#39;s update...
virtual int leftOverlap(bool doNotRecalculate=false) const
This is called at layout time by KDChart::AutoSpacerLayoutItem::sizeHint().
virtual void setGeometry(const QRect &r)
const QObject * autoReferenceArea() const
virtual QSize sizeHintUnrotated() const
virtual void setGeometry(const QRect &r)
virtual Qt::Orientations expandingDirections() const
AutoSpacerLayoutItem(bool layoutIsAtTopPosition, QHBoxLayout *rightLeftLayout, bool layoutIsAtLeftPosition, QVBoxLayout *topBottomLayout)
virtual bool isEmpty() const
pure virtual in QLayoutItem
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().
virtual void setGeometry(const QRect &r)
virtual QSize sizeHint() const
pure virtual in QLayoutItem
virtual QSize maximumSize() const
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)
virtual QSize sizeHint() const
virtual QSize maximumSize() const
Qt::Alignment textAlignment() const
virtual QSize minimumSize() const
pure virtual in QLayoutItem
virtual QSize maximumSize() const
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 QSize maximumSize() const
pure virtual in QLayoutItem
virtual bool isEmpty() const
pure virtual in QLayoutItem
virtual int rightOverlap(bool doNotRecalculate=false) const
This is called at layout time by KDChart::AutoSpacerLayoutItem::sizeHint().
virtual Qt::Alignment legendLineSymbolAlignment() const
virtual void paintAll(QPainter &painter)
Default impl: just call paint.
virtual QSize minimumSize() const
pure virtual in QLayoutItem
virtual void paint(QPainter *)
virtual QFont realFont() const
virtual void paint(QPainter *)
static void paintIntoRect(QPainter *painter, const QRect &rect, const QPen &pen, Qt::Alignment lineAlignment)
virtual void setGeometry(const QRect &r)
Base class for all layout items of KD Chart.
virtual Qt::Orientations expandingDirections() const
const QObject * autoReferenceArea() const
virtual QSize minimumSize() const
virtual QRect geometry() const
pure virtual in QLayoutItem
virtual void paint(QPainter *)=0
void setTextAttributes(const TextAttributes &a)
Use this to specify the text attributes to be used for this item.
virtual void setGeometry(const QRect &r)
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.
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.
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.
A set of attributes controlling the appearance of data set markers.
void setText(const QString &text)
virtual QSize sizeHint() const
virtual int marginWidth() const
virtual QSize maximumSize() const
Class only listed here to document inheritance of some KDChart classes.
virtual Qt::Orientations expandingDirections() const
static QPen scalePen(const QPen &pen)
TextAttributes textAttributes() const
virtual QSize sizeHint() const
pure virtual in QLayoutItem
virtual void paint(QPainter *)
virtual bool isEmpty() const
void setTextAttributes(const TextAttributes &a)
virtual QSize minimumSize() const
Class only listed here to document inheritance of some KDChart classes.
virtual QSize minimumSize() const
virtual void setGeometry(const QRect &r)
virtual Qt::Orientations expandingDirections() const
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
virtual Qt::Orientations expandingDirections() const
pure virtual in QLayoutItem
virtual void paintCtx(PaintContext *context)
Default impl: Paint the complete item using its layouted position and size.
virtual QRect geometry() const
pure virtual in QLayoutItem
QPolygon boundingPolygon() const
virtual QRect geometry() const
A set of text attributes.
Set of attributes usable for background pixmaps.
virtual QRect geometry() const

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/