2006-10-27 15:47:22 +00:00
|
|
|
|
#include <QtDebug>
|
|
|
|
|
#include "conducteur.h"
|
|
|
|
|
#include "element.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Constructeur
|
|
|
|
|
@param p1 Premiere Borne auquel le conducteur est lie
|
|
|
|
|
@param p2 Seconde Borne auquel le conducteur est lie
|
|
|
|
|
@param parent Element parent du conducteur (0 par defaut)
|
|
|
|
|
@param scene QGraphicsScene auquelle appartient le conducteur
|
|
|
|
|
*/
|
|
|
|
|
Conducteur::Conducteur(Borne *p1, Borne* p2, Element *parent, QGraphicsScene *scene) : QGraphicsPathItem(parent, scene) {
|
|
|
|
|
// bornes que le conducteur relie
|
|
|
|
|
borne1 = p1;
|
|
|
|
|
borne2 = p2;
|
|
|
|
|
// ajout du conducteur a la liste de conducteurs de chacune des deux bornes
|
|
|
|
|
bool ajout_p1 = borne1 -> addConducteur(this);
|
|
|
|
|
bool ajout_p2 = borne2 -> addConducteur(this);
|
|
|
|
|
// en cas d'echec de l'ajout (conducteur deja existant notamment)
|
|
|
|
|
if (!ajout_p1 || !ajout_p2) return;
|
|
|
|
|
destroyed = false;
|
|
|
|
|
// le conducteur est represente par un trait fin
|
|
|
|
|
QPen t;
|
|
|
|
|
t.setWidthF(1.0);
|
|
|
|
|
setPen(t);
|
|
|
|
|
// calcul du rendu du conducteur
|
|
|
|
|
calculeConducteur();
|
2006-11-26 21:35:05 +00:00
|
|
|
|
setFlags(QGraphicsItem::ItemIsSelectable);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Met a jour la representation graphique du conducteur.
|
|
|
|
|
@param rect Rectangle a mettre a jour
|
|
|
|
|
*/
|
|
|
|
|
void Conducteur::update(const QRectF &rect = QRectF()) {
|
|
|
|
|
calculeConducteur();
|
|
|
|
|
QGraphicsPathItem::update(rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Met a jour la representation graphique du conducteur.
|
|
|
|
|
@param x abscisse du rectangle a mettre a jour
|
|
|
|
|
@param y ordonnee du rectangle a mettre a jour
|
|
|
|
|
@param width longueur du rectangle a mettre a jour
|
|
|
|
|
@param height hauteur du rectangle a mettre a jour
|
|
|
|
|
*/
|
|
|
|
|
void Conducteur::update(qreal x, qreal y, qreal width, qreal height) {
|
|
|
|
|
calculeConducteur();
|
|
|
|
|
QGraphicsPathItem::update(x, y, width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Met a jour le QPainterPath constituant le conducteur pour obtenir
|
|
|
|
|
un conducteur uniquement compose de droites reliant les deux bornes.
|
|
|
|
|
*/
|
|
|
|
|
void Conducteur::calculeConducteur() {
|
|
|
|
|
QPainterPath t;
|
|
|
|
|
|
|
|
|
|
QPointF p1 = borne1 -> amarrageConducteur();
|
|
|
|
|
QPointF p2 = borne2 -> amarrageConducteur();
|
|
|
|
|
|
|
|
|
|
QPointF depart, arrivee;
|
|
|
|
|
Borne::Orientation ori_depart, ori_arrivee;
|
|
|
|
|
// distingue le depart de l'arrivee : le trajet se fait toujours de gauche a droite
|
|
|
|
|
if (p1.x() <= p2.x()) {
|
|
|
|
|
depart = mapFromScene(p1);
|
|
|
|
|
arrivee = mapFromScene(p2);
|
|
|
|
|
ori_depart = borne1 -> orientation();
|
|
|
|
|
ori_arrivee = borne2 -> orientation();
|
|
|
|
|
} else {
|
|
|
|
|
depart = mapFromScene(p2);
|
|
|
|
|
arrivee = mapFromScene(p1);
|
|
|
|
|
ori_depart = borne2 -> orientation();
|
|
|
|
|
ori_arrivee = borne1 -> orientation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// debut du trajet
|
|
|
|
|
t.moveTo(depart);
|
|
|
|
|
if (depart.y() < arrivee.y()) {
|
|
|
|
|
// trajet descendant
|
|
|
|
|
if ((ori_depart == Borne::Nord && (ori_arrivee == Borne::Sud || ori_arrivee == Borne::Ouest)) || (ori_depart == Borne::Est && ori_arrivee == Borne::Ouest)) {
|
|
|
|
|
// cas <20> 3 <20>
|
|
|
|
|
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
|
|
|
|
|
t.lineTo(ligne_inter_x, depart.y());
|
|
|
|
|
t.lineTo(ligne_inter_x, arrivee.y());
|
|
|
|
|
} else if ((ori_depart == Borne::Sud && (ori_arrivee == Borne::Nord || ori_arrivee == Borne::Est)) || (ori_depart == Borne::Ouest && ori_arrivee == Borne::Est)) {
|
|
|
|
|
// cas <20> 4 <20>
|
|
|
|
|
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
|
|
|
|
|
t.lineTo(depart.x(), ligne_inter_y);
|
|
|
|
|
t.lineTo(arrivee.x(), ligne_inter_y);
|
|
|
|
|
} else if ((ori_depart == Borne::Nord || ori_depart == Borne::Est) && (ori_arrivee == Borne::Nord || ori_arrivee == Borne::Est)) {
|
|
|
|
|
t.lineTo(arrivee.x(), depart.y()); // cas <20> 2 <20>
|
|
|
|
|
} else t.lineTo(depart.x(), arrivee.y()); // cas <20> 1 <20>
|
|
|
|
|
} else {
|
|
|
|
|
// trajet montant
|
|
|
|
|
if ((ori_depart == Borne::Ouest && (ori_arrivee == Borne::Est || ori_arrivee == Borne::Sud)) || (ori_depart == Borne::Nord && ori_arrivee == Borne::Sud)) {
|
|
|
|
|
// cas <20> 3 <20>
|
|
|
|
|
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
|
|
|
|
|
t.lineTo(depart.x(), ligne_inter_y);
|
|
|
|
|
t.lineTo(arrivee.x(), ligne_inter_y);
|
|
|
|
|
} else if ((ori_depart == Borne::Est && (ori_arrivee == Borne::Ouest || ori_arrivee == Borne::Nord)) || (ori_depart == Borne::Sud && ori_arrivee == Borne::Nord)) {
|
|
|
|
|
// cas <20> 4 <20>
|
|
|
|
|
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
|
|
|
|
|
t.lineTo(ligne_inter_x, depart.y());
|
|
|
|
|
t.lineTo(ligne_inter_x, arrivee.y());
|
|
|
|
|
} else if ((ori_depart == Borne::Ouest || ori_depart == Borne::Nord) && (ori_arrivee == Borne::Ouest || ori_arrivee == Borne::Nord)) {
|
|
|
|
|
t.lineTo(depart.x(), arrivee.y()); // cas <20> 2 <20>
|
|
|
|
|
} else t.lineTo(arrivee.x(), depart.y()); // cas <20> 1 <20>
|
|
|
|
|
}
|
|
|
|
|
// fin du trajet
|
|
|
|
|
t.lineTo(arrivee);
|
|
|
|
|
setPath(t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Dessine le conducteur sans antialiasing.
|
|
|
|
|
@param qp Le QPainter a utiliser pour dessiner le conducteur
|
|
|
|
|
@param qsogi Les options de style pour le conducteur
|
|
|
|
|
@param qw Le QWidget sur lequel on dessine
|
|
|
|
|
*/
|
2006-11-26 21:35:05 +00:00
|
|
|
|
void Conducteur::paint(QPainter *qp, const QStyleOptionGraphicsItem */*qsogi*/, QWidget */*qw*/) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
qp -> save();
|
|
|
|
|
qp -> setRenderHint(QPainter::Antialiasing, false);
|
|
|
|
|
qp -> setRenderHint(QPainter::TextAntialiasing, false);
|
|
|
|
|
qp -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
2006-11-26 21:35:05 +00:00
|
|
|
|
|
|
|
|
|
// recupere le QPen et la QBrush du QPainter
|
|
|
|
|
QPen pen = qp -> pen();
|
|
|
|
|
QBrush brush = qp -> brush();
|
|
|
|
|
|
|
|
|
|
// attributs par defaut
|
|
|
|
|
pen.setJoinStyle(Qt::MiterJoin);
|
|
|
|
|
pen.setCapStyle(Qt::SquareCap);
|
|
|
|
|
pen.setColor(isSelected() ? Qt::red : Qt::black);
|
|
|
|
|
pen.setStyle(Qt::SolidLine);
|
|
|
|
|
pen.setWidthF(1.0);
|
|
|
|
|
brush.setStyle(Qt::NoBrush);
|
|
|
|
|
|
|
|
|
|
// affectation du QPen et de la QBrush modifies au QPainter
|
|
|
|
|
qp -> setPen(pen);
|
|
|
|
|
qp -> setBrush(brush);
|
|
|
|
|
|
|
|
|
|
qp -> drawPath(path());
|
|
|
|
|
//QGraphicsPathItem::paint(qp, qsogi, qw);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
qp -> restore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Indique si deux orientations de Borne sont sur le meme axe (Vertical / Horizontal).
|
|
|
|
|
@param a La premiere orientation de Borne
|
|
|
|
|
@param b La seconde orientation de Borne
|
|
|
|
|
@return Un booleen a true si les deux orientations de bornes sont sur le meme axe
|
|
|
|
|
*/
|
|
|
|
|
bool Conducteur::surLeMemeAxe(Borne::Orientation a, Borne::Orientation b) {
|
|
|
|
|
if ((a == Borne::Nord || a == Borne::Sud) && (b == Borne::Nord || b == Borne::Sud)) return(true);
|
|
|
|
|
else if ((a == Borne::Est || a == Borne::Ouest) && (b == Borne::Est || b == Borne::Ouest)) return(true);
|
|
|
|
|
else return(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Indique si une orientation de borne est horizontale (Est / Ouest).
|
|
|
|
|
@param a L'orientation de borne
|
|
|
|
|
@return True si l'orientation de borne est horizontale, false sinon
|
|
|
|
|
*/
|
|
|
|
|
bool Conducteur::estHorizontale(Borne::Orientation a) {
|
|
|
|
|
return(a == Borne::Est || a == Borne::Ouest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Indique si une orientation de borne est verticale (Nord / Sud).
|
|
|
|
|
@param a L'orientation de borne
|
|
|
|
|
@return True si l'orientation de borne est verticale, false sinon
|
|
|
|
|
*/
|
|
|
|
|
bool Conducteur::estVerticale(Borne::Orientation a) {
|
|
|
|
|
return(a == Borne::Nord || a == Borne::Sud);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Methode de preparation a la destruction du conducteur ; le conducteur se detache de ses deux bornes
|
|
|
|
|
*/
|
|
|
|
|
void Conducteur::destroy() {
|
|
|
|
|
destroyed = true;
|
|
|
|
|
borne1 -> removeConducteur(this);
|
|
|
|
|
borne2 -> removeConducteur(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Methode de validation d'element XML
|
|
|
|
|
@param e Un element XML sense represente un Conducteur
|
|
|
|
|
@return true si l'element XML represente bien un Conducteur ; false sinon
|
|
|
|
|
*/
|
|
|
|
|
bool Conducteur::valideXml(QDomElement &e){
|
|
|
|
|
// verifie le nom du tag
|
|
|
|
|
if (e.tagName() != "conducteur") return(false);
|
|
|
|
|
|
|
|
|
|
// verifie la presence des attributs minimaux
|
|
|
|
|
if (!e.hasAttribute("borne1")) return(false);
|
|
|
|
|
if (!e.hasAttribute("borne2")) return(false);
|
|
|
|
|
|
|
|
|
|
bool conv_ok;
|
|
|
|
|
// parse l'abscisse
|
|
|
|
|
e.attribute("borne1").toInt(&conv_ok);
|
|
|
|
|
if (!conv_ok) return(false);
|
|
|
|
|
|
|
|
|
|
// parse l'ordonnee
|
|
|
|
|
e.attribute("borne2").toInt(&conv_ok);
|
|
|
|
|
if (!conv_ok) return(false);
|
|
|
|
|
return(true);
|
|
|
|
|
}
|