diff --git a/conducer.cpp b/conducer.cpp index 8e429dc7e..5ce36fd6c 100644 --- a/conducer.cpp +++ b/conducer.cpp @@ -739,10 +739,14 @@ bool Conducer::fromXml(QDomElement &e) { return(true); } -void Conducer::toXml(QDomDocument &d, QDomElement &e) { +QDomElement Conducer::toXml(QDomDocument &d, QHash &table_adr_id) const { + QDomElement e = d.createElement("conducteur"); + e.setAttribute("borne1", table_adr_id.value(terminal1)); + e.setAttribute("borne2", table_adr_id.value(terminal2)); + // on n'exporte les segments du conducteur que si ceux-ci ont // ete modifies par l'utilisateur - if (!modified_path) return; + if (!modified_path) return(e); // parcours et export des segments ConducerSegment *segment = segments; @@ -758,4 +762,5 @@ void Conducer::toXml(QDomDocument &d, QDomElement &e) { current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical"); current_segment.setAttribute("length", segment -> length()); e.appendChild(current_segment); + return(e); } diff --git a/conducer.h b/conducer.h index deb147338..0c85f14b5 100644 --- a/conducer.h +++ b/conducer.h @@ -23,7 +23,7 @@ virtual QPainterPath shape() const; static bool valideXml(QDomElement &); bool fromXml(QDomElement &); - void toXml(QDomDocument &, QDomElement &); + QDomElement toXml(QDomDocument &, QHash &) const; ///Premiere borne a laquelle le fil est rattache Terminal *terminal1; diff --git a/customelement.h b/customelement.h index c34976087..65f855f7b 100644 --- a/customelement.h +++ b/customelement.h @@ -7,11 +7,11 @@ CustomElement(QString &, QGraphicsItem * = 0, Diagram * = 0, int * = NULL); virtual int nbTerminals() const; virtual void paint(QPainter *, const QStyleOptionGraphicsItem *); - inline QString typeId() { return(nomfichier); } - inline QString fichier() { return(nomfichier); } - inline bool isNull() { return(elmt_etat != 0); } - inline int etat() { return(elmt_etat); } - inline QString nom() { return(priv_nom); } + inline QString typeId() const { return(nomfichier); } + inline QString fichier() const { return(nomfichier); } + inline bool isNull() const { return(elmt_etat != 0); } + inline int etat() const { return(elmt_etat); } + inline QString nom() const { 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 diff --git a/diagram.cpp b/diagram.cpp index fec22f8a7..d4c8ea648 100644 --- a/diagram.cpp +++ b/diagram.cpp @@ -140,7 +140,7 @@ QSize Diagram::imageSize() const { /** Exporte tout ou partie du schema - @param schema Booleen (a vrai par defaut) indiquant si le XML genere doit + @param diagram 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) */ @@ -168,7 +168,6 @@ QDomDocument Diagram::toXml(bool diagram) { QList liste_elements; QList liste_conducers; - // Determine les elements a « XMLiser » foreach(QGraphicsItem *qgi, items()) { if (Element *elmt = qgraphicsitem_cast(qgi)) { @@ -182,59 +181,22 @@ QDomDocument Diagram::toXml(bool diagram) { } } - // enregistrement des elements - if (liste_elements.isEmpty()) return(document); - int id_terminal = 0; // table de correspondance entre les adresses des bornes et leurs ids QHash table_adr_id; + + // enregistrement des elements + if (liste_elements.isEmpty()) return(document); QDomElement elements = document.createElement("elements"); - QDir dossier_elmts_persos = QDir(QETApp::customElementsDir()); foreach(Element *elmt, liste_elements) { - QDomElement element = document.createElement("element"); - - // type - QString chemin_elmt = elmt -> typeId(); - QString type_elmt = QETApp::symbolicPath(chemin_elmt); - element.setAttribute("type", type_elmt); - - // position, selection et orientation - element.setAttribute("x", elmt -> pos().x()); - element.setAttribute("y", elmt -> pos().y()); - if (elmt -> isSelected()) element.setAttribute("selected", "selected"); - element.setAttribute("sens", QString("%1").arg(elmt -> orientation())); - - // enregistrements des bornes de chaque appareil - QDomElement terminals = document.createElement("bornes"); - // pour chaque enfant de l'element - foreach(QGraphicsItem *child, elmt -> children()) { - // si cet enfant est une borne - if (Terminal *p = qgraphicsitem_cast(child)) { - // alors on enregistre la borne - QDomElement terminal = p -> toXml(document); - terminal.setAttribute("id", id_terminal); - table_adr_id.insert(p, id_terminal ++); - terminals.appendChild(terminal); - } - } - element.appendChild(terminals); - - /** - @todo appeler une methode virtuelle de la classe Element qui permettra - aux developpeurs d'elements de personnaliser l'enregistrement des elements - */ - elements.appendChild(element); + elements.appendChild(elmt -> toXml(document, table_adr_id)); } racine.appendChild(elements); // enregistrement des conducteurs if (liste_conducers.isEmpty()) return(document); QDomElement conducers = document.createElement("conducteurs"); - foreach(Conducer *f, liste_conducers) { - QDomElement conducer = document.createElement("conducteur"); - conducer.setAttribute("borne1", table_adr_id.value(f -> terminal1)); - conducer.setAttribute("borne2", table_adr_id.value(f -> terminal2)); - f -> toXml(document, conducer); - conducers.appendChild(conducer); + foreach(Conducer *cond, liste_conducers) { + conducers.appendChild(cond -> toXml(document, table_adr_id)); } racine.appendChild(conducers); @@ -272,7 +234,6 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in // chargement de tous les Elements du fichier XML QList elements_ajoutes; - //uint nb_elements = 0; QHash< int, Terminal *> table_adr_id; QHash< int, Terminal *> &ref_table_adr_id = table_adr_id; for (QDomNode node = racine.firstChild() ; !node.isNull() ; node = node.nextSibling()) { @@ -284,9 +245,27 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in // 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"); + + // cree un element dont le type correspond à l'id type + QString type_id = e.attribute("type"); + QString chemin_fichier = QETApp::realPath(type_id); + CustomElement *nvel_elmt = new CustomElement(chemin_fichier); + if (nvel_elmt -> isNull()) { + QString debug_message = QString("Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2").arg(chemin_fichier).arg(nvel_elmt -> etat()); + delete nvel_elmt; + qDebug(debug_message.toLatin1().data()); + continue; + } + + // charge les caracteristiques de l'element + if (nvel_elmt -> fromXml(e, ref_table_adr_id)) { + // ajout de l'element au schema et a la liste des elements ajoutes + addItem(nvel_elmt); + elements_ajoutes << nvel_elmt; + } else { + delete nvel_elmt; + qDebug("Le chargement des parametres d'un element a echoue"); + } } } @@ -350,38 +329,6 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in 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 *Diagram::elementFromXml(QDomElement &e, QHash &table_id_adr) { - // cree un element dont le type correspond à l'id type - QString type = e.attribute("type"); - QString chemin_fichier = QETApp::realPath(type); - int etat; - Element *nvel_elmt = new CustomElement(chemin_fichier, 0, 0, &etat); - if (etat != 0) return(false); - - // charge les caracteristiques de l'element - 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); - bool conv_ok; - int read_ori = e.attribute("sens").toInt(&conv_ok); - if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = nvel_elmt -> defaultOrientation(); - nvel_elmt -> setOrientation((Terminal::Orientation)read_ori); - nvel_elmt -> setSelected(e.attribute("selected") == "selected"); - } - return(retour ? nvel_elmt : NULL); -} - /** Verifie si la liste des elements selectionnes a change. Si oui, le signal selectionChanged() est emis. diff --git a/diagram.h b/diagram.h index 63d7b69dd..4dbe41371 100644 --- a/diagram.h +++ b/diagram.h @@ -58,8 +58,6 @@ bool draw_grid; bool use_border; - Element *elementFromXml(QDomElement &, QHash &); - private slots: void slot_checkSelectionChange(); diff --git a/element.cpp b/element.cpp index 62c04f88a..ec910a4cb 100644 --- a/element.cpp +++ b/element.cpp @@ -279,3 +279,130 @@ bool Element::valideXml(QDomElement &e) { if (!conv_ok) return(false); return(true); } + +/** + 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 Element::fromXml(QDomElement &e, QHash &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 liste_terminals; + // 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 terminals = enfant.toElement(); + if (terminals.isNull() || terminals.tagName() != "bornes") continue; + // parcours des enfants de l'element XML "bornes" + for (QDomNode node_terminal = terminals.firstChild() ; !node_terminal.isNull() ; node_terminal = node_terminal.nextSibling()) { + // on s'interesse a l'element XML "borne" + QDomElement terminal = node_terminal.toElement(); + if (!terminal.isNull() && Terminal::valideXml(terminal)) liste_terminals.append(terminal); + } + } + + QHash priv_id_adr; + int terminals_non_trouvees = 0; + foreach(QGraphicsItem *qgi, children()) { + if (Terminal *p = qgraphicsitem_cast(qgi)) { + bool terminal_trouvee = false; + foreach(QDomElement qde, liste_terminals) { + if (p -> fromXml(qde)) { + priv_id_adr.insert(qde.attribute("id").toInt(), p); + terminal_trouvee = true; + break; + } + } + if (!terminal_trouvee) ++ terminals_non_trouvees; + } + } + + if (terminals_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)); + } + } + + // position, selection et orientation + setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble()); + setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); + bool conv_ok; + int read_ori = e.attribute("sens").toInt(&conv_ok); + if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = defaultOrientation(); + setOrientation((Terminal::Orientation)read_ori); + setSelected(e.attribute("selected") == "selected"); + + return(true); +} + +/** + Permet d'exporter l'element en XML + @param document Document XML a utiliser + @param table_adr_id Table de correspondance entre les adresses des bornes + et leur id dans la representation XML ; cette table completee par cette + methode + @return L'element XML representant cet element electrique +*/ +QDomElement Element::toXml(QDomDocument &document, QHash &table_adr_id) const { + QDomElement element = document.createElement("element"); + + // type + QString chemin_elmt = typeId(); + QString type_elmt = QETApp::symbolicPath(chemin_elmt); + element.setAttribute("type", type_elmt); + + // position, selection et orientation + element.setAttribute("x", pos().x()); + element.setAttribute("y", pos().y()); + if (isSelected()) element.setAttribute("selected", "selected"); + element.setAttribute("sens", QString("%1").arg(orientation())); + + /* recupere le premier id a utiliser pour les bornes de cet element */ + int id_terminal = 0; + if (!table_adr_id.isEmpty()) { + // trouve le plus grand id + int max_id_t = -1; + foreach (int id_t, table_adr_id.values()) { + if (id_t > max_id_t) max_id_t = id_t; + } + id_terminal = max_id_t + 1; + } + + // enregistrement des bornes de l'appareil + QDomElement terminals = document.createElement("bornes"); + // pour chaque enfant de l'element + foreach(QGraphicsItem *child, children()) { + // si cet enfant est une borne + if (Terminal *t = qgraphicsitem_cast(child)) { + // alors on enregistre la borne + QDomElement terminal = t -> toXml(document); + terminal.setAttribute("id", id_terminal); + table_adr_id.insert(t, id_terminal ++); + terminals.appendChild(terminal); + } + } + element.appendChild(terminals); + return(element); +} diff --git a/element.h b/element.h index dcf043fd0..7370d80b9 100644 --- a/element.h +++ b/element.h @@ -13,9 +13,9 @@ virtual int nbTerminalsMin() const = 0; virtual int nbTerminalsMax() const = 0; virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0; - virtual QString typeId() = 0; + virtual QString typeId() const = 0; - virtual QString nom() = 0; + virtual QString nom() const = 0; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); QRectF boundingRect() const; QSize setSize(int, int); @@ -25,16 +25,15 @@ void deselect(); QPixmap pixmap(); QVariant itemChange(GraphicsItemChange, const QVariant &); - bool orientation() const; - bool invertOrientation(); void setPos(const QPointF &); void setPos(qreal, qreal); inline bool connexionsInternesAcceptees() { return(peut_relier_ses_propres_terminals); } inline void setConnexionsInternesAcceptees(bool cia) { peut_relier_ses_propres_terminals = cia; } static bool valideXml(QDomElement &); - virtual bool fromXml(QDomElement &, QHash&) = 0; + virtual bool fromXml(QDomElement &, QHash&); + virtual QDomElement toXml (QDomDocument &, QHash&) const; // methodes d'acces aux possibilites d'orientation - inline Terminal::Orientation orientation() { return(ori); } + inline Terminal::Orientation orientation() const { return(ori); } inline bool acceptOrientation(Terminal::Orientation o) { switch(o) { case Terminal::Nord: return(ori_n); diff --git a/fixedelement.cpp b/fixedelement.cpp index e7e6328b3..fc125a33e 100644 --- a/fixedelement.cpp +++ b/fixedelement.cpp @@ -18,65 +18,3 @@ int FixedElement::nbTerminalsMin() const { int FixedElement::nbTerminalsMax() const { return(nbTerminals()); } - -/** - 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 FixedElement::fromXml(QDomElement &e, QHash &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 liste_terminals; - // 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 terminals = enfant.toElement(); - if (terminals.isNull() || terminals.tagName() != "bornes") continue; - // parcours des enfants de l'element XML "bornes" - for (QDomNode node_terminal = terminals.firstChild() ; !node_terminal.isNull() ; node_terminal = node_terminal.nextSibling()) { - // on s'interesse a l'element XML "borne" - QDomElement terminal = node_terminal.toElement(); - if (!terminal.isNull() && Terminal::valideXml(terminal)) liste_terminals.append(terminal); - } - } - - QHash priv_id_adr; - int terminals_non_trouvees = 0; - foreach(QGraphicsItem *qgi, children()) { - if (Terminal *p = qgraphicsitem_cast(qgi)) { - bool terminal_trouvee = false; - foreach(QDomElement qde, liste_terminals) { - if (p -> fromXml(qde)) { - priv_id_adr.insert(qde.attribute("id").toInt(), p); - terminal_trouvee = true; - break; - } - } - if (!terminal_trouvee) ++ terminals_non_trouvees; - } - } - - if (terminals_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); -} diff --git a/fixedelement.h b/fixedelement.h index 55ca20957..374c9921e 100644 --- a/fixedelement.h +++ b/fixedelement.h @@ -6,10 +6,9 @@ FixedElement(QGraphicsItem * = 0, Diagram * = 0); int nbTerminalsMin() const; int nbTerminalsMax() const; - virtual bool fromXml(QDomElement &, QHash&); virtual int nbTerminals() const = 0; virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0; - virtual QString typeId() = 0; - virtual QString nom() = 0; + virtual QString typeId() const = 0; + virtual QString nom() const = 0; }; #endif