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 "xmlelementcollection.h"
19 #include "nameslist.h"
20 #include "qetxml.h"
21 #include "elementslocation.h"
22 #include "qetproject.h"
23 
24 /**
25  * @brief XmlElementCollection::XmlElementCollection
26  * Build an empty collection.
27  * The collection start by :
28  *		<collection>
29  *			<category name="import>
30  *			</category>
31  *		</collection>
32  * All elements and category are stored as child of <category name="import>
33  * @param project : the project of this collection
34  */
XmlElementCollection(QETProject * project)35 XmlElementCollection::XmlElementCollection(QETProject *project) :
36 	QObject(project),
37 	m_project(project)
38 {
39 	QDomElement collection = m_dom_document.createElement("collection");
40 	m_dom_document.appendChild(collection);
41 	QDomElement import = m_dom_document.createElement("category");
42 	import.setAttribute("name", "import");
43 	collection.appendChild(import);
44 
45 	NamesList names;
46 
47 	const QChar russian_data[24] = { 0x0418, 0x043C, 0x043F, 0x043E, 0x0440, 0x0442, 0x0438, 0x0440, 0x043E, 0x0432, 0x0430, 0x043D, 0x043D, 0x044B, 0x0435, 0x0020, 0x044D, 0x043B, 0x0435, 0x043C, 0x0435, 0x043D, 0x0442, 0x044B };
48 	const QChar greek_data[18] = { 0x0395, 0x03b9, 0x03c3, 0x03b7, 0x03b3, 0x03bc, 0x03ad, 0x03bd, 0x03b1, 0x0020, 0x03c3, 0x03c4, 0x03bf, 0x03b9, 0x03c7, 0x03b5, 0x03af, 0x03b1 };
49 	const QChar turkish_data[12] ={ 0x0130, 0x0074, 0x0068, 0x0061, 0x006C, 0x0020, 0x00F6, 0x011F, 0x0065, 0x006C, 0x0065, 0x0072 };
50 	names.addName("fr", "Éléments importés");
51 	names.addName("en", "Imported elements");
52 	names.addName("de", "Importierte elemente");
53 	names.addName("es", "Elementos importados");
54 	names.addName("ru", QString(russian_data, 24));
55 	names.addName("cs", "Zavedené prvky");
56 	names.addName("pl", "Elementy importowane");
57 	names.addName("pt", "elementos importados");
58 	names.addName("it", "Elementi importati");
59 	names.addName("el", QString(greek_data, 18));
60 	names.addName("nl", "Elementen geïmporteerd");
61 	names.addName("hr", "Uvezeni elementi");
62 	names.addName("ca", "Elements importats");
63 	names.addName("ro", "Elemente importate");
64 	names.addName("tr", QString(turkish_data, 12));
65 	names.addName("da", "Importerede elementer");
66 	names.addName("hr", "Uvezeni elementi");
67 	names.addName("sl", "Uvoženi elementi");
68 
69 
70 	import.appendChild(names.toXml(m_dom_document));
71 }
72 
73 /**
74  * @brief XmlElementCollection::XmlElementCollection
75  * Constructor with an collection. The tagName of @dom_element must be "collection"
76  * @param dom_element -the collection in a dom_element (the dom element in cloned)
77  * @param project : the project of this collection
78  */
XmlElementCollection(const QDomElement & dom_element,QETProject * project)79 XmlElementCollection::XmlElementCollection(const QDomElement &dom_element, QETProject *project) :
80 	QObject(project),
81 	m_project(project)
82 {
83 	if (dom_element.tagName() == "collection")
84 		m_dom_document.appendChild(m_dom_document.importNode(dom_element, true));
85 	else
86 		qDebug() << "XmlElementCollection : tagName of dom_element is not collection";
87 }
88 
89 /**
90  * @brief XmlElementCollection::root
91  * The root is the first DOM-Element the xml collection, the tag name
92  * of the dom element is : collection
93  * @return The root QDomElement of the collection
94  */
root() const95 QDomElement XmlElementCollection::root() const {
96 	return m_dom_document.documentElement();
97 }
98 
99 /**
100  * @brief XmlElementCollection::importCategory
101  * @return The QDomElement import (the begining of a xml collection) or
102  * a null QDomElement if doesn't exist.
103  */
importCategory() const104 QDomElement XmlElementCollection::importCategory() const {
105 	return root().firstChildElement("category");
106 }
107 
108 /**
109  * @brief XmlElementCollection::childs
110  * @param parent_element
111  * @return All childs element in the @parent_element tree
112  */
childs(const QDomElement & parent_element) const113 QDomNodeList XmlElementCollection::childs(const QDomElement &parent_element) const
114 {
115 	if (parent_element.ownerDocument() != m_dom_document) return QDomNodeList();
116 	return parent_element.childNodes();
117 }
118 
119 /**
120  * @brief XmlElementCollection::child
121  * If parent_element have child element with an attribute name = @child_name, return it, else return a null QDomElement.
122  * Only search for element with tag-name "category" and "element" (if child_name end with ".elmt")
123  * @param parent_element : the parent DomElement where we search for child.
124  * @parent_element must be a child node of this XmlElementCollection.
125  * @param child_name : name of child to search.
126  * @return The child QDomElement or a null QDomElement if not found
127  */
child(const QDomElement & parent_element,const QString & child_name) const128 QDomElement XmlElementCollection::child(const QDomElement &parent_element, const QString &child_name) const
129 {
130 	if (parent_element.ownerDocument() != m_dom_document) return QDomElement();
131 
132 		//Get all childs element of parent_element
133 	QDomNodeList child_list = parent_element.childNodes();
134 	QString tag_name(child_name.endsWith(".elmt")? "element" : "category");
135 	QList <QDomElement> found_dom_element;
136 	for (int i=0 ; i<child_list.length() ; i++)
137 	{
138 		QDomElement child_element = child_list.item(i).toElement();
139 		if (child_element.tagName() == tag_name) found_dom_element << child_element;
140 	}
141 
142 	if (found_dom_element.isEmpty()) return QDomElement();
143 
144 	foreach (QDomElement elmt, found_dom_element)
145 		if (elmt.attribute("name") == child_name)
146 			return elmt;
147 
148 	return QDomElement();
149 }
150 
151 /**
152  * @brief XmlElementCollection::child
153  * @param path
154  * @return the DomElement at path if exist, else return a null QDomElement
155  */
child(const QString & path) const156 QDomElement XmlElementCollection::child(const QString &path) const
157 {
158 	QStringList path_list = path.split("/");
159 	if (path_list.isEmpty()) return QDomElement();
160 
161 	QDomElement parent_element = root();
162 	foreach (QString str, path_list)
163 	{
164 		QDomElement child_element = child(parent_element, str);
165 
166 		if (child_element.isNull())
167 			return QDomElement();
168 		else
169 			parent_element = child_element;
170 	}
171 
172 	return parent_element;
173 }
174 
175 /**
176  * @brief XmlElementCollection::directories
177  * @param parent_element
178  * @return A list of directory stored in @parent_element
179  */
directories(const QDomElement & parent_element) const180 QList<QDomElement> XmlElementCollection::directories(const QDomElement &parent_element) const
181 {
182 	QList <QDomElement> directory_list;
183 	QDomNodeList node_list = childs(parent_element);
184 	if (node_list.isEmpty()) return directory_list;
185 
186 	for (int i=0 ; i < node_list.count() ; i++)
187 	{
188 		QDomNode node = node_list.at(i);
189 		if (node.isElement() &&  node.toElement().tagName() == "category")
190 			directory_list << node.toElement();
191 	}
192 
193 	return directory_list;
194 }
195 
196 /**
197  * @brief XmlElementCollection::directoriesNames
198  * @param parent_element
199  * @return a list of names for every child directories of @parent_element
200  */
directoriesNames(const QDomElement & parent_element) const201 QStringList XmlElementCollection::directoriesNames(const QDomElement &parent_element) const
202 {
203 	QList <QDomElement> childs = directories(parent_element);
204 	QStringList names;
205 
206 	foreach (QDomElement child, childs)
207 	{
208 		QString name = child.attribute("name");
209 		if (!name.isEmpty())
210 			names.append(name);
211 	}
212 
213 	return names;
214 }
215 
216 /**
217  * @brief XmlElementCollection::elements
218  * @param parent_element
219  * @return A list of element stored in @parent_element
220  */
elements(const QDomElement & parent_element) const221 QList<QDomElement> XmlElementCollection::elements(const QDomElement &parent_element) const
222 {
223 	QList <QDomElement> element_list;
224 	QDomNodeList node_list = childs(parent_element);
225 	if (node_list.isEmpty()) return element_list;
226 
227 	for (int i=0 ; i < node_list.count() ; i++)
228 	{
229 		QDomNode node = node_list.at(i);
230 		if (node.isElement() &&  node.toElement().tagName() == "element")
231 			element_list << node.toElement();
232 	}
233 
234 	return element_list;
235 }
236 
237 /**
238  * @brief XmlElementCollection::elementsNames
239  * @param parent_element
240  * @return A list of names fr every childs element of @parent_element
241  */
elementsNames(const QDomElement & parent_element) const242 QStringList XmlElementCollection::elementsNames(const QDomElement &parent_element) const
243 {
244 	QList <QDomElement> childs = elements(parent_element);
245 	QStringList names;
246 
247 	foreach (QDomElement child, childs)
248 	{
249 		QString name = child.attribute("name");
250 		if (!name.isEmpty())
251 			names.append(name);
252 	}
253 
254 	return names;
255 }
256 
257 /**
258  * @brief XmlElementCollection::element
259  * @param path : path of the element in this collection
260  * @return the QDomElement that represent the element at path @path
261  * or a null QDomElement if not found or doesn't represent an element
262  */
element(const QString & path) const263 QDomElement XmlElementCollection::element(const QString &path) const
264 {
265 	if (!path.endsWith(".elmt")) return QDomElement();
266 
267 	QDomElement element = child(path);
268 
269 	if (element.tagName() == "element")
270 		return element;
271 	else
272 		return QDomElement();
273 }
274 
275 /**
276  * @brief XmlElementCollection::directory
277  * @param path : path of the directory in this collection
278  * @return the QDomElement that represent the directory at path @path
279  * or a null QDomElement if not found.
280  */
directory(const QString & path) const281 QDomElement XmlElementCollection::directory(const QString &path) const
282 {
283 	QDomElement directory = child(path);
284 
285 	if (directory.tagName() == "category")
286 		return directory;
287 	else
288 		return QDomElement();
289 }
290 
291 /**
292  * @brief XmlElementCollection::addElement
293  * Add the element at location to this collection.
294  * The element is copied in this collection in "import" dir with the same path, in other word
295  * if the path is dir1/dir2/dir3/myElement.elmt, myElement is copied to this collection at the path : import/dir1/dir2/dir3/myElement.elmt
296  * If the path doesn't exist, he was created.
297  * If the element already exist, do nothing.
298  * @param location, location of the element
299  * @return the collection path of the added item or a null QString if element can't be added.
300  */
addElement(ElementsLocation & location)301 QString XmlElementCollection::addElement(ElementsLocation &location)
302 {
303 		//location must be an element and exist
304 	if (!(location.exist() && location.isElement()))
305 		return QString();
306 
307 		//Add an element from this collection to this collection have no sense
308 	if (location.isProject() && location.projectCollection() == this)
309 		return QString();
310 
311 		//First we check if this location exist in this collection if so, we do nothing
312 	if ( exist("import/" + location.collectionPath(false)) )
313 		return QString();
314 
315 		//Get the import dir of this collection
316 	QDomElement parent_element = importCategory();
317 	if (parent_element.isNull())
318 		return QString();
319 
320 	QString integrated_path = parent_element.attribute("name");
321 
322 		//Split the path
323 	QStringList splitted_path = location.collectionPath(false).split("/");
324 	if (splitted_path.isEmpty())
325 		return QString();
326 
327 	if (location.isFileSystem()) {
328 			//Get the root dir of the filesystem collection
329 		QDir dir(location.fileSystemPath().remove(location.collectionPath(false)));
330 		if (!dir.exists())
331 			return QString();
332 
333 		foreach(QString str, splitted_path) {
334 			QDomElement child_element = child(parent_element, str);
335 
336 				//Child doesn't exist, we create it
337 			if (child_element.isNull()) {
338 				QDomElement created_child;
339 
340 					//str is the path of an element, we integrate an element
341 				if (str.endsWith(".elmt")) {
342 					QFile element_file(dir.filePath(str));
343 					if (!element_file.exists())
344 						return QString();
345 
346 					created_child = QETXML::fileSystemElementToXmlCollectionElement(m_dom_document, element_file);
347 				}
348 
349 					//str is the path of a directory, we integrate a directory.
350 				else {
351 						//Dir doesn't exist.
352 					if (!dir.cd(str))
353 						return QString();
354 
355 					created_child = QETXML::fileSystemDirToXmlCollectionDir(m_dom_document, dir);
356 				}
357 
358 				if(created_child.isNull())
359 					return QString();
360 
361 				parent_element.appendChild(created_child);
362 				parent_element = created_child;
363 			}
364 				//Child exist
365 			else {
366 				if (!dir.cd(str))
367 					return QString();
368 
369 				parent_element = child_element;
370 			}
371 
372 			integrated_path.append("/"+str);
373 		}
374 	}
375 	else if (location.isProject()) {
376 		QString path;
377 		foreach(QString str, splitted_path) {
378 			if (path.isEmpty())
379 				path = str;
380 			else
381 				path = path + "/" + str;
382 
383 			QDomElement child_element = child(parent_element, str);
384 
385 				//Child doesn't exist, we create it
386 			if (child_element.isNull()) {
387 				QDomElement created_child;
388 
389 					//str is the path of an element, we integrate an element
390 				if (str.endsWith(".elmt")) {
391 					created_child = m_dom_document.createElement("element");
392 					created_child.setAttribute("name", str);
393 
394 					created_child.appendChild(location.xml().cloneNode(true));
395 				}
396 
397 					//str is the path of a directory, we integrate a directory.
398 				else {
399 					created_child = m_dom_document.createElement("category");
400 					created_child.setAttribute("name", str);
401 
402 					ElementsLocation sub_dir_location(path, location.project());
403 					QDomElement names_element = sub_dir_location.nameList().toXml(m_dom_document);
404 					created_child.appendChild(names_element);
405 				}
406 
407 				if(created_child.isNull())
408 					return QString();
409 
410 				parent_element.appendChild(created_child);
411 				parent_element = created_child;
412 			}
413 				//Child exist
414 			else
415 				parent_element = child_element;
416 
417 			integrated_path.append("/"+str);
418 		}
419 	}
420 
421 	emit elementAdded(integrated_path);
422 	return integrated_path;
423 }
424 
425 /**
426  * @brief XmlElementCollection::addElementDefinition
427  * Add the élément defintion @xml_definition in the directory at path @dir_path with the name @elmt_name.
428  * @param dir_path : the path of the directory where we must add the element.
429  * The path must be an existing directory of this collection.
430  * @param elmt_name : The name used to store the element (the name must end with .elmt, if not, .elmt will be append to @elmt_name)
431  * @param xml_definition : The xml definition of the element.
432  * The tag name of @xml_definition must be "definition".
433  * @return True if the element is added with success.
434  */
addElementDefinition(const QString & dir_path,const QString & elmt_name,const QDomElement & xml_definition)435 bool XmlElementCollection::addElementDefinition(const QString &dir_path, const QString &elmt_name, const QDomElement &xml_definition)
436 {
437 	QDomElement dom_dir = directory(dir_path);
438 	if (dom_dir.isNull()) {
439 		qDebug() << "XmlElementCollection::addElementDefinition : No directory at path : " << dir_path;
440 		return false;
441 	}
442 
443 	if (xml_definition.tagName() != "definition") {
444 		qDebug() << "XmlElementCollection::addElementDefinition : xml_defintion tag name is not \"definition\"";
445 		return false;
446 	}
447 
448 	QString name = elmt_name;
449 	if (!name.endsWith(".elmt")) {
450 		name += ".elmt";
451 	}
452 
453 	QDomElement dom_elmt = m_dom_document.createElement("element");
454 	dom_elmt.setAttribute("name", name);
455 	dom_elmt.appendChild(xml_definition.cloneNode(true));
456 	dom_dir.appendChild(dom_elmt);
457 
458 	emit elementAdded(dir_path + "/" + name);
459 
460 	return true;
461 }
462 
463 /**
464  * @brief XmlElementCollection::removeElement
465  * Remove the element at path @path.
466  * @param path
467  * @return True if element is removed and emit the signal elementRemoved.
468  * else false.
469  */
removeElement(const QString & path)470 bool XmlElementCollection::removeElement(const QString& path)
471 {
472 	QDomElement elmt = element(path);
473 
474 	if (!elmt.isNull()) {
475 		elmt.parentNode().removeChild(elmt);
476 		emit elementRemoved(path);
477 		return true;
478 	}
479 
480 	return false;
481 }
482 
483 /**
484  * @brief XmlElementCollection::copy
485  * Copy the content represented by source (an element or a directory) to destination.
486  * Destination must be a directory of this collection.
487  * If the destination already have an item at the same path of source, he will be replaced by source.
488  * @param source : content to copy
489  * @param destination : destination of the copy, must be a directory of this collection
490  * @param rename : rename the copy with @rename else use the name of source
491  * @param deep_copy : if true copy all childs of source (only if source is directory)
492  * @return the ElementLocation that represent the copy, if copy failed return a null ElementLocation
493  */
copy(ElementsLocation & source,ElementsLocation & destination,const QString & rename,bool deep_copy)494 ElementsLocation XmlElementCollection::copy(ElementsLocation &source, ElementsLocation &destination, const QString& rename, bool deep_copy)
495 {
496 	if (!(source.exist() && destination.isDirectory() && destination.isProject() && destination.projectCollection() == this))
497 		return ElementsLocation();
498 
499 	if (source.isElement())
500 		return copyElement(source, destination, rename);
501 	else
502 		return copyDirectory(source, destination, rename, deep_copy);
503 }
504 
505 /**
506  * @brief XmlElementCollection::exist
507  * Return true if the path @path exist in this collection
508  * @param path
509  * @return
510  */
exist(const QString & path) const511 bool XmlElementCollection::exist(const QString &path) const
512 {
513 	if (child(path).isNull())
514 		return false;
515 	else
516 		return true;
517 }
518 
519 /**
520  * @brief XmlElementCollection::createDir
521  * Create a child directorie at path @path with the name @name.
522  * Emit directorieAdded if success.
523  * @param path : path of parent diectorie
524  * @param name : name of the directori to create.
525  * @param name_list : translation of the directorie name.
526  * @return true if creation success, if directorie already exist return true.
527  */
createDir(const QString & path,const QString & name,const NamesList & name_list)528 bool XmlElementCollection::createDir(const QString& path, const QString& name, const NamesList &name_list)
529 {
530 	QString new_dir_path = path + "/" + name;
531 
532 	if (!directory(new_dir_path).isNull()) {
533 		return true;
534 	}
535 
536 	QDomElement parent_dir = directory(path);
537 	if (parent_dir.isNull()) {
538 		qDebug() << "XmlElementCollection::createDir : directorie at path doesn't exist";
539 		return false;
540 	}
541 
542 	QDomElement new_dir = m_dom_document.createElement("category");
543 	new_dir.setAttribute("name", name);
544 	new_dir.appendChild(name_list.toXml(m_dom_document));
545 
546 	parent_dir.appendChild(new_dir);
547 
548 	emit directorieAdded(new_dir_path);
549 
550 	return true;
551 }
552 
553 /**
554  * @brief XmlElementCollection::removeDir
555  * Remove the directory at path @path.
556  * @param path
557  * @return true if successfuly removed and emit directoryRemoved(QString),
558  * else false.
559  */
removeDir(const QString & path)560 bool XmlElementCollection::removeDir(const QString& path)
561 {
562 	QDomElement dir = directory(path);
563 	if (!dir.isNull()) {
564 		dir.parentNode().removeChild(dir);
565 		emit directoryRemoved(path);
566 		return true;
567 	}
568 	return false;
569 }
570 
571 /**
572  * @brief XmlElementCollection::elementsLocation
573  * Return all locations stored in dom_element (element and directory).
574  * If dom_element is null, return all location owned by this collection
575  * dom_element must be a child of this collection.
576  * @param dom_element : dom_element where we must to search location.
577  * @param childs = if true return all childs location of dom_element, if false, only return the direct childs location of dom_element.
578  * @return
579  */
elementsLocation(QDomElement dom_element,bool childs) const580 QList<ElementsLocation> XmlElementCollection::elementsLocation(QDomElement dom_element, bool childs) const
581 {
582 	QList <ElementsLocation> location_list;
583 
584 	if (dom_element.isNull())
585 		dom_element = m_dom_document.documentElement();
586 
587 	if (dom_element.ownerDocument() != m_dom_document)
588 		return location_list;
589 
590 		//get element childs
591 	QList <QDomElement> element_list = elements(dom_element);
592 
593 	foreach (QDomElement elmt, element_list) {
594 		ElementsLocation location = domToLocation(elmt);
595 		if (location.exist())
596 			location_list << location;
597 	}
598 
599 		//get directory childs
600 	QList <QDomElement> directory_list = directories(dom_element);
601 
602 	foreach (QDomElement dir, directory_list) {
603 		ElementsLocation location = domToLocation(dir);
604 		if (location.exist())
605 			location_list << location;
606 
607 		if (childs)
608 			location_list.append(elementsLocation(dir, childs));
609 	}
610 
611 	return location_list;
612 }
613 
614 /**
615  * @brief XmlElementCollection::domToLocation
616  * Return the element location who represent the xml element : dom_element
617  * dom_element must be owned by this collection
618  * @param dom_element : the dom_element of this collection that represent an element.
619  * The tag name of dom_element must be "element"
620  * @return the element location, location can be null if fail.
621  */
domToLocation(QDomElement dom_element) const622 ElementsLocation XmlElementCollection::domToLocation(QDomElement dom_element) const
623 {
624 	if (dom_element.ownerDocument() == m_dom_document) {
625 		QString path = dom_element.attribute("name");
626 
627 		while (!dom_element.parentNode().isNull() && dom_element.parentNode().isElement()) {
628 			dom_element = dom_element.parentNode().toElement();
629 
630 			if (dom_element.tagName() == "category")
631 				path.prepend(dom_element.attribute("name") + "/");
632 		}
633 
634 		return ElementsLocation(path, m_project);
635 	}
636 	else
637 		return ElementsLocation();
638 }
639 
640 /**
641  * @brief XmlElementCollection::cleanUnusedElement
642  * Remove elements in this collection which is not used in the owner project
643  */
cleanUnusedElement()644 void XmlElementCollection::cleanUnusedElement()
645 {
646 	foreach (ElementsLocation loc, m_project->unusedElements())
647 		removeElement(loc.collectionPath(false));
648 }
649 
650 /**
651  * @brief XmlElementCollection::cleanUnusedDirectory
652  * Remove the empty directories of this collection
653  */
cleanUnusedDirectory()654 void XmlElementCollection::cleanUnusedDirectory()
655 {
656 	QDomNodeList lst = importCategory().elementsByTagName("category");
657 
658 	for(int i=0 ; i<lst.size() ; i++) {
659 		QDomElement dir = lst.item(i).toElement();
660 			//elmt haven't got child node "element" or "category", so he is emty, we can remove it
661 		if (dir.elementsByTagName("element").isEmpty() && dir.elementsByTagName("category").isEmpty()) {
662 			if (removeDir(domToLocation(dir).collectionPath(false)))
663 				i=-1;
664 		}
665 	}
666 }
667 
668 /**
669  * @brief XmlElementCollection::copyDirectory
670  * Copy the directory represented by source to destination.
671  * if destination have a directory with the same name as source, then this directory is removed
672  * @param source : directory to copy
673  * @param destination : destination of the copy
674  * @param rename : rename the copy with @rename else use the name of source
675  * @param deep_copy :if true copy all childs of source
676  * @return the ElementLocation that represent the copy, if copy failed return a null ElementLocation
677  */
copyDirectory(ElementsLocation & source,ElementsLocation & destination,const QString & rename,bool deep_copy)678 ElementsLocation XmlElementCollection::copyDirectory(ElementsLocation &source, ElementsLocation &destination, const QString& rename, bool deep_copy)
679 {
680 	QString new_dir_name = rename.isEmpty() ? source.fileName() : rename;
681 
682 			//Get the xml directory where the new directory must be added
683 	QDomElement parent_dir_dom = directory(destination.collectionPath(false));
684 	if (parent_dir_dom.isNull()) return ElementsLocation();
685 
686 		//Remove the previous directory with the same path
687 	QDomElement element = child(destination.collectionPath(false) + "/" + new_dir_name);
688 	if (!element.isNull()) {
689 		element.parentNode().removeChild(element);
690 		emit directoryRemoved(destination.collectionPath(false) + "/" + new_dir_name);
691 	}
692 
693 	ElementsLocation created_location;
694 
695 		//Copy with a file system collection source
696 	if (source.isFileSystem())
697 	{
698 		QDir source_dir(source.fileSystemPath());
699 		if (!source_dir.exists()) return ElementsLocation();
700 
701 
702 		QDir dir(source.fileSystemPath());
703 		QDomElement elmt_dom = QETXML::fileSystemDirToXmlCollectionDir(m_dom_document, dir, new_dir_name);
704 		if (elmt_dom.isNull()) return ElementsLocation();
705 
706 		parent_dir_dom.appendChild(elmt_dom);
707 
708 		created_location.setPath(destination.projectCollectionPath() + "/" + new_dir_name);
709 
710 		if (deep_copy)
711 		{
712 				//Append all directories of source to the new created directory
713 			foreach(QString str, source_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
714 			{
715 				ElementsLocation sub_source(source.fileSystemPath() + "/" + str);
716 				copyDirectory(sub_source, created_location);
717 			}
718 
719 				//Append all elements of source to the new created directory
720 			source_dir.setNameFilters(QStringList() << "*.elmt");
721 			foreach(QString str, source_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name))
722 			{
723 				ElementsLocation sub_source(source.fileSystemPath() + "/" + str);
724 				copyElement(sub_source, created_location);
725 			}
726 		}
727 	}
728 
729 		//Copy with a xml collection source
730 	else
731 	{
732 		if (!source.projectCollection()) return ElementsLocation();
733 
734 		QDomNode other_collection_node = source.projectCollection()->child(source.collectionPath(false)).cloneNode(deep_copy);
735 
736 			//We don't make a deep copy, but we must to get the local names of the copied directory
737 		if (!deep_copy) {
738 			QDomNode names = source.projectCollection()->child(source.collectionPath(false)).namedItem("names");
739 			if (!names.isNull() && names.isElement())
740 				other_collection_node.appendChild(names.cloneNode(true));
741 		}
742 
743 		if (other_collection_node.isNull()) return ElementsLocation();
744 
745 		QDomElement other_collection_dom_dir = other_collection_node.toElement();
746 		other_collection_dom_dir.setAttribute("name", new_dir_name);
747 		parent_dir_dom.appendChild(other_collection_dom_dir);
748 
749 		created_location.setPath(destination.projectCollectionPath() + "/" + new_dir_name);
750 	}
751 
752 	emit directorieAdded(created_location.collectionPath(false));
753 	return created_location;
754 }
755 
756 /**
757  * @brief XmlElementCollection::copyElement
758  * Copy the element represented by source to destination (must be a directory)
759  * If element already exist in destination he will be replaced by the new.
760  * @param source : element to copy
761  * @param destination : destination of the copy
762  * @param rename : rename the copy with @rename else use the name of source
763  * @return The ElementsLocation of the copy
764  */
copyElement(ElementsLocation & source,ElementsLocation & destination,const QString & rename)765 ElementsLocation XmlElementCollection::copyElement(ElementsLocation &source, ElementsLocation &destination, const QString& rename)
766 {
767 	QString new_elmt_name = rename.isEmpty() ? source.fileName() : rename;
768 
769 	QDomElement elmt_dom;
770 
771 		//Copy with a file system collection source
772 	if (source.isFileSystem())
773 	{
774 		QFile file(source.fileSystemPath());
775 		elmt_dom = QETXML::fileSystemElementToXmlCollectionElement(m_dom_document, file, new_elmt_name);
776 		if (elmt_dom.isNull()) return ElementsLocation();
777 	}
778 		//Copy with a xml collection source
779 	else
780 	{
781 		QDomElement other_collection = source.xml();
782 		elmt_dom = m_dom_document.createElement("element");
783 		elmt_dom.setAttribute("name", new_elmt_name);
784 		elmt_dom.appendChild(other_collection.cloneNode());
785 	}
786 
787 
788 		//Remove the previous element with the same path
789 	QDomElement element = child(destination.collectionPath(false) + "/" + new_elmt_name);
790 	bool removed = false;
791 	if (!element.isNull()) {
792 		element.parentNode().removeChild(element);
793 		removed = true;
794 	}
795 
796 		//Get the xml directory where the new element must be added
797 	QDomElement dir_dom = directory(destination.collectionPath(false));
798 	if (dir_dom.isNull()) return ElementsLocation();
799 	dir_dom.appendChild(elmt_dom);
800 
801 	ElementsLocation copy_loc(destination.projectCollectionPath() + "/" + new_elmt_name);
802 
803 	if (removed) {
804 		emit elementChanged(copy_loc.collectionPath(false));
805 	}
806 	else {
807 		emit elementAdded(copy_loc.collectionPath(false));
808 	}
809 
810 	return copy_loc;
811 }
812