diff --git a/conducer.cpp b/conducer.cpp index d3b8f3480..9af4b9595 100644 --- a/conducer.cpp +++ b/conducer.cpp @@ -57,6 +57,7 @@ Conducer::Conducer(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene * text_item -> setPlainText("_"); text_item -> previous_text = "_"; calculateTextItemPosition(); + //setSingleLine(true); text_item -> setParentItem(this); } @@ -416,6 +417,13 @@ void Conducer::paint(QPainter *qp, const QStyleOptionGraphicsItem */*qsogi*/, QW // dessin du conducteur qp -> drawPath(path()); + if (isSingleLine()) { + singleLineProperties.draw( + qp, + middleSegment() -> isHorizontal() ? QET::Horizontal : QET::Vertical, + QRectF(middleSegment() -> middle() - QPointF(7.5, 7.5), QSizeF(15.0, 15.0)) + ); + } // dessin des points d'accroche du conducteur si celui-ci est selectionne if (isSelected()) { @@ -776,8 +784,17 @@ bool Conducer::hasClickedOn(QPointF press_point, QPointF point) const { @return true si le chargement a reussi, false sinon */ bool Conducer::fromXml(QDomElement &e) { - text_item -> setPlainText(e.attribute("num")); - text_item -> previous_text = e.attribute("num"); + // recupere la "configuration" du conducteur + if (e.attribute("singleline") == "true") { + // recupere les parametres specifiques a un conducteur unifilaire + singleLineProperties.fromXml(e); + setSingleLine(true); + } else { + // recupere le champ de texte + text_item -> setPlainText(e.attribute("num")); + text_item -> previous_text = e.attribute("num"); + setSingleLine(false); + } // parcourt les elements XML "segment" et en extrait deux listes de longueurs // les segments non valides sont ignores @@ -854,19 +871,26 @@ QDomElement Conducer::toXml(QDomDocument &d, QHash &table_adr_i QDomElement e = d.createElement("conducer"); e.setAttribute("terminal1", table_adr_id.value(terminal1)); e.setAttribute("terminal2", table_adr_id.value(terminal2)); - e.setAttribute("num", text_item -> toPlainText()); // on n'exporte les segments du conducteur que si ceux-ci ont // ete modifies par l'utilisateur - if (!modified_path) return(e); + if (modified_path) { + // parcours et export des segments + QDomElement current_segment; + foreach(ConducerSegment *segment, segmentsList()) { + current_segment = d.createElement("segment"); + current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical"); + current_segment.setAttribute("length", segment -> length()); + e.appendChild(current_segment); + } + } - // parcours et export des segments - QDomElement current_segment; - foreach(ConducerSegment *segment, segmentsList()) { - current_segment = d.createElement("segment"); - current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical"); - current_segment.setAttribute("length", segment -> length()); - e.appendChild(current_segment); + // exporte la "configuration" du conducteur + e.setAttribute("singleline", isSingleLine() ? "true" : "false"); + if (isSingleLine()) { + singleLineProperties.toXml(d, e); + } else { + e.setAttribute("num", text_item -> toPlainText()); } return(e); } @@ -975,3 +999,175 @@ void Conducer::setProfile(const ConducerProfile &cp) { } calculateTextItemPosition(); } + +bool Conducer::isSingleLine() const { + return(is_single_line); +} + +void Conducer::setSingleLine(bool sl) { + is_single_line = sl; + text_item -> setVisible(!is_single_line); +} + +/** + Constructeur par defaut +*/ +SingleLineProperties::SingleLineProperties() : + hasGround(true), + hasNeutral(true), + phases(1) +{ +} + +/// Destructeur +SingleLineProperties::~SingleLineProperties() { +} + +/** + Definit le nombre de phases (0, 1, 2, ou 3) + @param n Nombre de phases +*/ +void SingleLineProperties::setPhasesCount(int n) { + phases = qBound(0, n, 3); +} + +/// @return le nombre de phases (0, 1, 2, ou 3) +unsigned short int SingleLineProperties::phasesCount() { + return(phases); +} + +/** + Dessine les symboles propres a un conducteur unifilaire + @param painter QPainter a utiliser pour dessiner les symboles + @param direction direction du segment sur lequel les symboles apparaitront + @param rect rectangle englobant le dessin ; utilise pour specifier a la fois la position et la taille du dessin +*/ +void SingleLineProperties::draw(QPainter *painter, QET::ConducerSegmentType direction, const QRectF &rect) { + // s'il n'y a rien a dessiner, on retourne immediatement + if (!hasNeutral && !hasGround && !phases) return; + + // prepare le QPainter + painter -> save(); + QPen pen(painter -> pen()); + pen.setCapStyle(Qt::FlatCap); + pen.setJoinStyle(Qt::MiterJoin); + painter -> setPen(pen); + painter -> setRenderHint(QPainter::Antialiasing, true); + + uint symbols_count = (hasNeutral ? 1 : 0) + (hasGround ? 1 : 0) + phases; + qreal interleave; + qreal symbol_width; + if (direction == QET::Horizontal) { + interleave = rect.width() / symbols_count; + symbol_width = rect.width() / 12; + for (uint i = 1 ; i <= symbols_count ; ++ i) { + // dessine le tronc du symbole + QPointF symbol_p1(rect.x() + (i * interleave) + symbol_width, rect.y() + rect.height() * 0.75); + QPointF symbol_p2(rect.x() + (i * interleave) - symbol_width, rect.y() + rect.height() * 0.25); + painter -> drawLine(QLineF(symbol_p1, symbol_p2)); + + // dessine le reste des symboles terre et neutre + if (hasGround && i == 1) { + drawGround(painter, direction, symbol_p2, symbol_width * 2.0); + } else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) { + drawNeutral(painter, direction, symbol_p2, symbol_width * 1.5); + } + } + } else { + interleave = rect.height() / symbols_count; + symbol_width = rect.height() / 12; + for (uint i = 1 ; i <= symbols_count ; ++ i) { + // dessine le tronc du symbole + QPointF symbol_p2(rect.x() + rect.width() * 0.75, rect.y() + (i * interleave) - symbol_width); + QPointF symbol_p1(rect.x() + rect.width() * 0.25, rect.y() + (i * interleave) + symbol_width); + painter -> drawLine(QLineF(symbol_p1, symbol_p2)); + + // dessine le reste des symboles terre et neutre + if (hasGround && i == 1) { + drawGround(painter, direction, symbol_p2, symbol_width * 2.0); + } else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) { + drawNeutral(painter, direction, symbol_p2, symbol_width * 1.5); + } + } + } + painter -> restore(); +} + +/** + Dessine le segment correspondant au symbole de la terre sur un conducteur unifilaire + @param painter QPainter a utiliser pour dessiner le segment + @param direction direction du segment sur lequel le symbole apparaitra + @param center centre du segment + @param size taille du segment +*/ +void SingleLineProperties::drawGround(QPainter *painter, QET::ConducerSegmentType direction, QPointF center, qreal size) { + painter -> save(); + + // prepare le QPainter + painter -> setRenderHint(QPainter::Antialiasing, false); + QPen pen2(painter -> pen()); + pen2.setCapStyle(Qt::SquareCap); + painter -> setPen(pen2); + + // dessine le segment representant la terre + qreal half_size = size / 2.0; + QPointF offset_point( + (direction == QET::Horizontal) ? half_size : 0.0, + (direction == QET::Horizontal) ? 0.0 : half_size + ); + painter -> drawLine( + QLineF( + center + offset_point, + center - offset_point + ) + ); + + painter -> restore(); +} + +/** + Dessine le cercle correspondant au symbole du neutre sur un conducteur unifilaire + @param painter QPainter a utiliser pour dessiner le segment + @param direction direction du segment sur lequel le symbole apparaitra + @param center centre du cercle + @param size diametre du cercle +*/ +void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConducerSegmentType, QPointF center, qreal size) { + painter -> save(); + + // prepare le QPainter + painter -> setBrush(Qt::black); + + // desine le cercle representant le neutre + painter -> drawEllipse( + QRectF( + center - QPointF(size / 2.0, size / 2.0), + QSizeF(size, size) + ) + ); + + painter -> restore(); +} + +/** + exporte les parametres du conducteur unifilaire sous formes d'attributs XML + ajoutes a l'element e. + @param d Document XML ; utilise pour ajouter (potentiellement) des elements XML + @param e Element XML auquel seront ajoutes des attributs +*/ +void SingleLineProperties::toXml(QDomDocument &, QDomElement &e) const { + e.setAttribute("ground", hasGround ? "true" : "false"); + e.setAttribute("neutral", hasNeutral ? "true" : "false"); + e.setAttribute("phase", phases); +} + +/** + importe les parametres du conducteur unifilaire a partir des attributs XML + de l'element e + @param e Element XML dont les attributs seront lus +*/ +void SingleLineProperties::fromXml(QDomElement &e) { + hasGround = e.attribute("ground") == "true"; + hasNeutral = e.attribute("neutral") == "true"; + setPhasesCount(e.attribute("phase").toInt()); +} diff --git a/conducer.h b/conducer.h index 8c3499451..326305cae 100644 --- a/conducer.h +++ b/conducer.h @@ -6,6 +6,26 @@ #include "diagramtextitem.h" class ConducerSegment; class Element; +/** + Cette classe represente les proprietes specifiques a un conducteur unifilaire +*/ +class SingleLineProperties { + public: + SingleLineProperties(); + virtual ~SingleLineProperties(); + void setPhasesCount(int); + unsigned short int phasesCount(); + void draw(QPainter *, QET::ConducerSegmentType, const QRectF &); + void toXml(QDomDocument &, QDomElement &) const; + void fromXml(QDomElement &); + bool hasGround; + bool hasNeutral; + private: + unsigned short int phases; + void drawGround (QPainter *, QET::ConducerSegmentType, QPointF, qreal); + void drawNeutral(QPainter *, QET::ConducerSegmentType, QPointF, qreal); +}; + /** Cette classe represente un conducteur. Un conducteur relie deux bornes d'element. */ @@ -27,24 +47,8 @@ class Conducer : public QGraphicsPathItem { Terminal *terminal1; ///Deuxieme borne a laquelle le fil est rattache Terminal *terminal2; - - private: - /// booleen indiquant si le fil est encore valide - bool destroyed; - DiagramTextItem *text_item; - ConducerSegment *segments; - QPointF press_point; - bool moving_point; - bool moving_segment; - int moved_point; - qreal previous_z_value; - ConducerSegment *moved_segment; - bool modified_path; - bool has_to_save_profile; - ConducerProfile conducer_profile; - static QPen conducer_pen; - static QBrush conducer_brush; - static bool pen_and_brush_initialized; + /// caracteristiques des conducteurs unifilaires + SingleLineProperties singleLineProperties; // methodes public: @@ -64,6 +68,8 @@ class Conducer : public QGraphicsPathItem { QDomElement toXml(QDomDocument &, QHash &) const; const QList segmentsList() const; void setProfile(const ConducerProfile &); + void setSingleLine(bool); + bool isSingleLine() const; protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *); @@ -71,6 +77,33 @@ class Conducer : public QGraphicsPathItem { virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *); virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *); + private: + /// booleen indiquant si le fil est encore valide + bool destroyed; + /// booleen indiquant le mode du conducteur : unifilaire ou non + bool is_single_line; + /// champ de texte editable pour les conducteurs non unifilaires + DiagramTextItem *text_item; + /// Segments composant le conducteur + ConducerSegment *segments; + /// Attributs lies aux manipulations a la souris + QPointF press_point; + bool moving_point; + bool moving_segment; + int moved_point; + qreal previous_z_value; + ConducerSegment *moved_segment; + /// booleen indiquant si le conducteur a ete modifie manuellement par l'utilisateur + bool modified_path; + /// booleen indiquant s'il faut sauver le profil courant au plus tot + bool has_to_save_profile; + /// profil du conducteur : "photo" de ce a quoi le conducteur doit ressembler + ConducerProfile conducer_profile; + /// QPen et QBrush utilises pour dessiner les conducteurs + static QPen conducer_pen; + static QBrush conducer_brush; + static bool pen_and_brush_initialized; + private: void segmentsToPath(); void saveProfile(bool = true); diff --git a/lang/qet_en.qm b/lang/qet_en.qm index fafcac0d3..a9ad8177a 100644 Binary files a/lang/qet_en.qm and b/lang/qet_en.qm differ diff --git a/lang/qet_en.ts b/lang/qet_en.ts index cd98462fb..fe293b64f 100644 --- a/lang/qet_en.ts +++ b/lang/qet_en.ts @@ -1,6 +1,5 @@ - AboutQET @@ -679,47 +678,47 @@ Please check rights of the directory ExportDialog - + Aperçu Preview - + Bitmap (*.bmp) Bitmap (*.bmp) - + Conserver les couleurs Keep colors - + Conserver les proportions Keep aspect ratio - + Dessiner la grille Draw the grid - + Dessiner le cadre Draw the border - + Dessiner le cartouche Draw the inset - + Dessiner les colonnes Draw columns - + Dimensions Dimensions @@ -729,90 +728,95 @@ Please check rights of the directory Export - + Exporter le cadre Export the border - + Exporter les éléments Export only elements - + Exporter vers le fichier Export to file - + Fichier non spécifié Filename not given - + Format : Format : - + Hauteur : Height : - + Il semblerait que vous n'ayez pas les permissions nécessaires pour écrire dans ce fichier.. It seems you don't have the permissions needed to write this file.. - + Images (*.png *.bmp *.jpg) Pictures (*.png *.bmp *.jpg) - + Impossible d'écrire dans ce fichier Can't Write to the file - + JPEG (*.jpg) JPEG (*.jpg) - + Largeur : Width : - + Nom de fichier : Filename : - + Options Options - + Parcourir Browse - + PNG (*.png) PNG (*.png) - + px px - + Vous devez spécifier le chemin du fichier dans lequel sera enregistrée l'image. You must give a filename to save the picture. + + + Dessiner les bornes + Draw terminals + HotspotEditor