24 #include "KDChartAbstractDiagram_p.h"
28 #include <QApplication>
29 #include <QAbstractProxyModel>
39 #include "KDChartPainterSaver_p.h"
41 #include <KDABLibFakes>
45 using namespace KDChart;
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;
137 disconnect( model(), SIGNAL( rowsInserted( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
138 disconnect( model(), SIGNAL( columnsInserted( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
139 disconnect( model(), SIGNAL( rowsRemoved( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
140 disconnect( model(), SIGNAL( columnsRemoved( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
145 QAbstractItemView::setModel( newModel );
148 d->setAttributesModel(amodel);
149 scheduleDelayedItemsLayout();
153 connect( model(), SIGNAL( rowsInserted( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
154 connect( model(), SIGNAL( columnsInserted( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
155 connect( model(), SIGNAL( rowsRemoved( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
156 connect( model(), SIGNAL( columnsRemoved( QModelIndex,
int,
int ) ),
this, SLOT(
setDataBoundariesDirty() ) );
166 if ( selectionModel() )
168 disconnect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SIGNAL(
modelsChanged() ) );
169 disconnect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SIGNAL(
modelsChanged() ) );
171 QAbstractItemView::setSelectionModel( newSelectionModel );
172 if ( selectionModel() )
174 connect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SIGNAL(
modelsChanged() ) );
175 connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SIGNAL(
modelsChanged() ) );
189 if ( amodel->sourceModel() != model() ) {
190 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
191 "Trying to set an attributesmodel which works on a different "
192 "model than the diagram.");
195 if ( qobject_cast<PrivateAttributesModel*>(amodel) ) {
196 qWarning(
"KDChart::AbstractDiagram::setAttributesModel() failed: "
197 "Trying to set an attributesmodel that is private to another diagram.");
200 d->setAttributesModel(amodel);
201 scheduleDelayedItemsLayout();
208 return d->usesExternalAttributesModel();
213 return d->attributesModel;
216 QModelIndex AbstractDiagram::conditionallyMapFromSource(
const QModelIndex & index )
const
225 QAbstractItemView::setRootIndex( idx );
232 d->attributesModelRootIndex = idx;
234 scheduleDelayedItemsLayout();
241 if ( !
d->attributesModelRootIndex.isValid() )
242 d->attributesModelRootIndex =
d->attributesModel->mapFromSource( rootIndex() );
243 return d->attributesModelRootIndex;
254 d->plane->layoutDiagrams();
257 QAbstractItemView::doItemsLayout();
260 #if QT_VERSION < 0x050000
262 const QModelIndex &bottomRight )
265 const QModelIndex &bottomRight,
270 Q_UNUSED( bottomRight );
272 setDataBoundariesDirty();
273 scheduleDelayedItemsLayout();
279 d->attributesModel->setData(
280 conditionallyMapFromSource( index ),
281 qVariantFromValue( hidden ),
288 d->setDatasetAttrs( dataset, qVariantFromValue( hidden ),
DataHiddenRole );
294 d->attributesModel->setModelData( qVariantFromValue( hidden ),
DataHiddenRole );
306 if ( boolFlag.isValid() )
307 return boolFlag.value<
bool >();
313 const QVariant boolFlag(
attributesModel()->data( conditionallyMapFromSource( index ),
315 if ( boolFlag.isValid() ) {
316 return boolFlag.value<
bool >();
318 int dataset = index.column() /
d->datasetDimension;
326 d->attributesModel->setData( conditionallyMapFromSource( index ), qVariantFromValue( a ),
356 const QVariant headerAttrs(
358 if ( headerAttrs.isValid() )
366 conditionallyMapFromSource( index ),
381 d->allowOverlappingDataValueTexts = allow;
387 return d->allowOverlappingDataValueTexts;
392 d->antiAliasing = enabled;
398 return d->antiAliasing;
403 d->percent = percent;
414 const QModelIndex& index,
418 d->paintDataValueText( painter, index, pos, value );
428 d->forgetAlreadyPaintedDataValues();
429 const int rowCount = model()->rowCount( rootIndex() );
430 const int columnCount = model()->columnCount( rootIndex() );
431 for (
int column = 0; column < columnCount; column +=
datasetDimension() ) {
432 for (
int row = 0; row < rowCount; ++row ) {
433 QModelIndex index = model()->index( row, column, rootIndex() );
438 y = index.data().toReal();
440 x = index.data().toReal();
441 y = model()->index( row, column + 1, rootIndex() ).data().toReal();
451 const QModelIndex& index,
458 const PainterSaver painterSaver( painter );
460 const QSizeF maSize( ma.
markerSize().width() / painter->matrix().m11(),
461 ma.
markerSize().height() / painter->matrix().m22() );
462 QBrush indexBrush(
brush( index ) );
463 QPen indexPen( ma.
pen() );
467 paintMarker( painter, ma, indexBrush, indexPen, pos, maSize );
474 d->reverseMapper.addCircle( index.row(), index.column(), pos, 2 * maSize );
478 const QModelIndex& index,
490 const QSizeF& maSize )
492 const QPen oldPen( painter->pen() );
499 if ( isFourPixels ) {
500 const qreal x = pos.x();
501 const qreal y = pos.y();
502 painter->drawLine( QPointF(x-1.0,y-1.0),
503 QPointF(x+1.0,y-1.0) );
504 painter->drawLine( QPointF(x-1.0,y),
506 painter->drawLine( QPointF(x-1.0,y+1.0),
507 QPointF(x+1.0,y+1.0) );
509 painter->drawPoint( pos );
511 const PainterSaver painterSaver( painter );
512 QPen painterPen( pen );
514 painter->setBrush( brush );
515 painter->setRenderHint ( QPainter::Antialiasing );
516 painter->translate( pos );
520 if ( markerAttributes.
threeD() ) {
521 QRadialGradient grad;
522 grad.setCoordinateMode( QGradient::ObjectBoundingMode );
523 QColor drawColor = brush.color();
524 grad.setCenter( 0.5, 0.5 );
525 grad.setRadius( 1.0 );
526 grad.setFocalPoint( 0.35, 0.35 );
527 grad.setColorAt( 0.00, drawColor.lighter( 150 ) );
528 grad.setColorAt( 0.20, drawColor );
529 grad.setColorAt( 0.50, drawColor.darker( 150 ) );
530 grad.setColorAt( 0.75, drawColor.darker( 200 ) );
531 grad.setColorAt( 0.95, drawColor.darker( 250 ) );
532 grad.setColorAt( 1.00, drawColor.darker( 200 ) );
533 QBrush newBrush( grad );
534 newBrush.setMatrix( brush.matrix() );
535 painter->setBrush( newBrush );
537 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
538 maSize.height(), maSize.width()) );
543 QRectF rect( 0 - maSize.width()/2, 0 - maSize.height()/2,
544 maSize.width(), maSize.height() );
545 painter->drawRect( rect );
551 QPointF top, left, bottom, right;
552 top = QPointF( 0, 0 - maSize.height()/2 );
553 left = QPointF( 0 - maSize.width()/2, 0 );
554 bottom = QPointF( 0, maSize.height()/2 );
555 right = QPointF( maSize.width()/2, 0 );
556 diamondPoints << top << left << bottom << right;
557 painter->drawPolygon( diamondPoints );
566 painter->setBrush( Qt::NoBrush );
568 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
569 maSize.height(), maSize.width()) );
576 const qreal w02 = maSize.width() * 0.2;
577 const qreal w05 = maSize.width() * 0.5;
578 const qreal h02 = maSize.height()* 0.2;
579 const qreal h05 = maSize.height()* 0.5;
582 p[ 0] = QPointF( -w02, -h05 );
583 p[ 1] = QPointF( w02, -h05 );
584 p[ 2] = QPointF( w02, -h02 );
585 p[ 3] = QPointF( w05, -h02 );
586 p[ 4] = QPointF( w05, h02 );
587 p[ 5] = QPointF( w02, h02 );
588 p[ 6] = QPointF( w02, h05 );
589 p[ 7] = QPointF( -w02, h05 );
590 p[ 8] = QPointF( -w02, h02 );
591 p[ 9] = QPointF( -w05, h02 );
592 p[10] = QPointF( -w05, -h02 );
593 p[11] = QPointF( -w02, -h02 );
594 for (
int i=0; i<12; ++i )
597 painter->drawPolygon( crossPoints );
602 QPointF left, right, top, bottom;
603 left = QPointF( -maSize.width()/2, 0 );
604 right = QPointF( maSize.width()/2, 0 );
605 top = QPointF( 0, -maSize.height()/2 );
606 bottom= QPointF( 0, maSize.height()/2 );
608 painter->drawLine( left, right );
609 painter->drawLine( top, bottom );
617 const QRectF pathBoundingRect = path.boundingRect();
618 const qreal xScaling = maSize.height() / pathBoundingRect.height();
619 const qreal yScaling = maSize.width() / pathBoundingRect.width();
620 const qreal scaling = qMin( xScaling, yScaling );
621 painter->scale( scaling, scaling );
623 painter->drawPath(path);
627 Q_ASSERT_X (
false,
"paintMarkers()",
628 "Type item does not match a defined Marker Type." );
631 painter->setPen( oldPen );
640 const int rowCount = model()->rowCount( rootIndex() );
641 const int columnCount = model()->columnCount( rootIndex() );
642 for (
int column = 0; column < columnCount; column +=
datasetDimension() ) {
643 for (
int row = 0; row < rowCount; ++row ) {
644 QModelIndex index = model()->index( row, column, rootIndex() );
649 y = index.data().toReal();
651 x = index.data().toReal();
652 y = model()->index( row, column + 1, rootIndex() ).data().toReal();
663 conditionallyMapFromSource( index ),
677 d->setDatasetAttrs( dataset, qVariantFromValue( pen ),
DatasetPenRole );
688 const QVariant penSettings(
d->datasetAttrs( dataset,
DatasetPenRole ) );
689 if ( penSettings.isValid() )
690 return penSettings.value< QPen >();
697 conditionallyMapFromSource( index ),
704 conditionallyMapFromSource( index ),
730 if ( brushSettings.isValid() )
731 return brushSettings.value< QBrush >();
749 d->unitPrefixMap[ column ][ orientation ]= prefix;
759 d->unitPrefix[ orientation ] = prefix;
770 d->unitSuffixMap[ column ][ orientation ]= suffix;
780 d->unitSuffix[ orientation ] = suffix;
792 if ( !fallback ||
d->unitPrefixMap[ column ].contains( orientation ) )
793 return d->unitPrefixMap[ column ][ orientation ];
794 return d->unitPrefix[ orientation ];
803 return d->unitPrefix[ orientation ];
815 if ( !fallback ||
d->unitSuffixMap[ column ].contains( orientation ) )
816 return d->unitSuffixMap[ column ][ orientation ];
817 return d->unitSuffix[ orientation ];
826 return d->unitSuffix[ orientation ];
832 return d->reverseMapper.boundingRect( index.row(), index.column() ).toRect();
841 {
return QModelIndex(); }
854 const QModelIndexList indexes =
d->indexesIn( rect );
855 QItemSelection selection;
856 KDAB_FOREACH(
const QModelIndex& index, indexes )
858 selection.append( QItemSelectionRange( index ) );
860 selectionModel()->select( selection, command );
866 KDAB_FOREACH(
const QModelIndex& index, selection.indexes() )
868 polygon <<
d->reverseMapper.polygon(index.row(), index.column());
870 return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
875 QPolygonF polygon =
d->reverseMapper.polygon(index.row(), index.column());
876 return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
900 for (
int i = 0; i < rowCount; ++i ) {
902 ret <<
unitPrefix( i, Qt::Horizontal,
true ) +
916 const int datasetCount =
d->datasetCount();
917 for (
int i = 0; i < datasetCount; ++i ) {
918 ret <<
d->datasetAttrs( i, Qt::DisplayRole ).toString();
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 ) {
955 const int datasetCount =
d->datasetCount();
956 for (
int i = 0; i < datasetCount; ++i ) {
964 if ( ! justReturnTheStatus ) {
965 Q_ASSERT_X ( model(),
"AbstractDiagram::checkInvariants()",
966 "There is no usable model set, for the diagram." );
969 "There is no usable coordinate plane set, for the diagram." );
976 return d->datasetDimension;
981 Q_UNUSED( dimension );
982 qDebug() <<
"Setting the dataset dimension using AbstractDiagram::setDatasetDimension is "
983 "obsolete. Use the specific diagram types instead.";
988 Q_ASSERT( dimension != 0 );
989 if (
d->datasetDimension == dimension ) {
992 d->datasetDimension = dimension;
993 d->attributesModel->setDatasetDimension( dimension );
1001 qWarning() <<
"AbstractDiagram::valueForCell(): Requesting value for invalid index!";
1002 return std::numeric_limits<qreal>::quiet_NaN();
1004 return d->attributesModel->data(
1017 return d->indexAt( point );
1022 return d->indexesAt( point );
1027 return d->indexesIn( rect );