2007-12-01 10:47:15 +00:00
/*
2009-04-03 19:30:25 +00:00
Copyright 2006 - 2009 Xavier Guerrin
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/>.
*/
2006-10-27 15:47:22 +00:00
# include <math.h>
2007-09-21 13:22:18 +00:00
# include "qetapp.h"
2007-10-03 17:02:39 +00:00
# include "conductor.h"
2007-01-30 22:32:21 +00:00
# include "customelement.h"
2007-01-29 00:41:12 +00:00
# include "diagram.h"
2009-04-04 21:47:07 +00:00
# include "elementtextitem.h"
2007-02-01 01:07:26 +00:00
# include "exportdialog.h"
2009-04-03 19:30:25 +00:00
# include "ghostelement.h"
2007-09-26 17:14:09 +00:00
# include "diagramcommands.h"
2007-11-09 13:06:51 +00:00
# include "diagramcontent.h"
2009-05-20 21:29:17 +00:00
# include "diagramposition.h"
2006-10-27 15:47:22 +00:00
2007-10-10 22:35:32 +00:00
const int Diagram : : xGrid = 10 ;
const int Diagram : : yGrid = 10 ;
const qreal Diagram : : margin = 5.0 ;
2006-10-27 15:47:22 +00:00
/**
Constructeur
@ param parent Le QObject parent du schema
*/
2007-10-11 12:51:56 +00:00
Diagram : : Diagram ( QObject * parent ) :
QGraphicsScene ( parent ) ,
draw_grid ( true ) ,
use_border ( true ) ,
moved_elements_fetched ( false ) ,
2009-04-03 19:30:25 +00:00
draw_terminals ( true ) ,
2009-11-22 16:12:22 +00:00
draw_colored_conductors_ ( true ) ,
2009-04-03 19:30:25 +00:00
project_ ( 0 ) ,
read_only_ ( false )
2007-10-11 12:51:56 +00:00
{
2008-07-17 22:57:50 +00:00
undo_stack = new QUndoStack ( ) ;
qgi_manager = new QGIManager ( this ) ;
2006-10-27 15:47:22 +00:00
setBackgroundBrush ( Qt : : white ) ;
2007-10-03 17:02:39 +00:00
conductor_setter = new QGraphicsLineItem ( 0 , 0 ) ;
conductor_setter - > setZValue ( 1000000 ) ;
2006-10-27 15:47:22 +00:00
QPen t ;
t . setColor ( Qt : : black ) ;
t . setWidthF ( 1.5 ) ;
t . setStyle ( Qt : : DashLine ) ;
2007-10-03 17:02:39 +00:00
conductor_setter - > setPen ( t ) ;
conductor_setter - > setLine ( QLineF ( QPointF ( 0.0 , 0.0 ) , QPointF ( 0.0 , 0.0 ) ) ) ;
2006-10-27 15:47:22 +00:00
}
2007-04-12 03:13:13 +00:00
/**
Destructeur
*/
Diagram : : ~ Diagram ( ) {
2008-07-17 22:57:50 +00:00
// suppression de la liste des annulations - l'undo stack fait appel au qgimanager pour supprimer certains elements
delete undo_stack ;
// suppression du QGIManager - tous les elements qu'il connait sont supprimes
delete qgi_manager ;
// recense les items supprimables
QList < QGraphicsItem * > deletable_items ;
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( qgi - > parentItem ( ) ) continue ;
if ( qgraphicsitem_cast < Conductor * > ( qgi ) ) continue ;
deletable_items < < qgi ;
}
// suppression des items supprimables
foreach ( QGraphicsItem * qgi_d , deletable_items ) {
delete qgi_d ;
}
2007-09-29 12:54:01 +00:00
}
2007-04-12 03:13:13 +00:00
2006-10-27 15:47:22 +00:00
/**
Dessine l ' arriere - plan du schema , cad la grille .
@ param p Le QPainter a utiliser pour dessiner
@ param r Le rectangle de la zone a dessiner
*/
2007-01-29 00:41:12 +00:00
void Diagram : : drawBackground ( QPainter * p , const QRectF & r ) {
2006-10-27 15:47:22 +00:00
p - > save ( ) ;
2007-02-01 01:07:26 +00:00
// desactive tout antialiasing, sauf pour le texte
2006-10-27 15:47:22 +00:00
p - > setRenderHint ( QPainter : : Antialiasing , false ) ;
2007-02-01 01:07:26 +00:00
p - > setRenderHint ( QPainter : : TextAntialiasing , true ) ;
2006-10-27 15:47:22 +00:00
p - > setRenderHint ( QPainter : : SmoothPixmapTransform , false ) ;
// dessine un fond blanc
p - > setPen ( Qt : : NoPen ) ;
p - > setBrush ( Qt : : white ) ;
p - > drawRect ( r ) ;
2007-09-04 18:15:41 +00:00
if ( draw_grid ) {
2006-10-27 15:47:22 +00:00
// dessine les points de la grille
p - > setPen ( Qt : : black ) ;
p - > setBrush ( Qt : : NoBrush ) ;
qreal limite_x = r . x ( ) + r . width ( ) ;
qreal limite_y = r . y ( ) + r . height ( ) ;
int g_x = ( int ) ceil ( r . x ( ) ) ;
2007-10-10 22:35:32 +00:00
while ( g_x % xGrid ) + + g_x ;
2006-10-27 15:47:22 +00:00
int g_y = ( int ) ceil ( r . y ( ) ) ;
2007-10-10 22:35:32 +00:00
while ( g_y % yGrid ) + + g_y ;
2006-10-27 15:47:22 +00:00
2007-10-10 22:35:32 +00:00
for ( int gx = g_x ; gx < limite_x ; gx + = xGrid ) {
for ( int gy = g_y ; gy < limite_y ; gy + = yGrid ) {
2006-10-27 15:47:22 +00:00
p - > drawPoint ( gx , gy ) ;
}
}
}
2007-01-28 00:53:17 +00:00
2007-10-10 22:35:32 +00:00
if ( use_border ) border_and_inset . draw ( p , margin , margin ) ;
2006-10-27 15:47:22 +00:00
p - > restore ( ) ;
}
2007-09-15 23:45:27 +00:00
/**
2007-10-10 17:50:26 +00:00
Gere les enfoncements de touches du clavier
2007-09-15 23:45:27 +00:00
@ param e QKeyEvent decrivant l ' evenement clavier
*/
void Diagram : : keyPressEvent ( QKeyEvent * e ) {
2009-04-03 19:30:25 +00:00
if ( ! isReadOnly ( ) ) {
QPointF movement ;
switch ( e - > key ( ) ) {
case Qt : : Key_Left : movement = QPointF ( - xGrid , 0.0 ) ; break ;
case Qt : : Key_Right : movement = QPointF ( + xGrid , 0.0 ) ; break ;
case Qt : : Key_Up : movement = QPointF ( 0.0 , - yGrid ) ; break ;
case Qt : : Key_Down : movement = QPointF ( 0.0 , + yGrid ) ; break ;
}
if ( ! movement . isNull ( ) & & ! focusItem ( ) ) {
moveElements ( movement ) ;
}
2007-09-15 23:45:27 +00:00
}
QGraphicsScene : : keyPressEvent ( e ) ;
}
2007-10-10 17:50:26 +00:00
/**
Gere les relachements de touches du clavier
@ param e QKeyEvent decrivant l ' evenement clavier
*/
2007-09-15 23:45:27 +00:00
void Diagram : : keyReleaseEvent ( QKeyEvent * e ) {
2009-04-03 19:30:25 +00:00
if ( ! isReadOnly ( ) ) {
// detecte le relachement d'une touche de direction ( = deplacement d'elements)
if (
( e - > key ( ) = = Qt : : Key_Left | | e - > key ( ) = = Qt : : Key_Right | | \
e - > key ( ) = = Qt : : Key_Up | | e - > key ( ) = = Qt : : Key_Down ) & & \
! current_movement . isNull ( ) & & ! e - > isAutoRepeat ( )
) {
// cree un objet d'annulation pour le mouvement qui vient de se finir
undoStack ( ) . push ( new MoveElementsCommand ( this , selectedContent ( ) , current_movement ) ) ;
invalidateMovedElements ( ) ;
current_movement = QPointF ( ) ;
}
2007-09-26 17:14:09 +00:00
}
2007-09-15 23:45:27 +00:00
QGraphicsScene : : keyReleaseEvent ( e ) ;
}
2006-11-11 18:25:42 +00:00
/**
Exporte le schema vers une image
@ return Une QImage representant le schema
*/
2007-10-05 12:06:39 +00:00
bool Diagram : : toPaintDevice ( QPaintDevice & pix , int width , int height , Qt : : AspectRatioMode aspectRatioMode ) {
2007-02-01 01:07:26 +00:00
// determine la zone source = contenu du schema + marges
QRectF source_area ;
if ( ! use_border ) {
source_area = itemsBoundingRect ( ) ;
2007-10-10 22:35:32 +00:00
source_area . translate ( - margin , - margin ) ;
source_area . setWidth ( source_area . width ( ) + 2.0 * margin ) ;
source_area . setHeight ( source_area . height ( ) + 2.0 * margin ) ;
2007-02-01 01:07:26 +00:00
} else {
source_area = QRectF (
0.0 ,
0.0 ,
2007-10-10 22:35:32 +00:00
border_and_inset . borderWidth ( ) + 2.0 * margin ,
border_and_inset . borderHeight ( ) + 2.0 * margin
2007-02-01 01:07:26 +00:00
) ;
}
2007-01-20 18:11:42 +00:00
// si les dimensions ne sont pas precisees, l'image est exportee a l'echelle 1:1
QSize image_size = ( width = = - 1 & & height = = - 1 ) ? source_area . size ( ) . toSize ( ) : QSize ( width , height ) ;
// prepare le rendu
2006-10-27 15:47:22 +00:00
QPainter p ;
2007-10-05 12:06:39 +00:00
if ( ! p . begin ( & pix ) ) return ( false ) ;
2006-10-27 15:47:22 +00:00
// rendu antialiase
p . setRenderHint ( QPainter : : Antialiasing , true ) ;
p . setRenderHint ( QPainter : : TextAntialiasing , true ) ;
p . setRenderHint ( QPainter : : SmoothPixmapTransform , true ) ;
2007-01-20 18:11:42 +00:00
// deselectionne tous les elements
QList < QGraphicsItem * > selected_elmts = selectedItems ( ) ;
foreach ( QGraphicsItem * qgi , selected_elmts ) qgi - > setSelected ( false ) ;
// effectue le rendu lui-meme
2007-10-05 12:06:39 +00:00
render ( & p , QRect ( QPoint ( 0 , 0 ) , image_size ) , source_area , aspectRatioMode ) ;
2006-10-27 15:47:22 +00:00
p . end ( ) ;
2007-01-20 18:11:42 +00:00
// restaure les elements selectionnes
foreach ( QGraphicsItem * qgi , selected_elmts ) qgi - > setSelected ( true ) ;
2007-10-05 12:06:39 +00:00
return ( true ) ;
2006-10-27 15:47:22 +00:00
}
2007-01-20 18:11:42 +00:00
/**
Permet de connaitre les dimensions qu ' aura l ' image generee par la methode toImage ( )
@ return La taille de l ' image generee par toImage ( )
*/
2007-01-29 00:41:12 +00:00
QSize Diagram : : imageSize ( ) const {
2007-02-01 01:07:26 +00:00
// determine la zone source = contenu du schema + marges
qreal image_width , image_height ;
if ( ! use_border ) {
QRectF items_rect = itemsBoundingRect ( ) ;
image_width = items_rect . width ( ) ;
image_height = items_rect . height ( ) ;
} else {
image_width = border_and_inset . borderWidth ( ) ;
image_height = border_and_inset . borderHeight ( ) ;
}
2007-01-20 18:11:42 +00:00
2007-10-10 22:35:32 +00:00
image_width + = 2.0 * margin ;
image_height + = 2.0 * margin ;
2007-01-20 18:11:42 +00:00
// renvoie la taille de la zone source
2007-02-01 01:07:26 +00:00
return ( QSizeF ( image_width , image_height ) . toSize ( ) ) ;
2007-01-20 18:11:42 +00:00
}
2009-04-03 19:30:25 +00:00
/**
@ return true si le schema est considere comme vide , false sinon .
Un schema vide ne contient ni element , ni conducteur , ni champ de texte
*/
bool Diagram : : isEmpty ( ) const {
return ( ! items ( ) . count ( ) ) ;
}
2006-10-27 15:47:22 +00:00
/**
Exporte tout ou partie du schema
2007-02-24 18:37:07 +00:00
@ param diagram Booleen ( a vrai par defaut ) indiquant si le XML genere doit
2006-11-11 18:25:42 +00:00
representer tout le schema ou seulement les elements selectionnes
2006-10-27 15:47:22 +00:00
@ return Un Document XML ( QDomDocument )
*/
2007-01-29 00:41:12 +00:00
QDomDocument Diagram : : toXml ( bool diagram ) {
2006-10-27 15:47:22 +00:00
// document
QDomDocument document ;
// racine de l'arbre XML
2007-03-09 19:18:55 +00:00
QDomElement racine = document . createElement ( " diagram " ) ;
2006-10-27 15:47:22 +00:00
// proprietes du schema
2007-01-29 00:41:12 +00:00
if ( diagram ) {
2007-03-09 19:18:55 +00:00
if ( ! border_and_inset . author ( ) . isNull ( ) ) racine . setAttribute ( " author " , border_and_inset . author ( ) ) ;
2007-01-28 00:53:17 +00:00
if ( ! border_and_inset . date ( ) . isNull ( ) ) racine . setAttribute ( " date " , border_and_inset . date ( ) . toString ( " yyyyMMdd " ) ) ;
2007-03-09 19:18:55 +00:00
if ( ! border_and_inset . title ( ) . isNull ( ) ) racine . setAttribute ( " title " , border_and_inset . title ( ) ) ;
2007-01-28 00:53:17 +00:00
if ( ! border_and_inset . fileName ( ) . isNull ( ) ) racine . setAttribute ( " filename " , border_and_inset . fileName ( ) ) ;
if ( ! border_and_inset . folio ( ) . isNull ( ) ) racine . setAttribute ( " folio " , border_and_inset . folio ( ) ) ;
2008-08-10 15:07:59 +00:00
racine . setAttribute ( " cols " , border_and_inset . nbColumns ( ) ) ;
2008-08-23 19:27:14 +00:00
racine . setAttribute ( " colsize " , QString ( " %1 " ) . arg ( border_and_inset . columnsWidth ( ) ) ) ;
2008-08-10 15:07:59 +00:00
racine . setAttribute ( " rows " , border_and_inset . nbRows ( ) ) ;
2008-08-23 19:27:14 +00:00
racine . setAttribute ( " rowsize " , QString ( " %1 " ) . arg ( border_and_inset . rowsHeight ( ) ) ) ;
2008-08-10 15:07:59 +00:00
// attribut datant de la version 0.1 - laisse pour retrocompatibilite
2008-08-23 19:27:14 +00:00
racine . setAttribute ( " height " , QString ( " %1 " ) . arg ( border_and_inset . diagramHeight ( ) ) ) ;
2008-08-15 12:46:22 +00:00
racine . setAttribute ( " displaycols " , border_and_inset . columnsAreDisplayed ( ) ? " true " : " false " ) ;
racine . setAttribute ( " displayrows " , border_and_inset . rowsAreDisplayed ( ) ? " true " : " false " ) ;
2007-10-14 21:38:27 +00:00
// type de conducteur par defaut
QDomElement default_conductor = document . createElement ( " defaultconductor " ) ;
2009-04-03 19:30:25 +00:00
defaultConductorProperties . toXml ( default_conductor ) ;
2007-10-14 21:38:27 +00:00
racine . appendChild ( default_conductor ) ;
2006-10-27 15:47:22 +00:00
}
document . appendChild ( racine ) ;
// si le schema ne contient pas d'element (et donc pas de conducteurs), on retourne de suite le document XML
if ( items ( ) . isEmpty ( ) ) return ( document ) ;
2007-10-27 13:18:17 +00:00
// creation de trois listes : une qui contient les elements, une qui contient les conducteurs, une qui contient les champs de texte
QList < Element * > list_elements ;
QList < Conductor * > list_conductors ;
QList < DiagramTextItem * > list_texts ;
2006-10-27 15:47:22 +00:00
2009-04-11 13:09:47 +00:00
// Determine les elements a "XMLiser"
2006-10-27 15:47:22 +00:00
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( Element * elmt = qgraphicsitem_cast < Element * > ( qgi ) ) {
2007-10-27 13:18:17 +00:00
if ( diagram ) list_elements < < elmt ;
else if ( elmt - > isSelected ( ) ) list_elements < < elmt ;
2007-10-03 17:02:39 +00:00
} else if ( Conductor * f = qgraphicsitem_cast < Conductor * > ( qgi ) ) {
2007-10-27 13:18:17 +00:00
if ( diagram ) list_conductors < < f ;
2007-01-29 00:41:12 +00:00
// lorsqu'on n'exporte pas tout le diagram, il faut retirer les conducteurs non selectionnes
2006-10-27 15:47:22 +00:00
// et pour l'instant, les conducteurs non selectionnes sont les conducteurs dont un des elements n'est pas relie
2007-10-27 13:18:17 +00:00
else if ( f - > terminal1 - > parentItem ( ) - > isSelected ( ) & & f - > terminal2 - > parentItem ( ) - > isSelected ( ) ) list_conductors < < f ;
} else if ( DiagramTextItem * dti = qgraphicsitem_cast < DiagramTextItem * > ( qgi ) ) {
if ( ! dti - > parentItem ( ) ) {
if ( diagram ) list_texts < < dti ;
else if ( dti - > isSelected ( ) ) list_texts < < dti ;
}
2006-10-27 15:47:22 +00:00
}
}
// table de correspondance entre les adresses des bornes et leurs ids
2007-01-29 20:14:26 +00:00
QHash < Terminal * , int > table_adr_id ;
2007-02-24 18:37:07 +00:00
// enregistrement des elements
2007-10-27 13:18:17 +00:00
if ( ! list_elements . isEmpty ( ) ) {
QDomElement elements = document . createElement ( " elements " ) ;
foreach ( Element * elmt , list_elements ) {
elements . appendChild ( elmt - > toXml ( document , table_adr_id ) ) ;
}
racine . appendChild ( elements ) ;
2006-10-27 15:47:22 +00:00
}
// enregistrement des conducteurs
2007-10-27 13:18:17 +00:00
if ( ! list_conductors . isEmpty ( ) ) {
QDomElement conductors = document . createElement ( " conductors " ) ;
foreach ( Conductor * cond , list_conductors ) {
conductors . appendChild ( cond - > toXml ( document , table_adr_id ) ) ;
}
racine . appendChild ( conductors ) ;
}
// enregistrement des champs de texte
if ( ! list_texts . isEmpty ( ) ) {
QDomElement inputs = document . createElement ( " inputs " ) ;
foreach ( DiagramTextItem * dti , list_texts ) {
inputs . appendChild ( dti - > toXml ( document ) ) ;
}
racine . appendChild ( inputs ) ;
2006-10-27 15:47:22 +00:00
}
// on retourne le document XML ainsi genere
return ( document ) ;
}
/**
2009-04-03 19:30:25 +00:00
Importe le schema decrit dans un document XML . Si une position est
2006-11-11 18:25:42 +00:00
precisee , les elements importes sont positionnes de maniere a ce que le
coin superieur gauche du plus petit rectangle pouvant les entourant tous
( le bounding rect ) soit a cette position .
2006-10-27 15:47:22 +00:00
@ param document Le document XML a analyser
2009-04-03 19:30:25 +00:00
@ param position La position du schema importe
2007-09-26 12:36:31 +00:00
@ param consider_informations Si vrai , les informations complementaires
( auteur , titre , . . . ) seront prises en compte
2009-04-28 18:04:29 +00:00
@ param content_ptr si ce pointeur vers un DiagramContent est different de 0 ,
il sera rempli avec le contenu ajoute au schema par le fromXml
2006-10-27 15:47:22 +00:00
@ return true si l ' import a reussi , false sinon
*/
2007-11-09 13:06:51 +00:00
bool Diagram : : fromXml ( QDomDocument & document , QPointF position , bool consider_informations , DiagramContent * content_ptr ) {
2007-10-27 13:18:17 +00:00
QDomElement root = document . documentElement ( ) ;
2009-04-03 19:30:25 +00:00
return ( fromXml ( root , position , consider_informations , content_ptr ) ) ;
}
2009-04-28 18:04:29 +00:00
/**
Importe le schema decrit dans un element XML . Cette methode delegue son travail a Diagram : : fromXml
Si l ' import reussit , cette methode initialise egalement le document XML
interne permettant de bien gerer l ' enregistrement de ce schema dans le
projet auquel il appartient .
@ see Diagram : : fromXml
@ param document Le document XML a analyser
@ param position La position du schema importe
@ param consider_informations Si vrai , les informations complementaires
( auteur , titre , . . . ) seront prises en compte
@ param content_ptr si ce pointeur vers un DiagramContent est different de 0 ,
il sera rempli avec le contenu ajoute au schema par le fromXml
@ return true si l ' import a reussi , false sinon
*/
bool Diagram : : initFromXml ( QDomElement & document , QPointF position , bool consider_informations , DiagramContent * content_ptr ) {
// import le contenu et les proprietes du schema depuis l'element XML fourni en parametre
bool from_xml = fromXml ( document , position , consider_informations , content_ptr ) ;
// initialise le document XML interne a partir de l'element XML fourni en parametre
if ( from_xml ) {
xml_document . clear ( ) ;
xml_document . appendChild ( xml_document . importNode ( document , true ) ) ;
// a ce stade, le document XML interne contient le code XML qui a ete importe, et non pas une version re-exporte par la methode toXml()
}
return ( from_xml ) ;
}
2009-04-03 19:30:25 +00:00
/**
Importe le schema decrit dans un element XML . Si une position est
precisee , les elements importes sont positionnes de maniere a ce que le
coin superieur gauche du plus petit rectangle pouvant les entourant tous
( le bounding rect ) soit a cette position .
@ param document Le document XML a analyser
@ param position La position du schema importe
@ param consider_informations Si vrai , les informations complementaires
( auteur , titre , . . . ) seront prises en compte
2009-04-28 18:04:29 +00:00
@ param content_ptr si ce pointeur vers un DiagramContent est different de 0 ,
il sera rempli avec le contenu ajoute au schema par le fromXml
2009-04-03 19:30:25 +00:00
@ return true si l ' import a reussi , false sinon
*/
bool Diagram : : fromXml ( QDomElement & document , QPointF position , bool consider_informations , DiagramContent * content_ptr ) {
QDomElement root = document ;
2006-10-27 15:47:22 +00:00
// le premier element doit etre un schema
2007-10-27 13:18:17 +00:00
if ( root . tagName ( ) ! = " diagram " ) return ( false ) ;
2007-01-29 00:41:12 +00:00
2006-10-27 15:47:22 +00:00
// lecture des attributs de ce schema
2007-01-28 00:53:17 +00:00
if ( consider_informations ) {
2007-10-27 13:18:17 +00:00
border_and_inset . setAuthor ( root . attribute ( " author " ) ) ;
border_and_inset . setTitle ( root . attribute ( " title " ) ) ;
border_and_inset . setDate ( QDate : : fromString ( root . attribute ( " date " ) , " yyyyMMdd " ) ) ;
border_and_inset . setFileName ( root . attribute ( " filename " ) ) ;
border_and_inset . setFolio ( root . attribute ( " folio " ) ) ;
2007-02-28 20:48:11 +00:00
bool ok ;
// nombre de colonnes
2007-10-27 13:18:17 +00:00
int nb_cols = root . attribute ( " cols " ) . toInt ( & ok ) ;
2007-02-28 20:48:11 +00:00
if ( ok ) border_and_inset . setNbColumns ( nb_cols ) ;
// taille des colonnes
2007-10-27 13:18:17 +00:00
double col_size = root . attribute ( " colsize " ) . toDouble ( & ok ) ;
2007-02-28 20:48:11 +00:00
if ( ok ) border_and_inset . setColumnsWidth ( col_size ) ;
2008-08-10 15:07:59 +00:00
// retrocompatibilite : les schemas enregistres avec la 0.1 ont un attribut "height"
if ( root . hasAttribute ( " rows " ) & & root . hasAttribute ( " rowsize " ) ) {
// nombre de lignes
int nb_rows = root . attribute ( " rows " ) . toInt ( & ok ) ;
if ( ok ) border_and_inset . setNbRows ( nb_rows ) ;
// taille des lignes
double row_size = root . attribute ( " rowsize " ) . toDouble ( & ok ) ;
if ( ok ) border_and_inset . setRowsHeight ( row_size ) ;
} else {
// hauteur du schema
double height = root . attribute ( " height " ) . toDouble ( & ok ) ;
if ( ok ) border_and_inset . setDiagramHeight ( height ) ;
}
2007-10-14 21:38:27 +00:00
2008-08-15 12:46:22 +00:00
// affichage des lignes et colonnes
border_and_inset . displayColumns ( root . attribute ( " displaycols " ) ! = " false " ) ;
border_and_inset . displayRows ( root . attribute ( " displayrows " ) ! = " false " ) ;
2007-11-14 20:27:45 +00:00
border_and_inset . adjustInsetToColumns ( ) ;
2007-10-14 21:38:27 +00:00
// repere le permier element "defaultconductor"
2007-10-27 13:18:17 +00:00
for ( QDomNode node = root . firstChild ( ) ; ! node . isNull ( ) ; node = node . nextSibling ( ) ) {
2007-10-14 21:38:27 +00:00
QDomElement elmts = node . toElement ( ) ;
if ( elmts . isNull ( ) | | elmts . tagName ( ) ! = " defaultconductor " ) continue ;
defaultConductorProperties . fromXml ( elmts ) ;
break ;
}
2007-01-28 00:53:17 +00:00
}
2006-10-27 15:47:22 +00:00
// si la racine n'a pas d'enfant : le chargement est fini (schema vide)
2009-04-03 19:30:25 +00:00
if ( root . firstChild ( ) . isNull ( ) ) {
write ( document ) ;
return ( true ) ;
}
2007-10-27 13:18:17 +00:00
// chargement de tous les elements du fichier XML
QList < Element * > added_elements ;
QHash < int , Terminal * > table_adr_id ;
foreach ( QDomElement e , QET : : findInDomElement ( root , " elements " , " element " ) ) {
if ( ! Element : : valideXml ( e ) ) continue ;
2007-12-05 21:16:01 +00:00
// cree un element dont le type correspond a l'id type
2007-10-27 13:18:17 +00:00
QString type_id = e . attribute ( " type " ) ;
2009-04-03 19:30:25 +00:00
ElementsLocation element_location = ElementsLocation ( type_id ) ;
if ( type_id . startsWith ( " embed:// " ) ) element_location . setProject ( project_ ) ;
CustomElement * nvel_elmt = new CustomElement ( element_location ) ;
2007-10-27 13:18:17 +00:00
if ( nvel_elmt - > isNull ( ) ) {
2009-04-13 01:35:01 +00:00
QString debug_message = QString ( " Diagram::fromXml() : Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2 " ) . arg ( element_location . path ( ) ) . arg ( nvel_elmt - > state ( ) ) ;
qDebug ( ) < < qPrintable ( debug_message ) ;
2007-10-27 13:18:17 +00:00
delete nvel_elmt ;
2009-04-03 19:30:25 +00:00
2009-04-13 01:35:01 +00:00
qDebug ( ) < < " Diagram::fromXml() : Utilisation d'un GhostElement en lieu et place de cet element. " ;
2009-04-03 19:30:25 +00:00
nvel_elmt = new GhostElement ( element_location ) ;
2007-10-27 13:18:17 +00:00
}
// charge les caracteristiques de l'element
if ( nvel_elmt - > fromXml ( e , table_adr_id ) ) {
// ajout de l'element au schema et a la liste des elements ajoutes
2009-04-04 21:47:07 +00:00
addElement ( nvel_elmt ) ;
2007-10-27 13:18:17 +00:00
added_elements < < nvel_elmt ;
} else {
delete nvel_elmt ;
2009-04-13 01:35:01 +00:00
qDebug ( ) < < " Diagram::fromXml() : Le chargement des parametres d'un element a echoue " ;
2006-10-27 15:47:22 +00:00
}
}
2007-10-27 13:18:17 +00:00
// chargement de tous les textes du fichiers XML
QList < DiagramTextItem * > added_texts ;
foreach ( QDomElement f , QET : : findInDomElement ( root , " inputs " , " input " ) ) {
DiagramTextItem * dti = new DiagramTextItem ( 0 , this ) ;
dti - > fromXml ( f ) ;
2009-04-04 21:47:07 +00:00
addDiagramTextItem ( dti ) ;
2007-10-27 13:18:17 +00:00
added_texts < < dti ;
}
2006-10-27 15:47:22 +00:00
2007-10-27 13:18:17 +00:00
// gere la translation des nouveaux elements et texte si celle-ci est demandee
2006-10-27 15:47:22 +00:00
if ( position ! = QPointF ( ) ) {
// determine quel est le coin superieur gauche du rectangle entourant les elements ajoutes
qreal minimum_x = 0 , minimum_y = 0 ;
bool init = false ;
2007-10-27 13:18:17 +00:00
QList < QGraphicsItem * > added_items ;
foreach ( Element * added_element , added_elements ) added_items < < added_element ;
foreach ( DiagramTextItem * added_text , added_texts ) added_items < < added_text ;
foreach ( QGraphicsItem * item , added_items ) {
2007-11-02 18:04:13 +00:00
QPointF csg = item - > mapToScene ( item - > boundingRect ( ) ) . boundingRect ( ) . topLeft ( ) ;
2006-10-27 15:47:22 +00:00
qreal px = csg . x ( ) ;
qreal py = csg . y ( ) ;
if ( ! init ) {
minimum_x = px ;
minimum_y = py ;
init = true ;
} else {
if ( px < minimum_x ) minimum_x = px ;
if ( py < minimum_y ) minimum_y = py ;
}
}
qreal diff_x = position . x ( ) - minimum_x ;
qreal diff_y = position . y ( ) - minimum_y ;
2007-10-27 13:18:17 +00:00
foreach ( Element * added_element , added_elements ) {
added_element - > setPos ( added_element - > pos ( ) . x ( ) + diff_x , added_element - > pos ( ) . y ( ) + diff_y ) ;
}
foreach ( DiagramTextItem * added_text , added_texts ) {
added_text - > setPos ( added_text - > pos ( ) . x ( ) + diff_x , added_text - > pos ( ) . y ( ) + diff_y ) ;
2006-10-27 15:47:22 +00:00
}
}
// chargement de tous les Conducteurs du fichier XML
2007-10-27 13:18:17 +00:00
QList < Conductor * > added_conductors ;
foreach ( QDomElement f , QET : : findInDomElement ( root , " conductors " , " conductor " ) ) {
if ( ! Conductor : : valideXml ( f ) ) continue ;
// verifie que les bornes que le conducteur relie sont connues
int id_p1 = f . attribute ( " terminal1 " ) . toInt ( ) ;
int id_p2 = f . attribute ( " terminal2 " ) . toInt ( ) ;
if ( table_adr_id . contains ( id_p1 ) & & table_adr_id . contains ( id_p2 ) ) {
// pose le conducteur... si c'est possible
Terminal * p1 = table_adr_id . value ( id_p1 ) ;
Terminal * p2 = table_adr_id . value ( id_p2 ) ;
if ( p1 ! = p2 ) {
bool can_add_conductor = true ;
2007-12-09 10:30:35 +00:00
bool cia = ( ( Element * ) p2 - > parentItem ( ) ) - > internalConnections ( ) ;
2007-10-27 13:18:17 +00:00
if ( ! cia ) {
foreach ( QGraphicsItem * item , p2 - > parentItem ( ) - > children ( ) ) {
if ( item = = p1 ) can_add_conductor = false ;
2007-02-18 19:33:15 +00:00
}
2006-10-27 15:47:22 +00:00
}
2007-10-27 13:18:17 +00:00
if ( can_add_conductor ) {
Conductor * c = new Conductor ( table_adr_id . value ( id_p1 ) , table_adr_id . value ( id_p2 ) , 0 , this ) ;
c - > fromXml ( f ) ;
added_conductors < < c ;
}
}
2009-04-13 01:35:01 +00:00
} else qDebug ( ) < < " Diagram::fromXml() : Le chargement du conducteur " < < id_p1 < < id_p2 < < " a echoue " ;
2006-10-27 15:47:22 +00:00
}
2007-10-27 13:18:17 +00:00
// remplissage des listes facultatives
2009-04-28 18:04:29 +00:00
if ( content_ptr ) {
2007-11-09 13:06:51 +00:00
content_ptr - > elements = added_elements ;
content_ptr - > conductorsToMove = added_conductors ;
content_ptr - > textFields = added_texts ;
}
2007-10-27 13:18:17 +00:00
2006-10-27 15:47:22 +00:00
return ( true ) ;
}
2009-04-03 19:30:25 +00:00
/**
Enregistre le schema XML dans son document XML interne et emet le signal
written ( ) .
*/
void Diagram : : write ( ) {
qDebug ( ) < < qPrintable ( QString ( " Diagram::write() : saving changes from diagram \" %1 \" [%2] " ) . arg ( title ( ) ) . arg ( QET : : pointerString ( this ) ) ) ;
write ( toXml ( ) . documentElement ( ) ) ;
undoStack ( ) . setClean ( ) ;
}
/**
Enregistre un element XML dans son document XML interne et emet le signal
written ( ) .
@ param element xml a enregistrer
*/
void Diagram : : write ( const QDomElement & element ) {
xml_document . clear ( ) ;
xml_document . appendChild ( xml_document . importNode ( element , true ) ) ;
emit ( written ( ) ) ;
}
/**
@ return true si la fonction write a deja ete appele ( pour etre plus exact :
si le document XML utilise en interne n ' est pas vide ) , false sinon
*/
bool Diagram : : wasWritten ( ) const {
return ( ! xml_document . isNull ( ) ) ;
}
/**
@ return le schema en XML tel qu ' il doit etre enregistre dans le fichier projet
@ param xml_doc document XML a utiliser pour creer l ' element
*/
QDomElement Diagram : : writeXml ( QDomDocument & xml_doc ) const {
// si le schema n'a pas ete enregistre explicitement, on n'ecrit rien
if ( ! wasWritten ( ) ) return ( QDomElement ( ) ) ;
QDomElement diagram_elmt = xml_document . documentElement ( ) ;
QDomNode new_node = xml_doc . importNode ( diagram_elmt , true ) ;
return ( new_node . toElement ( ) ) ;
}
2009-04-04 21:47:07 +00:00
/**
Ajoute un element sur le schema
@ param element Element a ajouter
*/
void Diagram : : addElement ( Element * element ) {
if ( ! element | | isReadOnly ( ) ) return ;
// ajoute l'element au schema
if ( element - > scene ( ) ! = this ) {
addItem ( element ) ;
}
// surveille les modifications de ses champs de texte
foreach ( ElementTextItem * eti , element - > texts ( ) ) {
connect (
eti ,
SIGNAL ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) ) ,
this ,
SLOT ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) )
) ;
}
}
/**
Ajoute un conducteur sur le schema
@ param conductor Conducteur a ajouter
*/
void Diagram : : addConductor ( Conductor * conductor ) {
if ( ! conductor | | isReadOnly ( ) ) return ;
// ajoute le conducteur au schema
if ( conductor - > scene ( ) ! = this ) {
addItem ( conductor ) ;
conductor - > terminal1 - > addConductor ( conductor ) ;
conductor - > terminal2 - > addConductor ( conductor ) ;
}
}
/**
Aoute un champ de texte independant sur le schema
@ param dti Champ de texte a ajouter
*/
void Diagram : : addDiagramTextItem ( DiagramTextItem * dti ) {
if ( ! dti | | isReadOnly ( ) ) return ;
// ajoute le champ de texte au schema
if ( dti - > scene ( ) ! = this ) {
addItem ( dti ) ;
}
// surveille les modifications apportees au champ de texte
connect (
dti ,
SIGNAL ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) ) ,
this ,
SLOT ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) )
) ;
}
/**
Enleve un element du schema
@ param element Element a enlever
*/
void Diagram : : removeElement ( Element * element ) {
if ( ! element | | isReadOnly ( ) ) return ;
// enleve l'element au schema
removeItem ( element ) ;
// arrete la surveillance des modifications de ses champs de texte
foreach ( ElementTextItem * eti , element - > texts ( ) ) {
disconnect (
eti ,
SIGNAL ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) ) ,
this ,
SLOT ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) )
) ;
}
}
/**
Enleve un conducteur du schema
@ param conductor Conducteur a enlever
*/
void Diagram : : removeConductor ( Conductor * conductor ) {
if ( ! conductor | | isReadOnly ( ) ) return ;
// detache le conducteur sans le detruire
conductor - > terminal1 - > removeConductor ( conductor ) ;
conductor - > terminal2 - > removeConductor ( conductor ) ;
// enleve le conducteur du schema
removeItem ( conductor ) ;
}
/**
Enleve un champ de texte independant du schema
@ param dti Champ de texte a enlever
*/
void Diagram : : removeDiagramTextItem ( DiagramTextItem * dti ) {
if ( ! dti | | isReadOnly ( ) ) return ;
// enleve le champ de texte au schema
removeItem ( dti ) ;
// arrete la surveillance des modifications apportees au champ de texte
disconnect (
dti ,
SIGNAL ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) ) ,
this ,
SLOT ( diagramTextChanged ( DiagramTextItem * , const QString & , const QString & ) )
) ;
}
2008-07-09 21:14:30 +00:00
/**
Gere le fait qu ' un texte du schema ait ete modifie
@ param text_item Texte modifie
@ param old_text Ancien texte
@ param new_text Nouveau texte
*/
void Diagram : : diagramTextChanged ( DiagramTextItem * text_item , const QString & old_text , const QString & new_text ) {
if ( ! text_item ) return ;
2008-07-17 22:57:50 +00:00
undo_stack - > push ( new ChangeDiagramTextCommand ( text_item , old_text , new_text ) ) ;
2008-07-09 21:14:30 +00:00
}
2007-02-25 17:53:16 +00:00
/**
2009-04-18 15:30:44 +00:00
Selectionne tous les objets du schema
2007-02-25 17:53:16 +00:00
*/
2009-04-18 15:30:44 +00:00
void Diagram : : selectAll ( ) {
if ( items ( ) . isEmpty ( ) ) return ;
blockSignals ( true ) ;
foreach ( QGraphicsItem * qgi , items ( ) ) qgi - > setSelected ( true ) ;
blockSignals ( false ) ;
emit ( selectionChanged ( ) ) ;
}
/**
Deslectionne tous les objets selectionnes
*/
void Diagram : : deselectAll ( ) {
if ( items ( ) . isEmpty ( ) ) return ;
clearSelection ( ) ;
}
/**
Inverse l ' etat de selection de tous les objets du schema
*/
void Diagram : : invertSelection ( ) {
if ( items ( ) . isEmpty ( ) ) return ;
blockSignals ( true ) ;
foreach ( QGraphicsItem * item , items ( ) ) item - > setSelected ( ! item - > isSelected ( ) ) ;
blockSignals ( false ) ;
emit ( selectionChanged ( ) ) ;
2007-02-25 17:53:16 +00:00
}
2007-01-28 00:53:17 +00:00
/**
@ return Le rectangle ( coordonnees par rapport a la scene ) delimitant le bord du schema
*/
2007-01-29 00:41:12 +00:00
QRectF Diagram : : border ( ) const {
2007-01-28 00:53:17 +00:00
return (
QRectF (
2007-10-10 22:35:32 +00:00
margin ,
margin ,
2007-01-28 00:53:17 +00:00
border_and_inset . borderWidth ( ) ,
border_and_inset . borderHeight ( )
)
) ;
}
2007-09-05 20:42:08 +00:00
2009-04-03 19:30:25 +00:00
/**
@ return le titre du cartouche
*/
QString Diagram : : title ( ) const {
return ( border_and_inset . title ( ) ) ;
}
/**
@ return la liste des elements de ce schema
*/
QList < CustomElement * > Diagram : : customElements ( ) const {
QList < CustomElement * > elements_list ;
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( CustomElement * elmt = qgraphicsitem_cast < CustomElement * > ( qgi ) ) {
elements_list < < elmt ;
}
}
return ( elements_list ) ;
}
2009-04-13 01:35:01 +00:00
/**
Oublie la liste des elements et conducteurs en mouvement
*/
2007-09-15 22:14:23 +00:00
void Diagram : : invalidateMovedElements ( ) {
if ( ! moved_elements_fetched ) return ;
moved_elements_fetched = false ;
elements_to_move . clear ( ) ;
2007-10-03 17:02:39 +00:00
conductors_to_move . clear ( ) ;
conductors_to_update . clear ( ) ;
2007-10-27 13:18:17 +00:00
texts_to_move . clear ( ) ;
2007-09-15 22:14:23 +00:00
}
2009-04-13 01:35:01 +00:00
/**
Reconstruit la liste des elements et conducteurs en mouvement
*/
2007-09-15 22:14:23 +00:00
void Diagram : : fetchMovedElements ( ) {
// recupere les elements deplaces
foreach ( QGraphicsItem * item , selectedItems ( ) ) {
if ( Element * elmt = qgraphicsitem_cast < Element * > ( item ) ) {
elements_to_move < < elmt ;
2007-10-27 13:18:17 +00:00
} else if ( DiagramTextItem * t = qgraphicsitem_cast < DiagramTextItem * > ( item ) ) {
if ( ! t - > parentItem ( ) ) texts_to_move < < t ;
2007-09-15 22:14:23 +00:00
}
}
// pour chaque element deplace, determine les conducteurs qui seront modifies
foreach ( Element * elmt , elements_to_move ) {
foreach ( Terminal * terminal , elmt - > terminals ( ) ) {
2007-10-03 17:02:39 +00:00
foreach ( Conductor * conductor , terminal - > conductors ( ) ) {
2007-09-15 22:14:23 +00:00
Terminal * other_terminal ;
2007-10-03 17:02:39 +00:00
if ( conductor - > terminal1 = = terminal ) {
other_terminal = conductor - > terminal2 ;
2007-09-15 22:14:23 +00:00
} else {
2007-10-03 17:02:39 +00:00
other_terminal = conductor - > terminal1 ;
2007-09-15 22:14:23 +00:00
}
// si les deux elements du conducteur sont deplaces
if ( elements_to_move . contains ( static_cast < Element * > ( other_terminal - > parentItem ( ) ) ) ) {
2007-10-03 17:02:39 +00:00
conductors_to_move < < conductor ;
2007-09-15 22:14:23 +00:00
} else {
2007-10-03 17:02:39 +00:00
conductors_to_update . insert ( conductor , terminal ) ;
2007-09-15 22:14:23 +00:00
}
}
}
}
moved_elements_fetched = true ;
}
2007-09-30 12:35:25 +00:00
2007-10-27 13:18:17 +00:00
/**
Deplace les elements , conducteurs et textes selectionnes en gerant au
mieux les conducteurs ( seuls les conducteurs dont un seul des elements
est deplace sont recalcules , les autres sont deplaces ) .
@ param diff Translation a effectuer
@ param dontmove QGraphicsItem ( optionnel ) a ne pas deplacer ; note : ce
parametre ne concerne que les elements et les champs de texte .
*/
void Diagram : : moveElements ( const QPointF & diff , QGraphicsItem * dontmove ) {
// inutile de deplacer les autres elements s'il n'y a pas eu de mouvement concret
if ( diff . isNull ( ) ) return ;
current_movement + = diff ;
// deplace les elements selectionnes
foreach ( Element * element , elementsToMove ( ) ) {
2009-04-28 18:04:29 +00:00
if ( dontmove & & element = = dontmove ) continue ;
2007-10-27 13:18:17 +00:00
element - > setPos ( element - > pos ( ) + diff ) ;
}
// deplace certains conducteurs
foreach ( Conductor * conductor , conductorsToMove ( ) ) {
conductor - > setPos ( conductor - > pos ( ) + diff ) ;
}
// recalcule les autres conducteurs
const QHash < Conductor * , Terminal * > & conductors_modify = conductorsToUpdate ( ) ;
foreach ( Conductor * conductor , conductors_modify . keys ( ) ) {
conductor - > updateWithNewPos ( QRectF ( ) , conductors_modify [ conductor ] , conductors_modify [ conductor ] - > amarrageConductor ( ) ) ;
}
// deplace les champs de texte
foreach ( DiagramTextItem * dti , textsToMove ( ) ) {
2009-04-28 18:04:29 +00:00
if ( dontmove & & dti = = dontmove ) continue ;
2007-10-27 13:18:17 +00:00
dti - > setPos ( dti - > pos ( ) + diff ) ;
}
}
2009-04-03 19:30:25 +00:00
/**
Permet de savoir si un element est utilise sur un schema
@ param location Emplacement d ' un element
@ return true si l ' element location est utilise sur ce schema , false sinon
*/
bool Diagram : : usesElement ( const ElementsLocation & location ) {
foreach ( CustomElement * element , customElements ( ) ) {
if ( element - > location ( ) = = location ) {
return ( true ) ;
}
}
return ( false ) ;
}
2009-11-22 16:12:22 +00:00
/**
Cette methode permet d ' appliquer de nouvelles options de rendu tout en
accedant aux proprietes de rendu en cours .
@ param new_properties Nouvelles options de rendu a appliquer
@ return les options de rendu avant l ' application de new_properties
*/
ExportProperties Diagram : : applyProperties ( const ExportProperties & new_properties ) {
// exporte les options de rendu en cours
ExportProperties old_properties ;
old_properties . draw_grid = displayGrid ( ) ;
old_properties . draw_border = border_and_inset . borderIsDisplayed ( ) ;
old_properties . draw_inset = border_and_inset . insetIsDisplayed ( ) ;
old_properties . draw_terminals = drawTerminals ( ) ;
old_properties . draw_colored_conductors = drawColoredConductors ( ) ;
old_properties . exported_area = useBorder ( ) ? QET : : BorderArea : QET : : ElementsArea ;
// applique les nouvelles options de rendu
setUseBorder ( new_properties . exported_area = = QET : : BorderArea ) ;
setDrawTerminals ( new_properties . draw_terminals ) ;
setDrawColoredConductors ( new_properties . draw_colored_conductors ) ;
setDisplayGrid ( new_properties . draw_grid ) ;
border_and_inset . displayBorder ( new_properties . draw_border ) ;
border_and_inset . displayInset ( new_properties . draw_inset ) ;
// retourne les anciennes options de rendu
return ( old_properties ) ;
}
2009-05-20 21:29:17 +00:00
/**
@ param pos Position cartesienne ( ex : 10.3 , 45.2 ) a transformer en position
dans la grille ( ex : B2 )
@ return la position dans la grille correspondant a pos
*/
DiagramPosition Diagram : : convertPosition ( const QPointF & pos ) {
// decale la position pour prendre en compte les marges en haut a gauche du schema
QPointF final_pos = pos - QPointF ( margin , margin ) ;
// delegue le calcul au BorderInset
DiagramPosition diagram_position = border_and_inset . convertPosition ( final_pos ) ;
// embarque la position cartesienne
diagram_position . setPosition ( pos ) ;
return ( diagram_position ) ;
}
2007-10-10 17:50:26 +00:00
/**
Definit s ' il faut afficher ou non les bornes
@ param dt true pour afficher les bornes , false sinon
*/
2007-09-30 12:35:25 +00:00
void Diagram : : setDrawTerminals ( bool dt ) {
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( Terminal * t = qgraphicsitem_cast < Terminal * > ( qgi ) ) {
t - > setVisible ( dt ) ;
}
}
}
2007-10-03 13:11:47 +00:00
2009-11-22 16:12:22 +00:00
/**
Definit s ' il faut respecter ou non les couleurs des conducteurs .
Si non , les conducteurs sont tous dessines en noir .
@ param dcc true pour respecter les couleurs , false sinon
*/
void Diagram : : setDrawColoredConductors ( bool dcc ) {
draw_colored_conductors_ = dcc ;
}
2007-10-10 17:50:26 +00:00
/**
@ return la liste des conducteurs selectionnes sur le schema
*/
2007-10-03 17:02:39 +00:00
QSet < Conductor * > Diagram : : selectedConductors ( ) const {
QSet < Conductor * > conductors_set ;
2007-10-03 13:11:47 +00:00
foreach ( QGraphicsItem * qgi , selectedItems ( ) ) {
2007-10-03 17:02:39 +00:00
if ( Conductor * c = qgraphicsitem_cast < Conductor * > ( qgi ) ) {
conductors_set < < c ;
2007-10-03 13:11:47 +00:00
}
}
2007-10-03 17:02:39 +00:00
return ( conductors_set ) ;
2007-10-03 13:11:47 +00:00
}
2007-11-03 20:20:34 +00:00
/// @return true si le presse-papier semble contenir un schema
bool Diagram : : clipboardMayContainDiagram ( ) {
QString clipboard_text = QApplication : : clipboard ( ) - > text ( ) . trimmed ( ) ;
bool may_be_diagram = clipboard_text . startsWith ( " <diagram " ) & & clipboard_text . endsWith ( " </diagram> " ) ;
return ( may_be_diagram ) ;
}
2007-11-09 13:06:51 +00:00
2009-04-03 19:30:25 +00:00
/**
@ return le projet auquel ce schema appartient ou 0 s ' il s ' agit d ' un schema
independant .
*/
QETProject * Diagram : : project ( ) const {
return ( project_ ) ;
}
/**
@ param project le nouveau projet auquel ce schema appartient ou 0 s ' il
s ' agit d ' un schema independant . Indiquer 0 pour rendre ce schema independant .
*/
void Diagram : : setProject ( QETProject * project ) {
project_ = project ;
}
2009-04-05 11:48:26 +00:00
2009-04-03 19:30:25 +00:00
/**
@ return true si le schema est en lecture seule
*/
bool Diagram : : isReadOnly ( ) const {
return ( read_only_ ) ;
}
/**
@ param read_only true pour passer le schema en lecture seule , false sinon
*/
void Diagram : : setReadOnly ( bool read_only ) {
if ( read_only_ ! = read_only ) {
read_only_ = read_only ;
emit ( readOnlyChanged ( read_only_ ) ) ;
}
}
2007-11-09 13:06:51 +00:00
/**
@ return Le contenu du schema . Les conducteurs sont tous places dans
conductorsToMove .
*/
DiagramContent Diagram : : content ( ) const {
DiagramContent dc ;
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( Element * e = qgraphicsitem_cast < Element * > ( qgi ) ) {
dc . elements < < e ;
} else if ( DiagramTextItem * dti = qgraphicsitem_cast < DiagramTextItem * > ( qgi ) ) {
dc . textFields < < dti ;
} else if ( Conductor * c = qgraphicsitem_cast < Conductor * > ( qgi ) ) {
dc . conductorsToMove < < c ;
}
}
return ( dc ) ;
}
/**
@ return le contenu selectionne du schema .
*/
DiagramContent Diagram : : selectedContent ( ) {
2007-11-11 16:12:45 +00:00
invalidateMovedElements ( ) ;
2007-11-09 13:06:51 +00:00
DiagramContent dc ;
dc . elements = elementsToMove ( ) . toList ( ) ;
dc . textFields = textsToMove ( ) . toList ( ) ;
dc . conductorsToMove = conductorsToMove ( ) . toList ( ) ;
dc . conductorsToUpdate = conductorsToUpdate ( ) ;
2007-11-11 16:12:45 +00:00
// recupere les conducteurs selectionnes isoles (= non deplacables mais supprimables)
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( Conductor * c = qgraphicsitem_cast < Conductor * > ( qgi ) ) {
if (
c - > isSelected ( ) & & \
! c - > terminal1 - > parentItem ( ) - > isSelected ( ) & & \
! c - > terminal2 - > parentItem ( ) - > isSelected ( )
) {
dc . otherConductors < < c ;
}
}
}
invalidateMovedElements ( ) ;
2007-11-09 13:06:51 +00:00
return ( dc ) ;
}
2009-06-16 22:37:15 +00:00
/**
@ return true s ' il est possible de tourner les elements selectionnes .
Concretement , cette methode retourne true s ' il y a des elements selectionnes
et qu ' au moins l ' un d ' entre eux peut etre pivote .
*/
bool Diagram : : canRotateSelection ( ) const {
foreach ( QGraphicsItem * qgi , selectedItems ( ) ) {
2009-11-29 21:56:48 +00:00
if ( /*DiagramTextItem *dti = */ qgraphicsitem_cast < DiagramTextItem * > ( qgi ) ) {
return ( true ) ;
} else if ( Element * e = qgraphicsitem_cast < Element * > ( qgi ) ) {
2009-06-16 22:37:15 +00:00
// l'element est-il pivotable ?
if ( e - > orientation ( ) . current ( ) ! = e - > orientation ( ) . next ( ) ) {
return ( true ) ;
}
}
}
return ( false ) ;
}