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 canGraphScene.cpp
24 // \author Benoit Autheman (benoit@libqanava.org)
25 // \date 2005 November 22
26 //-----------------------------------------------------------------------------
30 #include "./qanGraph.h"
31 #include "./qanEdge.h"
32 #include "./qanGraphScene.h"
33 #include "./qanGrid.h"
41 #include <QVBoxLayout>
46 //-----------------------------------------------------------------------------
47 namespace qan
{ // ::qan
50 /* GraphScene Object Management *///-------------------------------------------
52 \param backgroundColor Graph canvas background color.
54 GraphScene::GraphScene( QWidget
* parent
, QColor backgroundColor
, QSize size
) :
55 QGraphicsScene( parent
)
60 GraphScene::~GraphScene( )
62 _styleManager
.clear( );
64 //-----------------------------------------------------------------------------
68 /* Scene Management *///-------------------------------------------------------
69 /*! Styles registered in the style manager are not cleared, and can be reused when this
70 model will receive new edges and noeds.
72 void GraphScene::clear( )
74 // Clear all graphics items in the graphic view
75 foreach ( QGraphicsItem
* item
, _edgeGraphicItemMap
.values( ) )
77 foreach ( AbstractNodeItem
* item
, _nodeGraphicItemMap
.values( ) )
78 removeItem( item
->getGraphicsItem( ) );
81 _nodeGraphicItemMap
.clear( );
82 _edgeGraphicItemMap
.clear( );
85 VectorF
GraphScene::getBoundingBox( const Node::List
& nodes
)
91 Node::List::const_iterator nodeIter
= nodes
.begin( );
92 for ( ; nodeIter
!= nodes
.end( ); nodeIter
++ )
94 const Node
* node
= *nodeIter
;
95 const VectorF
& position
= node
->getPosition( );
96 const VectorF
& dimension
= node
->getDimension( );
98 if ( position( 0 ) + dimension( 0 ) > bbox( 0 ) )
99 bbox( 0 ) = position( 0 ) + dimension( 0 );
100 if ( position( 1 ) + dimension( 1 ) > bbox( 1 ) )
101 bbox( 1 ) = position( 1 ) + dimension( 1 );
106 void GraphScene::updatePositions( Node
* except
)
108 // Update all nodes positions
109 NodeGraphicItemMap::iterator nodeIter
= _nodeGraphicItemMap
.begin( );
110 for ( ; nodeIter
!= _nodeGraphicItemMap
.end( ); nodeIter
++ )
112 const Node
* node
= nodeIter
.key( );
113 AbstractNodeItem
* item
= nodeIter
.value( );
114 if ( node
!= 0 && item
!= 0 && node
!= except
)
116 item
->getGraphicsItem( )->setPos( node
->getPosition( )( 0 ), node
->getPosition( )( 1 ) );
117 item
->updateEdges( );
121 //-----------------------------------------------------------------------------
125 /* Style Management *///-------------------------------------------------------
126 void GraphScene::applyStyle( void* item
, Style
* style
)
128 if ( item
!= 0 && style
!= 0 )
130 _styleManager
.setStyle( item
, *style
);
131 updateStyle( item
, style
);
135 void GraphScene::updateStyle( void* item
, Style
* style
)
137 // Update node graphic item with the style content
138 NodeGraphicItemMap::const_iterator nodeIter
= _nodeGraphicItemMap
.find( reinterpret_cast< Node
* >( item
) );
139 if ( nodeIter
!= _nodeGraphicItemMap
.end( ) )
141 AbstractNodeItem
* item
= nodeIter
.value( );
142 item
->setStyle( style
);
144 EdgeGraphicItemMap::const_iterator edgeIter
= _edgeGraphicItemMap
.find( reinterpret_cast< Edge
* >( item
) );
145 if ( edgeIter
!= _edgeGraphicItemMap
.end( ) )
147 GraphItem
* item
= edgeIter
.value( );
148 item
->setStyle( style
);
151 //-----------------------------------------------------------------------------
155 /* Scene Topology Management *///----------------------------------------------
156 void GraphScene::init( Node::List
& rootNodes
)
158 // Generate persistent model indexes for all graph nodes
159 Node::List::iterator nodeIter
= rootNodes
.begin( );
160 for ( int row
= 0; nodeIter
!= rootNodes
.end( ); row
++, nodeIter
++ )
164 void GraphScene::edgeInserted( qan::Edge
& edge
)
169 void GraphScene::edgeRemoved( qan::Edge
& edge
)
174 void GraphScene::nodeInserted( qan::Node
& node
)
179 void GraphScene::nodeRemoved( qan::Node
& node
)
181 QGraphicsItem
* nodeItem
= getNodeGraphicItem( &node
);
185 std::copy( node
.getInEdges( ).begin( ), node
.getInEdges( ).end( ), std::back_insert_iterator
< Edge::List
>( edges
) );
186 std::copy( node
.getOutEdges( ).begin( ), node
.getOutEdges( ).end( ), std::back_insert_iterator
< Edge::List
>( edges
) );
187 for ( Edge::List::iterator edgeIter
= edges
.begin( ); edgeIter
!= edges
.end( ); edgeIter
++ )
189 EdgeGraphicItemMap::iterator canvasEdgeIter
= _edgeGraphicItemMap
.find( *edgeIter
);
190 if ( canvasEdgeIter
!= _edgeGraphicItemMap
.end( ) )
192 ( canvasEdgeIter
.value( ) )->disconnectEdge( );
193 _edgeGraphicItemMap
.remove( *edgeIter
);
197 _nodeGraphicItemMap
.remove( &node
);
202 void GraphScene::nodeChanged( qan::Node
& node
)
204 NodeItem
* nodeItem
= static_cast< NodeItem
* >( getNodeGraphicItem( &node
) );
206 nodeItem
->updateItem( );
209 void GraphScene::visit( qan::Node
& node
)
211 if ( _nodeGraphicItemMap
.find( &node
) != _nodeGraphicItemMap
.end( ) )
216 Edge::List
& edgeList
= node
.getOutEdges( );
217 for ( Edge::List::iterator edgeIter
= edgeList
.begin( ); edgeIter
!= edgeList
.end( ); edgeIter
++ )
219 Edge
* edge
= *edgeIter
;
220 visit( edge
->getDst( ) );
224 void GraphScene::insertNode( qan::Node
& node
)
226 // Map a graphic item to a graph node
227 AbstractNodeItem
* nodeItem
= createNodeItem( node
, 0, QPoint( 1, 1 ), node
.getLabel( ) );
229 _nodeGraphicItemMap
.insert( &node
, nodeItem
);
231 // Generate arrows for the model
232 Edge::Set edges
= Edge::Set::fromList( node
.getInEdges( ) );
233 edges
.unite( Edge::Set::fromList( node
.getOutEdges( ) ) );
234 foreach ( Edge
* edge
, edges
)
238 void GraphScene::insertEdge( qan::Edge
& edge
)
240 EdgeGraphicItemMap::iterator canvasEdgeIter
= _edgeGraphicItemMap
.find( &edge
);
241 if ( canvasEdgeIter
== _edgeGraphicItemMap
.end( ) )
243 NodeItem
* src
= static_cast< NodeItem
* >( getNodeGraphicItem( &edge
.getSrc( ) ) );
244 NodeItem
* dst
= static_cast< NodeItem
* >( getNodeGraphicItem( &edge
.getDst( ) ) );
245 if ( src
!= 0 && dst
!= 0 )
247 // Get node type associed style
248 Style
* style
= getStyleManager( ).getEmptyStyle( );
249 Style
* edgeStyle
= getStyleManager( ).getStyle( &edge
);
250 if ( edgeStyle
!= 0 )
253 EdgeItem
* edgeItem
= new EdgeItem( getStyleManager( ), style
, 0, this, edge
, src
, dst
);
254 _edgeGraphicItemMap
.insert( &edge
, edgeItem
);
258 canvasEdgeIter
.value( )->show( ); // The arrow might have been previously hiden, so set it visible again
260 //-----------------------------------------------------------------------------
264 /* Model Index and Graphic Item Management *///--------------------------------
265 Node
* GraphScene::getGraphicItemNode( const QGraphicsItem
* item
)
267 return const_cast< Node
* >( _nodeGraphicItemMap
.key( reinterpret_cast< AbstractNodeItem
* >( const_cast< QGraphicsItem
* >( item
) ) ) );
270 QGraphicsItem
* GraphScene::getNodeGraphicItem( const Node
* node
)
274 NodeGraphicItemMap::const_iterator nodeIter
= _nodeGraphicItemMap
.find( node
);
275 if ( nodeIter
!= _nodeGraphicItemMap
.end( ) )
276 return ( nodeIter
.value( ) )->getGraphicsItem( );
280 Node
* GraphScene::getCurrentNode( QPoint
& p
)
282 /*Item::List collisions;
283 //getCanvas( )->getCollisions( p, collisions ); // FIXME
284 if ( collisions.begin( ) != collisions.end( ) )
286 Item* item = *collisions.begin( );
287 //if ( getCanvas( ) != 0 && !getCanvas( )->isFreed( item ) ) // FIXME
288 // return getGraphicItemNode( item );
292 //-----------------------------------------------------------------------------
295 /* Graphic Node Factory Management *///----------------------------------------
296 /*! Ownership for the factory is transfrerred to this graph item view.
297 \param factory Graphic node factory that must be used when generating node graphic counterpart.
299 void GraphScene::registerGraphicNodeFactory( AbstractNodeItem::AbstractFactory
* factory
)
301 assert( factory
!= 0 );
302 if ( factory
->isDefaultFactory( ) )
303 _factories
.push_back( factory
); // Default factories must be tested after standard ones
305 _factories
.push_front( factory
);
309 \return A adequat graphic counterpart for node, or a node from a default factory, or 0 if no (default) factories are registered.
311 AbstractNodeItem
* GraphScene::createNodeItem( Node
& node
, QGraphicsItem
* parent
,
312 QPoint origin
, const QString
& label
)
314 // Get node type associed style
315 Style
* style
= getStyleManager( ).getEmptyStyle( );
316 Style
* nodeStyle
= getStyleManager( ).getStyle( &node
);
317 if ( nodeStyle
!= 0 )
319 nodeStyle
= getStyleManager( ).getStyle( node
.getType( ) );
320 if ( nodeStyle
!= 0 )
323 // Find a factory able to create a grpahic item for my node
324 AbstractNodeItem::AbstractFactory::List::iterator factoryIter
= _factories
.begin( );
325 for ( ; factoryIter
!= _factories
.end( ); factoryIter
++ )
327 AbstractNodeItem::AbstractFactory
* factory
= *factoryIter
;
328 if ( factory
->isDefaultFactory( ) ) // Default factories create graphic node whatever the node type is
329 return factory
->create( node
, getStyleManager( ), parent
, this, style
, origin
, label
);
331 if ( node
.getType( ) == factory
->getNodeType( ) )
332 return factory
->create( node
, getStyleManager( ), parent
, this, style
, origin
, label
);
334 return 0; // No adequat nor default factory found
336 //-----------------------------------------------------------------------------
340 //-----------------------------------------------------------------------------