2007-12-01 10:47:15 +00:00
/*
2015-02-20 14:56:22 +00:00
Copyright 2006 - 2015 The QElectroTech Team
2007-12-01 10:47:15 +00:00
This file is part of QElectroTech .
QElectroTech 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 .
QElectroTech 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 QElectroTech . If not , see < http : //www.gnu.org/licenses/>.
*/
2007-01-29 20:14:26 +00:00
# include "terminal.h"
2007-01-29 00:41:12 +00:00
# include "diagram.h"
2013-11-14 10:11:22 +00:00
# include "qetgraphicsitem/element.h"
# include "qetgraphicsitem/conductor.h"
2007-09-25 23:24:36 +00:00
# include "diagramcommands.h"
2008-02-25 18:28:19 +00:00
# include "qetapp.h"
2015-01-09 17:18:16 +00:00
# include "conductorautonumerotation.h"
2006-10-27 15:47:22 +00:00
2010-04-18 20:48:15 +00:00
QColor Terminal : : neutralColor = QColor ( Qt : : blue ) ;
QColor Terminal : : allowedColor = QColor ( Qt : : darkGreen ) ;
QColor Terminal : : warningColor = QColor ( " #ff8000 " ) ;
QColor Terminal : : forbiddenColor = QColor ( Qt : : red ) ;
2007-10-10 22:35:32 +00:00
const qreal Terminal : : terminalSize = 4.0 ;
2007-06-30 17:41:07 +00:00
2006-10-27 15:47:22 +00:00
/**
2010-04-18 20:48:15 +00:00
Methode privee pour initialiser la borne .
2006-10-27 15:47:22 +00:00
@ param pf position du point d ' amarrage pour un conducteur
@ param o orientation de la borne : Qt : : Horizontal ou Qt : : Vertical
2013-11-16 16:53:46 +00:00
@ param number of terminal
@ param name of terminal
2006-10-27 15:47:22 +00:00
*/
2014-05-29 13:46:04 +00:00
void Terminal : : init ( QPointF pf , Qet : : Orientation o , QString number , QString name , bool hiddenName ) {
2006-10-27 15:47:22 +00:00
// definition du pount d'amarrage pour un conducteur
2010-04-18 20:48:15 +00:00
dock_conductor_ = pf ;
2006-10-27 15:47:22 +00:00
2010-04-18 20:48:15 +00:00
// definition de l'orientation de la borne (par defaut : sud)
2014-05-29 13:46:04 +00:00
if ( o < Qet : : North | | o > Qet : : West ) ori_ = Qet : : South ;
2010-04-18 20:48:15 +00:00
else ori_ = o ;
2006-10-27 15:47:22 +00:00
// calcul de la position du point d'amarrage a l'element
2010-04-18 20:48:15 +00:00
dock_elmt_ = dock_conductor_ ;
switch ( ori_ ) {
2014-05-29 13:46:04 +00:00
case Qet : : North : dock_elmt_ + = QPointF ( 0 , Terminal : : terminalSize ) ; break ;
case Qet : : East : dock_elmt_ + = QPointF ( - Terminal : : terminalSize , 0 ) ; break ;
case Qet : : West : dock_elmt_ + = QPointF ( Terminal : : terminalSize , 0 ) ; break ;
case Qet : : South :
2010-04-18 20:48:15 +00:00
default : dock_elmt_ + = QPointF ( 0 , - Terminal : : terminalSize ) ;
2006-10-27 15:47:22 +00:00
}
2013-11-12 18:43:59 +00:00
// Number of terminal
number_terminal_ = number ;
2013-11-16 16:53:46 +00:00
// Name of terminal
name_terminal_ = name ;
name_terminal_hidden = hiddenName ;
2006-10-27 15:47:22 +00:00
// par defaut : pas de conducteur
// QRectF null
2010-04-18 20:48:15 +00:00
br_ = new QRectF ( ) ;
previous_terminal_ = 0 ;
2006-10-27 15:47:22 +00:00
// divers
2015-03-02 20:14:56 +00:00
setAcceptHoverEvents ( true ) ;
2006-10-27 15:47:22 +00:00
setAcceptedMouseButtons ( Qt : : LeftButton ) ;
2010-04-18 20:48:15 +00:00
hovered_ = false ;
2009-04-03 19:30:25 +00:00
setToolTip ( QObject : : tr ( " Borne " , " tooltip " ) ) ;
2006-10-27 15:47:22 +00:00
}
/**
initialise une borne
@ param pf position du point d ' amarrage pour un conducteur
@ param o orientation de la borne : Qt : : Horizontal ou Qt : : Vertical
@ param e Element auquel cette borne appartient
@ param s Scene sur laquelle figure cette borne
*/
2014-12-14 13:06:21 +00:00
Terminal : : Terminal ( QPointF pf , Qet : : Orientation o , Element * e ) :
QGraphicsItem ( e ) ,
2015-01-07 19:21:17 +00:00
m_draw_help_line ( false ) ,
m_help_line ( nullptr ) ,
2015-01-18 11:28:56 +00:00
m_help_line_a ( nullptr ) ,
2015-01-07 19:21:17 +00:00
parent_element_ ( e ) ,
hovered_color_ ( Terminal : : neutralColor )
2007-06-30 17:41:07 +00:00
{
2013-11-16 16:53:46 +00:00
init ( pf , o , " _ " , " _ " , false ) ;
2006-10-27 15:47:22 +00:00
}
/**
initialise une borne
@ param pf_x Abscisse du point d ' amarrage pour un conducteur
@ param pf_y Ordonnee du point d ' amarrage pour un conducteur
@ param o orientation de la borne : Qt : : Horizontal ou Qt : : Vertical
@ param e Element auquel cette borne appartient
@ param s Scene sur laquelle figure cette borne
*/
2014-12-14 13:06:21 +00:00
Terminal : : Terminal ( qreal pf_x , qreal pf_y , Qet : : Orientation o , Element * e ) :
QGraphicsItem ( e ) ,
2015-01-07 19:21:17 +00:00
m_draw_help_line ( false ) ,
m_help_line ( nullptr ) ,
2015-01-18 11:28:56 +00:00
m_help_line_a ( nullptr ) ,
2015-01-07 19:21:17 +00:00
parent_element_ ( e ) ,
hovered_color_ ( Terminal : : neutralColor )
2007-06-30 17:41:07 +00:00
{
2013-11-16 16:53:46 +00:00
init ( QPointF ( pf_x , pf_y ) , o , " _ " , " _ " , false ) ;
2013-11-13 11:55:27 +00:00
}
/**
initialise une borne
@ param pf position du point d ' amarrage pour un conducteur
@ param o orientation de la borne : Qt : : Horizontal ou Qt : : Vertical
@ param num number of terminal ( ex 3 - 4 for NO )
2013-11-16 16:53:46 +00:00
@ param name of terminal
@ param hiddenName hide or show the name
2013-11-13 11:55:27 +00:00
@ param e Element auquel cette borne appartient
@ param s Scene sur laquelle figure cette borne
*/
2014-12-14 13:06:21 +00:00
Terminal : : Terminal ( QPointF pf , Qet : : Orientation o , QString num , QString name , bool hiddenName , Element * e ) :
2015-01-18 11:28:56 +00:00
QGraphicsItem ( e ) ,
m_draw_help_line ( false ) ,
m_help_line ( nullptr ) ,
m_help_line_a ( nullptr ) ,
parent_element_ ( e ) ,
hovered_color_ ( Terminal : : neutralColor )
2013-11-13 11:55:27 +00:00
{
2013-11-16 16:53:46 +00:00
init ( pf , o , num , name , hiddenName ) ;
2006-10-27 15:47:22 +00:00
}
/**
Destructeur
2007-04-12 03:13:13 +00:00
La destruction de la borne entraine la destruction des conducteurs
associes .
2006-10-27 15:47:22 +00:00
*/
2007-01-29 20:14:26 +00:00
Terminal : : ~ Terminal ( ) {
2010-04-18 20:48:15 +00:00
foreach ( Conductor * c , conductors_ ) delete c ;
delete br_ ;
2006-10-27 15:47:22 +00:00
}
/**
Permet de connaitre l ' orientation de la borne . Si le parent de la borne
est bien un Element , cette fonction renvoie l ' orientation par rapport a
la scene de la borne , en tenant compte du fait que l ' element ait pu etre
pivote . Sinon elle renvoie son sens normal .
2007-01-29 20:14:26 +00:00
@ return L ' orientation actuelle de la Terminal .
2006-10-27 15:47:22 +00:00
*/
2014-05-29 13:46:04 +00:00
Qet : : Orientation Terminal : : orientation ( ) const {
2006-10-27 15:47:22 +00:00
if ( Element * elt = qgraphicsitem_cast < Element * > ( parentItem ( ) ) ) {
2006-11-09 19:19:51 +00:00
// orientations actuelle et par defaut de l'element
2013-11-14 10:11:22 +00:00
int ori_cur = elt - > orientation ( ) ;
if ( ori_cur = = 0 ) return ( ori_ ) ;
2006-10-27 15:47:22 +00:00
else {
2007-01-20 18:11:42 +00:00
// calcul l'angle de rotation implique par l'orientation de l'element parent
2006-11-09 19:19:51 +00:00
// angle de rotation de la borne sur la scene, divise par 90
2013-11-14 10:11:22 +00:00
int angle = ori_cur + ori_ ;
2006-11-09 19:19:51 +00:00
while ( angle > = 4 ) angle - = 4 ;
2014-05-29 13:46:04 +00:00
return ( ( Qet : : Orientation ) angle ) ;
2006-10-27 15:47:22 +00:00
}
2010-04-18 20:48:15 +00:00
} else return ( ori_ ) ;
2006-10-27 15:47:22 +00:00
}
2013-11-13 11:55:27 +00:00
/**
* @ brief Terminal : : setNumber
* @ param number
*/
void Terminal : : setNumber ( QString number ) {
number_terminal_ = number ;
}
2013-11-16 16:53:46 +00:00
/**
* @ brief Terminal : : setName
* @ param name
*/
void Terminal : : setName ( QString name , bool hiddenName ) {
name_terminal_ = name ;
name_terminal_hidden = hiddenName ;
}
2006-10-27 15:47:22 +00:00
/**
2007-10-03 17:02:39 +00:00
Attribue un conductor a la borne
2006-10-27 15:47:22 +00:00
@ param f Le conducteur a rattacher a cette borne
*/
2007-10-03 17:02:39 +00:00
bool Terminal : : addConductor ( Conductor * f ) {
2006-10-27 15:47:22 +00:00
// pointeur 0 refuse
if ( ! f ) return ( false ) ;
// une seule des deux bornes du conducteur doit etre this
2008-07-30 12:44:57 +00:00
Q_ASSERT_X ( ( ( f - > terminal1 = = this ) ^ ( f - > terminal2 = = this ) ) , " Terminal::addConductor " , " Le conductor devrait etre relie exactement une fois a la terminal en cours " ) ;
2006-10-27 15:47:22 +00:00
// determine l'autre borne a laquelle cette borne va etre relie grace au conducteur
2007-01-29 20:14:26 +00:00
Terminal * autre_terminal = ( f - > terminal1 = = this ) ? f - > terminal2 : f - > terminal1 ;
2006-10-27 15:47:22 +00:00
// verifie que la borne n'est pas deja reliee avec l'autre borne
bool deja_liees = false ;
2010-04-18 20:48:15 +00:00
foreach ( Conductor * conductor , conductors_ ) {
2007-10-03 17:02:39 +00:00
if ( conductor - > terminal1 = = autre_terminal | | conductor - > terminal2 = = autre_terminal ) deja_liees = true ;
2006-10-27 15:47:22 +00:00
}
// si les deux bornes sont deja reliees, on refuse d'ajouter le conducteur
if ( deja_liees ) return ( false ) ;
// sinon on ajoute le conducteur
2010-04-18 20:48:15 +00:00
conductors_ . append ( f ) ;
2006-10-27 15:47:22 +00:00
return ( true ) ;
}
2007-04-09 02:56:47 +00:00
/**
Enleve un conducteur donne a la borne
@ param f Conducteur a enlever
*/
2007-10-03 17:02:39 +00:00
void Terminal : : removeConductor ( Conductor * f ) {
2010-04-18 20:48:15 +00:00
int index = conductors_ . indexOf ( f ) ;
2006-10-27 15:47:22 +00:00
if ( index = = - 1 ) return ;
2010-04-18 20:48:15 +00:00
conductors_ . removeAt ( index ) ;
2006-10-27 15:47:22 +00:00
}
/**
Fonction de dessin des bornes
@ param p Le QPainter a utiliser
@ param options Les options de dessin
@ param widget Le widget sur lequel on dessine
*/
2007-10-11 12:34:53 +00:00
void Terminal : : paint ( QPainter * p , const QStyleOptionGraphicsItem * options , QWidget * widget ) {
2009-04-05 11:48:26 +00:00
// en dessous d'un certain zoom, les bornes ne sont plus dessinees
if ( options & & options - > levelOfDetail < 0.5 ) return ;
2006-10-27 15:47:22 +00:00
p - > save ( ) ;
2015-03-02 20:14:56 +00:00
# ifndef Q_OS_WIN
2007-10-11 12:34:53 +00:00
// corrige un bug de rendu ne se produisant que lors du rendu sur QGraphicsScene sous X11 au zoom par defaut
2008-08-23 10:55:37 +00:00
static bool must_correct_rendering_bug = QETApp : : settings ( ) . value ( " correct-rendering " , false ) . toBool ( ) ;
2007-10-11 12:34:53 +00:00
if ( must_correct_rendering_bug ) {
Diagram * dia = diagram ( ) ;
if ( dia & & options - > levelOfDetail = = 1.0 & & widget ) {
// calcule la rotation qu'a subi l'element
qreal applied_rotation = 0.0 ;
if ( Element * elt = qgraphicsitem_cast < Element * > ( parentItem ( ) ) ) {
// orientations actuelle et par defaut de l'element
2013-11-14 10:11:22 +00:00
int ori_cur = elt - > orientation ( ) ;
applied_rotation = QET : : correctAngle ( 90.0 * ori_cur ) ;
2007-10-11 12:34:53 +00:00
}
if ( applied_rotation = = 90.0 ) p - > translate ( 1.0 , - 1.0 ) ;
else if ( applied_rotation = = 180.0 ) p - > translate ( - 1.0 , - 1.0 ) ;
else if ( applied_rotation = = 270.0 ) p - > translate ( - 1.0 , 1.0 ) ;
}
}
# endif
2006-10-27 15:47:22 +00:00
//annulation des renderhints
p - > setRenderHint ( QPainter : : Antialiasing , false ) ;
p - > setRenderHint ( QPainter : : TextAntialiasing , false ) ;
p - > setRenderHint ( QPainter : : SmoothPixmapTransform , false ) ;
// on travaille avec les coordonnees de l'element parent
2010-04-18 20:48:15 +00:00
QPointF c = mapFromParent ( dock_conductor_ ) ;
QPointF e = mapFromParent ( dock_elmt_ ) ;
2006-10-27 15:47:22 +00:00
QPen t ;
t . setWidthF ( 1.0 ) ;
2009-04-05 11:48:26 +00:00
if ( options & & options - > levelOfDetail < 1.0 ) {
t . setCosmetic ( true ) ;
}
2006-10-27 15:47:22 +00:00
// dessin de la borne en rouge
t . setColor ( Qt : : red ) ;
p - > setPen ( t ) ;
2010-04-18 20:48:15 +00:00
p - > drawLine ( c , e ) ;
2006-10-27 15:47:22 +00:00
// dessin du point d'amarrage au conducteur en bleu
2010-04-18 20:48:15 +00:00
t . setColor ( hovered_color_ ) ;
2006-10-27 15:47:22 +00:00
p - > setPen ( t ) ;
2010-04-18 20:48:15 +00:00
p - > setBrush ( hovered_color_ ) ;
if ( hovered_ ) {
2007-02-14 01:08:29 +00:00
p - > setRenderHint ( QPainter : : Antialiasing , true ) ;
2010-04-18 20:48:15 +00:00
p - > drawEllipse ( QRectF ( c . x ( ) - 2.5 , c . y ( ) - 2.5 , 5.0 , 5.0 ) ) ;
} else p - > drawPoint ( c ) ;
2015-01-07 19:21:17 +00:00
2015-01-18 11:28:56 +00:00
//Draw help line if needed,
if ( diagram ( ) & & m_draw_help_line )
2015-01-07 19:21:17 +00:00
{
2015-01-18 11:28:56 +00:00
//Draw the help line with same orientation of terminal
//Only if there isn't docked conductor
if ( conductors ( ) . isEmpty ( ) )
{
if ( ! m_help_line )
m_help_line = new QGraphicsLineItem ( this ) ;
2015-01-19 12:13:27 +00:00
QPen pen ;
pen . setColor ( Qt : : darkBlue ) ;
2015-01-07 19:21:17 +00:00
2015-01-18 11:28:56 +00:00
QLineF line ( HelpLine ( ) ) ;
2015-01-07 19:21:17 +00:00
2015-01-18 11:28:56 +00:00
if ( diagram ( ) - > project ( ) - > autoConductor ( ) )
2015-01-11 11:10:57 +00:00
{
Terminal * t = alignedWithTerminal ( ) ;
if ( t )
{
line . setP2 ( t - > dockConductor ( ) ) ;
2015-01-18 11:28:56 +00:00
pen . setColor ( Qt : : darkGreen ) ;
2015-01-11 11:10:57 +00:00
}
}
2015-01-18 11:28:56 +00:00
//Map the line (in scene coordinate) to m_help_line coordinate
line . setP1 ( m_help_line - > mapFromScene ( line . p1 ( ) ) ) ;
line . setP2 ( m_help_line - > mapFromScene ( line . p2 ( ) ) ) ;
m_help_line - > setPen ( pen ) ;
m_help_line - > setLine ( line ) ;
}
//Draw the help line perpendicular to the terminal
if ( ! m_help_line_a )
{
m_help_line_a = new QGraphicsLineItem ( this ) ;
QPen pen ;
2015-06-28 12:37:10 +00:00
pen . setColor ( Diagram : : background_color = = Qt : : darkGray ? Qt : : lightGray : Qt : : darkGray ) ;
2015-01-18 11:28:56 +00:00
m_help_line_a - > setPen ( pen ) ;
2015-01-07 19:21:17 +00:00
}
2015-03-18 18:07:18 +00:00
QRectF rect = diagram ( ) - > border_and_titleblock . insideBorderRect ( ) ;
2015-01-18 11:28:56 +00:00
QLineF line ;
if ( Qet : : isHorizontal ( orientation ( ) ) )
{
line . setP1 ( QPointF ( dockConductor ( ) . x ( ) , rect . topLeft ( ) . y ( ) ) ) ;
line . setP2 ( QPointF ( dockConductor ( ) . x ( ) , rect . bottomLeft ( ) . y ( ) ) ) ;
}
else
{
line . setP1 ( QPointF ( rect . topLeft ( ) . x ( ) , dockConductor ( ) . y ( ) ) ) ;
line . setP2 ( QPointF ( rect . topRight ( ) . x ( ) , dockConductor ( ) . y ( ) ) ) ;
}
//Map the line (in scene coordinate) to m_help_line_a coordinate
line . setP1 ( m_help_line_a - > mapFromScene ( line . p1 ( ) ) ) ;
line . setP2 ( m_help_line_a - > mapFromScene ( line . p2 ( ) ) ) ;
m_help_line_a - > setLine ( line ) ;
2015-01-07 19:21:17 +00:00
}
2015-01-19 00:12:05 +00:00
2006-10-27 15:47:22 +00:00
p - > restore ( ) ;
}
2015-01-07 19:21:17 +00:00
/**
* @ brief Terminal : : drawHelpLine
* @ param draw : true , display the help line
* false , hide it .
*/
void Terminal : : drawHelpLine ( bool draw )
{
if ( m_draw_help_line = = draw ) return ;
m_draw_help_line = draw ;
2015-01-18 11:28:56 +00:00
if ( ! draw )
2015-01-07 19:21:17 +00:00
{
2015-01-18 11:28:56 +00:00
if ( m_help_line )
{
delete m_help_line ;
m_help_line = nullptr ;
}
if ( m_help_line_a )
{
delete m_help_line_a ;
m_help_line_a = nullptr ;
}
2015-01-07 19:21:17 +00:00
}
}
/**
* @ brief Terminal : : HelpLine
* @ return a line with coordinate P1 the dock point of conductor
* and P2 the border of diagram , according to the orientation of terminal
* The line is in scene coordinate ;
*/
QLineF Terminal : : HelpLine ( ) const
{
QPointF scene_dock = dockConductor ( ) ;
2015-03-18 18:07:18 +00:00
QRectF rect = diagram ( ) - > border_and_titleblock . insideBorderRect ( ) ;
2015-01-07 19:21:17 +00:00
QLineF line ( scene_dock , QPointF ( ) ) ;
//Set te second point of line to the edge of diagram,
//according with the orientation of this terminal
switch ( orientation ( ) )
{
case Qet : : North :
line . setP2 ( QPointF ( scene_dock . x ( ) , rect . top ( ) ) ) ;
break ;
case Qet : : East :
line . setP2 ( QPointF ( rect . right ( ) , scene_dock . y ( ) ) ) ;
break ;
case Qet : : South :
line . setP2 ( QPointF ( scene_dock . x ( ) , rect . bottom ( ) ) ) ;
break ;
case Qet : : West :
line . setP2 ( QPointF ( rect . left ( ) , scene_dock . y ( ) ) ) ;
break ;
}
return line ;
}
2006-10-27 15:47:22 +00:00
/**
@ return Le rectangle ( en precision flottante ) delimitant la borne et ses alentours .
*/
2007-01-29 20:14:26 +00:00
QRectF Terminal : : boundingRect ( ) const {
2010-04-18 20:48:15 +00:00
if ( br_ - > isNull ( ) ) {
qreal dcx = dock_conductor_ . x ( ) ;
qreal dcy = dock_conductor_ . y ( ) ;
qreal dex = dock_elmt_ . x ( ) ;
qreal dey = dock_elmt_ . y ( ) ;
QPointF origin = ( dcx < = dex & & dcy < = dey ? dock_conductor_ : dock_elmt_ ) ;
origin + = QPointF ( - 3.0 , - 3.0 ) ;
qreal w = qAbs ( ( int ) ( dcx - dex ) ) + 7 ;
qreal h = qAbs ( ( int ) ( dcy - dey ) ) + 7 ;
* br_ = QRectF ( origin , QSizeF ( w , h ) ) ;
2006-10-27 15:47:22 +00:00
}
2010-04-18 20:48:15 +00:00
return ( * br_ ) ;
2006-10-27 15:47:22 +00:00
}
2015-01-07 19:21:17 +00:00
/**
* @ brief Terminal : : alignedWithTerminal
* If this terminal is aligned with an other terminal
* and is orientation is opposed return the other terminal
* else return nullptr
* @ return
*/
Terminal * Terminal : : alignedWithTerminal ( ) const
{
QLineF line ( HelpLine ( ) ) ;
QPainterPath path ;
path . moveTo ( line . p1 ( ) ) ;
path . lineTo ( line . p2 ( ) ) ;
//Get all QGraphicsItem in the alignement of this terminal
QList < QGraphicsItem * > qgi_list = diagram ( ) - > items ( path ) ;
//Remove all terminals of the parent element
foreach ( Terminal * t , parent_element_ - > terminals ( ) )
qgi_list . removeAll ( t ) ;
if ( qgi_list . isEmpty ( ) ) return nullptr ;
//Get terminals only if orientation is opposed with this terminal
QList < Terminal * > available_terminals ;
foreach ( QGraphicsItem * qgi , qgi_list )
{
if ( Terminal * tt = qgraphicsitem_cast < Terminal * > ( qgi ) )
{
//Call QET::lineContainsPoint to be sure the line intersect
//the dock point and not an other part of terminal
if ( Qet : : isOpposed ( orientation ( ) , tt - > orientation ( ) ) & &
QET : : lineContainsPoint ( line , tt - > dockConductor ( ) ) )
{
available_terminals < < tt ;
}
}
}
if ( available_terminals . isEmpty ( ) ) return nullptr ;
if ( available_terminals . size ( ) = = 1 ) return ( available_terminals . first ( ) ) ;
//Available_terminals have several terminals, we get the nearest terminal
line . setP2 ( available_terminals . first ( ) - > dockConductor ( ) ) ;
qreal current_lenght = line . length ( ) ;
Terminal * nearest_terminal = available_terminals . takeFirst ( ) ;
//Search the nearest terminal to this one
foreach ( Terminal * terminal , available_terminals )
{
line . setP2 ( terminal - > dockConductor ( ) ) ;
if ( line . length ( ) < current_lenght )
{
current_lenght = line . length ( ) ;
nearest_terminal = terminal ;
}
}
return nearest_terminal ;
}
2006-10-27 15:47:22 +00:00
/**
Gere l ' entree de la souris sur la zone de la Borne .
*/
2007-01-29 20:14:26 +00:00
void Terminal : : hoverEnterEvent ( QGraphicsSceneHoverEvent * ) {
2010-04-18 20:48:15 +00:00
hovered_ = true ;
2006-10-27 15:47:22 +00:00
update ( ) ;
}
/**
Gere les mouvements de la souris sur la zone de la Borne .
*/
2007-01-29 20:14:26 +00:00
void Terminal : : hoverMoveEvent ( QGraphicsSceneHoverEvent * ) {
2006-10-27 15:47:22 +00:00
}
/**
Gere le fait que la souris sorte de la zone de la Borne .
*/
2007-01-29 20:14:26 +00:00
void Terminal : : hoverLeaveEvent ( QGraphicsSceneHoverEvent * ) {
2010-04-18 20:48:15 +00:00
hovered_ = false ;
2006-10-27 15:47:22 +00:00
update ( ) ;
}
/**
Gere le fait qu ' on enfonce un bouton de la souris sur la Borne .
@ param e L ' evenement souris correspondant
*/
2007-01-29 20:14:26 +00:00
void Terminal : : mousePressEvent ( QGraphicsSceneMouseEvent * e ) {
2010-04-18 20:48:15 +00:00
if ( Diagram * d = diagram ( ) ) {
d - > setConductorStart ( mapToScene ( QPointF ( dock_conductor_ ) ) ) ;
d - > setConductorStop ( e - > scenePos ( ) ) ;
d - > setConductor ( true ) ;
2007-04-15 19:22:54 +00:00
//setCursor(Qt::CrossCursor);
2006-10-27 15:47:22 +00:00
}
}
/**
Gere le fait qu ' on bouge la souris sur la Borne .
@ param e L ' evenement souris correspondant
*/
2007-01-29 20:14:26 +00:00
void Terminal : : mouseMoveEvent ( QGraphicsSceneMouseEvent * e ) {
2006-10-27 15:47:22 +00:00
// pendant la pose d'un conducteur, on adopte un autre curseur
2007-04-15 19:22:54 +00:00
//setCursor(Qt::CrossCursor);
2006-10-27 15:47:22 +00:00
// d'un mouvement a l'autre, il faut retirer l'effet hover de la borne precedente
2010-04-18 20:48:15 +00:00
if ( previous_terminal_ ) {
if ( previous_terminal_ = = this ) hovered_ = true ;
else previous_terminal_ - > hovered_ = false ;
previous_terminal_ - > hovered_color_ = previous_terminal_ - > neutralColor ;
previous_terminal_ - > update ( ) ;
2006-10-27 15:47:22 +00:00
}
2007-09-25 23:24:36 +00:00
2010-04-18 20:48:15 +00:00
Diagram * d = diagram ( ) ;
if ( ! d ) return ;
2007-01-29 00:41:12 +00:00
// si la scene est un Diagram, on actualise le poseur de conducteur
2010-04-18 20:48:15 +00:00
d - > setConductorStop ( e - > scenePos ( ) ) ;
2006-10-27 15:47:22 +00:00
// on recupere la liste des qgi sous le pointeur
2010-04-18 20:48:15 +00:00
QList < QGraphicsItem * > qgis = d - > items ( e - > scenePos ( ) ) ;
2006-10-27 15:47:22 +00:00
/* le qgi le plus haut
2007-10-03 17:02:39 +00:00
= le poseur de conductor
2006-10-27 15:47:22 +00:00
= le premier element de la liste
= la liste ne peut etre vide
= on prend le deuxieme element de la liste
*/
2007-01-29 20:14:26 +00:00
Q_ASSERT_X ( ! ( qgis . isEmpty ( ) ) , " Terminal::mouseMoveEvent " , " La liste d'items ne devrait pas etre vide " ) ;
2006-10-27 15:47:22 +00:00
2010-04-18 20:48:15 +00:00
// s'il n'y rien d'autre que le poseur de conducteur dans la liste, on arrete la
if ( qgis . size ( ) < = 1 ) return ;
// sinon on prend le deuxieme element de la liste et on verifie s'il s'agit d'une borne
QGraphicsItem * qgi = qgis . at ( 1 ) ;
// si le qgi est une borne...
Terminal * other_terminal = qgraphicsitem_cast < Terminal * > ( qgi ) ;
if ( ! other_terminal ) return ;
previous_terminal_ = other_terminal ;
// s'il s'agit d'une borne, on lui applique l'effet hover approprie
if ( ! canBeLinkedTo ( other_terminal ) ) {
other_terminal - > hovered_color_ = forbiddenColor ;
} else if ( other_terminal - > conductorsCount ( ) ) {
other_terminal - > hovered_color_ = warningColor ;
} else {
other_terminal - > hovered_color_ = allowedColor ;
2006-10-27 15:47:22 +00:00
}
2010-04-18 20:48:15 +00:00
other_terminal - > hovered_ = true ;
other_terminal - > update ( ) ;
2006-10-27 15:47:22 +00:00
}
2015-01-09 17:18:16 +00:00
2006-10-27 15:47:22 +00:00
/**
2015-01-09 17:18:16 +00:00
* @ brief Terminal : : mouseReleaseEvent
* @ param e
*/
void Terminal : : mouseReleaseEvent ( QGraphicsSceneMouseEvent * e )
{
2010-04-18 20:48:15 +00:00
previous_terminal_ = 0 ;
2015-01-09 17:18:16 +00:00
hovered_color_ = neutralColor ;
if ( Diagram * d = diagram ( ) )
{
//Stop conductor preview
2010-04-18 20:48:15 +00:00
d - > setConductor ( false ) ;
2015-01-09 17:18:16 +00:00
//Get item under cursor
2015-03-02 20:14:56 +00:00
QGraphicsItem * qgi = d - > itemAt ( e - > scenePos ( ) , QTransform ( ) ) ;
2006-10-27 15:47:22 +00:00
if ( ! qgi ) return ;
2015-01-09 17:18:16 +00:00
//Element must be a terminal
2010-04-18 20:48:15 +00:00
Terminal * other_terminal = qgraphicsitem_cast < Terminal * > ( qgi ) ;
if ( ! other_terminal ) return ;
2015-01-09 17:18:16 +00:00
2010-04-18 20:48:15 +00:00
other_terminal - > hovered_color_ = neutralColor ;
2015-01-09 17:18:16 +00:00
other_terminal - > hovered_ = false ;
//We stop her if we can't link this terminal with other terminal
2010-04-18 20:48:15 +00:00
if ( ! canBeLinkedTo ( other_terminal ) ) return ;
2015-01-09 17:18:16 +00:00
//Create conductor
2014-11-16 20:32:55 +00:00
Conductor * new_conductor = new Conductor ( this , other_terminal ) ;
2010-04-18 20:48:15 +00:00
new_conductor - > setProperties ( d - > defaultConductorProperties ) ;
2015-01-09 17:18:16 +00:00
QUndoCommand * undo = new AddItemCommand < Conductor * > ( new_conductor , d ) ;
//Autonum it
ConductorAutoNumerotation can ( new_conductor , d , undo ) ;
can . numerate ( ) ;
//Add undo command to the parent diagram
d - > undoStack ( ) . push ( undo ) ;
2006-10-27 15:47:22 +00:00
}
}
/**
2010-05-04 20:18:30 +00:00
Met a jour l ' eventuel conducteur relie a la borne .
2006-11-30 18:05:02 +00:00
@ param newpos Position de l ' element parent a prendre en compte
2006-10-27 15:47:22 +00:00
*/
2010-05-04 20:18:30 +00:00
void Terminal : : updateConductor ( ) {
2006-11-30 18:05:02 +00:00
if ( ! scene ( ) | | ! parentItem ( ) ) return ;
2010-04-18 20:48:15 +00:00
foreach ( Conductor * conductor , conductors_ ) {
2007-10-03 17:02:39 +00:00
if ( conductor - > isDestroyed ( ) ) continue ;
2010-05-04 20:36:55 +00:00
conductor - > updatePath ( ) ;
2010-04-18 20:48:15 +00:00
}
}
/**
@ param other_terminal Autre borne
@ return true si cette borne est reliee a other_terminal , false sion
*/
bool Terminal : : isLinkedTo ( Terminal * other_terminal ) {
if ( other_terminal = = this ) return ( false ) ;
bool already_linked = false ;
foreach ( Conductor * c , conductors_ ) {
if ( c - > terminal1 = = other_terminal | | c - > terminal2 = = other_terminal ) {
already_linked = true ;
break ;
2006-11-30 18:05:02 +00:00
}
2006-10-27 15:47:22 +00:00
}
2010-04-18 20:48:15 +00:00
return ( already_linked ) ;
}
/**
2014-12-23 19:00:37 +00:00
* @ brief Terminal : : canBeLinkedTo
* @ param other_terminal
* @ return true if this terminal can be linked to @ other_terminal ,
* otherwise false
*/
bool Terminal : : canBeLinkedTo ( Terminal * other_terminal )
{
if ( other_terminal = = this | | isLinkedTo ( other_terminal ) )
return false ;
return true ;
2006-10-27 15:47:22 +00:00
}
/**
@ return La liste des conducteurs lies a cette borne
*/
2007-10-03 17:02:39 +00:00
QList < Conductor * > Terminal : : conductors ( ) const {
2010-04-18 20:48:15 +00:00
return ( conductors_ ) ;
2006-10-27 15:47:22 +00:00
}
/**
Methode d ' export en XML
@ param doc Le Document XML a utiliser pour creer l ' element XML
@ return un QDomElement representant cette borne
*/
2007-01-29 20:14:26 +00:00
QDomElement Terminal : : toXml ( QDomDocument & doc ) const {
2007-03-09 19:18:55 +00:00
QDomElement qdo = doc . createElement ( " terminal " ) ;
2010-04-18 20:48:15 +00:00
qdo . setAttribute ( " x " , QString ( " %1 " ) . arg ( dock_elmt_ . x ( ) ) ) ;
qdo . setAttribute ( " y " , QString ( " %1 " ) . arg ( dock_elmt_ . y ( ) ) ) ;
qdo . setAttribute ( " orientation " , ori_ ) ;
2013-11-12 18:43:59 +00:00
qdo . setAttribute ( " number " , number_terminal_ ) ;
2013-11-21 16:24:55 +00:00
qdo . setAttribute ( " name " , name_terminal_ ) ;
qdo . setAttribute ( " nameHidden " , name_terminal_hidden ) ;
2006-10-27 15:47:22 +00:00
return ( qdo ) ;
}
/**
Permet de savoir si un element XML represente une borne
2007-10-21 16:10:21 +00:00
@ param terminal Le QDomElement a analyser
2006-10-27 15:47:22 +00:00
@ return true si le QDomElement passe en parametre est une borne , false sinon
*/
2007-01-29 20:14:26 +00:00
bool Terminal : : valideXml ( QDomElement & terminal ) {
2006-10-27 15:47:22 +00:00
// verifie le nom du tag
2007-03-09 19:18:55 +00:00
if ( terminal . tagName ( ) ! = " terminal " ) return ( false ) ;
2006-10-27 15:47:22 +00:00
// verifie la presence des attributs minimaux
2007-01-29 20:14:26 +00:00
if ( ! terminal . hasAttribute ( " x " ) ) return ( false ) ;
if ( ! terminal . hasAttribute ( " y " ) ) return ( false ) ;
if ( ! terminal . hasAttribute ( " orientation " ) ) return ( false ) ;
2006-10-27 15:47:22 +00:00
bool conv_ok ;
// parse l'abscisse
2007-01-29 20:14:26 +00:00
terminal . attribute ( " x " ) . toDouble ( & conv_ok ) ;
2006-10-27 15:47:22 +00:00
if ( ! conv_ok ) return ( false ) ;
// parse l'ordonnee
2007-01-29 20:14:26 +00:00
terminal . attribute ( " y " ) . toDouble ( & conv_ok ) ;
2006-10-27 15:47:22 +00:00
if ( ! conv_ok ) return ( false ) ;
// parse l'id
2007-01-29 20:14:26 +00:00
terminal . attribute ( " id " ) . toInt ( & conv_ok ) ;
2006-10-27 15:47:22 +00:00
if ( ! conv_ok ) return ( false ) ;
// parse l'orientation
2007-01-29 20:14:26 +00:00
int terminal_or = terminal . attribute ( " orientation " ) . toInt ( & conv_ok ) ;
2006-10-27 15:47:22 +00:00
if ( ! conv_ok ) return ( false ) ;
2014-05-29 13:46:04 +00:00
if ( terminal_or ! = Qet : : North & & terminal_or ! = Qet : : South & & terminal_or ! = Qet : : East & & terminal_or ! = Qet : : West ) return ( false ) ;
2006-10-27 15:47:22 +00:00
// a ce stade, la borne est syntaxiquement correcte
return ( true ) ;
}
/**
Permet de savoir si un element XML represente cette borne . Attention , l ' element XML n ' est pas verifie
2007-10-21 16:10:21 +00:00
@ param terminal Le QDomElement a analyser
2006-10-27 15:47:22 +00:00
@ return true si la borne " se reconnait " ( memes coordonnes , meme orientation ) , false sinon
*/
2007-01-29 20:14:26 +00:00
bool Terminal : : fromXml ( QDomElement & terminal ) {
2013-11-21 16:24:55 +00:00
number_terminal_ = terminal . attribute ( " number " ) ;
name_terminal_ = terminal . attribute ( " name " ) ;
name_terminal_hidden = terminal . attribute ( " nameHidden " ) . toInt ( ) ;
2006-10-27 15:47:22 +00:00
return (
2010-04-18 20:48:15 +00:00
qFuzzyCompare ( terminal . attribute ( " x " ) . toDouble ( ) , dock_elmt_ . x ( ) ) & &
qFuzzyCompare ( terminal . attribute ( " y " ) . toDouble ( ) , dock_elmt_ . y ( ) ) & &
2013-11-21 16:24:55 +00:00
( terminal . attribute ( " orientation " ) . toInt ( ) = = ori_ )
2006-10-27 15:47:22 +00:00
) ;
}
2007-09-25 23:24:36 +00:00
2010-04-18 20:48:15 +00:00
/**
@ return le Diagram auquel cette borne appartient , ou 0 si cette borne est independant
*/
2007-09-25 23:24:36 +00:00
Diagram * Terminal : : diagram ( ) const {
return ( qobject_cast < Diagram * > ( scene ( ) ) ) ;
}
2010-04-18 20:48:15 +00:00
/**
@ return L ' element auquel cette borne est rattachee
*/
Element * Terminal : : parentElement ( ) const {
return ( parent_element_ ) ;
}
2013-11-13 11:55:27 +00:00
2014-10-09 09:02:41 +00:00
/**
* @ brief Conductor : : relatedPotentialTerminal
* Return terminal at the same potential from the same
* parent element of @ t .
* For folio report , return the terminal of linked other report .
* For Terminal element , return the other terminal of terminal element .
* @ param t terminal to start search
* @ param all_diagram : if true return all related terminal ,
* false return only terminal in the same diagram of @ t
* @ return
*/
Terminal * relatedPotentialTerminal ( const Terminal * terminal , const bool all_diagram ) {
// If terminal parent element is a folio report.
if ( all_diagram & & terminal - > parentElement ( ) - > linkType ( ) & Element : : AllReport ) {
QList < Element * > elmt_list = terminal - > parentElement ( ) - > linkedElements ( ) ;
if ( ! elmt_list . isEmpty ( ) ) {
return ( elmt_list . first ( ) - > terminals ( ) . first ( ) ) ;
}
}
// If terminal parent element is a Terminal element.
else if ( terminal - > parentElement ( ) - > linkType ( ) & Element : : Terminale ) {
QList < Terminal * > terminals = terminal - > parentElement ( ) - > terminals ( ) ;
terminals . removeAll ( const_cast < Terminal * > ( terminal ) ) ;
if ( ! terminals . isEmpty ( ) )
return terminals . first ( ) ;
}
return nullptr ;
}