/*! \return The bounding rectangle for the graphics used to represent
 * a constraint between points \a start and \a end (typically an
 * arrow)
 */
QRectF ItemDelegate::constraintBoundingRect( const QPointF& start, const QPointF& end, const Constraint &constraint ) const
{
    QPolygonF poly;
    QPointF e = end;
    switch ( constraint.relationType() ) {
        case Constraint::FinishStart:
            if ( constraint.endIndex().data( KDGantt::ItemTypeRole ).toInt() == KDGantt::TypeEvent ) {
                e.setX( e.x() - TURN );
            }
            poly = finishStartLine( start, e ) + finishStartArrow( start, e );
            break;
        case Constraint::FinishFinish:
            if ( constraint.endIndex().data( KDGantt::ItemTypeRole ).toInt() == KDGantt::TypeEvent ) {
                e.setX( e.x() + TURN );
            }
            poly = finishFinishLine( start, e ) + finishFinishArrow( start, e );
            break;
        case Constraint::StartStart:
            if ( constraint.endIndex().data( KDGantt::ItemTypeRole ).toInt() == KDGantt::TypeEvent ) {
                e.setX( e.x() - TURN );
            }
            poly = startStartLine( start, e ) + startStartArrow( start, e );
            break;
        case Constraint::StartFinish:
            if ( constraint.endIndex().data( KDGantt::ItemTypeRole ).toInt() == KDGantt::TypeEvent ) {
                e.setX( e.x() + TURN );
            }
            poly = startFinishLine( start, e ) + startFinishArrow( start, e );
            break;
        default:
            break;
    }
    return poly.boundingRect().adjusted( -PW, -PW, PW, PW );
}
/*!\returns true if the startpoint is before the endpoint
 * of the constraint \a c.
 */
bool AbstractGrid::isSatisfiedConstraint( const Constraint& c ) const
{
    // First check if the data is valid,
    // TODO: review if true is the right choice
    if ( !c.startIndex().isValid() || !c.endIndex().isValid() ) return true;

    Span ss = mapToChart( c.startIndex() );
    Span es = mapToChart( c.endIndex() );
    return ( ss.end() <= es.start() );
}
void ItemDelegate::paintStartFinishConstraint( QPainter* painter, const QStyleOptionGraphicsItem& opt, const QPointF& start, const QPointF& end, const Constraint &constraint )
{
    Q_UNUSED( opt );

    QPen pen;
    QVariant dataPen;

    // default pens
    if ( start.x() <= end.x() ) {
        pen = QPen( Qt::black );
        dataPen = constraint.data( Constraint::ValidConstraintPen );
    } else {
        pen = QPen( Qt::red );
        dataPen = constraint.data( Constraint::InvalidConstraintPen );
    }

    // data() pen
    if( qVariantCanConvert< QPen >( dataPen ) )
        pen = qVariantValue< QPen >( dataPen );

    painter->setPen( pen );
    painter->setBrush( pen.color() );

    QPointF e = end;
    if ( constraint.endIndex().data( KDGantt::ItemTypeRole ).toInt() == KDGantt::TypeEvent ) {
        e.setX( e.x() + TURN );
    }
    painter->drawPolyline( startFinishLine( start, e ) );
    painter->drawPolygon( startFinishArrow( start, e ) );
}