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 "elementtextpattern.h"
19 #include "qetapp.h"
20 #include "element.h"
21 #include "qet.h"
22 #include "dynamicelementtextitem.h"
23 #include "elementtextitemgroup.h"
24 #include "addelementtextcommand.h"
25 #include "diagram.h"
26 #include "importelementtextpatterndialog.h"
27 #include "deleteqgraphicsitemcommand.h"
28
29 #include <QDir>
30 #include <QInputDialog>
31 #include <QGraphicsScene>
32 #include <QMessageBox>
33 #include <QObject>
34 #include <QGraphicsView>
35 #include <QStringList>
36
37 /**
38 * @brief ExportElementTextPattern::ExportElementTextPattern
39 * Constructor
40 * @param elmt
41 */
ExportElementTextPattern(Element * elmt)42 ExportElementTextPattern::ExportElementTextPattern(Element *elmt) :
43 m_element(elmt)
44 {
45 //Create the conf dir if not yet.
46 QDir dir(QETApp::configDir()+ "/element_texts_pattern");
47 if(!dir.exists())
48 {
49 dir.cdUp();
50 dir.mkdir("element_texts_pattern");
51 dir.cd("element_texts_pattern");
52 }
53
54 //Get the name of conf
55 bool ok;
56 m_name = getName(ok);
57 if(ok == false)
58 return;
59
60 //Check if a conf with the same name already exist
61 if (QFileInfo::exists(dir.absoluteFilePath(m_name + ".xml")))
62 {
63 bool r = QMessageBox::question(parentWidget(),
64 QObject::tr("Configuration de textes"),
65 QObject::tr("Une configuration de textes nommée << %1 >> existe déjà.\n"
66 "Voulez-vous la remplacer ?").arg(m_name));
67
68 if(r == false)
69 return;
70 }
71
72 QDomDocument doc = xmlConf();
73 QET::writeXmlFile(doc, dir.absoluteFilePath(m_name + ".xml"));
74 }
75
76 /**
77 * @brief ExportElementTextConf::getName
78 * Open a dialog to let user set the name of the conf and return it
79 * @return
80 */
getName(bool & ok) const81 QString ExportElementTextPattern::getName(bool &ok) const
82 {
83 QString text = QInputDialog::getText(parentWidget(),
84 QObject::tr("Nom de la configuration"),
85 QObject::tr("Entrer le nom de la configuration à créer"),
86 QLineEdit::Normal,
87 QString(),
88 &ok);
89
90 text.replace(" ", "_");
91 text.replace(".","");
92 return text;
93 }
94
parentWidget() const95 QWidget *ExportElementTextPattern::parentWidget() const
96 {
97 QWidget *parent = nullptr;
98 if(m_element->scene() && !m_element->scene()->views().isEmpty())
99 parent = m_element->scene()->views().first();
100
101 return parent;
102 }
103
xmlConf() const104 QDomDocument ExportElementTextPattern::xmlConf() const
105 {
106 QDomDocument doc;
107 QDomElement root = doc.createElement("Element_texts_pattern");
108 root.setAttribute("name", m_name);
109 doc.appendChild(root);
110
111 QHash<Terminal *, int> H;
112 QDomElement elmt = m_element->toXml(doc, H);
113 QDomElement texts = elmt.firstChildElement("dynamic_texts");
114 QDomElement groups = elmt.firstChildElement("texts_groups");
115
116 if(texts.tagName() == "dynamic_texts")
117 root.appendChild(texts);
118 if(groups.tagName() == "texts_groups")
119 root.appendChild(groups);
120
121 return doc;
122 }
123
124 //*******************//
125 //******IMPORT*******//
126 //*******************//
ImportElementTextPattern(Element * elmt)127 ImportElementTextPattern::ImportElementTextPattern(Element *elmt):
128 m_element(elmt)
129 {
130 bool exist = true;
131 QDir dir(QETApp::configDir()+ "/element_texts_pattern");
132
133 if(!dir.exists())
134 exist = false;
135
136 QStringList entry = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
137 QStringList result = entry.filter(".xml");
138 if(result.isEmpty())
139 exist = false;
140
141 if(!exist)
142 {
143 QMessageBox::information(parentWidget(),
144 QObject::tr("Configuration de textes"),
145 QObject::tr("Aucune configuration de textes existante."));
146 return;
147 }
148
149 bool ok=false;
150 bool erase = false;
151 //Remove the .xml extention of the files
152 result.replaceInStrings(".xml", "");
153 QString name = getName(result, &ok, &erase);
154
155 if(!ok || name.isEmpty())
156 return;
157 else
158 apply(name, erase);
159 }
160
161 /**
162 * @brief ImportElementTextPattern::getName
163 * Open a dialog to let user select a conf
164 * @param ok
165 * @return
166 */
getName(const QStringList & list,bool * ok,bool * erase) const167 QString ImportElementTextPattern::getName(const QStringList& list, bool *ok, bool *erase) const
168 {
169 return ImportElementTextPatternDialog::getItem(parentWidget(),
170 QObject::tr("Sélectionner une configuration de textes"),
171 QObject::tr("Sélectionner la configuration de textes à ajouter à l'élément"),
172 list,
173 ok,
174 erase);
175 }
176
parentWidget() const177 QWidget *ImportElementTextPattern::parentWidget() const
178 {
179 QWidget *parent = nullptr;
180 if(m_element->scene() && !m_element->scene()->views().isEmpty())
181 parent = m_element->scene()->views().first();
182
183 return parent;
184 }
185
186
187 /**
188 * @brief ImportElementTextPattern::apply
189 * Apply the user choice
190 * @param name : the name of the selected pattern
191 * @param erase : erase the existing texts and groups of element.
192 */
apply(QString name,bool erase) const193 void ImportElementTextPattern::apply(QString name, bool erase) const
194 {
195 if(!name.endsWith(".xml"))
196 name.append(".xml");
197
198 QFile conf_file(QETApp::configDir() + "/element_texts_pattern/" + name);
199 if(!conf_file.open(QIODevice::ReadOnly | QIODevice::Text))
200 return;
201
202 //Load the content of the xml file
203 QDomDocument xml_conf;
204 if(!xml_conf.setContent(&conf_file))
205 return;
206
207 QDomElement root = xml_conf.firstChildElement("Element_texts_pattern");
208
209 //Get the text
210 QList <QDomElement> texts = QET::findInDomElement(root, "dynamic_texts", "dynamic_elmt_text");
211 if (texts.isEmpty())
212 return;
213
214 //Replace the original uuid of texts in the xml description, by a new one for every texts
215 QHash<QUuid, QUuid> uuid_hash;
216 for(QDomElement text : texts)
217 {
218 QUuid original_uuid(text.attribute("uuid"));
219 QUuid new_uuid = QUuid::createUuid();
220 text.setAttribute("uuid", new_uuid.toString());
221
222 uuid_hash.insert(original_uuid, new_uuid);
223 }
224
225 //In each group of the xml description, replace the original uuids, by the news created upper.
226 QList <QDomElement> groups = QET::findInDomElement(root, "texts_groups", "texts_group");
227 for(const QDomElement& group : groups)
228 {
229 for(QDomElement text : QET::findInDomElement(group, "texts", "text"))
230 {
231 QUuid original_uuid(text.attribute("uuid"));
232 QUuid new_uuid = uuid_hash.value(original_uuid);
233 if(!new_uuid.isNull())
234 text.setAttribute("uuid", new_uuid.toString());
235 }
236 }
237
238 QUndoStack &undo_stack = m_element->diagram()->undoStack();
239 undo_stack.beginMacro(QObject::tr("Importer la configuration de texte : %1").arg(name.remove(".xml")));
240
241 //erase existing texts and groups
242 if (erase)
243 {
244 for (ElementTextItemGroup *group : m_element->textGroups()) {
245 undo_stack.push(new RemoveTextsGroupCommand(m_element, group));
246 }
247 for (DynamicElementTextItem *deti : m_element->dynamicTextItems())
248 {
249 DiagramContent dc;
250 dc.m_element_texts << deti;
251 undo_stack.push(new DeleteQGraphicsItemCommand(m_element->diagram(), dc));
252 }
253 }
254
255 //Add the texts to element
256 for(const QDomElement& text : texts)
257 {
258 DynamicElementTextItem *deti = new DynamicElementTextItem(m_element);
259 undo_stack.push(new AddElementTextCommand(m_element, deti));
260 deti->fromXml(text);
261 }
262 //Add the groups to element
263 for(const QDomElement& xml_group : groups)
264 undo_stack.push(new AddTextsGroupCommand(m_element, xml_group));
265
266 undo_stack.endMacro();
267 }
268