QElectroTech  0.70
exportdialog.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 "exportdialog.h"
19 #include <QSvgGenerator>
20 #include <cmath>
21 #include <QtXml>
22 #include <utility>
23 #include "qeticons.h"
24 #include "qetmessagebox.h"
25 #include "exportpropertieswidget.h"
26 #include "createdxf.h"
27 #include "conductorsegment.h"
34 #include "diagramfoliolist.h"
35 #include "elementpicturefactory.h"
36 #include "element.h"
37 #include "dynamicelementtextitem.h"
38 
39 #include <QGraphicsSimpleTextItem>
40 
46 ExportDialog::ExportDialog(QETProject *project, QWidget *parent) : QDialog(parent) {
47  if (!project) return;
48 
49  // recupere le projet a exporter
50  project_ = project;
51 
52  // recupere les parametres d'export definis dans la configuration de l'application
53  ExportProperties default_export_properties = ExportProperties::defaultExportProperties();
54 
55  // on utilise le repertoire du projet a exporter si possible
56  if (!project_ -> filePath().isEmpty()) {
57  default_export_properties.destination_directory = project_ -> currentDir();
58  }
59 
60  // la taille minimale du dialogue est fixee
61  setMinimumSize(800, 590);
62  resize(minimumSize());
63  setWindowTitle(tr("Exporter les folios du projet", "window title"));
64 
65  // options d'export, dans le widget epw
66  epw = new ExportPropertiesWidget(default_export_properties);
67 
68  // le dialogue comporte deux boutons
69  buttons = new QDialogButtonBox(this);
70  buttons -> setOrientation(Qt::Horizontal);
71  buttons -> setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Save);
72  QPushButton *export_button = buttons -> button(QDialogButtonBox::Save);
73  export_button -> setText(tr("Exporter"));
74 
75  // disposition des elements
76 
77  QHBoxLayout *hLayout = new QHBoxLayout();
78  hLayout -> addWidget(new QLabel(tr("Choisissez les folios que vous désirez exporter ainsi que leurs dimensions :")));
79  selectAll = new QPushButton();
80  deSelectAll = new QPushButton();
81  selectAll -> setText(tr("Tout cocher"));
82  deSelectAll -> setText(tr("Tout décocher"));
83  hLayout -> addWidget(selectAll);
84  hLayout -> addWidget(deSelectAll);
85  connect(selectAll, SIGNAL(clicked()), this, SLOT(slot_selectAllClicked()));
86  connect(deSelectAll, SIGNAL(clicked()), this, SLOT(slot_deSelectAllClicked()));
87 
88 
89  QVBoxLayout *layout = new QVBoxLayout(this);
90  layout -> addLayout(hLayout);
91  layout -> addWidget(initDiagramsListPart(), 1);
92  layout -> addWidget(epw);
93  layout -> addWidget(buttons);
94 
95  // connexions signaux/slots
96  connect(epw, SIGNAL(formatChanged()), this, SLOT(slot_changeFilesExtension()));
97  connect(epw, SIGNAL(exportedAreaChanged()), this, SLOT(slot_changeUseBorder()));
98  connect(buttons, SIGNAL(accepted()), this, SLOT(slot_export()));
99  connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
100 
101  // ajustement des extensions des fichiers
103 }
104 
109 }
110 
115  int checked_diagrams_count = 0;
116  foreach(ExportDiagramLine *diagram_line, diagram_lines_.values()) {
117  if (diagram_line -> must_export -> isChecked()) ++ checked_diagrams_count;
118  }
119  return(checked_diagrams_count);
120 }
121 
127  preview_mapper_ = new QSignalMapper(this);
128  width_mapper_ = new QSignalMapper(this);
129  height_mapper_ = new QSignalMapper(this);
130  ratio_mapper_ = new QSignalMapper(this);
131  reset_mapper_ = new QSignalMapper(this);
132  clipboard_mapper_ = new QSignalMapper(this);
133 
134  connect(preview_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_previewDiagram(int)));
135  connect(width_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctHeight(int)));
136  connect(height_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctWidth(int)));
137  connect(ratio_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_keepRatioChanged(int)));
138  connect(reset_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_resetSize(int)));
139  connect(clipboard_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_exportToClipBoard(int)));
140 
141  diagrams_list_layout_ = new QGridLayout();
142 
143  int line_count = 0;
144  diagrams_list_layout_ -> addWidget(new QLabel(tr("Titre du folio")), line_count, 1, Qt::AlignHCenter | Qt::AlignVCenter);
145  diagrams_list_layout_ -> addWidget(new QLabel(tr("Nom de fichier")), line_count, 2, Qt::AlignHCenter | Qt::AlignVCenter);
146  diagrams_list_layout_ -> addWidget(new QLabel(tr("Dimensions")), line_count, 3, Qt::AlignHCenter | Qt::AlignVCenter);
147 
148  // remplit la liste
149  foreach (Diagram *diagram, project_ -> diagrams()) {
150  ++ line_count;
151  ExportDiagramLine *diagram_line = new ExportDiagramLine(diagram, diagramSize(diagram));
152  diagram_lines_.insert(line_count, diagram_line);
153  diagrams_list_layout_ -> addWidget(diagram_line -> must_export, line_count, 0);
154  diagrams_list_layout_ -> addWidget(diagram_line -> title_label, line_count, 1);
155  diagrams_list_layout_ -> addWidget(diagram_line -> file_name, line_count, 2);
156  diagrams_list_layout_ -> addLayout(diagram_line -> sizeLayout(), line_count, 3);
157 
158  // si on decoche tous les schemas, on desactive le bouton "Exporter"
159  connect(diagram_line -> must_export, SIGNAL(toggled(bool)), this, SLOT(slot_checkDiagramsCount()));
160 
161  // mappings et signaux pour la gestion des dimensions du schema
162  width_mapper_ -> setMapping(diagram_line -> width, line_count);
163  height_mapper_ -> setMapping(diagram_line -> height, line_count);
164  ratio_mapper_ -> setMapping(diagram_line -> keep_ratio, line_count);
165  reset_mapper_ -> setMapping(diagram_line -> reset_size, line_count);
166  connect(diagram_line -> width, SIGNAL(valueChanged(int)), width_mapper_, SLOT(map()));
167  connect(diagram_line -> height, SIGNAL(valueChanged(int)), height_mapper_, SLOT(map()));
168  connect(diagram_line -> keep_ratio, SIGNAL(toggled(bool)), ratio_mapper_, SLOT(map()));
169  connect(diagram_line -> reset_size, SIGNAL(clicked(bool)), reset_mapper_, SLOT(map()));
170 
171  // mappings et signaux pour l'apercu du schema
172  preview_mapper_ -> setMapping(diagram_line -> preview, line_count);
173  connect(diagram_line -> preview, SIGNAL(clicked(bool)), preview_mapper_, SLOT(map()));
174 
175  // mappings et signaux pour l'export du schema vers le presse-papier
176  clipboard_mapper_ -> setMapping(diagram_line -> clipboard, line_count);
177  connect(diagram_line -> clipboard, SIGNAL(clicked(bool)), clipboard_mapper_, SLOT(map()));
178  }
179 
180  QWidget *widget_diagrams_list = new QWidget();
181  widget_diagrams_list -> setLayout(diagrams_list_layout_);
182 
183  QScrollArea *scroll_diagrams_list = new QScrollArea();
184  scroll_diagrams_list -> setWidget(widget_diagrams_list);
185 
186  return(scroll_diagrams_list);
187 }
188 
190  foreach (ExportDiagramLine *diagramLine, diagram_lines_) {
191  diagramLine -> must_export -> setChecked(true);
192  }
193 }
194 
196  foreach (ExportDiagramLine *diagramLine, diagram_lines_) {
197  diagramLine -> must_export -> setChecked(false);
198  }
199 }
200 
201 
202 
208  QSize diagram_size = diagramSize(diagram);
209  qreal diagram_ratio = (qreal)diagram_size.width() / (qreal)diagram_size.height();
210  return(diagram_ratio);
211 }
212 
219  // sauvegarde le parametre useBorder du schema
220  bool state_useBorder = diagram -> useBorder();
221 
222  // applique le useBorder adequat et calcule le ratio
223  diagram -> setUseBorder(epw -> exportProperties().exported_area == QET::BorderArea);
224  QSize diagram_size = diagram -> imageSize();
225 
226  // restaure le parametre useBorder du schema
227  diagram -> setUseBorder(state_useBorder);
228 
229  return(diagram_size);
230 }
231 
238 void ExportDialog::slot_correctWidth(int diagram_id) {
239  // recupere l'ExportDiagramLine concernee
240  ExportDialog::ExportDiagramLine *current_diagram = diagram_lines_[diagram_id];
241  if (!current_diagram) return;
242 
243  // ne fait rien si l'option "Conserver les proportions" n'est pas activee
244  if (!(current_diagram -> keep_ratio -> isChecked())) return;
245 
246  // recupere les proportions du schema
247  qreal diagram_ratio = diagramRatio(current_diagram -> diagram);
248 
249  // ajuste la largeur
250  current_diagram -> width -> blockSignals(true);
251  current_diagram -> width -> setValue(qRound(current_diagram -> height -> value() * diagram_ratio));
252  current_diagram -> width -> blockSignals(false);
253 }
254 
261 void ExportDialog::slot_correctHeight(int diagram_id) {
262  // recupere l'ExportDiagramLine concernee
263  ExportDialog::ExportDiagramLine *current_diagram = diagram_lines_[diagram_id];
264  if (!current_diagram) return;
265 
266  // ne fait rien si l'option "Conserver les proportions" n'est pas activee
267  if (!(current_diagram -> keep_ratio -> isChecked())) return;
268 
269  // recupere les proportions du schema
270  qreal diagram_ratio = diagramRatio(current_diagram -> diagram);
271 
272  // ajuste la hauteur
273  current_diagram -> height -> blockSignals(true);
274  current_diagram -> height -> setValue(qRound(current_diagram -> width -> value() / diagram_ratio));
275  current_diagram -> height -> blockSignals(false);
276 }
277 
284  // recupere l'ExportDiagramLine concernee
285  ExportDialog::ExportDiagramLine *current_diagram = diagram_lines_[diagram_id];
286  if (!current_diagram) return;
287 
288  // gere l'icone du bouton "Conserver les proportions"
289  if (current_diagram -> keep_ratio -> isChecked()) {
290  current_diagram -> keep_ratio -> setIcon(QET::Icons::ObjectLocked);
291  } else {
292  current_diagram -> keep_ratio -> setIcon(QET::Icons::ObjectUnlocked);
293  }
294 
295  // ne fait rien si l'option "Conserver les proportions" n'est pas activee
296  if (!(current_diagram -> keep_ratio -> isChecked())) return;
297 
298  // au contraire, si elle est activee, ajuste la hauteur en fonction de la largeur
299  slot_correctHeight(diagram_id);
300 }
301 
306 void ExportDialog::slot_resetSize(int diagram_id) {
307  // recupere l'ExportDiagramLine concernee
308  ExportDialog::ExportDiagramLine *current_diagram = diagram_lines_[diagram_id];
309  if (!current_diagram) return;
310 
311  // recupere la taille du schema
312  QSize diagram_size = diagramSize(current_diagram -> diagram);
313 
314  // reinitialise les champs largeur et hauteur
315  current_diagram -> width -> blockSignals(true);
316  current_diagram -> height -> blockSignals(true);
317  current_diagram -> width -> setValue(diagram_size.width());
318  current_diagram -> height -> setValue(diagram_size.height());
319  current_diagram -> width -> blockSignals(false);
320  current_diagram -> height -> blockSignals(false);
321 }
322 
331 QImage ExportDialog::generateImage(Diagram *diagram, int width, int height, bool keep_aspect_ratio) {
332  saveReloadDiagramParameters(diagram, true);
333 
334  QImage image(width, height, QImage::Format_RGB32);
335  diagram -> toPaintDevice(
336  image,
337  width,
338  height,
339  keep_aspect_ratio ? Qt::KeepAspectRatio : Qt::IgnoreAspectRatio
340  );
341 
342  saveReloadDiagramParameters(diagram, false);
343 
344  return(image);
345 }
346 
354  static ExportProperties state_exportProperties;
355 
356  if (save) {
357  // memorise les parametres relatifs au schema tout en appliquant les nouveaux
358  state_exportProperties = diagram -> applyProperties(epw -> exportProperties());
359  } else {
360  // restaure les parametres relatifs au schema
361  diagram -> applyProperties(state_exportProperties);
362  }
363 }
364 
373 void ExportDialog::generateSvg(Diagram *diagram, int width, int height, bool keep_aspect_ratio, QIODevice &io_device) {
374  saveReloadDiagramParameters(diagram, true);
375 
376  // genere une QPicture a partir du schema
377  QPicture picture;
378  diagram -> toPaintDevice(
379  picture,
380  width,
381  height,
382  keep_aspect_ratio ? Qt::KeepAspectRatio : Qt::IgnoreAspectRatio
383  );
384 
385  // "joue" la QPicture sur un QSvgGenerator
386  QSvgGenerator svg_engine;
387  svg_engine.setSize(QSize(width, height));
388  svg_engine.setOutputDevice(&io_device);
389  QPainter svg_painter(&svg_engine);
390  picture.play(&svg_painter);
391 
392  saveReloadDiagramParameters(diagram, false);
393 }
394 
403 void ExportDialog::generateDxf(Diagram *diagram, int width, int height, bool keep_aspect_ratio, QString &file_path) {
404  saveReloadDiagramParameters(diagram, true);
405 
406  width -= 2*Diagram::margin;
407  height -= 2*Diagram::margin;
408 
409  Createdxf::xScale = Createdxf::sheetWidth / double(width);
410  Createdxf::yScale = Createdxf::sheetHeight / double(height);
411 
412  Createdxf::dxfBegin(file_path);
413 
414  //Add project elements (lines, rectangles, circles, texts) to dxf file
415  if (epw -> exportProperties().draw_border) {
416  Createdxf::drawRectangle(file_path, 0, 0, double(width)*Createdxf::xScale, double(height)*Createdxf::yScale, 0);
417  }
418  diagram -> border_and_titleblock.drawDxf(width, height, keep_aspect_ratio, file_path, 0);
419 
420  // Build the lists of elements.
421  QList<Element *> list_elements;
422  QList<Conductor *> list_conductors;
423  QList<DiagramTextItem *> list_texts;
424  QList<DiagramImageItem *> list_images;
425  QList<QLineF *> list_lines;
426  QList<QRectF *> list_rectangles;
427  //QList<QRectF *> list_ellipses;
428  QList <QetShapeItem *> list_shapes;
429 
430  DiagramFolioList *ptr = dynamic_cast<DiagramFolioList *>(diagram);
431  if (ptr) {
432  list_lines = ptr -> lines();
433  list_rectangles = ptr -> rectangles();
434  QSettings settings;
435 
436  // fill the rows with text.
437  QString authorTranslatable = tr("Auteur");
438  QString titleTranslatable = tr("Titre");
439  QString folioTranslatable = tr("Folio");
440  QString dateTranslatable = tr("Date");
441 
442  qreal x0 = list_rectangles[0] -> topLeft().x();
443  qreal y0 = list_rectangles[0] -> topLeft().y();
444  qreal rowHeight = (list_rectangles[0] -> height())/30;
445  QRectF row_RectF(x0, y0, list_rectangles[0] -> width(), rowHeight);
446 
447  fillRow(file_path, row_RectF, authorTranslatable, titleTranslatable, folioTranslatable, dateTranslatable);
448  QList<Diagram *> diagram_list = ptr -> project() -> diagrams();
449 
450  int startDiagram = (ptr -> getId()) *29;
451 
452  for (int i = startDiagram; i < startDiagram+29 && i < diagram_list.size(); ++i) {
453  y0 += rowHeight;
454  QRectF row_rect(x0, y0, list_rectangles[0] -> width(), rowHeight);
455  if (settings.value("genericpanel/folio", true).toBool()){
456  fillRow(file_path, row_rect, diagram_list[i] -> border_and_titleblock.author(),
457  diagram_list[i] -> title(),
458  diagram_list[i] -> border_and_titleblock.finalfolio(),
459  diagram_list[i] -> border_and_titleblock.date().toString("dd/MM/yy"));
460 
461  }else{
462  fillRow(file_path, row_rect, diagram_list[i] -> border_and_titleblock.author(),
463  diagram_list[i] -> title(),
464  QString::number(diagram_list[i] ->folioIndex()+1),
465  diagram_list[i] -> border_and_titleblock.date().toString("dd/MM/yy"));
466 
467  }
468 }
469 
470  } else {
471  // Determine les elements a "XMLiser"
472  foreach(QGraphicsItem *qgi, diagram -> items()) {
473  if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
474  list_elements << elmt;
475  } else if (Conductor *f = qgraphicsitem_cast<Conductor *>(qgi)) {
476  list_conductors << f;
477  } else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(qgi)) {
478  list_texts << iti;
479  } else if (DiagramImageItem *dii = qgraphicsitem_cast<DiagramImageItem *>(qgi)) {
480  list_images << dii;
481  } else if (QetShapeItem *dii = qgraphicsitem_cast<QetShapeItem *>(qgi)) {
482  list_shapes << dii;
483  } else if (DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(qgi)) {
484  list_texts << deti;
485  }
486  }
487  }
488 
489  foreach (QetShapeItem *qsi, list_shapes) qsi->toDXF(file_path, qsi->pen());
490 
491  //Draw elements
492  foreach(Element *elmt, list_elements)
493  {
494  double rotation_angle = elmt -> orientation() * 90;
495 
496  qreal elem_pos_x = elmt -> pos().x();
497  qreal elem_pos_y = elmt -> pos().y();// - (diagram -> margin / 2);
498 
499  qreal hotspot_x = (elem_pos_x) * Createdxf::xScale;
500  qreal hotspot_y = Createdxf::sheetHeight - (elem_pos_y) * Createdxf::yScale;
501 
503 
504  for(QGraphicsSimpleTextItem *text : primitives.m_texts)
505  {
506  qreal fontSize = text->font().pointSizeF();
507  if (fontSize < 0)
508  fontSize = text->font().pixelSize();
509 
510  fontSize *= Createdxf::yScale;
511  qreal x = elem_pos_x + text->pos().x();
512  qreal y = elem_pos_y + text->pos().y();
513  x *= Createdxf::xScale;
514  y = Createdxf::sheetHeight - (y * Createdxf::yScale);// - fontSize;
515  QPointF transformed_point = rotation_transformed(x, y, hotspot_x, hotspot_y, rotation_angle);
516  x = transformed_point.x();
517  y = transformed_point.y();
518  QStringList lines = text->text().split('\n');
519  y += (fontSize/2) * (lines.count()-1);
520  for (QString line : lines)
521  {
522  qreal angle = 360 - (text->rotation() + rotation_angle);
523  if (line.size() > 0 && line != "_" ) {
524  Createdxf::drawText(file_path, line, x, y, fontSize, angle, 0);
525  }
526  angle += 1080;
527  // coordinates for next line
528  if (int(angle) % 360 == 0) // no rotation
529  y -= fontSize*1.06;
530  else if (int(angle - 180) % 360 == 0) // 180 degrees rotation
531  y += fontSize*1.06;
532  else if (int(angle - 270) % 360 == 0) // 270 degrees rotation
533  x -= fontSize*1.06;
534  else // ((angle - 90) % 360 == 0) 90 degrees rotation
535  x += fontSize*1.06;
536  }
537  }
538 
539  for (QLineF line : primitives.m_lines)
540  {
541  qreal x1 = (elem_pos_x + line.p1().x()) * Createdxf::xScale;
542  qreal y1 = Createdxf::sheetHeight - (elem_pos_y + line.p1().y()) * Createdxf::yScale;
543  QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle);
544  x1 = transformed_point.x();
545  y1 = transformed_point.y();
546  qreal x2 = (elem_pos_x + line.p2().x()) * Createdxf::xScale;
547  qreal y2 = Createdxf::sheetHeight - (elem_pos_y + line.p2().y()) * Createdxf::yScale;
548  transformed_point = rotation_transformed(x2, y2, hotspot_x, hotspot_y, rotation_angle);
549  x2 = transformed_point.x();
550  y2 = transformed_point.y();
551  Createdxf::drawLine(file_path, x1, y1, x2, y2, 0);
552  }
553 
554  for (QRectF rect : primitives.m_rectangles)
555  {
556  qreal x1 = (elem_pos_x + rect.bottomLeft().x()) * Createdxf::xScale;
557  qreal y1 = Createdxf::sheetHeight - (elem_pos_y + rect.bottomLeft().y()) * Createdxf::yScale;
558  qreal w = rect.width() * Createdxf::xScale;
559  qreal h = rect.height() * Createdxf::yScale;
560  // opposite corner
561  qreal x2 = x1 + w;
562  qreal y2 = y1 + h;
563  QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle);
564  x1 = transformed_point.x();
565  y1 = transformed_point.y();
566  transformed_point = rotation_transformed(x2, y2, hotspot_x, hotspot_y, rotation_angle);
567  x2 = transformed_point.x();
568  y2 = transformed_point.y();
569  qreal bottom_left_x = (x1 < x2) ? x1 : x2;
570  qreal bottom_left_y = (y1 < y2) ? y1 : y2;
571  w = (x1 < x2) ? x2-x1 : x1-x2;
572  h = (y1 < y2) ? y2-y1 : y1-y2;
573  Createdxf::drawRectangle(file_path, bottom_left_x, bottom_left_y, w, h, 0);
574  }
575 
576  for (QRectF circle_rect : primitives.m_circles)
577  {
578  qreal x1 = (elem_pos_x + circle_rect.center().x()) * Createdxf::xScale;
579  qreal y1 = Createdxf::sheetHeight - (elem_pos_y + circle_rect.center().y()) * Createdxf::yScale;
580  qreal r = circle_rect.width() * Createdxf::xScale / 2;
581  QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle);
582  x1 = transformed_point.x();
583  y1 = transformed_point.y();
584  Createdxf::drawCircle(file_path, r, x1, y1, 0);
585  }
586 
587  for (QVector<QPointF> polygon : primitives.m_polygons)
588  {
589  if (polygon.size() == 0)
590  continue;
591  qreal x1 = (elem_pos_x + polygon.at(0).x()) * Createdxf::xScale;
592  qreal y1 = Createdxf::sheetHeight - (elem_pos_y + polygon.at(0).y()) * Createdxf::yScale;
593  QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle);
594  x1 = transformed_point.x();
595  y1 = transformed_point.y();
596  for (int i = 1; i < polygon.size(); ++i ) {
597  qreal x2 = (elem_pos_x + polygon.at(i).x()) * Createdxf::xScale;
598  qreal y2 = Createdxf::sheetHeight - (elem_pos_y + polygon.at(i).y()) * Createdxf::yScale;
599  QPointF transformed_point = rotation_transformed(x2, y2, hotspot_x, hotspot_y, rotation_angle);
600  x2 = transformed_point.x();
601  y2 = transformed_point.y();
602  Createdxf::drawLine(file_path, x1, y1, x2, y2, 0);
603  x1 = x2;
604  y1 = y2;
605  }
606  }
607 
608  // Draw arcs and ellipses
609  for (QVector<qreal> arc : primitives.m_arcs)
610  {
611  if (arc.size() == 0)
612  continue;
613  qreal x = (elem_pos_x + arc.at(0)) * Createdxf::xScale;
614  qreal y = Createdxf::sheetHeight - (elem_pos_y + arc.at(1)) * Createdxf::yScale;
615  qreal w = arc.at(2) * Createdxf::xScale;
616  qreal h = arc.at(3) * Createdxf::yScale;
617  qreal startAngle = arc.at(4);
618  qreal spanAngle = arc .at(5);
619  Createdxf::drawArcEllipse(file_path, x, y, w, h, startAngle, spanAngle, hotspot_x, hotspot_y, rotation_angle, 0);
620  }
621  }
622 
623  //Draw conductors
624  foreach(Conductor *cond, list_conductors) {
625  foreach(ConductorSegment *segment, cond -> segmentsList()) {
626  qreal x1 = (segment -> firstPoint().x()) * Createdxf::xScale;
627  qreal y1 = Createdxf::sheetHeight - (segment -> firstPoint().y() * Createdxf::yScale);
628  qreal x2 = (segment -> secondPoint().x()) * Createdxf::xScale;
629  qreal y2 = Createdxf::sheetHeight - (segment -> secondPoint().y() * Createdxf::yScale);
630  Createdxf::drawLine(file_path, x1, y1, x2, y2, 0);
631  }
632  //Draw conductor text item
633  ConductorTextItem *textItem = cond -> textItem();
634  if (textItem) {
635  qreal fontSize = textItem -> font().pointSizeF();
636  if (fontSize < 0)
637  fontSize = textItem -> font().pixelSize();
638  fontSize *= Createdxf::yScale;
639  qreal x = (textItem -> pos().x()) * Createdxf::xScale;
640  qreal y = Createdxf::sheetHeight - (textItem -> pos().y() * Createdxf::yScale) - fontSize;
641  QStringList lines = textItem->toPlainText().split('\n');
642  foreach (QString line, lines) {
643  qreal angle = 360 - (textItem -> rotation());
644  if (line.size() > 0 && line != "_" )
645  Createdxf::drawText(file_path, line, x, y, fontSize, angle, 0 );
646 
647  angle += 1080;
648  // coordinates for next line
649  if (int(angle) % 360 == 0) // no rotation
650  y -= fontSize*1.06;
651  else if (int(angle - 180) % 360 == 0) // 180 degrees rotation
652  y += fontSize*1.06;
653  else if (int(angle - 270) % 360 == 0) // 270 degrees rotation
654  x -= fontSize*1.06;
655  else // ((angle - 90) % 360 == 0) 90 degrees rotation
656  x += fontSize*1.06;
657  }
658 
659  }
660  }
661 
662  //Draw text items
663  foreach(DiagramTextItem *dti, list_texts) {
664  qreal fontSize = dti -> font().pointSizeF();
665  if (fontSize < 0)
666  fontSize = dti -> font().pixelSize();
667  fontSize *= Createdxf::yScale;
668  qreal x = (dti->scenePos().x()) * Createdxf::xScale;
669  qreal y = Createdxf::sheetHeight - (dti->scenePos().y() * Createdxf::yScale) - fontSize*1.05;
670  QStringList lines = dti -> toPlainText().split('\n');
671  foreach (QString line, lines) {
672  qreal angle = 360 - (dti -> rotation());
673  if (line.size() > 0 && line != "_" )
674  Createdxf::drawText(file_path, line, x, y, fontSize, angle, 0);
675 
676  angle += 1080;
677  // coordinates for next line
678  if (int(angle) % 360 == 0) // no rotation
679  y -= fontSize*1.06;
680  else if (int(angle - 180) % 360 == 0) // 180 degrees rotation
681  y += fontSize*1.06;
682  else if (int(angle - 270) % 360 == 0) // 270 degrees rotation
683  x -= fontSize*1.06;
684  else // ((angle - 90) % 360 == 0) 90 degrees rotation
685  x += fontSize*1.06;
686  }
687  }
688  Createdxf::dxfEnd(file_path);
689 
690  saveReloadDiagramParameters(diagram, false);
691 }
692 
693 void ExportDialog::fillRow(const QString& file_path, const QRectF &row_rect, QString author, const QString& title,
694  QString folio, QString date)
695 {
696  qreal x = row_rect.bottomLeft().x();
697  qreal y = row_rect.bottomLeft().y();
698 
699  x *= Createdxf::xScale;
701  qreal height = row_rect.height() * Createdxf::yScale *0.7;
702  y += height*0.2;
703 
704  Createdxf::drawTextAligned(file_path, std::move(folio),
705  x + 0.02*DiagramFolioList::colWidths[0]*row_rect.width()*Createdxf::xScale, y, height, 0, 0, 5, 0,
706  x + 0.95*DiagramFolioList::colWidths[0]*row_rect.width()*Createdxf::xScale, 0);
707 
708  x += DiagramFolioList::colWidths[0]*row_rect.width()*Createdxf::xScale;
709  QString heading = tr("Titre");
710  if (title == heading)
711  Createdxf::drawTextAligned(file_path, title,
712  x + 0.02*DiagramFolioList::colWidths[1]*row_rect.width()*Createdxf::xScale, y, height, 0, 0, 5, 0,
713  x + 0.02*DiagramFolioList::colWidths[1]*row_rect.width()*Createdxf::xScale, 0);
714  else
715  Createdxf::drawTextAligned(file_path, title,
716  x + 0.02*DiagramFolioList::colWidths[1]*row_rect.width()*Createdxf::xScale, y, height, 0, 0, 5, 0,
717  x + 0.02*DiagramFolioList::colWidths[1]*row_rect.width()*Createdxf::xScale, 0, true);
718 
719  x += DiagramFolioList::colWidths[1]*row_rect.width()*Createdxf::xScale;
720  Createdxf::drawTextAligned(file_path, std::move(author),
721  x + 0.02*DiagramFolioList::colWidths[2]*row_rect.width()*Createdxf::xScale, y, height, 0, 0, 5, 0,
722  x + 3.02*DiagramFolioList::colWidths[2]*row_rect.width()*Createdxf::xScale, 0);
723 
724  x += DiagramFolioList::colWidths[2]*row_rect.width()*Createdxf::xScale;
725  Createdxf::drawTextAligned(file_path, std::move(date),
726  x + 0.02*DiagramFolioList::colWidths[3]*row_rect.width()*Createdxf::xScale, y, height, 0, 0, 5, 0,
727  x + 5.02*DiagramFolioList::colWidths[3]*row_rect.width()*Createdxf::xScale, 0);
728 }
729 
730 QPointF ExportDialog::rotation_transformed(qreal px, qreal py , qreal origin_x, qreal origin_y, qreal angle) {
731 
732  angle *= -3.14159265 / 180;
733 
734  float s = sin(angle);
735  float c = cos(angle);
736 
737  // Vector to rotate:
738  qreal Vx = px - origin_x;
739  qreal Vy = py - origin_y;
740 
741  // rotate vector
742  float xnew = Vx * c - Vy * s;
743  float ynew = Vx * s + Vy * c;
744 
745  return QPointF(xnew + origin_x, ynew + origin_y);
746 }
747 
748 
749 
754  // recupere la liste des schemas a exporter
755  QList<ExportDiagramLine *> diagrams_to_export;
756  foreach(ExportDiagramLine *diagram_line, diagram_lines_.values()) {
757  if (diagram_line -> must_export -> isChecked()) {
758  diagrams_to_export << diagram_line;
759  }
760  }
761 
762  // verification #1 : chaque schema coche doit avoir un nom de fichier distinct
763  QSet<QString> filenames;
764  foreach(ExportDiagramLine *diagram_line, diagrams_to_export) {
765  QString diagram_file = diagram_line -> file_name -> text();
766  if (!diagram_file.isEmpty()) {
767  filenames << diagram_file;
768  }
769  }
770  if (filenames.count() != diagrams_to_export.count()) {
772  this,
773  tr("Noms des fichiers cibles", "message box title"),
774  tr(
775  "Vous devez entrer un nom de fichier non vide et unique pour chaque "
776  "folio à exporter.",
777  "message box content"
778  )
779  );
780  return;
781  }
782 
783  // verification #2 : un chemin vers un dossier doit avoir ete specifie
784 
785  QDir target_dir_path(epw -> exportProperties().destination_directory);
786  if (!target_dir_path.exists()) {
788  this,
789  tr("Dossier non spécifié", "message box title"),
790  tr("Vous devez spécifier le chemin du dossier dans lequel seront enregistrés les fichiers images.", "message box content"),
791  QMessageBox::Ok
792  );
793  return;
794  }
795 
796  // exporte chaque schema a exporter
797  foreach(ExportDiagramLine *diagram_line, diagrams_to_export) {
798  exportDiagram(diagram_line);
799  }
800 
801  // fermeture du dialogue
802  accept();
803 }
804 
811  ExportProperties export_properties(epw -> exportProperties());
812 
813  // recupere le format a utiliser (acronyme et extension)
814  QString format_acronym = export_properties.format;
815  QString format_extension = "." + format_acronym.toLower();
816 
817  // determine le nom de fichier a utiliser
818  QString diagram_path = diagram_line -> file_name -> text();
819 
820  // determine le chemin du fichier
821  QDir target_dir_path(export_properties.destination_directory);
822  diagram_path = target_dir_path.absoluteFilePath(diagram_path);
823 
824  // recupere des informations sur le fichier specifie
825  QFileInfo file_infos(diagram_path);
826 
827  // verifie qu'il est possible d'ecrire dans le fichier en question
828  if (file_infos.exists() && !file_infos.isWritable()) {
830  this,
831  tr("Impossible d'écrire dans ce fichier", "message box title"),
832  QString(
833  tr(
834  "Il semblerait que vous n'ayez pas les permissions "
835  "nécessaires pour écrire dans le fichier %1.",
836  "message box content"
837  )
838  ).arg(diagram_path),
839  QMessageBox::Ok
840  );
841  return;
842  }
843 
844  // ouvre le fichier
845  QFile target_file(diagram_path);
846 
847  // enregistre l'image dans le fichier
848  if (format_acronym == "SVG") {
849  generateSvg(
850  diagram_line -> diagram,
851  diagram_line -> width -> value(),
852  diagram_line -> height -> value(),
853  diagram_line -> keep_ratio -> isChecked(),
854  target_file
855  );
856  } else if (format_acronym == "DXF") {
857  generateDxf(
858  diagram_line -> diagram,
859  diagram_line -> width -> value(),
860  diagram_line -> height -> value(),
861  diagram_line -> keep_ratio -> isChecked(),
862  diagram_path
863  );
864  } else {
865  QImage image = generateImage(
866  diagram_line -> diagram,
867  diagram_line -> width -> value(),
868  diagram_line -> height -> value(),
869  diagram_line -> keep_ratio -> isChecked()
870  );
871  image.save(&target_file, format_acronym.toUtf8().data());
872  }
873  target_file.close();
874 }
875 
881  // parcourt les schemas a exporter
882  foreach(int diagram_id, diagram_lines_.keys()) {
883  ExportDiagramLine *diagram_line = diagram_lines_[diagram_id];
884 
885  // corrige les dimensions des schemas dont il faut preserver le ratio
886  if (diagram_line -> keep_ratio -> isChecked()) {
887  slot_correctHeight(diagram_id);
888  }
889  }
890 }
891 
899  QPushButton *export_button = buttons -> button(QDialogButtonBox::Save);
900  export_button -> setEnabled(diagramsToExportCount());
901 }
902 
908 void ExportDialog::slot_changeFilesExtension(bool force_extension) {
909  // recupere le format a utiliser (acronyme et extension)
910  QString format_acronym = epw -> exportProperties().format;
911  QString format_extension = "." + format_acronym.toLower();
912 
913  // parcourt les schemas a exporter
914  foreach(ExportDiagramLine *diagram_line, diagram_lines_.values()) {
915  QString diagram_filename = diagram_line -> file_name -> text();
916 
917  // cas 1 : l'extension est presente et correcte : on ne fait rien
918  if (diagram_filename.endsWith(format_extension, Qt::CaseInsensitive)) {
919  continue;
920  }
921 
922  QFileInfo diagram_filename_info(diagram_filename);
923  // cas 2 : l'extension est absente
924  if (diagram_filename_info.suffix().isEmpty()) {
925  if (force_extension) {
926  diagram_filename = diagram_filename_info.completeBaseName() + format_extension;
927  }
928  } else {
929  // cas 3 : l'extension est presente mais erronee
930  diagram_filename = diagram_filename_info.completeBaseName() + format_extension;
931  }
932 
933  diagram_line -> file_name -> setText(diagram_filename);
934  }
935 }
936 
942 void ExportDialog::slot_previewDiagram(int diagram_id) {
943  // recupere l'ExportDiagramLine concernee
944  ExportDialog::ExportDiagramLine *current_diagram = diagram_lines_[diagram_id];
945  if (!current_diagram) return;
946 
947  // initialise un dialogue
948  QDialog preview_dialog;
949  preview_dialog.setWindowTitle(tr("Aperçu"));
950  preview_dialog.setWindowState(preview_dialog.windowState() | Qt::WindowMaximized);
951 
952  QGraphicsScene *preview_scene = new QGraphicsScene();
953  preview_scene -> setBackgroundBrush(Qt::lightGray);
954  QGraphicsView *preview_view = new QGraphicsView(preview_scene);
955  preview_view -> setDragMode(QGraphicsView::ScrollHandDrag);
956  QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
957  connect(buttons, SIGNAL(accepted()), &preview_dialog, SLOT(accept()));
958 
959  QVBoxLayout *vboxlayout1 = new QVBoxLayout();
960  vboxlayout1 -> addWidget(preview_view);
961  vboxlayout1 -> addWidget(buttons);
962  preview_dialog.setLayout(vboxlayout1);
963 
964  // genere le nouvel apercu
965  QImage preview_image = generateImage(
966  current_diagram -> diagram,
967  current_diagram -> width -> value(),
968  current_diagram -> height -> value(),
969  current_diagram -> keep_ratio -> isChecked()
970  );
971 
972  // nettoie l'apercu
973  foreach (QGraphicsItem *qgi, preview_scene -> items()) {
974  preview_scene -> removeItem(qgi);
975  delete qgi;
976  }
977 
978  // ajoute le nouvel apercu
979  QGraphicsPixmapItem *qgpi = new QGraphicsPixmapItem(QPixmap::fromImage(preview_image));
980  preview_scene -> addItem(qgpi);
981  preview_scene -> setSceneRect(QRectF(0.0, 0.0, preview_image.width(), preview_image.height()));
982 
983  // montre l'apercu
984  preview_dialog.exec();
985 }
986 
992  // recupere l'ExportDiagramLine concernee
993  ExportDialog::ExportDiagramLine *diagram_line = diagram_lines_[diagram_id];
994  if (!diagram_line) return;
995 
996  // recupere le format a utiliser (acronyme et extension)
997  QString format_acronym = epw -> exportProperties().format;
998 
999  QClipboard *clipboard = QApplication::clipboard();
1000 
1001  // enregistre l'image dans le fichier
1002  if (format_acronym == "SVG") {
1003  QByteArray ba;
1004  QBuffer buffer(&ba);
1005  buffer.open(QIODevice::WriteOnly);
1006  generateSvg(
1007  diagram_line -> diagram,
1008  diagram_line -> width -> value(),
1009  diagram_line -> height -> value(),
1010  diagram_line -> keep_ratio -> isChecked(),
1011  buffer
1012  );
1013  buffer.close();
1014  clipboard -> setText(ba);
1015  } else {
1016  QImage image = generateImage(
1017  diagram_line -> diagram,
1018  diagram_line -> width -> value(),
1019  diagram_line -> height -> value(),
1020  diagram_line -> keep_ratio -> isChecked()
1021  );
1022  clipboard -> setImage(image);
1023  }
1024 }
1025 
1032  diagram = dia;
1033  must_export = new QCheckBox();
1034  must_export -> setChecked(true);
1035 
1036  // titre et nom de fichier du schema
1037  QString diagram_title = diagram -> title();
1038  QString diagram_index = QString::number(diagram -> folioIndex()+1);
1039  //QString diagram_folio_label = diagram -> border_and_titleblock.finalfolio();
1040  if (diagram_title.isEmpty()) diagram_title = QObject::tr("Folio sans titre");
1041  QString diagram_filename = diagram -> title();
1042  if (diagram_filename.isEmpty()) diagram_filename = QObject::tr("schema");
1043  diagram_filename = QET::stringToFileName(diagram_index + "_" + diagram_filename);
1044 
1045  title_label = new QLabel(diagram_title);
1046 
1047  file_name = new QLineEdit();
1048  file_name -> setText(diagram_filename);
1049  file_name -> setMinimumWidth(280);
1050 
1051  width = new QSpinBox();
1052  width -> setRange(1, 10000);
1053  width -> setSuffix(tr("px"));
1054  width -> setValue(diagram_size.width());
1055 
1056  height = new QSpinBox();
1057  height -> setRange(1, 10000);
1058  height -> setSuffix(tr("px"));
1059  height -> setValue(diagram_size.height());
1060 
1061  x_label = new QLabel("*");
1062 
1063  keep_ratio = new QPushButton();
1064  keep_ratio -> setCheckable(true);
1065  keep_ratio -> setChecked(true);
1067  keep_ratio -> setToolTip(QObject::tr("Conserver les proportions"));
1068 
1069  reset_size = new QPushButton();
1070  reset_size -> setIcon(QET::Icons::Start);
1071  reset_size -> setToolTip(QObject::tr("Réinitialiser les dimensions"));
1072 
1073  preview = new QPushButton();
1074  preview -> setIcon(QET::Icons::ZoomOriginal);
1075  preview -> setToolTip(QObject::tr("Aperçu"));
1076 
1077  clipboard = new QPushButton();
1078  clipboard -> setIcon(QET::Icons::IC_CopyFile);
1079  clipboard -> setToolTip(QObject::tr("Exporter vers le presse-papier"));
1080 }
1081 
1086 }
1087 
1093  QHBoxLayout *layout = new QHBoxLayout();
1094  layout -> addWidget(width);
1095  layout -> addWidget(x_label);
1096  layout -> addWidget(height);
1097  layout -> addWidget(keep_ratio);
1098  layout -> addWidget(reset_size);
1099  layout -> addWidget(preview);
1100  layout -> addWidget(clipboard);
1101  return(layout);
1102 }
void slot_keepRatioChanged(int)
QString format
Image format of generated files.
QPushButton * deSelectAll
Definition: exportdialog.h:74
ElementsLocation location() const
Definition: element.cpp:1569
QHash< int, ExportDialog::ExportDiagramLine * > diagram_lines_
Definition: exportdialog.h:67
The DynamicElementTextItem class This class provide a simple text field of element who can be added o...
void saveReloadDiagramParameters(Diagram *, bool=true)
static void dxfEnd(const QString &)
Definition: createdxf.cpp:232
~ExportDialog() override
void generateDxf(Diagram *, int, int, bool, QString &)
static const qreal margin
margin around the diagram
Definition: diagram.h:88
static ElementPictureFactory * instance()
instance
static void drawRectangle(const QString &filepath, double, double, double, double, const int &colorcode)
Definition: createdxf.cpp:565
QSignalMapper * preview_mapper_
Definition: exportdialog.h:77
void slot_deSelectAllClicked()
static void drawText(const QString &, const QString &, double, double, double, double, int)
Definition: createdxf.cpp:708
static const double sheetHeight
Definition: createdxf.h:56
QWidget * initDiagramsListPart()
QSignalMapper * reset_mapper_
Definition: exportdialog.h:81
static void drawArcEllipse(const QString &file_path, qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal spanAngle, qreal hotspot_x, qreal hotspot_y, qreal rotation_angle, const int &colorcode)
Definition: createdxf.cpp:426
QIcon Start
Definition: qeticons.cpp:162
void fillRow(const QString &, const QRectF &, QString, const QString &, QString, QString)
static double yScale
Definition: createdxf.h:58
void slot_exportToClipBoard(int)
QIcon ObjectLocked
Definition: qeticons.cpp:123
void generateSvg(Diagram *, int, int, bool, QIODevice &)
void slot_checkDiagramsCount()
QPushButton * selectAll
Definition: exportdialog.h:73
void slot_changeUseBorder()
QETProject * project_
Definition: exportdialog.h:85
static double xScale
Definition: createdxf.h:57
void slot_selectAllClicked()
QDir destination_directory
Target directory for generated files.
static ExportProperties defaultExportProperties()
ExportProperties::defaultProperties.
ElementPictureFactory::primitives getPrimitives(const ElementsLocation &location)
ElementPictureFactory::getPrimitives.
QIcon tr
Definition: qeticons.cpp:204
void slot_resetSize(int)
void exportDiagram(ExportDiagramLine *)
QSize diagramSize(Diagram *)
QString stringToFileName(const QString &)
Definition: qet.cpp:379
static const double sheetWidth
Definition: createdxf.h:55
void slot_correctWidth(int)
ExportPropertiesWidget * epw
Definition: exportdialog.h:70
The QetShapeItem class this class is used to draw a basic shape (line, rectangle, ellipse) into a dia...
Definition: qetshapeitem.h:35
QIcon ZoomOriginal
Definition: qeticons.cpp:180
static QPointF rotation_transformed(qreal, qreal, qreal, qreal, qreal)
QDialogButtonBox * buttons
Definition: exportdialog.h:71
QSignalMapper * height_mapper_
Definition: exportdialog.h:79
static void drawCircle(const QString &, double, double, double, int)
Definition: createdxf.cpp:256
QIcon IC_CopyFile
Definition: qeticons.cpp:40
void slot_export()
ExportDialog(QETProject *, QWidget *=nullptr)
void slot_correctHeight(int)
QIcon ObjectUnlocked
Definition: qeticons.cpp:125
void slot_changeFilesExtension(bool=false)
QIcon Cancel
Definition: qeticons.cpp:34
qreal diagramRatio(Diagram *)
int diagramsToExportCount() const
static void drawTextAligned(const QString &fileName, const QString &text, double x, double y, double height, double rotation, double oblique, int hAlign, int vAlign, double xAlign, int colour, bool leftAlign=false, float scale=0)
Definition: createdxf.cpp:747
QImage generateImage(Diagram *, int, int, bool)
QGridLayout * diagrams_list_layout_
Definition: exportdialog.h:69
QSignalMapper * clipboard_mapper_
Definition: exportdialog.h:82
QMessageBox::StandardButton critical(QWidget *, const QString &, const QString &, QMessageBox::StandardButtons=QMessageBox::Ok, QMessageBox::StandardButton=QMessageBox::NoButton)
Export the diagram along with its border and title block.
Definition: qet.h:138
static void drawLine(const QString &filapath, double, double, double, double, const int &clorcode)
Definition: createdxf.cpp:290
QSignalMapper * ratio_mapper_
Definition: exportdialog.h:80
void slot_previewDiagram(int)
Horizontal segment.
Definition: qet.h:87
virtual bool toDXF(const QString &filepath, const QPen &pen)
QetShapeItem::toDXF Draw this element to the dxf document.
QSignalMapper * width_mapper_
Definition: exportdialog.h:78
QMessageBox::StandardButton warning(QWidget *, const QString &, const QString &, QMessageBox::StandardButtons=QMessageBox::Ok, QMessageBox::StandardButton=QMessageBox::NoButton)
static void dxfBegin(const QString &)
Definition: createdxf.cpp:42
static qreal colWidths[7]