File: xmlelementcollection.cpp

package info (click to toggle)
qelectrotech 1%3A0.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 91,680 kB
  • sloc: cpp: 62,335; xml: 750; sh: 264; perl: 258; makefile: 6
file content (811 lines) | stat: -rw-r--r-- 26,483 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
/*
	Copyright 2006-2019 The QElectroTech Team
	This file is part of QElectroTech.

	QElectroTech is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	QElectroTech is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with QElectroTech.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "xmlelementcollection.h"
#include "nameslist.h"
#include "qetxml.h"
#include "elementslocation.h"
#include "qetproject.h"

/**
 * @brief XmlElementCollection::XmlElementCollection
 * Build an empty collection.
 * The collection start by :
 *		<collection>
 *			<category name="import>
 *			</category>
 *		</collection>
 * All elements and category are stored as child of <category name="import>
 * @param project : the project of this collection
 */
XmlElementCollection::XmlElementCollection(QETProject *project) :
	QObject(project),
	m_project(project)
{
	QDomElement collection = m_dom_document.createElement("collection");
	m_dom_document.appendChild(collection);
	QDomElement import = m_dom_document.createElement("category");
	import.setAttribute("name", "import");
	collection.appendChild(import);

	NamesList names;

	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 };
	const QChar greek_data[18] = { 0x0395, 0x03b9, 0x03c3, 0x03b7, 0x03b3, 0x03bc, 0x03ad, 0x03bd, 0x03b1, 0x0020, 0x03c3, 0x03c4, 0x03bf, 0x03b9, 0x03c7, 0x03b5, 0x03af, 0x03b1 };
	const QChar turkish_data[12] ={ 0x0130, 0x0074, 0x0068, 0x0061, 0x006C, 0x0020, 0x00F6, 0x011F, 0x0065, 0x006C, 0x0065, 0x0072 };
	names.addName("fr", "Éléments importés");
	names.addName("en", "Imported elements");
	names.addName("de", "Importierte elemente");
	names.addName("es", "Elementos importados");
	names.addName("ru", QString(russian_data, 24));
	names.addName("cs", "Zavedené prvky");
	names.addName("pl", "Elementy importowane");
	names.addName("pt", "elementos importados");
	names.addName("it", "Elementi importati");
	names.addName("el", QString(greek_data, 18));
	names.addName("nl", "Elementen geïmporteerd");
	names.addName("hr", "Uvezeni elementi");
	names.addName("ca", "Elements importats");
	names.addName("ro", "Elemente importate");
	names.addName("tr", QString(turkish_data, 12));
	names.addName("da", "Importerede elementer");
	names.addName("hr", "Uvezeni elementi");
	names.addName("sl", "Uvoženi elementi");
	

	import.appendChild(names.toXml(m_dom_document));
}

/**
 * @brief XmlElementCollection::XmlElementCollection
 * Constructor with an collection. The tagName of @dom_element must be "collection"
 * @param dom_element -the collection in a dom_element (the dom element in cloned)
 * @param project : the project of this collection
 */
XmlElementCollection::XmlElementCollection(const QDomElement &dom_element, QETProject *project) :
	QObject(project),
	m_project(project)
{
	if (dom_element.tagName() == "collection")
		m_dom_document.appendChild(m_dom_document.importNode(dom_element, true));
	else
		qDebug() << "XmlElementCollection : tagName of dom_element is not collection";
}

/**
 * @brief XmlElementCollection::root
 * The root is the first DOM-Element the xml collection, the tag name
 * of the dom element is : collection
 * @return The root QDomElement of the collection
 */
QDomElement XmlElementCollection::root() const {
	return m_dom_document.documentElement();
}

/**
 * @brief XmlElementCollection::importCategory
 * @return The QDomElement import (the begining of a xml collection) or
 * a null QDomElement if doesn't exist.
 */
QDomElement XmlElementCollection::importCategory() const {
	return root().firstChildElement("category");
}

/**
 * @brief XmlElementCollection::childs
 * @param parent_element
 * @return All childs element in the @parent_element tree
 */
QDomNodeList XmlElementCollection::childs(const QDomElement &parent_element) const
{
	if (parent_element.ownerDocument() != m_dom_document) return QDomNodeList();
	return parent_element.childNodes();
}

/**
 * @brief XmlElementCollection::child
 * If parent_element have child element with an attribute name = @child_name, return it, else return a null QDomElement.
 * Only search for element with tag-name "category" and "element" (if child_name end with ".elmt")
 * @param parent_element : the parent DomElement where we search for child.
 * @parent_element must be a child node of this XmlElementCollection.
 * @param child_name : name of child to search.
 * @return The child QDomElement or a null QDomElement if not found
 */
QDomElement XmlElementCollection::child(const QDomElement &parent_element, const QString &child_name) const
{
	if (parent_element.ownerDocument() != m_dom_document) return QDomElement();

		//Get all childs element of parent_element
	QDomNodeList child_list = parent_element.childNodes();
	QString tag_name(child_name.endsWith(".elmt")? "element" : "category");
	QList <QDomElement> found_dom_element;
	for (int i=0 ; i<child_list.length() ; i++)
	{
		QDomElement child_element = child_list.item(i).toElement();
		if (child_element.tagName() == tag_name) found_dom_element << child_element;
	}

	if (found_dom_element.isEmpty()) return QDomElement();

	foreach (QDomElement elmt, found_dom_element)
		if (elmt.attribute("name") == child_name)
			return elmt;

	return QDomElement();
}

/**
 * @brief XmlElementCollection::child
 * @param path
 * @return the DomElement at path if exist, else return a null QDomElement
 */
QDomElement XmlElementCollection::child(const QString &path) const
{
	QStringList path_list = path.split("/");
	if (path_list.isEmpty()) return QDomElement();

	QDomElement parent_element = root();
	foreach (QString str, path_list)
	{
		QDomElement child_element = child(parent_element, str);

		if (child_element.isNull())
			return QDomElement();
		else
			parent_element = child_element;
	}

	return parent_element;
}

/**
 * @brief XmlElementCollection::directories
 * @param parent_element
 * @return A list of directory stored in @parent_element
 */
QList<QDomElement> XmlElementCollection::directories(const QDomElement &parent_element) const
{
	QList <QDomElement> directory_list;
	QDomNodeList node_list = childs(parent_element);
	if (node_list.isEmpty()) return directory_list;

	for (int i=0 ; i < node_list.count() ; i++)
	{
		QDomNode node = node_list.at(i);
		if (node.isElement() &&  node.toElement().tagName() == "category")
			directory_list << node.toElement();
	}

	return directory_list;
}

/**
 * @brief XmlElementCollection::directoriesNames
 * @param parent_element
 * @return a list of names for every child directories of @parent_element
 */
QStringList XmlElementCollection::directoriesNames(const QDomElement &parent_element) const
{
	QList <QDomElement> childs = directories(parent_element);
	QStringList names;

	foreach (QDomElement child, childs)
	{
		QString name = child.attribute("name");
		if (!name.isEmpty())
			names.append(name);
	}

	return names;
}

/**
 * @brief XmlElementCollection::elements
 * @param parent_element
 * @return A list of element stored in @parent_element
 */
QList<QDomElement> XmlElementCollection::elements(const QDomElement &parent_element) const
{
	QList <QDomElement> element_list;
	QDomNodeList node_list = childs(parent_element);
	if (node_list.isEmpty()) return element_list;

	for (int i=0 ; i < node_list.count() ; i++)
	{
		QDomNode node = node_list.at(i);
		if (node.isElement() &&  node.toElement().tagName() == "element")
			element_list << node.toElement();
	}

	return element_list;
}

/**
 * @brief XmlElementCollection::elementsNames
 * @param parent_element
 * @return A list of names fr every childs element of @parent_element
 */
QStringList XmlElementCollection::elementsNames(const QDomElement &parent_element) const
{
	QList <QDomElement> childs = elements(parent_element);
	QStringList names;

	foreach (QDomElement child, childs)
	{
		QString name = child.attribute("name");
		if (!name.isEmpty())
			names.append(name);
	}

	return names;
}

/**
 * @brief XmlElementCollection::element
 * @param path : path of the element in this collection
 * @return the QDomElement that represent the element at path @path
 * or a null QDomElement if not found or doesn't represent an element
 */
QDomElement XmlElementCollection::element(const QString &path) const
{
	if (!path.endsWith(".elmt")) return QDomElement();

	QDomElement element = child(path);

	if (element.tagName() == "element")
		return element;
	else
		return QDomElement();
}

/**
 * @brief XmlElementCollection::directory
 * @param path : path of the directory in this collection
 * @return the QDomElement that represent the directory at path @path
 * or a null QDomElement if not found.
 */
QDomElement XmlElementCollection::directory(const QString &path) const
{
	QDomElement directory = child(path);

	if (directory.tagName() == "category")
		return directory;
	else
		return QDomElement();
}

/**
 * @brief XmlElementCollection::addElement
 * Add the element at location to this collection.
 * The element is copied in this collection in "import" dir with the same path, in other word
 * if the path is dir1/dir2/dir3/myElement.elmt, myElement is copied to this collection at the path : import/dir1/dir2/dir3/myElement.elmt
 * If the path doesn't exist, he was created.
 * If the element already exist, do nothing.
 * @param location, location of the element
 * @return the collection path of the added item or a null QString if element can't be added.
 */
QString XmlElementCollection::addElement(ElementsLocation &location)
{
		//location must be an element and exist
	if (!(location.exist() && location.isElement()))
		return QString();

		//Add an element from this collection to this collection have no sense
	if (location.isProject() && location.projectCollection() == this)
		return QString();

		//First we check if this location exist in this collection if so, we do nothing
	if ( exist("import/" + location.collectionPath(false)) )
		return QString();

		//Get the import dir of this collection
	QDomElement parent_element = importCategory();
	if (parent_element.isNull())
		return QString();

	QString integrated_path = parent_element.attribute("name");

		//Split the path
	QStringList splitted_path = location.collectionPath(false).split("/");
	if (splitted_path.isEmpty())
		return QString();

	if (location.isFileSystem()) {
			//Get the root dir of the filesystem collection
		QDir dir(location.fileSystemPath().remove(location.collectionPath(false)));
		if (!dir.exists())
			return QString();

		foreach(QString str, splitted_path) {
			QDomElement child_element = child(parent_element, str);

				//Child doesn't exist, we create it
			if (child_element.isNull()) {
				QDomElement created_child;

					//str is the path of an element, we integrate an element
				if (str.endsWith(".elmt")) {
					QFile element_file(dir.filePath(str));
					if (!element_file.exists())
						return QString();

					created_child = QETXML::fileSystemElementToXmlCollectionElement(m_dom_document, element_file);
				}

					//str is the path of a directory, we integrate a directory.
				else {
						//Dir doesn't exist.
					if (!dir.cd(str))
						return QString();

					created_child = QETXML::fileSystemDirToXmlCollectionDir(m_dom_document, dir);
				}

				if(created_child.isNull())
					return QString();

				parent_element.appendChild(created_child);
				parent_element = created_child;
			}
				//Child exist
			else {
				if (!dir.cd(str))
					return QString();

				parent_element = child_element;
			}

			integrated_path.append("/"+str);
		}
	}
	else if (location.isProject()) {
		QString path;
		foreach(QString str, splitted_path) {
			if (path.isEmpty())
				path = str;
			else
				path = path + "/" + str;

			QDomElement child_element = child(parent_element, str);

				//Child doesn't exist, we create it
			if (child_element.isNull()) {
				QDomElement created_child;

					//str is the path of an element, we integrate an element
				if (str.endsWith(".elmt")) {
					created_child = m_dom_document.createElement("element");
					created_child.setAttribute("name", str);

					created_child.appendChild(location.xml().cloneNode(true));
				}

					//str is the path of a directory, we integrate a directory.
				else {
					created_child = m_dom_document.createElement("category");
					created_child.setAttribute("name", str);

					ElementsLocation sub_dir_location(path, location.project());
					QDomElement names_element = sub_dir_location.nameList().toXml(m_dom_document);
					created_child.appendChild(names_element);
				}

				if(created_child.isNull())
					return QString();

				parent_element.appendChild(created_child);
				parent_element = created_child;
			}
				//Child exist
			else
				parent_element = child_element;

			integrated_path.append("/"+str);
		}
	}

	emit elementAdded(integrated_path);
	return integrated_path;
}

/**
 * @brief XmlElementCollection::addElementDefinition
 * Add the élément defintion @xml_definition in the directory at path @dir_path with the name @elmt_name.
 * @param dir_path : the path of the directory where we must add the element.
 * The path must be an existing directory of this collection.
 * @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)
 * @param xml_definition : The xml definition of the element.
 * The tag name of @xml_definition must be "definition".
 * @return True if the element is added with success.
 */
bool XmlElementCollection::addElementDefinition(const QString &dir_path, const QString &elmt_name, const QDomElement &xml_definition)
{
	QDomElement dom_dir = directory(dir_path);
	if (dom_dir.isNull()) {
		qDebug() << "XmlElementCollection::addElementDefinition : No directory at path : " << dir_path;
		return false;
	}

	if (xml_definition.tagName() != "definition") {
		qDebug() << "XmlElementCollection::addElementDefinition : xml_defintion tag name is not \"definition\"";
		return false;
	}

	QString name = elmt_name;
	if (!name.endsWith(".elmt")) {
		name += ".elmt";
	}

	QDomElement dom_elmt = m_dom_document.createElement("element");
	dom_elmt.setAttribute("name", name);
	dom_elmt.appendChild(xml_definition.cloneNode(true));
	dom_dir.appendChild(dom_elmt);

	emit elementAdded(dir_path + "/" + name);

	return true;
}

/**
 * @brief XmlElementCollection::removeElement
 * Remove the element at path @path.
 * @param path
 * @return True if element is removed and emit the signal elementRemoved.
 * else false.
 */
bool XmlElementCollection::removeElement(const QString& path)
{
	QDomElement elmt = element(path);

	if (!elmt.isNull()) {
		elmt.parentNode().removeChild(elmt);
		emit elementRemoved(path);
		return true;
	}

	return false;
}

/**
 * @brief XmlElementCollection::copy
 * Copy the content represented by source (an element or a directory) to destination.
 * Destination must be a directory of this collection.
 * If the destination already have an item at the same path of source, he will be replaced by source.
 * @param source : content to copy
 * @param destination : destination of the copy, must be a directory of this collection
 * @param rename : rename the copy with @rename else use the name of source
 * @param deep_copy : if true copy all childs of source (only if source is directory)
 * @return the ElementLocation that represent the copy, if copy failed return a null ElementLocation
 */
ElementsLocation XmlElementCollection::copy(ElementsLocation &source, ElementsLocation &destination, const QString& rename, bool deep_copy)
{
	if (!(source.exist() && destination.isDirectory() && destination.isProject() && destination.projectCollection() == this))
		return ElementsLocation();

	if (source.isElement())
		return copyElement(source, destination, rename);
	else
		return copyDirectory(source, destination, rename, deep_copy);
}

/**
 * @brief XmlElementCollection::exist
 * Return true if the path @path exist in this collection
 * @param path
 * @return
 */
bool XmlElementCollection::exist(const QString &path) const
{
	if (child(path).isNull())
		return false;
	else
		return true;
}

/**
 * @brief XmlElementCollection::createDir
 * Create a child directorie at path @path with the name @name.
 * Emit directorieAdded if success.
 * @param path : path of parent diectorie
 * @param name : name of the directori to create.
 * @param name_list : translation of the directorie name.
 * @return true if creation success, if directorie already exist return true.
 */
bool XmlElementCollection::createDir(const QString& path, const QString& name, const NamesList &name_list)
{
	QString new_dir_path = path + "/" + name;

	if (!directory(new_dir_path).isNull()) {
		return true;
	}

	QDomElement parent_dir = directory(path);
	if (parent_dir.isNull()) {
		qDebug() << "XmlElementCollection::createDir : directorie at path doesn't exist";
		return false;
	}

	QDomElement new_dir = m_dom_document.createElement("category");
	new_dir.setAttribute("name", name);
	new_dir.appendChild(name_list.toXml(m_dom_document));

	parent_dir.appendChild(new_dir);

	emit directorieAdded(new_dir_path);

	return true;
}

/**
 * @brief XmlElementCollection::removeDir
 * Remove the directory at path @path.
 * @param path
 * @return true if successfuly removed and emit directoryRemoved(QString),
 * else false.
 */
bool XmlElementCollection::removeDir(const QString& path)
{
	QDomElement dir = directory(path);
	if (!dir.isNull()) {
		dir.parentNode().removeChild(dir);
		emit directoryRemoved(path);
		return true;
	}
	return false;
}

/**
 * @brief XmlElementCollection::elementsLocation
 * Return all locations stored in dom_element (element and directory).
 * If dom_element is null, return all location owned by this collection
 * dom_element must be a child of this collection.
 * @param dom_element : dom_element where we must to search location.
 * @param childs = if true return all childs location of dom_element, if false, only return the direct childs location of dom_element.
 * @return
 */
QList<ElementsLocation> XmlElementCollection::elementsLocation(QDomElement dom_element, bool childs) const
{
	QList <ElementsLocation> location_list;

	if (dom_element.isNull())
		dom_element = m_dom_document.documentElement();

	if (dom_element.ownerDocument() != m_dom_document)
		return location_list;

		//get element childs
	QList <QDomElement> element_list = elements(dom_element);

	foreach (QDomElement elmt, element_list) {
		ElementsLocation location = domToLocation(elmt);
		if (location.exist())
			location_list << location;
	}

		//get directory childs
	QList <QDomElement> directory_list = directories(dom_element);

	foreach (QDomElement dir, directory_list) {
		ElementsLocation location = domToLocation(dir);
		if (location.exist())
			location_list << location;

		if (childs)
			location_list.append(elementsLocation(dir, childs));
	}

	return location_list;
}

/**
 * @brief XmlElementCollection::domToLocation
 * Return the element location who represent the xml element : dom_element
 * dom_element must be owned by this collection
 * @param dom_element : the dom_element of this collection that represent an element.
 * The tag name of dom_element must be "element"
 * @return the element location, location can be null if fail.
 */
ElementsLocation XmlElementCollection::domToLocation(QDomElement dom_element) const
{
	if (dom_element.ownerDocument() == m_dom_document) {
		QString path = dom_element.attribute("name");

		while (!dom_element.parentNode().isNull() && dom_element.parentNode().isElement()) {
			dom_element = dom_element.parentNode().toElement();

			if (dom_element.tagName() == "category")
				path.prepend(dom_element.attribute("name") + "/");
		}

		return ElementsLocation(path, m_project);
	}
	else
		return ElementsLocation();
}

/**
 * @brief XmlElementCollection::cleanUnusedElement
 * Remove elements in this collection which is not used in the owner project
 */
void XmlElementCollection::cleanUnusedElement()
{
	foreach (ElementsLocation loc, m_project->unusedElements())
		removeElement(loc.collectionPath(false));
}

/**
 * @brief XmlElementCollection::cleanUnusedDirectory
 * Remove the empty directories of this collection
 */
void XmlElementCollection::cleanUnusedDirectory()
{
	QDomNodeList lst = importCategory().elementsByTagName("category");

	for(int i=0 ; i<lst.size() ; i++) {
		QDomElement dir = lst.item(i).toElement();
			//elmt haven't got child node "element" or "category", so he is emty, we can remove it
		if (dir.elementsByTagName("element").isEmpty() && dir.elementsByTagName("category").isEmpty()) {
			if (removeDir(domToLocation(dir).collectionPath(false)))
				i=-1;
		}
	}
}

/**
 * @brief XmlElementCollection::copyDirectory
 * Copy the directory represented by source to destination.
 * if destination have a directory with the same name as source, then this directory is removed
 * @param source : directory to copy
 * @param destination : destination of the copy
 * @param rename : rename the copy with @rename else use the name of source
 * @param deep_copy :if true copy all childs of source
 * @return the ElementLocation that represent the copy, if copy failed return a null ElementLocation
 */
ElementsLocation XmlElementCollection::copyDirectory(ElementsLocation &source, ElementsLocation &destination, const QString& rename, bool deep_copy)
{
	QString new_dir_name = rename.isEmpty() ? source.fileName() : rename;

			//Get the xml directory where the new directory must be added
	QDomElement parent_dir_dom = directory(destination.collectionPath(false));
	if (parent_dir_dom.isNull()) return ElementsLocation();

		//Remove the previous directory with the same path
	QDomElement element = child(destination.collectionPath(false) + "/" + new_dir_name);
	if (!element.isNull()) {
		element.parentNode().removeChild(element);
		emit directoryRemoved(destination.collectionPath(false) + "/" + new_dir_name);
	}

	ElementsLocation created_location;

		//Copy with a file system collection source
	if (source.isFileSystem())
	{
		QDir source_dir(source.fileSystemPath());
		if (!source_dir.exists()) return ElementsLocation();


		QDir dir(source.fileSystemPath());
		QDomElement elmt_dom = QETXML::fileSystemDirToXmlCollectionDir(m_dom_document, dir, new_dir_name);
		if (elmt_dom.isNull()) return ElementsLocation();

		parent_dir_dom.appendChild(elmt_dom);

		created_location.setPath(destination.projectCollectionPath() + "/" + new_dir_name);

		if (deep_copy)
		{
				//Append all directories of source to the new created directory
			foreach(QString str, source_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
			{
				ElementsLocation sub_source(source.fileSystemPath() + "/" + str);
				copyDirectory(sub_source, created_location);
			}

				//Append all elements of source to the new created directory
			source_dir.setNameFilters(QStringList() << "*.elmt");
			foreach(QString str, source_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name))
			{
				ElementsLocation sub_source(source.fileSystemPath() + "/" + str);
				copyElement(sub_source, created_location);
			}
		}
	}

		//Copy with a xml collection source
	else
	{
		if (!source.projectCollection()) return ElementsLocation();

		QDomNode other_collection_node = source.projectCollection()->child(source.collectionPath(false)).cloneNode(deep_copy);

			//We don't make a deep copy, but we must to get the local names of the copied directory
		if (!deep_copy) {
			QDomNode names = source.projectCollection()->child(source.collectionPath(false)).namedItem("names");
			if (!names.isNull() && names.isElement())
				other_collection_node.appendChild(names.cloneNode(true));
		}

		if (other_collection_node.isNull()) return ElementsLocation();

		QDomElement other_collection_dom_dir = other_collection_node.toElement();
		other_collection_dom_dir.setAttribute("name", new_dir_name);
		parent_dir_dom.appendChild(other_collection_dom_dir);

		created_location.setPath(destination.projectCollectionPath() + "/" + new_dir_name);
	}

	emit directorieAdded(created_location.collectionPath(false));
	return created_location;
}

/**
 * @brief XmlElementCollection::copyElement
 * Copy the element represented by source to destination (must be a directory)
 * If element already exist in destination he will be replaced by the new.
 * @param source : element to copy
 * @param destination : destination of the copy
 * @param rename : rename the copy with @rename else use the name of source
 * @return The ElementsLocation of the copy
 */
ElementsLocation XmlElementCollection::copyElement(ElementsLocation &source, ElementsLocation &destination, const QString& rename)
{
	QString new_elmt_name = rename.isEmpty() ? source.fileName() : rename;

	QDomElement elmt_dom;

		//Copy with a file system collection source
	if (source.isFileSystem())
	{
		QFile file(source.fileSystemPath());
		elmt_dom = QETXML::fileSystemElementToXmlCollectionElement(m_dom_document, file, new_elmt_name);
		if (elmt_dom.isNull()) return ElementsLocation();
	}
		//Copy with a xml collection source
	else
	{
		QDomElement other_collection = source.xml();
		elmt_dom = m_dom_document.createElement("element");
		elmt_dom.setAttribute("name", new_elmt_name);
		elmt_dom.appendChild(other_collection.cloneNode());
	}


		//Remove the previous element with the same path
	QDomElement element = child(destination.collectionPath(false) + "/" + new_elmt_name);
	bool removed = false;
	if (!element.isNull()) {
		element.parentNode().removeChild(element);
		removed = true;
	}

		//Get the xml directory where the new element must be added
	QDomElement dir_dom = directory(destination.collectionPath(false));
	if (dir_dom.isNull()) return ElementsLocation();
	dir_dom.appendChild(elmt_dom);

	ElementsLocation copy_loc(destination.projectCollectionPath() + "/" + new_elmt_name);

	if (removed) {
		emit elementChanged(copy_loc.collectionPath(false));
	}
	else {
		emit elementAdded(copy_loc.collectionPath(false));
	}

	return copy_loc;
}