0.3.1
[qanava.git] / src / qanEdgeItem.cpp
blobf263ed5cfbdca2178284ae34910b6ca936373643
1 /*
2 Qanava - Graph drawing library for QT
3 Copyright (C) 2006 Benoit AUTHEMAN
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //-----------------------------------------------------------------------------
21 // This file is a part of the Qanava software.
23 // \file qanEdgeItem.cpp
24 // \author Benoit Autheman (benoit@libqanava.org)
25 // \date 2007 February 08
26 //-----------------------------------------------------------------------------
29 // Qanava headers
30 #include "./qanNodeItem.h"
31 #include "./qanEdgeItem.h"
34 // QT headers
35 #include <QGraphicsScene>
36 #include <QPainter>
39 namespace qan { // ::qan
42 /* Arrow Constructor/Destructor *///-------------------------------------------
43 EdgeItem::EdgeItem( Style::Manager& styleManager, Style* style, QGraphicsItem* parent, QGraphicsScene* scene,
44 Edge& edge, NodeItem* src, NodeItem* dst ) :
45 GraphItem( styleManager, style ),
46 QGraphicsItem( parent, scene ),
47 _edge( edge ),
48 _src( src ),
49 _dst( dst ),
50 _hasArrow( true ),
51 _arrowSize( 4 ),
52 _lineType( Qt::SolidLine ),
53 _lineWeight( 1 )
55 setZValue( 1. );
57 if ( src != 0 && dst != 0 )
59 src->addEdge( this );
60 dst->addEdge( this );
61 updateItem( );
64 setVisible( true );
67 EdgeItem::~EdgeItem( )
69 // FIXME: segfault with node dtor
70 /*if ( _src != 0 )
71 _src->removeEdge( this );
72 if ( _dst != 0 )
73 _dst->removeEdge( this );*/
76 QRectF EdgeItem::boundingRect( ) const
78 if ( _src == 0 || _dst == 0 )
79 return QRectF( );
81 QPointF src = _src->mapToScene( _src->boundingRect( ).center( ) );
82 QPointF dst = _dst->mapToScene( _dst->boundingRect( ).center( ) );
84 QPointF topLeft( qMin( src.x( ), dst.x( ) ), // tl=(minx, miny)
85 qMin( src.y( ), dst.y( ) ) );
86 QPointF bottomRight( qMax( src.x( ), dst.x( ) ), // br=(maxx, maxy)
87 qMax( src.y( ), dst.y( ) ) );
89 QRectF br( 0., 0., qAbs( bottomRight.x( ) - topLeft.x( ) ), qAbs( bottomRight.y( ) - topLeft.y( ) ) );
91 // Take the text label into account
92 br = br.unite( _labelRect );
94 // Take the arrow into account
95 br.adjust( -_arrowSize, -_arrowSize, _arrowSize, _arrowSize );
97 return br;
100 void EdgeItem::updateItem( )
102 if ( _src == 0 || _dst == 0 )
103 return;
105 QPointF srcF = _src->mapToScene( _src->boundingRect( ).center( ) );
106 QPointF dstF = _dst->mapToScene( _dst->boundingRect( ).center( ) );
107 QPointF topLeft( qMin( srcF.x( ), dstF.x( ) ), // tl=(minx, miny)
108 qMin( srcF.y( ), dstF.y( ) ) );
110 setPos( topLeft ); // setPos should have been called update on the old garbage area ?
112 if ( getStyle( ) != 0 && getStyle( )->has( "linetype" ) )
114 _lineType = Qt::SolidLine;
115 const QVariant& value = getStyle( )->get( "linetype" );
116 if ( value.isValid( ) )
117 _lineType = value.value< int >( );
119 if ( getStyle( ) != 0 && getStyle( )->has( "lineweight" ) )
121 _lineWeight = 1;
122 const QVariant& value = getStyle( )->get( "lineweight" );
123 if ( value.isValid( ) )
124 _lineWeight = value.value< int >( );
126 if ( getStyle( ) != 0 && getStyle( )->has( "arrowsize" ) )
128 _arrowSize = 4;
129 const QVariant& value = getStyle( )->get( "arrowsize" );
130 if ( value.isValid( ) )
131 _arrowSize = value.value< int >( );
134 QGraphicsItem::update( );
137 void EdgeItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget )
139 if ( _src == 0 || _dst == 0 )
140 return;
142 QPointF srcF = _src->mapToScene( _src->boundingRect( ).center( ) );
143 QPointF dstF = _dst->mapToScene( _dst->boundingRect( ).center( ) );
144 QLineF line( mapFromScene( srcF ), mapFromScene( dstF ) );
146 QPen arrowPen( Qt::black, _lineWeight, ( Qt::PenStyle )_lineType, Qt::RoundCap, Qt::RoundJoin );
148 if ( _edge.getLabel( ).length( ) > 0 )
150 QPointF middleF = QPointF( 15., 5. ) + srcF + ( dstF - srcF ) / 2;
151 middleF = mapFromScene( middleF );
152 painter->setPen( QPen( Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
153 _labelRect = painter->boundingRect( QRectF( ), Qt::AlignLeft | Qt::AlignVCenter, _edge.getLabel( ) );
154 _labelRect.translate( middleF ); // Keep the label rect to compute the edge bbox
155 painter->drawText( middleF, _edge.getLabel( ) );
158 if ( _hasArrow )
160 const double Pi = 3.141592653;
161 double TwoPi = 2.0 * Pi;
162 double angle = ::acos( line.dx( ) / line.length( ) );
163 if ( line.dy( ) >= 0 )
164 angle = TwoPi - angle;
166 // Get the intersection between arrow and dst node
167 QRectF br = mapFromItem( _dst, _dst->boundingRect( ) ).boundingRect( );
169 // Test intersection with all borders
170 QLineF top( br.topLeft( ), br.topRight( ) );
171 QLineF right( br.topRight( ), br.bottomRight( ) );
172 QLineF bottom( br.bottomLeft( ), br.bottomRight( ) );
173 QLineF left( br.topLeft( ), br.bottomLeft( ) );
175 QPointF i;
176 if ( line.intersect( top, &i ) == QLineF::BoundedIntersection ||
177 line.intersect( right, &i ) == QLineF::BoundedIntersection ||
178 line.intersect( bottom, &i ) == QLineF::BoundedIntersection ||
179 line.intersect( left, &i ) == QLineF::BoundedIntersection )
181 QLineF shortLine( mapFromScene( srcF ), i );
182 painter->setPen( arrowPen );
183 painter->drawLine( shortLine );
185 painter->setRenderHint( QPainter::Antialiasing );
186 painter->setPen( QPen( Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
187 painter->setBrush( QBrush( QColor( 0, 0, 0 ) ) );
189 double angle = ::acos( line.dx( ) / line.length( ) );
190 if ( line.dy( ) <= 0 )
191 angle = TwoPi - angle;
192 painter->save( );
193 painter->translate( i );
194 painter->rotate( angle * 180. / Pi );
196 double arrowSize = _arrowSize;
197 double arrowLength = _arrowSize * 2.;
198 i = QPointF( -arrowLength - 1., 0. );
199 QPolygonF poly;
200 poly << QPointF( i.x( ), i.y( ) - arrowSize )
201 << QPointF( i.x( ) + arrowLength, i.y( ) )
202 << QPointF( i.x( ), i.y( ) + arrowSize ) << QPointF( i.x( ), i.y( ) - arrowSize );
203 painter->drawPolygon( poly );
204 painter->restore( );
207 else
209 painter->setPen( arrowPen );
210 painter->drawLine( line );
214 void EdgeItem::disconnectEdge( )
216 _src = 0;
217 _dst = 0;
220 void EdgeItem::nodeDestroyed( )
222 disconnectEdge( );
224 //-----------------------------------------------------------------------------
226 } // ::qan