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 canController.cpp
24 // \author Benoit Autheman (benoit@libqanava.org)
25 // \date 2003 August 13
26 //-----------------------------------------------------------------------------
30 #include "./qanController.h"
31 #include "./qanGraphView.h"
39 #include <QResizeEvent>
40 #include <QMouseEvent>
44 namespace qan
{ // ::qan
47 bool Controller::Manager::keyPressEvent( QKeyEvent
* e
)
49 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
51 if ( ( *controllerIter
)->keyPressEvent( e
) )
57 bool Controller::Manager::mousePressEvent( QMouseEvent
* e
)
59 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
61 if ( ( *controllerIter
)->mousePressEvent( e
) )
67 bool Controller::Manager::mouseReleaseEvent( QMouseEvent
* e
)
69 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
71 if ( ( *controllerIter
)->mouseReleaseEvent( e
) )
77 bool Controller::Manager::mouseMoveEvent( QMouseEvent
* e
)
79 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
81 if ( ( *controllerIter
)->mouseMoveEvent( e
) )
87 bool Controller::Manager::mouseDoubleClickEvent( QMouseEvent
* e
)
89 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
91 if ( ( *controllerIter
)->mouseDoubleClickEvent( e
) )
97 bool Controller::Manager::wheelEvent( QWheelEvent
* e
)
99 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
101 if ( ( *controllerIter
)->wheelEvent( e
) )
107 Controller
* Controller::Manager::getController( QString name
)
109 for ( Controller::Manager::iterator controllerIter
= begin( ); controllerIter
!= end( ); controllerIter
++ )
111 if ( ( *controllerIter
)->getName( ) == name
)
112 return ( *controllerIter
);
117 void Controller::Manager::registerController( Controller
* controller
)
119 if ( controller
== 0 )
122 push_back( controller
);
123 QAction
* controllerAction
= controller
->getAction( );
124 if ( controllerAction
->isCheckable( ) )
125 _actionGroup
->addAction( controllerAction
); // Only one checkable action active at a time
128 Controller::Controller( QString name
, GraphView
& GraphView
) :
129 _GraphView( GraphView
),
137 /* PanController Constructor/Destructor *///-----------------------------------
138 PanController::PanController( GraphView
& GraphView
) :
139 Controller( "pan_controller", GraphView
),
140 _keyboardNavigation( true ),
141 _keyboardNavigationIntensity( 10.0 ),
144 QAction
* action
= new QAction( this );
145 action
->setCheckable( true );
146 action
->setText( "Pan" );
147 action
->setVisible( true );
148 action
->setIcon( QIcon( "images/qanava_pan.png" ) );
149 connect( action
, SIGNAL( toggled( bool ) ), this, SLOT( toggled( bool ) ) );
152 setKeyboardNavigation( true );
155 void PanController::toggled( bool state
)
157 setMode( state
? PAN
: NONE
);
159 //-----------------------------------------------------------------------------
163 /* PanController Keyboard Management *///--------------------------------------
164 bool PanController::keyPressEvent( QKeyEvent
* e
)
166 getGraphView( ).setFocusPolicy( Qt::ClickFocus
);
167 if ( getKeyboardNavigation( ) )
172 getGraphView( ).translate( ( int )-_keyboardNavigationIntensity
, 0 );
176 getGraphView( ).translate( 0, ( int )-_keyboardNavigationIntensity
);
180 getGraphView( ).translate( ( int )_keyboardNavigationIntensity
, 0 );
184 getGraphView( ).translate( 0, ( int )_keyboardNavigationIntensity
);
195 /*! To use keyboard navigation, ensure that this widget parent widget has at least a 'Click'
196 focus policy (in Designer or with the QWidget::setFocusPolicy() method).
198 void PanController::setKeyboardNavigation( bool state
)
200 _keyboardNavigation
= state
;
203 getGraphView( ).viewport( )->setFocusPolicy( Qt::StrongFocus
);
204 getGraphView( ).setFocusPolicy( Qt::StrongFocus
);
207 //-----------------------------------------------------------------------------
211 /* PanController Mouse Management *///-----------------------------------------
212 bool PanController::mousePressEvent( QMouseEvent
* e
)
214 // Navigation must not occurs if a node is under the mouse
215 QPointF p
= getGraphView( ).mapToScene( e
->pos( ) );
216 QList
< QGraphicsItem
* > items
= getGraphView( ).scene( )->items( p
);
217 if ( items
.size( ) == 0 )
218 { // TODO: prendre les elements de grille en compte (et tous ceux qui ne sont pas manipulables)
219 if ( getMode( ) == PAN
)
222 getGraphView( ).viewport( )->setCursor( QCursor( Qt::SizeAllCursor
) );
231 bool PanController::mouseReleaseEvent( QMouseEvent
* e
)
233 getGraphView( ).viewport( )->setCursor( QCursor( Qt::ArrowCursor
) );
235 if ( getMode( ) == PAN
&& getState( ) == PANNING
)
236 setState( NONE
); // Stop panning until next click
241 bool PanController::mouseMoveEvent( QMouseEvent
* e
)
243 if ( getMode( ) == PAN
&& getState( ) == PANNING
)
245 QPointF p
= e
->pos( ); // No mapping, we move scrollbars in their coordinate system
246 //QPointF p = getGraphView( ).mapToScene( e->pos( ) );
249 double dx
= ( _start
.x( ) - p
.x( ) ) * accel
;
250 double dy
= ( _start
.y( ) - p
.y( ) ) * accel
;
252 int valueY
= ( int )( getGraphView( ).verticalScrollBar( )->value( ) + dy
);
253 getGraphView( ).verticalScrollBar( )->setValue( valueY
);
254 int valueX
= ( int )( getGraphView( ).horizontalScrollBar( )->value( ) + dx
);
255 getGraphView( ).horizontalScrollBar( )->setValue( valueX
);
262 //-----------------------------------------------------------------------------
266 /* ZoomWindowController Constructor/Destructor *///-------------------------------
267 ZoomWindowController::ZoomWindowController( GraphView
& GraphView
) :
268 Controller( "zoom_window_controller", GraphView
),
272 QAction
* action
= new QAction( this );
273 action
->setCheckable( true );
274 action
->setText( "Zoom Window" );
275 action
->setVisible( true );
276 action
->setIcon( QIcon( "images/qanava_zoomwindow.png" ) );
277 connect( action
, SIGNAL( toggled( bool ) ), this, SLOT( toggled( bool ) ) );
280 _zoomRectItem
= new QGraphicsRectItem( QRectF( 0., 0., 50., 50. ), 0, getGraphView( ).scene( ) );
281 _zoomRectItem
->setZValue( 100. );
283 p
.setStyle( Qt::DotLine
);
285 p
.setColor( QColor( 55, 55, 55 ) );
286 _zoomRectItem
->setPen( p
);
287 _zoomRectItem
->hide( );
290 void ZoomWindowController::toggled( bool state
)
292 setMode( state
? ZOOM
: NONE
);
294 //-----------------------------------------------------------------------------
298 /* ZoomWindowController Zooming Management *///--------------------------------
299 bool ZoomWindowController::mousePressEvent( QMouseEvent
* e
)
301 // Navigation must not occurs if a node is under the mouse
302 QPointF p
= getGraphView( ).mapToScene( e
->pos( ) );
303 QList
< QGraphicsItem
* > items
= getGraphView( ).scene( )->items( p
);
304 if ( items
.size( ) == 0 )
305 { // TODO: prendre les elements de grille en compte (et tous ceux qui ne sont pas manipulables)
306 if ( getMode( ) == ZOOM
)
308 _start
= getGraphView( ).mapToScene( e
->pos( ) );
317 bool ZoomWindowController::mouseReleaseEvent( QMouseEvent
* e
)
319 if ( getMode( ) == ZOOM
&& getState( ) == ZOOMING
)
321 getGraphView( ).fitInView( _zoomRectItem
->rect( ), Qt::KeepAspectRatioByExpanding
);
322 _zoomRectItem
->hide( );
323 setState( NONE
); // Stop zooming until next click
330 bool ZoomWindowController::mouseMoveEvent( QMouseEvent
* e
)
332 if ( getMode( ) == ZOOM
&& getState( ) == ZOOMING
&& _zoomRectItem
!= 0 )
334 QPointF p
= getGraphView( ).mapToScene( e
->pos( ) );
336 QRectF
r( _start
.x( ), _start
.y( ),
337 p
.x( ) - _start
.x( ), p
.y( ) - _start
.y( ) );
338 _zoomRectItem
->setRect( r
);
339 _zoomRectItem
->show( );
344 //-----------------------------------------------------------------------------
348 /* ZoomController Constructor/Destructor *///----------------------------------
349 ZoomController::ZoomController( GraphView
& GraphView
) :
350 Controller( "zoom_controller", GraphView
),
351 _actionZoomIn( new QAction( this ) ),
352 _actionZoomOut( new QAction( this ) )
354 QAction
* action
= new QAction( this );
355 action
->setCheckable( true );
356 action
->setText( "Zoom" );
357 action
->setVisible( true );
358 action
->setIcon( QIcon( "images/qanava_zoom.png" ) );
361 _actionZoomIn
->setText( "Zoom In" );
362 _actionZoomIn
->setVisible( true );
363 _actionZoomIn
->setIcon( QIcon( "images/qanava_zoomin.png" ) );
364 connect( _actionZoomIn
, SIGNAL( triggered( bool ) ), this, SLOT( zoomIn( bool ) ) );
366 _actionZoomOut
->setText( "Zoom Out" );
367 _actionZoomOut
->setVisible( true );
368 _actionZoomOut
->setIcon( QIcon( "images/qanava_zoomout.png" ) );
369 connect( _actionZoomOut
, SIGNAL( triggered( bool ) ), this, SLOT( zoomOut( bool ) ) );
371 //-----------------------------------------------------------------------------
375 /* ZoomController Zooming Management *///--------------------------------------
376 void ZoomController::zoomIn( bool state
)
378 getGraphView( ).setZoom( getGraphView( ).getZoom( ) + 0.2 );
381 void ZoomController::zoomOut( bool state
)
383 getGraphView( ).setZoom( getGraphView( ).getZoom( ) - 0.2 );
386 bool ZoomController::wheelEvent( QWheelEvent
* e
)
391 QAction
* ZoomController::getAction( QString name
)
393 if ( name
== "zoom_in" )
394 return _actionZoomIn
;
395 else if ( name
== "zoom_out" )
396 return _actionZoomOut
;
400 //-----------------------------------------------------------------------------
404 /* Selection Controller Management *///------------------------------------------
405 /*SelectionController::SelectionController( GraphView& GraphView ) :
406 Controller( GraphView )
410 bool SelectionController::mouseDoubleClickEvent( QMouseEvent* e )
413 /* QPointF p = getGraphView( ).mapToScene( e->pos( ) );
414 Item::List collisions;
415 getGraphView( ).getCanvas( )->getCollisions( p, collisions );
416 for ( Item::List::iterator itemIter = collisions.begin( ); itemIter != collisions.end( ); itemIter++ )
418 Item* item = *itemIter;
419 if ( getGraphView( ).getCanvas( )->isFreed( item ) )
422 Node* node = getGraphView( ).getGraphicItemNode( item );
424 emit nodeSelected( node, p );
429 //-----------------------------------------------------------------------------
433 /* Tooltip Controller Management *///--------------------------------------------
434 /*TooltipController::TooltipController( GraphView& GraphView ) :
435 Controller( GraphView ),
440 _timer = new QTimer( this );
441 connect( _timer, SIGNAL( timeout( ) ), SLOT( tipTimeout( ) ) );
444 /*void TooltipController::tipTimeout( )
447 // Don't show tooltips in case of error or if another controller is already active
448 /* if ( _tipItem == 0 || getGraphView( ).getControllerManager( ).isControllerActive( ) )
454 // Test if the mouse is still on the item that has started the tooltip demand (tooltip delay) milliseconds ago
455 Item::List collisions;
456 getGraphView( ).getCanvas( )->getCollisions( _tipPos, collisions );
457 for ( Item::List::iterator itemIter = collisions.begin( ); itemIter != collisions.end( ); itemIter++ )
459 Item* item = *itemIter;
461 if ( item == _tipItem )
463 Node* node = getGraphView( ).getGraphicItemNode( _tipItem );
466 // Compute the real screen viewport coordinates
467 QPoint viewportTipPosContent = getGraphView( ).mapFromCanvas( _tipPos );
468 emit nodeTipped( node, getGraphView( ).viewport( )->mapToGlobal( viewportTipPosContent ) );
476 //bool TooltipController::mouseMoveEvent( QMouseEvent* e )
479 /* QPointF p = getGraphView( ).mapToScene( e->pos( ) );
482 // If no button is pressed, there is no manipulation or navigation operation going on, so tooltip can be displayed
483 if ( e->button() != Qt::LeftButton )
485 Item::List collisions;
486 getGraphView( ).getCanvas( )->getCollisions( _tipPos, collisions );
487 for ( Item::List::iterator itemIter = collisions.begin( ); itemIter != collisions.end( ); itemIter++ )
489 Item* item = *itemIter;
490 if ( item == _tipItem && _timer->isActive( ) ) // Avoid the timer to be restarted when moving in the same item
494 if ( getGraphView( ).getCanvas( )->isFreed( item ) )
497 Node* node = getGraphView( ).getGraphicItemNode( item );
500 _timer->start( 800 );
504 break; // Take just the first intersecting item to avoid deep z selection
509 // There is a complex navigation or manipulation operation going on, don't display tooltips
517 //bool TooltipController::mouseDoubleClickEvent( QMouseEvent* e )
519 // Avoid interference with other controllers (such as simultaneous tip and double click node selection)
525 //-----------------------------------------------------------------------------