24 #include "KDChartAbstractDiagram_p.h"
28 #include <QApplication>
29 #include <QAbstractProxyModel>
39 #include "KDChartPainterSaver_p.h"
41 #include <KDABLibFakes>
62 void AbstractDiagram::init()
65 d->reverseMapper.setDiagram(
this );
71 if ( other ==
this )
return true;
76 (horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) &&
77 (verticalScrollBarPolicy() == other->verticalScrollBarPolicy()) &&
79 (frameShadow() == other->frameShadow()) &&
80 (frameShape() == other->frameShape()) &&
83 (lineWidth() == other->lineWidth()) &&
84 (midLineWidth() == other->midLineWidth()) &&
86 (alternatingRowColors() == other->alternatingRowColors()) &&
87 (hasAutoScroll() == other->hasAutoScroll()) &&
88 #
if QT_VERSION > 0x040199
89 (dragDropMode() == other->dragDropMode()) &&
90 (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
91 (horizontalScrollMode() == other->horizontalScrollMode ()) &&
92 (verticalScrollMode() == other->verticalScrollMode()) &&
94 (dragEnabled() == other->dragEnabled()) &&
95 (editTriggers() == other->editTriggers()) &&
96 (iconSize() == other->iconSize()) &&
97 (selectionBehavior() == other->selectionBehavior()) &&
98 (selectionMode() == other->selectionMode()) &&
99 (showDropIndicator() == other->showDropIndicator()) &&
100 (tabKeyNavigation() == other->tabKeyNavigation()) &&
101 (textElideMode() == other->textElideMode()) &&
105 (rootIndex().column() == other->rootIndex().column()) &&
106 (rootIndex().row() == other->rootIndex().row()) &&
120 if (
d->databoundariesDirty ) {
122 d->databoundariesDirty =
false;
124 return d->databoundaries;
129 d->databoundariesDirty =
true;
135 if ( newModel == model() ) {
141 d->setAttributesModel(amodel);
143 QAbstractItemView::setModel( newModel );
145 scheduleDelayedItemsLayout();
152 if ( selectionModel() )
154 disconnect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SIGNAL(
modelsChanged() ) );
155 disconnect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SIGNAL(
modelsChanged() ) );
157 QAbstractItemView::setSelectionModel( newSelectionModel );
158 if ( selectionModel() )
160 connect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SIGNAL(
modelsChanged() ) );
161 connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SIGNAL(
modelsChanged() ) );
175 if ( amodel->sourceModel() != model() ) {
176 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
177 "Trying to set an attributesmodel which works on a different "
178 "model than the diagram.");
181 if ( qobject_cast<PrivateAttributesModel*>(amodel) ) {
182 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
183 "Trying to set an attributesmodel that is private to another diagram.");
187 d->setAttributesModel( amodel );
188 scheduleDelayedItemsLayout();
195 return d->usesExternalAttributesModel();
200 return d->attributesModel;
203 QModelIndex AbstractDiagram::conditionallyMapFromSource(
const QModelIndex & index )
const
212 QAbstractItemView::setRootIndex( idx );
219 d->attributesModelRootIndex = idx;
221 scheduleDelayedItemsLayout();
228 if ( !
d->attributesModelRootIndex.isValid() )
229 d->attributesModelRootIndex =
d->attributesModel->mapFromSource( rootIndex() );
230 return d->attributesModelRootIndex;
241 d->plane->layoutDiagrams();
244 QAbstractItemView::doItemsLayout();
247 #if QT_VERSION < 0x050000
249 const QModelIndex &bottomRight )
252 const QModelIndex &bottomRight,
257 Q_UNUSED( bottomRight );
259 setDataBoundariesDirty();
260 scheduleDelayedItemsLayout();
266 d->attributesModel->setData(
267 conditionallyMapFromSource( index ),
268 qVariantFromValue( hidden ),
275 d->setDatasetAttrs( dataset, qVariantFromValue( hidden ),
DataHiddenRole );
281 d->attributesModel->setModelData( qVariantFromValue( hidden ),
DataHiddenRole );
293 if ( boolFlag.isValid() )
294 return boolFlag.value<
bool >();
300 const QVariant boolFlag(
attributesModel()->data( conditionallyMapFromSource( index ),
302 if ( boolFlag.isValid() ) {
303 return boolFlag.value<
bool >();
305 int dataset = index.column() /
d->datasetDimension;
313 d->attributesModel->setData( conditionallyMapFromSource( index ), qVariantFromValue( a ),
343 const QVariant headerAttrs(
345 if ( headerAttrs.isValid() )
353 conditionallyMapFromSource( index ),
368 d->allowOverlappingDataValueTexts = allow;
374 return d->allowOverlappingDataValueTexts;
379 d->antiAliasing = enabled;
385 return d->antiAliasing;
390 d->percent = percent;
401 const QModelIndex& index,
405 d->paintDataValueText( painter, index, pos, value );
415 d->forgetAlreadyPaintedDataValues();
416 const int rowCount = model()->rowCount( rootIndex() );
417 const int columnCount = model()->columnCount( rootIndex() );
418 for (
int column = 0; column < columnCount; column +=
datasetDimension() ) {
419 for (
int row = 0; row < rowCount; ++row ) {
420 QModelIndex index = model()->index( row, column, rootIndex() );
425 y = index.data().toReal();
427 x = index.data().toReal();
428 y = model()->index( row, column + 1, rootIndex() ).data().toReal();
438 const QModelIndex& index,
445 const PainterSaver painterSaver( painter );
447 const QSizeF maSize( ma.
markerSize().width() / painter->matrix().m11(),
448 ma.
markerSize().height() / painter->matrix().m22() );
449 QBrush indexBrush(
brush( index ) );
450 QPen indexPen( ma.
pen() );
454 paintMarker( painter, ma, indexBrush, indexPen, pos, maSize );
461 d->reverseMapper.addCircle( index.row(), index.column(), pos, 2 * maSize );
465 const QModelIndex& index,
477 const QSizeF& maSize )
479 const QPen oldPen( painter->pen() );
486 if ( isFourPixels ) {
487 const qreal x = pos.x();
488 const qreal y = pos.y();
489 painter->drawLine( QPointF(x-1.0,y-1.0),
490 QPointF(x+1.0,y-1.0) );
491 painter->drawLine( QPointF(x-1.0,y),
493 painter->drawLine( QPointF(x-1.0,y+1.0),
494 QPointF(x+1.0,y+1.0) );
496 painter->drawPoint( pos );
498 const PainterSaver painterSaver( painter );
499 QPen painterPen(
pen );
501 painter->setBrush(
brush );
502 painter->setRenderHint ( QPainter::Antialiasing );
503 painter->translate( pos );
507 if ( markerAttributes.
threeD() ) {
508 QRadialGradient grad;
509 grad.setCoordinateMode( QGradient::ObjectBoundingMode );
510 QColor drawColor =
brush.color();
511 grad.setCenter( 0.5, 0.5 );
512 grad.setRadius( 1.0 );
513 grad.setFocalPoint( 0.35, 0.35 );
514 grad.setColorAt( 0.00, drawColor.lighter( 150 ) );
515 grad.setColorAt( 0.20, drawColor );
516 grad.setColorAt( 0.50, drawColor.darker( 150 ) );
517 grad.setColorAt( 0.75, drawColor.darker( 200 ) );
518 grad.setColorAt( 0.95, drawColor.darker( 250 ) );
519 grad.setColorAt( 1.00, drawColor.darker( 200 ) );
520 QBrush newBrush( grad );
521 newBrush.setMatrix(
brush.matrix() );
522 painter->setBrush( newBrush );
524 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
525 maSize.height(), maSize.width()) );
530 QRectF rect( 0 - maSize.width()/2, 0 - maSize.height()/2,
531 maSize.width(), maSize.height() );
532 painter->drawRect( rect );
538 QPointF top, left, bottom, right;
539 top = QPointF( 0, 0 - maSize.height()/2 );
540 left = QPointF( 0 - maSize.width()/2, 0 );
541 bottom = QPointF( 0, maSize.height()/2 );
542 right = QPointF( maSize.width()/2, 0 );
543 diamondPoints << top << left << bottom << right;
544 painter->drawPolygon( diamondPoints );
553 painter->setBrush( Qt::NoBrush );
555 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
556 maSize.height(), maSize.width()) );
563 const qreal w02 = maSize.width() * 0.2;
564 const qreal w05 = maSize.width() * 0.5;
565 const qreal h02 = maSize.height()* 0.2;
566 const qreal h05 = maSize.height()* 0.5;
569 p[ 0] = QPointF( -w02, -h05 );
570 p[ 1] = QPointF( w02, -h05 );
571 p[ 2] = QPointF( w02, -h02 );
572 p[ 3] = QPointF( w05, -h02 );
573 p[ 4] = QPointF( w05, h02 );
574 p[ 5] = QPointF( w02, h02 );
575 p[ 6] = QPointF( w02, h05 );
576 p[ 7] = QPointF( -w02, h05 );
577 p[ 8] = QPointF( -w02, h02 );
578 p[ 9] = QPointF( -w05, h02 );
579 p[10] = QPointF( -w05, -h02 );
580 p[11] = QPointF( -w02, -h02 );
581 for (
int i=0; i<12; ++i )
584 painter->drawPolygon( crossPoints );
589 QPointF left, right, top, bottom;
590 left = QPointF( -maSize.width()/2, 0 );
591 right = QPointF( maSize.width()/2, 0 );
592 top = QPointF( 0, -maSize.height()/2 );
593 bottom= QPointF( 0, maSize.height()/2 );
595 painter->drawLine( left, right );
596 painter->drawLine( top, bottom );
604 const QRectF pathBoundingRect = path.boundingRect();
605 const qreal xScaling = maSize.height() / pathBoundingRect.height();
606 const qreal yScaling = maSize.width() / pathBoundingRect.width();
607 const qreal scaling = qMin( xScaling, yScaling );
608 painter->scale( scaling, scaling );
610 painter->drawPath(path);
614 Q_ASSERT_X (
false,
"paintMarkers()",
615 "Type item does not match a defined Marker Type." );
618 painter->setPen( oldPen );
627 const int rowCount = model()->rowCount( rootIndex() );
628 const int columnCount = model()->columnCount( rootIndex() );
629 for (
int column = 0; column < columnCount; column +=
datasetDimension() ) {
630 for (
int row = 0; row < rowCount; ++row ) {
631 QModelIndex index = model()->index( row, column, rootIndex() );
636 y = index.data().toReal();
638 x = index.data().toReal();
639 y = model()->index( row, column + 1, rootIndex() ).data().toReal();
650 conditionallyMapFromSource( index ),
675 const QVariant penSettings(
d->datasetAttrs( dataset,
DatasetPenRole ) );
676 if ( penSettings.isValid() )
677 return penSettings.value< QPen >();
684 conditionallyMapFromSource( index ),
691 conditionallyMapFromSource( index ),
717 if ( brushSettings.isValid() )
718 return brushSettings.value< QBrush >();
736 d->unitPrefixMap[ column ][ orientation ]= prefix;
746 d->unitPrefix[ orientation ] = prefix;
757 d->unitSuffixMap[ column ][ orientation ]= suffix;
767 d->unitSuffix[ orientation ] = suffix;
779 if ( !fallback ||
d->unitPrefixMap[ column ].contains( orientation ) )
780 return d->unitPrefixMap[ column ][ orientation ];
781 return d->unitPrefix[ orientation ];
790 return d->unitPrefix[ orientation ];
802 if ( !fallback ||
d->unitSuffixMap[ column ].contains( orientation ) )
803 return d->unitSuffixMap[ column ][ orientation ];
804 return d->unitSuffix[ orientation ];
813 return d->unitSuffix[ orientation ];
819 return d->reverseMapper.boundingRect( index.row(), index.column() ).toRect();
828 {
return QModelIndex(); }
841 const QModelIndexList indexes =
d->indexesIn( rect );
842 QItemSelection selection;
843 KDAB_FOREACH(
const QModelIndex& index, indexes )
845 selection.append( QItemSelectionRange( index ) );
847 selectionModel()->select( selection, command );
853 KDAB_FOREACH(
const QModelIndex& index, selection.indexes() )
855 polygon <<
d->reverseMapper.polygon(index.row(), index.column());
857 return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
862 QPolygonF polygon =
d->reverseMapper.polygon(index.row(), index.column());
863 return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
887 for (
int i = 0; i < rowCount; ++i ) {
889 ret <<
unitPrefix( i, Qt::Horizontal,
true ) +
903 const int datasetCount =
d->datasetCount();
904 for (
int i = 0; i < datasetCount; ++i ) {
905 ret <<
d->datasetAttrs( i, Qt::DisplayRole ).toString();
916 const int datasetCount =
d->datasetCount();
917 for (
int i = 0; i < datasetCount; ++i ) {
929 const int datasetCount =
d->datasetCount();
930 for (
int i = 0; i < datasetCount; ++i ) {
942 const int datasetCount =
d->datasetCount();
943 for (
int i = 0; i < datasetCount; ++i ) {
951 if ( ! justReturnTheStatus ) {
952 Q_ASSERT_X ( model(),
"AbstractDiagram::checkInvariants()",
953 "There is no usable model set, for the diagram." );
956 "There is no usable coordinate plane set, for the diagram." );
963 return d->datasetDimension;
968 Q_UNUSED( dimension );
969 qDebug() <<
"Setting the dataset dimension using AbstractDiagram::setDatasetDimension is "
970 "obsolete. Use the specific diagram types instead.";
975 Q_ASSERT( dimension != 0 );
976 if (
d->datasetDimension == dimension ) {
979 d->datasetDimension = dimension;
980 d->attributesModel->setDatasetDimension( dimension );
988 qWarning() <<
"AbstractDiagram::valueForCell(): Requesting value for invalid index!";
989 return std::numeric_limits<qreal>::quiet_NaN();
991 return d->attributesModel->data(
1004 return d->indexAt( point );
1009 return d->indexesAt( point );
1014 return d->indexesIn( rect );