Ajout de l'editeur d'elements

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@94 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
xavierqet 2007-06-30 17:41:07 +00:00
parent 0472392977
commit 75ca8fd3f2
79 changed files with 3867 additions and 345 deletions

View File

@ -74,7 +74,7 @@ Conducer::~Conducer() {
*/ */
void Conducer::update(const QRectF &rect) { void Conducer::update(const QRectF &rect) {
// utilise soit la fonction priv_modifieConducteur soit la fonction priv_calculeConducteur // utilise soit la fonction priv_modifieConducteur soit la fonction priv_calculeConducteur
void (Conducer::* fonction_update) (const QPointF &, Terminal::Orientation, const QPointF &, Terminal::Orientation); void (Conducer::* fonction_update) (const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
fonction_update = (nbSegments() && modified_path) ? &Conducer::priv_modifieConducer : &Conducer::priv_calculeConducer; fonction_update = (nbSegments() && modified_path) ? &Conducer::priv_modifieConducer : &Conducer::priv_calculeConducer;
// appelle la bonne fonction pour calculer l'aspect du conducteur // appelle la bonne fonction pour calculer l'aspect du conducteur
@ -147,7 +147,7 @@ void Conducer::segmentsToPath() {
@param p2 Coordonnees du point d'amarrage de la borne 2 @param p2 Coordonnees du point d'amarrage de la borne 2
@param o2 Orientation de la borne 2 @param o2 Orientation de la borne 2
*/ */
void Conducer::priv_modifieConducer(const QPointF &p1, Terminal::Orientation, const QPointF &p2, Terminal::Orientation) { void Conducer::priv_modifieConducer(const QPointF &p1, QET::Orientation, const QPointF &p2, QET::Orientation) {
Q_ASSERT_X(nbSegments() > 1, "priv_modifieConducer", "pas de points a modifier"); Q_ASSERT_X(nbSegments() > 1, "priv_modifieConducer", "pas de points a modifier");
// recupere les dernieres coordonnees connues des bornes // recupere les dernieres coordonnees connues des bornes
@ -194,9 +194,9 @@ void Conducer::priv_modifieConducer(const QPointF &p1, Terminal::Orientation, co
@param p2 Coordonnees du point d'amarrage de la borne 2 @param p2 Coordonnees du point d'amarrage de la borne 2
@param o2 Orientation de la borne 2 @param o2 Orientation de la borne 2
*/ */
void Conducer::priv_calculeConducer(const QPointF &p1, Terminal::Orientation o1, const QPointF &p2, Terminal::Orientation o2) { void Conducer::priv_calculeConducer(const QPointF &p1, QET::Orientation o1, const QPointF &p2, QET::Orientation o2) {
QPointF sp1, sp2, depart, newp1, newp2, arrivee, depart0, arrivee0; QPointF sp1, sp2, depart, newp1, newp2, arrivee, depart0, arrivee0;
Terminal::Orientation ori_depart, ori_arrivee; QET::Orientation ori_depart, ori_arrivee;
// s'assure qu'il n'y a ni points // s'assure qu'il n'y a ni points
QList<QPointF> points; QList<QPointF> points;
@ -236,34 +236,34 @@ void Conducer::priv_calculeConducer(const QPointF &p1, Terminal::Orientation o1,
// commence le vrai trajet // commence le vrai trajet
if (depart.y() < arrivee.y()) { if (depart.y() < arrivee.y()) {
// trajet descendant // trajet descendant
if ((ori_depart == Terminal::Nord && (ori_arrivee == Terminal::Sud || ori_arrivee == Terminal::Ouest)) || (ori_depart == Terminal::Est && ori_arrivee == Terminal::Ouest)) { if ((ori_depart == QET::North && (ori_arrivee == QET::South || ori_arrivee == QET::West)) || (ori_depart == QET::East && ori_arrivee == QET::West)) {
// cas « 3 » // cas « 3 »
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0; qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
points << QPointF(ligne_inter_x, depart.y()); points << QPointF(ligne_inter_x, depart.y());
points << QPointF(ligne_inter_x, arrivee.y()); points << QPointF(ligne_inter_x, arrivee.y());
} else if ((ori_depart == Terminal::Sud && (ori_arrivee == Terminal::Nord || ori_arrivee == Terminal::Est)) || (ori_depart == Terminal::Ouest && ori_arrivee == Terminal::Est)) { } else if ((ori_depart == QET::South && (ori_arrivee == QET::North || ori_arrivee == QET::East)) || (ori_depart == QET::West && ori_arrivee == QET::East)) {
// cas « 4 » // cas « 4 »
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0; qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
points << QPointF(depart.x(), ligne_inter_y); points << QPointF(depart.x(), ligne_inter_y);
points << QPointF(arrivee.x(), ligne_inter_y); points << QPointF(arrivee.x(), ligne_inter_y);
} else if ((ori_depart == Terminal::Nord || ori_depart == Terminal::Est) && (ori_arrivee == Terminal::Nord || ori_arrivee == Terminal::Est)) { } else if ((ori_depart == QET::North || ori_depart == QET::East) && (ori_arrivee == QET::North || ori_arrivee == QET::East)) {
points << QPointF(arrivee.x(), depart.y()); // cas « 2 » points << QPointF(arrivee.x(), depart.y()); // cas « 2 »
} else { } else {
points << QPointF(depart.x(), arrivee.y()); // cas « 1 » points << QPointF(depart.x(), arrivee.y()); // cas « 1 »
} }
} else { } else {
// trajet montant // trajet montant
if ((ori_depart == Terminal::Ouest && (ori_arrivee == Terminal::Est || ori_arrivee == Terminal::Sud)) || (ori_depart == Terminal::Nord && ori_arrivee == Terminal::Sud)) { if ((ori_depart == QET::West && (ori_arrivee == QET::East || ori_arrivee == QET::South)) || (ori_depart == QET::North && ori_arrivee == QET::South)) {
// cas « 3 » // cas « 3 »
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0; qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
points << QPointF(depart.x(), ligne_inter_y); points << QPointF(depart.x(), ligne_inter_y);
points << QPointF(arrivee.x(), ligne_inter_y); points << QPointF(arrivee.x(), ligne_inter_y);
} else if ((ori_depart == Terminal::Est && (ori_arrivee == Terminal::Ouest || ori_arrivee == Terminal::Nord)) || (ori_depart == Terminal::Sud && ori_arrivee == Terminal::Nord)) { } else if ((ori_depart == QET::East && (ori_arrivee == QET::West || ori_arrivee == QET::North)) || (ori_depart == QET::South && ori_arrivee == QET::North)) {
// cas « 4 » // cas « 4 »
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0; qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
points << QPointF(ligne_inter_x, depart.y()); points << QPointF(ligne_inter_x, depart.y());
points << QPointF(ligne_inter_x, arrivee.y()); points << QPointF(ligne_inter_x, arrivee.y());
} else if ((ori_depart == Terminal::Ouest || ori_depart == Terminal::Nord) && (ori_arrivee == Terminal::Ouest || ori_arrivee == Terminal::Nord)) { } else if ((ori_depart == QET::West || ori_depart == QET::North) && (ori_arrivee == QET::West || ori_arrivee == QET::North)) {
points << QPointF(depart.x(), arrivee.y()); // cas « 2 » points << QPointF(depart.x(), arrivee.y()); // cas « 2 »
} else { } else {
points << QPointF(arrivee.x(), depart.y()); // cas « 1 » points << QPointF(arrivee.x(), depart.y()); // cas « 1 »
@ -287,19 +287,19 @@ void Conducer::priv_calculeConducer(const QPointF &p1, Terminal::Orientation o1,
@param ext_size la taille de la prolongation @param ext_size la taille de la prolongation
@return le point correspondant a la borne apres prolongation @return le point correspondant a la borne apres prolongation
*/ */
QPointF Conducer::extendTerminal(const QPointF &terminal, Terminal::Orientation terminal_orientation, qreal ext_size) { QPointF Conducer::extendTerminal(const QPointF &terminal, QET::Orientation terminal_orientation, qreal ext_size) {
QPointF extended_terminal; QPointF extended_terminal;
switch(terminal_orientation) { switch(terminal_orientation) {
case Terminal::Nord: case QET::North:
extended_terminal = QPointF(terminal.x(), terminal.y() - ext_size); extended_terminal = QPointF(terminal.x(), terminal.y() - ext_size);
break; break;
case Terminal::Est: case QET::East:
extended_terminal = QPointF(terminal.x() + ext_size, terminal.y()); extended_terminal = QPointF(terminal.x() + ext_size, terminal.y());
break; break;
case Terminal::Sud: case QET::South:
extended_terminal = QPointF(terminal.x(), terminal.y() + ext_size); extended_terminal = QPointF(terminal.x(), terminal.y() + ext_size);
break; break;
case Terminal::Ouest: case QET::West:
extended_terminal = QPointF(terminal.x() - ext_size, terminal.y()); extended_terminal = QPointF(terminal.x() - ext_size, terminal.y());
break; break;
default: extended_terminal = terminal; default: extended_terminal = terminal;
@ -356,36 +356,6 @@ void Conducer::paint(QPainter *qp, const QStyleOptionGraphicsItem */*qsogi*/, QW
qp -> restore(); 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 Conducer::surLeMemeAxe(Terminal::Orientation a, Terminal::Orientation b) {
if ((a == Terminal::Nord || a == Terminal::Sud) && (b == Terminal::Nord || b == Terminal::Sud)) return(true);
else if ((a == Terminal::Est || a == Terminal::Ouest) && (b == Terminal::Est || b == Terminal::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 Conducer::estHorizontale(Terminal::Orientation a) {
return(a == Terminal::Est || a == Terminal::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 Conducer::estVerticale(Terminal::Orientation a) {
return(a == Terminal::Nord || a == Terminal::Sud);
}
/** /**
Methode de preparation a la destruction du conducteur ; le conducteur se detache de ses deux bornes Methode de preparation a la destruction du conducteur ; le conducteur se detache de ses deux bornes
*/ */

View File

@ -71,17 +71,14 @@ class Conducer : public QGraphicsPathItem {
private: private:
void segmentsToPath(); void segmentsToPath();
void updatePoints(); void updatePoints();
void priv_calculeConducer(const QPointF &, Terminal::Orientation, const QPointF &, Terminal::Orientation); void priv_calculeConducer(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
void priv_modifieConducer(const QPointF &, Terminal::Orientation, const QPointF &, Terminal::Orientation); void priv_modifieConducer(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
int nbSegments() const; int nbSegments() const;
QList<QPointF> segmentsToPoints() const; QList<QPointF> segmentsToPoints() const;
void pointsToSegments(QList<QPointF>); void pointsToSegments(QList<QPointF>);
bool hasClickedOn(QPointF, QPointF) const; bool hasClickedOn(QPointF, QPointF) const;
void calculateTextItemPosition(); void calculateTextItemPosition();
static QPointF extendTerminal(const QPointF &, Terminal::Orientation, qreal = 12.0); static QPointF extendTerminal(const QPointF &, QET::Orientation, qreal = 12.0);
static bool surLeMemeAxe(Terminal::Orientation, Terminal::Orientation);
static bool estHorizontale(Terminal::Orientation a);
static bool estVerticale(Terminal::Orientation a);
static qreal conducer_bound(qreal tobound, qreal bound1, qreal bound2); static qreal conducer_bound(qreal tobound, qreal bound1, qreal bound2);
static qreal conducer_bound(qreal tobound, qreal bound, bool positive); static qreal conducer_bound(qreal tobound, qreal bound, bool positive);
}; };

View File

@ -1,7 +1,6 @@
#include "customelement.h" #include "customelement.h"
#include "elementtextitem.h" #include "elementtextitem.h"
#include "diagram.h" #include "diagram.h"
/** /**
Constructeur de la classe ElementPerso. Permet d'instancier un element Constructeur de la classe ElementPerso. Permet d'instancier un element
utilisable comme un element fixe a la difference que l'element perso lit utilisable comme un element fixe a la difference que l'element perso lit
@ -63,10 +62,10 @@ CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *
// ces attributs doivent etre presents et valides // ces attributs doivent etre presents et valides
int w, h, hot_x, hot_y; int w, h, hot_x, hot_y;
if ( if (
!attributeIsAnInteger(racine, QString("width"), &w) ||\ !QET::attributeIsAnInteger(racine, QString("width"), &w) ||\
!attributeIsAnInteger(racine, QString("height"), &h) ||\ !QET::attributeIsAnInteger(racine, QString("height"), &h) ||\
!attributeIsAnInteger(racine, QString("hotspot_x"), &hot_x) ||\ !QET::attributeIsAnInteger(racine, QString("hotspot_x"), &hot_x) ||\
!attributeIsAnInteger(racine, QString("hotspot_y"), &hot_y) ||\ !QET::attributeIsAnInteger(racine, QString("hotspot_y"), &hot_y) ||\
!validOrientationAttribute(racine) !validOrientationAttribute(racine)
) { ) {
if (etat != NULL) *etat = 5; if (etat != NULL) *etat = 5;
@ -78,6 +77,7 @@ CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *
setSize(w, h); setSize(w, h);
setHotspot(QPoint(hot_x, hot_y)); setHotspot(QPoint(hot_x, hot_y));
setConnexionsInternesAcceptees(racine.attribute("ci") == "true"); setConnexionsInternesAcceptees(racine.attribute("ci") == "true");
// la definition est supposee avoir des enfants // la definition est supposee avoir des enfants
if (racine.firstChild().isNull()) { if (racine.firstChild().isNull()) {
if (etat != NULL) *etat = 6; if (etat != NULL) *etat = 6;
@ -194,12 +194,20 @@ bool CustomElement::parseElement(QDomElement &e, QPainter &qp, Diagram *s) {
@return true si l'analyse reussit, false sinon @return true si l'analyse reussit, false sinon
*/ */
bool CustomElement::parseLine(QDomElement &e, QPainter &qp) { bool CustomElement::parseLine(QDomElement &e, QPainter &qp) {
//qDebug() << "parseLine sur " << (void *)(&dessin);
// qDebug() << names.name() << (void *)(&dessin);
// qp.end();
// PartLine t;
// t.fromXml(e);
// t.renderToCustomElement(*this);
// qp.begin(&dessin);
//return(true);
// verifie la presence et la validite des attributs obligatoires // verifie la presence et la validite des attributs obligatoires
double x1, y1, x2, y2; double x1, y1, x2, y2;
if (!attributeIsAReal(e, QString("x1"), &x1)) return(false); if (!QET::attributeIsAReal(e, QString("x1"), &x1)) return(false);
if (!attributeIsAReal(e, QString("y1"), &y1)) return(false); if (!QET::attributeIsAReal(e, QString("y1"), &y1)) return(false);
if (!attributeIsAReal(e, QString("x2"), &x2)) return(false); if (!QET::attributeIsAReal(e, QString("x2"), &x2)) return(false);
if (!attributeIsAReal(e, QString("y2"), &y2)) return(false); if (!QET::attributeIsAReal(e, QString("y2"), &y2)) return(false);
qp.save(); qp.save();
setPainterStyle(e, qp); setPainterStyle(e, qp);
qp.drawLine(QLineF(x1, y1, x2, y2)); qp.drawLine(QLineF(x1, y1, x2, y2));
@ -223,9 +231,9 @@ bool CustomElement::parseLine(QDomElement &e, QPainter &qp) {
bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) { bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires // verifie la presence des attributs obligatoires
double cercle_x, cercle_y, cercle_r; double cercle_x, cercle_y, cercle_r;
if (!attributeIsAReal(e, QString("x"), &cercle_x)) return(false); if (!QET::attributeIsAReal(e, QString("x"), &cercle_x)) return(false);
if (!attributeIsAReal(e, QString("y"), &cercle_y)) return(false); if (!QET::attributeIsAReal(e, QString("y"), &cercle_y)) return(false);
if (!attributeIsAReal(e, QString("diameter"), &cercle_r)) return(false); if (!QET::attributeIsAReal(e, QString("diameter"), &cercle_r)) return(false);
qp.save(); qp.save();
setPainterStyle(e, qp); setPainterStyle(e, qp);
qp.drawEllipse(QRectF(cercle_x, cercle_y, cercle_r, cercle_r)); qp.drawEllipse(QRectF(cercle_x, cercle_y, cercle_r, cercle_r));
@ -250,10 +258,10 @@ bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) {
bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp) { bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires // verifie la presence des attributs obligatoires
double ellipse_x, ellipse_y, ellipse_l, ellipse_h; double ellipse_x, ellipse_y, ellipse_l, ellipse_h;
if (!attributeIsAReal(e, QString("x"), &ellipse_x)) return(false); if (!QET::attributeIsAReal(e, QString("x"), &ellipse_x)) return(false);
if (!attributeIsAReal(e, QString("y"), &ellipse_y)) return(false); if (!QET::attributeIsAReal(e, QString("y"), &ellipse_y)) return(false);
if (!attributeIsAReal(e, QString("width"), &ellipse_l)) return(false); if (!QET::attributeIsAReal(e, QString("width"), &ellipse_l)) return(false);
if (!attributeIsAReal(e, QString("height"), &ellipse_h)) return(false); if (!QET::attributeIsAReal(e, QString("height"), &ellipse_h)) return(false);
qp.save(); qp.save();
setPainterStyle(e, qp); setPainterStyle(e, qp);
qp.drawEllipse(QRectF(ellipse_x, ellipse_y, ellipse_l, ellipse_h)); qp.drawEllipse(QRectF(ellipse_x, ellipse_y, ellipse_l, ellipse_h));
@ -278,12 +286,12 @@ bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp) {
bool CustomElement::parseArc(QDomElement &e, QPainter &qp) { bool CustomElement::parseArc(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires // verifie la presence des attributs obligatoires
double arc_x, arc_y, arc_l, arc_h, arc_s, arc_a; double arc_x, arc_y, arc_l, arc_h, arc_s, arc_a;
if (!attributeIsAReal(e, QString("x"), &arc_x)) return(false); if (!QET::attributeIsAReal(e, QString("x"), &arc_x)) return(false);
if (!attributeIsAReal(e, QString("y"), &arc_y)) return(false); if (!QET::attributeIsAReal(e, QString("y"), &arc_y)) return(false);
if (!attributeIsAReal(e, QString("width"), &arc_l)) return(false); if (!QET::attributeIsAReal(e, QString("width"), &arc_l)) return(false);
if (!attributeIsAReal(e, QString("height"), &arc_h)) return(false); if (!QET::attributeIsAReal(e, QString("height"), &arc_h)) return(false);
if (!attributeIsAReal(e, QString("start"), &arc_s)) return(false); if (!QET::attributeIsAReal(e, QString("start"), &arc_s)) return(false);
if (!attributeIsAReal(e, QString("angle"), &arc_a)) return(false); if (!QET::attributeIsAReal(e, QString("angle"), &arc_a)) return(false);
qp.save(); qp.save();
setPainterStyle(e, qp); setPainterStyle(e, qp);
@ -306,7 +314,7 @@ bool CustomElement::parseArc(QDomElement &e, QPainter &qp) {
bool CustomElement::parsePolygon(QDomElement &e, QPainter &qp) { bool CustomElement::parsePolygon(QDomElement &e, QPainter &qp) {
int i = 1; int i = 1;
while(true) { while(true) {
if (attributeIsAReal(e, QString("x%1").arg(i)) && attributeIsAReal(e, QString("y%1").arg(i))) ++ i; if (QET::attributeIsAReal(e, QString("x%1").arg(i)) && QET::attributeIsAReal(e, QString("y%1").arg(i))) ++ i;
else break; else break;
} }
if (i < 3) return(false); if (i < 3) return(false);
@ -338,9 +346,9 @@ bool CustomElement::parseText(QDomElement &e, QPainter &qp) {
qreal pos_x, pos_y; qreal pos_x, pos_y;
int size; int size;
if ( if (
!attributeIsAReal(e, "x", &pos_x) ||\ !QET::attributeIsAReal(e, "x", &pos_x) ||\
!attributeIsAReal(e, "y", &pos_y) ||\ !QET::attributeIsAReal(e, "y", &pos_y) ||\
!attributeIsAnInteger(e, "size", &size) ||\ !QET::attributeIsAnInteger(e, "size", &size) ||\
!e.hasAttribute("text") !e.hasAttribute("text")
) return(false); ) return(false);
@ -368,9 +376,9 @@ bool CustomElement::parseInput(QDomElement &e, Diagram *s) {
qreal pos_x, pos_y; qreal pos_x, pos_y;
int size; int size;
if ( if (
!attributeIsAReal(e, "x", &pos_x) ||\ !QET::attributeIsAReal(e, "x", &pos_x) ||\
!attributeIsAReal(e, "y", &pos_y) ||\ !QET::attributeIsAReal(e, "y", &pos_y) ||\
!attributeIsAnInteger(e, "size", &size) !QET::attributeIsAnInteger(e, "size", &size)
) return(false); ) return(false);
ElementTextItem *eti = new ElementTextItem(e.attribute("text"), this, s); ElementTextItem *eti = new ElementTextItem(e.attribute("text"), this, s);
@ -394,14 +402,14 @@ bool CustomElement::parseInput(QDomElement &e, Diagram *s) {
bool CustomElement::parseTerminal(QDomElement &e, Diagram *s) { bool CustomElement::parseTerminal(QDomElement &e, Diagram *s) {
// verifie la presence et la validite des attributs obligatoires // verifie la presence et la validite des attributs obligatoires
double terminalx, terminaly; double terminalx, terminaly;
Terminal::Orientation terminalo; QET::Orientation terminalo;
if (!attributeIsAReal(e, QString("x"), &terminalx)) return(false); if (!QET::attributeIsAReal(e, QString("x"), &terminalx)) return(false);
if (!attributeIsAReal(e, QString("y"), &terminaly)) return(false); if (!QET::attributeIsAReal(e, QString("y"), &terminaly)) return(false);
if (!e.hasAttribute("orientation")) return(false); if (!e.hasAttribute("orientation")) return(false);
if (e.attribute("orientation") == "n") terminalo = Terminal::Nord; if (e.attribute("orientation") == "n") terminalo = QET::North;
else if (e.attribute("orientation") == "s") terminalo = Terminal::Sud; else if (e.attribute("orientation") == "s") terminalo = QET::South;
else if (e.attribute("orientation") == "e") terminalo = Terminal::Est; else if (e.attribute("orientation") == "e") terminalo = QET::East;
else if (e.attribute("orientation") == "w") terminalo = Terminal::Ouest; else if (e.attribute("orientation") == "w") terminalo = QET::West;
else return(false); else return(false);
new Terminal(terminalx, terminaly, terminalo, this, s); new Terminal(terminalx, terminaly, terminalo, this, s);
++ nb_terminals; ++ nb_terminals;
@ -419,44 +427,6 @@ void CustomElement::setQPainterAntiAliasing(QPainter &qp, bool aa) {
qp.setRenderHint(QPainter::SmoothPixmapTransform, aa); qp.setRenderHint(QPainter::SmoothPixmapTransform, aa);
} }
/**
Permet de savoir si l'attribut nom_attribut d'un element XML e est bien un
entier. Si oui, sa valeur est copiee dans entier.
@param e Element XML
@param nom_attribut Nom de l'attribut a analyser
@param entier Pointeur facultatif vers un entier
@return true si l'attribut est bien un entier, false sinon
*/
bool CustomElement::attributeIsAnInteger(QDomElement &e, QString nom_attribut, int *entier) {
// verifie la presence de l'attribut
if (!e.hasAttribute(nom_attribut)) return(false);
// verifie la validite de l'attribut
bool ok;
int tmp = e.attribute(nom_attribut).toInt(&ok);
if (!ok) return(false);
if (entier != NULL) *entier = tmp;
return(true);
}
/**
Permet de savoir si l'attribut nom_attribut d'un element XML e est bien un
reel. Si oui, sa valeur est copiee dans reel.
@param e Element XML
@param nom_attribut Nom de l'attribut a analyser
@param reel Pointeur facultatif vers un double
@return true si l'attribut est bien un reel, false sinon
*/
bool CustomElement::attributeIsAReal(QDomElement &e, QString nom_attribut, double *reel) {
// verifie la presence de l'attribut
if (!e.hasAttribute(nom_attribut)) return(false);
// verifie la validite de l'attribut
bool ok;
qreal tmp = e.attribute(nom_attribut).toDouble(&ok);
if (!ok) return(false);
if (reel != NULL) *reel = tmp;
return(true);
}
/** /**
Verifie si l'attribut "orientation" de l'element XML e correspond bien a la Verifie si l'attribut "orientation" de l'element XML e correspond bien a la
syntaxe decrivant les orientations possibles pour un element. syntaxe decrivant les orientations possibles pour un element.
@ -477,30 +447,7 @@ bool CustomElement::attributeIsAReal(QDomElement &e, QString nom_attribut, doubl
@return true si l'attribut "orientation" est valide, false sinon @return true si l'attribut "orientation" est valide, false sinon
*/ */
bool CustomElement::validOrientationAttribute(QDomElement &e) { bool CustomElement::validOrientationAttribute(QDomElement &e) {
// verifie la presence de l'attribut orientation return(ori.fromString(e.attribute("orientation")));
if (!e.hasAttribute("orientation")) return(false);
QString t = e.attribute("orientation");
// verification syntaxique : 4 lettres, un d, que des y ou des n pour le reste
if (t.length() != 4) return(false);
int d_pos = -1;
for (int i = 0 ; i < 4 ; ++ i) {
QChar c = t.at(i);
if (c != 'd' && c != 'y' && c != 'n') return(false);
if (c == 'd') {
if (d_pos == -1) d_pos = i;
else return(false);
}
}
if (d_pos == -1) return(false);
// orientation : 4 lettres = nord/est/sud/ouest avec d = default, y = yes et n = no
ori_n = (t.at(0) == 'd' || t.at(0) == 'y');
ori_e = (t.at(1) == 'd' || t.at(1) == 'y');
ori_s = (t.at(2) == 'd' || t.at(2) == 'y');
ori_w = (t.at(3) == 'd' || t.at(3) == 'y');
ori_d = (Terminal::Orientation)d_pos;
ori = ori_d;
return(true);
} }
/** /**

View File

@ -3,6 +3,9 @@
#include "fixedelement.h" #include "fixedelement.h"
#include <QtGui> #include <QtGui>
#include "nameslist.h" #include "nameslist.h"
class CustomElementPart;
// #include "customelementpart.h"
// #include "cep_line.h"
/** /**
Cette classe represente un element electrique. Elle est utilisable Cette classe represente un element electrique. Elle est utilisable
comme un element fixe. La difference est que l'element perso lit comme un element fixe. La difference est que l'element perso lit
@ -15,6 +18,8 @@ class CustomElement : public FixedElement {
CustomElement(QString &, QGraphicsItem * = 0, Diagram * = 0, int * = NULL); CustomElement(QString &, QGraphicsItem * = 0, Diagram * = 0, int * = NULL);
virtual ~CustomElement(); virtual ~CustomElement();
friend class CustomElementPart;
private: private:
CustomElement(const CustomElement &); CustomElement(const CustomElement &);
@ -47,8 +52,6 @@ class CustomElement : public FixedElement {
bool parseInput(QDomElement &, Diagram *); bool parseInput(QDomElement &, Diagram *);
bool parseTerminal(QDomElement &, Diagram *); bool parseTerminal(QDomElement &, Diagram *);
void setQPainterAntiAliasing(QPainter &, bool); void setQPainterAntiAliasing(QPainter &, bool);
bool attributeIsAnInteger(QDomElement &, QString, int * = NULL);
bool attributeIsAReal(QDomElement &, QString, double * = NULL);
bool validOrientationAttribute(QDomElement &); bool validOrientationAttribute(QDomElement &);
void setPainterStyle(QDomElement &, QPainter &); void setPainterStyle(QDomElement &, QPainter &);
}; };

View File

@ -153,7 +153,7 @@ void DiagramView::pivoter() {
if (scene -> selectedItems().isEmpty()) return; if (scene -> selectedItems().isEmpty()) return;
foreach (QGraphicsItem *item, scene -> selectedItems()) { foreach (QGraphicsItem *item, scene -> selectedItems()) {
if (Element *elt = qgraphicsitem_cast<Element *>(item)) { if (Element *elt = qgraphicsitem_cast<Element *>(item)) {
elt -> setOrientation(elt -> nextAcceptableOrientation()); elt -> setOrientation(elt -> orientation().next());
elt -> update(); elt -> update();
} }
} }

56
editor/circleeditor.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "circleeditor.h"
#include "partcircle.h"
CircleEditor::CircleEditor(PartCircle *circle, QWidget *parent) : QWidget(parent) {
part = circle;
x = new QLineEdit();
y = new QLineEdit();
r = new QLineEdit();
// QDoubleValidator *format = new QDoubleValidator(-1000.0, -1000.0, 4, this);
// x -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
// y -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
// h -> setValidator(new QDoubleValidator(0.0, 1000.0, 4, this));
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel(tr("Centre : ")), 0, 0);
grid -> addWidget(new QLabel("x"), 1, 0);
grid -> addWidget(x, 1, 1);
grid -> addWidget(new QLabel("y"), 1, 2);
grid -> addWidget(y, 1, 3);
grid -> addWidget(new QLabel(tr("Diam\350tre : ")), 2, 0);
grid -> addWidget(r, 2, 1);
updateForm();
connect(x, SIGNAL(editingFinished()), this, SLOT(updateCircle()));
connect(y, SIGNAL(editingFinished()), this, SLOT(updateCircle()));
connect(r, SIGNAL(editingFinished()), this, SLOT(updateCircle()));
}
CircleEditor::~CircleEditor() {
qDebug() << "~CircleEditor()";
}
void CircleEditor::updateCircle() {
qreal _x = x -> text().toDouble();
qreal _y = y -> text().toDouble();
qreal _d = r -> text().toDouble();
part -> setRect(
QRectF(
part -> mapFromScene(QPointF(_x - _d / 2.0, _y - _d / 2.0)),
QSizeF(_d, _d)
)
);
}
void CircleEditor::updateForm() {
qreal _d = part -> rect().width();
QPointF top_left(part -> sceneTopLeft());
x -> setText(QString("%1").arg(top_left.x() + _d / 2.0));
y -> setText(QString("%1").arg(top_left.y() + _d / 2.0));
r -> setText(QString("%1").arg(_d));
}

29
editor/circleeditor.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef CIRCLE_EDITOR_H
#define CIRCLE_EDITOR_H
#include <QtGui>
class PartCircle;
/**
Cette classe represente un editeur de cercle.
Elle permet d'editer a travers une interface graphique les
proprietes d'une cercle composant le dessin d'un element.
*/
class CircleEditor : public QWidget {
Q_OBJECT
// Constructeurs, destructeur
public:
CircleEditor(PartCircle *, QWidget * = 0);
virtual ~CircleEditor();
private:
CircleEditor(const CircleEditor &);
// attributs
private:
PartCircle *part;
QLineEdit *x, *y, *r;
// methodes
public slots:
void updateCircle();
void updateForm();
};
#endif

View File

@ -0,0 +1,447 @@
#include "customelementeditor.h"
#include "editorscene.h"
#include "customelementpart.h"
#include "newelementwizard.h"
#include "qetapp.h"
CustomElementEditor::CustomElementEditor(QWidget *parent) :
QMainWindow(parent),
read_only(false),
min_title(tr("QElectroTech - \311diteur d'\351l\351ment")),
_filename(QString())
{
setMinimumWidth(700);
setMinimumHeight(450);
setWindowTitle(min_title);
setWindowIcon(QIcon(":/ico/qet.png"));
setupInterface();
setupActions();
setupMenus();
}
CustomElementEditor::~CustomElementEditor() {
qDebug() << "~CustomElementEditor()";
// recupere le layout
// QLayout *layout = tools_dock -> widget() -> layout();
//
// // enleve les widgets deja presents
// QLayoutItem *qli;
// while ((qli = layout -> takeAt(0)) != 0) {
// if (qli -> widget()) {
// layout -> removeWidget(qli -> widget());
// qli -> widget() -> setParent(0);
// }
// }
}
void CustomElementEditor::setupActions() {
new_element = new QAction(QIcon(":/ico/new.png"), tr("&Nouveau"), this);
open = new QAction(QIcon(":/ico/open.png"), tr("&Ouvrir"), this);
save = new QAction(QIcon(":/ico/save.png"), tr("&Enregistrer"), this);
save_as = new QAction(QIcon(":/ico/saveas.png"), tr("Enregistrer sous"), this);
quit = new QAction(QIcon(":/ico/exit.png"), tr("&Quitter"), this);
selectall = new QAction( tr("Tout s\351lectionner"), this);
deselectall = new QAction( tr("D\351s\351lectionner tout"), this);
inv_select = new QAction( tr("Inverser la s\351lection"), this);
edit_delete = new QAction(QIcon(":/ico/delete.png"), tr("&Supprimer"), this);
edit_size = new QAction( tr("Modifier la taille"), this);
edit_hotspot = new QAction( tr("Modifier le point de saisie"), this);
edit_names = new QAction( tr("\311diter les noms"), this);
edit_ori = new QAction(QIcon(":/ico/orientations.png"), tr("\311diter les orientations"), this);
move = new QAction(QIcon(":/ico/select.png"), tr("D\351placer un objet"), this);
add_line = new QAction(QIcon(":/ico/line.png"), tr("Ajouter une ligne"), this);
add_ellipse = new QAction(QIcon(":/ico/ellipse.png"), tr("Ajouter une ellipse"), this);
add_circle = new QAction(QIcon(":/ico/circle.png"), tr("Ajouter un cercle"), this);
add_polygon = new QAction(QIcon(":/ico/polygon.png"), tr("Ajouter un polygone"), this);
add_text = new QAction(QIcon(":/ico/text.png"), tr("Ajouter du texte"), this);
add_arc = new QAction(QIcon(":/ico/arc.png"), tr("Ajouter un arc de cercle"), this);
add_terminal = new QAction(QIcon(":/ico/terminal.png"), tr("Ajouter une borne"), this);
add_textfield = new QAction(QIcon(":/ico/textfield.png"), tr("Ajouter un champ de texte"), this);
edit_delete -> setEnabled(false);
edit_size -> setEnabled(false);
edit_hotspot -> setEnabled(false);
selectall -> setShortcut(QKeySequence::SelectAll);
deselectall -> setShortcut(QKeySequence(tr("Ctrl+Shift+A")));
inv_select -> setShortcut(QKeySequence(tr("Ctrl+I")));
edit_delete -> setShortcut(QKeySequence(tr("Ctrl+Suppr")));
connect(new_element, SIGNAL(triggered()), this, SLOT(slot_new()));
connect(open, SIGNAL(triggered()), this, SLOT(slot_open()));
connect(save, SIGNAL(triggered()), this, SLOT(slot_save()));
connect(save_as, SIGNAL(triggered()), this, SLOT(slot_saveAs()));
connect(quit, SIGNAL(triggered()), this, SLOT(slot_quit()));
connect(selectall, SIGNAL(triggered()), ce_scene, SLOT(slot_selectAll()));
connect(deselectall, SIGNAL(triggered()), ce_scene, SLOT(slot_deselectAll()));
connect(inv_select, SIGNAL(triggered()), ce_scene, SLOT(slot_invertSelection()));
connect(edit_delete, SIGNAL(triggered()), ce_scene, SLOT(slot_delete()));
connect(edit_size, SIGNAL(triggered()), ce_scene, SLOT(slot_editSize()));
connect(edit_hotspot, SIGNAL(triggered()), ce_scene, SLOT(slot_editHotSpot()));
connect(edit_names, SIGNAL(triggered()), ce_scene, SLOT(slot_editNames()));
connect(edit_ori, SIGNAL(triggered()), ce_scene, SLOT(slot_editOrientations()));
connect(move, SIGNAL(triggered()), ce_scene, SLOT(slot_move()));
connect(add_line, SIGNAL(triggered()), ce_scene, SLOT(slot_addLine()));
connect(add_ellipse, SIGNAL(triggered()), ce_scene, SLOT(slot_addEllipse()));
connect(add_circle, SIGNAL(triggered()), ce_scene, SLOT(slot_addCircle()));
connect(add_polygon, SIGNAL(triggered()), ce_scene, SLOT(slot_addPolygon()));
connect(add_text, SIGNAL(triggered()), ce_scene, SLOT(slot_addText()));
connect(add_arc, SIGNAL(triggered()), ce_scene, SLOT(slot_addArc()));
connect(add_terminal, SIGNAL(triggered()), ce_scene, SLOT(slot_addTerminal()));
connect(add_textfield, SIGNAL(triggered()), ce_scene, SLOT(slot_addTextField()));
connect(move, SIGNAL(triggered()), this, SLOT(slot_setRubberBandToView()));
connect(add_line, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_ellipse, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_circle, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_polygon, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_text, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_arc, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_terminal, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_textfield, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(ce_scene, SIGNAL(needNormalMode()), this, SLOT(slot_setNormalMode()));
move -> setCheckable(true);
add_line -> setCheckable(true);
add_ellipse -> setCheckable(true);
add_circle -> setCheckable(true);
add_polygon -> setCheckable(true);
add_text -> setCheckable(true);
add_arc -> setCheckable(true);
add_terminal -> setCheckable(true);
add_textfield -> setCheckable(true);
parts = new QActionGroup(this);
parts -> addAction(move);
parts -> addAction(add_line);
parts -> addAction(add_ellipse);
parts -> addAction(add_circle);
parts -> addAction(add_polygon);
parts -> addAction(add_text);
parts -> addAction(add_arc);
parts -> addAction(add_textfield);
parts -> addAction(add_terminal);
parts -> setExclusive(true);
parts_toolbar = new QToolBar(tr("Parties"), this);
foreach (QAction *action, parts -> actions()) parts_toolbar -> addAction(action);
move -> setChecked(true);
parts_toolbar -> setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
QAction *xml_preview = new QAction(QIcon(":/ico/info.png"), tr("XML"), this);
connect(xml_preview, SIGNAL(triggered()), this, SLOT(xmlPreview()));
parts_toolbar -> addAction(xml_preview);
addToolBar(Qt::LeftToolBarArea, parts_toolbar);
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateInformations()));
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateMenus()));
}
void CustomElementEditor::setupMenus() {
file_menu = new QMenu(tr("Fichier"));
edit_menu = new QMenu(tr("\311dition"));
display_menu = new QMenu(tr("Affichage"));
tools_menu = new QMenu(tr("Outils"));
help_menu = new QMenu(tr("Aide"));
file_menu -> setTearOffEnabled(true);
edit_menu -> setTearOffEnabled(true);
display_menu -> setTearOffEnabled(true);
tools_menu -> setTearOffEnabled(true);
help_menu -> setTearOffEnabled(true);
file_menu -> addAction(new_element);
file_menu -> addAction(open);
file_menu -> addAction(save);
file_menu -> addAction(save_as);
file_menu -> addSeparator();
file_menu -> addAction(quit);
edit_menu -> addAction(selectall);
edit_menu -> addAction(deselectall);
edit_menu -> addAction(inv_select);
edit_menu -> addSeparator();
edit_menu -> addAction(edit_delete);
edit_menu -> addSeparator();
edit_menu -> addAction(edit_names);
edit_menu -> addAction(edit_size);
edit_menu -> addAction(edit_hotspot);
edit_menu -> addAction(edit_ori);
menuBar() -> addMenu(file_menu);
menuBar() -> addMenu(edit_menu);
menuBar() -> addMenu(display_menu);
menuBar() -> addMenu(tools_menu);
menuBar() -> addMenu(help_menu);
}
void CustomElementEditor::slot_updateMenus() {
edit_delete -> setEnabled(!ce_scene -> selectedItems().isEmpty());
}
void CustomElementEditor::setupInterface() {
// editeur
ce_scene = new EditorScene(this);
ce_scene -> slot_move();
ce_view = new QGraphicsView(ce_scene, this);
ce_view -> setInteractive(true);
ce_view -> setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//ce_view -> setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
ce_view -> setResizeAnchor(QGraphicsView::AnchorUnderMouse);
//ce_view -> setSceneRect(QRectF(0.0, 0.0, 50.0, 200.0));
ce_view -> scale(4.0, 4.0);
slot_setRubberBandToView();
setCentralWidget(ce_view);
// widget par defaut dans le QDockWidget
default_informations = new QLabel();
// panel sur le cote
tools_dock = new QDockWidget(tr("Informations"), this);
tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
tools_dock -> setMinimumWidth(285);
addDockWidget(Qt::RightDockWidgetArea, tools_dock);
QWidget *info_widget = new QWidget();
info_widget -> setLayout(new QVBoxLayout(info_widget));
tools_dock -> setWidget(info_widget);
slot_updateInformations();
// barre d'etat
statusBar() -> showMessage(tr("\311diteur d'\351l\351ments"));
}
void CustomElementEditor::slot_setRubberBandToView() {
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
}
void CustomElementEditor::slot_setNoDragToView() {
ce_view -> setDragMode(QGraphicsView::NoDrag);
}
void CustomElementEditor::slot_setNormalMode() {
if (!move -> isChecked()) move -> setChecked(true);
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
ce_scene -> slot_move();
}
void CustomElementEditor::slot_updateInformations() {
QList<QGraphicsItem *> selected_qgis = ce_scene -> selectedItems();
QList<CustomElementPart *> selected_parts;
foreach(QGraphicsItem *qgi, selected_qgis) {
if (CustomElementPart *cep = dynamic_cast<CustomElementPart *>(qgi)) {
selected_parts.append(cep);
}
}
// recupere le layout
QLayout *layout = tools_dock -> widget() -> layout();
// enleve les widgets deja presents
QLayoutItem *qli;
while ((qli = layout -> takeAt(0)) != 0) {
if (qli -> widget()) {
layout -> removeWidget(qli -> widget());
qli -> widget() -> setParent(0);
}
}
if (selected_parts.size() == 1) {
// recupere le premier CustomElementPart et en ajoute le widget d'edition
layout -> addWidget(selected_parts.first() -> elementInformations());
} else {
default_informations -> setText(
selected_parts.size() ?
QString("%1").arg(selected_parts.size()) + tr(" parties s\351lectionn\351es.") :
tr("Aucune partie s\351lectionn\351e.")
);
layout -> addWidget(default_informations);
}
}
void CustomElementEditor::xmlPreview() {
QMessageBox::information(
this,
"Export XML",
ce_scene -> toXml().toString(4)
);
}
void CustomElementEditor::fromFile(const QString &filepath) {
bool state = true;
QString error_message;
// le fichier doit exister
QFileInfo infos_file(filepath);
if (!infos_file.exists() || !infos_file.isFile()) {
state = false;
error_message = tr("Le fichier ") + filepath + tr(" n'existe pas.");
}
// le fichier doit etre lisible
QFile file(filepath);
if (state) {
if (!file.open(QIODevice::ReadOnly)) {
state = false;
error_message = tr("Impossible d'ouvrir le fichier ") + filepath + ".";
}
}
// le fichier doit etre un document XML
QDomDocument document_xml;
if (state) {
if (!document_xml.setContent(&file)) {
state = false;
error_message = tr("Ce fichier n'est pas un document XML valide");
}
file.close();
}
if (!state) {
QMessageBox::critical(this, tr("Erreur"), error_message);
return;
}
// chargement de l'element
ce_scene -> fromXml(document_xml);
// gestion de la lecture seule
if (!infos_file.isWritable()) {
QMessageBox::warning(
this,
tr("\311dition en lecture seule"),
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cet \351lement. Il sera donc ouvert en lecture seule.")
);
setReadOnly(true);
}
// memorise le fichier
_filename = filepath;
// modifie le titre de la fenetre
QString new_title = min_title + " - " + ce_scene -> names().name();
if (isReadOnly()) new_title += tr(" [lecture seule]");
setWindowTitle(new_title);
}
bool CustomElementEditor::toFile(const QString &fn) {
QFile file(fn);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, tr("Erreur"), tr("Impossible d'ecrire dans ce fichier"));
return(false);
}
QTextStream out(&file);
out.setCodec("UTF-8");
out << ce_scene -> toXml().toString(4);
file.close();
return(true);
}
/**
specifie si l'editeur d'element doit etre en mode lecture seule
@param ro true pour activer le mode lecture seule, false pour le desactiver
*/
void CustomElementEditor::setReadOnly(bool ro) {
read_only = ro;
// active / desactive les actions
foreach (QAction *action, parts -> actions()) action -> setEnabled(!ro);
// active / desactive les interactions avec la scene
ce_view -> setInteractive(!ro);
// active / desactive l'edition de la taille, du hotspot, des noms et des orientations
edit_size -> setEnabled(!ro);
edit_hotspot -> setEnabled(!ro);
edit_names -> setEnabled(!ro);
edit_ori -> setEnabled(!ro);
}
/**
@return true si l'editeur d'element est en mode lecture seule
*/
bool CustomElementEditor::isReadOnly() const {
return(read_only);
}
void CustomElementEditor::slot_new() {
NewElementWizard new_element_wizard;
new_element_wizard.exec();
}
void CustomElementEditor::slot_open() {
// demande un nom de fichier a ouvrir a l'utilisateur
QString user_filename = QFileDialog::getOpenFileName(
this,
tr("Ouvrir un fichier"),
QETApp::customElementsDir(),
tr("\311l\351ments QElectroTech (*.elmt);;Fichiers XML (*.xml);;Tous les fichiers (*)")
);
if (user_filename == "") return;
CustomElementEditor *cee = new CustomElementEditor();
cee -> fromFile(user_filename);
cee -> show();
}
bool CustomElementEditor::slot_save() {
// si on ne connait pas le nom du fichier en cours, enregistrer revient a enregistrer sous
if (_filename == QString()) return(slot_saveAs());
// sinon on enregistre dans le nom de fichier connu
return(toFile(_filename));
}
bool CustomElementEditor::slot_saveAs() {
// demande un nom de fichier a l'utilisateur pour enregistrer l'element
QString fn = QFileDialog::getSaveFileName(
this,
tr("Enregistrer sous"),
QETApp::customElementsDir(),
tr("\311l\351ments QElectroTech (*.elmt)")
);
// si aucun nom n'est entre, renvoie faux.
if (fn == "") return(false);
// si le nom ne se termine pas par l'extension .elmt, celle-ci est ajoutee
if (!fn.endsWith(".elmt", Qt::CaseInsensitive)) fn += ".elmt";
// tente d'enregistrer le fichier
bool result_save = toFile(fn);
// si l'enregistrement reussit, le nom du fichier est conserve
if (result_save) setFileName(fn);
// retourne un booleen representatif de la reussite de l'enregistrement
return(result_save);
}
void CustomElementEditor::slot_quit(QCloseEvent *event) {
if (close()) {
if (event != NULL) event -> accept();
delete(this);
} else if (event != NULL) event -> ignore();
}
bool CustomElementEditor::close() {
// demande d'abord a l'utilisateur s'il veut enregistrer l'element en cours
QMessageBox::StandardButton answer = QMessageBox::question(
this,
tr("Enregistrer l'\351l\351ment en cours ?"),
tr("Voulez-vous enregistrer l'\351l\351ment ") + ce_scene -> names().name() + tr(" ?"),
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
QMessageBox::Cancel
);
bool result;
switch(answer) {
case QMessageBox::Cancel: result = false; break; // l'utilisateur annule : echec de la fermeture
case QMessageBox::Yes: result = slot_save(); break; // l'utilisateur dit oui : la reussite depend de l'enregistrement
default: result = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi
}
return(result);
}
/**
Permet de quitter l'editeur lors de la fermeture de la fenetre principale
@param qce Le QCloseEvent correspondant a l'evenement de fermeture
*/
void CustomElementEditor::closeEvent(QCloseEvent *qce) {
slot_quit(qce);
}

View File

@ -0,0 +1,128 @@
#ifndef CUSTOM_ELEMENT_EDITOR_H
#define CUSTOM_ELEMENT_EDITOR_H
#include <QtGui>
#include "editorscene.h"
#include "orientationset.h"
class CustomElementEditor : public QMainWindow {
Q_OBJECT
// constructeur, destructeur
public:
CustomElementEditor(QWidget * = 0);
virtual ~CustomElementEditor();
private:
CustomElementEditor(const CustomElementEditor &);
// attributs
private:
/// booleen indiquant si l'editeur est en mode "lecture seule" ou non
bool read_only;
/// menus
QMenu *file_menu, *edit_menu, *display_menu, *tools_menu, *help_menu;
/// vue sur la scene d'edition
QGraphicsView *ce_view;
/// scene d'edition
EditorScene *ce_scene;
/// container pour les widgets d'edition des parties
QDockWidget *tools_dock;
/// actions du menu fichier
QAction *new_element, *open, *save, *save_as, *quit;
/// actions du menu edition
QAction *selectall, *deselectall, *inv_select;
QAction *edit_delete, *edit_size, *edit_hotspot, *edit_names, *edit_ori;
/// barre d'outils
QToolBar *parts_toolbar;
/// actions de la barre d'outils
QActionGroup *parts;
QAction *move, *add_line, *add_circle, *add_ellipse, *add_polygon, *add_text;
QAction *add_arc, *add_terminal, *add_textfield;
/// label affiche lors de la selection de plusieurs elements
QLabel *default_informations;
/// titre minimal
QString min_title;
/// Nom de fichier
QString _filename;
// methodes
public:
void setSize(const QSize &);
QSize size() const;
void setHotspot(const QPoint &);
QPoint hotspot() const;
void setNames(const NamesList &);
void setOrientations(const OrientationSet &orientation_set);
OrientationSet orientations() const;
void setFileName(const QString &);
QString fileName() const;
void setReadOnly(bool);
bool isReadOnly() const;
void fromFile(const QString &);
bool toFile(const QString &);
protected:
void closeEvent(QCloseEvent *);
private:
void setupActions();
void setupMenus();
void setupInterface();
bool close();
public slots:
void slot_new();
void slot_open();
bool slot_save();
bool slot_saveAs();
void slot_quit(QCloseEvent * = NULL);
void slot_setRubberBandToView();
void slot_setNoDragToView();
void slot_setNormalMode();
void slot_updateInformations();
void slot_updateMenus();
void xmlPreview();
};
inline void CustomElementEditor::setSize(const QSize &siz) {
ce_scene -> setWidth(siz.width());
ce_scene -> setHeight(siz.height());
}
inline QSize CustomElementEditor::size() const {
return(
QSize(
ce_scene -> width(),
ce_scene -> height()
)
);
}
inline void CustomElementEditor::setHotspot(const QPoint &hs) {
ce_scene -> setHotspot(hs);
}
inline QPoint CustomElementEditor::hotspot() const {
return(ce_scene -> hotspot());
}
inline void CustomElementEditor::setNames(const NamesList &nameslist) {
ce_scene -> setNames(nameslist);
}
inline void CustomElementEditor::setOrientations(const OrientationSet &orientation_set) {
ce_scene -> setOrientations(orientation_set);
}
inline OrientationSet CustomElementEditor::orientations() const {
return(ce_scene -> orientations());
}
inline void CustomElementEditor::setFileName(const QString &fn) {
setWindowTitle(min_title + " - " + fn);
_filename = fn;
}
inline QString CustomElementEditor::fileName() const {
return(_filename);
}
#endif

View File

@ -0,0 +1,133 @@
#include "customelementgraphicpart.h"
/**
Ecrit les attributs de style dans un element XML
@param qde L'element XML a modifier
*/
void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const {
QString css_like_styles;
css_like_styles += "line-style:";
if (_linestyle == DashedStyle) css_like_styles += "dashed";
else if (_linestyle == NormalStyle) css_like_styles += "normal";
css_like_styles += ";line-weight:";
if (_lineweight == NoneWeight) css_like_styles += "none";
else if (_lineweight == ThinWeight) css_like_styles += "thin";
else if (_lineweight == NormalWeight) css_like_styles += "normal";
css_like_styles += ";filling:";
if (_filling == NoneFilling) css_like_styles += "none";
else if (_filling == BlackFilling) css_like_styles += "black";
else if (_filling == WhiteFilling) css_like_styles += "white";
css_like_styles += ";color:";
if (_color == WhiteColor) css_like_styles += "white";
else if (_color == BlackColor) css_like_styles += "black";
qde.setAttribute("style", css_like_styles);
qde.setAttribute("antialias", _antialiased ? "true" : "false");
}
/**
Lit les attributs de style depuis un element XML
@param qde L'element XML a analyser
*/
void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde) {
resetStyles();
// recupere la liste des couples style / valeur
QStringList styles = qde.attribute("style").split(";", QString::SkipEmptyParts);
// analyse chaque couple
QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$");
foreach (QString style, styles) {
if (!rx.exactMatch(style)) continue;
QString style_name = rx.cap(1);
QString style_value = rx.cap(2);
if (style_name == "line-style") {
if (style_value == "dashed") _linestyle = DashedStyle;
else if (style_value == "normal") _linestyle = NormalStyle;
// il n'y a pas de else car les valeurs non conformes sont ignorees (idem par la suite)
} else if (style_name == "line-weight") {
if (style_value == "thin") _lineweight = ThinWeight;
else if (style_value == "normal") _lineweight = NormalWeight;
else if (style_value == "none") _lineweight = NoneWeight;
} else if (style_name == "filling") {
if (style_value == "white") _filling = WhiteFilling;
else if (style_value == "black") _filling = BlackFilling;
else if (style_value == "none") _filling = NoneFilling;
} else if (style_name == "color") {
if (style_value == "black") _color = BlackColor;
else if (style_value == "white") _color = WhiteColor;
}
}
// recupere l'antialiasing
_antialiased = qde.attribute("antialias") == "true";
// met a jour l'editeur de style
style_editor -> updateForm();
}
/**
Remet les styles par defaut
*/
void CustomElementGraphicPart::resetStyles() {
_linestyle = NormalStyle;
_lineweight = NormalWeight;
_filling = NoneFilling;
_color = BlackColor;
_antialiased = false;
}
/**
Applique les styles a un Qpainter
@param painter QPainter a modifier
*/
void CustomElementGraphicPart::applyStylesToQPainter(QPainter &painter) const {
// recupere le QPen et la QBrush du QPainter
QPen pen = painter.pen();
QBrush brush = painter.brush();
// applique le style de trait
if (_linestyle == DashedStyle) pen.setStyle(Qt::DashLine);
else if (_linestyle == NormalStyle) pen.setStyle(Qt::SolidLine);
// applique l'epaisseur de trait
if (_lineweight == NoneWeight) pen.setColor(QColor(0, 0, 0, 0));
else if (_lineweight == ThinWeight) pen.setWidth(0);
else if (_lineweight == NormalWeight) pen.setWidthF(1.0);
// applique le remplissage
if (_filling == NoneFilling) {
brush.setStyle(Qt::NoBrush);
} else if (_filling == BlackFilling) {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::black);
} else if (_filling == WhiteFilling) {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::white);
}
// applique la couleur de trait
if (_color == WhiteColor) pen.setColor(QColor(255, 255, 255, pen.color().alpha()));
else if (_color == BlackColor) pen.setColor(QColor( 0, 0, 0, pen.color().alpha()));
// applique l'antialiasing
painter.setRenderHint(QPainter::Antialiasing, _antialiased);
painter.setRenderHint(QPainter::TextAntialiasing, _antialiased);
painter.setRenderHint(QPainter::SmoothPixmapTransform, _antialiased);
painter.setPen(pen);
painter.setBrush(brush);
}
/**
@return Le widget permettant d'editer les styles
*/
QWidget *CustomElementGraphicPart::elementInformations() {
return(style_editor);
}

View File

@ -0,0 +1,145 @@
#ifndef CUSTOM_ELEMENT_GRAPHIC_PART_H
#define CUSTOM_ELEMENT_GRAPHIC_PART_H
#include <QPainter>
#include "customelementpart.h"
#include "styleeditor.h"
/**
Cette classe represente une partie graphique d'element
Elle encapsule des methodes afin de gerer les attributs de style communs
a la plupart des parties d'elements
*/
typedef CustomElementGraphicPart CEGP;
class CustomElementGraphicPart : public CustomElementPart {
public:
enum LineStyle { NormalStyle, DashedStyle };
enum LineWeight { NormalWeight, ThinWeight, NoneWeight };
enum Filling { NoneFilling, BlackFilling, WhiteFilling };
enum Color { BlackColor, WhiteColor };
// constructeurs, destructeur
public:
CustomElementGraphicPart() :
_linestyle(NormalStyle),
_lineweight(NormalWeight),
_filling(NoneFilling),
_color(BlackColor),
_antialiased(false)
{
style_editor = new StyleEditor(this);
};
virtual ~CustomElementGraphicPart() {
qDebug() << "~CustomElementGraphicPart()";
delete style_editor;
};
// attributs
private:
LineStyle _linestyle;
LineWeight _lineweight;
Filling _filling ;
Color _color;
bool _antialiased;
protected:
StyleEditor *style_editor;
//methodes
public:
void setLineStyle(LineStyle);
void setLineWeight(LineWeight);
void setFilling(Filling);
void setColor(Color);
void setAntialiased(bool);
LineStyle lineStyle() const;
LineWeight lineWeight() const;
Filling filling() const;
Color color() const;
bool antialiased() const;
QWidget *elementInformations();
protected:
void stylesToXml(QDomElement &) const;
void stylesFromXml(const QDomElement &);
void resetStyles();
void applyStylesToQPainter(QPainter &) const;
};
/**
Change le style de trait
@param ls Le nouveau style de trait
*/
inline void CustomElementGraphicPart::setLineStyle(LineStyle ls) {
_linestyle = ls;
}
/**
Change l'epaisseur de trait
@param lw La nouvelle epaisseur de trait
*/
inline void CustomElementGraphicPart::setLineWeight(LineWeight lw) {
_lineweight = lw;
}
/**
Change la couleur de remplissage
@param f La nouvelle couleur de remplissage
*/
inline void CustomElementGraphicPart::setFilling(Filling f) {
_filling = f;
}
/**
Change la couleur de trait
@param c La nouvelle couleur de trait
*/
inline void CustomElementGraphicPart::setColor(Color c) {
_color = c;
}
/**
@return Le style de trait
*/
inline CustomElementGraphicPart::LineStyle CustomElementGraphicPart::lineStyle() const {
return(_linestyle);
}
/**
@return L'epaisseur de trait
*/
inline CustomElementGraphicPart::LineWeight CustomElementGraphicPart::lineWeight() const {
return(_lineweight);
}
/**
@return La couleur de remplissage
*/
inline CustomElementGraphicPart::Filling CustomElementGraphicPart::filling() const {
return(_filling);
}
/**
@return La couleur de trait
*/
inline CustomElementGraphicPart::Color CustomElementGraphicPart::color() const {
return(_color);
}
/**
Definit si la partie doit etre antialiasee ou non
@param aa True pour activer l'antialiasing, false pour le desactiver
*/
inline void CustomElementGraphicPart::setAntialiased(bool aa) {
_antialiased = aa;
}
/**
@return true si la partie est antialiasee, false sinon
*/
inline bool CustomElementGraphicPart::antialiased() const {
return(_antialiased);
}
#endif

View File

@ -0,0 +1,6 @@
#include "customelementpart.h"
#include "customelement.h"
QPicture *CustomElementPart::getCustomElementQPicture(CustomElement &ce) const {
return(&(ce.dessin));
}

View File

@ -0,0 +1,39 @@
#ifndef CUSTOM_ELEMENT_PART_H
#define CUSTOM_ELEMENT_PART_H
#include <QtGui>
#include <QtXml>
#include <QImage>
class CustomElement;
/**
Cette classe abstraite represente une partie de la representation graphique
d'un element de schema electrique. Les attributs et methodes qu'elle
encapsule ne sont pas integres directement dans la classe CustomElement
afin de ne pas alourdir celle-ci. Il est en effet inutile pour cette classe
de retenir sa conception graphique autrement que sous la forme d'une
QImage.
*/
class CustomElementPart {
// constructeurs, destructeur
public:
CustomElementPart() {};
virtual ~CustomElementPart() {
qDebug() << "~CustomElementPart()";
};
private:
CustomElementPart(const CustomElementPart &);
// attributs
private:
// methodes
public:
virtual void fromXml(const QDomElement &) = 0;
virtual const QDomElement toXml(QDomDocument &) const = 0;
virtual QWidget *elementInformations() = 0;
//virtual void renderToCustomElement(CustomElement &) const = 0;
//virtual void toEditorPart(const EditorPart &);
//virtual void fromEditorPart(const EditorPart &) = 0;
protected:
QPicture *getCustomElementQPicture(CustomElement &ce) const;
};
#endif

447
editor/editorscene.cpp Normal file
View File

@ -0,0 +1,447 @@
#include "editorscene.h"
#include <cmath>
#include "partline.h"
#include "partellipse.h"
#include "partcircle.h"
#include "partpolygon.h"
#include "partterminal.h"
#include "parttext.h"
#define GRILLE_X 10
#define GRILLE_Y 10
EditorScene::EditorScene(QObject *parent) :
QGraphicsScene(parent),
_width(3),
_height(7),
_hotspot(15, 35)
{
current_polygon = NULL;
connect(this, SIGNAL(changed(const QList<QRectF> &)), this, SLOT(slot_checkSelectionChanged()));
}
EditorScene::~EditorScene() {
qDebug() << "~EditorScene()";
}
void EditorScene::slot_move() {
behavior = Normal;
}
void EditorScene::slot_addLine() {
behavior = Line;
}
void EditorScene::slot_addCircle() {
behavior = Circle;
}
void EditorScene::slot_addEllipse() {
behavior = Ellipse;
}
void EditorScene::slot_addPolygon() {
behavior = Polygon;
}
void EditorScene::slot_addText() {
behavior = Text;
}
void EditorScene::slot_addTerminal() {
behavior = Terminal;
}
void EditorScene::slot_addArc() {
behavior = Arc;
}
void EditorScene::slot_addTextField() {
behavior = TextField;
}
void EditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
QRectF temp_rect;
qreal radius;
QPointF temp_point;
QPolygonF temp_polygon;
if (e -> buttons() & Qt::LeftButton) {
switch(behavior) {
case Normal:
QGraphicsScene::mouseMoveEvent(e);
break;
case Line:
current_line -> setLine(QLineF(current_line -> line().p1(), e -> scenePos()));
break;
case Ellipse:
temp_rect = current_ellipse -> rect();
temp_rect.setBottomRight(e -> scenePos());
current_ellipse -> setRect(temp_rect);
break;
case Circle:
temp_rect = current_circle -> rect();
temp_point = e -> scenePos() - current_circle -> mapToScene(temp_rect.center());
radius = sqrt(pow(temp_point.x(), 2) + pow(temp_point.y(), 2));
temp_rect = QRectF(
temp_rect.center() - QPointF(radius, radius),
QSizeF(2.0 * radius, 2.0 * radius)
);
current_circle -> setRect(temp_rect);
break;
case Polygon:
if (current_polygon == NULL) break;
temp_polygon = current_polygon -> polygon();
temp_polygon.pop_back();
temp_polygon << e -> scenePos();
current_polygon -> setPolygon(temp_polygon);
break;
default:
QGraphicsScene::mouseMoveEvent(e);
}
} else if (behavior == Polygon && current_polygon != NULL) {
temp_polygon = current_polygon -> polygon();
temp_polygon.pop_back();
temp_polygon << e -> scenePos();
current_polygon -> setPolygon(temp_polygon);
} else QGraphicsScene::mouseMoveEvent(e);
}
void EditorScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
QPolygonF temp_polygon;
if (e -> button() & Qt::LeftButton) {
switch(behavior) {
case Normal:
QGraphicsScene::mousePressEvent(e);
break;
case Line:
current_line = new PartLine(0, this);
current_line -> setLine(QLineF(e -> scenePos(), e -> scenePos()));
break;
case Ellipse:
current_ellipse = new PartEllipse(0, this);
current_ellipse -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
break;
case Circle:
current_circle = new PartCircle(0, this);
current_circle -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
break;
case Polygon:
if (current_polygon == NULL) {
current_polygon = new PartPolygon(0, this);
temp_polygon = QPolygonF(0);
} else temp_polygon = current_polygon -> polygon();
// au debut, on insere deux points
if (!temp_polygon.count()) temp_polygon << e -> scenePos();
temp_polygon << e -> scenePos();
current_polygon -> setPolygon(temp_polygon);
break;
default:
QGraphicsScene::mousePressEvent(e);
}
} else QGraphicsScene::mousePressEvent(e);
}
void EditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
PartTerminal *terminal;
PartText *text;
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
if (e -> button() & Qt::LeftButton) {
switch(behavior) {
case Normal:
QGraphicsScene::mouseReleaseEvent(e);
break;
case Line:
break;
case Ellipse:
current_ellipse -> setRect(current_ellipse -> rect().normalized());
break;
case Circle:
current_circle -> setRect(current_circle -> rect().normalized());
break;
case Terminal:
terminal = new PartTerminal(0, this);
terminal -> setPos(e -> scenePos());
break;
case Text:
text = new PartText(0, this);
text -> setPos(e -> scenePos());
break;
default:
QGraphicsScene::mouseReleaseEvent(e);
}
} else if (e -> button() & Qt::RightButton) {
if (behavior == Polygon) {
behavior = Normal;
current_polygon = NULL;
emit(needNormalMode());
} else QGraphicsScene::mouseReleaseEvent(e);
} else QGraphicsScene::mouseReleaseEvent(e);
}
/**
Dessine l'arriere-plan de l'editeur, cad la grille.
@param p Le QPainter a utiliser pour dessiner
@param r Le rectangle de la zone a dessiner
*/
void EditorScene::drawBackground(QPainter *p, const QRectF &r) {
p -> save();
// desactive tout antialiasing, sauf pour le texte
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, true);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
// dessine un fond blanc
p -> setPen(Qt::NoPen);
p -> setBrush(Qt::white);
p -> drawRect(r);
// encadre la zone dessinable de l'element
QRectF drawable_area(-_hotspot.x(), -_hotspot.y(), width(), height());
p -> setPen(Qt::black);
p -> setBrush(Qt::NoBrush);
p -> drawRect(drawable_area);
if (r.width() < 2500 && r.height() < 2500) {
// 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());
while (g_x % GRILLE_X) ++ g_x;
int g_y = (int)ceil(r.y());
while (g_y % GRILLE_Y) ++ g_y;
for (int gx = g_x ; gx < limite_x ; gx += GRILLE_X) {
for (int gy = g_y ; gy < limite_y ; gy += GRILLE_Y) {
p -> drawPoint(gx, gy);
}
}
}
p -> restore();
}
/**
Dessine l'arriere-plan de l'editeur, cad l'indicateur de hotspotó.
@param p Le QPainter a utiliser pour dessiner
@param r Le rectangle de la zone a dessiner
*/
void EditorScene::drawForeground(QPainter *p, const QRectF &) {
p -> save();
// desactive tout antialiasing, sauf pour le texte
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, true);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
p -> setPen(Qt::red);
p -> setBrush(Qt::NoBrush);
p -> drawLine(QLineF(0.0, -_hotspot.y(), 0.0, height() - _hotspot.y()));
p -> drawLine(QLineF(-_hotspot.x(), 0.0, width() - _hotspot.x(), 0.0));
p -> restore();
}
const QDomDocument EditorScene::toXml() const {
// document XML
QDomDocument xml_document;
// racine du document XML
QDomElement root = xml_document.createElement("definition");
root.setAttribute("type", "element");
root.setAttribute("width", QString("%1").arg(_width * 10));
root.setAttribute("height", QString("%1").arg(_height * 10));
root.setAttribute("hotspot_x", QString("%1").arg(_hotspot.x()));
root.setAttribute("hotspot_y", QString("%1").arg(_hotspot.y()));
root.setAttribute("orientation", ori.toString());
// noms de l'element
root.appendChild(_names.toXml(xml_document));
QDomElement description = xml_document.createElement("description");
// description de l'element
foreach(QGraphicsItem *qgi, items()) {
if (CustomElementPart *ce = dynamic_cast<CustomElementPart *>(qgi)) {
description.appendChild(ce -> toXml(xml_document));
}
}
root.appendChild(description);
xml_document.appendChild(root);
return(xml_document);
}
void EditorScene::fromXml(const QDomDocument &xml_document) {
QString error_message;
bool state = true;
// la racine est supposee etre une definition d'element
QDomElement root = xml_document.documentElement();
if (root.tagName() != "definition" || root.attribute("type") != "element") {
state = false;
error_message = tr("Ce document XML n'est pas une definition d'\351l\351ment.");
}
// dimensions et hotspot
if (state) {
// ces attributs doivent etre presents et valides
int w, h, hot_x, hot_y;
if (
!QET::attributeIsAnInteger(root, QString("width"), &w) ||\
!QET::attributeIsAnInteger(root, QString("height"), &h) ||\
!QET::attributeIsAnInteger(root, QString("hotspot_x"), &hot_x) ||\
!QET::attributeIsAnInteger(root, QString("hotspot_y"), &hot_y)
) {
state = false;
error_message = tr("Les dimensions ou le point de saisie ne sont pas valides.");
} else {
setWidth(w);
setHeight(h);
setHotspot(QPoint(hot_x, hot_y));
}
}
// orientations
if (state) {
if (!ori.fromString(root.attribute("orientation"))) {
state = false;
error_message = tr("Les orientations ne sont pas valides.");
}
}
// extrait les noms de la definition XML
if (state) {
_names.fromXml(root);
}
// parcours des enfants de la definition : parties de l'element
if (state) {
for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
QDomElement elmts = node.toElement();
if (elmts.isNull()) continue;
if (elmts.tagName() == "description") {
// gestion de la description graphique de l'element
// = parcours des differentes parties du dessin
int z = 1;
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
QDomElement qde = n.toElement();
if (qde.isNull()) continue;
CustomElementPart *cep;
if (qde.tagName() == "line") cep = new PartLine (0, this);
else if (qde.tagName() == "ellipse") cep = new PartEllipse (0, this);
else if (qde.tagName() == "circle") cep = new PartCircle (0, this);
else if (qde.tagName() == "polygon") cep = new PartPolygon (0, this);
else if (qde.tagName() == "terminal") cep = new PartTerminal(0, this);
else if (qde.tagName() == "text") cep = new PartText (0, this);
else continue;
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep)) qgi -> setZValue(z++);
cep -> fromXml(qde);
}
}
}
}
}
void EditorScene::slot_checkSelectionChanged() {
static QList<QGraphicsItem *> cache_selecteditems = QList<QGraphicsItem *>();
QList<QGraphicsItem *> selecteditems = selectedItems();
if (cache_selecteditems != selecteditems) emit(selectionChanged());
cache_selecteditems = selecteditems;
}
void EditorScene::slot_selectAll() {
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(true);
}
void EditorScene::slot_deselectAll() {
clearSelection();
}
void EditorScene::slot_invertSelection() {
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(!qgi -> isSelected());
}
void EditorScene::slot_delete() {
// verifie qu'il y a qqc de selectionne
QList<QGraphicsItem *> selected_items = selectedItems();
if (selected_items.isEmpty()) return;
// efface tout ce qui est selectionne
foreach(QGraphicsItem *qgi, selected_items) {
removeItem(qgi);
delete qgi;
}
}
void EditorScene::slot_editSize() {
}
void EditorScene::slot_editHotSpot() {
}
void EditorScene::slot_editOrientations() {
// cree un dialogue
QDialog dialog_ori;
dialog_ori.setModal(true);
dialog_ori.setFixedSize(400, 230);
dialog_ori.setWindowTitle(tr("\311diter les orientations"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_ori);
// ajoute un champ explicatif au dialogue
QLabel *information_label = new QLabel(tr("L'orientation par d\351faut est l'orientation dans laquelle s'effectue la cr\351ation de l'\351l\351ment."));
information_label -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
information_label -> setWordWrap(true);
dialog_layout -> addWidget(information_label);
// ajoute un OrientationSetWidget au dialogue
OrientationSetWidget *ori_widget = new OrientationSetWidget();
ori_widget -> setOrientationSet(ori);
dialog_layout -> addWidget(ori_widget);
// ajoute deux boutons au dialogue
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dialog_buttons);
connect(dialog_buttons, SIGNAL(accepted()), &dialog_ori, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), &dialog_ori, SLOT(reject()));
// lance le dialogue
if (dialog_ori.exec() == QDialog::Accepted) ori = ori_widget -> orientationSet();
}
void EditorScene::slot_editNames() {
// cree un dialogue
QDialog dialog;
dialog.setModal(true);
dialog.setFixedSize(400, 330);
dialog.setWindowTitle(tr("\311diter les noms"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog);
// ajoute un champ explicatif au dialogue
QLabel *information_label = new QLabel(tr("Vous pouvez sp\351cifier le nom de l'\351l\351ment dans plusieurs langues."));
information_label -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
information_label -> setWordWrap(true);
dialog_layout -> addWidget(information_label);
// ajoute un NamesListWidget au dialogue
NamesListWidget *names_widget = new NamesListWidget();
names_widget -> setNames(_names);
dialog_layout -> addWidget(names_widget);
// ajoute deux boutons au dialogue
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dialog_buttons);
connect(dialog_buttons, SIGNAL(accepted()), names_widget, SLOT(check()));
connect(names_widget, SIGNAL(inputChecked()), &dialog, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), &dialog, SLOT(reject()));
// lance le dialogue
if (dialog.exec() == QDialog::Accepted) _names = names_widget -> names();
}

136
editor/editorscene.h Normal file
View File

@ -0,0 +1,136 @@
#ifndef EDITOR_SCNE_H
#define EDITOR_SCNE_H
#include <QtGui>
#include <QtXml>
#include "nameslistwidget.h"
#include "orientationsetwidget.h"
class PartLine;
class PartEllipse;
class PartCircle;
class PartPolygon;
class EditorScene : public QGraphicsScene {
Q_OBJECT
// enum
enum Behavior { Normal, Line, Circle, Ellipse, Polygon, Text, Terminal, Arc, TextField };
// constructeurs, destructeur
public:
EditorScene(QObject * = 0);
virtual ~EditorScene();
private:
EditorScene(const EditorScene &);
// attributs
private:
/// longueur de l'element en dizaines de pixels
uint _width;
/// hauteur de l'element en dizaines de pixels
uint _height;
/// position du point de saisie
QPoint _hotspot;
/// Liste des noms de l'element
NamesList _names;
/// Liste des orientations de l'element
OrientationSet ori;
/// Variables relatives a la gestion du dessin des parties sur la scene
Behavior behavior;
PartLine *current_line;
PartEllipse *current_ellipse;
PartCircle *current_circle;
PartPolygon *current_polygon;
// methodes
public:
void setWidth(const uint& theValue);
uint width() const;
void setHeight(const uint& theValue);
uint height() const;
void setHotspot(const QPoint &);
QPoint hotspot() const;
void setNames(const NamesList);
NamesList names() const;
OrientationSet orientations();
void setOrientations(const OrientationSet &);
virtual const QDomDocument toXml() const;
virtual void fromXml(const QDomDocument &);
protected:
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
virtual void drawBackground(QPainter *, const QRectF &);
virtual void drawForeground(QPainter *, const QRectF &);
public slots:
void slot_move();
void slot_addLine();
void slot_addCircle();
void slot_addEllipse();
void slot_addPolygon();
void slot_addText();
void slot_addArc();
void slot_addTerminal();
void slot_addTextField();
void slot_checkSelectionChanged();
void slot_selectAll();
void slot_deselectAll();
void slot_invertSelection();
void slot_delete();
void slot_editSize();
void slot_editHotSpot();
void slot_editNames();
void slot_editOrientations();
signals:
void selectionChanged();
void needNormalMode();
};
inline void EditorScene::setWidth(const uint &wid) {
_width = wid;
while (_width % 10) ++ _width;
_width /= 10;
}
inline uint EditorScene::width() const {
return(_width * 10);
}
inline void EditorScene::setHeight(const uint &hei) {
_height = hei;
while (_height % 10) ++ _height;
_height /= 10;
}
inline uint EditorScene::height() const {
return(_height * 10);
}
inline void EditorScene::setHotspot(const QPoint &hs) {
_hotspot = hs;
}
inline QPoint EditorScene::hotspot() const {
return(_hotspot);
}
inline void EditorScene::setNames(const NamesList nameslist) {
_names = nameslist;
}
inline NamesList EditorScene::names() const {
return(_names);
}
inline OrientationSet EditorScene::orientations() {
return(ori);
}
inline void EditorScene::setOrientations(const OrientationSet &orientation_set) {
ori = orientation_set;
}
#endif

66
editor/ellipseeditor.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "ellipseeditor.h"
#include "partellipse.h"
EllipseEditor::EllipseEditor(PartEllipse *ellipse, QWidget *parent) : QWidget(parent) {
part = ellipse;
x = new QLineEdit();
y = new QLineEdit();
h = new QLineEdit();
v = new QLineEdit();
// QDoubleValidator *format = new QDoubleValidator(-1000.0, -1000.0, 4, this);
// x -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
// y -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
// h -> setValidator(new QDoubleValidator(0.0, 1000.0, 4, this));
// v -> setValidator(new QDoubleValidator(0.0, 1000.0, 4, this));
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel(tr("Centre : ")), 0, 0);
grid -> addWidget(new QLabel("x"), 1, 0);
grid -> addWidget(x, 1, 1);
grid -> addWidget(new QLabel("y"), 1, 2);
grid -> addWidget(y, 1, 3);
grid -> addWidget(new QLabel(tr("Diam\350tres : ")), 2, 0);
grid -> addWidget(new QLabel(tr("horizontal :")), 3, 0);
grid -> addWidget(h, 3, 1);
grid -> addWidget(new QLabel(tr("vertical :")), 4, 0);
grid -> addWidget(v, 4, 1);
updateForm();
connect(x, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
connect(y, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
connect(h, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
connect(v, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
}
EllipseEditor::~EllipseEditor() {
qDebug() << "~EllipseEditor()";
}
void EllipseEditor::updateEllipse() {
qreal _x = x -> text().toDouble();
qreal _y = y -> text().toDouble();
qreal _h = h -> text().toDouble();
qreal _v = v -> text().toDouble();
_v = _v < 0 ? -_v : _v;
part -> setRect(
QRectF(
part -> mapFromScene(QPointF(_x - (_h / 2.0), _y - (_v / 2.0))),
QSizeF(_h, _v)
)
);
}
void EllipseEditor::updateForm() {
qreal _h = part -> rect().width();
qreal _v = part -> rect().height();
QPointF top_left(part -> sceneTopLeft());
x -> setText(QString("%1").arg(top_left.x() + (_h / 2.0)));
y -> setText(QString("%1").arg(top_left.y() + (_v / 2.0)));
h -> setText(QString("%1").arg(_h));
v -> setText(QString("%1").arg(_v));
}

24
editor/ellipseeditor.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef ELLIPSE_EDITOR_H
#define ELLIPSE_EDITOR_H
#include <QtGui>
class PartEllipse;
class EllipseEditor : public QWidget {
Q_OBJECT
//constructeurs, destructeur
public:
EllipseEditor(PartEllipse *, QWidget * = 0);
~EllipseEditor();
private:
EllipseEditor(const EllipseEditor &);
// attributs
private:
PartEllipse *part;
QLineEdit *x, *y, *h, *v;
// methodes
public slots:
void updateEllipse();
void updateForm();
};
#endif

57
editor/lineeditor.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "lineeditor.h"
#include "partline.h"
LineEditor::LineEditor(PartLine *line, QWidget *parent) : QWidget(parent) {
part = line;
x1 = new QLineEdit();
y1 = new QLineEdit();
x2 = new QLineEdit();
y2 = new QLineEdit();
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel("x1"), 0, 0);
grid -> addWidget(x1, 0, 1);
grid -> addWidget(new QLabel("y1"), 0, 2);
grid -> addWidget(y1, 0, 3);
grid -> addWidget(new QLabel("x2"), 1, 0);
grid -> addWidget(x2, 1, 1);
grid -> addWidget(new QLabel("y2"), 1, 2);
grid -> addWidget(y2, 1, 3);
updateForm();
connect(x1, SIGNAL(editingFinished()), this, SLOT(updateLine()));
connect(y1, SIGNAL(editingFinished()), this, SLOT(updateLine()));
connect(x2, SIGNAL(editingFinished()), this, SLOT(updateLine()));
connect(y2, SIGNAL(editingFinished()), this, SLOT(updateLine()));
}
LineEditor::~LineEditor() {
qDebug() << "~LineEditor()";
}
void LineEditor::updateLine() {
part -> setLine(
QLineF(
part -> mapFromScene(
x1 -> text().toDouble(),
y1 -> text().toDouble()
),
part -> mapFromScene(
x2 -> text().toDouble(),
y2 -> text().toDouble()
)
)
);
}
void LineEditor::updateForm() {
QPointF p1(part -> sceneP1());
QPointF p2(part -> sceneP2());
x1 -> setText(QString("%1").arg(p1.x()));
y1 -> setText(QString("%1").arg(p1.y()));
x2 -> setText(QString("%1").arg(p2.x()));
y2 -> setText(QString("%1").arg(p2.y()));
}

24
editor/lineeditor.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef LINE_EDITOR_H
#define LINE_EDITOR_H
#include <QtGui>
class PartLine;
class LineEditor : public QWidget {
Q_OBJECT
//constructeurs, destructeur
public:
LineEditor(PartLine *, QWidget * = 0);
~LineEditor();
private:
LineEditor(const LineEditor &);
// attributs
private:
PartLine *part;
QLineEdit *x1, *y1, *x2, *y2;
// methodes
public slots:
void updateLine();
void updateForm();
};
#endif

77
editor/partcircle.cpp Normal file
View File

@ -0,0 +1,77 @@
#include "partcircle.h"
#include "circleeditor.h"
PartCircle::PartCircle(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart() {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new CircleEditor(this);
style_editor -> appendWidget(informations);
}
void PartCircle::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> drawEllipse(rect());
if (isSelected()) {
painter -> setRenderHint(QPainter::Antialiasing, false);
painter -> setPen((painter -> brush().color() == QColor(Qt::black) && painter -> brush().isOpaque()) ? Qt::yellow : Qt::blue);
QPointF center = rect().center();
painter -> drawLine(QLineF(center.x() - 2.0, center.y(), center.x() + 2.0, center.y()));
painter -> drawLine(QLineF(center.x(), center.y() - 2.0, center.x(), center.y() + 2.0));
}
}
const QDomElement PartCircle::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("circle");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", top_left.x());
xml_element.setAttribute("y", top_left.y());
xml_element.setAttribute("diameter", rect().width());
stylesToXml(xml_element);
return(xml_element);
}
void PartCircle::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
qreal diameter = qde.attribute("diameter", "0").toDouble();
setRect(
QRectF(
mapFromScene(
qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()
),
QSizeF(
diameter,
diameter
)
)
);
}
QVariant PartCircle::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsEllipseItem::itemChange(change, value));
}
QPointF PartCircle::sceneTopLeft() const {
return(mapToScene(rect().topLeft()));
}
QPointF PartCircle::sceneCenter() const {
return(mapToScene(rect().center()));
}
QRectF PartCircle::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsEllipseItem::boundingRect());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}

33
editor/partcircle.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef PART_CIRCLE_H
#define PART_CIRCLE_H
#include <QtGui>
#include "customelementgraphicpart.h"
class CircleEditor;
class PartCircle : public QGraphicsEllipseItem, public CustomElementGraphicPart {
// constructeurs, destructeur
public:
PartCircle(QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartCircle() {
qDebug() << "~PartCircle()";
}
private:
PartCircle(const PartCircle &);
// attributs
private:
CircleEditor *informations;
// methodes
public:
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneTopLeft() const;
virtual QRectF boundingRect() const;
QPointF sceneCenter() const;
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
};
#endif

66
editor/partellipse.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "partellipse.h"
#include "ellipseeditor.h"
PartEllipse::PartEllipse(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart() {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new EllipseEditor(this);
style_editor -> appendWidget(informations);
}
void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> drawEllipse(rect());
if (isSelected()) {
painter -> setRenderHint(QPainter::Antialiasing, false);
painter -> setPen((painter -> brush().color() == QColor(Qt::black) && painter -> brush().isOpaque()) ? Qt::yellow : Qt::blue);
QPointF center = rect().center();
painter -> drawLine(QLineF(center.x() - 2.0, center.y(), center.x() + 2.0, center.y()));
painter -> drawLine(QLineF(center.x(), center.y() - 2.0, center.x(), center.y() + 2.0));
}
}
const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("ellipse");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", top_left.x());
xml_element.setAttribute("y", top_left.y());
xml_element.setAttribute("width", rect().width());
xml_element.setAttribute("height", rect().height());
stylesToXml(xml_element);
return(xml_element);
}
void PartEllipse::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
setRect(
QRectF(
mapFromScene(
qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()
),
QSizeF(
qde.attribute("width", "0").toDouble(),
qde.attribute("height", "0").toDouble()
)
)
);
}
QVariant PartEllipse::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsEllipseItem::itemChange(change, value));
}
QPointF PartEllipse::sceneTopLeft() const {
return(mapToScene(rect().topLeft()));
}

31
editor/partellipse.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef PART_ELLIPSE_H
#define PART_ELLIPSE_H
#include <QtGui>
#include "customelementgraphicpart.h"
class EllipseEditor;
class PartEllipse : public QGraphicsEllipseItem, public CustomElementGraphicPart {
// constructeurs, destructeur
public:
PartEllipse(QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartEllipse() {
qDebug() << "~PartEllipse()";
}
private:
PartEllipse(const PartEllipse &);
// attributs
private:
EllipseEditor *informations;
// methodes
public:
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneTopLeft() const;
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
};
#endif

143
editor/partline.cpp Normal file
View File

@ -0,0 +1,143 @@
#include "partline.h"
#include "lineeditor.h"
#include <cmath>
PartLine::PartLine(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsLineItem(parent, scene), CustomElementGraphicPart() {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new LineEditor(this);
style_editor -> appendWidget(informations);
}
void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem */*q*/, QWidget */*w*/) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> setBrush(Qt::NoBrush);
painter -> drawLine(line());
}
const QDomElement PartLine::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("line");
QPointF p1(sceneP1());
QPointF p2(sceneP2());
xml_element.setAttribute("x1", p1.x());
xml_element.setAttribute("y1", p1.y());
xml_element.setAttribute("x2", p2.x());
xml_element.setAttribute("y2", p2.y());
stylesToXml(xml_element);
return(xml_element);
}
void PartLine::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
setLine(
QLineF(
mapFromScene(
qde.attribute("x1", "0").toDouble(),
qde.attribute("y1", "0").toDouble()
),
mapFromScene(
qde.attribute("x2", "0").toDouble(),
qde.attribute("y2", "0").toDouble()
)
)
);
}
QVariant PartLine::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsLineItem::itemChange(change, value));
}
QPointF PartLine::sceneP1() const {
return(mapToScene(line().p1()));
}
QPointF PartLine::sceneP2() const {
return(mapToScene(line().p2()));
}
/*
*/
QPainterPath PartLine::shape() const {
QList<QPointF> points = fourShapePoints();
QPainterPath t;
t.setFillRule(Qt::WindingFill);
t.moveTo(points.at(0));
t.lineTo(points.at(1));
t.lineTo(points.at(2));
t.lineTo(points.at(3));
t.lineTo(points.at(0));
return(t);
}
/*
QRectF PartLine::boundingRect() const {
QList<QPointF> points = fourShapePoints();
qreal min_x = points.first().x();
qreal max_x = points.first().x();
qreal min_y = points.first().y();
qreal max_y = points.first().y();
foreach(QPointF p, points) {
if (p.x() > max_x) max_x = p.x();
if (p.x() < min_x) min_x = p.x();
if (p.y() > max_y) max_y = p.y();
if (p.y() < min_y) min_y = p.y();
}
QRectF r;
r.setCoords(min_x, min_y, max_x, max_y);
return(r);
}
*/
/**
@return une liste contenant les deux points de la droite + les 4 points entourant ces deux points
*/
QList<QPointF> PartLine::fourShapePoints() const {
// on a donc A(xa , ya) et B(xb, yb)
QPointF a = line().p1();
QPointF b = line().p2();
// on calcule le vecteur AB : (xb-xa, yb-ya)
QPointF v_ab = b - a;
// et la distance AB : racine des coordonnees du vecteur au carre
qreal ab = sqrt(pow(v_ab.x(), 2) + pow(v_ab.y(), 2));
// ensuite on definit le vecteur u(a, b) qui est egal au vecteur AB divise
// par sa longueur et multiplie par la longueur de la marge que tu veux
// laisser
QPointF u = v_ab / ab * 2.0;
// on définit le vecteur v(-b , a) qui est perpendiculaire à AB
QPointF v(-u.y(), u.x());
QPointF m = -u + v; // on a le vecteur M = -u + v
QPointF n = -u - v; // et le vecteur N=-u-v
QPointF h = a + m; // H = A + M
QPointF k = a + n; // K = A + N
QPointF i = b - n; // I = B - N
QPointF j = b - m; // J = B - M
QList<QPointF> result;
result << h << i << j << k;
return(result);
}
QRectF PartLine::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsLineItem::boundingRect());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}

37
editor/partline.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef PART_LINE_H
#define PART_LINE_H
#include <QtGui>
#include "customelementgraphicpart.h"
class LineEditor;
class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
// constructeurs, destructeur
public:
PartLine(QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartLine() {
qDebug() << "~PartLine()";
}
private:
PartLine(const PartLine &);
// attributs
private:
LineEditor *informations;
// methodes
public:
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneP1() const;
virtual QPointF sceneP2() const;
virtual QPainterPath shape() const;
virtual QRectF boundingRect() const;
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
QList<QPointF> fourShapePoints() const;
};
#endif

69
editor/partpolygon.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "partpolygon.h"
#include "qet.h"
#include "polygoneditor.h"
PartPolygon::PartPolygon(QGraphicsItem *parent, QGraphicsScene *scene) :
QGraphicsPolygonItem(parent, scene),
CustomElementGraphicPart(),
closed(false)
{
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new PolygonEditor(this);
style_editor -> appendWidget(informations);
}
void PartPolygon::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
int i = 1;
while(true) {
if (
QET::attributeIsAReal(qde, QString("x%1").arg(i)) &&\
QET::attributeIsAReal(qde, QString("y%1").arg(i))
) ++ i;
else break;
}
QPolygonF temp_polygon;
for (int j = 1 ; j < i ; ++ j) {
temp_polygon << QPointF(
qde.attribute(QString("x%1").arg(j)).toDouble(),
qde.attribute(QString("y%1").arg(j)).toDouble()
);
}
setPolygon(temp_polygon);
closed = qde.attribute("closed") != "false";
}
const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("polygon");
int i = 1;
foreach(QPointF point, polygon()) {
xml_element.setAttribute(QString("x%1").arg(i), point.x());
xml_element.setAttribute(QString("y%1").arg(i), point.y());
++ i;
}
if (!closed) xml_element.setAttribute("closed", "false");
stylesToXml(xml_element);
return(xml_element);
}
void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem */*q*/, QWidget */*w*/) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
if (closed) painter -> drawPolygon(polygon());
else painter -> drawPolyline(polygon());
}
QVariant PartPolygon::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsPolygonItem::itemChange(change, value));
}

61
editor/partpolygon.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef PART_POLYGON_H
#define PART_POLYGON_H
#include <QtGui>
#include "customelementgraphicpart.h"
class PolygonEditor;
class PartPolygon : public QGraphicsPolygonItem, public CustomElementGraphicPart {
// constructeurs, destructeur
public:
PartPolygon(QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartPolygon() {
qDebug() << "~PartPolygon()";
}
private:
PartPolygon(const PartPolygon &);
// attributs
private:
bool closed;
PolygonEditor *informations;
/**
constructeur
paint()
widget bidon pour l'edition
methode pour poser le polygone :
-mousePressEvent = pose un nouveau point
-mouseMoveEvent = deplace ce point
-mouveReleaseEvent = finalise ce point
utiliser QPolygonF ; memoriser le point en cours (tout comme le
partploygon en cours) et ne l'ajouter au qpolygonf que lors du
mouseReleaseEvent
*/
// methodes
public:
void fromXml(const QDomElement &);
const QDomElement toXml(QDomDocument &) const;
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
void setClosed(bool c);
bool isClosed() const;
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
};
/**
Specifie si le polygone doit etre ferme
@param c true pour un polygone ferme, false sinon
*/
inline void PartPolygon::setClosed(bool c) {
closed = c;
}
/**
Indique si le polygone est ferme
@return true si le polygone est ferme, false sinon
*/
inline bool PartPolygon::isClosed() const {
return(closed);
}
#endif

117
editor/partterminal.cpp Normal file
View File

@ -0,0 +1,117 @@
#include "partterminal.h"
#include "terminal.h"
#include "terminaleditor.h"
PartTerminal::PartTerminal(QGraphicsItem *parent, QGraphicsScene *scene) :
CustomElementPart(),
QGraphicsItem(parent, scene),
_orientation(QET::North)
{
informations = new TerminalEditor(this);
updateSecondPoint();
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setZValue(100000);
}
PartTerminal::~PartTerminal() {
qDebug() << "~PartTerminal()";
delete informations;
};
void PartTerminal::fromXml(const QDomElement &xml_elmt) {
// lit la position de la borne
qreal term_x = 0.0, term_y = 0.0;
QET::attributeIsAReal(xml_elmt, "x", &term_x);
QET::attributeIsAReal(xml_elmt, "y", &term_y);
setPos(QPointF(term_x, term_y));
// lit l'orientation de la borne
_orientation = QET::orientationFromString(xml_elmt.attribute("orientation"));
updateSecondPoint();
}
const QDomElement PartTerminal::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("terminal");
// ecrit la position de la borne
xml_element.setAttribute("x", QString("%1").arg(pos().x()));
xml_element.setAttribute("y", QString("%1").arg(pos().y()));
// ecrit l'orientation de la borne
xml_element.setAttribute("orientation", orientationToString(_orientation));
return(xml_element);
}
QWidget *PartTerminal::elementInformations() {
return(informations);
}
void PartTerminal::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) {
p -> save();
// annulation des renderhints
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, false);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
QPen t;
t.setWidthF(1.0);
// dessin de la borne en rouge
t.setColor(Qt::red);
p -> setPen(t);
p -> drawLine(QPointF(0.0, 0.0), second_point);
// dessin du point d'amarrage au conducteur en bleu
t.setColor(Terminal::couleur_neutre);
p -> setPen(t);
p -> setBrush(Terminal::couleur_neutre);
p -> drawPoint(QPointF(0.0, 0.0));
p -> restore();
}
QRectF PartTerminal::boundingRect() const {
QPointF p1, p2;
if (second_point.x() <= 0.0 && second_point.y() <= 0.0) {
p1 = second_point;
p2 = QPointF(0.0, 0.0);
} else {
p1 = QPointF(0.0, 0.0);
p2 = second_point;
}
QRectF br;
br.setTopLeft (p1 - QPointF(2.0, 2.0));
br.setBottomRight(p2 + QPointF(2.0, 2.0));
return(br);
}
QET::Orientation PartTerminal::orientation() const {
return(_orientation);
}
void PartTerminal::setOrientation(QET::Orientation ori) {
prepareGeometryChange();
_orientation = ori;
updateSecondPoint();
informations -> updateForm();
}
QVariant PartTerminal::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsItem::itemChange(change, value));
}
void PartTerminal::updateSecondPoint() {
qreal ts = 4.0; // terminal size
switch(_orientation) {
case QET::North: second_point = QPointF(0.0, ts); break;
case QET::East : second_point = QPointF(-ts, 0.0); break;
case QET::South: second_point = QPointF(0.0, -ts); break;
case QET::West : second_point = QPointF(ts, 0.0); break;
}
}

37
editor/partterminal.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef PART_TERMINAL_H
#define PART_TERMINAL_H
#include "customelementpart.h"
#include "qet.h"
#include <QtGui>
class TerminalEditor;
class PartTerminal : public CustomElementPart, public QGraphicsItem {
public:
// constructeurs, destructeur
PartTerminal(QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartTerminal();
private:
PartTerminal(const PartTerminal &);
// attributs
private:
QET::Orientation _orientation;
QPointF second_point;
TerminalEditor *informations;
// methodes
public:
virtual void fromXml(const QDomElement &);
virtual const QDomElement toXml(QDomDocument &) const;
virtual QWidget *elementInformations();
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
virtual QRectF boundingRect() const;
QET::Orientation orientation() const;
void setOrientation(QET::Orientation);
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
void updateSecondPoint();
};
#endif

104
editor/parttext.cpp Normal file
View File

@ -0,0 +1,104 @@
#include "parttext.h"
#include "texteditor.h"
PartText::PartText(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsTextItem(parent, scene), CustomElementPart(), can_check_changes(true) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setPlainText(tr("T"));
infos = new TextEditor(this);
}
PartText::~PartText() {
qDebug() << "~PartText()";
delete infos;
}
void PartText::fromXml(const QDomElement &xml_element) {
bool ok;
int font_size = xml_element.attribute("size").toInt(&ok);
if (!ok || font_size < 1) font_size = 20;
setFont(QFont(QString("Sans Serif"), font_size));
setPlainText(xml_element.attribute("text"));
setPos(
xml_element.attribute("x").toDouble(),
xml_element.attribute("y").toDouble()
);
}
const QDomElement PartText::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("text");
xml_element.setAttribute("x", QString("%1").arg(pos().x()));
xml_element.setAttribute("y", QString("%1").arg(pos().y()));
xml_element.setAttribute("text", toPlainText());
xml_element.setAttribute("size", font().pointSize());
return(xml_element);
}
QWidget *PartText::elementInformations() {
return(infos);
}
/**
Retourne la position du texte, l'origine etant le point en bas a gauche du
texte (et pas du cadre)
@return la position du texte
*/
QPointF PartText::pos() const {
return(QGraphicsTextItem::pos() + margin());
}
void PartText::setPos(const QPointF &left_corner_pos) {
QGraphicsTextItem::setPos(left_corner_pos - margin());
}
void PartText::setPos(qreal x, qreal y) {
QGraphicsTextItem::setPos(QPointF(x, y) - margin());
}
/**
@return Les coordonnees du point situe en bas a gauche du texte.
*/
QPointF PartText::margin() const {
QFont used_font = font();
QFontMetrics qfm(used_font);
QPointF margin(
(boundingRect().width () - qfm.width(toPlainText())) / 2.0,
((boundingRect().height() - used_font.pointSizeF()) / 3.0) + used_font.pointSizeF()
);
return(margin);
}
/**
Permet a l'element texte de redevenir deplacable a la fin de l'edition de texte
@param e Le QFocusEvent decrivant la perte de focus
*/
void PartText::focusOutEvent(QFocusEvent *e) {
QGraphicsTextItem::focusOutEvent(e);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
/**
Permet a l'element texte de devenir editable lorsqu'on double-clique dessus
@param e Le QGraphicsSceneMouseEvent qui decrit le double-clic
*/
void PartText::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(e);
setFocus(Qt::MouseFocusReason);
}
QVariant PartText::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene() && can_check_changes) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
infos -> updateForm();
}
}
return(QGraphicsTextItem::itemChange(change, value));
}
QRectF PartText::boundingRect() const {
QRectF r = QGraphicsTextItem::boundingRect();
r.adjust(0.0, -2.0, 0.0, 0.0);
return(r);
}

39
editor/parttext.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef PART_TEXT
#define PART_TEXT
#include <QtGui>
#include "customelementgraphicpart.h"
class TextEditor;
class PartText : public QGraphicsTextItem, public CustomElementPart {
// constructeurs, destructeur
public:
PartText(QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartText();
private:
PartText(const PartText &);
// attributs
TextEditor *infos;
// methodes
public:
void fromXml(const QDomElement &);
const QDomElement toXml(QDomDocument &) const;
QWidget *elementInformations();
QPointF pos() const;
void setPos(const QPointF &);
void setPos(qreal, qreal);
protected:
virtual void focusOutEvent(QFocusEvent *);
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
QRectF boundingRect() const;
public:
bool can_check_changes;
private:
QPointF margin() const;
};
#endif

89
editor/polygoneditor.cpp Normal file
View File

@ -0,0 +1,89 @@
#include "polygoneditor.h"
#include "partpolygon.h"
/**
Constructeur
@param p Le polygone a editer
@param parent le Widget parent
*/
PolygonEditor::PolygonEditor(PartPolygon *p, QWidget *parent) :
QWidget(parent),
points_list(this),
close_polygon(tr("Polygone ferm\351"), this)
{
part = p;
// prepare la liste de points
points_list.setColumnCount(2);
QStringList headers;
headers << tr("x") << tr("y");
points_list.setHeaderLabels(headers);
points_list.setRootIsDecorated(false);
updateForm();
// layout
QVBoxLayout *layout = new QVBoxLayout(this);
layout -> addWidget(new QLabel(tr("Points du polygone :")));
layout -> addWidget(&points_list);
layout -> addWidget(&close_polygon);
// connexions signaux/slots
connect(&close_polygon, SIGNAL(stateChanged(int)), this, SLOT(updatePolygonClosedState()));
connect(&points_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(validColumn(QTreeWidgetItem *, int)));
}
void PolygonEditor::updatePolygon() {
updatePolygonPoints();
updatePolygonClosedState();
}
void PolygonEditor::updatePolygonPoints() {
QVector<QPointF> points = getPointsFromTree();
if (points.count() < 2) {
QMessageBox::warning(
this,
tr("Erreur"),
tr("Le polygone doit comporter au moins deux points.")
);
return;
}
part -> setPolygon(points);
}
void PolygonEditor::updatePolygonClosedState() {
part -> setClosed(close_polygon.isChecked());
}
void PolygonEditor::updateForm() {
while(points_list.takeTopLevelItem(0));
foreach(QPointF point, part -> polygon()) {
point = part -> mapToScene(point);
QStringList qsl;
qsl << QString("%1").arg(point.x()) << QString("%1").arg(point.y());
QTreeWidgetItem *qtwi = new QTreeWidgetItem(qsl);
qtwi -> setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
points_list.addTopLevelItem(qtwi);
}
close_polygon.setChecked(part -> isClosed());
}
QVector<QPointF> PolygonEditor::getPointsFromTree() {
QVector<QPointF> points;
for(int i = 0 ; i < points_list.topLevelItemCount() ; ++ i) {
QTreeWidgetItem *qtwi = points_list.topLevelItem(i);
bool x_convert_ok, y_convert_ok;
qreal x = qtwi -> text(0).toDouble(&x_convert_ok);
qreal y = qtwi -> text(1).toDouble(&y_convert_ok);
if (!x_convert_ok || !y_convert_ok) continue;
points << part -> mapFromScene(QPointF(x, y));
}
return(points);
}
void PolygonEditor::validColumn(QTreeWidgetItem *qtwi, int column) {
bool convert_ok;
qtwi -> text(column).toDouble(&convert_ok);
if (convert_ok) {
points_list.closePersistentEditor(qtwi, column);
updatePolygonPoints();
} else points_list.openPersistentEditor(qtwi, column);
}

35
editor/polygoneditor.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef POLYGON_EDITOR_H
#define POLYGON_EDITOR_H
#include <QtGui>
class PartPolygon;
class PolygonEditor : public QWidget {
Q_OBJECT
// constructeurs, destructeur
public:
PolygonEditor(PartPolygon *, QWidget * = 0);
~PolygonEditor() {
qDebug() << "~PolygonEditor()";
}
private:
PolygonEditor(const PolygonEditor &);
// attributs
private:
PartPolygon *part;
QTreeWidget points_list;
QCheckBox close_polygon;
// methodes
private:
QVector<QPointF> getPointsFromTree();
public slots:
void updatePolygon();
void updatePolygonPoints();
void updatePolygonClosedState();
void updateForm();
void validColumn(QTreeWidgetItem *qtwi, int column);
};
#endif

125
editor/qet.cpp Normal file
View File

@ -0,0 +1,125 @@
#include "qet.h"
/**
Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w")
en orientation. Si la chaine fait plusieurs caracteres, seul le
premier est pris en compte. En cas d'incoherence, QET::North est
retourne.
@param s Chaine de caractere cense representer une orientation
@return l'orientation designee par la chaine de caractere
*/
QET::Orientation QET::orientationFromString(const QString &s) {
QChar c = s[0];
if (c == 'e') return(QET::East);
else if (c == 's') return(QET::South);
else if (c == 'w') return (QET::West);
else return(QET::North);
}
/**
@param o une orientation
@return une chaine de caractere representant l'orientation
*/
QString QET::orientationToString(QET::Orientation o) {
QString ret;
switch(o) {
case QET::North: ret = "n"; break;
case QET::East : ret = "e"; break;
case QET::South: ret = "s"; break;
case QET::West : ret = "w"; break;
}
return(ret);
}
/**
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 QET::surLeMemeAxe(QET::Orientation a, QET::Orientation b) {
if ((a == QET::North || a == QET::South) && (b == QET::North || b == QET::South)) return(true);
else if ((a == QET::East || a == QET::West) && (b == QET::East || b == QET::West)) 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 QET::estHorizontale(QET::Orientation a) {
return(a == QET::East || a == QET::West);
}
/**
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 QET::estVerticale(QET::Orientation a) {
return(a == QET::North || a == QET::South);
}
/**
Permet de connaitre l'orientation suivante apres celle donnee en parametre.
Les orientations sont generalement presentees dans l'ordre suivant : Nord,
Est, Sud, Ouest.
@param o une orientation
@return l'orientation suivante
*/
QET::Orientation QET::nextOrientation(QET::Orientation o) {
if (o < 0 || o > 2) return(QET::North);
return((QET::Orientation)(o + 1));
}
/**
Permet de connaitre l'orientation precedant celle donnee en parametre.
Les orientations sont generalement presentees dans l'ordre suivant : Nord,
Est, Sud, Ouest.
@param o une orientation
@return l'orientation precedente
*/
QET::Orientation QET::previousOrientation(QET::Orientation o) {
if (o < 0 || o > 3) return(QET::North);
if (o == QET::North) return(QET::West);
return((QET::Orientation)(o - 1));
}
/**
Permet de savoir si l'attribut nom_attribut d'un element XML e est bien un
entier. Si oui, sa valeur est copiee dans entier.
@param e Element XML
@param nom_attribut Nom de l'attribut a analyser
@param entier Pointeur facultatif vers un entier
@return true si l'attribut est bien un entier, false sinon
*/
bool QET::attributeIsAnInteger(const QDomElement &e, QString nom_attribut, int *entier) {
// verifie la presence de l'attribut
if (!e.hasAttribute(nom_attribut)) return(false);
// verifie la validite de l'attribut
bool ok;
int tmp = e.attribute(nom_attribut).toInt(&ok);
if (!ok) return(false);
if (entier != NULL) *entier = tmp;
return(true);
}
/**
Permet de savoir si l'attribut nom_attribut d'un element XML e est bien un
reel. Si oui, sa valeur est copiee dans reel.
@param e Element XML
@param nom_attribut Nom de l'attribut a analyser
@param reel Pointeur facultatif vers un double
@return true si l'attribut est bien un reel, false sinon
*/
bool QET::attributeIsAReal(const QDomElement &e, QString nom_attribut, double *reel) {
// verifie la presence de l'attribut
if (!e.hasAttribute(nom_attribut)) return(false);
// verifie la validite de l'attribut
bool ok;
qreal tmp = e.attribute(nom_attribut).toDouble(&ok);
if (!ok) return(false);
if (reel != NULL) *reel = tmp;
return(true);
}

121
editor/styleeditor.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "styleeditor.h"
#include "customelementgraphicpart.h"
StyleEditor::StyleEditor(CustomElementGraphicPart *p, QWidget *parent) : QWidget(parent), part(p) {
// couleur
color = new QButtonGroup(this);
color -> addButton(black_color = new QRadioButton(tr("Noir")), CustomElementGraphicPart::BlackColor);
color -> addButton(white_color = new QRadioButton(tr("Blanc")), CustomElementGraphicPart::WhiteColor);
connect(color, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
// style
style = new QButtonGroup(this);
style -> addButton(normal_style = new QRadioButton(tr("Normal")), CustomElementGraphicPart::NormalStyle);
style -> addButton(dashed_style = new QRadioButton(tr("Pointill\351")), CustomElementGraphicPart::DashedStyle);
style -> button(part -> lineStyle()) -> setChecked(true);
connect(style, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
// epaisseur
weight = new QButtonGroup(this);
weight -> addButton(none_weight = new QRadioButton(tr("Nulle")), CustomElementGraphicPart::NoneWeight);
weight -> addButton(thin_weight = new QRadioButton(tr("Fine")), CustomElementGraphicPart::ThinWeight);
weight -> addButton(normal_weight = new QRadioButton(tr("Normale")), CustomElementGraphicPart::NormalWeight);
connect(weight, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
// remplissage
filling = new QButtonGroup(this);
filling -> addButton(no_filling = new QRadioButton(tr("Aucun")), CustomElementGraphicPart::NoneFilling );
filling -> addButton(black_filling = new QRadioButton(tr("Noir")), CustomElementGraphicPart::BlackFilling);
filling -> addButton(white_filling = new QRadioButton(tr("Blanc")), CustomElementGraphicPart::WhiteFilling);
connect(filling, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
// antialiasing
antialiasing = new QCheckBox(tr("Antialiasing"));
connect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePart()));
updateForm();
main_layout = new QVBoxLayout();
main_layout -> addWidget(antialiasing);
main_layout -> addWidget(new QLabel("<u>" + tr("Trait :") + "</u> "));
QHBoxLayout *color_layout = new QHBoxLayout();
color_layout -> addWidget(new QLabel(tr("Couleur : ")));
color_layout -> addWidget(black_color);
color_layout -> addWidget(white_color);
color_layout -> addStretch();
main_layout -> addItem(color_layout);
QHBoxLayout *style_layout = new QHBoxLayout();
style_layout -> addWidget(new QLabel(tr("Style : ")));
style_layout -> addWidget(normal_style);
style_layout -> addWidget(dashed_style);
style_layout -> addStretch();
main_layout -> addItem(style_layout);
QHBoxLayout *weight_layout = new QHBoxLayout();
weight_layout -> addWidget(new QLabel(tr("\311paisseur : ")));
weight_layout -> addWidget(none_weight);
weight_layout -> addWidget(thin_weight);
weight_layout -> addWidget(normal_weight);
weight_layout -> addStretch();
main_layout -> addItem(weight_layout);
main_layout -> addWidget(new QLabel("<u>" + tr("Remplissage :") + "</u> "));
QHBoxLayout *filling_layout = new QHBoxLayout();
filling_layout -> addWidget(no_filling);
filling_layout -> addWidget(black_filling);
filling_layout -> addWidget(white_filling);
filling_layout -> addStretch();
main_layout -> addItem(filling_layout);
main_layout -> addStretch();
setLayout(main_layout);
}
StyleEditor::~StyleEditor() {
qDebug() << "~StyleEditor()";
}
void StyleEditor::updatePart() {
// applique l'antialiasing
part -> setAntialiased(antialiasing -> isChecked());
// applique la couleur
part -> setColor(static_cast<CEGP::Color>(color -> checkedId()));
// applique le style
part -> setLineStyle(static_cast<CEGP::LineStyle>(style -> checkedId()));
// applique l'epaisseur
part -> setLineWeight(static_cast<CEGP::LineWeight>(weight -> checkedId()));
// applique le remplissage
part -> setFilling(static_cast<CEGP::Filling>(filling -> checkedId()));
}
void StyleEditor::updateForm() {
// lit l'antialiasing : deconnexion du slot pour eviter l'appel a updatePart()
disconnect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePart()));
antialiasing -> setChecked(part -> antialiased());
connect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePart()));
// lit la couleur
color -> button(part -> color()) -> setChecked(true);
// lit le style
style -> button(part -> lineStyle()) -> setChecked(true);
// lit l'epaisseur
weight -> button(part -> lineWeight()) -> setChecked(true);
// lit le remplissage
filling -> button(part -> filling()) -> setChecked(true);
}
void StyleEditor::appendWidget(QWidget *w) {
main_layout -> insertWidget(7, w);
}

33
editor/styleeditor.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef STYLE_EDITOR_H
#define STYLE_EDITOR_H
#include <QtGui>
class CustomElementGraphicPart;
class StyleEditor : public QWidget {
Q_OBJECT
// constructeurs, destructeur
public:
StyleEditor(CustomElementGraphicPart *, QWidget * = 0);
virtual ~StyleEditor();
private:
StyleEditor(const StyleEditor &);
// attributs
private:
CustomElementGraphicPart *part;
QVBoxLayout *main_layout;
QButtonGroup *color, *style, *weight, *filling;
QRadioButton *black_color, *white_color, *normal_style, *dashed_style;
QRadioButton *none_weight, *thin_weight, *normal_weight, *no_filling;
QRadioButton *black_filling, *white_filling;
QCheckBox *antialiasing;
//methodes
public:
void appendWidget(QWidget *w);
public slots:
void updatePart();
void updateForm();
};
#endif

67
editor/terminaleditor.cpp Normal file
View File

@ -0,0 +1,67 @@
#include "terminaleditor.h"
#include "partterminal.h"
/**
Constructeur
@param term Borne a editer
@param parent QWidget parent de ce widget
*/
TerminalEditor::TerminalEditor(PartTerminal *term, QWidget *parent) : QWidget(parent) {
part = term;
qle_x = new QLineEdit();
qle_y = new QLineEdit();
orientation = new QComboBox();
orientation -> addItem(QIcon(":/ico/north.png"), tr("Nord"), QET::North);
orientation -> addItem(QIcon(":/ico/east.png"), tr("Est"), QET::East);
orientation -> addItem(QIcon(":/ico/south.png"), tr("Sud"), QET::South);
orientation -> addItem(QIcon(":/ico/west.png"), tr("Ouest"), QET::West);
QVBoxLayout *main_layout = new QVBoxLayout();
main_layout -> addWidget(new QLabel(tr("Postion : ")));
QHBoxLayout *position = new QHBoxLayout();
position -> addWidget(new QLabel(tr("x : ")));
position -> addWidget(qle_x );
position -> addWidget(new QLabel(tr("y : ")));
position -> addWidget(qle_y );
main_layout -> addLayout(position);
QHBoxLayout *ori = new QHBoxLayout();
ori -> addWidget(new QLabel(tr("Orientation : ")));
ori -> addWidget(orientation );
main_layout -> addLayout(ori);
main_layout -> addStretch();
setLayout(main_layout);
connect(qle_x, SIGNAL(textEdited(const QString &)), this, SLOT(updateTerminal()));
connect(qle_y, SIGNAL(textEdited(const QString &)), this, SLOT(updateTerminal()));
connect(orientation, SIGNAL(activated(int)), this, SLOT(updateTerminal()));
updateForm();
}
/**
Destructeur
*/
TerminalEditor::~TerminalEditor() {
qDebug() << "~TerminalEditor()";
};
void TerminalEditor::updateTerminal() {
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
part -> setOrientation(
static_cast<QET::Orientation>(
orientation -> itemData(
orientation -> currentIndex()
).toInt()
)
);
}
void TerminalEditor::updateForm() {
qle_x -> setText(QString("%1").arg(part -> pos().x()));
qle_y -> setText(QString("%1").arg(part -> pos().y()));
orientation -> setCurrentIndex(static_cast<int>(part -> orientation()));
}

30
editor/terminaleditor.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef TERMINAL_EDITOR_H
#define TERMINAL_EDITOR_H
#include <QtGui>
class PartTerminal;
/**
Cette classe represente un editeur de borne.
Elle permet d'editer a travers une interface graphique les
proprietes d'une borne d'element.
*/
class TerminalEditor : public QWidget {
Q_OBJECT
// Constructeurs, destructeur
public:
TerminalEditor(PartTerminal *, QWidget * = 0);
virtual ~TerminalEditor();
private:
TerminalEditor(const TerminalEditor &);
// attributs
private:
PartTerminal *part;
QLineEdit *qle_x, *qle_y;
QComboBox *orientation;
// methodes
public slots:
void updateTerminal();
void updateForm();
};
#endif

68
editor/texteditor.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "texteditor.h"
#include "parttext.h"
/**
Constructeur
@param term Champ de texte a editer
@param parent QWidget parent de ce widget
*/
TextEditor::TextEditor(PartText *text, QWidget *parent) : QWidget(parent) {
part = text;
qle_x = new QLineEdit();
qle_y = new QLineEdit();
qle_text = new QLineEdit();
font_size = new QSpinBox();
font_size -> setRange(0, 144);
QVBoxLayout *main_layout = new QVBoxLayout();
main_layout -> addWidget(new QLabel(tr("Postion : ")));
QHBoxLayout *position = new QHBoxLayout();
position -> addWidget(new QLabel(tr("x : ")));
position -> addWidget(qle_x );
position -> addWidget(new QLabel(tr("y : ")));
position -> addWidget(qle_y );
main_layout -> addLayout(position);
QHBoxLayout *fs = new QHBoxLayout();
fs -> addWidget(new QLabel(tr("Taille : ")));
fs -> addWidget(font_size);
main_layout -> addLayout(fs);
QHBoxLayout *t = new QHBoxLayout();
t -> addWidget(new QLabel(tr("Texte : ")));
t -> addWidget(qle_text);
main_layout -> addLayout(t);
main_layout -> addStretch();
setLayout(main_layout);
connect(qle_x, SIGNAL(textEdited(const QString &)), this, SLOT(updateText()));
connect(qle_y, SIGNAL(textEdited(const QString &)), this, SLOT(updateText()));
connect(qle_text, SIGNAL(textEdited(const QString &)), this, SLOT(updateText()));
connect(font_size, SIGNAL(valueChanged(int)), this, SLOT(updateText()));
//updateForm();
}
/**
Destructeur
*/
TextEditor::~TextEditor() {
qDebug() << "~TextEditor()";
}
void TextEditor::updateText() {
part -> can_check_changes = false;
part -> setFont(QFont(part -> font().family(), font_size -> value()));
part -> setPlainText(qle_text -> text());
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
part -> can_check_changes = true;
}
void TextEditor::updateForm() {
qle_x -> setText(QString("%1").arg(part -> pos().x()));
qle_y -> setText(QString("%1").arg(part -> pos().y()));
qle_text -> setText(part -> toPlainText());
font_size -> setValue(part -> font().pointSize());
}

30
editor/texteditor.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef TEXT_EDITOR_H
#define TEXT_EDITOR_H
#include <QtGui>
class PartText;
/**
Cette classe represente un editeur de champ de texte non editable
Elle permet d'editer a travers une interface graphique les
proprietes d'un champ de texte non editable.
*/
class TextEditor : public QWidget {
Q_OBJECT
// Constructeurs, destructeur
public:
TextEditor(PartText *, QWidget * = 0);
virtual ~TextEditor();
private:
TextEditor(const TextEditor &);
// attributs
private:
PartText *part;
QLineEdit *qle_x, *qle_y, *qle_text;
QSpinBox *font_size;
// methodes
public slots:
void updateText();
void updateForm();
};
#endif

View File

@ -123,14 +123,14 @@ QVariant Element::itemChange(GraphicsItemChange change, const QVariant &value) {
@param o la nouvelle orientation de l'objet @param o la nouvelle orientation de l'objet
@return true si l'orientation a pu etre appliquee, false sinon @return true si l'orientation a pu etre appliquee, false sinon
*/ */
bool Element::setOrientation(Terminal::Orientation o) { bool Element::setOrientation(QET::Orientation o) {
// verifie que l'orientation demandee est acceptee // verifie que l'orientation demandee est acceptee
if (!acceptOrientation(o)) return(false); if (!ori.accept(o)) return(false);
prepareGeometryChange(); prepareGeometryChange();
// rotation en consequence et rafraichissement de l'element graphique // rotation en consequence et rafraichissement de l'element graphique
qreal rotation_value = 90.0 * (o - ori); qreal rotation_value = 90.0 * (o - ori.current());
rotate(rotation_value); rotate(rotation_value);
ori = o; ori.setCurrent(o);
update(); update();
foreach(QGraphicsItem *qgi, children()) { foreach(QGraphicsItem *qgi, children()) {
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) p -> updateConducer(); if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) p -> updateConducer();
@ -353,8 +353,8 @@ bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
bool conv_ok; bool conv_ok;
int read_ori = e.attribute("orientation").toInt(&conv_ok); int read_ori = e.attribute("orientation").toInt(&conv_ok);
if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = defaultOrientation(); if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = ori.defaultOrientation();
setOrientation((Terminal::Orientation)read_ori); setOrientation((QET::Orientation)read_ori);
setSelected(e.attribute("selected") == "selected"); setSelected(e.attribute("selected") == "selected");
return(true); return(true);
@ -380,7 +380,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &table
element.setAttribute("x", pos().x()); element.setAttribute("x", pos().x());
element.setAttribute("y", pos().y()); element.setAttribute("y", pos().y());
if (isSelected()) element.setAttribute("selected", "selected"); if (isSelected()) element.setAttribute("selected", "selected");
element.setAttribute("orientation", QString("%1").arg(orientation())); element.setAttribute("orientation", QString("%1").arg(ori.current()));
/* recupere le premier id a utiliser pour les bornes de cet element */ /* recupere le premier id a utiliser pour les bornes de cet element */
int id_terminal = 0; int id_terminal = 0;

View File

@ -2,6 +2,7 @@
#define ELEMENT_H #define ELEMENT_H
#include <QtGui> #include <QtGui>
#include "terminal.h" #include "terminal.h"
#include "orientationset.h"
/** /**
Cette classe abstraite represente un element electrique. Cette classe abstraite represente un element electrique.
*/ */
@ -21,12 +22,7 @@ class Element : public QGraphicsItem {
enum { Type = UserType + 1000 }; enum { Type = UserType + 1000 };
protected: protected:
bool ori_n; OrientationSet ori;
bool ori_s;
bool ori_e;
bool ori_w;
Terminal::Orientation ori_d;
Terminal::Orientation ori;
private: private:
QSize dimensions; QSize dimensions;
@ -74,12 +70,8 @@ class Element : public QGraphicsItem {
virtual QDomElement toXml(QDomDocument &, QHash<Terminal *, int>&) const; virtual QDomElement toXml(QDomDocument &, QHash<Terminal *, int>&) const;
// methodes d'acces aux possibilites d'orientation // methodes d'acces aux possibilites d'orientation
Terminal::Orientation orientation() const; bool setOrientation(QET::Orientation o);
Terminal::Orientation defaultOrientation() const; const OrientationSet &orientation() const;
bool acceptOrientation(Terminal::Orientation o) const;
Terminal::Orientation nextAcceptableOrientation() const;
Terminal::Orientation previousAcceptableOrientation() const;
bool setOrientation(Terminal::Orientation o);
protected: protected:
void drawAxes(QPainter *, const QStyleOptionGraphicsItem *); void drawAxes(QPainter *, const QStyleOptionGraphicsItem *);
@ -89,8 +81,6 @@ class Element : public QGraphicsItem {
bool peut_relier_ses_propres_terminals; bool peut_relier_ses_propres_terminals;
void drawSelection(QPainter *, const QStyleOptionGraphicsItem *); void drawSelection(QPainter *, const QStyleOptionGraphicsItem *);
void updatePixmap(); void updatePixmap();
Terminal::Orientation nextOrientation(Terminal::Orientation o) const;
Terminal::Orientation previousOrientation(Terminal::Orientation o) const;
static QList<QDomElement> findInDomElement(QDomElement, QString, QString); static QList<QDomElement> findInDomElement(QDomElement, QString, QString);
}; };
@ -117,85 +107,8 @@ inline void Element::setConnexionsInternesAcceptees(bool cia) {
Permet de connaitre l'orientation actuelle de l'element Permet de connaitre l'orientation actuelle de l'element
@return L'orientation actuelle de l'element @return L'orientation actuelle de l'element
*/ */
inline Terminal::Orientation Element::orientation() const { inline const OrientationSet & Element::orientation() const {
return(ori); return(ori);
} }
/**
Permet de savoir si l'element peut etre positionne dans une orientation
donnee.
@param o L'orientation en question
@return true si l'orientation est utilisable, false sinon
*/
inline bool Element::acceptOrientation(Terminal::Orientation o) const {
switch(o) {
case Terminal::Nord: return(ori_n);
case Terminal::Est: return(ori_e);
case Terminal::Sud: return(ori_s);
case Terminal::Ouest: return(ori_w);
default: return(false);
}
}
/**
Permet de connaitre l'orientation par defaut de l'element
@return l'orientation par defaut de l'element
*/
inline Terminal::Orientation Element::defaultOrientation() const {
return(ori_d);
}
/**
Permet de connaitre la prochaine orientation autorisee pour cet element
@return la prochaine orientation autorisee pour cet element
*/
inline Terminal::Orientation Element::nextAcceptableOrientation() const {
Terminal::Orientation retour = nextOrientation(ori);
for (int i = 0 ; i < 4 ; ++ i) {
if (acceptOrientation(retour)) return(retour);
retour = nextOrientation(retour);
}
// on ne devrait pas arriver la : renvoi d'une valeur par defaut = nord
return(Terminal::Nord);
}
/**
Permet de connaitre la precedente orientation autorisee pour cet element
@return la precedente orientation autorisee pour cet element
*/
inline Terminal::Orientation Element::previousAcceptableOrientation() const {
Terminal::Orientation retour = previousOrientation(ori);
for (int i = 0 ; i < 4 ; ++ i) {
if (acceptOrientation(retour)) return(retour);
retour = previousOrientation(retour);
}
// on ne devrait pas arriver la : renvoi d'une valeur par defaut = nord
return(Terminal::Nord);
}
/**
Permet de connaitre l'orientation suivante apres celle donnee en parametre.
Les orientations sont generalement presentees dans l'ordre suivant : Nord,
Est, Sud, Ouest.
@param o une orientation
@return l'orientation suivante
*/
inline Terminal::Orientation Element::nextOrientation(Terminal::Orientation o) const {
if (o < 0 || o > 2) return(Terminal::Nord);
return((Terminal::Orientation)(o + 1));
}
/**
Permet de connaitre l'orientation precedant celle donnee en parametre.
Les orientations sont generalement presentees dans l'ordre suivant : Nord,
Est, Sud, Ouest.
@param o une orientation
@return l'orientation precedente
*/
inline Terminal::Orientation Element::previousOrientation(Terminal::Orientation o) const {
if (o < 0 || o > 3) return(Terminal::Nord);
if (o == Terminal::Nord) return(Terminal::Ouest);
return((Terminal::Orientation)(o - 1));
}
#endif #endif

View File

@ -135,3 +135,20 @@ bool ElementsCategory::remove() const {
return(rmdir(absolutePath())); return(rmdir(absolutePath()));
} }
/**
@return true s'il est possible d'ecrire le fichier qet_directory dans la
categorie
*/
bool ElementsCategory::isWritable() const {
// informations sur le dossier de la categorie
QFileInfo category(canonicalPath());
QFileInfo qet_directory(canonicalPath() + "/.qet_directory");
/*
soit .qet_directory n'existe pas et le dossier est accessible en ecriture,
soit .qet_directory existe et est accessible en ecriture
*/
return(
(!qet_directory.exists() && category.isWritable()) ||\
(qet_directory.exists() && qet_directory.isWritable())
);
}

View File

@ -28,6 +28,7 @@ class ElementsCategory : public QDir {
void addName(const QString &, const QString &); void addName(const QString &, const QString &);
bool write() const; bool write() const;
bool remove() const; bool remove() const;
bool isWritable() const;
//bool move(const QString &new_parent); //bool move(const QString &new_parent);
private: private:

View File

@ -29,6 +29,16 @@ ElementsCategoryEditor::ElementsCategoryEditor(const QString &category_path, boo
names_list -> setNames(cat_names); names_list -> setNames(cat_names);
//names_list -> openPersistentEditor(qtwi, 1); //names_list -> openPersistentEditor(qtwi, 1);
} }
// gestion de la lecture seule
if (!category -> isWritable()) {
QMessageBox::warning(
this,
tr("\311dition en lecture seule"),
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cette cat\351gorie. Elle sera donc ouverte en lecture seule.")
);
names_list -> setReadOnly(true);
}
} }
/** /**
@ -60,6 +70,8 @@ void ElementsCategoryEditor::buildDialog() {
categorie categorie
*/ */
void ElementsCategoryEditor::acceptCreation() { void ElementsCategoryEditor::acceptCreation() {
if (!category -> isWritable()) QDialog::accept();
// il doit y avoir au moins un nom // il doit y avoir au moins un nom
if (!names_list -> checkOneName()) return; if (!names_list -> checkOneName()) return;
@ -83,6 +95,8 @@ void ElementsCategoryEditor::acceptCreation() {
categorie categorie
*/ */
void ElementsCategoryEditor::acceptUpdate() { void ElementsCategoryEditor::acceptUpdate() {
if (!category -> isWritable()) QDialog::accept();
// il doit y avoir au moins un nom // il doit y avoir au moins un nom
if (!names_list -> checkOneName()) return; if (!names_list -> checkOneName()) return;

View File

@ -1,6 +1,8 @@
#include "elementspanel.h" #include "elementspanel.h"
#include "customelement.h"
#include "elementscategory.h" #include "elementscategory.h"
#include "elementscategoryeditor.h"
#include "customelement.h"
#include "customelementeditor.h"
/** /**
Constructeur Constructeur
@ -33,6 +35,9 @@ ElementsPanel::ElementsPanel(QWidget *parent) : QTreeWidget(parent) {
qp.setColor(QPalette::Highlight, QColor("#678db2")); qp.setColor(QPalette::Highlight, QColor("#678db2"));
qp.setColor(QPalette::HighlightedText, Qt::white); qp.setColor(QPalette::HighlightedText, Qt::white);
setPalette(qp); setPalette(qp);
// double-cliquer sur un element permet de l'editer
connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slot_doubleClick(QTreeWidgetItem *, int)));
} }
/** /**
@ -114,6 +119,7 @@ void ElementsPanel::addDir(QTreeWidgetItem *qtwi_parent, QString adr_dossier, QS
t.setColorAt(1, QColor("#ffffff")); t.setColorAt(1, QColor("#ffffff"));
qtwi_dossier -> setBackground(0, QBrush(t)); qtwi_dossier -> setBackground(0, QBrush(t));
qtwi_dossier -> setExpanded(true); qtwi_dossier -> setExpanded(true);
qtwi_dossier -> setData(0, 42, adr_dossier);
// ajout des sous-categories / sous-dossiers // ajout des sous-categories / sous-dossiers
QStringList dossiers = category.entryList(QStringList(), QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::Name); QStringList dossiers = category.entryList(QStringList(), QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::Name);
@ -160,3 +166,25 @@ void ElementsPanel::reload() {
// chargement des elements de la collection utilisateur // chargement des elements de la collection utilisateur
addDir(invisibleRootItem(), QETApp::customElementsDir(), tr("Collection utilisateur")); addDir(invisibleRootItem(), QETApp::customElementsDir(), tr("Collection utilisateur"));
} }
void ElementsPanel::slot_doubleClick(QTreeWidgetItem *qtwi, int) {
// recupere le fichier ou le dossier correspondant au QTreeWidgetItem
QString filename = qtwi -> data(0, 42).toString();
// le fichier doit exister
QFileInfo infos_file(filename);
if (!infos_file.exists()) return;
if (infos_file.isFile()) {
// il s'agit d'un element
CustomElementEditor *cee = new CustomElementEditor();
cee -> fromFile(filename);
cee -> show();
} else if (infos_file.isDir()) {
// il s'agit d'une categorie
ElementsCategory c(filename);
ElementsCategoryEditor ece(filename, true);
if (ece.exec() == QDialog::Accepted) reload();
}
}

View File

@ -24,6 +24,7 @@ class ElementsPanel : public QTreeWidget {
void addDir(QTreeWidgetItem *, QString, QString = QString()); void addDir(QTreeWidgetItem *, QString, QString = QString());
public slots: public slots:
void slot_doubleClick(QTreeWidgetItem *, int);
void dragMoveEvent(QDragMoveEvent *); void dragMoveEvent(QDragMoveEvent *);
void dropEvent(QDropEvent *); void dropEvent(QDropEvent *);
void startDrag(Qt::DropActions); void startDrag(Qt::DropActions);

View File

@ -35,6 +35,6 @@ ElementsPanelWidget::~ElementsPanelWidget() {
Appelle l'assistant de creation de nouvel element Appelle l'assistant de creation de nouvel element
*/ */
void ElementsPanelWidget::newElement() { void ElementsPanelWidget::newElement() {
NewElementWizard *new_element_wizard = new NewElementWizard(); NewElementWizard new_element_wizard;
new_element_wizard -> exec(); new_element_wizard.exec();
} }

BIN
ico/add_col.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

BIN
ico/allowed.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

BIN
ico/arc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

BIN
ico/circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

BIN
ico/east.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

BIN
ico/ellipse.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

BIN
ico/forbidden.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 B

BIN
ico/line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

BIN
ico/north.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

BIN
ico/orientations.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

BIN
ico/polygon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
ico/remove_col.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

BIN
ico/south.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

BIN
ico/terminal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

BIN
ico/text.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

BIN
ico/textfield.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

BIN
ico/west.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

View File

@ -4,7 +4,7 @@
Constructeur Constructeur
@param parent QWidget parent de la liste de noms @param parent QWidget parent de la liste de noms
*/ */
NamesListWidget::NamesListWidget(QWidget *parent) : QWidget(parent) { NamesListWidget::NamesListWidget(QWidget *parent) : QWidget(parent), read_only(false) {
QVBoxLayout *names_list_layout = new QVBoxLayout(); QVBoxLayout *names_list_layout = new QVBoxLayout();
setLayout(names_list_layout); setLayout(names_list_layout);
@ -32,6 +32,7 @@ NamesListWidget::~NamesListWidget() {
*/ */
void NamesListWidget::addLine() { void NamesListWidget::addLine() {
clean(); clean();
if (read_only) return;
QTreeWidgetItem *qtwi = new QTreeWidgetItem(); QTreeWidgetItem *qtwi = new QTreeWidgetItem();
qtwi -> setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); qtwi -> setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
tree_names -> addTopLevelItem(qtwi); tree_names -> addTopLevelItem(qtwi);
@ -45,8 +46,8 @@ bool NamesListWidget::checkOneName() {
if (!hash_names.count()) { if (!hash_names.count()) {
QMessageBox::critical( QMessageBox::critical(
this, this,
tr("La cat\351gorie doit avoir au moins un nom."), tr("Il doit y avoir au moins un nom."),
tr("Vous devez entrer au moins un nom pour la cat\351gorie.") tr("Vous devez entrer au moins un nom.")
); );
return(false); return(false);
} }
@ -62,7 +63,7 @@ void NamesListWidget::updateHash() {
for (int i = 0 ; i < names_count ; ++ i) { for (int i = 0 ; i < names_count ; ++ i) {
QString lang = tree_names -> topLevelItem(i) -> text(0); QString lang = tree_names -> topLevelItem(i) -> text(0);
QString value = tree_names -> topLevelItem(i) -> text(1); QString value = tree_names -> topLevelItem(i) -> text(1);
hash_names.addName(lang, value); if (lang != "" && value != "") hash_names.addName(lang, value);
} }
} }
@ -95,7 +96,25 @@ void NamesListWidget::setNames(const NamesList &provided_names) {
QStringList values; QStringList values;
values << lang << value; values << lang << value;
QTreeWidgetItem *qtwi = new QTreeWidgetItem(values); QTreeWidgetItem *qtwi = new QTreeWidgetItem(values);
qtwi -> setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); if (!read_only) qtwi -> setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
tree_names -> addTopLevelItem(qtwi); tree_names -> addTopLevelItem(qtwi);
} }
} }
void NamesListWidget::check() {
if (checkOneName()) emit(inputChecked());
}
void NamesListWidget::setReadOnly(bool ro) {
read_only = ro;
int names_count = tree_names -> topLevelItemCount() - 1;
for (int i = names_count ; i >= 0 ; -- i) {
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (!read_only) flags |= Qt::ItemIsEditable;
tree_names -> topLevelItem(i) -> setFlags(flags);
}
}
bool NamesListWidget::isReadOnly() const {
return(read_only);
}

View File

@ -22,12 +22,15 @@ class NamesListWidget : public QWidget {
QTreeWidget *tree_names; QTreeWidget *tree_names;
QPushButton *button_add_line; QPushButton *button_add_line;
NamesList hash_names; NamesList hash_names;
bool read_only;
// methodes // methodes
public: public:
bool checkOneName(); bool checkOneName();
NamesList names(); NamesList names();
void setNames(const NamesList &); void setNames(const NamesList &);
void setReadOnly(bool);
bool isReadOnly() const;
private: private:
void clean(); void clean();
@ -35,5 +38,9 @@ class NamesListWidget : public QWidget {
public slots: public slots:
void addLine(); void addLine();
void check();
signals:
void inputChecked();
}; };
#endif #endif

View File

@ -2,8 +2,10 @@
#include "elementscategorieswidget.h" #include "elementscategorieswidget.h"
#include "elementscategorieslist.h" #include "elementscategorieslist.h"
#include "nameslistwidget.h" #include "nameslistwidget.h"
#include "orientationsetwidget.h"
#include "diagram.h" #include "diagram.h"
#include "element.h" #include "element.h"
#include "customelementeditor.h"
/** /**
Constructeur Constructeur
@ -76,6 +78,7 @@ void NewElementWizard::previous() {
case Names: case Names:
current_state = Filename; current_state = Filename;
step2 -> show(); step2 -> show();
qle_filename -> setFocus();
step3 -> hide(); step3 -> hide();
break; break;
case Dimensions: case Dimensions:
@ -102,6 +105,7 @@ void NewElementWizard::next() {
current_state = Filename; current_state = Filename;
step1 -> hide(); step1 -> hide();
step2 -> show(); step2 -> show();
qle_filename -> setFocus();
button_previous -> setEnabled(true); button_previous -> setEnabled(true);
break; break;
case Filename: case Filename:
@ -158,7 +162,9 @@ void NewElementWizard::buildStep2() {
explication2 -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter); explication2 -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
explication2 -> setWordWrap(true); explication2 -> setWordWrap(true);
step2_layout -> addWidget(explication1); step2_layout -> addWidget(explication1);
step2_layout -> addWidget(qle_filename = new QLineEdit()); qle_filename = new QLineEdit(tr("nouvel_element"));
qle_filename -> selectAll();
step2_layout -> addWidget(qle_filename);
step2_layout -> addWidget(explication2); step2_layout -> addWidget(explication2);
step2_layout -> addSpacing(100); step2_layout -> addSpacing(100);
step2 -> setLayout(step2_layout); step2 -> setLayout(step2_layout);
@ -266,37 +272,12 @@ void NewElementWizard::buildStep5() {
explication -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter); explication -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
explication -> setWordWrap(true); explication -> setWordWrap(true);
#define MK_COMBO_BOX(a) a##_orientation = new QComboBox(); \ orientation_set = new OrientationSetWidget();
a##_orientation -> addItem(tr("Par d\351faut"), "d"); \
a##_orientation -> addItem(tr("Possible"), "y"); \
a##_orientation -> addItem(tr("Impossible"), "n");
// 4 combo box
MK_COMBO_BOX(north)
MK_COMBO_BOX(east)
MK_COMBO_BOX(south)
MK_COMBO_BOX(west)
#undef MK_COMBO_BOX
east_orientation -> setCurrentIndex(1);
south_orientation -> setCurrentIndex(1);
west_orientation -> setCurrentIndex(1);
QGridLayout *qgl = new QGridLayout();
qgl -> addWidget(new QLabel(tr("Nord :")), 0, 0);
qgl -> addWidget(north_orientation, 0, 1);
qgl -> addWidget(new QLabel(tr("Est :")), 1, 0);
qgl -> addWidget(east_orientation, 1, 1);
qgl -> addWidget(new QLabel(tr("Sud :")), 2, 0);
qgl -> addWidget(south_orientation, 2, 1);
qgl -> addWidget(new QLabel(tr("Ouest :")), 3, 0);
qgl -> addWidget(west_orientation, 3, 1);
QVBoxLayout *step5_layout = new QVBoxLayout(); QVBoxLayout *step5_layout = new QVBoxLayout();
step5_layout -> addWidget(explication); step5_layout -> addWidget(explication);
step5_layout -> addLayout(qgl); step5_layout -> addWidget(orientation_set);
step5_layout -> addSpacing(75); step5_layout -> addSpacing(25);
step5 -> setLayout(step5_layout); step5 -> setLayout(step5_layout);
} }
@ -349,6 +330,7 @@ bool NewElementWizard::validStep2() {
return(answer == QMessageBox::Yes); return(answer == QMessageBox::Yes);
} }
chosen_file = dir_path + "/" + file_name;
return(true); return(true);
} }
@ -377,19 +359,7 @@ bool NewElementWizard::validStep4() {
@return true si l'etape est validee, false sinon @return true si l'etape est validee, false sinon
*/ */
bool NewElementWizard::validStep5() { bool NewElementWizard::validStep5() {
int nb_orientations = 0; // l'editeur d'orientations se charge deja de valider tout ca
if (!north_orientation -> currentIndex()) ++ nb_orientations;
if (!east_orientation -> currentIndex()) ++ nb_orientations;
if (!south_orientation -> currentIndex()) ++ nb_orientations;
if (!west_orientation -> currentIndex()) ++ nb_orientations;
if (nb_orientations != 1) {
QMessageBox::critical(
this,
tr("Erreur"),
tr("Il doit y avoir exactement une orientation par d\351faut.")
);
return(false);
}
return(true); return(true);
} }
@ -445,6 +415,12 @@ void NewElementWizard::updateHotspotLimits() {
Cree le nouvel element Cree le nouvel element
*/ */
void NewElementWizard::createNewElement() { void NewElementWizard::createNewElement() {
/// @todo CustomElementEditor *edit_new_element = new CustomElementEditor(parentWidget());
QMessageBox::warning(this, "Creation de l'element", "Not Implemented Yet"); edit_new_element -> setSize(QSize(sb_width -> value() * 10, sb_height -> value() * 10));
edit_new_element -> setHotspot(QPoint(sb_hotspot_x -> value(), sb_hotspot_y -> value()));
edit_new_element -> setNames(element_names -> names());
edit_new_element -> setOrientations(orientation_set -> orientationSet());
edit_new_element -> setFileName(chosen_file);
edit_new_element -> show();
accept();
} }

View File

@ -14,6 +14,7 @@
*/ */
class ElementsCategoriesWidget; class ElementsCategoriesWidget;
class NamesListWidget; class NamesListWidget;
class OrientationSetWidget;
class Diagram; class Diagram;
class NewElementWizard : public QDialog { class NewElementWizard : public QDialog {
Q_OBJECT Q_OBJECT
@ -38,6 +39,7 @@ class NewElementWizard : public QDialog {
QSpinBox *sb_hotspot_x; QSpinBox *sb_hotspot_x;
QSpinBox *sb_hotspot_y; QSpinBox *sb_hotspot_y;
NamesListWidget *element_names; NamesListWidget *element_names;
OrientationSetWidget *orientation_set;
QPushButton *button_previous; QPushButton *button_previous;
QPushButton *button_next; QPushButton *button_next;
WizardState current_state; WizardState current_state;
@ -47,6 +49,7 @@ class NewElementWizard : public QDialog {
QComboBox *east_orientation; QComboBox *east_orientation;
QComboBox *south_orientation; QComboBox *south_orientation;
QComboBox *west_orientation; QComboBox *west_orientation;
QString chosen_file;
// methodes // methodes
private: private:

164
orientationset.cpp Normal file
View File

@ -0,0 +1,164 @@
#include "orientationset.h"
OrientationSet::OrientationSet() :
north_ori(true),
east_ori(true),
south_ori(true),
west_ori(true),
default_ori(QET::North),
current_ori(QET::North)
{}
bool OrientationSet::setNorth (bool ori) {
// pour desactiver une orientation, il doit y avoir au moins une autre orientation possible
bool can_set_ori = ori ? true : east_ori || south_ori || west_ori;
if (can_set_ori) {
north_ori = ori;
// en cas de desactivation d'une orientation, il faut verifier voire corriger les orientations courante et par defaut
if (!ori) {
if (default_ori == QET::North) default_ori = next();
if (current_ori == QET::North) current_ori = next();
}
}
return(can_set_ori);
}
bool OrientationSet::setEast (bool ori) {
// pour desactiver une orientation, il doit y avoir au moins une autre orientation possible
bool can_set_ori = ori ? true : south_ori || west_ori || north_ori;
if (can_set_ori) {
east_ori = ori;
// en cas de desactivation d'une orientation, il faut verifier voire corriger les orientations courante et par defaut
if (!ori) {
if (default_ori == QET::East) default_ori = next();
if (current_ori == QET::East) current_ori = next();
}
}
return(can_set_ori);
}
bool OrientationSet::setSouth (bool ori) {
// pour desactiver une orientation, il doit y avoir au moins une autre orientation possible
bool can_set_ori = ori ? true : west_ori || north_ori || east_ori;
if (can_set_ori) {
south_ori = ori;
// en cas de desactivation d'une orientation, il faut verifier voire corriger les orientations courante et par defaut
if (!ori) {
if (default_ori == QET::South) default_ori = next();
if (current_ori == QET::South) current_ori = next();
}
}
return(can_set_ori);
}
bool OrientationSet::setWest (bool ori) {
// pour desactiver une orientation, il doit y avoir au moins une autre orientation possible
bool can_set_ori = ori ? true : north_ori || east_ori || south_ori;
if (can_set_ori) {
west_ori = ori;
// en cas de desactivation d'une orientation, il faut verifier voire corriger les orientations courante et par defaut
if (!ori) {
if (default_ori == QET::West) default_ori = next();
if (current_ori == QET::West) current_ori = next();
}
}
return(can_set_ori);
}
bool OrientationSet::setCurrent(QET::Orientation ori) {
bool can_set_ori = accept(ori);
if (can_set_ori) current_ori = ori;
return(can_set_ori);
}
QET::Orientation OrientationSet::next() const {
QET::Orientation result = current_ori;
do result = QET::nextOrientation(result); while (!accept(result));
return(result);
}
QET::Orientation OrientationSet::previous() const {
QET::Orientation result = current_ori;
do result = QET::previousOrientation(result); while (!accept(result));
return(result);
}
const OrientationSet OrientationSet::operator++(int) {
OrientationSet before(*this);
setNext();
return(before);
}
const OrientationSet OrientationSet::operator--(int) {
OrientationSet before(*this);
setPrevious();
return(before);
}
/**
Permet de savoir si une orientation donnee peut etre utilisee.
@param o L'orientation en question
@return true si l'orientation est utilisable, false sinon
*/
bool OrientationSet::accept(QET::Orientation ori) const {
bool accepted_ori = false;
switch(ori) {
case QET::North: accepted_ori = north_ori; break;
case QET::East : accepted_ori = east_ori; break;
case QET::South: accepted_ori = south_ori; break;
case QET::West : accepted_ori = west_ori; break;
}
return(accepted_ori);
}
QET::Orientation OrientationSet::setNext() {
setCurrent(next());
return(current_ori);
}
QET::Orientation OrientationSet::setPrevious() {
setCurrent(previous());
return(current_ori);
}
const OrientationSet OrientationSet::operator++() {
setNext();
return(*this);
}
const OrientationSet OrientationSet::operator--() {
setPrevious();
return(*this);
}
bool OrientationSet::fromString(const QString &str) {
QRegExp osv("^([dyn])([dyn])([dyn])([dyn])$"); // osv : Orientation String Validator
if (osv.indexIn(str) == -1) return(false);
QStringList matches = osv.capturedTexts();
// il doit y avoir exactement UN d dans les 4 lettres capturees
if (matches.count("d") != 1) return(false);
bool *ori_pointers[4] = { &north_ori, &east_ori, &south_ori, &west_ori };
QET::Orientation ori_ints[4] = { QET::North, QET::East, QET::South, QET::West };
for(int i = 0 ; i < 4 ; ++ i) {
QString current = matches.at(i + 1);
if (current == "d") {
current_ori = default_ori = ori_ints[i];
current = "y";
}
*(ori_pointers[i]) = (current == "y");
}
return(true);
}
QString OrientationSet::toString() const {
bool ori_pointers[4] = { north_ori, east_ori, south_ori, west_ori };
QET::Orientation ori_ints[4] = { QET::North, QET::East, QET::South, QET::West };
QString result("");
for(int i = 0 ; i < 4 ; ++ i) {
if (default_ori == ori_ints[i]) result += "d";
else result += (ori_pointers[i] ? "y" : "n");
}
return(result);
}

76
orientationset.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef ORIENTATION_SET_H
#define ORIENTATION_SET_H
#include "qet.h"
class OrientationSet {
// constructeurs, destructeur
public:
OrientationSet();
virtual ~OrientationSet() {};
// attributs
private:
bool north_ori;
bool east_ori;
bool south_ori;
bool west_ori;
QET::Orientation default_ori;
QET::Orientation current_ori;
// methodes
public:
bool north() const;
bool east() const;
bool south() const;
bool west() const;
bool setNorth(bool);
bool setEast(bool);
bool setSouth(bool);
bool setWest(bool);
QET::Orientation defaultOrientation() const;
void setDefaultOrientation(const QET::Orientation &);
QET::Orientation current() const;
bool setCurrent(QET::Orientation);
QET::Orientation next() const;
QET::Orientation previous() const;
QET::Orientation setNext();
QET::Orientation setPrevious();
bool accept(QET::Orientation) const;
const OrientationSet operator++(int);
const OrientationSet operator--(int);
const OrientationSet operator++();
const OrientationSet operator--();
bool fromString(const QString &);
QString toString() const;
};
inline bool OrientationSet::north() const {
return(north_ori);
}
inline bool OrientationSet::east() const {
return(east_ori);
}
inline bool OrientationSet::south() const {
return(south_ori);
}
inline bool OrientationSet::west() const {
return(west_ori);
}
inline void OrientationSet::setDefaultOrientation(const QET::Orientation& theValue) {
default_ori = theValue;
}
inline QET::Orientation OrientationSet::defaultOrientation() const {
return(default_ori);
}
inline QET::Orientation OrientationSet::current() const {
return(current_ori);
}
#endif

111
orientationsetwidget.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "orientationsetwidget.h"
OrientationSetWidget::OrientationSetWidget(QWidget *parent) : QWidget(parent) {
default_radios = new QButtonGroup(this);
#define MK_COMBO_BOX(a) a##_orientation = new QComboBox();\
a##_orientation -> addItem(QIcon(":/ico/allowed.png"), tr("Possible"), "y");\
a##_orientation -> addItem(QIcon(":/ico/forbidden.png"),tr("Impossible"), "n");\
connect(a##_orientation, SIGNAL(activated(int)), this, SLOT(updateOrientationSet()));\
a##_default = new QRadioButton();
// 4 combo box, 4 boutons radios
MK_COMBO_BOX(north)
MK_COMBO_BOX(east)
MK_COMBO_BOX(south)
MK_COMBO_BOX(west)
#undef MK_COMBO_BOX
default_radios -> addButton(north_default, QET::North);
default_radios -> addButton(east_default, QET::East);
default_radios -> addButton(south_default, QET::South);
default_radios -> addButton(west_default, QET::West);
connect(default_radios, SIGNAL(buttonClicked(QAbstractButton *)), this, SLOT(slot_defaultChanged(QAbstractButton *)));
// petites icones symbolisant les orientations
QLabel *north_pixmap = new QLabel(tr("Nord :"));
north_pixmap -> setPixmap(QPixmap(":/ico/north.png"));
QLabel *east_pixmap = new QLabel(tr("Est :"));
east_pixmap -> setPixmap(QPixmap(":/ico/east.png"));
QLabel *south_pixmap = new QLabel(tr("Sud :"));
south_pixmap -> setPixmap(QPixmap(":/ico/south.png"));
QLabel *west_pixmap = new QLabel(tr("Ouest :"));
west_pixmap -> setPixmap(QPixmap(":/ico/west.png"));
QGridLayout *qgl = new QGridLayout(this);
qgl -> addWidget(new QLabel(tr("Par d\351faut")), 0, 3);
qgl -> addWidget(north_pixmap, 1, 0);
qgl -> addWidget(new QLabel(tr("Nord :")), 1, 1);
qgl -> addWidget(north_orientation, 1, 2);
qgl -> addWidget(north_default, 1, 3, Qt::AlignHCenter);
qgl -> addWidget(east_pixmap, 2, 0);
qgl -> addWidget(new QLabel(tr("Est :")), 2, 1);
qgl -> addWidget(east_orientation, 2, 2);
qgl -> addWidget(east_default, 2, 3, Qt::AlignHCenter);
qgl -> addWidget(south_pixmap, 3, 0);
qgl -> addWidget(new QLabel(tr("Sud :")), 3, 1);
qgl -> addWidget(south_orientation, 3, 2);
qgl -> addWidget(south_default, 3, 3, Qt::AlignHCenter);
qgl -> addWidget(west_pixmap, 4, 0);
qgl -> addWidget(new QLabel(tr("Ouest :")), 4, 1);
qgl -> addWidget(west_orientation, 4, 2);
qgl -> addWidget(west_default, 4, 3, Qt::AlignHCenter);
// les combobox s'etendent autant que possible
qgl -> setColumnStretch(2, 1);
// l'orientation par defaut par defaut est le Nord
north_default -> setChecked(true);
slot_defaultChanged(north_default);
}
OrientationSet OrientationSetWidget::orientationSet() const {
return(ori);
}
void OrientationSetWidget::setOrientationSet(const OrientationSet &os) {
ori = os;
updateForm();
}
void OrientationSetWidget::slot_defaultChanged(QAbstractButton *button) {
if (button == north_default) north_orientation -> setCurrentIndex(0);
else if (button == east_default) east_orientation -> setCurrentIndex(0);
else if (button == south_default) south_orientation -> setCurrentIndex(0);
else if (button == west_default) west_orientation -> setCurrentIndex(0);
north_orientation -> setEnabled(button != north_default);
east_orientation -> setEnabled(button != east_default);
south_orientation -> setEnabled(button != south_default);
west_orientation -> setEnabled(button != west_default);
updateOrientationSet();
}
void OrientationSetWidget::updateOrientationSet() {
ori.setNorth(!north_orientation -> currentIndex());
ori.setEast (!east_orientation -> currentIndex());
ori.setSouth(!south_orientation -> currentIndex());
ori.setWest (!west_orientation -> currentIndex());
ori.setDefaultOrientation(static_cast<QET::Orientation>(default_radios -> checkedId()));
}
void OrientationSetWidget::updateForm() {
north_orientation -> setCurrentIndex(ori.north() ? 0 : 1);
east_orientation -> setCurrentIndex(ori.east() ? 0 : 1);
south_orientation -> setCurrentIndex(ori.south() ? 0 : 1);
west_orientation -> setCurrentIndex(ori.west() ? 0 : 1);
QRadioButton *default_button = NULL;
switch(ori.defaultOrientation()) {
case QET::North: default_button = north_default; break;
case QET::East : default_button = east_default ; break;
case QET::South: default_button = south_default; break;
case QET::West : default_button = west_default ; break;
}
if (default_button != NULL) {
default_button -> setChecked(true);
slot_defaultChanged(default_button);
}
}

40
orientationsetwidget.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef ORIENTATION_SET_WIDGET_H
#define ORIENTATION_SET_WIDGET_H
#include <QtGui>
#include "orientationset.h"
class OrientationSetWidget : public QWidget {
Q_OBJECT
// constructeurs, destructeur
public:
OrientationSetWidget(QWidget * = 0);
virtual ~OrientationSetWidget() {};
private:
OrientationSetWidget(const OrientationSetWidget &);
// attributs
private:
OrientationSet ori;
QComboBox *north_orientation;
QComboBox *east_orientation;
QComboBox *south_orientation;
QComboBox *west_orientation;
QRadioButton *north_default;
QRadioButton *east_default;
QRadioButton *south_default;
QRadioButton *west_default;
QButtonGroup *default_radios;
// methodes
public:
OrientationSet orientationSet() const;
void setOrientationSet(const OrientationSet &);
private:
void updateForm();
public slots:
void slot_defaultChanged(QAbstractButton *);
void updateOrientationSet();
};
#endif

View File

@ -1,11 +1,11 @@
###################################################################### ######################################################################
# Automatically generated by qmake (2.01a) ven. avr. 6 18:45:47 2007 # Automatically generated by qmake (2.01a) dim. avr. 29 22:04:08 2007
###################################################################### ######################################################################
TEMPLATE = app TEMPLATE = app
TARGET = TARGET =
DEPENDPATH += . lang DEPENDPATH += . editor lang
INCLUDEPATH += . INCLUDEPATH += . editor
# Input # Input
HEADERS += aboutqet.h \ HEADERS += aboutqet.h \
@ -28,8 +28,28 @@ HEADERS += aboutqet.h \
nameslist.h \ nameslist.h \
nameslistwidget.h \ nameslistwidget.h \
newelementwizard.h \ newelementwizard.h \
qet.h \
qetapp.h \ qetapp.h \
terminal.h terminal.h \
editor/customelementeditor.h \
editor/customelementgraphicpart.h \
editor/customelementpart.h \
editor/editorscene.h \
editor/ellipseeditor.h \
editor/lineeditor.h \
editor/partellipse.h \
editor/partline.h \
editor/styleeditor.h \
editor/partcircle.h \
editor/circleeditor.h \
orientationset.h \
orientationsetwidget.h \
editor/partpolygon.h \
editor/polygoneditor.h \
editor/partterminal.h \
editor/terminaleditor.h \
editor/parttext.h \
editor/texteditor.h
SOURCES += aboutqet.cpp \ SOURCES += aboutqet.cpp \
borderinset.cpp \ borderinset.cpp \
conducer.cpp \ conducer.cpp \
@ -52,9 +72,27 @@ SOURCES += aboutqet.cpp \
nameslistwidget.cpp \ nameslistwidget.cpp \
newelementwizard.cpp \ newelementwizard.cpp \
qetapp.cpp \ qetapp.cpp \
terminal.cpp terminal.cpp \
editor/customelementeditor.cpp \
editor/customelementgraphicpart.cpp \
editor/customelementpart.cpp \
editor/editorscene.cpp \
editor/ellipseeditor.cpp \
editor/lineeditor.cpp \
editor/partellipse.cpp \
editor/partline.cpp \
editor/styleeditor.cpp \
editor/qet.cpp \
editor/partcircle.cpp \
editor/circleeditor.cpp \
orientationset.cpp \
orientationsetwidget.cpp \
editor/partpolygon.cpp \
editor/polygoneditor.cpp \
editor/partterminal.cpp \
editor/terminaleditor.cpp \
editor/parttext.cpp \
editor/texteditor.cpp
RESOURCES += qelectrotech.qrc RESOURCES += qelectrotech.qrc
TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts
CONFIG += debug warn_on
QT += xml QT += xml

View File

@ -2,39 +2,56 @@
<qresource> <qresource>
<file>ico/qet.png</file> <file>ico/qet.png</file>
<file>ico/qelectrotech.png</file> <file>ico/qelectrotech.png</file>
<file>ico/allowed.png</file>
<file>ico/add_col.png</file>
<file>ico/arc.png</file>
<file>ico/button_cancel.png</file> <file>ico/button_cancel.png</file>
<file>ico/button_ok.png</file> <file>ico/button_ok.png</file>
<file>ico/circle.png</file>
<file>ico/configure.png</file> <file>ico/configure.png</file>
<file>ico/copy.png</file> <file>ico/copy.png</file>
<file>ico/cut.png</file> <file>ico/cut.png</file>
<file>ico/delete.png</file> <file>ico/delete.png</file>
<file>ico/east.png</file>
<file>ico/editdelete.png</file> <file>ico/editdelete.png</file>
<file>ico/ellipse.png</file>
<file>ico/entrer_fs.png</file> <file>ico/entrer_fs.png</file>
<file>ico/exit.png</file> <file>ico/exit.png</file>
<file>ico/export.png</file> <file>ico/export.png</file>
<file>ico/fileclose.png</file> <file>ico/fileclose.png</file>
<file>ico/forbidden.png</file>
<file>ico/import.png</file> <file>ico/import.png</file>
<file>ico/info.png</file> <file>ico/info.png</file>
<file>ico/line.png</file>
<file>ico/masquer.png</file> <file>ico/masquer.png</file>
<file>ico/move.png</file> <file>ico/move.png</file>
<file>ico/new.png</file> <file>ico/new.png</file>
<file>ico/north.png</file>
<file>ico/open.png</file> <file>ico/open.png</file>
<file>ico/orientations.png</file>
<file>ico/paste.png</file> <file>ico/paste.png</file>
<file>ico/pivoter.png</file> <file>ico/pivoter.png</file>
<file>ico/polygon.png</file>
<file>ico/print.png</file> <file>ico/print.png</file>
<file>ico/qt.png</file> <file>ico/qt.png</file>
<file>ico/redo.png</file> <file>ico/redo.png</file>
<file>ico/reload.png</file> <file>ico/reload.png</file>
<file>ico/remove_col.png</file>
<file>ico/restaurer.png</file> <file>ico/restaurer.png</file>
<file>ico/saveas.png</file> <file>ico/saveas.png</file>
<file>ico/save.png</file> <file>ico/save.png</file>
<file>ico/select.png</file> <file>ico/select.png</file>
<file>ico/sortir_fs.png</file> <file>ico/sortir_fs.png</file>
<file>ico/south.png</file>
<file>ico/terminal.png</file>
<file>ico/text.png</file>
<file>ico/textfield.png</file>
<file>ico/toolbars.png</file> <file>ico/toolbars.png</file>
<file>ico/undo.png</file> <file>ico/undo.png</file>
<file>ico/viewmagfit.png</file> <file>ico/viewmagfit.png</file>
<file>ico/viewmag-.png</file> <file>ico/viewmag-.png</file>
<file>ico/viewmag.png</file> <file>ico/viewmag.png</file>
<file>ico/viewmag+.png</file> <file>ico/viewmag+.png</file>
<file>ico/west.png</file>
</qresource> </qresource>
</RCC> </RCC>

21
qet.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _QET_H
#define _QET_H
#include <QtXml>
/**
Ce fichier contient des fonctions utiles pouvant etre appelees depuis
n'importe ou. Il contient egalement des enums utilises dans plusieurs
classes de l'application
*/
namespace QET {
enum Orientation {North, East, South, West};
QET::Orientation nextOrientation(QET::Orientation);
QET::Orientation previousOrientation(QET::Orientation);
QET::Orientation orientationFromString(const QString &);
QString orientationToString(QET::Orientation);
bool surLeMemeAxe(QET::Orientation, QET::Orientation);
bool estHorizontale(QET::Orientation);
bool estVerticale(QET::Orientation);
bool attributeIsAnInteger(const QDomElement &, QString , int * = NULL);
bool attributeIsAReal(const QDomElement &, QString , double * = NULL);
}
#endif

View File

@ -221,8 +221,8 @@ void QETApp::actions() {
supprimer = new QAction(QIcon(":/ico/delete.png"), tr("Supprimer"), this); supprimer = new QAction(QIcon(":/ico/delete.png"), tr("Supprimer"), this);
pivoter = new QAction(QIcon(":/ico/pivoter.png"), tr("Pivoter"), this); pivoter = new QAction(QIcon(":/ico/pivoter.png"), tr("Pivoter"), this);
infos_diagram = new QAction(QIcon(":/ico/info.png"), tr("Informations sur le sch\351ma"), this); infos_diagram = new QAction(QIcon(":/ico/info.png"), tr("Informations sur le sch\351ma"), this);
add_column = new QAction( tr("Ajouter une colonne"), this); add_column = new QAction(QIcon(":/ico/add_col.png"), tr("Ajouter une colonne"), this);
remove_column = new QAction( tr("Enlever une colonne"), this); remove_column = new QAction(QIcon(":/ico/remove_col.png"), tr("Enlever une colonne"), this);
expand_diagram = new QAction( tr("Agrandir le sch\351ma"), this); expand_diagram = new QAction( tr("Agrandir le sch\351ma"), this);
shrink_diagram = new QAction( tr("R\351tr\351cir le sch\351ma"), this); shrink_diagram = new QAction( tr("R\351tr\351cir le sch\351ma"), this);

View File

@ -3,27 +3,32 @@
#include "element.h" #include "element.h"
#include "conducer.h" #include "conducer.h"
QColor Terminal::couleur_neutre = QColor(Qt::blue);
QColor Terminal::couleur_autorise = QColor(Qt::darkGreen);
QColor Terminal::couleur_prudence = QColor("#ff8000");
QColor Terminal::couleur_interdit = QColor(Qt::red);
/** /**
Fonction privee pour initialiser la borne. Fonction privee pour initialiser la borne.
@param pf position du point d'amarrage pour un conducteur @param pf position du point d'amarrage pour un conducteur
@param o orientation de la borne : Qt::Horizontal ou Qt::Vertical @param o orientation de la borne : Qt::Horizontal ou Qt::Vertical
*/ */
void Terminal::initialise(QPointF pf, Terminal::Orientation o) { void Terminal::initialise(QPointF pf, QET::Orientation o) {
// definition du pount d'amarrage pour un conducteur // definition du pount d'amarrage pour un conducteur
amarrage_conducer = pf; amarrage_conducer = pf;
// definition de l'orientation de la terminal (par defaut : sud) // definition de l'orientation de la terminal (par defaut : sud)
if (o < Terminal::Nord || o > Terminal::Ouest) sens = Terminal::Sud; if (o < QET::North || o > QET::West) sens = QET::South;
else sens = o; else sens = o;
// calcul de la position du point d'amarrage a l'element // calcul de la position du point d'amarrage a l'element
amarrage_elmt = amarrage_conducer; amarrage_elmt = amarrage_conducer;
switch(sens) { switch(sens) {
case Terminal::Nord : amarrage_elmt += QPointF(0, TAILLE_BORNE); break; case QET::North: amarrage_elmt += QPointF(0, TAILLE_BORNE); break;
case Terminal::Est : amarrage_elmt += QPointF(-TAILLE_BORNE, 0); break; case QET::East : amarrage_elmt += QPointF(-TAILLE_BORNE, 0); break;
case Terminal::Ouest : amarrage_elmt += QPointF(TAILLE_BORNE, 0); break; case QET::West : amarrage_elmt += QPointF(TAILLE_BORNE, 0); break;
case Terminal::Sud : case QET::South:
default : amarrage_elmt += QPointF(0, -TAILLE_BORNE); default : amarrage_elmt += QPointF(0, -TAILLE_BORNE);
} }
// par defaut : pas de conducteur // par defaut : pas de conducteur
@ -36,18 +41,16 @@ void Terminal::initialise(QPointF pf, Terminal::Orientation o) {
setAcceptedMouseButtons(Qt::LeftButton); setAcceptedMouseButtons(Qt::LeftButton);
hovered = false; hovered = false;
setToolTip("Terminal"); setToolTip("Terminal");
couleur_neutre = QColor(Qt::blue);
couleur_autorise = QColor(Qt::darkGreen);
couleur_prudence = QColor("#ff8000");
couleur_interdit = QColor(Qt::red);
couleur_hovered = couleur_neutre;
} }
/** /**
Constructeur par defaut Constructeur par defaut
*/ */
Terminal::Terminal() : QGraphicsItem(0, 0) { Terminal::Terminal() :
initialise(QPointF(0.0, 0.0), Terminal::Sud); QGraphicsItem(0, 0),
couleur_hovered(Terminal::couleur_neutre)
{
initialise(QPointF(0.0, 0.0), QET::South);
diagram_scene = 0; diagram_scene = 0;
} }
@ -58,7 +61,10 @@ Terminal::Terminal() : QGraphicsItem(0, 0) {
@param e Element auquel cette borne appartient @param e Element auquel cette borne appartient
@param s Scene sur laquelle figure cette borne @param s Scene sur laquelle figure cette borne
*/ */
Terminal::Terminal(QPointF pf, Terminal::Orientation o, Element *e, Diagram *s) : QGraphicsItem(e, s) { Terminal::Terminal(QPointF pf, QET::Orientation o, Element *e, Diagram *s) :
QGraphicsItem(e, s),
couleur_hovered(Terminal::couleur_neutre)
{
initialise(pf, o); initialise(pf, o);
diagram_scene = s; diagram_scene = s;
} }
@ -71,7 +77,10 @@ Terminal::Terminal(QPointF pf, Terminal::Orientation o, Element *e, Diagram *s)
@param e Element auquel cette borne appartient @param e Element auquel cette borne appartient
@param s Scene sur laquelle figure cette borne @param s Scene sur laquelle figure cette borne
*/ */
Terminal::Terminal(qreal pf_x, qreal pf_y, Terminal::Orientation o, Element *e, Diagram *s) : QGraphicsItem(e, s) { Terminal::Terminal(qreal pf_x, qreal pf_y, QET::Orientation o, Element *e, Diagram *s) :
QGraphicsItem(e, s),
couleur_hovered(Terminal::couleur_neutre)
{
initialise(QPointF(pf_x, pf_y), o); initialise(QPointF(pf_x, pf_y), o);
} }
@ -93,19 +102,18 @@ Terminal::~Terminal() {
pivote. Sinon elle renvoie son sens normal. pivote. Sinon elle renvoie son sens normal.
@return L'orientation actuelle de la Terminal. @return L'orientation actuelle de la Terminal.
*/ */
Terminal::Orientation Terminal::orientation() const { QET::Orientation Terminal::orientation() const {
//true pour une orientation verticale, false pour une orientation horizontale
if (Element *elt = qgraphicsitem_cast<Element *>(parentItem())) { if (Element *elt = qgraphicsitem_cast<Element *>(parentItem())) {
// orientations actuelle et par defaut de l'element // orientations actuelle et par defaut de l'element
Terminal::Orientation ori_cur = elt -> orientation(); QET::Orientation ori_cur = elt -> orientation().current();
Terminal::Orientation ori_def = elt -> defaultOrientation(); QET::Orientation ori_def = elt -> orientation().defaultOrientation();
if (ori_cur == ori_def) return(sens); if (ori_cur == ori_def) return(sens);
else { else {
// calcul l'angle de rotation implique par l'orientation de l'element parent // calcul l'angle de rotation implique par l'orientation de l'element parent
// angle de rotation de la borne sur la scene, divise par 90 // angle de rotation de la borne sur la scene, divise par 90
int angle = ori_cur - ori_def + sens; int angle = ori_cur - ori_def + sens;
while (angle >= 4) angle -= 4; while (angle >= 4) angle -= 4;
return((Terminal::Orientation)angle); return((QET::Orientation)angle);
} }
} else return(sens); } else return(sens);
} }
@ -410,7 +418,7 @@ bool Terminal::valideXml(QDomElement &terminal) {
// parse l'orientation // parse l'orientation
int terminal_or = terminal.attribute("orientation").toInt(&conv_ok); int terminal_or = terminal.attribute("orientation").toInt(&conv_ok);
if (!conv_ok) return(false); if (!conv_ok) return(false);
if (terminal_or != Terminal::Nord && terminal_or != Terminal::Sud && terminal_or != Terminal::Est && terminal_or != Terminal::Ouest) return(false); if (terminal_or != QET::North && terminal_or != QET::South && terminal_or != QET::East && terminal_or != QET::West) return(false);
// a ce stade, la borne est syntaxiquement correcte // a ce stade, la borne est syntaxiquement correcte
return(true); return(true);

View File

@ -3,6 +3,7 @@
#define TAILLE_BORNE 4 #define TAILLE_BORNE 4
#include <QtGui> #include <QtGui>
#include <QtXml> #include <QtXml>
#include "qet.h"
class Conducer; class Conducer;
class Diagram; class Diagram;
class Element; class Element;
@ -14,10 +15,9 @@ class Terminal : public QGraphicsItem {
// constructeurs, destructeur // constructeurs, destructeur
public: public:
enum Orientation {Nord, Est, Sud, Ouest};
Terminal(); Terminal();
Terminal(QPointF, Terminal::Orientation, Element * = 0, Diagram * = 0); Terminal(QPointF, QET::Orientation, Element * = 0, Diagram * = 0);
Terminal(qreal, qreal, Terminal::Orientation, Element * = 0, Diagram * = 0); Terminal(qreal, qreal, QET::Orientation, Element * = 0, Diagram * = 0);
virtual ~Terminal(); virtual ~Terminal();
private: private:
@ -39,7 +39,7 @@ class Terminal : public QGraphicsItem {
// methodes de lecture // methodes de lecture
QList<Conducer *> conducers() const; QList<Conducer *> conducers() const;
Terminal::Orientation orientation() const; QET::Orientation orientation() const;
QPointF amarrageConducer() const; QPointF amarrageConducer() const;
void updateConducer(QPointF = QPointF()); void updateConducer(QPointF = QPointF());
@ -61,6 +61,12 @@ class Terminal : public QGraphicsItem {
public: public:
enum { Type = UserType + 1002 }; enum { Type = UserType + 1002 };
// differentes couleurs statiques utilisables pour l'effet "hover"
static QColor couleur_neutre;
static QColor couleur_autorise;
static QColor couleur_prudence;
static QColor couleur_interdit;
private: private:
// pointeur vers la QGraphicsScene de type Diagram (evite quelques casts en interne) // pointeur vers la QGraphicsScene de type Diagram (evite quelques casts en interne)
Diagram *diagram_scene; Diagram *diagram_scene;
@ -68,7 +74,7 @@ class Terminal : public QGraphicsItem {
QPointF amarrage_conducer; QPointF amarrage_conducer;
QPointF amarrage_elmt; QPointF amarrage_elmt;
// orientation de la borne // orientation de la borne
Terminal::Orientation sens; QET::Orientation sens;
// liste des conducers lies a cette borne // liste des conducers lies a cette borne
QList<Conducer *> liste_conducers; QList<Conducer *> liste_conducers;
// pointeur vers un rectangle correspondant au bounding rect ; permet de ne calculer le bounding rect qu'une seule fois ; le pointeur c'est parce que le compilo exige une methode const // pointeur vers un rectangle correspondant au bounding rect ; permet de ne calculer le bounding rect qu'une seule fois ; le pointeur c'est parce que le compilo exige une methode const
@ -76,13 +82,9 @@ class Terminal : public QGraphicsItem {
Terminal *terminal_precedente; Terminal *terminal_precedente;
bool hovered; bool hovered;
// methode initialisant les differents membres de la borne // methode initialisant les differents membres de la borne
void initialise(QPointF, Terminal::Orientation); void initialise(QPointF, QET::Orientation);
// differentes couleurs utilisables pour l'effet "hover" // couleur de l'effet hover de la patte
QColor couleur_hovered; QColor couleur_hovered;
QColor couleur_neutre;
QColor couleur_autorise;
QColor couleur_prudence;
QColor couleur_interdit;
}; };
/** /**