QElectroTech  0.70
elementslocation.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 */
18 #include "elementslocation.h"
19 #include "qetapp.h"
20 #include "xmlelementcollection.h"
21 #include "qetproject.h"
23 #include "elementpicturefactory.h"
24 #include "element.h"
25 #include "qetxml.h"
26 #include <QPicture>
27 
28 // make this class usable with QVariant
29 int ElementsLocation::MetaTypeId = qRegisterMetaType<ElementsLocation>("ElementsLocation");
30 
36 {}
37 
43 ElementsLocation::ElementsLocation(const QString &path, QETProject *project) :
44  m_project(project)
45 {
46  setPath(path);
47 }
48 
53 }
54 
60  m_collection_path(other.m_collection_path),
61  m_file_system_path(other.m_file_system_path),
62  m_project(other.m_project)
63 {}
64 
72 ElementsLocation::ElementsLocation(const QMimeData *data)
73 {
74  if (data->hasFormat("application/x-qet-element-uri") || data->hasFormat("application/x-qet-category-uri"))
75  setPath(data->text());
76 }
77 
85  m_project = other.m_project;
86  return(*this);
87 }
88 
95  return(
97  m_project == other.m_project
98  );
99 }
100 
107  return(
109  m_project != other.m_project
110  );
111 }
112 
120 QString ElementsLocation::baseName() const {
121  QRegExp regexp("^.*([^/]+)\\.elmt$");
122  if (regexp.exactMatch(m_collection_path)) {
123  return(regexp.capturedTexts().at(1));
124  }
125  return(QString());
126 }
127 
136 }
137 
146 QString ElementsLocation::collectionPath(bool protocol) const
147 {
148  if (protocol)
149  return m_collection_path;
150  else
151  {
152  QString path = m_collection_path;
153  return path.remove(QRegularExpression("common://|custom://|embed://"));
154  }
155 }
156 
163 {
164  if (isFileSystem())
165  return QString();
166  else
167  return QString("project" + QString::number(QETApp::projectId(m_project)) + "+" + collectionPath());
168 }
169 
176 {
177  if (!m_project)
178  return m_file_system_path;
179  else
180  return QString();
181 }
182 
188 QString ElementsLocation::path() const {
189  return(m_collection_path);
190 }
191 
198 void ElementsLocation::setPath(const QString &path)
199 {
200  QString tmp_path = path;
201 #ifdef Q_OS_WIN32
202  //On windows, we convert backslash to slash
203  tmp_path = QDir::fromNativeSeparators(path);
204 
205 #endif
206 
207  //There is a project, the path is for an embedded coolection.
208  if (m_project)
209  {
211  //Add the protocol to the collection path
212  if (!path.startsWith("embed://"))
213  m_collection_path.prepend("embed://");
214 
215  }
216 
217  //The path start with project, we get the project and the path from the string
218  else if (tmp_path.startsWith("project"))
219  {
220  QRegExp rx("^project([0-9]+)\\+(embed:\\/\\/.*)$", Qt::CaseInsensitive);
221  if (rx.exactMatch(tmp_path))
222  {
223  bool conv_ok;
224  uint project_id = rx.capturedTexts().at(1).toUInt(&conv_ok);
225  if (conv_ok)
226  {
227  QETProject *project = QETApp::project(project_id);
228  if (project)
229  {
230  m_collection_path = rx.capturedTexts().at(2);
231  m_project = project;
232  }
233  }
234  }
235  }
236 
237  //The path is in file system, the given path is relative to common or custom collection
238  else if (path.startsWith("common://") || path.startsWith("custom://"))
239  {
240  QString p;
241  if (path.startsWith("common://"))
242  {
243  tmp_path.remove("common://");
244  p = QETApp::commonElementsDirN() + "/" + tmp_path;
245  }
246  else
247  {
248  tmp_path.remove("custom://");
249  p = QETApp::customElementsDirN() + "/" + tmp_path;
250  }
251 
252  m_file_system_path = p;
254  }
255  //In this case, the path is supposed to be relative to the file system.
256  else
257  {
258  QString path_ = path;
259  if(path_.endsWith(".elmt"))
260  {
261  m_file_system_path = path_;
262  if (path_.startsWith(QETApp::commonElementsDirN()))
263  {
264  path_.remove(QETApp::commonElementsDirN()+="/");
265  path_.prepend("common://");
266  m_collection_path = path_;
267  }
268  else if (path_.startsWith(QETApp::customElementsDirN()))
269  {
270  path_.remove(QETApp::customElementsDirN()+="/");
271  path_.prepend("custom://");
272  m_collection_path = path_;
273  }
274  }
275  else
276  {
277  m_file_system_path = path_;
278  if (path_.startsWith(QETApp::commonElementsDirN()))
279  {
280  path_.remove(QETApp::commonElementsDirN()+="/");
281  path_.prepend("common://");
282  m_collection_path = path_;
283  }
284  else if (path_.startsWith(QETApp::customElementsDirN()))
285  {
286  path_.remove(QETApp::customElementsDirN()+="/");
287  path_.prepend("custom://");
288  m_collection_path = path_;
289  }
290  }
291  }
292 }
293 
300 bool ElementsLocation::addToPath(const QString &string)
301 {
302  if (m_collection_path.endsWith(".elmt", Qt::CaseInsensitive))
303  {
304  qDebug() << "ElementsLocation::addToPath : Can't add string to the path of an element";
305  return(false);
306  }
307 
308  QString added_path = string;
309 
310  if (!m_collection_path.endsWith("/") && !added_path.startsWith("/"))
311  added_path.prepend("/");
312 
313  if (isFileSystem())
314  m_file_system_path += added_path;
315 
316  m_collection_path += added_path;
317  return(true);
318 }
319 
325  ElementsLocation copy(*this);
326  QRegExp re1("^([a-z]+://)(.*)/*$");
327  if (re1.exactMatch(m_collection_path)) {
328  QString path_proto = re1.capturedTexts().at(1);
329  QString path_path = re1.capturedTexts().at(2);
330  QString parent_path = path_path.remove(QRegExp("/*[^/]+$"));
331  copy.setPath(path_proto + parent_path);
332  }
333  return(copy);
334 }
335 
341  return(m_project);
342 }
343 
349  m_project = project;
350 }
351 
356  return(m_collection_path.isEmpty());
357 }
358 
362 QString ElementsLocation::toString() const {
363  QString result;
364  if (m_project) {
365  int project_id = QETApp::projectId(m_project);
366  if (project_id != -1) {
367  result += "project" + QString().setNum(project_id) + "+";
368  }
369  }
370  result += m_collection_path;
371  return(result);
372 }
373 
379  return m_collection_path.endsWith(".elmt");
380 }
381 
387  return (!isElement() && !m_collection_path.isEmpty());
388 }
389 
395 {
396  if (m_project) return false;
397  if (m_file_system_path.isEmpty()) return false;
398  return true;
399 }
400 
406 {
407  return fileSystemPath().startsWith(QETApp::commonElementsDirN());
408 }
409 
415 {
416  return fileSystemPath().startsWith(QETApp::customElementsDirN());
417 }
418 
424 {
425  if (m_project && !m_collection_path.isEmpty())
426  return true;
427  else
428  return false;
429 }
430 
436 {
437  if (m_project)
438  {
440  }
441  else
442  {
443  if (fileSystemPath().isEmpty()) return false;
444 
445  if (isDirectory())
446  {
447  QDir dir(fileSystemPath());
448  return dir.exists();
449  }
450  else if (isElement())
451  return QFile::exists(fileSystemPath());
452  else
453  return false;
454  }
455 }
456 
462 {
463  if (m_project)
464  return !m_project->isReadOnly();
465  else if (isFileSystem())
466  {
467  if (fileSystemPath().startsWith(QETApp::commonElementsDirN()))
468  return false;
469  else
470  return true;
471  }
472  return false;
473 }
474 
481 {
482  if (m_project)
484  else
485  return nullptr;
486 }
487 
494 {
495  NamesList nl;
496 
497  if (isElement())
498  nl.fromXml(xml());
499 
500  if (isDirectory())
501  {
502  if (m_project)
504  else
505  {
506  //Open the qet_directory file, to get the traductions name of this dir
507  QFile dir_conf(fileSystemPath() + "/qet_directory");
508  if (dir_conf.exists() && dir_conf.open(QIODevice::ReadOnly | QIODevice::Text))
509  {
510  //Get the content of the file
511  QDomDocument document;
512  if (document.setContent(&dir_conf))
513  {
514  QDomElement root = document.documentElement();
515  if (root.tagName() == "qet-directory")
516  nl.fromXml(root);
517  }
518  }
519  }
520  }
521 
522  return nl;
523 }
524 
530 QDomElement ElementsLocation::xml() const
531 {
532  if (!m_project)
533  {
534  QFile file (m_file_system_path);
535  QDomDocument docu;
536  if (docu.setContent(&file))
537  return docu.documentElement();
538  }
539  else
540  {
541  QString str = m_collection_path;
542  if (isElement())
543  {
544  QDomElement element = m_project->embeddedElementCollection()->element(str.remove("embed://"));
545  return element.firstChildElement("definition");
546  }
547  else
548  {
549  QDomElement element = m_project->embeddedElementCollection()->directory(str.remove("embed://"));
550  return element;
551  }
552  }
553 
554  return QDomElement();
555 }
556 
565 bool ElementsLocation::setXml(const QDomDocument &xml_document) const
566 {
567  if (!isWritable())
568  return false;
569 
570  if (xml_document.documentElement().tagName() != "definition")
571  {
572  qDebug() << "ElementsLocation::setXml : tag name of document element isn't 'definition'";
573  return false;
574  }
575 
576  if (isFileSystem())
577  {
578  QString error;
579  QETXML::writeXmlFile(xml_document, fileSystemPath(), &error);
580 
581  if (!error.isEmpty()) {
582  qDebug() << "ElementsLocation::setXml error : " << error;
583  return false;
584  }
585  else {
586  return true;
587  }
588  }
589  else if (isProject())
590  {
591  //Element exist, we overwrite the existing element.
592  if (exist())
593  {
594  QDomElement dom_element = xml();
595  QDomNode parent_node = dom_element.parentNode();
596  parent_node.removeChild(dom_element);
597  parent_node.appendChild(xml_document.documentElement().cloneNode(true));
598  return true;
599  }
600  //Element doesn't exist, we create the element
601  else
602  {
603  QString path_ = collectionPath(false);
604  QRegExp rx ("^(.*)/(.*\\.elmt)$");
605 
606  if (rx.exactMatch(path_)) {
607  return project()->embeddedElementCollection()->addElementDefinition(rx.cap(1), rx.cap(2), xml_document.documentElement());
608  }
609  else {
610  qDebug() << "ElementsLocation::setXml : rx don't match";
611  }
612 
613  }
614  }
615 
616  return false;
617 }
618 
625 {
626  //Get the uuid of element
627  QList<QDomElement> list_ = QET::findInDomElement(xml(), "uuid");
628 
629  if (!list_.isEmpty())
630  return QUuid(list_.first().attribute("uuid"));
631 
632  return QUuid();
633 }
634 
641 {
642  if (!m_project)
643  {
645  ElementsLocation loc(*this); //Make a copy of this to keep this method const
646  if (cache->fetchElement(loc))
647  return QIcon(cache->pixmap());
648  }
649  else {
650  return QIcon(ElementPictureFactory::instance()->pixmap(*this));
651  }
652 
653  return QIcon();
654 }
655 
660 QString ElementsLocation::name() const
661 {
662  NamesList nl;
663  nl.fromXml(xml());
664  return nl.name(fileName());
665 }
666 
676 {
677  if (m_collection_path.isEmpty()) return QString();
678 
679  QStringList qsl = m_collection_path.split("/");
680  if (qsl.isEmpty()) return QString();
681  else return qsl.last();
682 }
683 
690 {
691  DiagramContext context;
692  if (isDirectory()) {
693  return context;
694  }
695 
696  QDomElement dom = this->xml().firstChildElement("elementInformations");
697  context.fromXml(dom, "elementInformation");
698  return context;
699 }
700 
705 uint qHash(const ElementsLocation &location) {
706  return(qHash(location.toString()));
707 }
708 
709 QDebug operator<< (QDebug debug, const ElementsLocation &location)
710 {
711  QDebugStateSaver saver(debug);
712 
713 #if QT_VERSION >= 0x050400
714  debug.noquote();
715 #else
716  debug.nospace();
717 #endif
718 
719  QString msg;
720  msg += "ElementsLocation(";
721  msg += (location.isProject()? location.projectCollectionPath() : location.collectionPath(true));
722  msg += location.exist()? ", true" : ", false";
723  msg +=")";
724 
725  debug << msg;
726 
727  return debug;
728 }
QString projectCollectionPath() const
ElementsLocation::projectCollectionPath.
int projectId() const
ElementsLocation::projectId This method is used to know if an element belongs to a project or not...
QString baseName() const
ElementsLocation::baseName.
bool isProject() const
ElementsLocation::isProject.
NamesList nameList()
ElementsLocation::nameList.
bool isReadOnly() const
Definition: qetproject.cpp:915
void setProject(QETProject *)
QString toString() const
static ElementPictureFactory * instance()
instance
bool isFileSystem() const
ElementsLocation::isFileSystem.
QString fileName() const
ElementLocation::fileName.
static ElementsCollectionCache * collectionCache()
Definition: qetapp.cpp:281
static int projectId(const QETProject *)
Definition: qetapp.cpp:2002
static QETProject * project(const uint &)
Definition: qetapp.cpp:1990
QDomElement element(const QString &path) const
XmlElementCollection::element.
QIcon icon() const
ElementLocation::icon.
static int MetaTypeId
Id of the corresponding Qt meta type.
QDebug operator<<(QDebug debug, const ElementsLocation &location)
ElementsLocation & operator=(const ElementsLocation &)
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
DiagramContext elementInformations() const
ElementsLocation::elementInformations.
QString m_file_system_path
bool writeXmlFile(const QDomDocument &xml_document, const QString &file_path, QString *error_message=nullptr)
QETXML::writeXmlFile Export an XML document to an UTF-8 text file indented with 4 spaces...
Definition: qetxml.cpp:235
bool exist(const QString &path) const
XmlElementCollection::exist Return true if the path exist in this collection.
QIcon nl
Definition: qeticons.cpp:202
void fromXml(const QDomElement &, const QString &="property")
QUuid uuid() const
ElementsLocation::uuid.
XmlElementCollection * projectCollection() const
ElementsLocation::projectCollection.
bool setXml(const QDomDocument &xml_document) const
ElementsLocation::setXml Replace the current xml description by ; The document element of must have ...
void setPath(const QString &path)
ElementsLocation::setPath Set the path of this item. The path can be relative to a collection (start ...
bool operator!=(const ElementsLocation &) const
bool operator==(const ElementsLocation &) const
QDomElement directory(const QString &path) const
XmlElementCollection::directory.
QETProject * project() const
QString collectionPath(bool protocol=true) const
QList< QDomElement > findInDomElement(const QDomElement &, const QString &)
Definition: qet.cpp:300
QDomElement xml() const
ElementsLocation::xml.
QString name() const
ElementLocation::name.
ElementsLocation()
ElementsLocation::ElementsLocation Constructor.
bool exist() const
ElementsLocation::exist.
uint qHash(const ElementsLocation &location)
QString fileSystemPath() const
ElementsLocation::fileSystemPath.
bool isDirectory() const
ElementsLocation::isDirectory.
bool fetchElement(ElementsLocation &location)
ElementsCollectionCache::fetchElement Retrieve the data for a given element, using the cache if avail...
bool addElementDefinition(const QString &dir_path, const QString &elmt_name, const QDomElement &xml_definition)
XmlElementCollection::addElementDefinition Add the élément defintion in the directory at path with ...
static QString customElementsDirN()
QETApp::customElementsDirN like QString QETApp::customElementsDir but without "/" at the end...
Definition: qetapp.cpp:598
virtual ~ElementsLocation()
QETProject * m_project
bool isElement() const
ElementsLocation::isElement.
bool isCommonCollection() const
ElementsLocation::isCommonCollection.
bool isCustomCollection() const
ElementsLocation::isCustomCollection.
static QString commonElementsDirN()
QETApp::commonElementsDirN like QString QETApp::commonElementsDir but without "/" at the end...
Definition: qetapp.cpp:586
QString path() const
ElementsLocation::path.
bool isWritable() const
ElementsLocation::isWritable.
ElementsLocation parent() const
The XmlElementCollection class This class represent a collection of elements stored to xml...