diff --git a/src/KChart/Polar/KChartRadarDiagram.cpp b/src/KChart/Polar/KChartRadarDiagram.cpp index d03dc24..19ed72d 100644 --- a/src/KChart/Polar/KChartRadarDiagram.cpp +++ b/src/KChart/Polar/KChartRadarDiagram.cpp @@ -1,332 +1,331 @@ /* * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. * * This file is part of the KD Chart library. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "KChartRadarDiagram.h" #include "KChartRadarDiagram_p.h" #include "KChartPaintContext.h" #include "KChartPainterSaver_p.h" #include "KChartMath_p.h" #include using namespace KChart; RadarDiagram::Private::Private() : closeDatasets( false ), reverseData( false ), fillAlpha( 0.0 ) { } RadarDiagram::Private::~Private() {} #define d d_func() RadarDiagram::RadarDiagram( QWidget* parent, RadarCoordinatePlane* plane ) : AbstractPolarDiagram( new Private( ), parent, plane ) { //init(); } RadarDiagram::~RadarDiagram() { } void RadarDiagram::init() { } RadarDiagram * RadarDiagram::clone() const { RadarDiagram* newDiagram = new RadarDiagram( new Private( *d ) ); // This needs to be copied after the fact newDiagram->d->closeDatasets = d->closeDatasets; return newDiagram; } const QPair RadarDiagram::calculateDataBoundaries () const { if ( !checkInvariants(true) ) return QPair( QPointF( 0, 0 ), QPointF( 0, 0 ) ); const int rowCount = model()->rowCount(rootIndex()); const int colCount = model()->columnCount(rootIndex()); qreal xMin = 0.0; qreal xMax = colCount; qreal yMin = 0, yMax = 0; for ( int iCol=0; iColdata( model()->index( iRow, iCol, rootIndex() ) ).toReal(); // checked yMax = qMax( yMax, value ); yMin = qMin( yMin, value ); } } QPointF bottomLeft ( QPointF( xMin, yMin ) ); QPointF topRight ( QPointF( xMax, yMax ) ); return QPair ( bottomLeft, topRight ); } void RadarDiagram::paintEvent ( QPaintEvent*) { QPainter painter ( viewport() ); PaintContext ctx; ctx.setPainter ( &painter ); ctx.setRectangle( QRectF ( 0, 0, width(), height() ) ); paint ( &ctx ); } void RadarDiagram::paint( PaintContext* ctx ) { qreal dummy1, dummy2; paint( ctx, true, dummy1, dummy2 ); paint( ctx, false, dummy1, dummy2 ); } static qreal fitFontSizeToGeometry( const QString& text, const QFont& font, const QRectF& geometry, const TextAttributes& ta ) { QFont f = font; const qreal origResult = f.pointSizeF(); qreal result = origResult; const QSizeF mySize = geometry.size(); if ( mySize.isNull() ) return result; const QString t = text; QFontMetrics fm( f ); while ( true ) { const QSizeF textSize = rotatedRect( fm.boundingRect( t ), ta.rotation() ).normalized().size(); if ( textSize.height() <= mySize.height() && textSize.width() <= mySize.width() ) return result; result -= 0.5; if ( result <= 0.0 ) return origResult; f.setPointSizeF( result ); fm = QFontMetrics( f ); } } static QPointF scaleToRealPosition( const QPointF& origin, const QRectF& sourceRect, const QRectF& destRect, const AbstractCoordinatePlane& plane ) { QPointF result = plane.translate( origin ); result -= sourceRect.topLeft(); result.setX( result.x() / sourceRect.width() * destRect.width() ); result.setY( result.y() / sourceRect.height() * destRect.height() ); result += destRect.topLeft(); return result; } void RadarDiagram::setReverseData( bool val ) { d->reverseData = val; } bool RadarDiagram::reverseData() { return d->reverseData; } // local structure to remember the settings of a polygon inclusive the used color and pen. struct Polygon { QPolygonF polygon; QBrush brush; QPen pen; Polygon(const QPolygonF &polygon, const QBrush &brush, const QPen &pen) : polygon(polygon), brush(brush), pen(pen) {} }; void RadarDiagram::paint( PaintContext* ctx, bool calculateListAndReturnScale, qreal& newZoomX, qreal& newZoomY ) { // note: Not having any data model assigned is no bug // but we can not draw a diagram then either. if ( !checkInvariants(true) ) return; d->reverseMapper.clear(); const int rowCount = model()->rowCount( rootIndex() ); const int colCount = model()->columnCount( rootIndex() ); int iRow, iCol; const qreal min = dataBoundaries().first.y(); const qreal r = qAbs( min ) + dataBoundaries().second.y(); const qreal step = ( r - qAbs( min ) ) / ( numberOfGridRings() ); RadarCoordinatePlane* plane = dynamic_cast(ctx->coordinatePlane()); TextAttributes ta = plane->textAttributes(); QRectF fontRect = ctx->rectangle(); fontRect.setSize( QSizeF( fontRect.width(), step / 2.0 ) ); const qreal labelFontSize = fitFontSizeToGeometry( QString::fromLatin1( "TestXYWQgqy" ), ta.font(), fontRect, ta ); QFont labelFont = ta.font(); ctx->painter()->setPen( ta.pen() ); labelFont.setPointSizeF( labelFontSize ); const QFontMetricsF metric( labelFont ); const qreal labelHeight = metric.height(); - QPointF offset; QRectF destRect = ctx->rectangle(); if ( ta.isVisible() ) { destRect.setY( destRect.y() + 2 * labelHeight ); destRect.setHeight( destRect.height() - 4 * labelHeight ); } if ( calculateListAndReturnScale ) { ctx->painter()->save(); // Check if all of the data value texts / data comments will fit // into the available space: d->labelPaintCache.clear(); ctx->painter()->save(); for ( iCol=0; iCol < colCount; ++iCol ) { for ( iRow=0; iRow < rowCount; ++iRow ) { QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked const qreal value = model()->data( index ).toReal(); QPointF point = scaleToRealPosition( QPointF( value, iRow ), ctx->rectangle(), destRect, *ctx->coordinatePlane() ); d->addLabel( &d->labelPaintCache, index, nullptr, PositionPoints( point ), Position::Center, Position::Center, value ); } } ctx->painter()->restore(); const qreal oldZoomX = coordinatePlane()->zoomFactorX(); const qreal oldZoomY = coordinatePlane()->zoomFactorY(); newZoomX = oldZoomX; newZoomY = oldZoomY; if ( d->labelPaintCache.paintReplay.count() ) { QRectF txtRectF; d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true, true, &txtRectF ); const QRect txtRect = txtRectF.toRect(); const QRect curRect = coordinatePlane()->geometry(); const qreal gapX = qMin( txtRect.left() - curRect.left(), curRect.right() - txtRect.right() ); const qreal gapY = qMin( txtRect.top() - curRect.top(), curRect.bottom() - txtRect.bottom() ); newZoomX = oldZoomX; newZoomY = oldZoomY; if ( gapX < 0.0 ) newZoomX *= 1.0 + (gapX-1.0) / curRect.width(); if ( gapY < 0.0 ) newZoomY *= 1.0 + (gapY-1.0) / curRect.height(); } ctx->painter()->restore(); } else { // Iterate through data sets and create a list of polygons out of them. QList polygons; for ( iCol=0; iCol < colCount; ++iCol ) { //TODO(khz): As of yet RadarDiagram can not show per-segment line attributes // but it draws every polyline in one go - using one color. // This needs to be enhanced to allow for cell-specific settings // in the same way as LineDiagram does it. QPolygonF polygon; QPointF point0; for ( iRow=0; iRow < rowCount; ++iRow ) { QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked const qreal value = model()->data( index ).toReal(); QPointF point = scaleToRealPosition( QPointF( value, d->reverseData ? ( rowCount - iRow ) : iRow ), ctx->rectangle(), destRect, *ctx->coordinatePlane() ); polygon.append( point ); if ( ! iRow ) point0= point; } if ( closeDatasets() && rowCount ) polygon.append( point0 ); QBrush brush = d->datasetAttrs( iCol, KChart::DatasetBrushRole ).value(); QPen p = d->datasetAttrs( iCol, KChart::DatasetPenRole ).value< QPen >(); if ( p.style() != Qt::NoPen ) { polygons.append( Polygon( polygon, brush, PrintingParameters::scalePen( p ) ) ); } } // first fill the areas with the brush-color and the defined alpha-value. if (d->fillAlpha > 0.0) { Q_FOREACH(const Polygon& p, polygons) { PainterSaver painterSaver( ctx->painter() ); ctx->painter()->setRenderHint ( QPainter::Antialiasing ); QBrush br = p.brush; QColor c = br.color(); c.setAlphaF(d->fillAlpha); br.setColor(c); ctx->painter()->setBrush( br ); ctx->painter()->setPen( p.pen ); ctx->painter()->drawPolygon( p.polygon ); } } // then draw the poly-lines. Q_FOREACH(const Polygon& p, polygons) { PainterSaver painterSaver( ctx->painter() ); ctx->painter()->setRenderHint ( QPainter::Antialiasing ); ctx->painter()->setBrush( p.brush ); ctx->painter()->setPen( p.pen ); ctx->painter()->drawPolyline( p.polygon ); } d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true ); } } void RadarDiagram::resize ( const QSizeF& size ) { AbstractPolarDiagram::resize( size ); } /*virtual*/ qreal RadarDiagram::valueTotals () const { return model()->rowCount(rootIndex()); } /*virtual*/ qreal RadarDiagram::numberOfValuesPerDataset() const { return model() ? model()->rowCount(rootIndex()) : 0.0; } /*virtual*/ qreal RadarDiagram::numberOfGridRings() const { return 5; // FIXME } void RadarDiagram::setCloseDatasets( bool closeDatasets ) { d->closeDatasets = closeDatasets; } bool RadarDiagram::closeDatasets() const { return d->closeDatasets; } qreal RadarDiagram::fillAlpha() const { return d->fillAlpha; } void RadarDiagram::setFillAlpha(qreal alphaF) { d->fillAlpha = alphaF; } void RadarDiagram::resizeEvent ( QResizeEvent*) { } diff --git a/src/KChart/ReverseMapper.cpp b/src/KChart/ReverseMapper.cpp index 7e7596c..c058870 100644 --- a/src/KChart/ReverseMapper.cpp +++ b/src/KChart/ReverseMapper.cpp @@ -1,178 +1,177 @@ /* * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. * * This file is part of the KD Chart library. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ReverseMapper.h" #include #include #include #include #include #include #include "KChartAbstractDiagram.h" #include "ChartGraphicsItem.h" using namespace KChart; ReverseMapper::ReverseMapper() : m_scene( nullptr ) , m_diagram( nullptr ) { } ReverseMapper::ReverseMapper( AbstractDiagram* diagram ) : m_scene( nullptr ) , m_diagram( diagram ) { } ReverseMapper::~ReverseMapper() { delete m_scene; m_scene = nullptr; } void ReverseMapper::setDiagram( AbstractDiagram* diagram ) { m_diagram = diagram; } void ReverseMapper::clear() { m_itemMap.clear(); delete m_scene; m_scene = new QGraphicsScene(); } QModelIndexList ReverseMapper::indexesIn( const QRect& rect ) const { Q_ASSERT( m_diagram ); if ( m_scene && m_scene->sceneRect().intersects( rect ) ) { QList items = m_scene->items( rect ); QModelIndexList indexes; Q_FOREACH( QGraphicsItem* item, items ) { ChartGraphicsItem* i = qgraphicsitem_cast( item ); if ( i ) { QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) ); // checked indexes << index; } } return indexes; } else { return QModelIndexList(); } } QModelIndexList ReverseMapper::indexesAt( const QPointF& point ) const { Q_ASSERT( m_diagram ); if ( m_scene && m_scene->sceneRect().contains( point ) ) { QList items = m_scene->items( point ); QModelIndexList indexes; Q_FOREACH( QGraphicsItem* item, items ) { ChartGraphicsItem* i = qgraphicsitem_cast( item ); if ( i ) { QModelIndex index ( m_diagram->model()->index( i->row(), i->column(), m_diagram->rootIndex() ) ); // checked if ( !indexes.contains(index) ) indexes << index; } } return indexes; } else { return QModelIndexList(); } } QPolygonF ReverseMapper::polygon( int row, int column ) const { if ( !m_diagram->model()->hasIndex( row, column, m_diagram->rootIndex() ) ) return QPolygon(); const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() ); // checked return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon() : QPolygon(); } QRectF ReverseMapper::boundingRect( int row, int column ) const { if ( !m_diagram->model()->hasIndex( row, column, m_diagram->rootIndex() ) ) return QRectF(); const QModelIndex index = m_diagram->model()->index( row, column, m_diagram->rootIndex() ); // checked return m_itemMap.contains( index ) ? m_itemMap[ index ]->polygon().boundingRect() : QRectF(); } void ReverseMapper::addItem( ChartGraphicsItem* item ) { Q_ASSERT( m_scene ); m_scene->addItem( item ); m_itemMap.insert( m_diagram->model()->index( item->row(), item->column(), m_diagram->rootIndex() ), item ); // checked } void ReverseMapper::addRect( int row, int column, const QRectF& rect ) { addPolygon( row, column, QPolygonF( rect ) ); } void ReverseMapper::addPolygon( int row, int column, const QPolygonF& polygon ) { ChartGraphicsItem* item = new ChartGraphicsItem( row, column ); item->setPolygon( polygon ); addItem( item ); } void ReverseMapper::addCircle( int row, int column, const QPointF& location, const QSizeF& diameter ) { QPainterPath path; QPointF ossfet( -0.5*diameter.width(), -0.5*diameter.height() ); path.addEllipse( QRectF( location + ossfet, diameter ) ); addPolygon( row, column, QPolygonF( path.toFillPolygon() ) ); } void ReverseMapper::addLine( int row, int column, const QPointF& from, const QPointF& to ) { // that's no line, dude... make a small circle around that point, instead if ( from == to ) { addCircle( row, column, from, QSizeF( 1.5, 1.5 ) ); return; } // lines do not make good polygons to click on. we calculate a 2 // pixel wide rectangle, where the original line is excatly // centered in. // make a 3 pixel wide polygon from the line: - static const QPointF pixel( 1.0, 1.0 ); QPointF left, right; if ( from.x() < to.x() ) { left = from; right = to; } else { right = from; left = to; } const QPointF lineVector( right - left ); const qreal lineVectorLength = sqrt( lineVector.x() * lineVector.x() + lineVector.y() * lineVector.y() ); const QPointF lineVectorUnit( lineVector / lineVectorLength ); const QPointF normOfLineVectorUnit( -lineVectorUnit.y(), lineVectorUnit.x() ); // now the four polygon end points: const QPointF one( left - lineVectorUnit + normOfLineVectorUnit ); const QPointF two( left - lineVectorUnit - normOfLineVectorUnit ); const QPointF three( right + lineVectorUnit - normOfLineVectorUnit ); const QPointF four( right + lineVectorUnit + normOfLineVectorUnit ); addPolygon( row, column, QPolygonF() << one << two << three << four ); } diff --git a/src/KChart/Ternary/KChartTernaryAxis.cpp b/src/KChart/Ternary/KChartTernaryAxis.cpp index 5b1713f..13bd363 100644 --- a/src/KChart/Ternary/KChartTernaryAxis.cpp +++ b/src/KChart/Ternary/KChartTernaryAxis.cpp @@ -1,280 +1,279 @@ /* * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. * * This file is part of the KD Chart library. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "KChartTernaryAxis.h" #include #include #include #include "TernaryConstants.h" #include "KChartTernaryCoordinatePlane.h" #include "KChartAbstractTernaryDiagram.h" #include "KChartLayoutItems.h" #include "KChartTextLabelCache.h" using namespace KChart; // m_label and m_fifty do not have to be pointers, once the class is // pimpled (PrerenderedLabel is not published API) TernaryAxis::TernaryAxis ( AbstractTernaryDiagram* diagram) : AbstractAxis( diagram ) , m_position( KChartEnums::PositionUnknown ) , m_label( new PrerenderedLabel ) , m_fifty( new PrerenderedLabel ) { resetTitleTextAttributes(); setPosition( KChartEnums::PositionSouth ); // arbitrary m_fifty->setText( QObject::tr( "50%" ) ); // const // FIXME is this consistent with other diagram/axis/plane implementations? diagram->addAxis( this ); } TernaryAxis::~TernaryAxis() { delete m_label; m_label = nullptr; delete m_fifty; m_fifty = nullptr; } void TernaryAxis::paintAll (QPainter &) { // not used } void TernaryAxis::paint (QPainter *) { // not used } void TernaryAxis::paintCtx (PaintContext * paintContext) { QPainter* p = paintContext->painter(); TernaryCoordinatePlane* plane = (TernaryCoordinatePlane*) paintContext->coordinatePlane(); // QObject* refArea = plane->parent(); - QRectF titleArea; // paint the axis label (across the triangle, that one): QList labels; labels << m_label << m_fifty; Q_FOREACH( PrerenderedLabel* label, labels ) { const QPixmap& pixmap = label->pixmap(); QPointF point = plane->translate( label->position() ) - label->referencePointLocation(); p->drawPixmap( point, pixmap ); } } bool TernaryAxis::isEmpty() const { // todo: what's this method for? return false; } QRect TernaryAxis::geometry () const { return m_geometry; } void TernaryAxis::setGeometry (const QRect &rect) { m_geometry = rect; } QSize TernaryAxis::minimumSize () const { // todo: return realistic sizes return QSize( 100, 100 ); } QSize TernaryAxis::maximumSize () const { return QSize( 300, 200 ); } QSize TernaryAxis::sizeHint () const { return QSize( 150, 100 ); } Qt::Orientations TernaryAxis::expandingDirections () const { return Qt::Vertical | Qt::Horizontal; } const Position TernaryAxis::position () const { return m_position; } void TernaryAxis::setPosition (Position p) { if ( p == position() ) return; if ( p != KChartEnums::PositionWest && p != KChartEnums::PositionEast && p != KChartEnums::PositionSouth ) { qDebug() << "TernaryAxis::setPosition: only south, east and west are supported " "positions for ternary axes."; return; } if ( m_title.isEmpty() ) switch ( p.value() ) { case KChartEnums::PositionSouth: m_label->setText( tr( "A" ) ); break; case KChartEnums::PositionWest: m_label->setText( tr( "C" ) ); break; case KChartEnums::PositionEast: m_label->setText( tr( "B" ) ); break; default: break; } m_position = p; updatePrerenderedLabels(); // position has changed } void TernaryAxis::setTitleText( const QString& text ) { m_title = text; // do not remove m_label->setText( text ); } QString TernaryAxis::titleText() const { return m_label->text(); } void TernaryAxis::setTitleTextAttributes( const TextAttributes &a ) { m_titleAttributes = a; updatePrerenderedLabels(); } TextAttributes TernaryAxis::titleTextAttributes() const { return m_titleAttributes; } void TernaryAxis::resetTitleTextAttributes() { TextAttributes a; m_titleAttributes = a; updatePrerenderedLabels(); } bool TernaryAxis::hasDefaultTitleTextAttributes() const { TextAttributes a; return m_titleAttributes == a; } void TernaryAxis::updatePrerenderedLabels() { TextAttributes attributes = titleTextAttributes(); qreal axisLabelAngle = 0.0; qreal fiftyMarkAngle = 0.0; QPointF axisLabelPosition; QPointF fiftyMarkPosition; KChartEnums::PositionValue fiftyMarkReferencePoint = KChartEnums::PositionUnknown; switch ( position().value() ) { case KChartEnums::PositionSouth: // this is the axis on the other side of A axisLabelAngle = 0.0; fiftyMarkAngle = 0.0; axisLabelPosition = TriangleTop; fiftyMarkPosition = 0.5 * AxisVector_B_C - RelMarkerLength * Norm_B_C; fiftyMarkReferencePoint = KChartEnums::PositionNorth; break; case KChartEnums::PositionEast: // this is the axis on the other side of B axisLabelAngle = 240.0; fiftyMarkAngle = 60; axisLabelPosition = TriangleBottomLeft; fiftyMarkPosition = AxisVector_B_C + 0.5 * AxisVector_C_A - RelMarkerLength * Norm_C_A; fiftyMarkReferencePoint = KChartEnums::PositionSouth; break; case KChartEnums::PositionWest: // this is the axis on the other side of C axisLabelAngle = 120.0; fiftyMarkAngle = 300.0; axisLabelPosition = TriangleBottomRight; fiftyMarkPosition = 0.5 * AxisVector_B_A + RelMarkerLength * Norm_B_A; fiftyMarkReferencePoint = KChartEnums::PositionSouth; break; case KChartEnums::PositionUnknown: break; // initial value default: qDebug() << "TernaryAxis::updatePrerenderedLabel: unknown location"; }; m_label->setFont( attributes.font() ); // m_label->setText( titleText() ); // done by setTitleText() m_label->setAngle( axisLabelAngle ); m_label->setPosition( axisLabelPosition ); m_label->setReferencePoint( KChartEnums::PositionSouth ); QFont font = attributes.font(); font.setPointSizeF( 0.85 * font.pointSizeF() ); m_fifty->setFont( font ); m_fifty->setAngle( fiftyMarkAngle ); m_fifty->setPosition( fiftyMarkPosition ); m_fifty->setReferencePoint( fiftyMarkReferencePoint ); } QPair TernaryAxis::requiredMargins() const { QSizeF topleft( 0.0, 0.0 ); QSizeF bottomRight( 0.0, 0.0 ); switch ( position().value() ) { case KChartEnums::PositionSouth: // the label of the south axis is, in fact, up north. topleft.setHeight( m_label->pixmap().height() ); bottomRight.setHeight( m_fifty->pixmap().height() ); break; case KChartEnums::PositionWest: bottomRight.setWidth( m_label->pixmap().width() - m_label->referencePointLocation().x() ); bottomRight.setHeight( m_label->pixmap().height() - m_label->referencePointLocation().y() ); break; case KChartEnums::PositionEast: topleft.setWidth( m_label->pixmap().width() - ( m_label->pixmap().width() - m_label->referencePointLocation().x() ) ); bottomRight.setHeight( m_label->pixmap().height() - ( m_label->pixmap().height() - m_label->referencePointLocation().y() ) ); break; default: qDebug() << "TernaryAxis::requiredMargins: unknown location"; } // qDebug() << "TernaryAxis::requiredMargins:" << topleft << bottomRight; return QPair( topleft, bottomRight ); } diff --git a/src/KGantt/test/TestKGanttConstraintModel.cpp b/src/KGantt/test/TestKGanttConstraintModel.cpp index 4a5eba9..1f8d707 100644 --- a/src/KGantt/test/TestKGanttConstraintModel.cpp +++ b/src/KGantt/test/TestKGanttConstraintModel.cpp @@ -1,86 +1,84 @@ /* * Copyright (C) 2018 Dag Andersen * * This file is part of the KGantt library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "TestKGanttConstraintModel.h" #include "kganttglobal.h" #include using namespace KGantt; void TestKGanttConstraintModel::initTestCase() { itemModel = new QStandardItemModel(100, 100); } void TestKGanttConstraintModel::cleanupTestCase() { delete itemModel; } void TestKGanttConstraintModel::testModel() { ConstraintModel model; - QModelIndex invalidIndex; - QCOMPARE(model.constraints().count(), 0); model.addConstraint(Constraint(QModelIndex(), QModelIndex())); QCOMPARE(model.constraints().count(), 1); model.addConstraint(Constraint(QModelIndex(), QModelIndex())); QCOMPARE(model.constraints().count(), 1); QPersistentModelIndex idx1 = itemModel->index(7, 17, QModelIndex()); QPersistentModelIndex idx2 = itemModel->index(42, 17, QModelIndex()); model.addConstraint(Constraint(idx1, idx2)); QCOMPARE(model.constraints().count(), 2); QVERIFY(model.hasConstraint(Constraint(idx1, idx2))); QCOMPARE(model.constraintsForIndex(QModelIndex()).count(), 1); QCOMPARE(model.constraints().count(), 2); model.removeConstraint(Constraint(QModelIndex(), QModelIndex())); QCOMPARE(model.constraints().count(), 1); QVERIFY(!model.hasConstraint(Constraint(QModelIndex(), QModelIndex()))); model.removeConstraint(Constraint(QModelIndex(), QModelIndex())); QCOMPARE(model.constraints().count(), 1); model.removeConstraint(Constraint(idx1, idx2)); QCOMPARE(model.constraints().count(), 0); QVERIFY(!model.hasConstraint(Constraint(idx1, idx2))); model.addConstraint(Constraint(idx1, idx2)); QVERIFY(model.hasConstraint(Constraint(idx1, idx2))); itemModel->removeRow(8); QVERIFY(idx2 == itemModel->index(41, 17, QModelIndex())); QVERIFY(model.hasConstraint(Constraint(idx1, idx2))); itemModel->removeRow(7); QVERIFY(!idx1.isValid()); QVERIFY(idx2 == itemModel->index(40, 17, QModelIndex())); QVERIFY(model.hasConstraint(Constraint(idx1, idx2))); } QTEST_GUILESS_MAIN(TestKGanttConstraintModel)