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