QElectroTech  0.70
conductorproperties.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2006-2019 The QElectroTech Team
3  This file is part of QElectroTech.
4 
5  QElectroTech is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 2 of the License, or
8  (at your option) any later version.
9 
10  QElectroTech is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "conductorproperties.h"
19 #include <QPainter>
20 #include <utility>
21 
26  hasGround(true),
27  hasNeutral(true),
28  is_pen(false),
29  phases(1)
30 {
31 }
32 
35 }
36 
42  phases = qBound(0, n, 3);
43 }
44 
46 unsigned short int SingleLineProperties::phasesCount() {
47  return(phases);
48 }
49 
56  return(hasNeutral && hasGround && is_pen);
57 }
58 
65 void SingleLineProperties::draw(QPainter *painter, QET::ConductorSegmentType direction, const QRectF &rect) {
66  // s'il n'y a rien a dessiner, on retourne immediatement
67  if (!hasNeutral && !hasGround && !phases) return;
68 
69  // prepare le QPainter
70  painter -> save();
71  QPen pen(painter -> pen());
72  pen.setCapStyle(Qt::FlatCap);
73  pen.setJoinStyle(Qt::MiterJoin);
74  pen.setStyle(Qt::SolidLine);
75  pen.setWidthF(1);
76  painter -> setPen(pen);
77  painter -> setRenderHint(QPainter::Antialiasing, true);
78 
79  uint symbols_count = (hasNeutral ? 1 : 0) + (hasGround ? 1 : 0) - (isPen() ? 1 : 0) + phases;
80  qreal interleave_base = (direction == QET::Horizontal ? rect.width() : rect.height());
81  qreal interleave = interleave_base / (symbols_count + 1);;
82  qreal symbol_width = interleave_base / 12;
83 
84  for (uint i = 1 ; i <= symbols_count ; ++ i) {
85  // dessine le tronc du symbole
86  QPointF symbol_p1, symbol_p2;
87  if (direction == QET::Horizontal) {
88  symbol_p1 = QPointF(rect.x() + (i * interleave) + symbol_width, rect.y() + rect.height() * 0.75);
89  symbol_p2 = QPointF(rect.x() + (i * interleave) - symbol_width, rect.y() + rect.height() * 0.25);
90  } else {
91  symbol_p2 = QPointF(rect.x() + rect.width() * 0.75, rect.y() + (i * interleave) - symbol_width);
92  symbol_p1 = QPointF(rect.x() + rect.width() * 0.25, rect.y() + (i * interleave) + symbol_width);
93  }
94  painter -> drawLine(QLineF(symbol_p1, symbol_p2));
95 
96  // dessine le reste des symboles terre et neutre
97  if (isPen()) {
98  if (i == 1) {
99  drawPen(painter, direction, symbol_p2, symbol_width);
100  }
101  } else {
102  if (hasGround && i == 1) {
103  drawGround(painter, direction, symbol_p2, symbol_width * 2.0);
104  } else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) {
105  drawNeutral(painter, direction, symbol_p2, symbol_width * 1.5);
106  }
107  }
108  }
109  painter -> restore();
110 }
111 
119 void SingleLineProperties::drawGround(QPainter *painter, QET::ConductorSegmentType direction, QPointF center, qreal size) {
120  painter -> save();
121 
122  // prepare le QPainter
123  painter -> setRenderHint(QPainter::Antialiasing, false);
124  QPen pen2(painter -> pen());
125  pen2.setCapStyle(Qt::SquareCap);
126  painter -> setPen(pen2);
127 
128  // dessine le segment representant la terre
129  qreal half_size = size / 2.0;
130  QPointF offset_point(
131  (direction == QET::Horizontal) ? half_size : 0.0,
132  (direction == QET::Horizontal) ? 0.0 : half_size
133  );
134  painter -> drawLine(
135  QLineF(
136  center + offset_point,
137  center - offset_point
138  )
139  );
140 
141  painter -> restore();
142 }
143 
151 void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConductorSegmentType direction, QPointF center, qreal size) {
152  Q_UNUSED(direction);
153  painter -> save();
154 
155  // prepare le QPainter
156  if (painter -> brush() == Qt::NoBrush) painter -> setBrush(Qt::black);
157  painter -> setPen(Qt::NoPen);
158 
159  // desine le cercle representant le neutre
160  painter -> drawEllipse(
161  QRectF(
162  center - QPointF(size / 2.0, size / 2.0),
163  QSizeF(size, size)
164  )
165  );
166 
167  painter -> restore();
168 }
169 
175 void SingleLineProperties::drawPen(QPainter *painter, QET::ConductorSegmentType direction, QPointF center, qreal size) {
176  painter -> save();
177 
178  //painter -> setBrush(Qt::white);
179  // desine le cercle representant le neutre
180  //painter -> drawEllipse(
181  // QRectF(
182  // center - QPointF(size * 1.5 / 2.0, size * 1.5 / 2.0),
183  // QSizeF(size * 1.5, size * 1.5)
184  // )
185  //);
186  drawNeutral(painter, direction, center, size * 1.5);
187 
188  int offset = (size * 1.5 / 2.0);
189  QPointF pos = center + (direction == QET::Horizontal ? QPointF(0.0, -offset - 0.5) : QPointF(offset + 0.5, 0.0));
190  drawGround(painter, direction, pos, 2.0 * size);
191  painter -> restore();
192 }
193 
199 void SingleLineProperties::toXml(QDomElement &e) const {
200  e.setAttribute("ground", hasGround ? "true" : "false");
201  e.setAttribute("neutral", hasNeutral ? "true" : "false");
202  e.setAttribute("phase", phases);
203  if (isPen()) e.setAttribute("pen", "true");
204 }
205 
211 void SingleLineProperties::fromXml(QDomElement &e) {
212  hasGround = e.attribute("ground") == "true";
213  hasNeutral = e.attribute("neutral") == "true";
214  setPhasesCount(e.attribute("phase").toInt());
215  is_pen = (hasGround && hasNeutral && e.attribute("pen", "false") == "true");
216 }
217 
223  type(Multi),
224  color(Qt::black),
225  text("_"),
226  text_size(9),
227  cond_size(1),
228  verti_rotate_text(270),
229  horiz_rotate_text(0),
230  m_show_text(true),
231  m_one_text_per_folio(false),
232  style(Qt::SolidLine)
233 {}
234 
239 }
240 
241 
247 void ConductorProperties::toXml(QDomElement &e) const
248 {
249  e.setAttribute("type", typeToString(type));
250 
251  if (color != QColor(Qt::black))
252  e.setAttribute("color", color.name());
253 
254  e.setAttribute("bicolor", m_bicolor? "true" : "false");
255  e.setAttribute("color2", m_color_2.name());
256  e.setAttribute("dash-size", QString::number(m_dash_size));
257 
258  if (type == Single)
260 
261  e.setAttribute("num", text);
262  e.setAttribute("formula", m_formula);
263  e.setAttribute("function", m_function);
264  e.setAttribute("tension-protocol", m_tension_protocol);
265  e.setAttribute("numsize", QString::number(text_size));
266  e.setAttribute("condsize", QString::number(cond_size));
267  e.setAttribute("displaytext", m_show_text);
268  e.setAttribute("onetextperfolio", m_one_text_per_folio);
269  e.setAttribute("vertirotatetext", QString::number(verti_rotate_text));
270  e.setAttribute("horizrotatetext", QString::number(horiz_rotate_text));
271 
272  QMetaEnum me = QMetaEnum::fromType<Qt::Alignment>();
273  e.setAttribute("horizontal-alignment", me.valueToKey(m_horizontal_alignment));
274  e.setAttribute("vertical-alignment", me.valueToKey(m_vertical_alignment));
275 
276  QString conductor_style = writeStyle();
277  if (!conductor_style.isEmpty())
278  e.setAttribute("style", conductor_style);
279 }
280 
281 
287 void ConductorProperties::fromXml(QDomElement &e)
288 {
289  // get conductor color
290  QColor xml_color= QColor(e.attribute("color"));
291  color = (xml_color.isValid()? xml_color : QColor(Qt::black));
292 
293  QString bicolor_str = e.attribute("bicolor", "false");
294  m_bicolor = bicolor_str == "true"? true : false;
295 
296  QColor xml_color_2 = QColor(e.attribute("color2"));
297  m_color_2 = xml_color_2.isValid()? xml_color_2 : QColor(Qt::black);
298 
299  m_dash_size = e.attribute("dash-size", QString::number(1)).toInt();
300 
301  // read style of conductor
302  readStyle(e.attribute("style"));
303 
304  if (e.attribute("type") == typeToString(Single))
305  {
306  // get specific properties for single conductor
308  type = Single;
309  }
310  else
311  type = Multi;
312 
313  text = e.attribute("num");
314  m_formula = e.attribute("formula");
315  m_function = e.attribute("function");
316  m_tension_protocol = e.attribute("tension-protocol");
317  text_size = e.attribute("numsize", QString::number(9)).toInt();
318  cond_size = e.attribute("condsize", QString::number(1)).toDouble();
319  m_show_text = e.attribute("displaytext", QString::number(1)).toInt();
320  m_one_text_per_folio = e.attribute("onetextperfolio", QString::number(0)).toInt();
321  verti_rotate_text = e.attribute("vertirotatetext").toDouble();
322  horiz_rotate_text = e.attribute("horizrotatetext").toDouble();
323 
324  QMetaEnum me = QMetaEnum::fromType<Qt::Alignment>();
325  m_horizontal_alignment = Qt::Alignment(me.keyToValue(e.attribute("horizontal-alignment", "AlignBottom").toStdString().data()));
326  m_vertical_alignment = Qt::Alignment(me.keyToValue(e.attribute("vertical-alignment", "AlignRight").toStdString().data()));
327 
328  //Keep retrocompatible with version older than 0,4
329  //If the propertie @type is simple (removed since QET 0,4), we set text no visible.
330  //@TODO remove this code for qet 0.6 or later
331  if (e.attribute("type") == "simple") m_show_text = false;
332 }
333 
338 void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) const
339 {
340  settings.setValue(prefix + "color", color.name());
341  settings.setValue(prefix + "bicolor", m_bicolor);
342  settings.setValue(prefix + "color2", m_color_2.name());
343  settings.setValue(prefix + "dash-size", m_dash_size);
344  settings.setValue(prefix + "style", writeStyle());
345  settings.setValue(prefix + "type", typeToString(type));
346  settings.setValue(prefix + "text", text);
347  settings.setValue(prefix + "formula", m_formula);
348  settings.setValue(prefix + "function", m_function);
349  settings.setValue(prefix + "tension-protocol", m_tension_protocol);
350  settings.setValue(prefix + "textsize", QString::number(text_size));
351  settings.setValue(prefix + "size", QString::number(cond_size));
352  settings.setValue(prefix + "displaytext", m_show_text);
353  settings.setValue(prefix + "onetextperfolio", m_one_text_per_folio);
354  settings.setValue(prefix + "vertirotatetext", QString::number(verti_rotate_text));
355  settings.setValue(prefix + "horizrotatetext", QString::number(horiz_rotate_text));
356 
357  QMetaEnum me = QMetaEnum::fromType<Qt::Alignment>();
358  settings.setValue(prefix + "horizontal-alignment", me.valueToKey(m_horizontal_alignment));
359  settings.setValue(prefix + "vertical-alignment", me.valueToKey(m_vertical_alignment));
360 
361  singleLineProperties.toSettings(settings, prefix);
362 }
363 
368 void ConductorProperties::fromSettings(QSettings &settings, const QString &prefix)
369 {
370  QColor settings_color = QColor(settings.value(prefix + "color").toString());
371  color = (settings_color.isValid()? settings_color : QColor(Qt::black));
372 
373  QColor settings_color_2 = QColor(settings.value(prefix + "color2").toString());
374  m_color_2 = (settings_color_2.isValid()? settings_color_2 : QColor(Qt::black));
375 
376  m_bicolor = settings.value(prefix + "bicolor", false).toBool();
377  m_dash_size = settings.value(prefix + "dash-size", 1).toInt();
378 
379  QString setting_type = settings.value(prefix + "type", typeToString(Multi)).toString();
380  type = (setting_type == typeToString(Single)? Single : Multi);
381 
382  singleLineProperties.fromSettings(settings, prefix);
383 
384  text = settings.value(prefix + "text", "_").toString();
385  m_formula = settings.value(prefix + "formula", "").toString();
386  m_function = settings.value(prefix + "function", "").toString();
387  m_tension_protocol = settings.value(prefix + "tension-protocol", "").toString();
388  text_size = settings.value(prefix + "textsize", "7").toInt();
389  cond_size = settings.value(prefix + "size", "1").toInt();
390  m_show_text = settings.value(prefix + "displaytext", true).toBool();
391  m_one_text_per_folio = settings.value(prefix + "onetextperfolio", false).toBool();
392  verti_rotate_text = settings.value((prefix + "vertirotatetext"), "270").toDouble();
393  horiz_rotate_text = settings.value((prefix + "horizrotatetext"), "0").toDouble();
394 
395  QMetaEnum me = QMetaEnum::fromType<Qt::Alignment>();
396  m_horizontal_alignment = Qt::Alignment(me.keyToValue(settings.value(prefix + "horizontal-alignment", "AlignBottom").toString().toStdString().data()));
397  m_vertical_alignment = Qt::Alignment(me.keyToValue(settings.value(prefix + "vertical-alignment", "AlignRight").toString().toStdString().data()));
398 
399  readStyle(settings.value(prefix + "style").toString());
400 }
401 
406 {
407  switch(t)
408  {
409  case Single: return("single");
410  case Multi: return("multi");
411  }
412  return QString();
413 }
414 
421 void ConductorProperties::applyForEqualAttributes(QList<ConductorProperties> list)
422 {
423  const QList<ConductorProperties> clist = std::move(list);
424 
425  if (clist.isEmpty())
426  return;
427 
428  if (clist.size() == 1)
429  {
430  ConductorProperties cp = clist.first();
431  color = cp.color;
432  m_bicolor = cp.m_bicolor;
433  m_color_2 = cp.m_color_2;
435  text = cp.text;
436  m_formula = cp.m_formula;
437  m_function = cp.m_function;
439  text_size = cp.text_size;
440  cond_size = cp.cond_size;
447 
448  return;
449  }
450 
451  bool equal = true;
452  QColor c_value;
453  bool b_value;
454  QString s_value;
455  int i_value;
456  double d_value;
457  Qt::Alignment align_value;
458 
459  //Color
460  c_value = clist.first().color;
461  for(ConductorProperties cp : clist)
462  {
463  if (cp.color != c_value)
464  equal = false;
465  }
466  if (equal)
467  color = c_value;
468  equal = true;
469 
470  //bicolor
471  b_value = clist.first().m_bicolor;
472  for(ConductorProperties cp : clist)
473  {
474  if (cp.m_bicolor != b_value)
475  equal = false;
476  }
477  if (equal)
478  m_bicolor = b_value;
479  equal = true;
480 
481  //second color
482  c_value = clist.first().m_color_2;
483  for(ConductorProperties cp : clist)
484  {
485  if (cp.m_color_2 != c_value)
486  equal = false;
487  }
488  if (equal)
489  m_color_2 = c_value;
490  equal = true;
491 
492  //Dash size
493  i_value = clist.first().m_dash_size;
494  for(ConductorProperties cp : clist)
495  {
496  if (cp.m_dash_size != i_value)
497  equal = false;
498  }
499  if (equal)
500  m_dash_size = i_value;
501  equal = true;
502 
503  //text
504  s_value = clist.first().text;
505  for(ConductorProperties cp : clist)
506  {
507  if (cp.text != s_value)
508  equal = false;
509  }
510  if (equal)
511  text = s_value;
512  equal = true;
513 
514  //formula
515  s_value = clist.first().m_formula;
516  for(ConductorProperties cp : clist)
517  {
518  if (cp.m_formula != s_value)
519  equal = false;
520  }
521  if (equal)
522  m_formula = s_value;
523  equal = true;
524 
525  //function
526  s_value = clist.first().m_function;
527  for(ConductorProperties cp : clist)
528  {
529  if (cp.m_function != s_value)
530  equal = false;
531  }
532  if (equal)
533  m_function = s_value;
534  equal = true;
535 
536  //Tension protocol
537  s_value = clist.first().m_tension_protocol;
538  for(ConductorProperties cp : clist)
539  {
540  if (cp.m_tension_protocol != s_value)
541  equal = false;
542  }
543  if (equal)
544  m_tension_protocol = s_value;
545  equal = true;
546 
547  //text size
548  i_value = clist.first().text_size;
549  for(ConductorProperties cp : clist)
550  {
551  if (cp.text_size != i_value)
552  equal = false;
553  }
554  if (equal)
555  text_size = i_value;
556  equal = true;
557 
558  //conductor size
559  d_value = clist.first().cond_size;
560  for(ConductorProperties cp : clist)
561  {
562  if (cp.cond_size != d_value)
563  equal = false;
564  }
565  if (equal)
566  cond_size = d_value;
567  equal = true;
568 
569  //show text
570  b_value = clist.first().m_show_text;
571  for(ConductorProperties cp : clist)
572  {
573  if (cp.m_show_text != b_value)
574  equal = false;
575  }
576  if (equal)
577  m_show_text = b_value;
578  equal = true;
579 
580  //One text per folio
581  b_value = clist.first().m_one_text_per_folio;
582  for(ConductorProperties cp : clist)
583  {
584  if (cp.m_one_text_per_folio != b_value)
585  equal = false;
586  }
587  if (equal)
588  m_one_text_per_folio = b_value;
589  equal = true;
590 
591  //Text rotation for vertical conducor
592  d_value = clist.first().verti_rotate_text;
593  for(ConductorProperties cp : clist)
594  {
595  if (cp.verti_rotate_text != d_value)
596  equal = false;
597  }
598  if (equal)
599  verti_rotate_text = d_value;
600  equal = true;
601 
602  //Text rotation for horizontal conducor
603  d_value = clist.first().horiz_rotate_text;
604  for(ConductorProperties cp : clist)
605  {
606  if (cp.horiz_rotate_text != d_value)
607  equal = false;
608  }
609  if (equal)
610  horiz_rotate_text = d_value;
611  equal = true;
612 
613  //Text alignment for horizontal conducor
614  align_value = clist.first().m_horizontal_alignment;
615  for(ConductorProperties cp : clist)
616  {
617  if (cp.m_horizontal_alignment != align_value)
618  equal = false;
619  }
620  if (equal)
621  m_horizontal_alignment = align_value;
622  equal = true;
623 
624  //Text alignment for vertical conducor
625  align_value = clist.first().m_vertical_alignment;
626  for(ConductorProperties cp : clist)
627  {
628  if (cp.m_vertical_alignment != align_value)
629  equal = false;
630  }
631  if (equal)
632  m_vertical_alignment = align_value;
633  equal = true;
634 }
635 
641 {
642  QSettings settings;
643 
645  def.fromSettings(settings, "diagrameditor/defaultconductor");
646 
647  return(def);
648 }
649 
656 {
657  return(
658  other.type == type &&\
659  other.color == color &&\
660  other.m_bicolor == m_bicolor &&\
661  other.m_color_2 == m_color_2 &&\
662  other.m_dash_size == m_dash_size &&\
663  other.style == style &&\
664  other.text == text &&\
665  other.m_formula == m_formula &&\
666  other.m_function == m_function &&\
668  other.m_show_text == m_show_text &&\
669  other.text_size == text_size &&\
670  other.cond_size == cond_size &&\
677  );
678 }
679 
685  return(!(*this == other));
686 }
687 
692 void ConductorProperties::readStyle(const QString &style_string) {
693  style = Qt::SolidLine; // style par defaut
694 
695  if (style_string.isEmpty()) return;
696 
697  // recupere la liste des couples style / valeur
698  QStringList styles = style_string.split(";", QString::SkipEmptyParts);
699 
700  QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$");
701  foreach (QString style_str, styles) {
702  if (rx.exactMatch(style_str)) {
703  QString style_name = rx.cap(1);
704  QString style_value = rx.cap(2);
705  if (style_name == "line-style") {
706  if (style_value == "dashed") style = Qt::DashLine;
707  else if (style_value == "dashdotted") style = Qt::DashDotLine;
708  else if (style_value == "normal") style = Qt::SolidLine;
709  }
710  }
711  }
712 }
713 
719  if (style == Qt::DashLine) {
720  return("line-style: dashed;");
721  } else if (style == Qt::DashDotLine) {
722  return("line-style: dashdotted");
723  } else {
724  return(QString());
725  }
726 }
727 
733  return(
734  other.hasGround == hasGround &&\
735  other.hasNeutral == hasNeutral &&\
736  other.is_pen == is_pen &&\
737  other.phases == phases
738  );
739 }
740 
746  return(!(other == (*this)));
747 }
748 
753 void SingleLineProperties::toSettings(QSettings &settings, const QString &prefix) const {
754  settings.setValue(prefix + "hasGround", hasGround);
755  settings.setValue(prefix + "hasNeutral", hasNeutral);
756  settings.setValue(prefix + "phases", phases);
757  settings.setValue(prefix + "pen", is_pen);
758 }
759 
764 void SingleLineProperties::fromSettings(QSettings &settings, const QString &prefix) {
765  hasGround = settings.value(prefix + "hasGround", true).toBool();
766  hasNeutral = settings.value(prefix + "hasNeutral", true).toBool();
767  phases = settings.value(prefix + "phases", 1).toInt();
768  is_pen = settings.value(prefix + "pen", false).toBool();
769 }
bool hasGround
Whether the singleline conductor should display the ground symbol.
static ConductorProperties defaultProperties()
ConductorProperties::defaultProperties.
Qt::Alignment m_vertical_alignment
unsigned short int phasesCount()
static QString typeToString(ConductorType)
int operator!=(const SingleLineProperties &) const
void readStyle(const QString &)
SingleLineProperties singleLineProperties
void toXml(QDomElement &) const
ConductorProperties::toXml Export conductor propertie, in the XML element &#39;e&#39;.
Qt::Alignment m_horizontal_alignment
void fromXml(QDomElement &)
ConductorProperties::fromXml Import conductor propertie, from the attribute of the xml element &#39;e&#39;...
virtual ~SingleLineProperties()
Destructeur.
ConductorSegmentType
Known kinds of conductor segments.
Definition: qet.h:86
bool hasNeutral
Whether the singleline conductor should display the neutral symbol.
void fromSettings(QSettings &, const QString &=QString())
void drawGround(QPainter *, QET::ConductorSegmentType, QPointF, qreal)
bool operator!=(const ConductorProperties &) const
void drawNeutral(QPainter *, QET::ConductorSegmentType, QPointF, qreal)
void toSettings(QSettings &, const QString &=QString()) const
ConductorType
The ConductorType enum Represents the kind of a particular conductor: Single: singleline symbols...
unsigned short int phases
bool operator==(const ConductorProperties &) const
ConductorProperties::operator ==.
void fromXml(QDomElement &)
int operator==(const SingleLineProperties &) const
void drawPen(QPainter *, QET::ConductorSegmentType, QPointF, qreal)
void toSettings(QSettings &, const QString &=QString()) const
void fromSettings(QSettings &, const QString &=QString())
bool is_pen
Protective Earth Neutral: visually merge neutral and ground.
void applyForEqualAttributes(QList< ConductorProperties > list)
ConductorProperties::applyForEqualAttributes Test each attribute of properties in the list separatly...
Horizontal segment.
Definition: qet.h:87
void draw(QPainter *, QET::ConductorSegmentType, const QRectF &)
void toXml(QDomElement &) const