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 (dragDropMode() == other->dragDropMode()) &&
89 (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
90 (horizontalScrollMode() == other->horizontalScrollMode ()) &&
91 (verticalScrollMode() == other->verticalScrollMode()) &&
92 (dragEnabled() == other->dragEnabled()) &&
93 (editTriggers() == other->editTriggers()) &&
94 (iconSize() == other->iconSize()) &&
95 (selectionBehavior() == other->selectionBehavior()) &&
96 (selectionMode() == other->selectionMode()) &&
97 (showDropIndicator() == other->showDropIndicator()) &&
98 (tabKeyNavigation() == other->tabKeyNavigation()) &&
99 (textElideMode() == other->textElideMode()) &&
103 (rootIndex().column() == other->rootIndex().column()) &&
104 (rootIndex().row() == other->rootIndex().row()) &&
118 if (
d->databoundariesDirty ) {
120 d->databoundariesDirty =
false;
122 return d->databoundaries;
127 d->databoundariesDirty =
true;
133 if ( newModel == model() ) {
139 d->setAttributesModel(amodel);
141 QAbstractItemView::setModel( newModel );
143 scheduleDelayedItemsLayout();
150 if ( selectionModel() )
152 disconnect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SIGNAL(
modelsChanged() ) );
153 disconnect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SIGNAL(
modelsChanged() ) );
155 QAbstractItemView::setSelectionModel( newSelectionModel );
156 if ( selectionModel() )
158 connect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SIGNAL(
modelsChanged() ) );
159 connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SIGNAL(
modelsChanged() ) );
173 if ( amodel->sourceModel() != model() ) {
174 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
175 "Trying to set an attributesmodel which works on a different "
176 "model than the diagram.");
179 if ( qobject_cast<PrivateAttributesModel*>(amodel) ) {
180 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
181 "Trying to set an attributesmodel that is private to another diagram.");
185 d->setAttributesModel( amodel );
186 scheduleDelayedItemsLayout();
193 return d->usesExternalAttributesModel();
198 return d->attributesModel;
201 QModelIndex AbstractDiagram::conditionallyMapFromSource(
const QModelIndex & index )
const
210 QAbstractItemView::setRootIndex( idx );
217 d->attributesModelRootIndex = idx;
219 scheduleDelayedItemsLayout();
226 if ( !
d->attributesModelRootIndex.isValid() )
227 d->attributesModelRootIndex =
d->attributesModel->mapFromSource( rootIndex() );
228 return d->attributesModelRootIndex;
239 d->plane->layoutDiagrams();
242 QAbstractItemView::doItemsLayout();
246 const QModelIndex &bottomRight,
250 Q_UNUSED( bottomRight );
253 scheduleDelayedItemsLayout();
259 d->attributesModel->setData(
260 conditionallyMapFromSource( index ),
261 qVariantFromValue( hidden ),
268 d->setDatasetAttrs( dataset, qVariantFromValue( hidden ),
DataHiddenRole );
274 d->attributesModel->setModelData( qVariantFromValue( hidden ),
DataHiddenRole );
286 if ( boolFlag.isValid() )
287 return boolFlag.value<
bool >();
293 const QVariant boolFlag(
attributesModel()->data( conditionallyMapFromSource( index ),
295 if ( boolFlag.isValid() ) {
296 return boolFlag.value<
bool >();
298 int dataset = index.column() /
d->datasetDimension;
306 d->attributesModel->setData( conditionallyMapFromSource( index ), qVariantFromValue( a ),
336 const QVariant headerAttrs(
338 if ( headerAttrs.isValid() )
346 conditionallyMapFromSource( index ),
361 d->allowOverlappingDataValueTexts = allow;
367 return d->allowOverlappingDataValueTexts;
372 d->antiAliasing = enabled;
378 return d->antiAliasing;
383 d->percent = percent;
394 const QModelIndex& index,
398 d->paintDataValueText( painter, index, pos, value );
408 d->forgetAlreadyPaintedDataValues();
409 const int rowCount = model()->rowCount( rootIndex() );
410 const int columnCount = model()->columnCount( rootIndex() );
411 for (
int column = 0; column < columnCount; column +=
datasetDimension() ) {
412 for (
int row = 0; row < rowCount; ++row ) {
413 QModelIndex index = model()->index( row, column, rootIndex() );
418 y = index.data().toReal();
420 x = index.data().toReal();
421 y = model()->index( row, column + 1, rootIndex() ).data().toReal();
431 const QModelIndex& index,
438 const PainterSaver painterSaver( painter );
440 const QSizeF maSize( ma.
markerSize().width() / painter->matrix().m11(),
441 ma.
markerSize().height() / painter->matrix().m22() );
442 QBrush indexBrush(
brush( index ) );
443 QPen indexPen( ma.
pen() );
447 paintMarker( painter, ma, indexBrush, indexPen, pos, maSize );
454 d->reverseMapper.addCircle( index.row(), index.column(), pos, 2 * maSize );
458 const QModelIndex& index,
470 const QSizeF& maSize )
472 const QPen oldPen( painter->pen() );
479 if ( isFourPixels ) {
480 const qreal x = pos.x();
481 const qreal y = pos.y();
482 painter->drawLine( QPointF(x-1.0,y-1.0),
483 QPointF(x+1.0,y-1.0) );
484 painter->drawLine( QPointF(x-1.0,y),
486 painter->drawLine( QPointF(x-1.0,y+1.0),
487 QPointF(x+1.0,y+1.0) );
489 painter->drawPoint( pos );
491 const PainterSaver painterSaver( painter );
492 QPen painterPen(
pen );
494 painter->setBrush(
brush );
495 painter->setRenderHint ( QPainter::Antialiasing );
496 painter->translate( pos );
500 if ( markerAttributes.
threeD() ) {
501 QRadialGradient grad;
502 grad.setCoordinateMode( QGradient::ObjectBoundingMode );
503 QColor drawColor =
brush.color();
504 grad.setCenter( 0.5, 0.5 );
505 grad.setRadius( 1.0 );
506 grad.setFocalPoint( 0.35, 0.35 );
507 grad.setColorAt( 0.00, drawColor.lighter( 150 ) );
508 grad.setColorAt( 0.20, drawColor );
509 grad.setColorAt( 0.50, drawColor.darker( 150 ) );
510 grad.setColorAt( 0.75, drawColor.darker( 200 ) );
511 grad.setColorAt( 0.95, drawColor.darker( 250 ) );
512 grad.setColorAt( 1.00, drawColor.darker( 200 ) );
513 QBrush newBrush( grad );
514 newBrush.setMatrix(
brush.matrix() );
515 painter->setBrush( newBrush );
517 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
518 maSize.height(), maSize.width()) );
523 QRectF rect( 0 - maSize.width()/2, 0 - maSize.height()/2,
524 maSize.width(), maSize.height() );
525 painter->drawRect( rect );
531 QPointF top, left, bottom, right;
532 top = QPointF( 0, 0 - maSize.height()/2 );
533 left = QPointF( 0 - maSize.width()/2, 0 );
534 bottom = QPointF( 0, maSize.height()/2 );
535 right = QPointF( maSize.width()/2, 0 );
536 diamondPoints << top << left << bottom << right;
537 painter->drawPolygon( diamondPoints );
546 painter->setBrush( Qt::NoBrush );
548 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
549 maSize.height(), maSize.width()) );
556 const qreal w02 = maSize.width() * 0.2;
557 const qreal w05 = maSize.width() * 0.5;
558 const qreal h02 = maSize.height()* 0.2;
559 const qreal h05 = maSize.height()* 0.5;
562 p[ 0] = QPointF( -w02, -h05 );
563 p[ 1] = QPointF( w02, -h05 );
564 p[ 2] = QPointF( w02, -h02 );
565 p[ 3] = QPointF( w05, -h02 );
566 p[ 4] = QPointF( w05, h02 );
567 p[ 5] = QPointF( w02, h02 );
568 p[ 6] = QPointF( w02, h05 );
569 p[ 7] = QPointF( -w02, h05 );
570 p[ 8] = QPointF( -w02, h02 );
571 p[ 9] = QPointF( -w05, h02 );
572 p[10] = QPointF( -w05, -h02 );
573 p[11] = QPointF( -w02, -h02 );
574 for (
int i=0; i<12; ++i )
577 painter->drawPolygon( crossPoints );
582 QPointF left, right, top, bottom;
583 left = QPointF( -maSize.width()/2, 0 );
584 right = QPointF( maSize.width()/2, 0 );
585 top = QPointF( 0, -maSize.height()/2 );
586 bottom= QPointF( 0, maSize.height()/2 );
588 painter->drawLine( left, right );
589 painter->drawLine( top, bottom );
597 const QRectF pathBoundingRect = path.boundingRect();
598 const qreal xScaling = maSize.height() / pathBoundingRect.height();
599 const qreal yScaling = maSize.width() / pathBoundingRect.width();
600 const qreal scaling = qMin( xScaling, yScaling );
601 painter->scale( scaling, scaling );
603 painter->drawPath(path);
607 Q_ASSERT_X (
false,
"paintMarkers()",
608 "Type item does not match a defined Marker Type." );
611 painter->setPen( oldPen );
620 const int rowCount = model()->rowCount( rootIndex() );
621 const int columnCount = model()->columnCount( rootIndex() );
622 for (
int column = 0; column < columnCount; column +=
datasetDimension() ) {
623 for (
int row = 0; row < rowCount; ++row ) {
624 QModelIndex index = model()->index( row, column, rootIndex() );
629 y = index.data().toReal();
631 x = index.data().toReal();
632 y = model()->index( row, column + 1, rootIndex() ).data().toReal();
643 conditionallyMapFromSource( index ),
668 const QVariant penSettings(
d->datasetAttrs( dataset,
DatasetPenRole ) );
669 if ( penSettings.isValid() )
670 return penSettings.value< QPen >();
677 conditionallyMapFromSource( index ),
684 conditionallyMapFromSource( index ),
710 if ( brushSettings.isValid() )
711 return brushSettings.value< QBrush >();
729 d->unitPrefixMap[ column ][ orientation ]= prefix;
739 d->unitPrefix[ orientation ] = prefix;
750 d->unitSuffixMap[ column ][ orientation ]= suffix;
760 d->unitSuffix[ orientation ] = suffix;
772 if ( !fallback ||
d->unitPrefixMap[ column ].contains( orientation ) )
773 return d->unitPrefixMap[ column ][ orientation ];
774 return d->unitPrefix[ orientation ];
783 return d->unitPrefix[ orientation ];
795 if ( !fallback ||
d->unitSuffixMap[ column ].contains( orientation ) )
796 return d->unitSuffixMap[ column ][ orientation ];
797 return d->unitSuffix[ orientation ];
806 return d->unitSuffix[ orientation ];
812 return d->reverseMapper.boundingRect( index.row(), index.column() ).toRect();
821 {
return QModelIndex(); }
834 const QModelIndexList indexes =
d->indexesIn( rect );
835 QItemSelection selection;
836 KDAB_FOREACH(
const QModelIndex& index, indexes )
838 selection.append( QItemSelectionRange( index ) );
840 selectionModel()->select( selection, command );
846 KDAB_FOREACH(
const QModelIndex& index, selection.indexes() )
848 polygon <<
d->reverseMapper.polygon(index.row(), index.column());
850 return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
855 QPolygonF polygon =
d->reverseMapper.polygon(index.row(), index.column());
856 return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
880 for (
int i = 0; i < rowCount; ++i ) {
882 ret <<
unitPrefix( i, Qt::Horizontal,
true ) +
896 const int datasetCount =
d->datasetCount();
897 for (
int i = 0; i < datasetCount; ++i ) {
898 ret <<
d->datasetAttrs( i, Qt::DisplayRole ).toString();
909 const int datasetCount =
d->datasetCount();
910 for (
int i = 0; i < datasetCount; ++i ) {
922 const int datasetCount =
d->datasetCount();
923 for (
int i = 0; i < datasetCount; ++i ) {
935 const int datasetCount =
d->datasetCount();
936 for (
int i = 0; i < datasetCount; ++i ) {
944 if ( ! justReturnTheStatus ) {
945 Q_ASSERT_X ( model(),
"AbstractDiagram::checkInvariants()",
946 "There is no usable model set, for the diagram." );
949 "There is no usable coordinate plane set, for the diagram." );
956 return d->datasetDimension;
961 Q_UNUSED( dimension );
962 qDebug() <<
"Setting the dataset dimension using AbstractDiagram::setDatasetDimension is "
963 "obsolete. Use the specific diagram types instead.";
968 Q_ASSERT( dimension != 0 );
969 if (
d->datasetDimension == dimension ) {
972 d->datasetDimension = dimension;
973 d->attributesModel->setDatasetDimension( dimension );
981 qWarning() <<
"AbstractDiagram::valueForCell(): Requesting value for invalid index!";
982 return std::numeric_limits<qreal>::quiet_NaN();
984 return d->attributesModel->data(
997 return d->indexAt( point );
1002 return d->indexesAt( point );
1007 return d->indexesIn( rect );