QElectroTech  0.70
templatescollection.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 "templatescollection.h"
19 #include "titleblocktemplate.h"
20 #include "qetapp.h"
21 #include "qetproject.h"
22 
28  QObject(parent),
29  protocol_("unknown")
30 {
31 }
32 
37 }
38 
43  return(title_);
44 }
45 
49 void TitleBlockTemplatesCollection::setTitle(const QString &title) {
50  title_ = title;
51 }
52 
58  return(protocol_);
59 }
60 
65 void TitleBlockTemplatesCollection::setProtocol(const QString &protocol) {
66  if (!protocol.isEmpty()) protocol_ = protocol;
67 }
68 
74  return m_collection;
75 }
76 
83  m_collection = c;
84 }
85 
91  return(nullptr);
92 }
93 
99 QList<TitleBlockTemplateLocation> TitleBlockTemplatesCollection::templatesLocations() {
100  QList<TitleBlockTemplateLocation> locations;
101  foreach (QString template_name, templates()) {
102  locations << location(template_name);
103  }
104  return(locations);
105 }
106 
114  project_(project)
115 {
117 }
118 
123 }
124 
129  if (!title_.isEmpty()) return(title_);
130 
131  // if the title attribute is empty, we generate a suitable one using the
132  // parent project
133  QString final_title;
134  if (project_) {
135  QString project_title = project_ -> title();
136  if (project_title.isEmpty()) {
137  final_title = QString(
138  tr(
139  "Cartouches du projet sans titre (id %1)",
140  "collection title when the parent project has an empty title -- %1 is the project internal id"
141  )
142  );
143  final_title = final_title.arg(QETApp::projectId(project_));
144  } else {
145  final_title = QString(
146  tr(
147  "Cartouches du projet \"%1\"",
148  "collection title when the project has a suitable title -- %1 is the project title"
149  )
150  );
151  final_title = final_title.arg(project_title);
152  }
153  }
154  return(final_title);
155 }
156 
161  if (project_) {
162  int project_id = QETApp::projectId(project_);
163  if (project_id != -1) {
164  return(QString("project%1+embedtbt").arg(project_id));
165  }
166  }
167  // fall back on the parent method
169 }
170 
175  return(project_);
176 }
177 
182  return(titleblock_templates_xml_.keys());
183 }
184 
191  // Do we have already loaded this template?
192  if (titleblock_templates_.contains(template_name)) {
193  return(titleblock_templates_[template_name]);
194  }
195 
196  // No? Do we even know of it?
197  if (!titleblock_templates_xml_.contains(template_name)) {
198  return(nullptr);
199  }
200 
201  // Ok, we have its XML description, we have to generate a TitleBlockTemplate object
202  TitleBlockTemplate *titleblock_template = new TitleBlockTemplate(this);
203  if (titleblock_template -> loadFromXmlElement(titleblock_templates_xml_[template_name])) {
204  titleblock_templates_.insert(template_name, titleblock_template);
205  return(titleblock_template);
206  } else {
207  return(nullptr);
208  }
209 }
210 
216 QDomElement TitleBlockTemplatesProjectCollection::getTemplateXmlDescription(const QString &template_name) {
217  if (titleblock_templates_xml_.contains(template_name)) {
218  return(titleblock_templates_xml_[template_name]);
219  }
220  return(QDomElement());
221 }
222 
234 bool TitleBlockTemplatesProjectCollection::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_elmt) {
235  // check basic stuff
236  if (xml_elmt.tagName() != "titleblocktemplate") {
237  return(false);
238  }
239 
240  // we *require* a project (at least for the moment...)
241  if (!project_) return(false);
242 
243  // we import the provided XML element in the project document
244  QDomElement import = xml_document_.importNode(xml_elmt, true).toElement();
245 
246  // ensure the name stored in the XML description remains consistent with the provided template name
247  import.setAttribute("name", template_name);
248 
249  // we either replace the previous description
250  if (titleblock_templates_xml_.contains(template_name)) {
251  QDomElement old_description = titleblock_templates_xml_[template_name];
252  if (!old_description.parentNode().isNull()) {
253  old_description.parentNode().replaceChild(import, old_description);
254  }
255  }
256  titleblock_templates_xml_.insert(template_name, import);
257 
258  if (titleblock_templates_.contains(template_name)) {
259  titleblock_templates_[template_name] -> loadFromXmlElement(titleblock_templates_xml_[template_name]);
260  }
261  emit(changed(this, template_name));
262 
263  return(true);
264 }
265 
271 void TitleBlockTemplatesProjectCollection::removeTemplate(const QString &template_name) {
272  emit(aboutToRemove(this, template_name));
273 
274  // remove the template itself
275  titleblock_templates_xml_.remove(template_name);
276  titleblock_templates_.remove(template_name);
277 
278  // warn the rest of the world that the list of templates embedded within this project has changed
279  emit(changed(this, template_name));
280 }
281 
287  return(TitleBlockTemplateLocation(template_name, this));
288 }
289 
295  return(false);
296 }
297 
303  return(QString());
304 }
305 
311 bool TitleBlockTemplatesProjectCollection::isReadOnly(const QString &template_name) const {
312  Q_UNUSED(template_name)
313  if (project_) {
314  return(project_ -> isReadOnly());
315  }
316  return(false);
317 }
318 
322 void TitleBlockTemplatesProjectCollection::fromXml(const QDomElement &xml_element) {
323  foreach (QDomElement e, QET::findInDomElement(xml_element, "titleblocktemplates", "titleblocktemplate")) {
324  // each titleblock template must have a name
325  if (!e.hasAttribute("name")) continue;
326  QString titleblock_template_name = e.attribute("name");
327 
328  // if several templates have the same name, we keep the first one encountered
329  if (titleblock_templates_xml_.contains(titleblock_template_name)) continue;
330 
331  // we simply store the XML element describing the titleblock template,
332  // without any further analysis for the moment
333  titleblock_templates_xml_.insert(titleblock_template_name, e);
334  }
335 }
336 
341  if (!project_) return;
342 
343  foreach (QString template_name, templates()) {
344  if (!project_ -> usesTitleBlockTemplate(location(template_name))) {
345  removeTemplate(template_name);
346  }
347  }
348 }
349 
357  dir_(
358  path,
359  QString("*%1").arg(TITLEBLOCKS_FILE_EXTENSION),
360  QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
361  QDir::Readable | QDir::Files
362  )
363 {
364  if (dir_.exists()) {
365  watcher_.addPath(dir_.canonicalPath());
366  }
367  connect(&watcher_, SIGNAL(directoryChanged(const QString &)), this, SLOT(fileSystemChanged(const QString &)));
368 }
369 
374 }
375 
379 QString TitleBlockTemplatesFilesCollection::path(const QString &template_name) const {
380  if (template_name.isEmpty()) {
381  return(dir_.canonicalPath());
382  } else {
383  return(dir_.absoluteFilePath(toFileName(template_name)));
384  }
385 }
386 
391  QStringList templates_names;
392  QRegExp replace_regexp(QString("%1$").arg(TITLEBLOCKS_FILE_EXTENSION));
393  foreach(QString name, dir_.entryList()) {
394  templates_names << name.replace(replace_regexp, "");
395  }
396  return(templates_names);
397 }
398 
404  if (!templates().contains(template_name)) return(nullptr);
405 
406  TitleBlockTemplate *tbtemplate = new TitleBlockTemplate();
407  QString tbt_file_path = path(template_name);
408 
409  bool loading = tbtemplate -> loadFromXmlFile(tbt_file_path);
410  if (!loading) {
411  delete tbtemplate;
412  return(nullptr);
413  }
414  return(tbtemplate);
415 }
416 
421 QDomElement TitleBlockTemplatesFilesCollection::getTemplateXmlDescription(const QString &template_name) {
422  QString xml_file_path = path(template_name);
423 
424  QFileInfo xml_file_info(xml_file_path);
425  if (!xml_file_info.exists() || !xml_file_info.isReadable()) {
426  return(QDomElement());
427  }
428 
429  QFile xml_file(xml_file_path);
430  if (!xml_file.open(QIODevice::ReadOnly)) {
431  return(QDomElement());
432  }
433 
434  QDomDocument *xml_document = new QDomDocument();
435  bool xml_parsing = xml_document -> setContent(&xml_file);
436  if (!xml_parsing) {
437  delete xml_document;
438  return(QDomElement());
439  }
440  return(xml_document -> documentElement());
441 }
442 
448 bool TitleBlockTemplatesFilesCollection::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_element) {
449  if (template_name.isEmpty()) return(false);
450 
451  // prevent the watcher from emitting signals while we open and write to file
452  blockSignals(true);
453 
454  QDomDocument doc;
455  doc.appendChild(doc.importNode(xml_element, true));
456 
457  bool writing = QET::writeXmlFile(doc, path(template_name));
458  if (!writing) return(false);
459 
460  // emit a single signal for the change
461  blockSignals(false);
462  emit(changed(this, template_name));
463  return(true);
464 }
465 
469 void TitleBlockTemplatesFilesCollection::removeTemplate(const QString &template_name) {
470  emit(aboutToRemove(this, template_name));
471  // prevent the watcher from emitting signals while we open and write to file
472  blockSignals(true);
473 
474  dir_.remove(toFileName(template_name));
475 
476  // emit a single signal for the removal
477  blockSignals(false);
478  emit(changed(this, template_name));
479 }
480 
487  return(TitleBlockTemplateLocation(template_name, this));
488 }
489 
495  return(true);
496 }
497 
502  return(dir_.canonicalPath());
503 }
504 
510 bool TitleBlockTemplatesFilesCollection::isReadOnly(const QString &template_name) const {
511  if (template_name.isEmpty()) {
512  QFileInfo info(dir_.canonicalPath());
513  return(!info.isWritable());
514  } else {
515  QFileInfo info(dir_.absoluteFilePath(toFileName(template_name)));
516  return(!info.isWritable());
517  }
518 }
519 
524 QString TitleBlockTemplatesFilesCollection::toTemplateName(const QString &file_name) {
525  static QRegExp replace_regexp(QString("%1$").arg(TITLEBLOCKS_FILE_EXTENSION));
526  QString template_name(file_name);
527  return(template_name.replace(replace_regexp, ""));
528 }
529 
534 QString TitleBlockTemplatesFilesCollection::toFileName(const QString &template_name) {
535  return(QString("%1%2").arg(template_name).arg(TITLEBLOCKS_FILE_EXTENSION));
536 }
537 
543  Q_UNUSED(str);
544  dir_.refresh();
545  emit(changed(this));
546 }
virtual void setProtocol(const QString &)
virtual QETProject * parentProject()
QHash< QString, TitleBlockTemplate * > titleblock_templates_
Already parsed embedded titleblock templates.
void changed(TitleBlockTemplatesCollection *, const QString &=QString())
From an embedded collection (a project for exemple)
Definition: qet.h:153
QString protocol_
Protocol used to designate this collection.
TitleBlockTemplatesFilesCollection(const QString &, QObject *=nullptr)
void removeTemplate(const QString &) override
void fileSystemChanged(const QString &str)
QFileSystemWatcher watcher_
File System Watcher object to track the files changes made outside the application.
static QString toFileName(const QString &)
virtual QString protocol() const
QETProject * project_
Parent project.
virtual QStringList templates()=0
TitleBlockTemplateLocation location(const QString &=QString()) override
QDomDocument xml_document_
Parent QDomDocument for stored QDomElements.
void removeTemplate(const QString &) override
QetCollection
Enum used to specify the origin of a collection of thing (title block, element etc...)
Definition: qet.h:150
static int projectId(const QETProject *)
Definition: qetapp.cpp:2002
void aboutToRemove(TitleBlockTemplatesCollection *, const QString &)
TitleBlockTemplateLocation location(const QString &=QString()) override
TitleBlockTemplatesCollection(QObject *parent)
static QString toTemplateName(const QString &)
virtual void setCollection(QET::QetCollection)
TitleBlockTemplatesCollection::setCollection Set the storage of this collection.
QDomElement getTemplateXmlDescription(const QString &) override
virtual QET::QetCollection collection() const
TitleBlockTemplatesCollection::collection.
QList< QDomElement > findInDomElement(const QDomElement &, const QString &)
Definition: qet.cpp:300
virtual void setTitle(const QString &)
QIcon tr
Definition: qeticons.cpp:204
bool writeXmlFile(QDomDocument &xml_doc, const QString &filepath, QString *error_message=nullptr)
Definition: qet.cpp:544
virtual TitleBlockTemplateLocation location(const QString &=QString())=0
TitleBlockTemplate * getTemplate(const QString &) override
QString title_
Human-readable title for this collection.
QHash< QString, QDomElement > titleblock_templates_xml_
XML descriptions of embedded titleblock templates.
TitleBlockTemplate * getTemplate(const QString &) override
#define TITLEBLOCKS_FILE_EXTENSION
bool setTemplateXmlDescription(const QString &, const QDomElement &) override
QString path(const QString &=QString()) const
QDir dir_
Collection real directory.
virtual QList< TitleBlockTemplateLocation > templatesLocations()
QDomElement getTemplateXmlDescription(const QString &) override
bool isReadOnly(const QString &=QString()) const override
bool isReadOnly(const QString &=QString()) const override
bool setTemplateXmlDescription(const QString &, const QDomElement &) override
TitleBlockTemplatesProjectCollection(QETProject *, QObject *parent=nullptr)
virtual void fromXml(const QDomElement &)