QElectroTech  0.70
elementcollectionhandler.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 */
19 #include "renamedialog.h"
20 #include "xmlelementcollection.h"
21 #include "qetproject.h"
22 #include "qetxml.h"
23 #include <QFile>
24 #include <QDir>
25 
26 /******************************************************/
27 
29  m_source(source),
30  m_destination (destination)
31 {}
32 
34 
35 /******************************************************/
36 
38  ECHStrategy(source, destination)
39 {}
40 
42 {
43  //Check if the destination already have an item with the same name of the item to copy
45  QString rename;
46  if (location.exist())
47  {
48  RenameDialog rd(location.fileSystemPath());
49  if (rd.exec() == QDialog::Accepted)
50  {
51  if (rd.selectedAction() == QET::Erase)
52  {
53  if (location.isDirectory())
54  {
55  QDir dir(location.fileSystemPath());
56  dir.removeRecursively();
57  }
58  else
59  {
60  QFile file(location.fileSystemPath());
61  file.remove();
62  }
63  }
64  else if (rd.selectedAction() == QET::Rename)
65  {
66  rename = rd.newName();
67  }
68  }
69  else
70  return ElementsLocation();
71  }
72 
73  if (m_source.isElement())
74  return copyElement(m_source, m_destination, rename);
75  else
76  return copyDirectory(m_source, m_destination, rename);
77 }
78 
80 {
81  QDir source_dir(source.fileSystemPath());
82  QDir destination_dir(destination.fileSystemPath());
83 
84  if (!source_dir.exists() || !destination_dir.exists()) return ElementsLocation();
85 
86  QString new_dir_name = rename.isEmpty() ? source_dir.dirName() : rename;
87 
88  //Create a new dir
89  if (destination_dir.mkdir(new_dir_name))
90  {
91  //The new created directory
92  QDir created_dir(destination_dir.canonicalPath() + "/" + new_dir_name);
93 
94  //Copy the qet_directory file
95  QFile::copy(source_dir.canonicalPath() + "/qet_directory", created_dir.canonicalPath() + "/qet_directory");
96 
97  //Copy all dirs found in source_dir to destination_dir
98  ElementsLocation created_location(created_dir.canonicalPath());
99  //Used this bool when user drop a folder into itself to avoid infinite recursive creation of the dropped dir
100  bool copy_itself = false;
101  if (source_dir == destination_dir)
102  copy_itself = true;
103 
104  foreach(QString str, source_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name))
105  {
106  if (copy_itself)
107  {
108  if (source_dir.dirName() == str)
109  {
110  copy_itself = false;
111  continue;
112  }
113  }
114 
115  ElementsLocation sub_source(source.fileSystemPath() + "/" + str);
116  copyDirectory(sub_source, created_location);
117  }
118 
119  //Copy all elements found in source_dir to destination_dir
120  source_dir.setNameFilters(QStringList() << "*.elmt");
121  foreach(QString str, source_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name))
122  {
123  ElementsLocation sub_source(source.fileSystemPath() + "/" + str);
124  copyElement(sub_source, created_location);
125  }
126 
127  return created_location;
128  }
129 
130  return ElementsLocation();
131 }
132 
134 {
135  QString new_elmt_name = rename.isEmpty() ? source.fileName() : rename;
136  bool rb = QFile::copy(source.fileSystemPath(), destination.fileSystemPath() + "/" + new_elmt_name);
137  if (rb)
138  {
139 #ifdef Q_OS_WIN
140  //On windows when user drag and drop an element from the common elements collection
141  //to the custom elements collection, the element file stay in read only mode, and so
142  //user can't save the element
143  extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
144  qt_ntfs_permission_lookup++;
145  QFile file(destination.fileSystemPath() + "/" + new_elmt_name);
146  if (!file.isWritable()) {
147  if (!file.setPermissions(file.permissions() | QFileDevice::WriteUser)) {
148  qDebug() << "Failed to change file permission of : " << QFileInfo(file).canonicalFilePath() \
149  << " in ECHSFileToFile::copyElement";
150  }
151  }
152  qt_ntfs_permission_lookup--;
153 #endif
154  return ElementsLocation (destination.fileSystemPath() + "/" + new_elmt_name);
155  }
156  else
157  return ElementsLocation();
158 }
159 
160 /******************************************************/
161 
163  ECHStrategy(source, destination)
164 {}
165 
167 {
168  //Check if the destination already have an item with the same name of the item to copy
170  QString rename;
171  if (location.exist())
172  {
173  RenameDialog rd(location.fileSystemPath());
174  if (rd.exec() == QDialog::Accepted)
175  {
176  if (rd.selectedAction() == QET::Erase)
177  {
178  if (location.isDirectory())
179  {
180  QDir dir(location.fileSystemPath());
181  dir.removeRecursively();
182  }
183  else
184  {
185  QFile file(location.fileSystemPath());
186  file.remove();
187  }
188  }
189  else if (rd.selectedAction() == QET::Rename)
190  {
191  rename = rd.newName();
192  }
193  }
194  else
195  return ElementsLocation();
196  }
197 
198  if (m_source.isElement())
199  return copyElement(m_source, m_destination, rename);
200  else
201  return copyDirectory(m_source, m_destination, rename);
202 }
203 
205 {
206  QDir destination_dir(destination.fileSystemPath());
207 
208  if (!(destination_dir.exists() && source.exist())) return ElementsLocation();
209 
210  QString new_dir_name = rename.isEmpty() ? source.fileName() : rename;
211 
212  //Create new dir
213  if (destination_dir.mkdir(new_dir_name))
214  {
215  QDir created_dir(destination_dir.canonicalPath() + "/" + new_dir_name);
216  ElementsLocation created_location(created_dir.canonicalPath());
217 
218  //Create the qet-directory file
219  QDomDocument document;
220  QDomElement root = document.createElement("qet-directory");
221  document.appendChild(root);
222  root.appendChild(source.nameList().toXml(document));
223 
224  QString filepath = created_dir.canonicalPath() + "/qet_directory";
225  QET::writeXmlFile(document, filepath);
226 
227  //Create all directory found in source to created_dir
228  XmlElementCollection *project_collection = source.projectCollection();
229 
230  QStringList directories_names = project_collection->directoriesNames( project_collection->directory(source.collectionPath(false)) );
231  foreach(QString name, directories_names)
232  {
233  ElementsLocation sub_source_dir(source.projectCollectionPath() + "/" + name);
234  copyDirectory(sub_source_dir, created_location);
235  }
236 
237  //Create all elements found in source to destination
238  QStringList elements_names = project_collection->elementsNames( project_collection->directory(source.collectionPath(false))) ;
239  foreach (QString name, elements_names)
240  {
241  ElementsLocation source_element(source.projectCollectionPath() + "/" + name);
242  copyElement(source_element, created_location);
243  }
244 
245  return created_location;
246  }
247 
248  return ElementsLocation();
249 }
250 
252 {
253  if (!(destination.exist() && source.exist())) return ElementsLocation();
254 
255  QString new_element_name = rename.isEmpty() ? source.fileName() : rename;
256 
257  //Get the xml descrption of the element
258  QDomDocument document;
259  document.appendChild(document.importNode(source.xml(), true));
260 
261  //Create the .elmt file
262  QString filepath = destination.fileSystemPath() + "/" + new_element_name;
263  if (QET::writeXmlFile(document, filepath))
264  return ElementsLocation(filepath);
265  else
266  return ElementsLocation();
267 }
268 
269 /******************************************************/
270 
272  ECHStrategy(source, destination)
273 {}
274 
276 {
278 
279  //Check if the destination already have an item with the same name of the item to copy
281 
282  QString rename;
283  if (location.exist())
284  {
285  RenameDialog rd(location.collectionPath());
286  if(rd.exec() == QDialog::Accepted)
287  {
288  if (rd.selectedAction() == QET::Rename)
289  rename = rd.newName();
290  }
291  else
292  return ElementsLocation();
293  }
294 
296 }
297 
298 /******************************************************/
299 
305 
307 {
308  if (m_strategy) delete m_strategy;
309 }
310 
321 {
322  if (!source.exist() || !destination.exist() || destination.isElement()) return ElementsLocation();
323 
324  if (source.isFileSystem() && destination.isFileSystem()) m_strategy = new ECHSFileToFile(source, destination);
325  if (source.isProject() && destination.isFileSystem()) m_strategy = new ECHSXmlToFile(source, destination);
326  else if (destination.isProject()) m_strategy = new ECHSToXml(source, destination);
327 
328  if (m_strategy)
329  return m_strategy->copy();
330  else
331  return ElementsLocation();
332 }
333 
344 {
345  //Parent must be a directorie and writable
346  if (!(parent.isDirectory() && parent.isWritable() && parent.exist())) {
347  qDebug() << "ElementCollectionHandler::createDir : the prerequisites are not valid. " << parent;
348  return ElementsLocation();
349  }
350 
351  //Directorie to create must not already exist
352  ElementsLocation created_dir = parent;
353  created_dir.addToPath(name);
354  if (created_dir.exist()) {
355  return ElementsLocation();
356  }
357 
358  //Location is a file system
359  if (parent.isFileSystem()) {
360 
361  QDir parent_dir(parent.fileSystemPath());
362 
363  if (parent_dir.mkdir(name)) {
364  //Create the qet-directory file
365  QDomDocument document;
366  QDomElement root = document.createElement("qet-directory");
367  document.appendChild(root);
368  root.appendChild(name_list.toXml(document));
369 
370  QString filepath = created_dir.fileSystemPath() + "/qet_directory";
371  if (!QET::writeXmlFile(document, filepath)) {
372  qDebug() << "ElementCollectionHandler::createDir : write qet-directory file failed";
373  }
374  return created_dir;
375  }
376  else {
377  qDebug() << "ElementCollectionHandler::createDir : error was occurred at creation of new directories in file system. ";
378  return ElementsLocation();
379  }
380  }
381  else if (parent.isProject()) {
382  XmlElementCollection *xmlec = parent.projectCollection();
383  if (xmlec->createDir(parent.collectionPath(false), name, name_list)) {
384  return created_dir;
385  }
386  else {
387  qDebug() << "ElementCollectionHandler::createDir : error was occurred at creation of new directories in embbeded collection.";
388  return ElementsLocation();
389  }
390  }
391 
392  return ElementsLocation();
393 }
394 
404 {
405  if (!(location.isElement() && location.exist() && location.isProject())) return false;
406 
407  ElementsLocation destination(location.collectionPath(false), project);
408  if (destination.exist()) return true;
409 
410  QList <QString> names;
411 
412  //Get the parent of location and find if exist in embedded collection of project
413  ElementsLocation source = location.parent();
414  names.append(location.fileName());
415 
416  destination = ElementsLocation(source.collectionPath(), project);
417 
418  //Go back until to find an existing directory in destination
419  while (!destination.exist()) {
420  names.append(source.fileName());
421  source = source.parent();
422  destination = ElementsLocation(source.collectionPath(), project);
423  }
424 
425  XmlElementCollection *collection = project->embeddedElementCollection();
426 
427  while (!names.isEmpty()) {
428  source.addToPath(names.takeLast());
429  destination = collection->copy(source, destination, QString(), false);
430 
431  if (!destination.exist())
432  return false;
433  }
434 
435  return true;
436 }
437 
446 {
447  if ( !(location.exist() && location.isWritable()) ) {
448  return false;
449  }
450 
451  if (location.isFileSystem()) {
452  if (location.isDirectory()) {
453  QDomDocument document;
454  QDomElement root = document.createElement("qet-directory");
455  document.appendChild(root);
456  root.appendChild(name_list.toXml(document));
457 
458  QString filepath = location.fileSystemPath() + "/qet_directory";
459  if (!QET::writeXmlFile(document, filepath)) {
460  qDebug() << "ElementCollectionHandler::setNames : write qet-directory file failed";
461  return false;
462  }
463 
464  return true;
465  }
466 
467  if (location.isElement()) {
468  QDomDocument document;
469  document.appendChild(document.importNode(location.xml(), true));
470  if (document.isNull()) {
471  qDebug() << "ElementCollectionHandler::setNames : failed to load xml document from file";
472  return false;
473  }
474 
475  QDomElement document_element = document.documentElement();
476  document_element.replaceChild(name_list.toXml(document), document_element.firstChildElement("names"));
477  return true;
478  }
479  }
480 
481  if (location.isProject()) {
482  QDomElement element = location.xml();
483  QDomDocument document = element.ownerDocument();
484  element.replaceChild(name_list.toXml(document), element.firstChildElement("names"));
485  return true;
486  }
487 
488  return false;
489 }
QStringList directoriesNames(const QDomElement &parent_element) const
XmlElementCollection::directoriesNames.
QString projectCollectionPath() const
ElementsLocation::projectCollectionPath.
bool importFromProject(QETProject *project, ElementsLocation &location)
ElementCollectionHandler::importFromProject Import the element represented by to the embedded collec...
bool isProject() const
ElementsLocation::isProject.
NamesList nameList()
ElementsLocation::nameList.
ElementsLocation copyDirectory(ElementsLocation &source, ElementsLocation &destination, const QString &rename=QString())
ElementsLocation copy(ElementsLocation &source, ElementsLocation &destination, const QString &rename=QString(), bool deep_copy=true)
XmlElementCollection::copy Copy the content represented by source (an element or a directory) to dest...
The ECHSFileToFile class Manage the copy of directory or element from a file system collection to ano...
ElementsLocation copy(ElementsLocation &source, ElementsLocation &destination)
ElementCollectionHandler::copy Copy the content of collection represented by source to the collection...
bool createDir(const QString &path, const QString &name, const NamesList &name_list)
ECHStrategy(ElementsLocation &source, ElementsLocation &destination)
bool isFileSystem() const
ElementsLocation::isFileSystem.
ECHSToXml(ElementsLocation &source, ElementsLocation &destination)
ElementsLocation copy() override
ElementsLocation m_destination
The ECHStrategy class Abstract class for manage copy of directory or element from a collection to ano...
ECHSXmlToFile(ElementsLocation &source, ElementsLocation &destination)
QString fileName() const
ElementLocation::fileName.
ElementsLocation copyElement(ElementsLocation &source, ElementsLocation &destination, const QString &rename=QString())
QDomElement toXml(QDomDocument &, const QHash< QString, QString > &=QHash< QString, QString >()) const
Definition: nameslist.cpp:143
The ECHSXmlToFile class Manage the copy of a directory or element from an xml collection to a file...
QStringList elementsNames(const QDomElement &parent_element) const
XmlElementCollection::elementsNames.
ElementsLocation createDir(ElementsLocation &parent, const QString &name, const NamesList &name_list)
the target has to be renamed
Definition: qet.h:131
bool addToPath(const QString &)
ElementsLocation::addToPath Add a string to the actual path of this location.
XmlElementCollection * embeddedElementCollection() const
QETProject::embeddedCollection.
Definition: qetproject.cpp:229
Erase the target content.
Definition: qet.h:128
ElementsLocation copyDirectory(ElementsLocation &source, ElementsLocation &destination, const QString &rename=QString())
XmlElementCollection * projectCollection() const
ElementsLocation::projectCollection.
QDomElement directory(const QString &path) const
XmlElementCollection::directory.
QString collectionPath(bool protocol=true) const
ElementsLocation copy() override
bool writeXmlFile(QDomDocument &xml_doc, const QString &filepath, QString *error_message=nullptr)
Definition: qet.cpp:544
ElementsLocation copyElement(ElementsLocation &source, ElementsLocation &destination, const QString &rename=QString())
QString newName() const
Definition: renamedialog.h:36
QDomElement xml() const
ElementsLocation::xml.
ElementsLocation copy() override
bool exist() const
ElementsLocation::exist.
ElementCollectionHandler()
ElementCollectionHandler::ElementCollectionHandler.
QString fileSystemPath() const
ElementsLocation::fileSystemPath.
bool setNames(ElementsLocation &location, const NamesList &name_list)
ElementCollectionHandler::setNames Set the names stored in as the names of the item represented by l...
The ECHSToXml class Manage the copy of a directory or element from a collection (no matter if the sou...
bool isDirectory() const
ElementsLocation::isDirectory.
virtual ElementsLocation copy()=0
ECHSFileToFile(ElementsLocation &source, ElementsLocation &destination)
ElementsLocation m_source
bool isElement() const
ElementsLocation::isElement.
bool isWritable() const
ElementsLocation::isWritable.
ElementsLocation parent() const
The XmlElementCollection class This class represent a collection of elements stored to xml...