diff --git a/conductorproperties.cpp b/conductorproperties.cpp new file mode 100644 index 000000000..7df16bb89 --- /dev/null +++ b/conductorproperties.cpp @@ -0,0 +1,235 @@ +#include "conductorproperties.h" + +/** + 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::ConductorSegmentType 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 + 1); + 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.35); + } + } + } else { + interleave = rect.height() / (symbols_count + 1); + 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::ConductorSegmentType 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::ConductorSegmentType, QPointF center, qreal size) { + painter -> save(); + + // prepare le QPainter + if (painter -> brush() == Qt::NoBrush) painter -> setBrush(Qt::black); + painter -> setPen(Qt::NoPen); + + // 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()); +} + +/** + exporte les parametres du conducteur 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 ConductorProperties::toXml(QDomDocument &d, QDomElement &e) const { + e.setAttribute("type", typeToString(type)); + if (type == Single) { + singleLineProperties.toXml(d, e); + } else if (type == Multi) { + e.setAttribute("num", text); + } +} + +/** + 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 ConductorProperties::fromXml(QDomElement &e) { + if (e.attribute("type") == typeToString(Single)) { + // recupere les parametres specifiques a un conducteur unifilaire + singleLineProperties.fromXml(e); + type = Single; + } else if (e.attribute("type") == typeToString(Simple)) { + type = Simple; + } else { + // recupere le champ de texte + text = e.attribute("num"); + type = Multi; + } +} + +/** + @param t type du conducteur +*/ +QString ConductorProperties::typeToString(ConductorType t) { + switch(t) { + case Simple: return("simple"); + case Single: return("single"); + case Multi: return("mutli"); + default: return(QString()); + } +} + +int ConductorProperties::operator==(const ConductorProperties &other) { + return( + other.type == type &&\ + other.text == text &&\ + other.singleLineProperties == singleLineProperties + ); +} + +int ConductorProperties::operator!=(const ConductorProperties &other) { + return(!(other == (*this))); +} + +int SingleLineProperties::operator==(const SingleLineProperties &other) const { + return( + other.hasGround == hasGround &&\ + other.hasNeutral == hasNeutral &&\ + other.phases == phases + ); +} + +int SingleLineProperties::operator!=(const SingleLineProperties &other) const { + return(!(other == (*this))); +} diff --git a/conductorproperties.h b/conductorproperties.h new file mode 100644 index 000000000..32b688c22 --- /dev/null +++ b/conductorproperties.h @@ -0,0 +1,73 @@ +#ifndef CONDUCTOR_PROPERTIES_H +#define CONDUCTOR_PROPERTIES_H +#include "qet.h" +#include +#include +/** + 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::ConductorSegmentType, const QRectF &); + void toXml(QDomDocument &, QDomElement &) const; + void fromXml(QDomElement &); + + /// indique si le conducteur unifilaire doit afficher le symbole terre + bool hasGround; + /// indique si le conducteur unifilaire doit afficher le symbole neutre + bool hasNeutral; + + int operator==(const SingleLineProperties &) const; + int operator!=(const SingleLineProperties &) const; + + private: + unsigned short int phases; + void drawGround (QPainter *, QET::ConductorSegmentType, QPointF, qreal); + void drawNeutral(QPainter *, QET::ConductorSegmentType, QPointF, qreal); +}; + +/** + Cette classe represente les proprietes specifiques a un conducteur, + en dehors de ses bornes et de son trajet. +*/ +class ConductorProperties { + // constructeurs, destructeur + public: + /** + Constructeur : par defaut, les proprietes font un conducteur + multifilaire dont le texte est "_" + */ + ConductorProperties() : type(Multi), text("_") { + } + + /// Destructeur + virtual ~ConductorProperties() { + } + + enum ConductorType { Simple, Single, Multi }; + + // attributs + /// type du conducteur + ConductorType type; + + /// texte affiche si le conducteur est multifilaire + QString text; + + /// proprietes si le conducteur est unifilaire + SingleLineProperties singleLineProperties; + + // methodes + void toXml(QDomDocument &, QDomElement &) const; + void fromXml(QDomElement &); + static QString typeToString(ConductorType); + + // operateurs + int operator==(const ConductorProperties &); + int operator!=(const ConductorProperties &); +}; +#endif diff --git a/diagram.h b/diagram.h index 9191b353f..6187a934c 100644 --- a/diagram.h +++ b/diagram.h @@ -5,6 +5,7 @@ #include "qetdiagrameditor.h" #include "borderinset.h" #include "qgimanager.h" +#include "conductorproperties.h" class Element; class Terminal; class Conductor; @@ -27,6 +28,9 @@ class Diagram : public QGraphicsScene { // attributs public: enum BorderOptions { EmptyBorder, Inset, Columns }; + /// Proprietes par defaut des nouveaux conducteurs + ConductorProperties defaultConductorProperties; + /// Dimensions et cartouches du schema BorderInset border_and_inset; QPointF current_movement; /// taille de la grille en abscisse diff --git a/diagramview.cpp b/diagramview.cpp index c8e7a9296..86e34dd74 100644 --- a/diagramview.cpp +++ b/diagramview.cpp @@ -722,7 +722,7 @@ void DiagramView::editConductor() { // execute le dialogue et met a jour le conducteur if (conductor_dialog.exec() == QDialog::Accepted) { - // recupere les nouvelles propietes + // recupere les nouvelles proprietes ConductorProperties new_properties = cpw -> conductorProperties(); if (new_properties != old_properties) { @@ -753,6 +753,30 @@ void DiagramView::resetConductors() { scene -> undoStack().push(new ResetConductorCommand(conductors_and_profiles)); } +/** + Lance un dialogue permettant de modifier les proprietes par defaut des + futurs nouveaux conducteurs +*/ +void DiagramView::editDefaultConductorProperties() { + // initialise l'editeur de proprietes pour le conducteur + ConductorPropertiesWidget *cpw = new ConductorPropertiesWidget(scene -> defaultConductorProperties); + + // l'insere dans un dialogue + QDialog conductor_dialog; + conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s par d\351faut des conducteurs")); + QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog); + dialog_layout -> addWidget(cpw); + QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + dialog_layout -> addWidget(dbb); + connect(dbb, SIGNAL(accepted()), &conductor_dialog, SLOT(accept())); + connect(dbb, SIGNAL(rejected()), &conductor_dialog, SLOT(reject())); + + // execute le dialogue et met a jour le conducteur + if (conductor_dialog.exec() == QDialog::Accepted) { + scene -> defaultConductorProperties = cpw -> conductorProperties(); + } +} + /** Gere les evenements de la DiagramView @param e Evenement diff --git a/diagramview.h b/diagramview.h index 213d3a032..ca0e591bf 100644 --- a/diagramview.h +++ b/diagramview.h @@ -76,6 +76,7 @@ class DiagramView : public QGraphicsView { void updateWindowTitle(); void editConductor(); void resetConductors(); + void editDefaultConductorProperties(); private slots: void slot_selectionChanged(); diff --git a/ico/conductor3.png b/ico/conductor3.png new file mode 100644 index 000000000..a00582c7c Binary files /dev/null and b/ico/conductor3.png differ diff --git a/qelectrotech.qrc b/qelectrotech.qrc index df4a291d2..1c6c15cc3 100644 --- a/qelectrotech.qrc +++ b/qelectrotech.qrc @@ -15,6 +15,7 @@ ico/circle.png ico/conductor.png ico/conductor2.png + ico/conductor3.png ico/configure.png ico/copy.png ico/cut.png diff --git a/qetdiagrameditor.cpp b/qetdiagrameditor.cpp index a33cbe6b8..277775a07 100644 --- a/qetdiagrameditor.cpp +++ b/qetdiagrameditor.cpp @@ -163,6 +163,7 @@ void QETDiagramEditor::actions() { rotate_selection = new QAction(QIcon(":/ico/pivoter.png"), tr("Pivoter"), this); conductor_prop = new QAction(QIcon(":/ico/conductor.png"), tr("Propri\351t\351s du conducteur"), this); conductor_reset = new QAction(QIcon(":/ico/conductor2.png"), tr("R\351initialiser les conducteurs"), this); + conductor_default = new QAction(QIcon(":/ico/conductor3.png"), tr("Conducteurs par d\351faut"), this); infos_diagram = new QAction(QIcon(":/ico/info.png"), tr("Propri\351t\351s du sch\351ma"), this); add_column = new QAction(QIcon(":/ico/add_col.png"), tr("Ajouter une colonne"), this); remove_column = new QAction(QIcon(":/ico/remove_col.png"), tr("Enlever une colonne"), this); @@ -213,6 +214,7 @@ void QETDiagramEditor::actions() { conductor_prop -> setShortcut(QKeySequence(tr("Ctrl+J"))); conductor_reset -> setShortcut(QKeySequence(tr("Ctrl+K"))); infos_diagram -> setShortcut(QKeySequence(tr("Ctrl+L"))); + conductor_default -> setShortcut(QKeySequence(tr("Ctrl+D"))); zoom_in -> setShortcut(QKeySequence::ZoomIn); zoom_out -> setShortcut(QKeySequence::ZoomOut); @@ -248,6 +250,7 @@ void QETDiagramEditor::actions() { rotate_selection -> setStatusTip(tr("Pivote les \351l\351ments s\351lectionn\351s")); conductor_prop -> setStatusTip(tr("\311dite les propri\351t\351s du conducteur s\351lectionn\351")); conductor_reset -> setStatusTip(tr("Recalcule les chemins des conducteurs sans tenir compte des modifications")); + conductor_default -> setStatusTip(tr("Sp\351cifie les propri\351t\351s par d\351faut des conducteurs")); infos_diagram -> setStatusTip(tr("\311dite les informations affich\351es par le cartouche")); add_column -> setStatusTip(tr("Ajoute une colonne au sch\351ma")); remove_column -> setStatusTip(tr("Enl\350ve une colonne au sch\351ma")); @@ -319,6 +322,7 @@ void QETDiagramEditor::actions() { connect(prev_window, SIGNAL(triggered()), &workspace, SLOT(activatePreviousWindow()) ); connect(conductor_prop, SIGNAL(triggered()), this, SLOT(slot_editConductor()) ); connect(conductor_reset, SIGNAL(triggered()), this, SLOT(slot_resetConductors()) ); + connect(conductor_default,SIGNAL(triggered()), this, SLOT(slot_editDefaultConductors())); connect(infos_diagram, SIGNAL(triggered()), this, SLOT(slot_editInfos()) ); connect(add_column, SIGNAL(triggered()), this, SLOT(slot_addColumn()) ); connect(remove_column, SIGNAL(triggered()), this, SLOT(slot_removeColumn()) ); @@ -378,6 +382,7 @@ void QETDiagramEditor::menus() { menu_edition -> addSeparator(); menu_edition -> addAction(conductor_prop); menu_edition -> addAction(conductor_reset); + menu_edition -> addAction(conductor_default); menu_edition -> addSeparator(); menu_edition -> addAction(infos_diagram); menu_edition -> addAction(add_column); @@ -459,6 +464,7 @@ void QETDiagramEditor::toolbar() { view_bar -> addAction(zoom_reset); diagram_bar -> addAction(infos_diagram); + diagram_bar -> addAction(conductor_default); diagram_bar -> addAction(conductor_prop); diagram_bar -> addAction(conductor_reset); @@ -699,6 +705,7 @@ void QETDiagramEditor::slot_updateActions() { zoom_reset -> setEnabled(opened_document); conductor_prop -> setEnabled(opened_document && selected_conductors_count == 1); conductor_reset -> setEnabled(opened_document && selected_conductors_count); + conductor_default-> setEnabled(opened_document); infos_diagram -> setEnabled(opened_document); add_column -> setEnabled(opened_document); remove_column -> setEnabled(opened_document); @@ -880,3 +887,12 @@ void QETDiagramEditor::slot_resetConductors() { dv -> resetConductors(); } } + +/** + Edite les proprietes par defaut des conducteurs +*/ +void QETDiagramEditor::slot_editDefaultConductors() { + if (DiagramView *dv = currentDiagram()) { + dv->editDefaultConductorProperties(); + } +} diff --git a/qetdiagrameditor.h b/qetdiagrameditor.h index c68e0e695..d4d24a5e5 100644 --- a/qetdiagrameditor.h +++ b/qetdiagrameditor.h @@ -67,6 +67,7 @@ class QETDiagramEditor : public QMainWindow { void slot_shrink(); void slot_editConductor(); void slot_resetConductors(); + void slot_editDefaultConductors(); // attributs protected: @@ -94,6 +95,7 @@ class QETDiagramEditor : public QMainWindow { QAction *rotate_selection; QAction *conductor_prop; QAction *conductor_reset; + QAction *conductor_default; QAction *infos_diagram; QAction *add_column; QAction *remove_column; diff --git a/terminal.cpp b/terminal.cpp index fabab78e8..f9392cb20 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -372,7 +372,9 @@ void Terminal::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { // derniere verification : verifier que cette borne n'est pas deja reliee a l'autre borne foreach (Conductor *f, liste_conductors) if (f -> terminal1 == p || f -> terminal2 == p) return; // autrement, on pose un conducteur - s -> undoStack().push(new AddConductorCommand(s, new Conductor(this, p))); + Conductor * new_conductor = new Conductor(this, p); + new_conductor -> setProperties(s -> defaultConductorProperties); + s -> undoStack().push(new AddConductorCommand(s, new_conductor)); } }