QElectroTech  0.70
diagram.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 <math.h>
21 #include "factory/elementfactory.h"
22 #include "diagram.h"
23 #include "diagramcommands.h"
24 #include "diagramcontent.h"
25 #include "diagramposition.h"
26 #include "exportdialog.h"
30 #include "terminal.h"
31 #include "diagrameventinterface.h"
32 #include "qetapp.h"
34 #include "element.h"
35 #include "diagramview.h"
36 #include "dynamicelementtextitem.h"
37 #include "elementtextitemgroup.h"
40 
41 int Diagram::xGrid = 10;
42 int Diagram::yGrid = 10;
43 int Diagram::xKeyGrid = 10;
44 int Diagram::yKeyGrid = 10;
45 int Diagram::xKeyGridFine = 1;
46 int Diagram::yKeyGridFine = 1;
47 const qreal Diagram::margin = 5.0;
48 
49 // static variable to keep track of present background color of the diagram.
50 QColor Diagram::background_color = Qt::white;
51 
58  QGraphicsScene (project),
59  m_project (nullptr),
60  diagram_qet_version_ (-1),
61  draw_grid_ (true),
62  use_border_ (true),
63  draw_terminals_ (true),
64  draw_colored_conductors_ (true),
65  m_event_interface (nullptr),
66  m_freeze_new_elements (false),
67  m_freeze_new_conductors_ (false)
68 {
69  setItemIndexMethod(QGraphicsScene::NoIndex);
70  //Set to no index, because they can be the source of the crash with conductor and shape ghost.
71  //https://forum.qt.io/topic/71316/qgraphicsscenefinditembsptreevisitor-visit-crashes-due-to-an-obsolete-paintevent-after-qgraphicsscene-removeitem
72  //https://stackoverflow.com/questions/38458830/crash-after-qgraphicssceneremoveitem-with-custom-item-class
73  //http://www.qtcentre.org/archive/index.php/t-33730.html
74  //http://tech-artists.org/t/qt-properly-removing-qgraphicitems/3063
75 
77  qgi_manager_ = new QGIManager(this);
78  setBackgroundBrush(Qt::white);
79  conductor_setter_ = new QGraphicsLineItem(nullptr);
80  conductor_setter_ -> setZValue(1000000);
81 
82  QPen pen(Qt::NoBrush, 1.5, Qt::DashLine);
83  pen.setColor(Qt::black);
84  conductor_setter_ -> setPen(pen);
85 
86  connect(&border_and_titleblock, SIGNAL(needTitleBlockTemplate(const QString &)), this, SLOT(setTitleBlockTemplate(const QString &)));
87  connect(&border_and_titleblock, SIGNAL(diagramTitleChanged(const QString &)), this, SLOT(titleChanged(const QString &)));
88  connect(&border_and_titleblock, SIGNAL(titleBlockFolioChanged(const QString &)), this, SLOT(titleChanged(const QString &)));
89  connect(&border_and_titleblock, SIGNAL(borderChanged(QRectF,QRectF)), this, SLOT(adjustSceneRect()));
90  connect(&border_and_titleblock, SIGNAL(titleBlockFolioChanged(const QString &)), this, SLOT(updateLabels()));
91  connect(this, SIGNAL (diagramActivated()), this, SLOT(loadElmtFolioSeq()));
92  connect(this, SIGNAL (diagramActivated()), this, SLOT(loadCndFolioSeq()));
94 }
95 
101 {
102  //First clear every selection to close an hypothetical editor
103  clearSelection();
104  // clear undo stack to prevent errors, because contains pointers to this diagram and is elements.
105  undoStack().clear();
106  //delete of QGIManager, every elements he knows are removed
107  delete qgi_manager_;
108  // remove of conductor setter
109  delete conductor_setter_;
110 
111  if (m_event_interface)
112  delete m_event_interface;
113 
114  // list removable items
115  QList<QGraphicsItem *> deletable_items;
116  for(QGraphicsItem *qgi : items())
117  {
118  if (qgi -> parentItem()) continue;
119  if (qgraphicsitem_cast<Conductor *>(qgi)) continue;
120  deletable_items << qgi;
121  }
122 
123  qDeleteAll (deletable_items);
124 }
125 
131 void Diagram::drawBackground(QPainter *p, const QRectF &r) {
132  p -> save();
133 
134  // desactive tout antialiasing, sauf pour le texte
135  p -> setRenderHint(QPainter::Antialiasing, false);
136  p -> setRenderHint(QPainter::TextAntialiasing, true);
137  p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
138 
139  // dessine un fond blanc
140  p -> setPen(Qt::NoPen);
141  //set brush color to present background color.
142  p -> setBrush(Diagram::background_color);
143  p -> drawRect(r);
144 
145  if (draw_grid_) {
146  //Draw the point of the grid
147  // if background color is black, then grid spots shall be white, else they shall be black in color.
148  QPen pen;
149  Diagram::background_color == Qt::black? pen.setColor(Qt::white) : pen.setColor(Qt::black);
150  pen.setCosmetic(true);
151  p->setPen(pen);
152 
153  p -> setBrush(Qt::NoBrush);
154 
155  //If user allow zoom out beyond of folio, we draw grid outside of border.
156  QSettings settings;
157  int xGrid = settings.value("diagrameditor/Xgrid", Diagram::xGrid).toInt();
158  int yGrid = settings.value("diagrameditor/Ygrid", Diagram::yGrid).toInt();
159  QRectF rect = settings.value("diagrameditor/zoom-out-beyond-of-folio", false).toBool() ?
160  r :
161  border_and_titleblock.insideBorderRect().intersected(r);
162 
163  qreal limite_x = rect.x() + rect.width();
164  qreal limite_y = rect.y() + rect.height();
165 
166  int g_x = (int)ceil(rect.x());
167  while (g_x % xGrid) ++ g_x;
168  int g_y = (int)ceil(rect.y());
169  while (g_y % yGrid) ++ g_y;
170 
171  QPolygon points;
172  for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
173  for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
174  points << QPoint(gx, gy);
175  }
176  }
177  p -> drawPoints(points);
178  }
179 
181  p -> restore();
182 }
183 
189 void Diagram::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
190 {
191  event->setAccepted(false);
192 
193  if (m_event_interface) {
195  if (event->isAccepted()) {
196  return;
197  }
198  }
199 
200  QGraphicsScene::mouseDoubleClickEvent(event);
201 }
202 
208 void Diagram::mousePressEvent(QGraphicsSceneMouseEvent *event)
209 {
210  event->setAccepted(false);
211 
212  if (m_event_interface) {
214  if (event->isAccepted()) {
215  return;
216  }
217  }
218 
219  QGraphicsScene::mousePressEvent(event);
220 }
221 
227 void Diagram::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
228 {
229  event->setAccepted(false);
230 
231  if (m_event_interface) {
233  if (event->isAccepted()) {
234  return;
235  }
236  }
237 
238  QGraphicsScene::mouseMoveEvent(event);
239 }
240 
246 void Diagram::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
247 {
248  event->setAccepted(false);
249 
250  if (m_event_interface) {
252  if (event->isAccepted()) {
253  return;
254  }
255  }
256 
257  QGraphicsScene::mouseReleaseEvent(event);
258 }
259 
265 void Diagram::wheelEvent(QGraphicsSceneWheelEvent *event)
266 {
267  event->setAccepted(false);
268 
269  if (m_event_interface) {
271  if (event->isAccepted()) {
272  return;
273  }
274  }
275 
276  QGraphicsScene::wheelEvent(event);
277 }
278 
285 void Diagram::keyPressEvent(QKeyEvent *event)
286 {
287  QSettings settings;
288  int xKeyGrid = settings.value("diagrameditor/key_Xgrid", Diagram::xKeyGrid).toInt();
289  int yKeyGrid = settings.value("diagrameditor/key_Ygrid", Diagram::yKeyGrid).toInt();
290  int xKeyGridFine = settings.value("diagrameditor/key_fine_Xgrid", Diagram::xKeyGridFine).toInt();
291  int yKeyGridFine = settings.value("diagrameditor/key_fine_Ygrid", Diagram::yKeyGridFine).toInt();
292  event->setAccepted(false);
293 
294  if (m_event_interface) {
296  if (event->isAccepted()) {
297  return;
298  }
299  }
300 
301  if (!isReadOnly())
302  {
303  QPointF movement;
304  qreal top_position = 0;
305  qreal left_position = 0;
306  DiagramContent dc(this);
307  if (!dc.items(DiagramContent::All).isEmpty())
308  {
309  //Move item with the keyboard arrow
310  if(event->modifiers() == Qt::NoModifier)
311  {
312  switch(event->key())
313  {
314  case Qt::Key_Left:
315  for (Element *item : dc.m_elements)
316  {
317  left_position = item->sceneBoundingRect().x();
318  if(left_position <= 5)
319  return;
320  }
321  movement = QPointF(-xKeyGrid, 0.0);
322  break;
323  case Qt::Key_Right:
324  movement = QPointF(+xKeyGrid, 0.0);
325  break;
326  case Qt::Key_Up:
327  for(Element *item : dc.m_elements)
328  {
329  top_position = item->sceneBoundingRect().y();
330  if(top_position <= 5)
331  return;
332  }
333  movement = QPointF(0.0, -yKeyGrid);
334  break;
335  case Qt::Key_Down:
336  movement = QPointF(0.0, +yKeyGrid);
337  break;
338  }
339 
340  if (!movement.isNull() && !focusItem())
341  {
344  event->accept();
345  return;
346  }
347  }
348  else if(event->modifiers() == Qt::AltModifier)
349 
350  {
351  switch(event->key())
352  {
353  case Qt::Key_Left:
354  for (Element *item : dc.m_elements)
355  {
356  left_position = item->sceneBoundingRect().x();
357  if(left_position <= 5)
358  return;
359  }
360  movement = QPointF(-xKeyGridFine, 0.0);
361  break;
362  case Qt::Key_Right:
363  movement = QPointF(+xKeyGridFine, 0.0);
364  break;
365  case Qt::Key_Up:
366  for(Element *item : dc.m_elements)
367  {
368  top_position = item->sceneBoundingRect().y();
369  if(top_position <= 5)
370  return;
371  }
372  movement = QPointF(0.0, -yKeyGridFine);
373  break;
374  case Qt::Key_Down:
375  movement = QPointF(0.0, +yKeyGridFine);
376  break;
377  }
378 
379  if (!movement.isNull() && !focusItem())
380  {
383  event->accept();
384  return;
385  }
386  }
387  else if(event->modifiers() == Qt::ControlModifier)
388  {
389  //Adjust the alignment of a texts group
390  if(selectedItems().size() == 1 && selectedItems().first()->type() == QGraphicsItemGroup::Type)
391  {
392  if(ElementTextItemGroup *etig = dynamic_cast<ElementTextItemGroup *>(selectedItems().first()))
393  {
394  if(event->key() == Qt::Key_Left && etig->alignment() != Qt::AlignLeft)
395  undoStack().push(new AlignmentTextsGroupCommand(etig, Qt::AlignLeft));
396 
397  else if (event->key() == Qt::Key_Up && etig->alignment() != Qt::AlignVCenter)
398  undoStack().push(new AlignmentTextsGroupCommand(etig, Qt::AlignVCenter));
399 
400  else if (event->key() == Qt::Key_Right && etig->alignment() != Qt::AlignRight)
401  undoStack().push(new AlignmentTextsGroupCommand(etig, Qt::AlignRight));
402  }
403  }
404  }
405  }
406 
407  event->ignore();
408  QGraphicsScene::keyPressEvent(event);
409  }
410 }
411 
418 void Diagram::keyReleaseEvent(QKeyEvent *e)
419 {
420  e->setAccepted(false);
421 
422  if (m_event_interface) {
424  if (e->isAccepted()) {
425  return;
426  }
427  }
428 
429  bool transmit_event = true;
430  if (!isReadOnly()) {
431  // detecte le relachement d'une touche de direction ( = deplacement d'elements)
432  if (
433  (e -> key() == Qt::Key_Left || e -> key() == Qt::Key_Right ||
434  e -> key() == Qt::Key_Up || e -> key() == Qt::Key_Down) &&
435  !e -> isAutoRepeat()
436  ) {
438  e -> accept();
439  transmit_event = false;
440  }
441  }
442  if (transmit_event) {
443  QGraphicsScene::keyReleaseEvent(e);
444  }
445 }
446 
456 {
457  if (m_event_interface)
458  {
459  delete m_event_interface;
460  event_interface -> init();
461  }
462  m_event_interface = event_interface;
463 
465  {
466  delete this->m_event_interface;
467  this->m_event_interface = nullptr;
468  });
469 }
470 
476 {
478  {
479  delete m_event_interface;
480  m_event_interface = nullptr;
481  }
482 }
483 
490 }
491 
496 void Diagram::setConductorsAutonumName(const QString &name) {
498 }
499 
504 bool Diagram::toPaintDevice(QPaintDevice &pix, int width, int height, Qt::AspectRatioMode aspectRatioMode) {
505  // determine la zone source = contenu du schema + marges
506  QRectF source_area;
507  if (!use_border_) {
508  source_area = itemsBoundingRect();
509  source_area.translate(-margin, -margin);
510  source_area.setWidth (source_area.width () + 2.0 * margin);
511  source_area.setHeight(source_area.height() + 2.0 * margin);
512  } else {
513  source_area = QRectF(
514  0.0,
515  0.0,
518  );
519  }
520 
521  // si les dimensions ne sont pas precisees, l'image est exportee a l'echelle 1:1
522  QSize image_size = (width == -1 && height == -1) ? source_area.size().toSize() : QSize(width, height);
523 
524  // prepare le rendu
525  QPainter p;
526  if (!p.begin(&pix)) return(false);
527 
528  // rendu antialiase
529  p.setRenderHint(QPainter::Antialiasing, true);
530  p.setRenderHint(QPainter::TextAntialiasing, true);
531  p.setRenderHint(QPainter::SmoothPixmapTransform, true);
532 
533  // deselectionne tous les elements
534  QList<QGraphicsItem *> selected_elmts = selectedItems();
535  foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(false);
536 
537  // effectue le rendu lui-meme
538  render(&p, QRect(QPoint(0, 0), image_size), source_area, aspectRatioMode);
539  p.end();
540 
541  // restaure les elements selectionnes
542  foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(true);
543 
544  return(true);
545 }
546 
551 QSize Diagram::imageSize() const {
552  // determine la zone source = contenu du schema + marges
553  qreal image_width, image_height;
554  if (!use_border_) {
555  QRectF items_rect = itemsBoundingRect();
556  image_width = items_rect.width();
557  image_height = items_rect.height();
558  } else {
559  image_width = border_and_titleblock.borderAndTitleBlockRect().width();
560  image_height = border_and_titleblock.borderAndTitleBlockRect().height();
561  }
562 
563  image_width += 2.0 * margin;
564  image_height += 2.0 * margin;
565 
566  // renvoie la taille de la zone source
567  return(QSizeF(image_width, image_height).toSize());
568 }
569 
574 bool Diagram::isEmpty() const {
575  return(!items().count());
576 }
577 
583 QList < QSet <Conductor *> > Diagram::potentials() {
584  QList < QSet <Conductor *> > potential_List;
585  if (content().conductors().size() == 0) return (potential_List); //return an empty potential
586  QList <Conductor *> conductors_list = content().conductors();
587 
588  do {
589  QSet <Conductor *> one_potential = conductors_list.first() -> relatedPotentialConductors();
590  one_potential << conductors_list.takeFirst();
591  foreach (Conductor *c, one_potential) conductors_list.removeOne(c);
592  potential_List << one_potential;
593  } while (!conductors_list.empty());
594 
595  return (potential_List);
596 }
597 
604 QDomDocument Diagram::toXml(bool whole_content) {
605  // document
606  QDomDocument document;
607 
608  // racine de l'arbre XML
609  QDomElement racine = document.createElement("diagram");
610 
611  // add the application version number
612  racine.setAttribute("version", QET::version);
613 
614  // proprietes du schema
615  if (whole_content) {
618 
619  // Default conductor properties
620  QDomElement default_conductor = document.createElement("defaultconductor");
621  defaultConductorProperties.toXml(default_conductor);
622  racine.appendChild(default_conductor);
623 
624  // Conductor autonum
625  if (!m_conductors_autonum_name.isEmpty()) {
626  racine.setAttribute("conductorAutonum", m_conductors_autonum_name);
627  }
628 
629  //Default New Element
630  racine.setAttribute("freezeNewElement", m_freeze_new_elements ? "true" : "false");
631 
632  //Default New Conductor
633  racine.setAttribute("freezeNewConductor", m_freeze_new_conductors_ ? "true" : "false");
634 
635  //Element Folio Sequential Variables
636  if (!m_elmt_unitfolio_max.isEmpty() || !m_elmt_tenfolio_max.isEmpty() || !m_elmt_hundredfolio_max.isEmpty()) {
637  QDomElement elmtfoliosequential = document.createElement("elementautonumfoliosequentials");
638  if (!m_elmt_unitfolio_max.isEmpty()) {
639  QDomElement elmtfolioseq = document.createElement("elementunitfolioseq");
640  folioSequentialsToXml(&m_elmt_unitfolio_max, &elmtfolioseq, "sequf_", "unitfolioseq", &document);
641  elmtfoliosequential.appendChild(elmtfolioseq);
642  }
643  if (!m_elmt_tenfolio_max.isEmpty()) {
644  QDomElement elmtfolioseq = document.createElement("elementtenfolioseq");
645  folioSequentialsToXml(&m_elmt_tenfolio_max, &elmtfolioseq, "seqtf_", "tenfolioseq", &document);
646  elmtfoliosequential.appendChild(elmtfolioseq);
647  }
648  if (!m_elmt_hundredfolio_max.isEmpty()) {
649  QDomElement elmtfolioseq = document.createElement("elementhundredfolioseq");
650  folioSequentialsToXml(&m_elmt_hundredfolio_max, &elmtfolioseq, "seqhf_", "hundredfolioseq", &document);
651  elmtfoliosequential.appendChild(elmtfolioseq);
652  }
653  racine.appendChild(elmtfoliosequential);
654  }
655  //Conductor Folio Sequential Variables
656  if (!m_cnd_unitfolio_max.isEmpty() || !m_cnd_tenfolio_max.isEmpty() || !m_cnd_hundredfolio_max.isEmpty()) {
657  QDomElement cndfoliosequential = document.createElement("conductorautonumfoliosequentials");
658  QHash<QString, QStringList>::iterator i;
659  if (!m_cnd_unitfolio_max.isEmpty()) {
660  QDomElement cndfolioseq = document.createElement("conductorunitfolioseq");
661  folioSequentialsToXml(&m_cnd_unitfolio_max, &cndfolioseq, "sequf_", "unitfolioseq", &document);
662  cndfoliosequential.appendChild(cndfolioseq);
663  }
664  if (!m_cnd_tenfolio_max.isEmpty()) {
665  QDomElement cndfolioseq = document.createElement("conductortenfolioseq");
666  folioSequentialsToXml(&m_cnd_tenfolio_max, &cndfolioseq, "seqtf_", "tenfolioseq", &document);
667  cndfoliosequential.appendChild(cndfolioseq);
668  }
669  if (!m_cnd_hundredfolio_max.isEmpty()) {
670  QDomElement cndfolioseq = document.createElement("conductorhundredfolioseq");
671  folioSequentialsToXml(&m_cnd_hundredfolio_max, &cndfolioseq, "seqhf_", "hundredfolioseq", &document);
672  cndfoliosequential.appendChild(cndfolioseq);
673  }
674  racine.appendChild(cndfoliosequential);
675  }
676  }
677  else {
678  //this method with whole_content to false,
679  //is often use to copy and paste the current selection
680  //so we add the id of the project where copy occur.
681  racine.setAttribute("projectId", QETApp::projectId(m_project));
682  }
683  document.appendChild(racine);
684 
685  // si le schema ne contient pas d'element (et donc pas de conducteurs), on retourne de suite le document XML
686  if (items().isEmpty()) return(document);
687 
688  // creation de trois listes : une qui contient les elements, une qui contient les conducteurs, une qui contient les champs de texte
689  QList<Element *> list_elements;
690  QList<Conductor *> list_conductors;
691  QList<DiagramTextItem *> list_texts;
692  QList<DiagramImageItem *> list_images;
693  QList<QetShapeItem *> list_shapes;
694 
695  QList<QGraphicsItem *> list_items = items();
696  ;
697  // Determine les elements a "XMLiser"
698  foreach(QGraphicsItem *qgi, list_items) {
699  if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
700  if (whole_content) list_elements << elmt;
701  else if (elmt -> isSelected()) list_elements << elmt;
702  } else if (Conductor *f = qgraphicsitem_cast<Conductor *>(qgi)) {
703  if (whole_content) list_conductors << f;
704  // lorsqu'on n'exporte pas tout le diagram, il faut retirer les conducteurs non selectionnes
705  // et pour l'instant, les conducteurs non selectionnes sont les conducteurs dont un des elements n'est pas selectionne
706  else if (f -> terminal1 -> parentItem() -> isSelected() && f -> terminal2 -> parentItem() -> isSelected()) {
707  list_conductors << f;
708  }
709  } else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(qgi)) {
710  if (whole_content) list_texts << iti;
711  else if (iti -> isSelected()) list_texts << iti;
712  } else if (DiagramImageItem *dii = qgraphicsitem_cast<DiagramImageItem *>(qgi)) {
713  if (whole_content) list_images << dii;
714  else if (dii -> isSelected()) list_images << dii;
715  } else if (QetShapeItem *dsi = qgraphicsitem_cast<QetShapeItem *>(qgi)) {
716  if (whole_content) list_shapes << dsi;
717  else if (dsi -> isSelected()) list_shapes << dsi;
718  }
719  }
720 
721  // table de correspondance entre les adresses des bornes et leurs ids
722  QHash<Terminal *, int> table_adr_id;
723 
724  // enregistrement des elements
725  if (!list_elements.isEmpty()) {
726  QDomElement elements = document.createElement("elements");
727  foreach(Element *elmt, list_elements) {
728  elements.appendChild(elmt -> toXml(document, table_adr_id));
729  }
730  racine.appendChild(elements);
731  }
732 
733  // enregistrement des conducteurs
734  if (!list_conductors.isEmpty()) {
735  QDomElement conductors = document.createElement("conductors");
736  foreach(Conductor *cond, list_conductors) {
737  conductors.appendChild(cond -> toXml(document, table_adr_id));
738  }
739  racine.appendChild(conductors);
740  }
741 
742  // enregistrement des champs de texte
743  if (!list_texts.isEmpty()) {
744  QDomElement inputs = document.createElement("inputs");
745  foreach(DiagramTextItem *dti, list_texts) {
746  inputs.appendChild(dti -> toXml(document));
747  }
748  racine.appendChild(inputs);
749  }
750 
751  // save of images
752  if (!list_images.isEmpty()) {
753  QDomElement images = document.createElement("images");
754  foreach (DiagramImageItem *dii, list_images) {
755  images.appendChild(dii -> toXml(document));
756  }
757  racine.appendChild(images);
758  }
759 
760  // save of basic shapes
761  if (!list_shapes.isEmpty()) {
762  QDomElement shapes = document.createElement("shapes");
763  foreach (QetShapeItem *dii, list_shapes) {
764  shapes.appendChild(dii -> toXml(document));
765  }
766  racine.appendChild(shapes);
767  }
768  // on retourne le document XML ainsi genere
769  return(document);
770 }
771 
779 void Diagram::folioSequentialsToXml(QHash<QString, QStringList> *hash, QDomElement *domElement, const QString& seq_type, const QString& type, QDomDocument *doc) {
780  QHash<QString, QStringList>::iterator i;
781  for (i = hash->begin(); i != hash->end(); i++) {
782  QDomElement folioseq = doc->createElement(type);
783  folioseq.setAttribute("title", i.key());
784  for (int j = 0; j < i.value().size(); j++) {
785  folioseq.setAttribute(seq_type + QString::number(j+1), i.value().at(j));
786  }
787  domElement->appendChild(folioseq);
788  }
789 }
790 
804 bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_informations, DiagramContent *content_ptr) {
805  QDomElement root = document.documentElement();
806  return(fromXml(root, position, consider_informations, content_ptr));
807 }
808 
824 bool Diagram::initFromXml(QDomElement &document, QPointF position, bool consider_informations, DiagramContent *content_ptr) {
825  // import le contenu et les proprietes du schema depuis l'element XML fourni en parametre
826  bool from_xml = fromXml(document, position, consider_informations, content_ptr);
827 
828  return(from_xml);
829 }
830 
844 bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_informations, DiagramContent *content_ptr) {
845  const QDomElement& root = document;
846  // The first element must be a diagram
847  if (root.tagName() != "diagram") return(false);
848 
849  // Read attributes of this diagram
850  if (consider_informations) {
851  // Version of diagram
852  bool conv_ok;
853  qreal version_value = root.attribute("version").toDouble(&conv_ok);
854  if (conv_ok) {
855  diagram_qet_version_ = version_value;
856  }
857 
858  // Load border and titleblock
861 
862  // Find the element "defaultconductor".
863  // If found, load default conductor properties.
864  QDomElement default_conductor_elmt = root.firstChildElement("defaultconductor");
865  if (!default_conductor_elmt.isNull()) {
866  defaultConductorProperties.fromXml(default_conductor_elmt);
867  }
868 
869  // Load the autonum
870  m_conductors_autonum_name = root.attribute("conductorAutonum");
871 
872  // Load Freeze New Element
873  m_freeze_new_elements = root.attribute("freezeNewElement").toInt();
874 
875  // Load Freeze New Conductor
876  m_freeze_new_conductors_ = root.attribute("freezeNewConductor").toInt();
877 
878  //Load Element Folio Sequential
879  folioSequentialsFromXml(root, &m_elmt_unitfolio_max, "elementunitfolioseq","sequf_","unitfolioseq", "elementautonumfoliosequentials");
880  folioSequentialsFromXml(root, &m_elmt_tenfolio_max, "elementtenfolioseq","seqtf_", "tenfolioseq", "elementautonumfoliosequentials");
881  folioSequentialsFromXml(root, &m_elmt_hundredfolio_max, "elementhundredfolioseq","seqhf_", "hundredfolioseq", "elementautonumfoliosequentials");
882 
883  //Load Conductor Folio Sequential
884  folioSequentialsFromXml(root, &m_cnd_unitfolio_max, "conductorunitfolioseq","sequf_","unitfolioseq", "conductorautonumfoliosequentials");
885  folioSequentialsFromXml(root, &m_cnd_tenfolio_max, "conductortenfolioseq","seqtf_","tenfolioseq", "conductorautonumfoliosequentials");
886  folioSequentialsFromXml(root, &m_cnd_hundredfolio_max, "conductorhundredfolioseq","seqhf_","hundredfolioseq", "conductorautonumfoliosequentials");
887  }
888 
889  // if child haven't got a child, loading is finish (diagram is empty)
890  if (root.firstChild().isNull()) {
891  return(true);
892  }
893 
894  // Backward compatibility: prior to version 0.3, we need to compensate, at
895  // diagram-opening time, the rotation of the element for each of its
896  // textfields having the "FollowParentRotation" option disabled.
897  // After 0.3, elements textfields get userx, usery and userrotation attributes
898  // that explicitly specify their position and orientation.
899  qreal project_qet_version = declaredQElectroTechVersion(true);
900  bool handle_inputs_rotation = (
901  project_qet_version != -1 && project_qet_version < 0.3 &&
903  );
904 
905  //If paste from another project
906  if (root.hasAttribute("projectId")) {
907  QETProject *other_project = QETApp::project(root.attribute("projectId", "-1").toInt());
908 
909  //We try to paste from another project, then befor paste elements,
910  //we must to import the definition of the pasted elements (owned by other project)
911  //in the embedded collection of this project
912  if (other_project && other_project != m_project) {
914  foreach (QDomElement element_xml, QET::findInDomElement(root, "elements", "element")) {
915  if (!Element::valideXml(element_xml)) continue;
916 
917  QString type_id = element_xml.attribute("type");
918 
919  if (type_id.startsWith("embed://")) {
920  ElementsLocation location(type_id, other_project);
921  ech.importFromProject(m_project, location);
922  }
923  }
924  }
925  }
926  //Load all elements from the XML
927  QList<Element *> added_elements;
928  QHash<int, Terminal *> table_adr_id;
929  foreach (QDomElement element_xml, QET::findInDomElement(root, "elements", "element"))
930  {
931  if (!Element::valideXml(element_xml)) continue;
932 
933  // cree un element dont le type correspond a l'id type
934  QString type_id = element_xml.attribute("type");
935  ElementsLocation element_location;
936  if (type_id.startsWith("embed://")) {
937  element_location = ElementsLocation(type_id, m_project);
938  }
939  else {
940  element_location = ElementsLocation(type_id);
941  }
942 
943  int state = 0;
944  Element *nvel_elmt = ElementFactory::Instance() -> createElement(element_location, nullptr, &state);
945  if (state)
946  {
947  QString debug_message = QString("Diagram::fromXml() : Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2").arg(element_location.path()).arg(state);
948  qDebug() << qPrintable(debug_message);
949  delete nvel_elmt;
950  continue;
951  }
952 
953  addItem(nvel_elmt);
954  //Loading fail, remove item from the diagram
955  if (!nvel_elmt->fromXml(element_xml, table_adr_id, handle_inputs_rotation))
956  {
957  removeItem(nvel_elmt);
958  delete nvel_elmt;
959  qDebug() << "Diagram::fromXml() : Le chargement des parametres d'un element a echoue";
960  } else {
961  added_elements << nvel_elmt;
962  }
963  }
964 
965  // Load text
966  QList<IndependentTextItem *> added_texts;
967  foreach (QDomElement text_xml, QET::findInDomElement(root, "inputs", "input")) {
969  iti -> fromXml(text_xml);
970  addItem(iti);
971  added_texts << iti;
972  }
973 
974  // Load image
975  QList<DiagramImageItem *> added_images;
976  foreach (QDomElement image_xml, QET::findInDomElement(root, "images", "image")) {
977  DiagramImageItem *dii = new DiagramImageItem ();
978  dii -> fromXml(image_xml);
979  addItem(dii);
980  added_images << dii;
981  }
982 
983  // Load shape
984  QList<QetShapeItem *> added_shapes;
985  foreach (QDomElement shape_xml, QET::findInDomElement(root, "shapes", "shape")) {
986  QetShapeItem *dii = new QetShapeItem (QPointF(0,0));
987  dii -> fromXml(shape_xml);
988  addItem(dii);
989  added_shapes << dii;
990  }
991 
992  // Load conductor
993  QList<Conductor *> added_conductors;
994  foreach (QDomElement f, QET::findInDomElement(root, "conductors", "conductor"))
995  {
996  if (!Conductor::valideXml(f)) continue;
997 
998  //Check if terminal that conductor must be linked is know
999  int id_p1 = f.attribute("terminal1").toInt();
1000  int id_p2 = f.attribute("terminal2").toInt();
1001  if (table_adr_id.contains(id_p1) && table_adr_id.contains(id_p2))
1002  {
1003  Terminal *p1 = table_adr_id.value(id_p1);
1004  Terminal *p2 = table_adr_id.value(id_p2);
1005  if (p1 != p2)
1006  {
1007  Conductor *c = new Conductor(p1, p2);
1008  if (c->isValid())
1009  {
1010  addItem(c);
1011  c -> fromXml(f);
1012  added_conductors << c;
1013  }
1014  else
1015  delete c;
1016  }
1017  }
1018  else qDebug() << "Diagram::fromXml() : Le chargement du conducteur" << id_p1 << id_p2 << "a echoue";
1019  }
1020 
1021  //Translate items if a new position was given in parameter
1022  if (position != QPointF()) {
1023 
1024  QList<QGraphicsItem *> added_items;
1025  foreach (Element *added_element, added_elements ) added_items << added_element;
1026  foreach (Conductor *added_cond, added_conductors) added_items << added_cond;
1027  foreach (QetShapeItem *added_shape, added_shapes ) added_items << added_shape;
1028  foreach (DiagramTextItem *added_text, added_texts ) added_items << added_text;
1029  foreach (DiagramImageItem *added_image, added_images ) added_items << added_image;
1030 
1031  //Get the top left corner of the rectangle that contain all added items
1032  QRectF items_rect;
1033  foreach (QGraphicsItem *item, added_items) {
1034  items_rect = items_rect.united(item -> mapToScene(item -> boundingRect()).boundingRect());
1035  }
1036 
1037  QPointF point_ = items_rect.topLeft();
1038  QPointF pos_ = Diagram::snapToGrid(QPointF (position.x() - point_.x(),
1039  position.y() - point_.y()));
1040 
1041  //Translate all added items
1042  foreach (QGraphicsItem *qgi, added_items)
1043  qgi -> setPos( qgi -> pos() += pos_);
1044  }
1045 
1046  // remplissage des listes facultatives
1047  if (content_ptr) {
1048  content_ptr -> m_elements = added_elements;
1049  content_ptr -> m_conductors_to_move = added_conductors;
1050  content_ptr -> m_text_fields = added_texts.toSet();
1051  content_ptr -> m_images = added_images.toSet();
1052  content_ptr -> m_shapes = added_shapes.toSet();
1053  }
1054  adjustSceneRect();
1055  return(true);
1056 }
1057 
1067 void Diagram::folioSequentialsFromXml(const QDomElement &root, QHash<QString, QStringList>* hash, const QString& folioSeq, const QString& seq, const QString& type, const QString& autonumFolioSeqType) {
1068  foreach (QDomElement folioSeqAutoNum, QET::findInDomElement(root, autonumFolioSeqType, folioSeq)) {
1069  for(QDomElement folioseq = folioSeqAutoNum.firstChildElement(type); !folioseq.isNull(); folioseq = folioseq.nextSiblingElement(type)) {
1070  QString title = folioseq.attribute("title");
1071  QStringList list;
1072  int i = 1;
1073  while (folioseq.hasAttribute(seq + QString::number(i))) {
1074  list << folioseq.attribute(seq + QString::number(i));
1075  i++;
1076  }
1077  hash->insert(title,list);
1078  }
1079  }
1080 }
1081 
1090 {
1091  for (Element *elmt : elements())
1092  {
1093  elmt->initLink(project());
1094  for (DynamicElementTextItem *deti : elmt->dynamicTextItems())
1095  deti->refreshLabelConnection();
1096  }
1097 
1098  for (Conductor *conductor : conductors())
1099  conductor->refreshText();
1100 }
1101 
1108 void Diagram::addItem(QGraphicsItem *item)
1109 {
1110  if (!item || isReadOnly() || item->scene() == this) return;
1111  QGraphicsScene::addItem(item);
1112 
1113  switch (item->type())
1114  {
1115  case Conductor::Type:
1116  {
1117  Conductor *conductor = static_cast<Conductor *>(item);
1118  conductor->terminal1->addConductor(conductor);
1119  conductor->terminal2->addConductor(conductor);
1120  conductor->calculateTextItemPosition();
1121  break;
1122  }
1123  default: {break;}
1124  }
1125 }
1126 
1133 void Diagram::removeItem(QGraphicsItem *item)
1134 {
1135  if (!item || isReadOnly()) return;
1136 
1137  switch (item->type())
1138  {
1139  case Element::Type:
1140  {
1141  Element *elmt = static_cast<Element*>(item);
1142  elmt->unlinkAllElements();
1143  break;
1144  }
1145  case Conductor::Type:
1146  {
1147  Conductor *conductor = static_cast<Conductor *>(item);
1148  conductor->terminal1->removeConductor(conductor);
1149  conductor->terminal2->removeConductor(conductor);
1150  break;
1151  }
1152  default: {break;}
1153  }
1154 
1155  QGraphicsScene::removeItem(item);
1156 }
1157 
1158 void Diagram::titleChanged(const QString &title) {
1159  emit(diagramTitleChanged(this, title));
1160 }
1161 
1168 void Diagram::titleBlockTemplateChanged(const QString &template_name) {
1169  if (border_and_titleblock.titleBlockTemplateName() != template_name) return;
1170 
1172  update();
1173 }
1174 
1183 void Diagram::titleBlockTemplateRemoved(const QString &template_name, const QString &new_template)
1184 {
1185  if (border_and_titleblock.titleBlockTemplateName() != template_name) return;
1186  const TitleBlockTemplate *final_template = m_project->embeddedTitleBlockTemplatesCollection()->getTemplate(new_template);
1187  border_and_titleblock.titleBlockTemplateRemoved(template_name, final_template);
1188  update();
1189 }
1190 
1195 void Diagram::setTitleBlockTemplate(const QString &template_name)
1196 {
1197  if (!m_project) return;
1198 
1199  QString current_name = border_and_titleblock.titleBlockTemplateName();
1200  const TitleBlockTemplate *titleblock_template = m_project->embeddedTitleBlockTemplatesCollection()->getTemplate(template_name);
1201  border_and_titleblock.titleBlockTemplateRemoved(current_name, titleblock_template);
1202 
1203  if (template_name != current_name)
1204  emit(usedTitleBlockTemplateChanged(template_name));
1205 }
1206 
1211  if (items().isEmpty()) return;
1212 
1213  blockSignals(true);
1214  foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(true);
1215  blockSignals(false);
1216  emit(selectionChanged());
1217 }
1218 
1223  if (items().isEmpty()) return;
1224 
1225  clearSelection();
1226 }
1227 
1232  if (items().isEmpty()) return;
1233 
1234  blockSignals(true);
1235  foreach (QGraphicsItem *item, items()) item -> setSelected(!item -> isSelected());
1236  blockSignals(false);
1237  emit(selectionChanged());
1238 }
1239 
1246 {
1247  for (Conductor *cnd : content().conductors())
1248  {
1249  cnd->refreshText();
1250  }
1251 }
1252 
1263 void Diagram::insertFolioSeqHash(QHash<QString, QStringList> *hash, const QString& title, const QString& type, NumerotationContext *nc) {
1264  QStringList max;
1265  for (int i = 0; i < nc->size(); i++) {
1266  if (nc->itemAt(i).at(0) == type) {
1267  nc->replaceValue(i, QString::number(nc->itemAt(i).at(3).toInt()));
1268  max.append(QString::number(nc->itemAt(i).at(3).toInt() - nc->itemAt(i).at(2).toInt()));
1269  }
1270  }
1271  hash->insert(title,max);
1272 }
1273 
1284 void Diagram::loadFolioSeqHash(QHash<QString, QStringList> *hash, const QString& title, const QString& type, NumerotationContext *nc) {
1285  int j = 0;
1286  for (int i = 0; i < nc->size(); i++) {
1287  if (nc->itemAt(i).at(0) == type) {
1288  QString new_value;
1289  new_value = QString::number(hash->value(title).at(j).toInt() + nc->itemAt(i).at(2).toInt());
1290  nc->replaceValue(i,new_value);
1291  j++;
1292  }
1293  }
1294 }
1295 
1301 {
1302  DiagramContent dc(this);
1303  QUndoCommand *undo = new QUndoCommand(tr("Modifier la profondeur"));
1304  QList<QGraphicsItem *> l = dc.items(DiagramContent::SelectedOnly | \
1308  QList<QGraphicsObject *> list;
1309  for(QGraphicsItem *item : l)
1310  list << item->toGraphicsObject();
1311 
1312  qreal maxz=0,
1313  minz=0;
1314  for(QGraphicsItem *item : this->items())
1315  {
1316  qreal z = item->zValue();
1317  if(z >= Terminal::Z-2)
1318  continue;
1319  maxz = std::max(maxz,z);
1320  minz = std::min(minz,z);
1321  }
1322 
1323  if(option == QET::Raise)
1324  {
1325  for(QGraphicsObject *qgo : list)
1326  if(qgo->zValue() < (Terminal::Z-2)) //Ensure item is always below terminal
1327  new QPropertyUndoCommand(qgo, "z", qgo->zValue(), qgo->zValue()+1, undo);
1328  }
1329  else if(option == QET::Lower)
1330  {
1331  for(QGraphicsObject *qgo : list)
1332  if(qgo->zValue() < (Terminal::Z-2)) //Ensure item is always below terminal
1333  new QPropertyUndoCommand(qgo, "z", qgo->zValue(), qgo->zValue()-1, undo);
1334  }
1335  else if (option == QET::BringForward)
1336  {
1337  for(QGraphicsObject *qgo : list)
1338  new QPropertyUndoCommand(qgo, "z", qgo->zValue(), maxz+1, undo);
1339  }
1340  else if(option == QET::SendBackward)
1341  {
1342  for(QGraphicsObject *qgo : list)
1343  new QPropertyUndoCommand(qgo, "z", qgo->zValue(), minz-1, undo);
1344  }
1345 
1346  if(undo->childCount())
1347  this->undoStack().push(undo);
1348  else
1349  delete undo;
1350 }
1351 
1358  QString title = project()->elementCurrentAutoNum();
1360 
1361  //Unit Folio
1362  if (m_elmt_unitfolio_max.isEmpty() || !m_elmt_unitfolio_max.contains(title)) {
1363  //Insert Initial Value
1364  if (project()->elementAutoNumCurrentFormula().contains("%sequf_")) {
1365  insertFolioSeqHash(&m_elmt_unitfolio_max,title,"unitfolio",&nc);
1367  }
1368  }
1369  else if (m_elmt_unitfolio_max.contains(title)) {
1370  //Load Folio Current Value
1371  if (project()->elementAutoNumCurrentFormula().contains("%sequf_")) {
1372  loadFolioSeqHash(&m_elmt_unitfolio_max,title,"unitfolio",&nc);
1374  }
1375  }
1376 
1377  //Ten Folio
1378  if (m_elmt_tenfolio_max.isEmpty() || !m_elmt_tenfolio_max.contains(title)) {
1379  //Insert Initial Value
1380  if (project()->elementAutoNumCurrentFormula().contains("%seqtf_")) {
1381  insertFolioSeqHash(&m_elmt_tenfolio_max,title,"tenfolio",&nc);
1383  }
1384  }
1385  else if (m_elmt_tenfolio_max.contains(title)) {
1386  //Load Folio Current Value
1387  if (project()->elementAutoNumCurrentFormula().contains("%seqtf_")) {
1388  loadFolioSeqHash(&m_elmt_tenfolio_max,title,"tenfolio",&nc);
1390  }
1391  }
1392 
1393  //Hundred Folio
1394  if (m_elmt_hundredfolio_max.isEmpty() || !m_elmt_hundredfolio_max.contains(title)) {
1395  //Insert Initial Value
1396  if (project()->elementAutoNumCurrentFormula().contains("%seqhf_")) {
1397  insertFolioSeqHash(&m_elmt_hundredfolio_max,title,"hundredfolio",&nc);
1399  }
1400  }
1401  else if (m_elmt_hundredfolio_max.contains(title)) {
1402  //Load Folio Current Value
1403  if (project()->elementAutoNumCurrentFormula().contains("%seqhf_")) {
1404  loadFolioSeqHash(&m_elmt_hundredfolio_max,title,"hundredfolio",&nc);
1406  }
1407  }
1408 }
1409 
1416  //Conductor
1417  QString title = project()->conductorCurrentAutoNum();
1419  QString formula = autonum::numerotationContextToFormula(nc);
1420 
1421  //Unit Folio
1422  if (m_cnd_unitfolio_max.isEmpty() || !m_cnd_unitfolio_max.contains(title)) {
1423  //Insert Initial Value
1424  if (formula.contains("%sequf_")) {
1425  insertFolioSeqHash(&m_cnd_unitfolio_max,title,"unitfolio",&nc);
1427  }
1428  }
1429  else if (m_cnd_unitfolio_max.contains(title)) {
1430  //Load Folio Current Value
1431  if (formula.contains("%sequf_")) {
1432  loadFolioSeqHash(&m_cnd_unitfolio_max,title,"unitfolio",&nc);
1434  }
1435  }
1436 
1437  //Ten Folio
1438  if (m_cnd_tenfolio_max.isEmpty() || !m_cnd_tenfolio_max.contains(title)) {
1439  //Insert Initial Value
1440  if (formula.contains("%seqtf_")) {
1441  insertFolioSeqHash(&m_cnd_tenfolio_max,title,"tenfolio",&nc);
1443  }
1444  }
1445  else if (m_cnd_tenfolio_max.contains(title)) {
1446  //Load Folio Current Value
1447  if (formula.contains("%seqtf_")) {
1448  loadFolioSeqHash(&m_cnd_tenfolio_max,title,"tenfolio",&nc);
1450  }
1451  }
1452 
1453  //Hundred Folio
1454  if (m_cnd_hundredfolio_max.isEmpty() || !m_cnd_hundredfolio_max.contains(title)) {
1455  //Insert Initial Value
1456  if (formula.contains("%seqhf_")) {
1457  insertFolioSeqHash(&m_cnd_hundredfolio_max,title,"hundredfolio",&nc);
1459  }
1460  }
1461  else if (m_cnd_hundredfolio_max.contains(title)) {
1462  //Load Folio Current Value
1463  if (formula.contains("%seqhf_")) {
1464  loadFolioSeqHash(&m_cnd_hundredfolio_max,title,"hundredfolio",&nc);
1466  }
1467  }
1468 }
1469 
1473 QString Diagram::title() const {
1474  return(border_and_titleblock.title());
1475 }
1476 
1477 QList <Element *> Diagram::elements() const {
1478  QList<Element *> element_list;
1479  foreach (QGraphicsItem *qgi, items()) {
1480  if (Element *elmt = qgraphicsitem_cast<Element *>(qgi))
1481  element_list <<elmt;
1482  }
1483  return (element_list);
1484 }
1485 
1490 QList <Conductor *> Diagram::conductors() const {
1491  QList<Conductor *> cnd_list;
1492  foreach (QGraphicsItem *qgi, items()) {
1493  if (Conductor *cnd = qgraphicsitem_cast<Conductor *>(qgi))
1494  cnd_list <<cnd;
1495  }
1496  return (cnd_list);
1497 }
1498 
1500  return m_elements_mover;
1501 }
1502 
1504  return m_element_texts_mover;
1505 }
1506 
1513 {
1514  for(Element *element : elements()) {
1515  if (element -> location() == location) {
1516  return(true);
1517  }
1518  }
1519  return(false);
1520 }
1521 
1527 bool Diagram::usesTitleBlockTemplate(const QString &name) {
1529 }
1530 
1535 void Diagram::freezeElements(bool freeze) {
1536  foreach (Element *elmt, elements()) {
1537  elmt->freezeLabel(freeze);
1538  }
1539 }
1540 
1546  foreach (Element *elmt, elements()) {
1547  elmt->freezeLabel(false);
1548  }
1549 }
1550 
1557 }
1558 
1564  return m_freeze_new_elements;
1565 }
1566 
1571 void Diagram::freezeConductors(bool freeze) {
1572  foreach (Conductor *cnd, conductors()) {
1573  cnd->setFreezeLabel(freeze);
1574  }
1575 }
1576 
1583 }
1584 
1590  return m_freeze_new_conductors_;
1591 }
1592 
1598 {
1599  QRectF old_rect = sceneRect();
1600  setSceneRect(border_and_titleblock.borderAndTitleBlockRect().united(itemsBoundingRect()));
1601  update(old_rect.united(sceneRect()));
1602 }
1603 
1611  // exporte les options de rendu en cours
1612  ExportProperties old_properties;
1613  old_properties.draw_grid = displayGrid();
1616  old_properties.draw_terminals = drawTerminals();
1619 
1620  // applique les nouvelles options de rendu
1621  setUseBorder (new_properties.exported_area == QET::BorderArea);
1622  setDrawTerminals (new_properties.draw_terminals);
1624  setDisplayGrid (new_properties.draw_grid);
1627 
1628  // retourne les anciennes options de rendu
1629  return(old_properties);
1630 }
1631 
1638  // delegue le calcul au BorderTitleBlock
1639  DiagramPosition diagram_position = border_and_titleblock.convertPosition(pos);
1640 
1641  // embarque la position cartesienne
1642  diagram_position.setPosition(pos);
1643 
1644  return(diagram_position);
1645 }
1646 
1653 QPointF Diagram::snapToGrid(const QPointF &p)
1654 {
1655  //Return a point rounded to the nearest pixel
1656  if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
1657  {
1658  int p_x = qRound(p.x());
1659  int p_y = qRound(p.y());
1660  return (QPointF(p_x, p_y));
1661  }
1662 
1663  //Return a point snapped to the grid
1664  int p_x = qRound(p.x() / Diagram::xGrid) * Diagram::xGrid;
1665  int p_y = qRound(p.y() / Diagram::yGrid) * Diagram::yGrid;
1666  return (QPointF(p_x, p_y));
1667 }
1668 
1669 
1670 
1676  foreach(QGraphicsItem *qgi, items()) {
1677  if (Terminal *t = qgraphicsitem_cast<Terminal *>(qgi)) {
1678  t -> setVisible(dt);
1679  }
1680  }
1681 }
1682 
1690 }
1691 
1695 QSet<Conductor *> Diagram::selectedConductors() const {
1696  QSet<Conductor *> conductors_set;
1697  foreach(QGraphicsItem *qgi, selectedItems()) {
1698  if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
1699  conductors_set << c;
1700  }
1701  }
1702  return(conductors_set);
1703 }
1704 
1707  QString clipboard_text = QApplication::clipboard() -> text().trimmed();
1708  bool may_be_diagram = clipboard_text.startsWith("<diagram") && clipboard_text.endsWith("</diagram>");
1709  return(may_be_diagram);
1710 }
1711 
1717  return(m_project);
1718 }
1719 
1726 {
1727  if (m_project == project)
1728  return;
1729 
1730  m_project = project;
1731  setParent (project);
1732 }
1733 
1738 int Diagram::folioIndex() const {
1739  if (!m_project) return(-1);
1740  return(m_project -> folioIndex(this));
1741 }
1742 
1749 qreal Diagram::declaredQElectroTechVersion(bool fallback_to_project) const {
1750  if (diagram_qet_version_ != -1) {
1751  return diagram_qet_version_;
1752  }
1753  if (fallback_to_project && m_project) {
1755  }
1756  return(-1);
1757 }
1758 
1765 {
1766  return m_project -> isReadOnly();
1767 }
1768 
1774  DiagramContent dc;
1775  foreach(QGraphicsItem *qgi, items()) {
1776  if (Element *e = qgraphicsitem_cast<Element *>(qgi)) {
1777  dc.m_elements << e;
1778  } else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(qgi)) {
1779  dc.m_text_fields << iti;
1780  } else if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
1781  dc.m_conductors_to_move << c;
1782  }
1783  }
1784  return(dc);
1785 }
1786 
1792 {
1793  for (QGraphicsItem *qgi : selectedItems())
1794  {
1795  if (qgi->type() == IndependentTextItem::Type ||
1796  qgi->type() == ConductorTextItem::Type ||
1797  qgi->type() == DiagramImageItem::Type ||
1798  qgi->type() == Element::Type ||
1799  qgi->type() == DynamicElementTextItem::Type)
1800  return true;
1801 
1802  if(qgi->type() == QGraphicsItemGroup::Type)
1803  if(dynamic_cast<ElementTextItemGroup *>(qgi))
1804  return true;
1805  }
1806 
1807  return false;
1808 }
virtual void keyPressEvent(QKeyEvent *event)
DiagramEventInterface::keyPressEvent By default, press escape key abort the curent action...
The QPropertyUndoCommand class This undo command manage QProperty of a QObject. This undo command can...
void setTitleBlockTemplate(const QString &)
Definition: diagram.cpp:1195
QString conductorCurrentAutoNum() const
QETProject::conductorCurrentAutoNum.
Definition: qetproject.cpp:561
static int yGrid
ordinate grid step size
Definition: diagram.h:78
void continueMovement(const QPointF &)
ElementsMover::continueMovement Add a move to the current movement.
bool importFromProject(QETProject *project, ElementsLocation &location)
ElementCollectionHandler::importFromProject Import the element represented by to the embedded collec...
void setDisplayGrid(bool)
Definition: diagram.h:283
void setProject(QETProject *)
Diagram::setProject Set parent project of this diagram, project also become the parent QObject of thi...
Definition: diagram.cpp:1725
bool useBorder()
Definition: diagram.h:309
Send item one layer below their current one; zValues are decremented.
Definition: qet.h:46
void changeZValue(QET::DepthOption option)
Diagram::changeZValue Change the Z value of the current selected item, according to ...
Definition: diagram.cpp:1300
bool addConductor(Conductor *conductor)
Terminal::addConductor Add a conductor to this terminal.
Definition: terminal.cpp:191
QStringList itemAt(const int) const
NumerotationContext::itemAt.
The DynamicElementTextItem class This class provide a simple text field of element who can be added o...
bool draw_grid_
Definition: diagram.h:112
DiagramPosition convertPosition(const QPointF &)
BorderTitleBlock::convertPosition Convert a Point in cartesian coordinate (x : 12.5, 56.9) to a point in grid coordinate (ex : B2)
Raise item one layer above their current one; zValues are incremented.
Definition: qet.h:45
void insertFolioSeqHash(QHash< QString, QStringList > *hash, const QString &title, const QString &seq, NumerotationContext *nc)
Diagram::insertFolioSeqHash This class inserts a stringlist containing all sequential variables relat...
Definition: diagram.cpp:1263
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
ElementTextsMover m_element_texts_mover
Definition: diagram.h:104
void adjustSceneRect()
Diagram::adjustSceneRect Recalcul and adjust the size of the scene.
Definition: diagram.cpp:1597
void setConductorsAutonumName(const QString &name)
Diagram::setConductorsAutonumName.
Definition: diagram.cpp:496
QHash< QString, QStringList > m_cnd_unitfolio_max
Hash containing max values for folio sequential autonums in this diagram.
Definition: diagram.h:97
void folioSequentialsToXml(QHash< QString, QStringList > *, QDomElement *, const QString &, const QString &, QDomDocument *)
Diagram::folioSequentialsToXml.
Definition: diagram.cpp:779
static const qreal margin
margin around the diagram
Definition: diagram.h:88
void invertSelection()
Definition: diagram.cpp:1231
QHash< QString, NumerotationContext > conductorAutoNum() const
QETProject::conductorAutoNum.
Definition: qetproject.cpp:494
void setPosition(const QPointF &)
void diagramActivated()
Signal emitted when users wish to edit an element from the diagram.
void setFreezeLabel(bool freeze)
Conductor::setFreezeLabel Freeze this conductor label if true Unfreeze this conductor label if false...
Definition: conductor.cpp:1985
bool m_freeze_new_elements
Definition: diagram.h:120
bool usesTitleBlockTemplate(const QString &)
Definition: diagram.cpp:1527
bool draw_border
Whether to render the border (along with rows/columns headers)
QHash< QString, QStringList > m_cnd_hundredfolio_max
Definition: diagram.h:99
QETProject * m_project
Definition: diagram.h:106
int folioIndex() const
Definition: diagram.cpp:1738
QString title() const
void titleChanged(const QString &)
Definition: diagram.cpp:1158
QRectF insideBorderRect() const
BorderTitleBlock::insideBorderRect.
QSet< Conductor * > selectedConductors() const
Definition: diagram.cpp:1695
QHash< QString, QStringList > m_cnd_tenfolio_max
Definition: diagram.h:98
void setUseBorder(bool)
Definition: diagram.h:301
void borderFromXml(const QDomElement &)
QSize imageSize() const
Definition: diagram.cpp:551
void toXml(QDomElement &) const
ConductorProperties::toXml Export conductor propertie, in the XML element &#39;e&#39;.
bool borderIsDisplayed() const
QList< Conductor * > m_conductors_to_move
void setDrawTerminals(bool)
Definition: diagram.cpp:1675
QHash< QString, QStringList > m_elmt_unitfolio_max
Hash containing max values for folio sequential autonums in this diagram.
Definition: diagram.h:93
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
Diagram::mouseMoveEvent This event is managed by diagram event interface if any.
Definition: diagram.cpp:227
static int yKeyGridFine
Key grid fine y step size.
Definition: diagram.h:86
bool isReadOnly() const
Diagram::isReadOnly.
Definition: diagram.cpp:1764
QRectF borderAndTitleBlockRect() const
BorderTitleBlock::borderAndTitleBlockRect.
void freezeElements(bool freeze)
Diagram::freezeElements Freeze every existent element label.
Definition: diagram.cpp:1535
void displayTitleBlock(bool)
QList< Conductor * > conductors() const
Diagram::conductors Return the list containing all conductors.
Definition: diagram.cpp:1490
qreal diagram_qet_version_
Definition: diagram.h:110
static const qreal Z
Definition: terminal.h:97
Diagram(QETProject *project)
Diagram::Diagram Constructor.
Definition: diagram.cpp:57
static int projectId(const QETProject *)
Definition: qetapp.cpp:2002
static QETProject * project(const uint &)
Definition: qetapp.cpp:1990
void endMovement()
ElementsMover::endMovement Ended the current movement by creating an undo added to the undostack of t...
void fromXml(QDomElement &)
ConductorProperties::fromXml Import conductor propertie, from the attribute of the xml element &#39;e&#39;...
Bring item to the foreground so they have the highest zValue.
Definition: qet.h:44
QString numerotationContextToFormula(const NumerotationContext &nc)
numerotationContextToFormula
bool draw_colored_conductors_
Definition: diagram.h:115
void draw(QPainter *painter)
BorderTitleBlock::draw Draw the border and the titleblock.
Terminal * terminal2
Definition: conductor.h:68
QIcon Conductor
Definition: qeticons.cpp:35
static int xGrid
abscissa grid step size
Definition: diagram.h:76
QList< QSet< Conductor * > > potentials()
Diagram::potential.
Definition: diagram.cpp:583
bool drawTerminals() const
Definition: diagram.h:347
QDomDocument toXml(bool=true)
Definition: diagram.cpp:604
void usedTitleBlockTemplateChanged(const QString &)
QList< QGraphicsItem * > items(int=All) const
DiagramContent::items.
DiagramEventInterface * m_event_interface
Definition: diagram.h:118
QSet< IndependentTextItem * > m_text_fields
ElementsMover & elementsMover()
Definition: diagram.cpp:1499
const QString version
QElectroTech version (as string, used to mark projects and elements XML documents) ...
Definition: qet.h:30
ElementTextsMover & elementTextsMover()
Definition: diagram.cpp:1503
void titleBlockTemplateChanged(const QString &)
Definition: diagram.cpp:1168
virtual void removeItem(QGraphicsItem *item)
Diagram::removeItem Réimplemented from QGraphicsScene::removeItem(QGraphicsItem *item) Do some specif...
Definition: diagram.cpp:1133
bool draw_colored_conductors
Whether to render conductors colors.
int beginMovement(Diagram *, QGraphicsItem *=nullptr)
ElementsMover::beginMovement Start a new movement.
int size() const
NumerotationContext::size.
Terminal * terminal1
Definition: conductor.h:67
QString title() const
Definition: diagram.cpp:1473
bool initFromXml(QDomElement &, QPointF=QPointF(), bool=true, DiagramContent *=nullptr)
Definition: diagram.cpp:824
QString elementAutoNumCurrentFormula() const
QETProject::elementAutoNumCurrentFormula.
Definition: qetproject.cpp:524
static int xKeyGridFine
Key grid fine x step size.
Definition: diagram.h:84
void borderToXml(QDomElement &)
void addConductorAutoNum(const QString &key, const NumerotationContext &context)
QETProject::addConductorAutoNum Add a new conductor numerotation context. If key already exist...
Definition: qetproject.cpp:588
virtual bool fromXml(QDomElement &, QHash< int, Terminal *> &, bool=false)
Element::fromXml Import the parameters of this element from a xml document. When call this function e...
Definition: element.cpp:647
virtual void unlinkAllElements()
Definition: element.h:134
QString conductorsAutonumName() const
Diagram::conductorsAutonumName.
Definition: diagram.cpp:488
qreal declaredQElectroTechVersion(bool=true) const
Definition: diagram.cpp:1749
Export the content of the diagram only.
Definition: qet.h:139
bool freezeNewConductors()
Diagram::freezeNewConductors.
Definition: diagram.cpp:1589
bool isEmpty() const
Definition: diagram.cpp:574
ExportProperties applyProperties(const ExportProperties &)
Definition: diagram.cpp:1610
QList< QDomElement > findInDomElement(const QDomElement &, const QString &)
Definition: qet.cpp:300
bool isValid() const
Conductor::isValid.
Definition: conductor.cpp:148
static bool valideXml(QDomElement &)
Definition: conductor.cpp:573
QGraphicsLineItem * conductor_setter_
Definition: diagram.h:102
QIcon tr
Definition: qeticons.cpp:204
bool toPaintDevice(QPaintDevice &, int=-1, int=-1, Qt::AspectRatioMode=Qt::KeepAspectRatio)
Definition: diagram.cpp:504
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
Diagram::mouseReleaseEvent This event is managed by diagram event interface if any.
Definition: diagram.cpp:246
TitleBlockTemplate * getTemplate(const QString &) override
DepthOption
List the various kind of changes for the zValue.
Definition: qet.h:43
static int yKeyGrid
Key grid y step size.
Definition: diagram.h:82
void setEventInterface(DiagramEventInterface *event_interface)
Diagram::setEventInterface Set event_interface has current interface. Diagram become the ownership of...
Definition: diagram.cpp:455
DiagramContent content() const
Definition: diagram.cpp:1773
The ElementTextItemGroup class This class represent a group of element text Texts in the group can be...
DiagramPosition convertPosition(const QPointF &)
Definition: diagram.cpp:1637
void updateLabels()
Diagram::updateLabels Update elements and conductors that reference folio field in their labels...
Definition: diagram.cpp:1245
bool drawColoredConductors() const
Definition: diagram.h:352
void freezeConductors(bool freeze)
Diagram::freezeConductors Freeze every existent conductor label.
Definition: diagram.cpp:1571
bool draw_titleblock
Whether to render the title block.
bool titleBlockIsDisplayed() const
void keyReleaseEvent(QKeyEvent *) override
Diagram::keyReleaseEvent This event is managed by diagram event interface if any. Else move selected ...
Definition: diagram.cpp:418
QList< Element * > m_elements
void keyPressEvent(QKeyEvent *event) override
Diagram::keyPressEvent This event is managed by diagram event interface if any. Else move selected el...
Definition: diagram.cpp:285
void titleBlockTemplateChanged(const QString &)
void deselectAll()
Definition: diagram.cpp:1222
bool displayGrid()
Definition: diagram.h:290
void setDrawColoredConductors(bool)
Definition: diagram.cpp:1688
The QetShapeItem class this class is used to draw a basic shape (line, rectangle, ellipse) into a dia...
Definition: qetshapeitem.h:35
QString m_conductors_autonum_name
Definition: diagram.h:117
QString elementCurrentAutoNum() const
QETProject::elementCurrentAutoNum.
Definition: qetproject.cpp:532
void calculateTextItemPosition()
Conductor::calculateTextItemPosition Move the text at middle of conductor (if is vertical or horizont...
Definition: conductor.cpp:1253
static QColor background_color
background color of diagram
Definition: diagram.h:91
void drawBackground(QPainter *, const QRectF &) override
Definition: diagram.cpp:131
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
Diagram::mouseDoubleClickEvent This event is managed by diagram event interface if any...
Definition: diagram.cpp:189
bool fromXml(QDomDocument &, QPointF=QPointF(), bool=true, DiagramContent *=nullptr)
Definition: diagram.cpp:804
bool freezeNewElements()
Diagram::freezeNewElements.
Definition: diagram.cpp:1563
QHash< QString, QStringList > m_elmt_hundredfolio_max
Definition: diagram.h:95
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void loadFolioSeqHash(QHash< QString, QStringList > *hash, const QString &title, const QString &seq, NumerotationContext *nc)
Diagram::loadFolioSeqHash This class loads all folio sequential variables related to the current auto...
Definition: diagram.cpp:1284
bool m_freeze_new_conductors_
Definition: diagram.h:121
static QPointF snapToGrid(const QPointF &p)
Diagram::snapToGrid Return a nearest snap point of p.
Definition: diagram.cpp:1653
static bool valideXml(QDomElement &)
Definition: element.cpp:614
bool draw_grid
Whether to render the diagram grid.
void replaceValue(int, QString)
NumerotationContext::replaceValue This class replaces the current NC field value with content...
QUndoStack & undoStack()
Definition: diagram.h:337
QGIManager * qgi_manager_
Definition: diagram.h:105
void titleBlockFromXml(const QDomElement &)
void removeConductor(Conductor *conductor)
Terminal::removeConductor Remove a conductor from this terminal.
Definition: terminal.cpp:215
QHash< QString, QStringList > m_elmt_tenfolio_max
Definition: diagram.h:94
QET::DiagramArea exported_area
Area of diagrams to be rendered.
static bool clipboardMayContainDiagram()
Definition: diagram.cpp:1706
void unfreezeElements()
Diagram::unfreezeElements Unfreeze every existent element label.
Definition: diagram.cpp:1545
void diagramTitleChanged(Diagram *, const QString &)
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
static int xKeyGrid
Key grid x step size.
Definition: diagram.h:80
void setFreezeNewElements(bool)
Diagram::freezeNewElements Set new element label to be frozen.
Definition: diagram.cpp:1555
ElementsMover m_elements_mover
Definition: diagram.h:103
The DiagramEventInterface class isRunning() return true if action is running (do something). By default return false.
Send item to the background so they have the lowest zValue.
Definition: qet.h:47
void loadCndFolioSeq()
Diagram::loadCndFolioSeq This class loads all conductor folio sequential variables related to the cur...
Definition: diagram.cpp:1415
void selectAll()
Definition: diagram.cpp:1210
QList< Element * > elements() const
Definition: diagram.cpp:1477
virtual void keyReleaseEvent(QKeyEvent *event)
void loadElmtFolioSeq()
Diagram::loadElmtFolioSeq This class loads all folio sequential variables related to the current auto...
Definition: diagram.cpp:1357
void addElementAutoNum(const QString &key, const NumerotationContext &context)
QETProject::addElementAutoNum Add a new element numerotation context. If key already exist...
Definition: qetproject.cpp:599
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
void setFreezeNewConductors(bool)
Diagram::setfreezeNewConductors Set new conductor label to be frozen.
Definition: diagram.cpp:1581
virtual void addItem(QGraphicsItem *item)
Diagram::addItem Réimplemented from QGraphicsScene::addItem(QGraphicsItem *item) Do some specific ope...
Definition: diagram.cpp:1108
~Diagram() override
Diagram::~Diagram Destructor.
Definition: diagram.cpp:100
void refreshContents()
Diagram::refreshContents refresh all content of diagram.
Definition: diagram.cpp:1089
void clearEventInterface()
Diagram::clearEventInterface Clear the current event interface.
Definition: diagram.cpp:475
void freezeLabel(bool freeze)
Element::freezeLabel Freeze this element label.
Definition: element.cpp:1545
void titleBlockToXml(QDomElement &)
QHash< QString, NumerotationContext > elementAutoNum() const
QETProject::elementAutoNum.
Definition: qetproject.cpp:502
BorderTitleBlock border_and_titleblock
Diagram dimensions and title block.
Definition: diagram.h:74
TitleBlockTemplatesProjectCollection * embeddedTitleBlockTemplatesCollection()
Definition: qetproject.cpp:236
void titleBlockTemplateRemoved(const QString &, const QString &=QString())
Definition: diagram.cpp:1183
QETProject * project() const
Definition: diagram.cpp:1716
Export the diagram along with its border and title block.
Definition: qet.h:138
void folioSequentialsFromXml(const QDomElement &, QHash< QString, QStringList > *, const QString &, const QString &, const QString &, const QString &)
Diagram::folioSequentialsFromXml Load folio sequential from QDomElement.
Definition: diagram.cpp:1067
bool canRotateSelection() const
Diagram::canRotateSelection.
Definition: diagram.cpp:1791
QList< Conductor * > conductors(int=AnyConductor) const
DiagramContent::conductors.
XML parsing failed.
Definition: qetproject.h:55
virtual void wheelEvent(QGraphicsSceneWheelEvent *event)
QString path() const
ElementsLocation::path.
ConductorProperties defaultConductorProperties
Default properties for new conductors.
Definition: diagram.h:72
bool draw_terminals
Whether to render terminals.
QString titleBlockTemplateName() const
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
Diagram::mousePressEvent This event is managed by diagram event interface if any. ...
Definition: diagram.cpp:208
static ElementFactory * Instance()
void wheelEvent(QGraphicsSceneWheelEvent *event) override
Diagram::wheelEvent This event is managed by diagram event interface if any.
Definition: diagram.cpp:265
void titleBlockTemplateRemoved(const QString &, const TitleBlockTemplate *=nullptr)
The ElementCollectionHandler class Provide several method to copy element or directory from a collect...
bool use_border_
Definition: diagram.h:113
bool usesElement(const ElementsLocation &)
Definition: diagram.cpp:1512