Import initial
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@1 bfdf4180-ca20-0410-9c96-a3a8aa849046
122
aboutqet.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "aboutqet.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent de la boite de dialogue
|
||||
*/
|
||||
AboutQET::AboutQET(QWidget *parent) : QDialog(parent) {
|
||||
// Titre, taille, comportement...
|
||||
setWindowTitle(tr("\300 propos de QElectrotech"));
|
||||
setMinimumWidth(680);
|
||||
setMinimumHeight(350);
|
||||
setModal(true);
|
||||
|
||||
// Trois onglets
|
||||
QTabWidget *onglets = new QTabWidget(this);
|
||||
onglets -> addTab(ongletAPropos(), tr("\300 &propos"));
|
||||
onglets -> addTab(ongletAuteurs(), tr("A&uteurs"));
|
||||
onglets -> addTab(ongletLicence(), tr("&Accord de licence"));
|
||||
|
||||
// Un bouton pour fermer la boite de dialogue
|
||||
QDialogButtonBox *boutons = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
connect(boutons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(boutons, SIGNAL(rejected()), this, SLOT(accept()));
|
||||
|
||||
// Le tout dans une disposition verticale
|
||||
QVBoxLayout *disposition = new QVBoxLayout();
|
||||
disposition -> addWidget(titre());
|
||||
disposition -> addWidget(onglets);
|
||||
disposition -> addWidget(boutons);
|
||||
setLayout(disposition);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le titre QElectroTech avec son icone
|
||||
*/
|
||||
QWidget *AboutQET::titre() {
|
||||
QWidget *icone_et_titre = new QWidget();
|
||||
// icone
|
||||
QLabel *icone = new QLabel();
|
||||
icone -> setPixmap(QIcon(":/ico/qelectrotech.png").pixmap(48, 48));
|
||||
// label "QElectroTech"
|
||||
QLabel *titre = new QLabel("<span style=\"font-weight:0;font-size:16pt;\">QElectroTech</span>");
|
||||
titre -> setTextFormat(Qt::RichText);
|
||||
// le tout dans une grille
|
||||
QGridLayout *dispo_horiz = new QGridLayout();
|
||||
dispo_horiz -> addWidget(icone, 0, 0);
|
||||
dispo_horiz -> addWidget(titre, 0, 1);
|
||||
dispo_horiz -> setColumnStretch(0, 1);
|
||||
dispo_horiz -> setColumnStretch(1, 100);
|
||||
icone_et_titre -> setLayout(dispo_horiz);
|
||||
return(icone_et_titre);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget contenu par l'onglet « A propos »
|
||||
*/
|
||||
QWidget *AboutQET::ongletAPropos() {
|
||||
QLabel *apropos = new QLabel(
|
||||
tr(
|
||||
"QElectroTech, une application de "
|
||||
"r\351alisation de sch\351mas \351lectriques.\n\n\251 2006 Les "
|
||||
"d\351veloppeurs de QElectroTech\n\nMerde on n'a pas de site web"
|
||||
)
|
||||
);
|
||||
apropos -> setAlignment(Qt::AlignCenter);
|
||||
return(apropos);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget contenu par l'onglet « Auteurs »
|
||||
*/
|
||||
QWidget *AboutQET::ongletAuteurs() {
|
||||
QLabel *auteurs = new QLabel(
|
||||
tr(
|
||||
"Id\351e originale : Beno\356t Ansieau <benoit.ansieau@gmail.com>\n\n"
|
||||
"Programmation : Xavier Guerrin <xavier.guerrin@gmail.com>"
|
||||
)
|
||||
);
|
||||
auteurs -> setAlignment(Qt::AlignCenter);
|
||||
return(auteurs);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget contenu par l'onglet « Accord de Licence »
|
||||
*/
|
||||
QWidget *AboutQET::ongletLicence() {
|
||||
QWidget *licence = new QWidget();
|
||||
// label
|
||||
QLabel *titre_licence = new QLabel(tr("Ce programme est sous licence GNU/GPL."));
|
||||
|
||||
// Recuperation du texte de la GNU/GPL dans un fichier externe
|
||||
QFile *fichier_gpl = new QFile("./gnugpl.txt");
|
||||
QString txt_gpl;
|
||||
// verifie que le fichier existe
|
||||
if (!fichier_gpl -> exists()) {
|
||||
txt_gpl = QString(tr("Le fichier texte contenant la licence GNU/GPL est introuvable - bon bah de toute fa\347on, vous la connaissez par coeur non ?"));
|
||||
} else {
|
||||
// ouvre le fichier en mode texte et en lecture seule
|
||||
if (!fichier_gpl -> open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
txt_gpl = QString(tr("Le fichier texte contenant la licence GNU/GPL existe mais n'a pas pu \352tre ouvert - bon bah de toute fa\347on, vous la connaissez par coeur non ?"));
|
||||
} else {
|
||||
// charge le contenu du fichier dans une QString
|
||||
QTextStream in(fichier_gpl);
|
||||
txt_gpl = QString("");
|
||||
while (!in.atEnd()) txt_gpl += in.readLine()+"\n";
|
||||
// ferme le fichier
|
||||
fichier_gpl -> close();
|
||||
}
|
||||
}
|
||||
|
||||
// texte de la GNU/GPL dans une zone de texte scrollable non editable
|
||||
QTextEdit *texte_licence = new QTextEdit();
|
||||
texte_licence -> setPlainText(txt_gpl);
|
||||
texte_licence -> setReadOnly(true);
|
||||
|
||||
// le tout dans une disposition verticale
|
||||
QVBoxLayout *dispo_licence = new QVBoxLayout();
|
||||
dispo_licence -> addWidget(titre_licence);
|
||||
dispo_licence -> addWidget(texte_licence);
|
||||
licence -> setLayout(dispo_licence);
|
||||
return(licence);
|
||||
}
|
||||
18
aboutqet.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef ABOUTQET_H
|
||||
#define ABOUTQET_H
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette classe represente la boite de dialogue
|
||||
« A propos de QElectroTech »
|
||||
*/
|
||||
class AboutQET : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AboutQET(QWidget * = 0);
|
||||
private:
|
||||
QWidget *titre();
|
||||
QWidget *ongletAPropos();
|
||||
QWidget *ongletAuteurs();
|
||||
QWidget *ongletLicence();
|
||||
};
|
||||
#endif
|
||||
412
borne.cpp
Normal file
@@ -0,0 +1,412 @@
|
||||
#include "borne.h"
|
||||
#include "schema.h"
|
||||
#include "element.h"
|
||||
#include "conducteur.h"
|
||||
|
||||
/**
|
||||
Fonction privee pour initialiser la borne.
|
||||
@param pf position du point d'amarrage pour un conducteur
|
||||
@param o orientation de la borne : Qt::Horizontal ou Qt::Vertical
|
||||
*/
|
||||
void Borne::initialise(QPointF pf, Borne::Orientation o) {
|
||||
// definition du pount d'amarrage pour un conducteur
|
||||
amarrage_conducteur = pf;
|
||||
|
||||
// definition de l'orientation de la borne (par defaut : sud)
|
||||
if (o < Borne::Nord || o > Borne::Ouest) sens = Borne::Sud;
|
||||
else sens = o;
|
||||
|
||||
// calcul de la position du point d'amarrage a l'element
|
||||
amarrage_elmt = amarrage_conducteur;
|
||||
switch(sens) {
|
||||
case Borne::Nord : amarrage_elmt += QPointF(0, TAILLE_BORNE); break;
|
||||
case Borne::Est : amarrage_elmt += QPointF(-TAILLE_BORNE, 0); break;
|
||||
case Borne::Ouest : amarrage_elmt += QPointF(TAILLE_BORNE, 0); break;
|
||||
case Borne::Sud :
|
||||
default : amarrage_elmt += QPointF(0, -TAILLE_BORNE);
|
||||
}
|
||||
|
||||
// par defaut : pas de conducteur
|
||||
|
||||
// QRectF null
|
||||
br = new QRectF();
|
||||
borne_precedente = NULL;
|
||||
// divers
|
||||
setAcceptsHoverEvents(true);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
hovered = false;
|
||||
setToolTip("Borne");
|
||||
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
|
||||
*/
|
||||
Borne::Borne() : QGraphicsItem(0, 0) {
|
||||
initialise(QPointF(0.0, 0.0), Borne::Sud);
|
||||
schema_scene = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
initialise une borne
|
||||
@param pf position du point d'amarrage pour un conducteur
|
||||
@param o orientation de la borne : Qt::Horizontal ou Qt::Vertical
|
||||
@param e Element auquel cette borne appartient
|
||||
@param s Scene sur laquelle figure cette borne
|
||||
*/
|
||||
Borne::Borne(QPointF pf, Borne::Orientation o, Element *e, Schema *s) : QGraphicsItem(e, s) {
|
||||
initialise(pf, o);
|
||||
schema_scene = s;
|
||||
}
|
||||
|
||||
/**
|
||||
initialise une borne
|
||||
@param pf_x Abscisse du point d'amarrage pour un conducteur
|
||||
@param pf_y Ordonnee du point d'amarrage pour un conducteur
|
||||
@param o orientation de la borne : Qt::Horizontal ou Qt::Vertical
|
||||
@param e Element auquel cette borne appartient
|
||||
@param s Scene sur laquelle figure cette borne
|
||||
*/
|
||||
Borne::Borne(qreal pf_x, qreal pf_y, Borne::Orientation o, Element *e, Schema *s) : QGraphicsItem(e, s) {
|
||||
initialise(QPointF(pf_x, pf_y), o);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
Borne::~Borne() {
|
||||
delete br;
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de connaitre l'orientation de la borne. Si le parent de la borne
|
||||
est bien un Element, cette fonction renvoie l'orientation par rapport a
|
||||
la scene de la borne, en tenant compte du fait que l'element ait pu etre
|
||||
pivote. Sinon elle renvoie son sens normal.
|
||||
@return L'orientation actuelle de la Borne.
|
||||
*/
|
||||
Borne::Orientation Borne::orientation() const {
|
||||
//true pour une orientation verticale, false pour une orientation horizontale
|
||||
if (Element *elt = qgraphicsitem_cast<Element *>(parentItem())) {
|
||||
if (elt -> orientation()) return(sens);
|
||||
else {
|
||||
Borne::Orientation retour;
|
||||
switch(sens) {
|
||||
case Borne::Nord : retour = Borne::Ouest; break;
|
||||
case Borne::Est : retour = Borne::Nord; break;
|
||||
case Borne::Ouest : retour = Borne::Sud; break;
|
||||
case Borne::Sud :
|
||||
default : retour = Borne::Est;
|
||||
}
|
||||
return(retour);
|
||||
}
|
||||
} else return(sens);
|
||||
}
|
||||
|
||||
/**
|
||||
Attribue un conducteur a la borne
|
||||
@param f Le conducteur a rattacher a cette borne
|
||||
*/
|
||||
bool Borne::addConducteur(Conducteur *f) {
|
||||
// pointeur 0 refuse
|
||||
if (!f) return(false);
|
||||
|
||||
// une seule des deux bornes du conducteur doit etre this
|
||||
Q_ASSERT_X((f -> borne1 == this ^ f -> borne2 == this), "Borne::addConducteur", "Le conducteur devrait etre relie exactement une fois a la borne en cours");
|
||||
|
||||
// determine l'autre borne a laquelle cette borne va etre relie grace au conducteur
|
||||
Borne *autre_borne = (f -> borne1 == this) ? f -> borne2 : f -> borne1;
|
||||
|
||||
// verifie que la borne n'est pas deja reliee avec l'autre borne
|
||||
bool deja_liees = false;
|
||||
foreach (Conducteur* conducteur, liste_conducteurs) {
|
||||
if (conducteur -> borne1 == autre_borne || conducteur -> borne2 == autre_borne) deja_liees = true;
|
||||
}
|
||||
|
||||
// si les deux bornes sont deja reliees, on refuse d'ajouter le conducteur
|
||||
if (deja_liees) return(false);
|
||||
|
||||
// sinon on ajoute le conducteur
|
||||
liste_conducteurs.append(f);
|
||||
return(true);
|
||||
}
|
||||
|
||||
void Borne::removeConducteur(Conducteur *f) {
|
||||
int index = liste_conducteurs.indexOf(f);
|
||||
if (index == -1) return;
|
||||
liste_conducteurs.removeAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
Fonction de dessin des bornes
|
||||
@param p Le QPainter a utiliser
|
||||
@param options Les options de dessin
|
||||
@param widget Le widget sur lequel on dessine
|
||||
*/
|
||||
void Borne::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);
|
||||
|
||||
// on travaille avec les coordonnees de l'element parent
|
||||
QPointF f = mapFromParent(amarrage_conducteur);
|
||||
QPointF e = mapFromParent(amarrage_elmt);
|
||||
|
||||
QPen t;
|
||||
t.setWidthF(1.0);
|
||||
|
||||
// dessin de la borne en rouge
|
||||
t.setColor(Qt::red);
|
||||
p -> setPen(t);
|
||||
p -> drawLine(f, e);
|
||||
|
||||
// dessin du point d'amarrage au conducteur en bleu
|
||||
t.setColor(couleur_hovered);
|
||||
p -> setPen(t);
|
||||
p -> setBrush(couleur_hovered);
|
||||
if (hovered) p -> drawEllipse(((int)f.x())-2, ((int)f.y())-2, 5, 5);
|
||||
else p -> drawPoint(f);
|
||||
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le rectangle (en precision flottante) delimitant la borne et ses alentours.
|
||||
*/
|
||||
QRectF Borne::boundingRect() const {
|
||||
if (br -> isNull()) {
|
||||
qreal afx = amarrage_conducteur.x();
|
||||
qreal afy = amarrage_conducteur.y();
|
||||
qreal aex = amarrage_elmt.x();
|
||||
qreal aey = amarrage_elmt.y();
|
||||
QPointF origine;
|
||||
origine = (afx <= aex && afy <= aey ? amarrage_conducteur : amarrage_elmt);
|
||||
origine += QPointF(-3.0, -3.0);
|
||||
qreal w = qAbs((int)(afx - aex)) + 7;
|
||||
qreal h = qAbs((int)(afy - aey)) + 7;
|
||||
*br = QRectF(origine, QSizeF(w, h));
|
||||
}
|
||||
return(*br);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere l'entree de la souris sur la zone de la Borne.
|
||||
*/
|
||||
void Borne::hoverEnterEvent(QGraphicsSceneHoverEvent *) {
|
||||
hovered = true;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements de la souris sur la zone de la Borne.
|
||||
*/
|
||||
void Borne::hoverMoveEvent(QGraphicsSceneHoverEvent *) {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait que la souris sorte de la zone de la Borne.
|
||||
*/
|
||||
void Borne::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
hovered = false;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait qu'on enfonce un bouton de la souris sur la Borne.
|
||||
@param e L'evenement souris correspondant
|
||||
*/
|
||||
void Borne::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (Schema *s = qobject_cast<Schema *>(scene())) {
|
||||
s -> setDepart(mapToScene(QPointF(amarrage_conducteur)));
|
||||
s -> setArrivee(e -> scenePos());
|
||||
s -> poseConducteur(true);
|
||||
setCursor(Qt::CrossCursor);
|
||||
}
|
||||
//QGraphicsItem::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait qu'on bouge la souris sur la Borne.
|
||||
@param e L'evenement souris correspondant
|
||||
*/
|
||||
void Borne::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
// pendant la pose d'un conducteur, on adopte un autre curseur
|
||||
setCursor(Qt::CrossCursor);
|
||||
|
||||
// d'un mouvement a l'autre, il faut retirer l'effet hover de la borne precedente
|
||||
if (borne_precedente != NULL) {
|
||||
if (borne_precedente == this) hovered = true;
|
||||
else borne_precedente -> hovered = false;
|
||||
borne_precedente -> couleur_hovered = borne_precedente -> couleur_neutre;
|
||||
borne_precedente -> update();
|
||||
}
|
||||
|
||||
// si la scene est un Schema, on actualise le poseur de conducteur
|
||||
if (Schema *s = qobject_cast<Schema *>(scene())) s -> setArrivee(e -> scenePos());
|
||||
|
||||
// on recupere la liste des qgi sous le pointeur
|
||||
QList<QGraphicsItem *> qgis = scene() -> items(e -> scenePos());
|
||||
|
||||
/* le qgi le plus haut
|
||||
= le poseur de conducteur
|
||||
= le premier element de la liste
|
||||
= la liste ne peut etre vide
|
||||
= on prend le deuxieme element de la liste
|
||||
*/
|
||||
Q_ASSERT_X(!(qgis.isEmpty()), "Borne::mouseMoveEvent", "La liste d'items ne devrait pas etre vide");
|
||||
|
||||
// s'il y a autre chose que le poseur de conducteur dans la liste
|
||||
if (qgis.size() > 1) {
|
||||
// on prend le deuxieme element de la liste
|
||||
QGraphicsItem *qgi = qgis.at(1);
|
||||
// si le qgi est une borne...
|
||||
if (Borne *p = qgraphicsitem_cast<Borne *>(qgi)) {
|
||||
// ...on lui applique l'effet hover approprie
|
||||
if (p == this) {
|
||||
// effet si l'on hover sur la borne de depart
|
||||
couleur_hovered = couleur_interdit;
|
||||
} else if (p -> parentItem() == parentItem()) {
|
||||
// effet si l'on hover sur une borne du meme appareil
|
||||
if (((Element *)parentItem()) -> connexionsInternesAcceptees())
|
||||
p -> couleur_hovered = p -> couleur_autorise;
|
||||
else p -> couleur_hovered = p -> couleur_interdit;
|
||||
} else if (p -> nbConducteurs()) {
|
||||
// si la borne a deja un conducteur
|
||||
// verifie que cette borne n'est pas deja reliee a l'autre borne
|
||||
bool deja_reliee = false;
|
||||
foreach (Conducteur *f, liste_conducteurs) {
|
||||
if (f -> borne1 == p || f -> borne2 == p) {
|
||||
deja_reliee = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// interdit si les bornes sont deja reliees, prudence sinon
|
||||
p -> couleur_hovered = deja_reliee ? p -> couleur_interdit : p -> couleur_prudence;
|
||||
} else {
|
||||
// effet si on peut poser le conducteur
|
||||
p -> couleur_hovered = p -> couleur_autorise;
|
||||
}
|
||||
borne_precedente = p;
|
||||
p -> hovered = true;
|
||||
p -> update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait qu'on relache la souris sur la Borne.
|
||||
@param e L'evenement souris correspondant
|
||||
*/
|
||||
void Borne::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
borne_precedente = NULL;
|
||||
couleur_hovered = couleur_neutre;
|
||||
// verifie que la scene est bien un Schema
|
||||
if (Schema *s = qobject_cast<Schema *>(scene())) {
|
||||
// on arrete de dessiner l'apercu du conducteur
|
||||
s -> poseConducteur(false);
|
||||
// on recupere l'element sous le pointeur lors du MouseReleaseEvent
|
||||
QGraphicsItem *qgi = s -> itemAt(e -> scenePos());
|
||||
// s'il n'y a rien, on arrete la
|
||||
if (!qgi) return;
|
||||
// idem si l'element obtenu n'est pas une borne
|
||||
Borne *p = qgraphicsitem_cast<Borne *>(qgi);
|
||||
if (!p) return;
|
||||
// on remet la couleur de hover a sa valeur par defaut
|
||||
p -> couleur_hovered = p -> couleur_neutre;
|
||||
// idem s'il s'agit de la borne actuelle
|
||||
if (p == this) return;
|
||||
// idem s'il s'agit d'une borne de l'element actuel et que l'element n'a pas le droit de relier ses propres bornes
|
||||
bool cia = ((Element *)parentItem()) -> connexionsInternesAcceptees();
|
||||
if (!cia) foreach(QGraphicsItem *item, parentItem() -> children()) if (item == p) return;
|
||||
// derniere verification : verifier que cette borne n'est pas deja reliee a l'autre borne
|
||||
foreach (Conducteur *f, liste_conducteurs) if (f -> borne1 == p || f -> borne2 == p) return;
|
||||
// autrement, on pose un conducteur
|
||||
new Conducteur(this, (Borne *)qgi, 0, scene());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour l'eventuel conducteur relie a la Borne.
|
||||
*/
|
||||
void Borne::updateConducteur() {
|
||||
if (scene()) {
|
||||
foreach (Conducteur *conducteur, liste_conducteurs) if (!conducteur -> isDestroyed()) conducteur -> update(QRectF()/*scene()->sceneRect()*/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return La liste des conducteurs lies a cette borne
|
||||
*/
|
||||
QList<Conducteur *> Borne::conducteurs() const {
|
||||
return(liste_conducteurs);
|
||||
}
|
||||
|
||||
/**
|
||||
Methode d'export en XML
|
||||
@param doc Le Document XML a utiliser pour creer l'element XML
|
||||
@return un QDomElement representant cette borne
|
||||
*/
|
||||
QDomElement Borne::toXml(QDomDocument &doc) {
|
||||
QDomElement qdo = doc.createElement("borne");
|
||||
qdo.setAttribute("x", amarrage_elmt.x());
|
||||
qdo.setAttribute("y", amarrage_elmt.y());
|
||||
qdo.setAttribute("orientation", sens);
|
||||
return(qdo);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si un element XML represente une borne
|
||||
@param e Le QDomElement a analyser
|
||||
@return true si le QDomElement passe en parametre est une borne, false sinon
|
||||
*/
|
||||
bool Borne::valideXml(QDomElement &borne) {
|
||||
// verifie le nom du tag
|
||||
if (borne.tagName() != "borne") return(false);
|
||||
|
||||
// verifie la presence des attributs minimaux
|
||||
if (!borne.hasAttribute("x")) return(false);
|
||||
if (!borne.hasAttribute("y")) return(false);
|
||||
if (!borne.hasAttribute("orientation")) return(false);
|
||||
|
||||
bool conv_ok;
|
||||
// parse l'abscisse
|
||||
borne.attribute("x").toDouble(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
|
||||
// parse l'ordonnee
|
||||
borne.attribute("y").toDouble(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
|
||||
// parse l'id
|
||||
borne.attribute("id").toInt(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
|
||||
// parse l'orientation
|
||||
int borne_or = borne.attribute("orientation").toInt(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
if (borne_or != Borne::Nord && borne_or != Borne::Sud && borne_or != Borne::Est && borne_or != Borne::Ouest) return(false);
|
||||
|
||||
// a ce stade, la borne est syntaxiquement correcte
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si un element XML represente cette borne. Attention, l'element XML n'est pas verifie
|
||||
@param e Le QDomElement a analyser
|
||||
@return true si la borne "se reconnait" (memes coordonnes, meme orientation), false sinon
|
||||
*/
|
||||
bool Borne::fromXml(QDomElement &borne) {
|
||||
return (
|
||||
borne.attribute("x").toDouble() == amarrage_elmt.x() &&\
|
||||
borne.attribute("y").toDouble() == amarrage_elmt.y() &&\
|
||||
borne.attribute("orientation").toInt() == sens
|
||||
);
|
||||
}
|
||||
81
borne.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef BORNE_H
|
||||
#define BORNE_H
|
||||
#define TAILLE_BORNE 4
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
class Conducteur;
|
||||
class Element;
|
||||
class Schema;
|
||||
/**
|
||||
Classe modelisant la « borne » d'un appareil, c'est-a-dire un
|
||||
branchement possible pour un Conducteur.
|
||||
*/
|
||||
class Borne : public QGraphicsItem {
|
||||
public:
|
||||
// enum definissant l'orientation de la borne
|
||||
enum Orientation {Nord, Sud, Est, Ouest};
|
||||
|
||||
// permet de caster un QGraphicsItem en Borne avec qgraphicsitem_cast
|
||||
enum { Type = UserType + 1002 };
|
||||
virtual int type() const { return Type; }
|
||||
|
||||
// constructeurs
|
||||
Borne();
|
||||
Borne(QPointF, Borne::Orientation, Element * = 0, Schema * = 0);
|
||||
Borne(qreal, qreal, Borne::Orientation, Element * = 0, Schema * = 0);
|
||||
|
||||
// destructeur
|
||||
~Borne();
|
||||
|
||||
// implementation des methodes virtuelles pures de QGraphicsItem
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
QRectF boundingRect() const;
|
||||
|
||||
// methodes de manipulation des conducteurs lies a cette borne
|
||||
bool addConducteur(Conducteur *);
|
||||
void removeConducteur(Conducteur *);
|
||||
inline int nbConducteurs() { return(liste_conducteurs.size()); }
|
||||
|
||||
// methodes de lecture
|
||||
QList<Conducteur *> conducteurs() const;
|
||||
Borne::Orientation orientation() const;
|
||||
inline QPointF amarrageConducteur() const { return(mapToScene(amarrage_conducteur)); }
|
||||
void updateConducteur();
|
||||
|
||||
// methodes relatives a l'import/export au format XML
|
||||
static bool valideXml(QDomElement &);
|
||||
bool fromXml (QDomElement &);
|
||||
QDomElement toXml (QDomDocument &);
|
||||
|
||||
// methodes de gestion des evenements
|
||||
void hoverEnterEvent (QGraphicsSceneHoverEvent *);
|
||||
void hoverMoveEvent (QGraphicsSceneHoverEvent *);
|
||||
void hoverLeaveEvent (QGraphicsSceneHoverEvent *);
|
||||
void mousePressEvent (QGraphicsSceneMouseEvent *);
|
||||
void mouseMoveEvent (QGraphicsSceneMouseEvent *);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
|
||||
|
||||
private:
|
||||
// pointeur vers la QGraphicsScene de type Schema (evite quelques casts en interne)
|
||||
Schema *schema_scene;
|
||||
// coordonnees des points d'amarrage
|
||||
QPointF amarrage_conducteur;
|
||||
QPointF amarrage_elmt;
|
||||
// orientation de la borne
|
||||
Borne::Orientation sens;
|
||||
// liste des conducteurs lies a cette borne
|
||||
QList<Conducteur *> liste_conducteurs;
|
||||
// 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
|
||||
QRectF *br;
|
||||
Borne *borne_precedente;
|
||||
bool hovered;
|
||||
// methode initialisant les differents membres de la borne
|
||||
void initialise(QPointF, Borne::Orientation);
|
||||
// differentes couleurs utilisables pour l'effet "hover"
|
||||
QColor couleur_hovered;
|
||||
QColor couleur_neutre;
|
||||
QColor couleur_autorise;
|
||||
QColor couleur_prudence;
|
||||
QColor couleur_interdit;
|
||||
};
|
||||
#endif
|
||||
198
conducteur.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
#include <QtDebug>
|
||||
#include "conducteur.h"
|
||||
#include "element.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param p1 Premiere Borne auquel le conducteur est lie
|
||||
@param p2 Seconde Borne auquel le conducteur est lie
|
||||
@param parent Element parent du conducteur (0 par defaut)
|
||||
@param scene QGraphicsScene auquelle appartient le conducteur
|
||||
*/
|
||||
Conducteur::Conducteur(Borne *p1, Borne* p2, Element *parent, QGraphicsScene *scene) : QGraphicsPathItem(parent, scene) {
|
||||
// bornes que le conducteur relie
|
||||
borne1 = p1;
|
||||
borne2 = p2;
|
||||
// ajout du conducteur a la liste de conducteurs de chacune des deux bornes
|
||||
bool ajout_p1 = borne1 -> addConducteur(this);
|
||||
bool ajout_p2 = borne2 -> addConducteur(this);
|
||||
// en cas d'echec de l'ajout (conducteur deja existant notamment)
|
||||
if (!ajout_p1 || !ajout_p2) return;
|
||||
destroyed = false;
|
||||
// le conducteur est represente par un trait fin
|
||||
QPen t;
|
||||
t.setWidthF(1.0);
|
||||
setPen(t);
|
||||
// calcul du rendu du conducteur
|
||||
calculeConducteur();
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la representation graphique du conducteur.
|
||||
@param rect Rectangle a mettre a jour
|
||||
*/
|
||||
void Conducteur::update(const QRectF &rect = QRectF()) {
|
||||
calculeConducteur();
|
||||
QGraphicsPathItem::update(rect);
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la representation graphique du conducteur.
|
||||
@param x abscisse du rectangle a mettre a jour
|
||||
@param y ordonnee du rectangle a mettre a jour
|
||||
@param width longueur du rectangle a mettre a jour
|
||||
@param height hauteur du rectangle a mettre a jour
|
||||
*/
|
||||
void Conducteur::update(qreal x, qreal y, qreal width, qreal height) {
|
||||
calculeConducteur();
|
||||
QGraphicsPathItem::update(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur du Conducteur. Avant d'etre detruit, le conducteur se decroche des bornes
|
||||
auxquelles il est lie.
|
||||
*/
|
||||
/*Conducteur::~Conducteur() {
|
||||
|
||||
}*/
|
||||
|
||||
/**
|
||||
Met a jour le QPainterPath constituant le conducteur pour obtenir
|
||||
un conducteur uniquement compose de droites reliant les deux bornes.
|
||||
*/
|
||||
void Conducteur::calculeConducteur() {
|
||||
QPainterPath t;
|
||||
|
||||
QPointF p1 = borne1 -> amarrageConducteur();
|
||||
QPointF p2 = borne2 -> amarrageConducteur();
|
||||
|
||||
QPointF depart, arrivee;
|
||||
Borne::Orientation ori_depart, ori_arrivee;
|
||||
// distingue le depart de l'arrivee : le trajet se fait toujours de gauche a droite
|
||||
if (p1.x() <= p2.x()) {
|
||||
depart = mapFromScene(p1);
|
||||
arrivee = mapFromScene(p2);
|
||||
ori_depart = borne1 -> orientation();
|
||||
ori_arrivee = borne2 -> orientation();
|
||||
} else {
|
||||
depart = mapFromScene(p2);
|
||||
arrivee = mapFromScene(p1);
|
||||
ori_depart = borne2 -> orientation();
|
||||
ori_arrivee = borne1 -> orientation();
|
||||
}
|
||||
|
||||
// debut du trajet
|
||||
t.moveTo(depart);
|
||||
if (depart.y() < arrivee.y()) {
|
||||
// trajet descendant
|
||||
if ((ori_depart == Borne::Nord && (ori_arrivee == Borne::Sud || ori_arrivee == Borne::Ouest)) || (ori_depart == Borne::Est && ori_arrivee == Borne::Ouest)) {
|
||||
// cas « 3 »
|
||||
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
|
||||
t.lineTo(ligne_inter_x, depart.y());
|
||||
t.lineTo(ligne_inter_x, arrivee.y());
|
||||
} else if ((ori_depart == Borne::Sud && (ori_arrivee == Borne::Nord || ori_arrivee == Borne::Est)) || (ori_depart == Borne::Ouest && ori_arrivee == Borne::Est)) {
|
||||
// cas « 4 »
|
||||
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
|
||||
t.lineTo(depart.x(), ligne_inter_y);
|
||||
t.lineTo(arrivee.x(), ligne_inter_y);
|
||||
} else if ((ori_depart == Borne::Nord || ori_depart == Borne::Est) && (ori_arrivee == Borne::Nord || ori_arrivee == Borne::Est)) {
|
||||
t.lineTo(arrivee.x(), depart.y()); // cas « 2 »
|
||||
} else t.lineTo(depart.x(), arrivee.y()); // cas « 1 »
|
||||
} else {
|
||||
// trajet montant
|
||||
if ((ori_depart == Borne::Ouest && (ori_arrivee == Borne::Est || ori_arrivee == Borne::Sud)) || (ori_depart == Borne::Nord && ori_arrivee == Borne::Sud)) {
|
||||
// cas « 3 »
|
||||
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
|
||||
t.lineTo(depart.x(), ligne_inter_y);
|
||||
t.lineTo(arrivee.x(), ligne_inter_y);
|
||||
} else if ((ori_depart == Borne::Est && (ori_arrivee == Borne::Ouest || ori_arrivee == Borne::Nord)) || (ori_depart == Borne::Sud && ori_arrivee == Borne::Nord)) {
|
||||
// cas « 4 »
|
||||
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
|
||||
t.lineTo(ligne_inter_x, depart.y());
|
||||
t.lineTo(ligne_inter_x, arrivee.y());
|
||||
} else if ((ori_depart == Borne::Ouest || ori_depart == Borne::Nord) && (ori_arrivee == Borne::Ouest || ori_arrivee == Borne::Nord)) {
|
||||
t.lineTo(depart.x(), arrivee.y()); // cas « 2 »
|
||||
} else t.lineTo(arrivee.x(), depart.y()); // cas « 1 »
|
||||
}
|
||||
// fin du trajet
|
||||
t.lineTo(arrivee);
|
||||
setPath(t);
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le conducteur sans antialiasing.
|
||||
@param qp Le QPainter a utiliser pour dessiner le conducteur
|
||||
@param qsogi Les options de style pour le conducteur
|
||||
@param qw Le QWidget sur lequel on dessine
|
||||
*/
|
||||
void Conducteur::paint(QPainter *qp, const QStyleOptionGraphicsItem *qsogi, QWidget *qw) {
|
||||
qp -> save();
|
||||
qp -> setRenderHint(QPainter::Antialiasing, false);
|
||||
qp -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
qp -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
QGraphicsPathItem::paint(qp, qsogi, qw);
|
||||
qp -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si deux orientations de Borne sont sur le meme axe (Vertical / Horizontal).
|
||||
@param a La premiere orientation de Borne
|
||||
@param b La seconde orientation de Borne
|
||||
@return Un booleen a true si les deux orientations de bornes sont sur le meme axe
|
||||
*/
|
||||
bool Conducteur::surLeMemeAxe(Borne::Orientation a, Borne::Orientation b) {
|
||||
if ((a == Borne::Nord || a == Borne::Sud) && (b == Borne::Nord || b == Borne::Sud)) return(true);
|
||||
else if ((a == Borne::Est || a == Borne::Ouest) && (b == Borne::Est || b == Borne::Ouest)) return(true);
|
||||
else return(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si une orientation de borne est horizontale (Est / Ouest).
|
||||
@param a L'orientation de borne
|
||||
@return True si l'orientation de borne est horizontale, false sinon
|
||||
*/
|
||||
bool Conducteur::estHorizontale(Borne::Orientation a) {
|
||||
return(a == Borne::Est || a == Borne::Ouest);
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si une orientation de borne est verticale (Nord / Sud).
|
||||
@param a L'orientation de borne
|
||||
@return True si l'orientation de borne est verticale, false sinon
|
||||
*/
|
||||
bool Conducteur::estVerticale(Borne::Orientation a) {
|
||||
return(a == Borne::Nord || a == Borne::Sud);
|
||||
}
|
||||
|
||||
/**
|
||||
Methode de preparation a la destruction du conducteur ; le conducteur se detache de ses deux bornes
|
||||
*/
|
||||
void Conducteur::destroy() {
|
||||
destroyed = true;
|
||||
borne1 -> removeConducteur(this);
|
||||
borne2 -> removeConducteur(this);
|
||||
}
|
||||
|
||||
/**
|
||||
Methode de validation d'element XML
|
||||
@param e Un element XML sense represente un Conducteur
|
||||
@return true si l'element XML represente bien un Conducteur ; false sinon
|
||||
*/
|
||||
bool Conducteur::valideXml(QDomElement &e){
|
||||
// verifie le nom du tag
|
||||
if (e.tagName() != "conducteur") return(false);
|
||||
|
||||
// verifie la presence des attributs minimaux
|
||||
if (!e.hasAttribute("borne1")) return(false);
|
||||
if (!e.hasAttribute("borne2")) return(false);
|
||||
|
||||
bool conv_ok;
|
||||
// parse l'abscisse
|
||||
e.attribute("borne1").toInt(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
|
||||
// parse l'ordonnee
|
||||
e.attribute("borne2").toInt(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
return(true);
|
||||
}
|
||||
36
conducteur.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef CONDUCTEUR_H
|
||||
#define CONDUCTEUR_H
|
||||
#include <QtGui>
|
||||
#include "borne.h"
|
||||
class Element;
|
||||
/**
|
||||
Cette classe represente un conducteur. Un conducteur relie deux bornes d'element.
|
||||
*/
|
||||
class Conducteur : public QGraphicsPathItem {
|
||||
public:
|
||||
enum { Type = UserType + 1001 };
|
||||
virtual int type() const { return Type; }
|
||||
Conducteur(Borne *, Borne *, Element * = 0, QGraphicsScene * = 0);
|
||||
//virtual ~Conducteur();
|
||||
|
||||
void destroy();
|
||||
bool isDestroyed() const { return(destroyed); }
|
||||
void update(const QRectF & rect);
|
||||
void update(qreal x, qreal y, qreal width, qreal height);
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
static bool valideXml(QDomElement &);
|
||||
|
||||
///Premiere borne a laquelle le fil est rattache
|
||||
Borne *borne1;
|
||||
///Deuxieme borne a laquelle le fil est rattache
|
||||
Borne *borne2;
|
||||
private:
|
||||
/// booleen indiquant si le fil est encore valide
|
||||
bool destroyed;
|
||||
|
||||
void calculeConducteur();
|
||||
bool surLeMemeAxe(Borne::Orientation, Borne::Orientation);
|
||||
bool estHorizontale(Borne::Orientation a);
|
||||
bool estVerticale(Borne::Orientation a);
|
||||
};
|
||||
#endif
|
||||
56
contacteur.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "contacteur.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QObject parent de l'element.
|
||||
@param scene La scene sur laquelle l'element est affiche
|
||||
*/
|
||||
Contacteur::Contacteur(QGraphicsItem *parent, Schema *scene) : ElementFixe(parent, scene) {
|
||||
// taille et hotspot
|
||||
setSize(15, 70);
|
||||
setHotspot(QPoint(10, 5));
|
||||
|
||||
// ajout de deux bornes a l'element
|
||||
new Borne(0, 0, Borne::Nord, this, scene);
|
||||
new Borne(0, 60, Borne::Sud, this, scene);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nombre actuel de bornes de l'element
|
||||
*/
|
||||
int Contacteur::nbBornes() const {
|
||||
return(2);
|
||||
}
|
||||
|
||||
/**
|
||||
Fonction qui effectue le rendu graphique du contacteur
|
||||
@param p Le QPainter a utiliser pour dessiner l'element
|
||||
@param o Les options de dessin
|
||||
*/
|
||||
void Contacteur::paint(QPainter *p, const QStyleOptionGraphicsItem *) {
|
||||
// traits de couleur noire
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.0);
|
||||
t.setJoinStyle(Qt::MiterJoin);
|
||||
p -> setPen(t);
|
||||
|
||||
// une ligne eventuellement antialiasee
|
||||
p -> drawLine(-5, 19, 0, 40);
|
||||
|
||||
// deux lignes JAMAIS antialiasees (annulation des renderhints)
|
||||
p -> save();
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
p -> drawLine(0, 0, 0, 20);
|
||||
p -> drawLine(0, 40, 0, 60);
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'ID du type "Contacteur"
|
||||
*/
|
||||
QString Contacteur::typeId() {
|
||||
return(QString("0"));
|
||||
}
|
||||
16
contacteur.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef CONTACTEUR_H
|
||||
#define CONTACTEUR_H
|
||||
#include "elementfixe.h"
|
||||
/**
|
||||
Cette classe herite de la classe Element Fixe pour definir un
|
||||
contacteur
|
||||
*/
|
||||
class Contacteur : public ElementFixe {
|
||||
public:
|
||||
Contacteur(QGraphicsItem * = 0, Schema * = 0);
|
||||
virtual int nbBornes() const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
QString typeId();
|
||||
QString nom() { return("Contacteur"); }
|
||||
};
|
||||
#endif
|
||||
63
del.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "del.h"
|
||||
#include <QPen>
|
||||
#include <QGraphicsTextItem>
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QObject parent de l'element.
|
||||
@param scene La scene sur laquelle l'element est affiche
|
||||
*/
|
||||
DEL::DEL(QGraphicsItem *parent, Schema *scene) : ElementFixe(parent, scene) {
|
||||
// taille et hotspot
|
||||
setSize(30, 70);
|
||||
setHotspot(QPoint(15, 5));
|
||||
|
||||
// ajout de deux bornes a l'element
|
||||
new Borne(0, 0, Borne::Nord, this, scene);
|
||||
new Borne(0, 60, Borne::Sud, this, scene);
|
||||
|
||||
peut_relier_ses_propres_bornes = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nombre actuel de bornes de l'element
|
||||
*/
|
||||
int DEL::nbBornes() const {
|
||||
return(2);
|
||||
}
|
||||
|
||||
/**
|
||||
Fonction qui effectue le rendu graphique de la DEL
|
||||
@param p Le QPainter a utiliser pour dessiner l'element
|
||||
@param o Les options de dessin
|
||||
*/
|
||||
void DEL::paint(QPainter *p, const QStyleOptionGraphicsItem *) {
|
||||
// traits de couleur noire
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.0);
|
||||
p -> setPen(t);
|
||||
|
||||
// un cercle a fond blanc
|
||||
p -> setBrush(QBrush(Qt::white, Qt::SolidPattern));
|
||||
p -> drawEllipse(-10, 20, 20, 20);
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
// deux lignes eventuellement antialiasees
|
||||
p -> drawLine(-7, 23, 7, 37);
|
||||
p -> drawLine( 7, 23, -7, 37);
|
||||
// deux lignes JAMAIS antialiasees
|
||||
p -> save();
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
p -> drawLine(0, 0, 0, 20);
|
||||
p -> drawLine(0, 40, 0, 60);
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'ID du type "DEL"
|
||||
*/
|
||||
QString DEL::typeId() {
|
||||
return(QString("1"));
|
||||
}
|
||||
16
del.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef DEL_H
|
||||
#define DEL_H
|
||||
#include "elementfixe.h"
|
||||
/**
|
||||
Cette classe herite de la classe Element Fixe pour definir une
|
||||
Diode ElectroLuminescente
|
||||
*/
|
||||
class DEL : public ElementFixe {
|
||||
public:
|
||||
DEL(QGraphicsItem * = 0, Schema * = 0);
|
||||
virtual int nbBornes() const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
QString typeId();
|
||||
QString nom() { return("DEL"); }
|
||||
};
|
||||
#endif
|
||||
276
element.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
#include "element.h"
|
||||
#include "schema.h"
|
||||
#include <QtDebug>
|
||||
|
||||
/*** Methodes publiques ***/
|
||||
|
||||
/**
|
||||
Constructeur pour un element sans scene ni parent
|
||||
*/
|
||||
Element::Element(QGraphicsItem *parent, Schema *scene) : QGraphicsItem(parent, scene) {
|
||||
sens = true;
|
||||
peut_relier_ses_propres_bornes = false;
|
||||
}
|
||||
|
||||
/**
|
||||
Methode principale de dessin de l'element
|
||||
@param painter Le QPainter utilise pour dessiner l'elment
|
||||
@param options Les options de style a prendre en compte
|
||||
@param widget Le widget sur lequel on dessine
|
||||
*/
|
||||
void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *) {
|
||||
// Dessin de l'element lui-meme
|
||||
paint(painter, options);
|
||||
|
||||
// Dessin du cadre de selection si necessaire
|
||||
if (isSelected()) drawSelection(painter, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le rectangle delimitant le contour de l'element
|
||||
*/
|
||||
QRectF Element::boundingRect() const {
|
||||
return(QRectF(QPointF(-hotspot_coord.x(), -hotspot_coord.y()), dimensions));
|
||||
}
|
||||
|
||||
/**
|
||||
Definit la taille de l'element sur le schema. Les tailles doivent etre
|
||||
des multiples de 10 ; si ce n'est pas le cas, les dimensions indiquees
|
||||
seront arrrondies aux dizaines superieures.
|
||||
@param wid Largeur de l'element
|
||||
@param hei Hauteur de l'element
|
||||
@return La taille finale de l'element
|
||||
*/
|
||||
QSize Element::setSize(int wid, int hei) {
|
||||
prepareGeometryChange();
|
||||
// chaque dimension indiquee est arrondie a la dizaine superieure
|
||||
while (wid % 10) ++ wid;
|
||||
while (hei % 10) ++ hei;
|
||||
// les dimensions finales sont conservees et retournees
|
||||
return(dimensions = QSize(wid, hei));
|
||||
}
|
||||
|
||||
/**
|
||||
Definit le hotspot de l'element par rapport au coin superieur gauche de son rectangle delimitant.
|
||||
Necessite que la taille ait deja ete definie
|
||||
@param hsx Abscisse du hotspot
|
||||
@param hsy Ordonnee du hotspot
|
||||
*/
|
||||
QPoint Element::setHotspot(QPoint hs) {
|
||||
// la taille doit avoir ete definie
|
||||
prepareGeometryChange();
|
||||
if (dimensions.isNull()) hotspot_coord = QPoint(0, 0);
|
||||
else {
|
||||
// les coordonnees indiquees ne doivent pas depasser les dimensions de l'element
|
||||
int hsx = hs.x() > dimensions.width() ? dimensions.width() : hs.x();
|
||||
int hsy = hs.y() > dimensions.height() ? dimensions.height() : hs.y();
|
||||
hotspot_coord = QPoint(hsx, hsy);
|
||||
}
|
||||
return(hotspot_coord);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le hotspot courant de l'element
|
||||
*/
|
||||
QPoint Element::hotspot() const {
|
||||
return(hotspot_coord);
|
||||
}
|
||||
|
||||
/**
|
||||
Selectionne l'element
|
||||
*/
|
||||
void Element::select() {
|
||||
setSelected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Deselectionne l'element
|
||||
*/
|
||||
void Element::deselect() {
|
||||
setSelected(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@return La pixmap de l'element
|
||||
*/
|
||||
QPixmap Element::pixmap() {
|
||||
if (apercu.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait
|
||||
return(apercu);
|
||||
}
|
||||
|
||||
/**
|
||||
@todo distinguer les bornes avec un cast dynamique
|
||||
*/
|
||||
QVariant Element::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
foreach(QGraphicsItem *qgi, children()) {
|
||||
if (Borne *p = qgraphicsitem_cast<Borne *>(qgi)) p -> updateConducteur();
|
||||
}
|
||||
}
|
||||
return(QGraphicsItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return L'orientation en cours de l'element : true pour une orientation verticale, false pour une orientation horizontale
|
||||
*/
|
||||
bool Element::orientation() const {
|
||||
return(sens);
|
||||
}
|
||||
|
||||
/**
|
||||
Inverse l'orientation de l'element
|
||||
@return La nouvelle orientation : true pour une orientation verticale, false pour une orientation horizontale
|
||||
*/
|
||||
bool Element::invertOrientation() {
|
||||
// inversion du sens
|
||||
sens = !sens;
|
||||
// on cache temporairement l'element pour eviter un bug graphique
|
||||
hide();
|
||||
// rotation en consequence et rafraichissement de l'element graphique
|
||||
rotate(sens ? 90.0 : -90.0);
|
||||
// on raffiche l'element, on le reselectionne et on le rafraichit
|
||||
show();
|
||||
select();
|
||||
update();
|
||||
return(sens);
|
||||
}
|
||||
|
||||
/*** Methodes protegees ***/
|
||||
|
||||
/**
|
||||
Dessine un petit repere (axes x et y) relatif a l'element
|
||||
@param painter Le QPainter a utiliser pour dessiner les axes
|
||||
@param options Les options de style a prendre en compte
|
||||
*/
|
||||
void Element::drawAxes(QPainter *painter, const QStyleOptionGraphicsItem *) {
|
||||
painter -> setPen(Qt::blue);
|
||||
painter -> drawLine(0, 0, 10, 0);
|
||||
painter -> drawLine(7,-3, 10, 0);
|
||||
painter -> drawLine(7, 3, 10, 0);
|
||||
painter -> setPen(Qt::red);
|
||||
painter -> drawLine(0, 0, 0, 10);
|
||||
painter -> drawLine(0, 10,-3, 7);
|
||||
painter -> drawLine(0, 10, 3, 7);
|
||||
}
|
||||
|
||||
/*** Methodes privees ***/
|
||||
|
||||
/**
|
||||
Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee.
|
||||
@param qp Le QPainter a utiliser pour dessiner les bornes.
|
||||
@param options Les options de style a prendre en compte
|
||||
*/
|
||||
void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *) {
|
||||
painter -> save();
|
||||
// Annulation des renderhints
|
||||
painter -> setRenderHint(QPainter::Antialiasing, false);
|
||||
painter -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
painter -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
// Dessin du cadre de selection en gris
|
||||
QPen t;
|
||||
t.setColor(Qt::gray);
|
||||
t.setStyle(Qt::DashDotLine);
|
||||
painter -> setPen(t);
|
||||
// Le dessin se fait a partir du rectangle delimitant
|
||||
painter -> drawRoundRect(boundingRect(), 10, 10);
|
||||
painter -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Fonction initialisant et dessinant la pixmap de l'element.
|
||||
*/
|
||||
void Element::updatePixmap() {
|
||||
// Pixmap transparente faisant la taille de base de l'element
|
||||
apercu = QPixmap(dimensions);
|
||||
apercu.fill(QColor(255, 255, 255, 0));
|
||||
// QPainter sur la pixmap, avec antialiasing
|
||||
QPainter p(&apercu);
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
// Translation de l'origine du repere de la pixmap
|
||||
p.translate(hotspot_coord);
|
||||
// L'element se dessine sur la pixmap
|
||||
paint(&p, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Change la position de l'element en veillant a ce que l'element
|
||||
reste sur la grille du Schema auquel il appartient.
|
||||
@param p Nouvelles coordonnees de l'element
|
||||
*/
|
||||
void Element::setPos(const QPointF &p) {
|
||||
if (p == pos()) return;
|
||||
// pas la peine de positionner sur la grille si l'element n'est pas sur un Schema
|
||||
if (scene()) {
|
||||
// arrondit l'abscisse a 10 px pres
|
||||
int p_x = qRound(p.x() / 10.0) * 10;
|
||||
// arrondit l'ordonnee a 10 px pres
|
||||
int p_y = qRound(p.y() / 10.0) * 10;
|
||||
QGraphicsItem::setPos(p_x, p_y);
|
||||
} else QGraphicsItem::setPos(p);
|
||||
// actualise les bornes / conducteurs
|
||||
foreach(QGraphicsItem *qgi, children()) {
|
||||
if (Borne *p = qgraphicsitem_cast<Borne *>(qgi)) p -> updateConducteur();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Change la position de l'element en veillant a ce que l'element
|
||||
reste sur la grille du Schema auquel il appartient.
|
||||
@param x Nouvelle abscisse de l'element
|
||||
@param y Nouvelle ordonnee de l'element
|
||||
*/
|
||||
void Element::setPos(qreal x, qreal y) {
|
||||
setPos(QPointF(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements de souris lies a l'element, notamment
|
||||
*/
|
||||
void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
/*&& (flags() & ItemIsMovable)*/ // on le sait qu'il est movable
|
||||
if (e -> buttons() & Qt::LeftButton) {
|
||||
QPointF oldPos = pos();
|
||||
setPos(mapToParent(e->pos()) - matrix().map(e->buttonDownPos(Qt::LeftButton)));
|
||||
QPointF diff = pos() - oldPos;
|
||||
|
||||
// Recupere la liste des elements selectionnes
|
||||
QList<QGraphicsItem *> selectedItems;
|
||||
if (scene()) {
|
||||
selectedItems = scene() -> selectedItems();
|
||||
} else if (QGraphicsItem *parent = parentItem()) {
|
||||
while (parent && parent->isSelected()) selectedItems << parent;
|
||||
}
|
||||
|
||||
// Deplace tous les elements selectionnes
|
||||
foreach (QGraphicsItem *item, selectedItems) {
|
||||
if (!item->parentItem() || !item->parentItem()->isSelected())
|
||||
if (item != this) item->setPos(item->pos() + diff);
|
||||
}
|
||||
} else e -> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si un element XML (QDomElement) represente bien un element
|
||||
@param e Le QDomElement a valide
|
||||
@return true si l'element XML est un Element, false sinon
|
||||
*/
|
||||
bool Element::valideXml(QDomElement &e) {
|
||||
// verifie le nom du tag
|
||||
if (e.tagName() != "element") return(false);
|
||||
|
||||
// verifie la presence des attributs minimaux
|
||||
if (!e.hasAttribute("type")) return(false);
|
||||
if (!e.hasAttribute("x")) return(false);
|
||||
if (!e.hasAttribute("y")) return(false);
|
||||
|
||||
bool conv_ok;
|
||||
// parse l'abscisse
|
||||
e.attribute("x").toDouble(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
|
||||
// parse l'ordonnee
|
||||
e.attribute("y").toDouble(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
return(true);
|
||||
}
|
||||
50
element.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef ELEMENT_H
|
||||
#define ELEMENT_H
|
||||
#include <QtGui>
|
||||
#include "borne.h"
|
||||
class Schema;
|
||||
class Element : public QGraphicsItem {
|
||||
public:
|
||||
enum { Type = UserType + 1000 };
|
||||
virtual int type() const { return Type; }
|
||||
Element(QGraphicsItem * = 0, Schema * = 0);
|
||||
|
||||
virtual int nbBornes() const = 0;
|
||||
virtual int nbBornesMin() const = 0;
|
||||
virtual int nbBornesMax() const = 0;
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0;
|
||||
virtual QString typeId() = 0;
|
||||
|
||||
virtual QString nom() = 0;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
QRectF boundingRect() const;
|
||||
QSize setSize(int, int);
|
||||
QPoint setHotspot(QPoint);
|
||||
QPoint hotspot() const;
|
||||
void select();
|
||||
void deselect();
|
||||
QPixmap pixmap();
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
bool orientation() const;
|
||||
bool invertOrientation();
|
||||
void setPos(const QPointF &);
|
||||
void setPos(qreal, qreal);
|
||||
bool connexionsInternesAcceptees() { return(peut_relier_ses_propres_bornes); }
|
||||
static bool valideXml(QDomElement &);
|
||||
virtual bool fromXml(QDomElement &, QHash<int, Borne *>&) = 0;
|
||||
|
||||
protected:
|
||||
void drawAxes(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *);
|
||||
bool peut_relier_ses_propres_bornes;
|
||||
|
||||
private:
|
||||
void drawSelection(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
void updatePixmap();
|
||||
bool sens;
|
||||
QSize dimensions;
|
||||
QPoint hotspot_coord;
|
||||
QPixmap apercu;
|
||||
QMenu menu;
|
||||
};
|
||||
#endif
|
||||
82
elementfixe.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "elementfixe.h"
|
||||
/**
|
||||
Constructeur
|
||||
*/
|
||||
ElementFixe::ElementFixe(QGraphicsItem *parent, Schema *scene) : Element(parent, scene) {
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nombre minimal de bornes que l'element peut avoir
|
||||
*/
|
||||
int ElementFixe::nbBornesMin() const {
|
||||
return(nbBornes());
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nombre maximal de bornes que l'element peut avoir
|
||||
*/
|
||||
int ElementFixe::nbBornesMax() const {
|
||||
return(nbBornes());
|
||||
}
|
||||
|
||||
/**
|
||||
Methode d'import XML. Cette methode est appelee lors de l'import de contenu XML (coller, import, ouverture de fichier...) afin que l'element puisse gerer lui-meme l'importation de ses bornes. Ici, comme cette classe est caracterisee par un nombre fixe de bornes, l'implementation exige de retrouver exactement ses bornes dans le fichier XML.
|
||||
@param e L'element XML a analyser.
|
||||
@param table_id_adr Reference vers la table de correspondance entre les IDs du fichier XML et les adresses en memoire. Si l'import reussit, il faut y ajouter les bons couples (id, adresse).
|
||||
@return true si l'import a reussi, false sinon
|
||||
|
||||
*/
|
||||
bool ElementFixe::fromXml(QDomElement &e, QHash<int, Borne *> &table_id_adr) {
|
||||
/*
|
||||
les bornes vont maintenant etre recensees pour associer leurs id à leur adresse reelle
|
||||
ce recensement servira lors de la mise en place des fils
|
||||
*/
|
||||
|
||||
QList<QDomElement> liste_bornes;
|
||||
// parcours des enfants de l'element
|
||||
for (QDomNode enfant = e.firstChild() ; !enfant.isNull() ; enfant = enfant.nextSibling()) {
|
||||
// on s'interesse a l'element XML "bornes"
|
||||
QDomElement bornes = enfant.toElement();
|
||||
if (bornes.isNull() || bornes.tagName() != "bornes") continue;
|
||||
// parcours des enfants de l'element XML "bornes"
|
||||
for (QDomNode node_borne = bornes.firstChild() ; !node_borne.isNull() ; node_borne = node_borne.nextSibling()) {
|
||||
// on s'interesse a l'element XML "borne"
|
||||
QDomElement borne = node_borne.toElement();
|
||||
if (!borne.isNull() && Borne::valideXml(borne)) liste_bornes.append(borne);
|
||||
}
|
||||
}
|
||||
|
||||
QHash<int, Borne *> priv_id_adr;
|
||||
int bornes_non_trouvees = 0;
|
||||
foreach(QGraphicsItem *qgi, children()) {
|
||||
if (Borne *p = qgraphicsitem_cast<Borne *>(qgi)) {
|
||||
bool borne_trouvee = false;
|
||||
foreach(QDomElement qde, liste_bornes) {
|
||||
if (p -> fromXml(qde)) {
|
||||
priv_id_adr.insert(qde.attribute("id").toInt(), p);
|
||||
borne_trouvee = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!borne_trouvee) ++ bornes_non_trouvees;
|
||||
}
|
||||
}
|
||||
|
||||
if (bornes_non_trouvees > 0) {
|
||||
return(false);
|
||||
} else {
|
||||
// verifie que les associations id / adr n'entrent pas en conflit avec table_id_adr
|
||||
foreach(int id_trouve, priv_id_adr.keys()) {
|
||||
if (table_id_adr.contains(id_trouve)) {
|
||||
// cet element possede un id qui est deja reference (= conflit)
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
// copie des associations id / adr
|
||||
foreach(int id_trouve, priv_id_adr.keys()) {
|
||||
table_id_adr.insert(id_trouve, priv_id_adr.value(id_trouve));
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
15
elementfixe.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ELEMENTFIXE_H
|
||||
#define ELEMENTFIXE_H
|
||||
#include "element.h"
|
||||
class ElementFixe : public Element {
|
||||
public:
|
||||
ElementFixe(QGraphicsItem * = 0, Schema * = 0);
|
||||
int nbBornesMin() const;
|
||||
int nbBornesMax() const;
|
||||
virtual bool fromXml(QDomElement &, QHash<int, Borne *>&);
|
||||
virtual int nbBornes() const = 0;
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0;
|
||||
virtual QString typeId() = 0;
|
||||
virtual QString nom() = 0;
|
||||
};
|
||||
#endif
|
||||
196
elementperso.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
#include "elementperso.h"
|
||||
|
||||
ElementPerso::ElementPerso(QString &nom_fichier, QGraphicsItem *qgi, Schema *s, int *etat) : ElementFixe(qgi, s) {
|
||||
nomfichier = nom_fichier;
|
||||
nb_bornes = 0;
|
||||
// pessimisme inside : par defaut, ca foire
|
||||
elmt_etat = -1;
|
||||
|
||||
// le fichier doit exister
|
||||
QString chemin_elements = "elements/";
|
||||
nomfichier = chemin_elements + nom_fichier;
|
||||
if (!QFileInfo(nomfichier).exists()) {
|
||||
if (etat != NULL) *etat = 1;
|
||||
elmt_etat = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// le fichier doit etre lisible
|
||||
QFile fichier(nomfichier);
|
||||
if (!fichier.open(QIODevice::ReadOnly)) {
|
||||
if (etat != NULL) *etat = 2;
|
||||
elmt_etat = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
// le fichier doit etre un document XML
|
||||
QDomDocument document_xml;
|
||||
if (!document_xml.setContent(&fichier)) {
|
||||
if (etat != NULL) *etat = 3;
|
||||
elmt_etat = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
// la racine est supposee etre une definition d'element
|
||||
QDomElement racine = document_xml.documentElement();
|
||||
if (racine.tagName() != "definition" || racine.attribute("type") != "element") {
|
||||
if (etat != NULL) *etat = 4;
|
||||
elmt_etat = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
// ces attributs doivent etre presents et valides
|
||||
int w, h, hot_x, hot_y;
|
||||
if (
|
||||
racine.attribute("nom") == QString("") ||\
|
||||
!attributeIsAnInteger(racine, QString("width"), &w) ||\
|
||||
!attributeIsAnInteger(racine, QString("height"), &h) ||\
|
||||
!attributeIsAnInteger(racine, QString("hotspot_x"), &hot_x) ||\
|
||||
!attributeIsAnInteger(racine, QString("hotspot_y"), &hot_y)
|
||||
) {
|
||||
if (etat != NULL) *etat = 5;
|
||||
elmt_etat = 5;
|
||||
return;
|
||||
}
|
||||
|
||||
// on peut d'ores et deja specifier le nom, la taille et le hotspot
|
||||
priv_nom = racine.attribute("nom");
|
||||
setSize(w, h);
|
||||
setHotspot(QPoint(hot_x, hot_y));
|
||||
|
||||
// la definition est supposee avoir des enfants
|
||||
if (racine.firstChild().isNull()) {
|
||||
if (etat != NULL) *etat = 6;
|
||||
elmt_etat = 6;
|
||||
return;
|
||||
}
|
||||
|
||||
// parcours des enfants de la definition
|
||||
int nb_elements_parses = 0;
|
||||
QPainter qp;
|
||||
qp.begin(&dessin);
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.0);
|
||||
t.setJoinStyle(Qt::MiterJoin);
|
||||
qp.setPen(t);
|
||||
for (QDomNode node = racine.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
QDomElement elmts = node.toElement();
|
||||
if(elmts.isNull()) continue;
|
||||
if (parseElement(elmts, qp, s)) ++ nb_elements_parses;
|
||||
else {
|
||||
if (etat != NULL) *etat = 7;
|
||||
elmt_etat = 7;
|
||||
return;
|
||||
}
|
||||
}
|
||||
qp.end();
|
||||
|
||||
// il doit y avoir au moins un element charge
|
||||
if (!nb_elements_parses) {
|
||||
if (etat != NULL) *etat = 8;
|
||||
elmt_etat = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
// fermeture du fichier
|
||||
fichier.close();
|
||||
|
||||
if (etat != NULL) *etat = 0;
|
||||
elmt_etat = 0;
|
||||
}
|
||||
|
||||
int ElementPerso::nbBornes() const {
|
||||
return(nb_bornes);
|
||||
}
|
||||
|
||||
void ElementPerso::paint(QPainter *qp, const QStyleOptionGraphicsItem *) {
|
||||
dessin.play(qp);
|
||||
}
|
||||
|
||||
bool ElementPerso::parseElement(QDomElement &e, QPainter &qp, Schema *s) {
|
||||
if (e.tagName() == "borne") return(parseBorne(e, s));
|
||||
else if (e.tagName() == "ligne") return(parseLigne(e, qp));
|
||||
else if (e.tagName() == "cercle") return(parseCercle(e, qp));
|
||||
else if (e.tagName() == "polygone") return(parsePolygone(e, qp));
|
||||
else return(true); // on n'est pas chiant, on ignore l'element inconnu
|
||||
}
|
||||
|
||||
bool ElementPerso::parseLigne(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence et la validite des attributs obligatoires
|
||||
int x1, y1, x2, y2;
|
||||
if (!attributeIsAnInteger(e, QString("x1"), &x1)) return(false);
|
||||
if (!attributeIsAnInteger(e, QString("y1"), &y1)) return(false);
|
||||
if (!attributeIsAnInteger(e, QString("x2"), &x2)) return(false);
|
||||
if (!attributeIsAnInteger(e, QString("y2"), &y2)) return(false);
|
||||
/// @todo : gerer l'antialiasing (mieux que ca !) et le type de trait
|
||||
setQPainterAntiAliasing(&qp, e.attribute("antialias") == "true");
|
||||
qp.drawLine(x1, y1, x2, y2);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool ElementPerso::parseCercle(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence des attributs obligatoires
|
||||
int cercle_x, cercle_y, cercle_r;
|
||||
if (!attributeIsAnInteger(e, QString("x"), &cercle_x)) return(false);
|
||||
if (!attributeIsAnInteger(e, QString("y"), &cercle_y)) return(false);
|
||||
if (!attributeIsAnInteger(e, QString("rayon"), &cercle_r)) return(false);
|
||||
/// @todo : gerer l'antialiasing (mieux que ca !) et le type de trait
|
||||
setQPainterAntiAliasing(&qp, e.attribute("antialias") == "true");
|
||||
qp.drawEllipse(cercle_x, cercle_y, cercle_r, cercle_r);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool ElementPerso::parsePolygone(QDomElement &e, QPainter &qp) {
|
||||
int i = 1;
|
||||
while(true) {
|
||||
if (attributeIsAnInteger(e, QString("x%1").arg(i)) && attributeIsAnInteger(e, QString("y%1").arg(i))) ++ i;
|
||||
else break;
|
||||
}
|
||||
if (i < 3) return(false);
|
||||
QPointF points[i-1];
|
||||
for (int j = 1 ; j < i ; ++ j) {
|
||||
points[j-1] = QPointF(
|
||||
e.attribute(QString("x%1").arg(j)).toDouble(),
|
||||
e.attribute(QString("y%1").arg(j)).toDouble()
|
||||
);
|
||||
}
|
||||
setQPainterAntiAliasing(&qp, e.attribute("antialias") == "true");
|
||||
qp.drawPolygon(points, i-1);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool ElementPerso::parseBorne(QDomElement &e, Schema *s) {
|
||||
// verifie la presence et la validite des attributs obligatoires
|
||||
int bornex, borney;
|
||||
Borne::Orientation borneo;
|
||||
if (!attributeIsAnInteger(e, QString("x"), &bornex)) return(false);
|
||||
if (!attributeIsAnInteger(e, QString("y"), &borney)) return(false);
|
||||
if (!e.hasAttribute("orientation")) return(false);
|
||||
if (e.attribute("orientation") == "n") borneo = Borne::Nord;
|
||||
else if (e.attribute("orientation") == "s") borneo = Borne::Sud;
|
||||
else if (e.attribute("orientation") == "e") borneo = Borne::Est;
|
||||
else if (e.attribute("orientation") == "o") borneo = Borne::Ouest;
|
||||
else return(false);
|
||||
new Borne(bornex, borney, borneo, this, s);
|
||||
++ nb_bornes;
|
||||
return(true);
|
||||
}
|
||||
|
||||
void ElementPerso::setQPainterAntiAliasing(QPainter *qp, bool aa) {
|
||||
qp -> setRenderHint(QPainter::Antialiasing, aa);
|
||||
qp -> setRenderHint(QPainter::TextAntialiasing, aa);
|
||||
qp -> setRenderHint(QPainter::SmoothPixmapTransform, aa);
|
||||
}
|
||||
|
||||
int ElementPerso::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);
|
||||
}
|
||||
|
||||
30
elementperso.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef ELEMENTPERSO_H
|
||||
#define ELEMENTPERSO_H
|
||||
#include "elementfixe.h"
|
||||
#include <QtGui>
|
||||
class ElementPerso : public ElementFixe {
|
||||
public:
|
||||
ElementPerso(QString &, QGraphicsItem * = 0, Schema * = 0, int * = NULL);
|
||||
virtual int nbBornes() const;
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
QString typeId() { return(nomfichier); }
|
||||
QString fichier() { return(nomfichier); }
|
||||
bool isNull() { return(elmt_etat != 0); }
|
||||
int etat() { return(elmt_etat); }
|
||||
QString nom() { return(priv_nom); }
|
||||
|
||||
private:
|
||||
int elmt_etat; // contient le code d'erreur si l'instanciation a echoue ou 0 si l'instanciation s'est bien passe
|
||||
QString priv_nom;
|
||||
QString nomfichier;
|
||||
QPicture dessin;
|
||||
bool parseElement(QDomElement &, QPainter &, Schema *);
|
||||
bool parseLigne(QDomElement &, QPainter &);
|
||||
bool parseCercle(QDomElement &, QPainter &);
|
||||
bool parsePolygone(QDomElement &, QPainter &);
|
||||
bool parseBorne(QDomElement &, Schema *);
|
||||
void setQPainterAntiAliasing(QPainter *, bool);
|
||||
int attributeIsAnInteger(QDomElement &, QString, int * = NULL);
|
||||
int nb_bornes;
|
||||
};
|
||||
#endif
|
||||
8
elements/contacteur.elmt
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- orientation : 4 lettres = nord/sud/est/ouest avec d = default, y = yes et n = no -->
|
||||
<definition type="element" nom="contacteur" width="15" height="70" hotspot_x="10" hotspot_y="5" orientation="dnny">
|
||||
<ligne x1="-5" y1="19" x2="0" y2="40" antialias="true" style="normal" />
|
||||
<ligne x1="0" y1="0" x2="0" y2="20" antialias="false" style="normal" />
|
||||
<ligne x1="0" y1="40" x2="0" y2="60" antialias="false" style="normal" />
|
||||
<borne orientation="n" x="0" y="0" />
|
||||
<borne orientation="s" x="0" y="60" />
|
||||
</definition>
|
||||
9
elements/del.elmt
Normal file
@@ -0,0 +1,9 @@
|
||||
<definition type="element" nom="del" width="30" height="70" hotspot_x="15" hotspot_y="5" orientation="dnny">
|
||||
<cercle x="-10" y="20" rayon="20" antialias="true" style="normal" />
|
||||
<ligne x1="-7" y1="23" x2="7" y2="37" antialias="true" style="normal" />
|
||||
<ligne x1="7" y1="23" x2="-7" y2="37" antialias="true" style="normal" />
|
||||
<ligne x1="0" y1="0" x2="0" y2="20" antialias="false" style="normal" />
|
||||
<ligne x1="0" y1="40" x2="0" y2="60" antialias="false" style="normal" />
|
||||
<borne orientation="n" x="0" y="0" />
|
||||
<borne orientation="s" x="0" y="60" />
|
||||
</definition>
|
||||
6
elements/entree.elmt
Normal file
@@ -0,0 +1,6 @@
|
||||
<definition type="element" nom="entree" width="20" height="40" hotspot_x="10" hotspot_y="15" orientation="dnny">
|
||||
<!-- note : 7.5 a la place de 8 -->
|
||||
<polygone x1="-8" y1="-13" x2="8" y2="-13" x3="0" y3="0" antialias="true" style="normal" />
|
||||
<ligne x1="0" y1="0" x2="0" y2="13" antialias="false" style="normal" />
|
||||
<borne orientation="s" x="0" y="15" />
|
||||
</definition>
|
||||
62
entree.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "entree.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QObject parent de l'element.
|
||||
@param scene La scene sur laquelle l'element est affiche
|
||||
*/
|
||||
Entree::Entree(QGraphicsItem *parent, Schema *scene) : ElementFixe(parent, scene) {
|
||||
// taille et hotspot
|
||||
setSize(20, 40);
|
||||
setHotspot(QPoint(10, 15));
|
||||
|
||||
// ajout d'une borne a l'element
|
||||
new Borne(0, 15, Borne::Sud, this, scene);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nombre actuel de bornes de l'element
|
||||
*/
|
||||
int Entree::nbBornes() const {
|
||||
return(1);
|
||||
}
|
||||
|
||||
/**
|
||||
Fonction qui effectue le rendu graphique du contacteur
|
||||
@param p Le QPainter a utiliser pour dessiner l'element
|
||||
@param o Les options de dessin
|
||||
*/
|
||||
void Entree::paint(QPainter *p, const QStyleOptionGraphicsItem *) {
|
||||
// traits de couleur noire
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.0);
|
||||
t.setJoinStyle(Qt::MiterJoin);
|
||||
p -> setPen(t);
|
||||
p -> setBrush(Qt::black);
|
||||
|
||||
// Dessin du triangle
|
||||
static const QPointF points[3] = {
|
||||
QPointF(-7.5, -13),
|
||||
QPointF( 7.5, -13),
|
||||
QPointF( 0.0, 0.0)
|
||||
};
|
||||
|
||||
p -> drawPolygon(points, 3);
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
|
||||
// une ligne JAMAIS antialiasee (annulation des renderhints)
|
||||
p -> save();
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
p -> drawLine(0, 0, 0, 13);
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'ID du type "Contacteur"
|
||||
*/
|
||||
QString Entree::typeId() {
|
||||
return(QString("2"));
|
||||
}
|
||||
16
entree.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ENTREE_H
|
||||
#define ENTREE_H
|
||||
#include "elementfixe.h"
|
||||
/**
|
||||
Cette classe herite de la classe Element Fixe pour definir une
|
||||
entree.
|
||||
*/
|
||||
class Entree : public ElementFixe{
|
||||
public:
|
||||
Entree(QGraphicsItem * = 0, Schema * = 0);
|
||||
virtual int nbBornes() const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
QString typeId();
|
||||
QString nom() { return("Entr\351e"); }
|
||||
};
|
||||
#endif
|
||||
342
gnugpl.txt
Normal file
@@ -0,0 +1,342 @@
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
BIN
ico/button_cancel.png
Normal file
|
After Width: | Height: | Size: 883 B |
BIN
ico/button_ok.png
Normal file
|
After Width: | Height: | Size: 769 B |
BIN
ico/configure.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
ico/copy.png
Normal file
|
After Width: | Height: | Size: 777 B |
BIN
ico/cut.png
Normal file
|
After Width: | Height: | Size: 804 B |
BIN
ico/delete.png
Normal file
|
After Width: | Height: | Size: 951 B |
BIN
ico/editdelete.png
Normal file
|
After Width: | Height: | Size: 892 B |
BIN
ico/entrer_fs.png
Normal file
|
After Width: | Height: | Size: 785 B |
BIN
ico/exit.png
Normal file
|
After Width: | Height: | Size: 830 B |
BIN
ico/export.png
Normal file
|
After Width: | Height: | Size: 626 B |
BIN
ico/fileclose.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
ico/import.png
Normal file
|
After Width: | Height: | Size: 851 B |
BIN
ico/masquer.png
Normal file
|
After Width: | Height: | Size: 609 B |
BIN
ico/move.png
Normal file
|
After Width: | Height: | Size: 235 B |
BIN
ico/new.png
Normal file
|
After Width: | Height: | Size: 686 B |
BIN
ico/open.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
ico/paste.png
Normal file
|
After Width: | Height: | Size: 979 B |
BIN
ico/pivoter.png
Normal file
|
After Width: | Height: | Size: 749 B |
BIN
ico/print.png
Normal file
|
After Width: | Height: | Size: 684 B |
BIN
ico/qelectrotech.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
13
ico/qelectrotech.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="256" height="256" stroke="black" stroke-width="5">
|
||||
<defs>
|
||||
<mask id="Masque">
|
||||
<circle cx="128" cy="128" r="50" fill="white" stroke-width="1" />
|
||||
</mask>
|
||||
</defs>
|
||||
<path d="M128,0 128,256" fill="none" />
|
||||
<circle cx="128" cy="128" r="50" fill="white" />
|
||||
<path d="M0,0 256,256" fill="none" mask="url(#Masque)" />
|
||||
<path d="M256,0 0,256" fill="none" mask="url(#Masque)" />
|
||||
<text x="5" y="140" stroke-width="1" style="font-size:33px;font-weight:100;">QET</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 541 B |
BIN
ico/qet.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
12
ico/qet.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="256" height="256" stroke="black" stroke-width="10">
|
||||
<defs>
|
||||
<mask id="Masque">
|
||||
<circle cx="128" cy="128" r="100" fill="white" stroke-width="1" />
|
||||
</mask>
|
||||
</defs>
|
||||
<path d="M128,0 128,256" fill="none" />
|
||||
<circle cx="128" cy="128" r="100" fill="white" />
|
||||
<path d="M0,0 256,256" fill="none" mask="url(#Masque)" />
|
||||
<path d="M256,0 0,256" fill="none" mask="url(#Masque)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 454 B |
BIN
ico/qt.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
ico/redo.png
Normal file
|
After Width: | Height: | Size: 736 B |
BIN
ico/restaurer.png
Normal file
|
After Width: | Height: | Size: 679 B |
BIN
ico/save.png
Normal file
|
After Width: | Height: | Size: 838 B |
BIN
ico/saveas.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
ico/select.png
Normal file
|
After Width: | Height: | Size: 411 B |
BIN
ico/sortir_fs.png
Normal file
|
After Width: | Height: | Size: 772 B |
BIN
ico/toolbars.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
ico/undo.png
Normal file
|
After Width: | Height: | Size: 683 B |
BIN
ico/viewmag+.png
Normal file
|
After Width: | Height: | Size: 810 B |
BIN
ico/viewmag-.png
Normal file
|
After Width: | Height: | Size: 800 B |
BIN
ico/viewmag.png
Normal file
|
After Width: | Height: | Size: 815 B |
BIN
ico/viewmagfit.png
Normal file
|
After Width: | Height: | Size: 846 B |
21
main.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <QApplication>
|
||||
#include <QTranslator>
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Fonction principale du programme QElectroTech
|
||||
@param argc nombre de parametres
|
||||
@param argv parametres
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
// Creation de l'application
|
||||
QApplication app(argc, argv);
|
||||
// Traducteur
|
||||
QTranslator trad;
|
||||
//trad.load("qet_en");
|
||||
app.installTranslator(&trad);
|
||||
// Creation et affichage du QETApp : QElectroTechApplication
|
||||
(new QETApp()) -> show();
|
||||
// Execution de l'application
|
||||
return(app.exec());
|
||||
}
|
||||
111
panelappareils.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "panelappareils.h"
|
||||
#include "contacteur.h"
|
||||
#include "del.h"
|
||||
#include "entree.h"
|
||||
#include "elementperso.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent du panel d'appareils
|
||||
@todo : definir une classe heritant de QListWidgetItem et automatiser tout ca
|
||||
*/
|
||||
PanelAppareils::PanelAppareils(QWidget *parent) : QListWidget(parent) {
|
||||
|
||||
// selection unique
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
// drag'n drop autorise
|
||||
setDragEnabled(true);
|
||||
setAcceptDrops(false);
|
||||
setDropIndicatorShown(false);
|
||||
|
||||
// style, mouvement et taille des elements
|
||||
setIconSize(QSize(50, 50));
|
||||
setMovement(QListView::Free);
|
||||
setViewMode(QListView::ListMode);
|
||||
|
||||
// donnees
|
||||
/*Element *del = new DEL(0,0);
|
||||
Element *contacteur = new Contacteur(0,0);
|
||||
Element *entree = new Entree(0, 0);*/
|
||||
|
||||
QListWidgetItem *qlwi;
|
||||
QString whats_this = tr("Ceci est un \351l\351ment que vous pouvez ins\351rer dans votre sch\351ma par cliquer-d\351placer");
|
||||
QString tool_tip = tr("Cliquer-d\351posez cet \351l\351ment sur le sch\351ma pour ins\351rer un \351l\351ment ");
|
||||
|
||||
// remplissage de la liste
|
||||
QDir dossier_elements("elements/");
|
||||
QStringList filtres;
|
||||
filtres << "*.elmt";
|
||||
QStringList fichiers = dossier_elements.entryList(filtres, QDir::Files, QDir::Name);
|
||||
foreach(QString fichier, fichiers) {
|
||||
int etat;
|
||||
ElementPerso *elmt_perso = new ElementPerso(fichier, 0, 0, &etat);
|
||||
if (etat != 0) {
|
||||
qDebug() << "Le chargement du composant" << fichier << "a echoue avec le code d'erreur" << etat;
|
||||
continue;
|
||||
}
|
||||
qlwi = new QListWidgetItem(QIcon(elmt_perso -> pixmap()), elmt_perso -> nom(), this);
|
||||
qlwi -> setStatusTip(tool_tip + "\253 " + elmt_perso -> nom() + " \273");
|
||||
qlwi -> setToolTip(elmt_perso -> nom());
|
||||
qlwi -> setWhatsThis(whats_this);
|
||||
qlwi -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
|
||||
qlwi -> setData(42, fichier);
|
||||
}
|
||||
|
||||
// force du noir sur une alternance de blanc (comme le schema) et de bleu clair
|
||||
QPalette qp = palette();
|
||||
setAlternatingRowColors(true);
|
||||
qp.setColor(QPalette::Text, Qt::black);
|
||||
qp.setColor(QPalette::Base, Qt::white);
|
||||
//qp.setColor(QPalette::AlternateBase, QColor(240, 255, 255));
|
||||
setPalette(qp);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le mouvement lors d'un drag'n drop
|
||||
*/
|
||||
void PanelAppareils::dragMoveEvent(QDragMoveEvent */*e*/) {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le depot lors d'un drag'n drop
|
||||
*/
|
||||
void PanelAppareils::dropEvent(QDropEvent */*e*/) {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le debut des drag'n drop
|
||||
@param supportedActions Les actions supportees
|
||||
@todo virer les lignes type «if ("tel appareil") construire TelAppareil» => trouver un moyen d'automatiser ca
|
||||
*/
|
||||
void PanelAppareils::startDrag(Qt::DropActions /*supportedActions*/) {
|
||||
// objet QDrag pour realiser le drag'n drop
|
||||
QDrag *drag = new QDrag(this);
|
||||
|
||||
// donnees qui seront transmises par le drag'n drop
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
|
||||
// appareil temporaire pour fournir un apercu
|
||||
Element *appar;
|
||||
int etat;
|
||||
QString nom_fichier = currentItem() -> data(42).toString();
|
||||
appar = new ElementPerso(nom_fichier, 0, 0, &etat);
|
||||
if (etat != 0) {
|
||||
delete appar;
|
||||
return;
|
||||
}
|
||||
|
||||
mimeData -> setText(nom_fichier);
|
||||
drag -> setMimeData(mimeData);
|
||||
|
||||
// accrochage d'une pixmap representant l'appareil au pointeur
|
||||
drag -> setPixmap(appar -> pixmap());
|
||||
drag -> setHotSpot(appar -> hotspot());
|
||||
|
||||
// realisation du drag'n drop
|
||||
drag -> start(Qt::CopyAction);
|
||||
|
||||
// suppression de l'appareil temporaire
|
||||
delete appar;
|
||||
}
|
||||
18
panelappareils.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef PANELAPPAREILS_H
|
||||
#define PANELAPPAREILS_H
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette classe represente le panel d'appareils (en tant qu'element
|
||||
graphique) dans lequel l'utilisateur choisit les composants de
|
||||
son choix et les depose sur le schema par drag'n drop.
|
||||
*/
|
||||
class PanelAppareils : public QListWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PanelAppareils(QWidget * = 0);
|
||||
public slots:
|
||||
void dragMoveEvent(QDragMoveEvent *);
|
||||
void dropEvent(QDropEvent *);
|
||||
void startDrag(Qt::DropActions);
|
||||
};
|
||||
#endif
|
||||
40
qelectrotech.pro
Normal file
@@ -0,0 +1,40 @@
|
||||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) dim. oct. 8 23:57:43 2006
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
|
||||
# Input
|
||||
HEADERS += aboutqet.h \
|
||||
borne.h \
|
||||
conducteur.h \
|
||||
contacteur.h \
|
||||
del.h \
|
||||
element.h \
|
||||
elementfixe.h \
|
||||
elementperso.h \
|
||||
entree.h \
|
||||
panelappareils.h \
|
||||
qetapp.h \
|
||||
schema.h \
|
||||
schemavue.h
|
||||
SOURCES += aboutqet.cpp \
|
||||
borne.cpp \
|
||||
conducteur.cpp \
|
||||
contacteur.cpp \
|
||||
del.cpp \
|
||||
element.cpp \
|
||||
elementfixe.cpp \
|
||||
elementperso.cpp \
|
||||
entree.cpp \
|
||||
main.cpp \
|
||||
panelappareils.cpp \
|
||||
qetapp.cpp \
|
||||
schema.cpp \
|
||||
schemavue.cpp
|
||||
RESOURCES += qelectrotech.qrc
|
||||
TRANSLATIONS += qet_en.ts
|
||||
QT += xml
|
||||
38
qelectrotech.qrc
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>ico/qet.png</file>
|
||||
<file>ico/qelectrotech.png</file>
|
||||
<file>ico/button_cancel.png</file>
|
||||
<file>ico/button_ok.png</file>
|
||||
<file>ico/configure.png</file>
|
||||
<file>ico/copy.png</file>
|
||||
<file>ico/cut.png</file>
|
||||
<file>ico/delete.png</file>
|
||||
<file>ico/editdelete.png</file>
|
||||
<file>ico/entrer_fs.png</file>
|
||||
<file>ico/exit.png</file>
|
||||
<file>ico/export.png</file>
|
||||
<file>ico/fileclose.png</file>
|
||||
<file>ico/import.png</file>
|
||||
<file>ico/masquer.png</file>
|
||||
<file>ico/move.png</file>
|
||||
<file>ico/new.png</file>
|
||||
<file>ico/open.png</file>
|
||||
<file>ico/paste.png</file>
|
||||
<file>ico/pivoter.png</file>
|
||||
<file>ico/print.png</file>
|
||||
<file>ico/qt.png</file>
|
||||
<file>ico/redo.png</file>
|
||||
<file>ico/restaurer.png</file>
|
||||
<file>ico/saveas.png</file>
|
||||
<file>ico/save.png</file>
|
||||
<file>ico/select.png</file>
|
||||
<file>ico/sortir_fs.png</file>
|
||||
<file>ico/toolbars.png</file>
|
||||
<file>ico/undo.png</file>
|
||||
<file>ico/viewmagfit.png</file>
|
||||
<file>ico/viewmag-.png</file>
|
||||
<file>ico/viewmag.png</file>
|
||||
<file>ico/viewmag+.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
500
qet_en.ts
Normal file
@@ -0,0 +1,500 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS><TS version="1.1" language="en">
|
||||
<context>
|
||||
<name>AboutQET</name>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="18"/>
|
||||
<source>À propos de QElectrotech</source>
|
||||
<translation>About QElectroTech</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="25"/>
|
||||
<source>À &propos</source>
|
||||
<translation>&About</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="26"/>
|
||||
<source>A&uteurs</source>
|
||||
<translation>A&uthors</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="27"/>
|
||||
<source>&Accord de licence</source>
|
||||
<translation>&License Agreement</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="73"/>
|
||||
<source>QElectroTech, une application de réalisation de schémas électriques.
|
||||
|
||||
© 2006 Les développeurs de QElectroTech
|
||||
|
||||
Merde on n'a pas de site web</source>
|
||||
<translation>QElectroTech is a program to design electric schemas.
|
||||
|
||||
© 2006 QElectroTech Developers
|
||||
|
||||
Whoops, we have no website</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="87"/>
|
||||
<source>Idée originale : Benoît Ansieau <benoit.ansieau@gmail.com>
|
||||
|
||||
Programmation : Xavier Guerrin <xavier.guerrin@gmail.com></source>
|
||||
<translation>Original idea : Benoît Ansieau <benoit.ansieau@gmail.com>
|
||||
|
||||
Programming : Xavier Guerrin <xavier.guerrin@gmail.com></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="98"/>
|
||||
<source>Ce programme est sous licence GNU/GPL.</source>
|
||||
<translation>This program is under the GNU/GPL license.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="105"/>
|
||||
<source>Le fichier texte contenant la licence GNU/GPL est introuvable - bon bah de toute façon, vous la connaissez par c&oelig;ur non ?</source>
|
||||
<translation type="unfinished">The text file containing the GNU/GPL license could not be found - however, you know it by heart, don't you ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="aboutqet.cpp" line="109"/>
|
||||
<source>Le fichier texte contenant la licence GNU/GPL existe mais n'a pas pu être ouvert - bon bah de toute façon, vous la connaissez par c&oelig;ur non ?</source>
|
||||
<translation type="unfinished">The text file containing the GNU/GPL license exists but could not be opened - however, you know it by heart, don't you ?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PanelAppareils</name>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="41"/>
|
||||
<source>Ceci est un élément que vous pouvez insérer dans votre schéma par cliquer-déplacer</source>
|
||||
<translation>This is a device you can drag'n drop onto your plan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="42"/>
|
||||
<source>Cliquer-déposez cet élément sur le schéma pour insérer </source>
|
||||
<translation>Drag this device to the plan to insert </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="93"/>
|
||||
<source>Contacteur</source>
|
||||
<translation>Contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="45"/>
|
||||
<source>un contacteur</source>
|
||||
<translation>a contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="94"/>
|
||||
<source>Voyant DEL</source>
|
||||
<translation>LED light</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="51"/>
|
||||
<source>une DEL</source>
|
||||
<translation>a LED light</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="52"/>
|
||||
<source>Diode Electroluminescente</source>
|
||||
<translation>Light-Emitting Diode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="95"/>
|
||||
<source>Entrée</source>
|
||||
<translation>Input</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="panelappareils.cpp" line="57"/>
|
||||
<source>une entrée</source>
|
||||
<translation>an input</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QETApp</name>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="527"/>
|
||||
<source>QElectroTech</source>
|
||||
<translation>QElectroTech</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="29"/>
|
||||
<source>QElectrotech : dimensions de la zone de dessin : </source>
|
||||
<translation type="obsolete">QElectrotech : Size of the drawing area :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="29"/>
|
||||
<source>x</source>
|
||||
<translation type="obsolete">x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="190"/>
|
||||
<source>&Masquer</source>
|
||||
<translation>&Hide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="162"/>
|
||||
<source>&Quitter</source>
|
||||
<translation>&Quit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="191"/>
|
||||
<source>&Restaurer</source>
|
||||
<translation>&Show</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="269"/>
|
||||
<source>&Fichier</source>
|
||||
<translation>&File</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="270"/>
|
||||
<source>&Édition</source>
|
||||
<translation>&Edit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="271"/>
|
||||
<source>Afficha&ge</source>
|
||||
<translation>Displ&ay</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="272"/>
|
||||
<source>O&utils</source>
|
||||
<translation>&Tools</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="273"/>
|
||||
<source>&Configuration</source>
|
||||
<translation>&Settings</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="274"/>
|
||||
<source>&Aide</source>
|
||||
<translation>&Help</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="155"/>
|
||||
<source>&Nouveau</source>
|
||||
<translation>&New</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="156"/>
|
||||
<source>&Ouvrir</source>
|
||||
<translation>&Open</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="157"/>
|
||||
<source>&Enregistrer</source>
|
||||
<translation>&Save</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="411"/>
|
||||
<source>Enregistrer sous</source>
|
||||
<translation>Save as</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="159"/>
|
||||
<source>&Importer</source>
|
||||
<translation>&Import</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="201"/>
|
||||
<source>Ctrl+Shift+I</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="160"/>
|
||||
<source>E&xporter</source>
|
||||
<translation>&Export</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="202"/>
|
||||
<source>Ctrl+Shift+X</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="204"/>
|
||||
<source>Ctrl+Q</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="164"/>
|
||||
<source>Annu&ler</source>
|
||||
<translation>&Undo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="165"/>
|
||||
<source>Re&faire</source>
|
||||
<translation>&Redo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="166"/>
|
||||
<source>Co&uper</source>
|
||||
<translation>Cu&t</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="167"/>
|
||||
<source>Cop&ier</source>
|
||||
<translation>&Copy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="168"/>
|
||||
<source>C&oller</source>
|
||||
<translation>&Paste</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="169"/>
|
||||
<source>Tout sélectionner</source>
|
||||
<translation>Select All</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="170"/>
|
||||
<source>Désélectionner tout</source>
|
||||
<translation>Select none</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="212"/>
|
||||
<source>Ctrl+Shift+A</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="171"/>
|
||||
<source>Inverser la sélection</source>
|
||||
<translation>Invert selection</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="213"/>
|
||||
<source>Ctrl+I</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="185"/>
|
||||
<source>Cacher &la barre d'outils</source>
|
||||
<translation type="obsolete">Hide Too&lbar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="186"/>
|
||||
<source>&Mode plein écran</source>
|
||||
<translation type="obsolete">&Fullscreen Mode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="223"/>
|
||||
<source>Ctrl+Shift+F</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="188"/>
|
||||
<source>Configurer les &barres d'outils</source>
|
||||
<translation type="obsolete">Configure tool&bars</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="185"/>
|
||||
<source>&Configurer QElectroTech</source>
|
||||
<translation type="unfinished">&Configure QElectroTech</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="187"/>
|
||||
<source>À &propos de QElectroTech</source>
|
||||
<translation>A&bout QElectroTech</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="188"/>
|
||||
<source>À propos de &Qt</source>
|
||||
<translation>About &Qt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="320"/>
|
||||
<source>Désactiver l'&antialiasing</source>
|
||||
<translation>Render without &Antialiasing</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="320"/>
|
||||
<source>Activer l'&antialiasing</source>
|
||||
<translation>Render with &Antialiasing</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="23"/>
|
||||
<source>QElectrotech</source>
|
||||
<translation>QElectrotech</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="26"/>
|
||||
<source>Panel d'appareils</source>
|
||||
<translation>Elements Panel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="161"/>
|
||||
<source>Imprimer</source>
|
||||
<translation>Print</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="175"/>
|
||||
<source>Zoom avant</source>
|
||||
<translation>Zoom In</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="176"/>
|
||||
<source>Zoom arrière</source>
|
||||
<translation>Zoom Out</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="177"/>
|
||||
<source>Zoom adapté</source>
|
||||
<translation>Fit in view</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="178"/>
|
||||
<source>Pas de zoom</source>
|
||||
<translation>Reset zoom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="180"/>
|
||||
<source>Mode Selection</source>
|
||||
<translation>Selection Mode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="183"/>
|
||||
<source>Passer en &mode plein écran</source>
|
||||
<translation>F&ullScreen Screen Mode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="184"/>
|
||||
<source>Sortir du &mode plein écran</source>
|
||||
<translation>Exit F&ullScreen Screen Mode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="194"/>
|
||||
<source>Reduire QElectroTech dans le systray</source>
|
||||
<translation>Minimize QElectroTech to the sytray</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="195"/>
|
||||
<source>Restaurer QElectroTech</source>
|
||||
<translation>Restore QElectroTech</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="215"/>
|
||||
<source>P</source>
|
||||
<translation>P</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="219"/>
|
||||
<source>Ctrl+9</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="220"/>
|
||||
<source>Ctrl+0</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="313"/>
|
||||
<source>Afficher</source>
|
||||
<translation>Display</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="344"/>
|
||||
<source>Outils</source>
|
||||
<translation>Tools</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="379"/>
|
||||
<source>Exporter vers le fichier</source>
|
||||
<translation>Export to file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="379"/>
|
||||
<source>Image PNG (*.png)</source>
|
||||
<translation>PNG Picture (*.png)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="414"/>
|
||||
<source>Schema QelectroTech (*.qet)</source>
|
||||
<translation>QElectroTech Schema (*.qet)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="489"/>
|
||||
<source>Erreur</source>
|
||||
<translation>Error</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="437"/>
|
||||
<source>Impossible d'ecrire dans ce fichier</source>
|
||||
<translation>Can't write to the file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="475"/>
|
||||
<source>Ouvrir un fichier</source>
|
||||
<translation>Open a file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="478"/>
|
||||
<source>Schema QelectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*)</source>
|
||||
<translation>QelectroTech Schema (*.qet);;XML Files (*.xml);;All Files (*)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="484"/>
|
||||
<source>Impossible de lire ce fichier</source>
|
||||
<translation>Can't read that file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="489"/>
|
||||
<source>Ce fichier n'est pas un document XML valide.</source>
|
||||
<translation>This file is not a valid XML Document.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="513"/>
|
||||
<source>Enregistrer le schéma en cours ?</source>
|
||||
<translation>Save the current schema ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="514"/>
|
||||
<source>Voulez-vous enregistrer le schéma en cours ?</source>
|
||||
<translation>Do you wish to save the current schema ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="172"/>
|
||||
<source>Supprimer</source>
|
||||
<translation>Delete</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="173"/>
|
||||
<source>Pivoter</source>
|
||||
<translation>Rotate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qetapp.cpp" line="181"/>
|
||||
<source>Mode Visualisation</source>
|
||||
<translation>View Mode</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Schema</name>
|
||||
<message>
|
||||
<location filename="schema.cpp" line="124"/>
|
||||
<source>Contacteur</source>
|
||||
<translation type="obsolete">Contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="schema.cpp" line="126"/>
|
||||
<source>Voyant DEL</source>
|
||||
<translation type="obsolete">LED light</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SchemaVue</name>
|
||||
<message>
|
||||
<location filename="schemavue.cpp" line="191"/>
|
||||
<source>Contacteur</source>
|
||||
<translation>Contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="schemavue.cpp" line="192"/>
|
||||
<source>Voyant DEL</source>
|
||||
<translation>LED light</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="schemavue.cpp" line="193"/>
|
||||
<source>Entrée</source>
|
||||
<translation>Input</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
733
qetapp.cpp
Normal file
@@ -0,0 +1,733 @@
|
||||
#include "qetapp.h"
|
||||
#include "schemavue.h"
|
||||
#include "schema.h"
|
||||
#include "panelappareils.h"
|
||||
#include "aboutqet.h"
|
||||
|
||||
/**
|
||||
constructeur
|
||||
@param parent le widget parent de la fenetre principale
|
||||
*/
|
||||
QETApp::QETApp(QWidget *parent) : QMainWindow(parent) {
|
||||
// mise en place de l'interface MDI au centre de l'application
|
||||
setCentralWidget(&workspace);
|
||||
|
||||
// mise en place du signalmapper
|
||||
connect(&windowMapper, SIGNAL(mapped(QWidget *)), &workspace, SLOT(setActiveWindow(QWidget *)));
|
||||
|
||||
// recupere les arguments passes au programme
|
||||
QStringList args = QCoreApplication::arguments();
|
||||
|
||||
// recupere les chemins de fichiers parmi les arguments
|
||||
QStringList fichiers;
|
||||
for (int i = 1 ; i < args.size() ; ++ i) {
|
||||
if (QFileInfo(args.at(i)).exists()) fichiers << args.at(i);
|
||||
}
|
||||
|
||||
// si des chemins de fichiers valides sont passes en arguments
|
||||
QList<SchemaVue *> schema_vues;
|
||||
if (fichiers.size()) {
|
||||
// alors on ouvre ces fichiers
|
||||
foreach(QString fichier, fichiers) {
|
||||
SchemaVue *sv = new SchemaVue(this);
|
||||
if (sv -> ouvrir(fichier)) schema_vues << sv;
|
||||
else delete sv;
|
||||
}
|
||||
}
|
||||
|
||||
// si aucun schema n'a ete ouvert jusqu'a maintenant, on ouvre un nouveau schema
|
||||
if (!schema_vues.size()) schema_vues << new SchemaVue(this);
|
||||
|
||||
// ajout de tous les SchemaVue necessaires
|
||||
foreach (SchemaVue *sv, schema_vues) addSchemaVue(sv);
|
||||
|
||||
// titre de la fenetre
|
||||
setWindowTitle(tr("QElectroTech"));
|
||||
|
||||
// icone de la fenetre
|
||||
setWindowIcon(QIcon(":/ico/qet.png"));
|
||||
|
||||
// barre de statut de la fenetre
|
||||
statusBar() -> showMessage(tr("QElectrotech"));
|
||||
|
||||
// ajout du panel d'Appareils en tant que QDockWidget
|
||||
qdw_pa = new QDockWidget(tr("Panel d'appareils"), this);
|
||||
qdw_pa -> setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||
qdw_pa -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
qdw_pa -> setMinimumWidth(160);
|
||||
qdw_pa -> setWidget(pa = new PanelAppareils(qdw_pa));
|
||||
addDockWidget(Qt::LeftDockWidgetArea, qdw_pa);
|
||||
|
||||
// mise en place des actions
|
||||
actions();
|
||||
|
||||
// mise en place de la barre d'outils
|
||||
toolbar();
|
||||
|
||||
// mise en place des menus
|
||||
menus();
|
||||
|
||||
// systray de l'application
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
qsti = new QSystemTrayIcon(QIcon(":/ico/qet.png"), this);
|
||||
qsti -> setToolTip(tr("QElectroTech"));
|
||||
connect(qsti, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(systray(QSystemTrayIcon::ActivationReason)));
|
||||
menu_systray = new QMenu(tr("QElectroTech"));
|
||||
menu_systray -> addAction(masquer_appli);
|
||||
menu_systray -> addAction(quitter_qet);
|
||||
qsti -> setContextMenu(menu_systray);
|
||||
qsti -> show();
|
||||
}
|
||||
|
||||
// la fenetre est maximisee par defaut
|
||||
setMinimumWidth(500);
|
||||
setMinimumHeight(350);
|
||||
setWindowState(Qt::WindowMaximized);
|
||||
|
||||
// connexions signaux / slots pour une interface sensee
|
||||
connect(&workspace, SIGNAL(windowActivated(QWidget *)), this, SLOT(slot_updateActions()));
|
||||
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slot_updateActions()));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les evenements relatifs au QSystemTrayIcon
|
||||
@param raison un entier representant l'evenement survenu sur le systray
|
||||
*/
|
||||
void QETApp::systray(QSystemTrayIcon::ActivationReason raison) {
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable()) return;
|
||||
switch(raison) {
|
||||
case QSystemTrayIcon::Context:
|
||||
// affichage du menu
|
||||
(qsti -> contextMenu()) -> show();
|
||||
break;
|
||||
case QSystemTrayIcon::DoubleClick:
|
||||
case QSystemTrayIcon::Trigger:
|
||||
// reduction ou restauration de l'application
|
||||
if (isVisible()) systrayReduire(); else systrayRestaurer();
|
||||
break;
|
||||
case QSystemTrayIcon::Unknown:
|
||||
default: // ne rien faire
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reduit l'application dans le systray
|
||||
*/
|
||||
void QETApp::systrayReduire() {
|
||||
// on sauvegarde la position et les dimensions de l'application
|
||||
wg = saveGeometry();
|
||||
// on cache l'application
|
||||
hide();
|
||||
// on ajoute le menu "Restaurer" et on enlève le menu "Masquer"
|
||||
menu_systray -> insertAction(masquer_appli, restaurer_appli);
|
||||
menu_systray -> removeAction(masquer_appli);
|
||||
}
|
||||
|
||||
/**
|
||||
Restaure l'application reduite dans le systray
|
||||
*/
|
||||
void QETApp::systrayRestaurer() {
|
||||
// on restaure la position et les dimensions de l'application
|
||||
restoreGeometry(wg);
|
||||
// on affiche l'application
|
||||
show();
|
||||
// on ajoute le menu "Masquer" et on enlève le menu "Restaurer"
|
||||
menu_systray -> insertAction(restaurer_appli, masquer_appli);
|
||||
menu_systray -> removeAction(restaurer_appli);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de quitter l'application lors de la fermeture de la fenetre principale
|
||||
*/
|
||||
void QETApp::closeEvent(QCloseEvent *) {
|
||||
quitter();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere la sortie de l'application
|
||||
@todo gerer les eventuelles fermetures de fichiers
|
||||
*/
|
||||
void QETApp::quitter() {
|
||||
if (!schemaEnCours()) qApp -> quit();
|
||||
else {
|
||||
bool peut_quitter = true;
|
||||
foreach(QWidget *fenetre, workspace.windowList()) {
|
||||
if (qobject_cast<SchemaVue *>(fenetre)) {
|
||||
workspace.setActiveWindow(fenetre);
|
||||
if (!fermer()) {
|
||||
peut_quitter = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peut_quitter) qApp -> quit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Fait passer la fenetre en mode plein ecran au mode normal et vice-versa
|
||||
*/
|
||||
void QETApp::toggleFullScreen() {
|
||||
setWindowState(windowState() ^ Qt::WindowFullScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
Active ou desactive l'antialiasing sur le rendu graphique du Schema
|
||||
*/
|
||||
void QETApp::toggleAntialiasing() {
|
||||
SchemaVue *sv = schemaEnCours();
|
||||
if (!sv) return;
|
||||
sv -> setAntialiasing(!sv -> antialiased());
|
||||
toggle_aa -> setText(sv -> antialiased() ? tr("D\351sactiver l'&antialiasing") : tr("Activer l'&antialiasing"));
|
||||
}
|
||||
|
||||
/**
|
||||
Dialogue « A propos de QElectroTech »
|
||||
Le dialogue en question est cree lors du premier appel de cette fonction.
|
||||
En consequence, sa premiere apparition n'est pas immediate. Par la suite,
|
||||
le dialogue n'a pas a etre recree et il apparait instantanement. Il est
|
||||
detruit en meme temps que son parent (ici, la QETApp).
|
||||
*/
|
||||
void QETApp::aPropos() {
|
||||
static AboutQET *apqet = new AboutQET(this);
|
||||
apqet -> exec();
|
||||
}
|
||||
|
||||
/**
|
||||
Mise en place des actions
|
||||
*/
|
||||
void QETApp::actions() {
|
||||
// icones et labels
|
||||
nouveau_fichier = new QAction(QIcon(":/ico/new.png"), tr("&Nouveau"), this);
|
||||
ouvrir_fichier = new QAction(QIcon(":/ico/open.png"), tr("&Ouvrir"), this);
|
||||
fermer_fichier = new QAction(QIcon(":/ico/fileclose.png"), tr("&Fermer"), this);
|
||||
enr_fichier = new QAction(QIcon(":/ico/save.png"), tr("&Enregistrer"), this);
|
||||
enr_fichier_sous = new QAction(QIcon(":/ico/saveas.png"), tr("Enregistrer sous"), this);
|
||||
importer = new QAction(QIcon(":/ico/import.png"), tr("&Importer"), this);
|
||||
exporter = new QAction(QIcon(":/ico/export.png"), tr("E&xporter"), this);
|
||||
imprimer = new QAction(QIcon(":/ico/print.png"), tr("Imprimer"), this);
|
||||
quitter_qet = new QAction(QIcon(":/ico/exit.png"), tr("&Quitter"), this);
|
||||
|
||||
annuler = new QAction(QIcon(":/ico/undo.png"), tr("Annu&ler"), this);
|
||||
refaire = new QAction(QIcon(":/ico/redo.png"), tr("Re&faire"), this);
|
||||
couper = new QAction(QIcon(":/ico/cut.png"), tr("Co&uper"), this);
|
||||
copier = new QAction(QIcon(":/ico/copy.png"), tr("Cop&ier"), this);
|
||||
coller = new QAction(QIcon(":/ico/paste.png"), tr("C&oller"), this);
|
||||
sel_tout = new QAction( tr("Tout s\351lectionner"), this);
|
||||
sel_rien = new QAction( tr("D\351s\351lectionner tout"), this);
|
||||
sel_inverse = new QAction( tr("Inverser la s\351lection"), this);
|
||||
supprimer = new QAction(QIcon(":/ico/delete.png"), tr("Supprimer"), this);
|
||||
pivoter = new QAction(QIcon(":/ico/pivoter.png"), tr("Pivoter"), this);
|
||||
|
||||
toggle_aa = new QAction( tr("D\351sactiver l'&antialiasing"), this);
|
||||
zoom_avant = new QAction(QIcon(":/ico/viewmag+.png"), tr("Zoom avant"), this);
|
||||
zoom_arriere = new QAction(QIcon(":/ico/viewmag-.png"), tr("Zoom arri\350re"), this);
|
||||
zoom_adapte = new QAction(QIcon(":/ico/viewmagfit.png"), tr("Zoom adapt\351"), this);
|
||||
zoom_reset = new QAction(QIcon(":/ico/viewmag.png"), tr("Pas de zoom"), this);
|
||||
|
||||
mode_selection = new QAction(QIcon(":/ico/select.png"), tr("Mode Selection"), this);
|
||||
mode_visualise = new QAction(QIcon(":/ico/move.png"), tr("Mode Visualisation"), this);
|
||||
|
||||
entrer_pe = new QAction(QIcon(":/ico/entrer_fs.png"), tr("Passer en &mode plein \351cran"), this);
|
||||
sortir_pe = new QAction(QIcon(":/ico/sortir_fs.png"), tr("Sortir du &mode plein \351cran"), this);
|
||||
configurer = new QAction(QIcon(":/ico/configure.png"), tr("&Configurer QElectroTech"), this);
|
||||
|
||||
f_mosaique = new QAction( tr("&Mosa\357que"), this);
|
||||
f_cascade = new QAction( tr("&Cascade"), this);
|
||||
f_reorganise = new QAction( tr("Arranger les fen\352tres réduites"),this);
|
||||
f_suiv = new QAction( tr("Fen\352tre suivante"), this);
|
||||
f_prec = new QAction( tr("Fen\352tre pr\351c\351dente"), this);
|
||||
|
||||
a_propos_de_qet = new QAction(QIcon(":/ico/qet.png"), tr("\300 &propos de QElectroTech"), this);
|
||||
a_propos_de_qt = new QAction(QIcon(":/ico/qt.png"), tr("\300 propos de &Qt"), this);
|
||||
|
||||
masquer_appli = new QAction(QIcon(":/ico/masquer.png"), tr("&Masquer"), this);
|
||||
restaurer_appli = new QAction(QIcon(":/ico/restaurer.png"), tr("&Restaurer"), this);
|
||||
|
||||
// info-bulles / indications dans la barre de statut
|
||||
masquer_appli -> setToolTip(tr("Reduire QElectroTech dans le systray"));
|
||||
restaurer_appli -> setToolTip(tr("Restaurer QElectroTech"));
|
||||
|
||||
// raccourcis clavier
|
||||
nouveau_fichier -> setShortcut(QKeySequence::New);
|
||||
ouvrir_fichier -> setShortcut(QKeySequence::Open);
|
||||
fermer_fichier -> setShortcut(QKeySequence::Close);
|
||||
enr_fichier -> setShortcut(QKeySequence::Save);
|
||||
importer -> setShortcut(QKeySequence(tr("Ctrl+Shift+I")));
|
||||
exporter -> setShortcut(QKeySequence(tr("Ctrl+Shift+X")));
|
||||
imprimer -> setShortcut(QKeySequence(QKeySequence::Print));
|
||||
quitter_qet -> setShortcut(QKeySequence(tr("Ctrl+Q")));
|
||||
|
||||
annuler -> setShortcut(QKeySequence::Undo);
|
||||
refaire -> setShortcut(QKeySequence::Redo);
|
||||
couper -> setShortcut(QKeySequence::Cut);
|
||||
copier -> setShortcut(QKeySequence::Copy);
|
||||
coller -> setShortcut(QKeySequence::Paste);
|
||||
sel_tout -> setShortcut(QKeySequence::SelectAll);
|
||||
sel_rien -> setShortcut(QKeySequence(tr("Ctrl+Shift+A")));
|
||||
sel_inverse -> setShortcut(QKeySequence(tr("Ctrl+I")));
|
||||
supprimer -> setShortcut(QKeySequence::Delete);
|
||||
pivoter -> setShortcut(QKeySequence(tr("P")));
|
||||
|
||||
zoom_avant -> setShortcut(QKeySequence::ZoomIn);
|
||||
zoom_arriere -> setShortcut(QKeySequence::ZoomOut);
|
||||
zoom_adapte -> setShortcut(QKeySequence(tr("Ctrl+9")));
|
||||
zoom_reset -> setShortcut(QKeySequence(tr("Ctrl+0")));
|
||||
|
||||
entrer_pe -> setShortcut(QKeySequence(tr("Ctrl+Shift+F")));
|
||||
sortir_pe -> setShortcut(QKeySequence(tr("Ctrl+Shift+F")));
|
||||
|
||||
//
|
||||
f_mosaique -> setStatusTip(tr("Dispose les fen\352tres en mosa\357que"));
|
||||
f_cascade -> setStatusTip(tr("Dispose les fen\352tres en cascade"));
|
||||
f_reorganise -> setStatusTip(tr("Aligne les fen\352tres réduites"));
|
||||
f_suiv -> setStatusTip(tr("Active la fen\352tre suivante"));
|
||||
f_prec -> setStatusTip(tr("Active la fen\352tre pr\351c\351dente"));
|
||||
|
||||
// traitements speciaux
|
||||
mode_selection -> setCheckable(true);
|
||||
mode_visualise -> setCheckable(true);
|
||||
mode_selection -> setChecked(true);
|
||||
|
||||
QActionGroup *grp_visu_sel = new QActionGroup(this);
|
||||
grp_visu_sel -> addAction(mode_selection);
|
||||
grp_visu_sel -> addAction(mode_visualise);
|
||||
grp_visu_sel -> setExclusive(true);
|
||||
|
||||
// connexion a des slots
|
||||
connect(quitter_qet, SIGNAL(triggered()), this, SLOT(quitter()) );
|
||||
connect(sel_tout, SIGNAL(triggered()), this, SLOT(slot_selectAll()) );
|
||||
connect(sel_rien, SIGNAL(triggered()), this, SLOT(slot_selectNothing()) );
|
||||
connect(sel_inverse, SIGNAL(triggered()), this, SLOT(slot_selectInvert()) );
|
||||
connect(supprimer, SIGNAL(triggered()), this, SLOT(slot_supprimer()) );
|
||||
connect(pivoter, SIGNAL(triggered()), this, SLOT(slot_pivoter()) );
|
||||
connect(entrer_pe, SIGNAL(triggered()), this, SLOT(toggleFullScreen()) );
|
||||
connect(sortir_pe, SIGNAL(triggered()), this, SLOT(toggleFullScreen()) );
|
||||
connect(mode_selection, SIGNAL(triggered()), this, SLOT(slot_setSelectionMode()) );
|
||||
connect(mode_visualise, SIGNAL(triggered()), this, SLOT(slot_setVisualisationMode()));
|
||||
connect(a_propos_de_qet, SIGNAL(triggered()), this, SLOT(aPropos()) );
|
||||
connect(a_propos_de_qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()) );
|
||||
connect(masquer_appli, SIGNAL(triggered()), this, SLOT(systrayReduire ()) );
|
||||
connect(restaurer_appli, SIGNAL(triggered()), this, SLOT(systrayRestaurer()) );
|
||||
connect(zoom_avant, SIGNAL(triggered()), this, SLOT(slot_zoomPlus()) );
|
||||
connect(zoom_arriere, SIGNAL(triggered()), this, SLOT(slot_zoomMoins()) );
|
||||
connect(zoom_adapte, SIGNAL(triggered()), this, SLOT(slot_zoomFit()) );
|
||||
connect(zoom_reset, SIGNAL(triggered()), this, SLOT(slot_zoomReset()) );
|
||||
connect(imprimer, SIGNAL(triggered()), this, SLOT(dialogue_imprimer()) );
|
||||
connect(exporter, SIGNAL(triggered()), this, SLOT(dialogue_exporter()) );
|
||||
connect(enr_fichier_sous, SIGNAL(triggered()), this, SLOT(dialogue_enregistrer_sous()));
|
||||
connect(enr_fichier, SIGNAL(triggered()), this, SLOT(enregistrer()) );
|
||||
connect(nouveau_fichier, SIGNAL(triggered()), this, SLOT(nouveau()) );
|
||||
connect(ouvrir_fichier, SIGNAL(triggered()), this, SLOT(ouvrir()) );
|
||||
connect(fermer_fichier, SIGNAL(triggered()), this, SLOT(fermer()) );
|
||||
connect(couper, SIGNAL(triggered()), this, SLOT(slot_couper()) );
|
||||
connect(copier, SIGNAL(triggered()), this, SLOT(slot_copier()) );
|
||||
connect(coller, SIGNAL(triggered()), this, SLOT(slot_coller()) );
|
||||
connect(toggle_aa, SIGNAL(triggered()), this, SLOT(toggleAntialiasing()) );
|
||||
connect(f_mosaique, SIGNAL(triggered()), &workspace, SLOT(tile()));
|
||||
connect(f_cascade, SIGNAL(triggered()), &workspace, SLOT(cascade()));
|
||||
connect(f_reorganise, SIGNAL(triggered()), &workspace, SLOT(arrangeIcons()));
|
||||
connect(f_suiv, SIGNAL(triggered()), &workspace, SLOT(activateNextWindow()));
|
||||
connect(f_prec, SIGNAL(triggered()), &workspace, SLOT(activatePreviousWindow()));
|
||||
}
|
||||
|
||||
/**
|
||||
Mise en place des menus
|
||||
*/
|
||||
void QETApp::menus() {
|
||||
QMenu *menu_fichier = menuBar() -> addMenu(tr("&Fichier"));
|
||||
QMenu *menu_edition = menuBar() -> addMenu(tr("&\311dition"));
|
||||
QMenu *menu_affichage = menuBar() -> addMenu(tr("Afficha&ge"));
|
||||
QMenu *menu_outils = menuBar() -> addMenu(tr("O&utils"));
|
||||
QMenu *menu_config = menuBar() -> addMenu(tr("&Configuration"));
|
||||
menu_fenetres = menuBar() -> addMenu(tr("Fe&n\352tres"));
|
||||
QMenu *menu_aide = menuBar() -> addMenu(tr("&Aide"));
|
||||
|
||||
// tear off feature rulezz... pas ^^ mais bon...
|
||||
menu_fichier -> setTearOffEnabled(true);
|
||||
menu_edition -> setTearOffEnabled(true);
|
||||
menu_affichage -> setTearOffEnabled(true);
|
||||
menu_outils -> setTearOffEnabled(true);
|
||||
menu_config -> setTearOffEnabled(true);
|
||||
menu_aide -> setTearOffEnabled(true);
|
||||
|
||||
// menu Fichier
|
||||
menu_fichier -> addAction(nouveau_fichier);
|
||||
menu_fichier -> addAction(ouvrir_fichier);
|
||||
menu_fichier -> addAction(enr_fichier);
|
||||
menu_fichier -> addAction(enr_fichier_sous);
|
||||
menu_fichier -> addAction(fermer_fichier);
|
||||
menu_fichier -> addSeparator();
|
||||
menu_fichier -> addAction(importer);
|
||||
menu_fichier -> addAction(exporter);
|
||||
menu_fichier -> addSeparator();
|
||||
menu_fichier -> addAction(imprimer);
|
||||
menu_fichier -> addSeparator();
|
||||
menu_fichier -> addAction(quitter_qet);
|
||||
|
||||
// menu Edition
|
||||
menu_edition -> addAction(annuler);
|
||||
menu_edition -> addAction(refaire);
|
||||
menu_edition -> addSeparator();
|
||||
menu_edition -> addAction(couper);
|
||||
menu_edition -> addAction(copier);
|
||||
menu_edition -> addAction(coller);
|
||||
menu_edition -> addSeparator();
|
||||
menu_edition -> addAction(sel_tout);
|
||||
menu_edition -> addAction(sel_rien);
|
||||
menu_edition -> addAction(sel_inverse);
|
||||
menu_edition -> addSeparator();
|
||||
menu_edition -> addAction(supprimer);
|
||||
menu_edition -> addAction(pivoter);
|
||||
|
||||
// menu Affichage > Afficher
|
||||
QMenu *menu_aff_aff = new QMenu(tr("Afficher"));
|
||||
menu_aff_aff -> addAction(barre_outils -> toggleViewAction());
|
||||
menu_aff_aff -> addAction(qdw_pa -> toggleViewAction());
|
||||
|
||||
// menu Affichage
|
||||
menu_affichage -> addMenu(menu_aff_aff);
|
||||
menu_affichage -> addSeparator();
|
||||
menu_affichage -> addAction(toggle_aa);
|
||||
menu_affichage -> addSeparator();
|
||||
menu_affichage -> addAction(zoom_avant);
|
||||
menu_affichage -> addAction(zoom_arriere);
|
||||
menu_affichage -> addAction(zoom_adapte);
|
||||
menu_affichage -> addAction(zoom_reset);
|
||||
|
||||
// menu Outils
|
||||
menu_outils -> addAction(mode_selection);
|
||||
menu_outils -> addAction(mode_visualise);
|
||||
|
||||
// menu Configuration
|
||||
menu_config -> addAction(entrer_pe);
|
||||
menu_config -> addAction(configurer);
|
||||
|
||||
// menu Fenêtres
|
||||
slot_updateMenuFenetres();
|
||||
|
||||
// menu Aide
|
||||
menu_aide -> addAction(a_propos_de_qet);
|
||||
menu_aide -> addAction(a_propos_de_qt);
|
||||
}
|
||||
|
||||
/**
|
||||
Mise en place de la barre d'outils
|
||||
*/
|
||||
void QETApp::toolbar() {
|
||||
barre_outils = new QToolBar(tr("Outils"), this);
|
||||
|
||||
// Modes selection / visualisation
|
||||
barre_outils -> addAction(mode_selection);
|
||||
barre_outils -> addAction(mode_visualise);
|
||||
barre_outils -> addSeparator();
|
||||
barre_outils -> addAction(annuler);
|
||||
barre_outils -> addAction(refaire);
|
||||
barre_outils -> addSeparator();
|
||||
barre_outils -> addAction(couper);
|
||||
barre_outils -> addAction(copier);
|
||||
barre_outils -> addAction(coller);
|
||||
barre_outils -> addSeparator();
|
||||
barre_outils -> addAction(supprimer);
|
||||
barre_outils -> addAction(pivoter);
|
||||
barre_outils -> addSeparator();
|
||||
barre_outils -> addAction(zoom_avant);
|
||||
barre_outils -> addAction(zoom_arriere);
|
||||
barre_outils -> addAction(zoom_adapte);
|
||||
barre_outils -> addAction(zoom_reset);
|
||||
|
||||
// ajout de la barre d'outils a la fenetre principale
|
||||
addToolBar(Qt::TopToolBarArea, barre_outils);
|
||||
}
|
||||
|
||||
/**
|
||||
gere l'impression
|
||||
*/
|
||||
void QETApp::dialogue_imprimer() {
|
||||
QPrinter *qprin = new QPrinter();
|
||||
QPrintDialog *qpd = new QPrintDialog(qprin, this);
|
||||
qpd -> exec();
|
||||
}
|
||||
|
||||
void QETApp::dialogue_exporter() {
|
||||
QString nom_fichier = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Exporter vers le fichier"),
|
||||
QDir::homePath(),
|
||||
tr("Image PNG (*.png)")
|
||||
);
|
||||
if (nom_fichier != "") {
|
||||
if (!nom_fichier.endsWith(".png", Qt::CaseInsensitive)) nom_fichier += ".png";
|
||||
QFile fichier(nom_fichier);
|
||||
QImage image = schemaEnCours() -> scene -> toImage();
|
||||
image.save(&fichier, "PNG");
|
||||
fichier.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Methode enregistrant le schema dans le dernier nom de fichier connu.
|
||||
Si aucun nom de fichier n'est connu, cette methode appelle la methode enregistrer_sous
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
*/
|
||||
bool QETApp::enregistrer() {
|
||||
if (!schemaEnCours()) return(false);
|
||||
return(schemaEnCours() -> enregistrer());
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode demande un nom de fichier a l'utilisateur pour enregistrer le schema
|
||||
Si aucun nom n'est entre, elle renvoie faux.
|
||||
Si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee.
|
||||
Si l'enregistrement reussit, le nom du fichier est conserve et la fonction renvoie true.
|
||||
Sinon, faux est renvoye.
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
@todo detecter le chemin du bureau automatiquement
|
||||
*/
|
||||
bool QETApp::dialogue_enregistrer_sous() {
|
||||
if (!schemaEnCours()) return(false);
|
||||
return(schemaEnCours() -> enregistrer_sous());
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode cree un nouveau schema.
|
||||
@return true si tout s'est bien passe ; false si vous executez cette fonction dans un univers non cartesien (en fait y'a pas de return(false) :p)
|
||||
*/
|
||||
bool QETApp::nouveau() {
|
||||
addSchemaVue(new SchemaVue(this));
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Cette fonction demande un nom de fichier a ouvrir a l'utilisateur
|
||||
@return true si l'ouverture a reussi, false sinon
|
||||
*/
|
||||
bool QETApp::ouvrir() {
|
||||
// demande un nom de fichier a ouvrir a l'utilisateur
|
||||
QString nom_fichier = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
tr("Ouvrir un fichier"),
|
||||
QDir::homePath(),
|
||||
tr("Schema QelectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*)")
|
||||
);
|
||||
if (nom_fichier == "") return(false);
|
||||
|
||||
// verifie que le fichier n'est pas deja ouvert
|
||||
QString chemin_fichier = QFileInfo(nom_fichier).canonicalFilePath();
|
||||
foreach (QWidget *fenetre, workspace.windowList()) {
|
||||
SchemaVue *fenetre_en_cours = qobject_cast<SchemaVue *>(fenetre);
|
||||
if (QFileInfo(fenetre_en_cours -> nom_fichier).canonicalFilePath() == chemin_fichier) {
|
||||
workspace.setActiveWindow(fenetre);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
// ouvre le fichier
|
||||
SchemaVue *sv = new SchemaVue(this);
|
||||
int code_erreur;
|
||||
if (sv -> ouvrir(nom_fichier, &code_erreur)) {
|
||||
addSchemaVue(sv);
|
||||
return(true);
|
||||
} else {
|
||||
QString message_erreur;
|
||||
switch(code_erreur) {
|
||||
case 1: message_erreur = tr("Ce fichier n'existe pas."); break;
|
||||
case 2: message_erreur = tr("Impossible de lire ce fichier."); break;
|
||||
case 3: message_erreur = tr("Ce fichier n'est pas un document XML valide."); break;
|
||||
case 4: message_erreur = tr("Une erreur s'est produite lors de l'ouverture du fichier."); break;
|
||||
}
|
||||
QMessageBox::warning(this, tr("Erreur"), message_erreur);
|
||||
delete sv;
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Ferme le document courant
|
||||
@return true si la fermeture du fichier a reussi, false sinon
|
||||
@todo detecter les modifications et ne demander que si besoin est
|
||||
*/
|
||||
bool QETApp::fermer() {
|
||||
SchemaVue *sv = schemaEnCours();
|
||||
if (!sv) return(false);
|
||||
bool fermeture_schema = sv -> close();
|
||||
if (fermeture_schema) delete sv;
|
||||
return(fermeture_schema);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le SchemaVue qui a le focus dans l'interface MDI
|
||||
*/
|
||||
SchemaVue *QETApp::schemaEnCours() {
|
||||
return(qobject_cast<SchemaVue *>(workspace.activeWindow()));
|
||||
}
|
||||
|
||||
void QETApp::slot_couper() {
|
||||
if(schemaEnCours()) schemaEnCours() -> couper();
|
||||
}
|
||||
|
||||
void QETApp::slot_copier() {
|
||||
if(schemaEnCours()) schemaEnCours() -> copier();
|
||||
}
|
||||
|
||||
void QETApp::slot_coller() {
|
||||
if(schemaEnCours()) schemaEnCours() -> coller();
|
||||
}
|
||||
|
||||
void QETApp::slot_zoomPlus() {
|
||||
if(schemaEnCours()) schemaEnCours() -> zoomPlus();
|
||||
}
|
||||
|
||||
void QETApp::slot_zoomMoins() {
|
||||
if(schemaEnCours()) schemaEnCours() -> zoomMoins();
|
||||
}
|
||||
|
||||
void QETApp::slot_zoomFit() {
|
||||
if(schemaEnCours()) schemaEnCours() -> zoomFit();
|
||||
}
|
||||
|
||||
void QETApp::slot_zoomReset() {
|
||||
if(schemaEnCours()) schemaEnCours() -> zoomReset();
|
||||
}
|
||||
|
||||
void QETApp::slot_selectAll() {
|
||||
if(schemaEnCours()) schemaEnCours() -> selectAll();
|
||||
}
|
||||
|
||||
void QETApp::slot_selectNothing() {
|
||||
if(schemaEnCours()) schemaEnCours() -> selectNothing();
|
||||
}
|
||||
|
||||
void QETApp::slot_selectInvert() {
|
||||
if(schemaEnCours()) schemaEnCours() -> selectInvert();
|
||||
}
|
||||
|
||||
void QETApp::slot_supprimer() {
|
||||
if(schemaEnCours()) schemaEnCours() -> supprimer();
|
||||
}
|
||||
|
||||
void QETApp::slot_pivoter() {
|
||||
if(schemaEnCours()) schemaEnCours() -> pivoter();
|
||||
}
|
||||
|
||||
void QETApp::slot_setSelectionMode() {
|
||||
if(schemaEnCours()) schemaEnCours() -> setSelectionMode();
|
||||
}
|
||||
|
||||
void QETApp::slot_setVisualisationMode() {
|
||||
if(schemaEnCours()) schemaEnCours() -> setVisualisationMode();
|
||||
}
|
||||
|
||||
/**
|
||||
gere les actions ayant besoin d'un document ouvert
|
||||
*/
|
||||
void QETApp::slot_updateActions() {
|
||||
SchemaVue *sv = schemaEnCours();
|
||||
bool document_ouvert = (sv != 0);
|
||||
|
||||
// actions ayant juste besoin d'un document ouvert
|
||||
fermer_fichier -> setEnabled(document_ouvert);
|
||||
enr_fichier -> setEnabled(document_ouvert);
|
||||
enr_fichier_sous -> setEnabled(document_ouvert);
|
||||
importer -> setEnabled(document_ouvert);
|
||||
exporter -> setEnabled(document_ouvert);
|
||||
imprimer -> setEnabled(document_ouvert);
|
||||
sel_tout -> setEnabled(document_ouvert);
|
||||
sel_rien -> setEnabled(document_ouvert);
|
||||
sel_inverse -> setEnabled(document_ouvert);
|
||||
zoom_avant -> setEnabled(document_ouvert);
|
||||
zoom_arriere -> setEnabled(document_ouvert);
|
||||
zoom_adapte -> setEnabled(document_ouvert);
|
||||
zoom_reset -> setEnabled(document_ouvert);
|
||||
toggle_aa -> setEnabled(document_ouvert);
|
||||
|
||||
// actions ayant aussi besoin d'un historique des actions
|
||||
annuler -> setEnabled(document_ouvert);
|
||||
refaire -> setEnabled(document_ouvert);
|
||||
|
||||
// actions ayant aussi besoin d'elements selectionnes
|
||||
bool elements_selectionnes = document_ouvert ? (sv -> scene -> selectedItems().size() > 0) : false;
|
||||
couper -> setEnabled(elements_selectionnes);
|
||||
copier -> setEnabled(elements_selectionnes);
|
||||
supprimer -> setEnabled(elements_selectionnes);
|
||||
pivoter -> setEnabled(elements_selectionnes);
|
||||
|
||||
// action ayant aussi besoin d'un presse-papier plein
|
||||
bool peut_coller = QApplication::clipboard() -> text() != QString();
|
||||
coller -> setEnabled(document_ouvert && peut_coller);
|
||||
|
||||
// actions ayant aussi besoin d'un document ouvert et de la connaissance de son mode
|
||||
if (!document_ouvert) {
|
||||
mode_selection -> setEnabled(false);
|
||||
mode_visualise -> setEnabled(false);
|
||||
} else {
|
||||
switch((int)(sv -> dragMode())) {
|
||||
case QGraphicsView::NoDrag:
|
||||
mode_selection -> setEnabled(false);
|
||||
mode_visualise -> setEnabled(false);
|
||||
break;
|
||||
case QGraphicsView::ScrollHandDrag:
|
||||
mode_selection -> setEnabled(true);
|
||||
mode_visualise -> setEnabled(true);
|
||||
mode_selection -> setChecked(false);
|
||||
mode_visualise -> setChecked(true);
|
||||
break;
|
||||
case QGraphicsView::RubberBandDrag:
|
||||
mode_selection -> setEnabled(true);
|
||||
mode_visualise -> setEnabled(true);
|
||||
mode_selection -> setChecked(true);
|
||||
mode_visualise -> setChecked(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// actions ayant besoin de la connaissance de son mode
|
||||
if (document_ouvert) toggle_aa -> setText(sv -> antialiased() ? tr("D\351sactiver l'&antialiasing") : tr("Activer l'&antialiasing"));
|
||||
|
||||
slot_updateMenuFenetres();
|
||||
}
|
||||
|
||||
void QETApp::addSchemaVue(SchemaVue *sv) {
|
||||
if (!sv) return;
|
||||
SchemaVue *s_v = schemaEnCours();
|
||||
bool maximise = ((!s_v) || (s_v -> windowState() & Qt::WindowMaximized));
|
||||
QWidget *p = workspace.addWindow(sv);
|
||||
connect(sv, SIGNAL(selectionChanged()), this, SLOT(slot_updateActions()));
|
||||
connect(sv, SIGNAL(modeChanged()), this, SLOT(slot_updateActions()));
|
||||
if (maximise) p -> showMaximized();
|
||||
else p -> show();
|
||||
}
|
||||
|
||||
void QETApp::slot_updateMenuFenetres() {
|
||||
// nettoyage du menu
|
||||
menu_fenetres -> clear();
|
||||
|
||||
// actions de fermeture
|
||||
menu_fenetres -> addAction(fermer_fichier);
|
||||
//menu_fenetres -> addAction(closeAllAct);
|
||||
|
||||
// actions de reorganisation des fenetres
|
||||
menu_fenetres -> addSeparator();
|
||||
menu_fenetres -> addAction(f_mosaique);
|
||||
menu_fenetres -> addAction(f_cascade);
|
||||
menu_fenetres -> addAction(f_reorganise);
|
||||
|
||||
// actiosn de deplacement entre les fenetres
|
||||
menu_fenetres -> addSeparator();
|
||||
menu_fenetres -> addAction(f_suiv);
|
||||
menu_fenetres -> addAction(f_prec);
|
||||
|
||||
// liste des fenetres
|
||||
QList<QWidget *> fenetres = workspace.windowList();
|
||||
if (!fenetres.isEmpty()) menu_fenetres -> addSeparator();
|
||||
for (int i = 0 ; i < fenetres.size() ; ++ i) {
|
||||
SchemaVue *sv = qobject_cast<SchemaVue *>(fenetres.at(i));
|
||||
QAction *action = menu_fenetres -> addAction(sv -> windowTitle().left(sv -> windowTitle().length()-3));
|
||||
action -> setCheckable(true);
|
||||
action -> setChecked(sv == schemaEnCours());
|
||||
connect(action, SIGNAL(triggered()), &windowMapper, SLOT(map()));
|
||||
windowMapper.setMapping(action, sv);
|
||||
}
|
||||
}
|
||||
122
qetapp.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef QETAPP_H
|
||||
#define QETAPP_H
|
||||
#include <QtGui>
|
||||
class SchemaVue;
|
||||
class PanelAppareils;
|
||||
/**
|
||||
Cette classe represente la fenetre principale de QElectroTech et,
|
||||
ipso facto, la plus grande partie de l'interface graphique de QElectroTech.
|
||||
Il s'agit d'un objet QMainWindow avec un objet « Schema » en guise de widget central
|
||||
et un « Panel d'Appareils » en guise de widget « Dock ».
|
||||
*/
|
||||
class QETApp : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
QETApp(QWidget *parent=0);
|
||||
void closeEvent(QCloseEvent * event );
|
||||
void addSchemaVue(SchemaVue *);
|
||||
|
||||
public slots:
|
||||
void systray(QSystemTrayIcon::ActivationReason raison);
|
||||
void systrayReduire();
|
||||
void systrayRestaurer();
|
||||
void quitter();
|
||||
void toggleFullScreen();
|
||||
void toggleAntialiasing();
|
||||
void aPropos();
|
||||
void dialogue_imprimer();
|
||||
void dialogue_exporter();
|
||||
bool dialogue_enregistrer_sous();
|
||||
bool enregistrer();
|
||||
bool nouveau();
|
||||
bool ouvrir();
|
||||
bool fermer();
|
||||
|
||||
protected:
|
||||
// Actions faisables au travers de menus dans l'application QElectroTech
|
||||
QAction *mode_selection;
|
||||
QAction *mode_visualise;
|
||||
QAction *nouveau_fichier;
|
||||
QAction *ouvrir_fichier;
|
||||
QAction *fermer_fichier;
|
||||
QAction *enr_fichier;
|
||||
QAction *enr_fichier_sous;
|
||||
QAction *importer;
|
||||
QAction *exporter;
|
||||
QAction *imprimer;
|
||||
QAction *quitter_qet;
|
||||
QAction *annuler;
|
||||
QAction *refaire;
|
||||
QAction *couper;
|
||||
QAction *copier;
|
||||
QAction *coller;
|
||||
QAction *sel_tout;
|
||||
QAction *sel_rien;
|
||||
QAction *sel_inverse;
|
||||
QAction *supprimer;
|
||||
QAction *selectionner;
|
||||
QAction *pivoter;
|
||||
QAction *poser_fil;
|
||||
QAction *masquer_appli;
|
||||
QAction *restaurer_appli;
|
||||
QAction *zoom_avant;
|
||||
QAction *zoom_arriere;
|
||||
QAction *zoom_adapte;
|
||||
QAction *zoom_reset;
|
||||
QAction *a_propos_de_qet;
|
||||
QAction *a_propos_de_qt;
|
||||
QAction *configurer;
|
||||
QAction *entrer_pe;
|
||||
QAction *sortir_pe;
|
||||
QAction *toggle_aa;
|
||||
QAction *f_mosaique;
|
||||
QAction *f_cascade;
|
||||
QAction *f_reorganise;
|
||||
QAction *f_prec;
|
||||
QAction *f_suiv;
|
||||
|
||||
void actions();
|
||||
// menus variables
|
||||
QAction *menu_systray_masquer_restaurer;
|
||||
|
||||
private:
|
||||
QWorkspace workspace;
|
||||
SchemaVue *schemaEnCours();
|
||||
QSignalMapper windowMapper;
|
||||
/// Dock pour le Panel d'Appareils
|
||||
QDockWidget *qdw_pa;
|
||||
/// Panel d'Appareils
|
||||
PanelAppareils *pa;
|
||||
/// Elements de menus pour l'icone du systray
|
||||
QMenu *menu_systray;
|
||||
QAction *systray_masquer;
|
||||
QAction * config_fullscreen;
|
||||
QAction *systray_quitter;
|
||||
QMenu *menu_fenetres;
|
||||
/// Icone dans le systray
|
||||
QSystemTrayIcon *qsti;
|
||||
/// Geometrie de la fenetre principale
|
||||
QByteArray wg;
|
||||
void menus();
|
||||
void toolbar();
|
||||
QToolBar *barre_outils;
|
||||
|
||||
private slots:
|
||||
void slot_couper();
|
||||
void slot_copier();
|
||||
void slot_coller();
|
||||
void slot_zoomPlus();
|
||||
void slot_zoomMoins();
|
||||
void slot_zoomFit();
|
||||
void slot_zoomReset();
|
||||
void slot_selectAll();
|
||||
void slot_selectNothing();
|
||||
void slot_selectInvert();
|
||||
void slot_supprimer();
|
||||
void slot_pivoter();
|
||||
void slot_setSelectionMode();
|
||||
void slot_setVisualisationMode();
|
||||
void slot_updateActions();
|
||||
void slot_updateMenuFenetres();
|
||||
};
|
||||
#endif
|
||||
322
schema.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
#include <math.h>
|
||||
#include "conducteur.h"
|
||||
#include "contacteur.h"
|
||||
#include "elementperso.h"
|
||||
#include "schema.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QObject parent du schema
|
||||
*/
|
||||
Schema::Schema(QObject *parent) : QGraphicsScene(parent) {
|
||||
setBackgroundBrush(Qt::white);
|
||||
poseur_de_conducteur = new QGraphicsLineItem(0, 0);
|
||||
poseur_de_conducteur -> setZValue(1000000);
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.5);
|
||||
t.setStyle(Qt::DashLine);
|
||||
poseur_de_conducteur -> setPen(t);
|
||||
poseur_de_conducteur -> setLine(QLineF(QPointF(0.0, 0.0), QPointF(0.0, 0.0)));
|
||||
doit_dessiner_grille = true;
|
||||
connect(this, SIGNAL(changed(const QList<QRectF> &)), this, SLOT(slot_checkSelectionChange()));
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine l'arriere-plan du schema, cad la grille.
|
||||
@param p Le QPainter a utiliser pour dessiner
|
||||
@param r Le rectangle de la zone a dessiner
|
||||
*/
|
||||
void Schema::drawBackground(QPainter *p, const QRectF &r) {
|
||||
p -> save();
|
||||
|
||||
// desactive tout antialiasing
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
|
||||
// dessine un fond blanc
|
||||
p -> setPen(Qt::NoPen);
|
||||
p -> setBrush(Qt::white);
|
||||
p -> drawRect(r);
|
||||
|
||||
if (doit_dessiner_grille) {
|
||||
// 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 -> drawLine(0, 0, 0, 10);
|
||||
p -> drawLine(0, 0, 10, 0);
|
||||
}
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
QImage Schema::toImage() {
|
||||
|
||||
QRectF vue = itemsBoundingRect();
|
||||
// la marge = 5 % de la longueur necessaire
|
||||
qreal marge = 0.05 * vue.width();
|
||||
vue.translate(-marge, -marge);
|
||||
vue.setWidth(vue.width() + 2.0 * marge);
|
||||
vue.setHeight(vue.height() + 2.0 * marge);
|
||||
QSize dimensions_image = vue.size().toSize();
|
||||
|
||||
QImage pix = QImage(dimensions_image, QImage::Format_RGB32);
|
||||
QPainter p;
|
||||
bool painter_ok = p.begin(&pix);
|
||||
if (!painter_ok) return(QImage());
|
||||
|
||||
// rendu antialiase
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::TextAntialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
render(&p, pix.rect(), vue, Qt::KeepAspectRatio);
|
||||
p.end();
|
||||
return(pix);
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte tout ou partie du schema
|
||||
@param schema Booleen (a vrai par defaut) indiquant si le XML genere doit representer tout le schema ou seulement les elements selectionnes
|
||||
@return Un Document XML (QDomDocument)
|
||||
*/
|
||||
QDomDocument Schema::toXml(bool schema) {
|
||||
// document
|
||||
QDomDocument document;
|
||||
|
||||
// racine de l'arbre XML
|
||||
QDomElement racine = document.createElement("schema");
|
||||
|
||||
// proprietes du schema
|
||||
if (schema) {
|
||||
if (!auteur.isNull()) racine.setAttribute("auteur", auteur);
|
||||
if (!date.isNull()) racine.setAttribute("date", date.toString("yyyyMMdd"));
|
||||
if (!titre.isNull()) racine.setAttribute("titre", titre);
|
||||
}
|
||||
document.appendChild(racine);
|
||||
|
||||
// si le schema ne contient pas d'element (et donc pas de conducteurs), on retourne de suite le document XML
|
||||
if (items().isEmpty()) return(document);
|
||||
|
||||
// creation de deux listes : une qui contient les elements, une qui contient les conducteurs
|
||||
QList<Element *> liste_elements;
|
||||
QList<Conducteur *> liste_conducteurs;
|
||||
|
||||
|
||||
// Determine les elements a « XMLiser »
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
|
||||
if (schema) liste_elements << elmt;
|
||||
else if (elmt -> isSelected()) liste_elements << elmt;
|
||||
} else if (Conducteur *f = qgraphicsitem_cast<Conducteur *>(qgi)) {
|
||||
if (schema) liste_conducteurs << f;
|
||||
// lorsqu'on n'exporte pas tout le schema, il faut retirer les conducteurs non selectionnes
|
||||
// et pour l'instant, les conducteurs non selectionnes sont les conducteurs dont un des elements n'est pas relie
|
||||
else if (f -> borne1 -> parentItem() -> isSelected() && f -> borne2 -> parentItem() -> isSelected()) liste_conducteurs << f;
|
||||
}
|
||||
}
|
||||
|
||||
// enregistrement des elements
|
||||
if (liste_elements.isEmpty()) return(document);
|
||||
int id_borne = 0;
|
||||
// table de correspondance entre les adresses des bornes et leurs ids
|
||||
QHash<Borne *, int> table_adr_id;
|
||||
QDomElement elements = document.createElement("elements");
|
||||
foreach(Element *elmt, liste_elements) {
|
||||
QDomElement element = document.createElement("element");
|
||||
|
||||
// type, position, selection et orientation
|
||||
element.setAttribute("type", QFileInfo(elmt -> typeId()).fileName());
|
||||
element.setAttribute("x", elmt -> pos().x());
|
||||
element.setAttribute("y", elmt -> pos().y());
|
||||
if (elmt -> isSelected()) element.setAttribute("selected", "selected");
|
||||
element.setAttribute("sens", elmt -> orientation() ? "true" : "false");
|
||||
|
||||
// enregistrements des bornes de chaque appareil
|
||||
QDomElement bornes = document.createElement("bornes");
|
||||
// pour chaque enfant de l'element
|
||||
foreach(QGraphicsItem *child, elmt -> children()) {
|
||||
// si cet enfant est une borne
|
||||
if (Borne *p = qgraphicsitem_cast<Borne *>(child)) {
|
||||
// alors on enregistre la borne
|
||||
QDomElement borne = p -> toXml(document);
|
||||
borne.setAttribute("id", id_borne);
|
||||
table_adr_id.insert(p, id_borne ++);
|
||||
bornes.appendChild(borne);
|
||||
}
|
||||
}
|
||||
element.appendChild(bornes);
|
||||
|
||||
/**
|
||||
@todo appeler une methode virtuelle de la classe Element qui permettra
|
||||
aux developpeurs d'elements de personnaliser l'enregistrement des elements
|
||||
*/
|
||||
elements.appendChild(element);
|
||||
}
|
||||
racine.appendChild(elements);
|
||||
|
||||
// enregistrement des conducteurs
|
||||
if (liste_conducteurs.isEmpty()) return(document);
|
||||
QDomElement conducteurs = document.createElement("conducteurs");
|
||||
foreach(Conducteur *f, liste_conducteurs) {
|
||||
QDomElement conducteur = document.createElement("conducteur");
|
||||
conducteur.setAttribute("borne1", table_adr_id.value(f -> borne1));
|
||||
conducteur.setAttribute("borne2", table_adr_id.value(f -> borne2));
|
||||
conducteurs.appendChild(conducteur);
|
||||
}
|
||||
racine.appendChild(conducteurs);
|
||||
|
||||
// on retourne le document XML ainsi genere
|
||||
return(document);
|
||||
}
|
||||
|
||||
void Schema::reset() {
|
||||
/// @todo implementer cette fonction
|
||||
}
|
||||
|
||||
/**
|
||||
Importe le schema decrit dans un document XML. Si une position est precisee, les elements importes sont positionnes de maniere a ce que le coin superieur gauche du plus petit rectangle pouvant les entourant tous (le bounding rect) soit a cette position.
|
||||
@param document Le document XML a analyser
|
||||
@param position La position du schema importe
|
||||
@return true si l'import a reussi, false sinon
|
||||
*/
|
||||
bool Schema::fromXml(QDomDocument &document, QPointF position) {
|
||||
QDomElement racine = document.documentElement();
|
||||
// le premier element doit etre un schema
|
||||
if (racine.tagName() != "schema") return(false);
|
||||
// lecture des attributs de ce schema
|
||||
auteur = racine.attribute("auteur");
|
||||
titre = racine.attribute("titre");
|
||||
date = QDate::fromString(racine.attribute("date"), "yyyyMMdd");
|
||||
|
||||
// si la racine n'a pas d'enfant : le chargement est fini (schema vide)
|
||||
if (racine.firstChild().isNull()) return(true);
|
||||
|
||||
// chargement de tous les Elements du fichier XML
|
||||
QList<Element *> elements_ajoutes;
|
||||
//uint nb_elements = 0;
|
||||
QHash< int, Borne *> table_adr_id;
|
||||
QHash< int, Borne *> &ref_table_adr_id = table_adr_id;
|
||||
for (QDomNode node = racine.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
// on s'interesse a l'element XML "elements" (= groupe d'elements)
|
||||
QDomElement elmts = node.toElement();
|
||||
if(elmts.isNull() || elmts.tagName() != "elements") continue;
|
||||
// parcours des enfants de l'element XML "elements"
|
||||
for (QDomNode n = elmts.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
|
||||
// on s'interesse a l'element XML "element" (elements eux-memes)
|
||||
QDomElement e = n.toElement();
|
||||
if (e.isNull() || !Element::valideXml(e)) continue;
|
||||
Element *element_ajoute;
|
||||
if ((element_ajoute = elementFromXml(e, ref_table_adr_id)) != NULL) elements_ajoutes << element_ajoute;
|
||||
else qDebug("Le chargement d'un element a echoue");
|
||||
}
|
||||
}
|
||||
|
||||
// aucun Element n'a ete ajoute - inutile de chercher des conducteurs - le chargement est fini
|
||||
if (!elements_ajoutes.size()) return(true);
|
||||
|
||||
// gere la translation des nouveaux elements si celle-ci est demandee
|
||||
if (position != QPointF()) {
|
||||
// determine quel est le coin superieur gauche du rectangle entourant les elements ajoutes
|
||||
qreal minimum_x = 0, minimum_y = 0;
|
||||
bool init = false;
|
||||
foreach (Element *elmt_ajoute, elements_ajoutes) {
|
||||
QPointF csg = elmt_ajoute -> mapToScene(elmt_ajoute -> boundingRect().topLeft());
|
||||
qreal px = csg.x();
|
||||
qreal py = csg.y();
|
||||
if (!init) {
|
||||
minimum_x = px;
|
||||
minimum_y = py;
|
||||
init = true;
|
||||
} else {
|
||||
if (px < minimum_x) minimum_x = px;
|
||||
if (py < minimum_y) minimum_y = py;
|
||||
}
|
||||
}
|
||||
qreal diff_x = position.x() - minimum_x;
|
||||
qreal diff_y = position.y() - minimum_y;
|
||||
foreach (Element *elmt_ajoute, elements_ajoutes) {
|
||||
elmt_ajoute -> setPos(elmt_ajoute -> pos().x() + diff_x, elmt_ajoute -> pos().y() + diff_y);
|
||||
}
|
||||
}
|
||||
|
||||
// chargement de tous les Conducteurs du fichier XML
|
||||
for (QDomNode node = racine.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
// on s'interesse a l'element XML "conducteurs" (= groupe de conducteurs)
|
||||
QDomElement conducteurs = node.toElement();
|
||||
if(conducteurs.isNull() || conducteurs.tagName() != "conducteurs") continue;
|
||||
// parcours des enfants de l'element XML "conducteurs"
|
||||
for (QDomNode n = conducteurs.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
|
||||
// on s'interesse a l'element XML "element" (elements eux-memes)
|
||||
QDomElement f = n.toElement();
|
||||
if (f.isNull() || !Conducteur::valideXml(f)) continue;
|
||||
// verifie que les bornes que le conducteur relie sont connues
|
||||
int id_p1 = f.attribute("borne1").toInt();
|
||||
int id_p2 = f.attribute("borne2").toInt();
|
||||
if (table_adr_id.contains(id_p1) && table_adr_id.contains(id_p2)) {
|
||||
// pose le conducteur... si c'est possible
|
||||
Borne *p1 = table_adr_id.value(id_p1);
|
||||
Borne *p2 = table_adr_id.value(id_p2);
|
||||
if (p1 != p2) {
|
||||
bool peut_poser_conducteur = true;
|
||||
bool cia = ((Element *)p2 -> parentItem()) -> connexionsInternesAcceptees();
|
||||
if (!cia) foreach(QGraphicsItem *item, p2 -> parentItem() -> children()) if (item == p1) peut_poser_conducteur = false;
|
||||
if (peut_poser_conducteur) new Conducteur(table_adr_id.value(id_p1), table_adr_id.value(id_p2), 0, this);
|
||||
}
|
||||
} else qDebug() << "Le chargement du conducteur" << id_p1 << id_p2 << "a echoue";
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute au schema l'Element correspondant au QDomElement passe en parametre
|
||||
@param e QDomElement a analyser
|
||||
@param table_id_adr Table de correspondance entre les entiers et les bornes
|
||||
@return true si l'ajout a parfaitement reussi, false sinon
|
||||
*/
|
||||
Element *Schema::elementFromXml(QDomElement &e, QHash<int, Borne *> &table_id_adr) {
|
||||
// cree un element dont le type correspond à l'id type
|
||||
QString type = e.attribute("type");
|
||||
int etat;
|
||||
Element *nvel_elmt = new ElementPerso(type, 0, 0, &etat);
|
||||
/*switch(e.attribute("type").toInt()) {
|
||||
case 0: nvel_elmt = new Contacteur(); break;
|
||||
case 1: nvel_elmt = new DEL(); break;
|
||||
case 2: nvel_elmt = new Entree(); break;
|
||||
}*/
|
||||
if (etat != 0) return(false);
|
||||
bool retour = nvel_elmt -> fromXml(e, table_id_adr);
|
||||
if (!retour) {
|
||||
delete nvel_elmt;
|
||||
} else {
|
||||
// ajout de l'element au schema
|
||||
addItem(nvel_elmt);
|
||||
nvel_elmt -> setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble());
|
||||
nvel_elmt -> setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
if (e.attribute("sens") == "false") nvel_elmt -> invertOrientation();
|
||||
nvel_elmt -> setSelected(e.attribute("selected") == "selected");
|
||||
}
|
||||
return(retour ? nvel_elmt : NULL);
|
||||
}
|
||||
|
||||
void Schema::slot_checkSelectionChange() {
|
||||
static QList<QGraphicsItem *> cache_selecteditems = QList<QGraphicsItem *>();
|
||||
QList<QGraphicsItem *> selecteditems = selectedItems();
|
||||
if (cache_selecteditems != selecteditems) emit(selectionChanged());
|
||||
cache_selecteditems = selecteditems;
|
||||
}
|
||||
46
schema.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef SCHEMA_H
|
||||
#define SCHEMA_H
|
||||
#define GRILLE_X 10
|
||||
#define GRILLE_Y 10
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
class Element;
|
||||
class Borne;
|
||||
class Schema : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Schema(QObject * = 0);
|
||||
void drawBackground(QPainter *, const QRectF &);
|
||||
inline void poseConducteur(bool pf) {
|
||||
if (pf) {
|
||||
if (!poseur_de_conducteur -> scene()) addItem(poseur_de_conducteur);
|
||||
} else {
|
||||
if (poseur_de_conducteur -> scene()) removeItem(poseur_de_conducteur);
|
||||
}
|
||||
}
|
||||
inline void setDepart (QPointF d) { poseur_de_conducteur -> setLine(QLineF(d, poseur_de_conducteur -> line().p2())); }
|
||||
inline void setArrivee(QPointF a) { poseur_de_conducteur -> setLine(QLineF(poseur_de_conducteur -> line().p1(), a)); }
|
||||
QImage toImage();
|
||||
QDomDocument toXml(bool = true);
|
||||
bool fromXml(QDomDocument &, QPointF = QPointF());
|
||||
void reset();
|
||||
QGraphicsItem *getElementById(uint id);
|
||||
|
||||
private:
|
||||
QGraphicsLineItem *poseur_de_conducteur;
|
||||
bool doit_dessiner_grille;
|
||||
// elements du cartouche
|
||||
QString auteur;
|
||||
QDate date;
|
||||
QString titre;
|
||||
QString folio; // vraiment necessaire ce truc ?
|
||||
QString nom_fichier; // meme remarque
|
||||
Element *elementFromXml(QDomElement &e, QHash<int, Borne *> &);
|
||||
|
||||
private slots:
|
||||
void slot_checkSelectionChange();
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
};
|
||||
#endif
|
||||
431
schemavue.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
#include "schemavue.h"
|
||||
#include "schema.h"
|
||||
#include "elementperso.h"
|
||||
#include "contacteur.h"
|
||||
#include "del.h"
|
||||
#include "entree.h"
|
||||
|
||||
/**
|
||||
Initialise le SchemaVue
|
||||
*/
|
||||
void SchemaVue::initialise() {
|
||||
setInteractive(true);
|
||||
setAntialiasing(true);
|
||||
setScene(scene = new Schema(this));
|
||||
setDragMode(RubberBandDrag);
|
||||
setAcceptDrops(true);
|
||||
setWindowTitle(tr("Nouveau sch\351ma") + "[*]");
|
||||
connect(scene, SIGNAL(selectionChanged()), this, SLOT(slot_selectionChanged()));
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur par defaut
|
||||
*/
|
||||
SchemaVue::SchemaVue() : QGraphicsView() {
|
||||
initialise();
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidegt parent de cette vue de schema
|
||||
*/
|
||||
SchemaVue::SchemaVue(QWidget *parent) : QGraphicsView(parent) {
|
||||
initialise();
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si le rendu graphique du SchemaVue est antialiase ou non.
|
||||
@return Un booleen indiquant si le SchemaVue est antialiase
|
||||
*/
|
||||
bool SchemaVue::antialiased() const {
|
||||
return(antialiasing);
|
||||
}
|
||||
|
||||
/**
|
||||
Active ou desactive l'antialiasing pour le rendu graphique du SchemaVue.
|
||||
@param aa un booleen indiquant si le SchemaVue doit etre antialiase ou non
|
||||
*/
|
||||
void SchemaVue::setAntialiasing(bool aa) {
|
||||
antialiasing = aa;
|
||||
setRenderHint(QPainter::Antialiasing, aa);
|
||||
setRenderHint(QPainter::TextAntialiasing, aa);
|
||||
setRenderHint(QPainter::SmoothPixmapTransform, aa);
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
appelle la methode select sur tous les elements de la liste d'elements
|
||||
@todo modifier selectAll pour l'integration des conducteurs
|
||||
*/
|
||||
void SchemaVue::selectAll() {
|
||||
if (scene -> items().isEmpty()) return;
|
||||
foreach (QGraphicsItem *item, scene -> items()) item -> setSelected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
appelle la methode deselect sur tous les elements de la liste d'elements
|
||||
@todo modifier selectNothing pour l'integration des conducteurs
|
||||
*/
|
||||
void SchemaVue::selectNothing() {
|
||||
if (scene -> items().isEmpty()) return;
|
||||
foreach (QGraphicsItem *item, scene -> items()) item -> setSelected(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Inverse l'etat de selection de tous les elements de la liste d'elements
|
||||
@todo modifier selectInvert pour l'integration des conducteurs
|
||||
*/
|
||||
void SchemaVue::selectInvert() {
|
||||
if (scene -> items().isEmpty()) return;
|
||||
foreach (QGraphicsItem *item, scene -> items()) item -> setSelected(!item -> isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime les composants selectionnes
|
||||
*/
|
||||
void SchemaVue::supprimer() {
|
||||
QList<QGraphicsItem *> garbage_elmt;
|
||||
QList<QGraphicsItem *> garbage_conducteurs;
|
||||
|
||||
// useless but careful : creating two lists : one for wires, one for elements
|
||||
foreach (QGraphicsItem *qgi, scene -> selectedItems()) {
|
||||
if (!garbage_elmt.contains(qgi)) garbage_elmt.append(qgi);
|
||||
// pour chaque enfant de l'element
|
||||
foreach (QGraphicsItem *child, qgi -> children()) {
|
||||
// si cet enfant est une borne
|
||||
if (Borne *p = qgraphicsitem_cast<Borne *>(child)) {
|
||||
// alors chaque conducteur de la borne est recense
|
||||
foreach (Conducteur *f, p -> conducteurs()) {
|
||||
if (!garbage_conducteurs.contains(f)) garbage_conducteurs.append(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scene -> clearSelection();
|
||||
|
||||
// "destroying" the wires, removing them from the scene and stocking them into the « garbage »
|
||||
foreach (QGraphicsItem *qgi, garbage_conducteurs) {
|
||||
if (Conducteur *f = qgraphicsitem_cast<Conducteur *>(qgi)) {
|
||||
f -> destroy();
|
||||
scene -> removeItem(f);
|
||||
throwToGarbage(f);
|
||||
}
|
||||
}
|
||||
|
||||
// removing the elements from the scene and stocking them into the « garbage »
|
||||
foreach (QGraphicsItem *qgi, garbage_elmt) {
|
||||
scene -> removeItem(qgi);
|
||||
throwToGarbage(qgi);
|
||||
}
|
||||
resetCachedContent();
|
||||
QTimer::singleShot(5000, this, SLOT(flushGarbage()));
|
||||
}
|
||||
|
||||
/**
|
||||
Envoie un item vers le "garbage" pour qu'il soit supprime plus tard
|
||||
@param qgi L'item a supprimer
|
||||
*/
|
||||
void SchemaVue::throwToGarbage(QGraphicsItem *qgi) {
|
||||
// pas de doublon dans le garbage (sinon ca va sentir la segfault)
|
||||
bool qgi_deja_dans_le_garbage = false;
|
||||
foreach(QGraphicsItem *gbg_qgi, garbage) {
|
||||
if ((void *)gbg_qgi == (void *)qgi) {
|
||||
qgi_deja_dans_le_garbage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!qgi_deja_dans_le_garbage) garbage.append(qgi);
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime tous les elements du "garbage"
|
||||
*/
|
||||
void SchemaVue::flushGarbage() {
|
||||
foreach(QGraphicsItem *qgi, garbage) {
|
||||
delete(qgi);
|
||||
garbage.removeAll(qgi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Pivote les composants selectionnes
|
||||
*/
|
||||
void SchemaVue::pivoter() {
|
||||
if (scene -> selectedItems().isEmpty()) return;
|
||||
foreach (QGraphicsItem *item, scene -> selectedItems()) {
|
||||
if (Element *elt = qgraphicsitem_cast<Element *>(item)) {
|
||||
elt -> invertOrientation();
|
||||
elt -> update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
accepte ou refuse le drag'n drop en fonction du type de donnees entrant
|
||||
@param e le QDragEnterEvent correspondant au drag'n drop tente
|
||||
@todo trouver un MIME Type plus adapte
|
||||
*/
|
||||
void SchemaVue::dragEnterEvent(QDragEnterEvent *e) {
|
||||
if (e -> mimeData() -> hasFormat("text/plain")) e -> acceptProposedAction();
|
||||
else e-> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
gere les dragleaveevent
|
||||
@param e le QDragEnterEvent correspondant au drag'n drop sortant
|
||||
*/
|
||||
void SchemaVue::dragLeaveEvent(QDragLeaveEvent *) {}
|
||||
|
||||
/**
|
||||
accepte ou refuse le drag'n drop en fonction du type de donnees entrant
|
||||
@param e le QDragMoveEvent correspondant au drag'n drop tente
|
||||
*/
|
||||
void SchemaVue::dragMoveEvent(QDragMoveEvent *e) {
|
||||
if (e -> mimeData() -> hasFormat("text/plain")) e -> acceptProposedAction();
|
||||
else e-> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
gere les depots (drop) acceptes sur le Schema
|
||||
@param e le QDropEvent correspondant au drag'n drop effectue
|
||||
@todo Ajouter directement l'objet Element a la scene lorsque le drag'n drop aura ete ameliore
|
||||
*/
|
||||
void SchemaVue::dropEvent(QDropEvent *e) {
|
||||
QString fichier = e -> mimeData() -> text();
|
||||
int etat;
|
||||
Element *el = new ElementPerso(fichier, 0, 0, &etat);
|
||||
if (etat != 0) delete el;
|
||||
else {
|
||||
scene -> addItem(el);
|
||||
el -> setPos(mapToScene(e -> pos().x(), e -> pos().y()));
|
||||
el -> setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Passe le Schema en mode visualisation
|
||||
*/
|
||||
void SchemaVue::setVisualisationMode() {
|
||||
setDragMode(ScrollHandDrag);
|
||||
emit(modeChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Passe le Schema en mode Selection
|
||||
*/
|
||||
void SchemaVue::setSelectionMode() {
|
||||
setDragMode(RubberBandDrag);
|
||||
setCursor(Qt::ArrowCursor);
|
||||
emit(modeChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit le schema (+33% = inverse des -25 % de zoomMoins())
|
||||
*/
|
||||
void SchemaVue::zoomPlus() {
|
||||
scale(4.0/3.0, 4.0/3.0);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrecit le schema (-25% = inverse des +33 % de zoomPlus())
|
||||
*/
|
||||
void SchemaVue::zoomMoins() {
|
||||
scale(0.75, 0.75);
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit ou rectrecit le schema de facon a ce que tous les elements du
|
||||
schema soient visibles a l'ecran. S'il n'y a aucun element sur le schema,
|
||||
le zoom est reinitialise
|
||||
*/
|
||||
void SchemaVue::zoomFit() {
|
||||
if (scene -> items().isEmpty()) {
|
||||
zoomReset();
|
||||
return;
|
||||
}
|
||||
QRectF vue = scene -> itemsBoundingRect();
|
||||
// la marge = 5 % de la longueur necessaire
|
||||
qreal marge = 0.05 * vue.width();
|
||||
vue.translate(-marge, -marge);
|
||||
vue.setWidth(vue.width() + 2.0 * marge);
|
||||
vue.setHeight(vue.height() + 2.0 * marge);
|
||||
fitInView(vue, Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
Reinitialise le zoom
|
||||
*/
|
||||
void SchemaVue::zoomReset() {
|
||||
resetMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
copie les elements selectionnes du schema dans le presse-papier puis les supprime
|
||||
*/
|
||||
void SchemaVue::couper() {
|
||||
copier();
|
||||
supprimer();
|
||||
}
|
||||
|
||||
/**
|
||||
copie les elements selectionnes du schema dans le presse-papier
|
||||
*/
|
||||
void SchemaVue::copier() {
|
||||
QClipboard *presse_papier = QApplication::clipboard();
|
||||
QString contenu_presse_papier = scene -> toXml(false).toString(4);
|
||||
if (presse_papier -> supportsSelection()) presse_papier -> setText(contenu_presse_papier, QClipboard::Selection);
|
||||
presse_papier -> setText(contenu_presse_papier);
|
||||
}
|
||||
|
||||
/**
|
||||
importe les elements contenus dans le presse-papier dans le schema
|
||||
*/
|
||||
void SchemaVue::coller() {
|
||||
QString texte_presse_papier;
|
||||
QDomDocument document_xml;
|
||||
if ((texte_presse_papier = QApplication::clipboard() -> text()) == QString()) return;
|
||||
if (!document_xml.setContent(texte_presse_papier)) return;
|
||||
scene -> fromXml(document_xml);
|
||||
}
|
||||
|
||||
/**
|
||||
gere les clics et plus particulierement le clic du milieu (= coller pour X11)
|
||||
*/
|
||||
void SchemaVue::mousePressEvent(QMouseEvent *e) {
|
||||
if (e -> buttons() == Qt::MidButton) {
|
||||
QString texte_presse_papier;
|
||||
QDomDocument document_xml;
|
||||
if ((texte_presse_papier = QApplication::clipboard() -> text(QClipboard::Selection)) == QString()) return;
|
||||
if (!document_xml.setContent(texte_presse_papier)) return;
|
||||
scene -> fromXml(document_xml, mapToScene(e -> pos()));
|
||||
}
|
||||
QGraphicsView::mousePressEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Ouvre un fichier *.qet dans cette SchemaVue
|
||||
@param nom_fichier Nom du fichier a ouvrir
|
||||
@param erreur Si le pointeur est specifie, cet entier est mis a 0 en cas de reussite de l'ouverture, 1 si le fichier n'existe pas, 2 si le fichier n'est pas lisible, 3 si le fichier n'est pas un element XML, 4 si l'ouverture du fichier a echoue pour une autre raison (c'est pas ca qui manque ^^)
|
||||
@return true si l'ouverture a reussi, false sinon
|
||||
*/
|
||||
bool SchemaVue::ouvrir(QString n_fichier, int *erreur) {
|
||||
// verifie l'existence du fichier
|
||||
if (!QFileInfo(n_fichier).exists()) {
|
||||
if (erreur != NULL) *erreur = 1;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// ouvre le fichier
|
||||
QFile fichier(n_fichier);
|
||||
if (!fichier.open(QIODevice::ReadOnly)) {
|
||||
if (erreur != NULL) *erreur = 2;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// lit son contenu dans un QDomDocument
|
||||
QDomDocument document;
|
||||
if (!document.setContent(&fichier)) {
|
||||
if (erreur != NULL) *erreur = 3;
|
||||
fichier.close();
|
||||
return(false);
|
||||
}
|
||||
fichier.close();
|
||||
|
||||
// construit le schema a partir du QDomDocument
|
||||
QDomDocument &doc = document;
|
||||
if (scene -> fromXml(doc)) {
|
||||
if (erreur != NULL) *erreur = 0;
|
||||
nom_fichier = n_fichier;
|
||||
setWindowTitle(nom_fichier + "[*]");
|
||||
return(true);
|
||||
} else {
|
||||
if (erreur != NULL) *erreur = 4;
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SchemaVue::slot_selectionChanged() {
|
||||
emit(selectionChanged());
|
||||
}
|
||||
|
||||
void SchemaVue::closeEvent(QCloseEvent *event) {
|
||||
// demande d'abord a l'utilisateur s'il veut enregistrer le schema en cours
|
||||
QMessageBox::StandardButton reponse = QMessageBox::question(
|
||||
this,
|
||||
tr("Enregistrer le sch\351ma en cours ?"),
|
||||
tr("Voulez-vous enregistrer le sch\351ma en cours ?"),
|
||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
|
||||
QMessageBox::Cancel
|
||||
);
|
||||
bool retour;
|
||||
switch(reponse) {
|
||||
case QMessageBox::Cancel: retour = false; break; // l'utilisateur annule : echec de la fermeture
|
||||
case QMessageBox::Yes: retour = enregistrer(); break; // l'utilisateur dit oui : la reussite depend de l'enregistrement
|
||||
default: retour = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi
|
||||
}
|
||||
if (retour) event -> accept();
|
||||
else event -> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
Methode enregistrant le schema dans le dernier nom de fichier connu.
|
||||
Si aucun nom de fichier n'est connu, cette methode appelle la methode enregistrer_sous
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
*/
|
||||
bool SchemaVue::enregistrer() {
|
||||
if (nom_fichier == QString()) return(enregistrer_sous());
|
||||
else return(private_enregistrer(nom_fichier));
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode demande un nom de fichier a l'utilisateur pour enregistrer le schema
|
||||
Si aucun nom n'est entre, elle renvoie faux.
|
||||
Si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee.
|
||||
Si l'enregistrement reussit, le nom du fichier est conserve et la fonction renvoie true.
|
||||
Sinon, faux est renvoye.
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
@todo detecter le chemin du bureau automatiquement
|
||||
*/
|
||||
bool SchemaVue::enregistrer_sous() {
|
||||
// demande un nom de fichier a l'utilisateur pour enregistrer le schema
|
||||
QString n_fichier = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Enregistrer sous"),
|
||||
QDir::homePath(),
|
||||
tr("Schema QelectroTech (*.qet)")
|
||||
);
|
||||
// si aucun nom n'est entre, renvoie faux.
|
||||
if (n_fichier == "") return(false);
|
||||
// si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee
|
||||
if (!n_fichier.endsWith(".qet", Qt::CaseInsensitive)) n_fichier += ".qet";
|
||||
// tente d'enregistrer le fichier
|
||||
bool resultat_enregistrement = private_enregistrer(n_fichier);
|
||||
// si l'enregistrement reussit, le nom du fichier est conserve
|
||||
if (resultat_enregistrement) {
|
||||
nom_fichier = n_fichier;
|
||||
setWindowTitle(nom_fichier + "[*]");
|
||||
}
|
||||
// retourne un booleen representatif de la reussite de l'enregistrement
|
||||
return(resultat_enregistrement);
|
||||
}
|
||||
|
||||
/**
|
||||
Methode privee gerant l'enregistrement du fichier XML. S'il n'est pas possible
|
||||
d'ecrire dans le fichier, cette fonction affiche un message d'erreur et renvoie false.
|
||||
Autrement, elle renvoie true.
|
||||
@param nom_fichier Nom du fichier dans lequel l'arbre XML doit etre ecrit
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
*/
|
||||
bool SchemaVue::private_enregistrer(QString &n_fichier) {
|
||||
QFile fichier(n_fichier);
|
||||
if (!fichier.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QMessageBox::warning(this, tr("Erreur"), tr("Impossible d'ecrire dans ce fichier"));
|
||||
return(false);
|
||||
}
|
||||
QTextStream out(&fichier);
|
||||
out.setCodec("UTF-8");
|
||||
out << scene -> toXml().toString(4);
|
||||
fichier.close();
|
||||
return(true);
|
||||
}
|
||||
|
||||
69
schemavue.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef SCHEMAVUE_H
|
||||
#define SCHEMAVUE_H
|
||||
#include <QtGui>
|
||||
class Schema;
|
||||
#include "element.h"
|
||||
#include "conducteur.h"
|
||||
#define TAILLE_GRILLE 10
|
||||
/**
|
||||
Classe representant un SchemaVue electrique
|
||||
@todo creer une structure capable de retenir les differents composants du SchemaVue : elements, fils, indications eventuelles => revoir les SchemaVues
|
||||
*/
|
||||
class SchemaVue : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// constructeurs
|
||||
SchemaVue();
|
||||
SchemaVue(QWidget * = 0);
|
||||
|
||||
// nouveaux attributs
|
||||
Schema *scene;
|
||||
|
||||
// methodes publiques
|
||||
bool antialiased() const;
|
||||
void setAntialiasing(bool);
|
||||
bool ouvrir(QString, int * = NULL);
|
||||
void closeEvent(QCloseEvent *);
|
||||
QString nom_fichier;
|
||||
bool enregistrer();
|
||||
bool enregistrer_sous();
|
||||
|
||||
private:
|
||||
bool private_enregistrer(QString &);
|
||||
void initialise();
|
||||
bool antialiasing; // booleen indiquant s'il faut effectuer un antialiasing sur le rendu graphique du SchemaVue
|
||||
QList<QGraphicsItem *> garbage;
|
||||
|
||||
void throwToGarbage(QGraphicsItem *);
|
||||
void mousePressEvent(QMouseEvent *);
|
||||
void dragEnterEvent(QDragEnterEvent *);
|
||||
void dragLeaveEvent(QDragLeaveEvent *);
|
||||
void dragMoveEvent(QDragMoveEvent *);
|
||||
void dropEvent(QDropEvent *);
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
void antialiasingChanged();
|
||||
void modeChanged();
|
||||
|
||||
public slots:
|
||||
void selectNothing();
|
||||
void selectAll();
|
||||
void selectInvert();
|
||||
void supprimer();
|
||||
void pivoter();
|
||||
void setVisualisationMode();
|
||||
void setSelectionMode();
|
||||
void zoomPlus();
|
||||
void zoomMoins();
|
||||
void zoomFit();
|
||||
void zoomReset();
|
||||
void couper();
|
||||
void copier();
|
||||
void coller();
|
||||
|
||||
private slots:
|
||||
void flushGarbage();
|
||||
void slot_selectionChanged();
|
||||
};
|
||||
#endif
|
||||