mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-07-30 07:44:13 +02:00
287b532953
Since Qt 6.5, QDomDocument::setContent() returns a ParseResult struct with an *explicit* operator bool(), so 'bool x = doc.setContent(...)' (copy-initialization) no longer compiles - explicit conversions aren't considered there. This exact issue was already fixed in titleblocktemplate.cpp by dropping the intermediate bool and testing the call directly in the if condition (contextual bool conversion in an if() is fine even for an explicit operator bool), but this second occurrence in templatescollection.cpp used the same pattern and was missed. Applying the same fix here for consistency.
571 lines
16 KiB
C++
571 lines
16 KiB
C++
/*
|
|
Copyright 2006-2026 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 "templatescollection.h"
|
|
|
|
#include "../qetapp.h"
|
|
#include "../qetproject.h"
|
|
#include "../titleblocktemplate.h"
|
|
|
|
#include <QRegularExpression>
|
|
|
|
/**
|
|
Constructor
|
|
@param parent Parent QObject
|
|
*/
|
|
TitleBlockTemplatesCollection::TitleBlockTemplatesCollection(QObject *parent) :
|
|
QObject(parent),
|
|
protocol_("unknown")
|
|
{
|
|
}
|
|
|
|
/**
|
|
Destructor
|
|
*/
|
|
TitleBlockTemplatesCollection::~TitleBlockTemplatesCollection()
|
|
{
|
|
}
|
|
|
|
/**
|
|
@return the title of this collection
|
|
*/
|
|
QString TitleBlockTemplatesCollection::title() const
|
|
{
|
|
return(title_);
|
|
}
|
|
|
|
/**
|
|
@brief TitleBlockTemplatesCollection::setTitle
|
|
@param title : New title for this collection
|
|
*/
|
|
void TitleBlockTemplatesCollection::setTitle(const QString &title) {
|
|
title_ = title;
|
|
}
|
|
|
|
/**
|
|
@return the protocol used by this collection ; examples: commontbt,
|
|
customtbt, embedtbt, ...
|
|
*/
|
|
QString TitleBlockTemplatesCollection::protocol() const
|
|
{
|
|
return(protocol_);
|
|
}
|
|
|
|
/**
|
|
Define the protocol for this collection
|
|
@param protocol New protocol for this collection
|
|
*/
|
|
void TitleBlockTemplatesCollection::setProtocol(const QString &protocol) {
|
|
if (!protocol.isEmpty()) protocol_ = protocol;
|
|
}
|
|
|
|
/**
|
|
@brief TitleBlockTemplatesCollection::collection
|
|
@return the collection where is stored this collection.
|
|
*/
|
|
QET::QetCollection TitleBlockTemplatesCollection::collection() const
|
|
{
|
|
return m_collection;
|
|
}
|
|
|
|
/**
|
|
@brief TitleBlockTemplatesCollection::setCollection
|
|
Set the storage of this collection
|
|
@param c
|
|
*/
|
|
void TitleBlockTemplatesCollection::setCollection(QET::QetCollection c) {
|
|
m_collection = c;
|
|
}
|
|
|
|
/**
|
|
@return the project this collection is affiliated to, or 0 if this
|
|
collection is not related to any project.
|
|
*/
|
|
QETProject *TitleBlockTemplatesCollection::parentProject()
|
|
{
|
|
return(nullptr);
|
|
}
|
|
|
|
/**
|
|
@return the templates contained within this collection, as a list of location
|
|
objects.
|
|
@see templates()
|
|
*/
|
|
QList<TitleBlockTemplateLocation> TitleBlockTemplatesCollection::templatesLocations()
|
|
{
|
|
QList<TitleBlockTemplateLocation> locations;
|
|
foreach (QString template_name, templates()) {
|
|
locations << location(template_name);
|
|
}
|
|
return(locations);
|
|
}
|
|
|
|
/**
|
|
Constructor
|
|
@param project Parent project
|
|
@param parent Parent QObject
|
|
*/
|
|
TitleBlockTemplatesProjectCollection::TitleBlockTemplatesProjectCollection(QETProject *project, QObject *parent) :
|
|
TitleBlockTemplatesCollection(parent),
|
|
project_(project)
|
|
{
|
|
m_collection = QET::QetCollection::Embedded;
|
|
}
|
|
|
|
/**
|
|
Destructor
|
|
*/
|
|
TitleBlockTemplatesProjectCollection::~TitleBlockTemplatesProjectCollection()
|
|
{
|
|
}
|
|
|
|
/**
|
|
@return a human readable title for this collection
|
|
*/
|
|
QString TitleBlockTemplatesProjectCollection::title() const
|
|
{
|
|
if (!title_.isEmpty()) return(title_);
|
|
|
|
// if the title attribute is empty, we generate a suitable one using the
|
|
// parent project
|
|
QString final_title;
|
|
if (project_) {
|
|
QString project_title = project_ -> title();
|
|
if (project_title.isEmpty()) {
|
|
final_title = QString(
|
|
tr(
|
|
"Cartouches du projet sans titre (id %1)",
|
|
"collection title when the parent project has an empty title -- %1 is the project internal id"
|
|
)
|
|
);
|
|
final_title = final_title.arg(QETApp::projectId(project_));
|
|
} else {
|
|
final_title = QString(
|
|
tr(
|
|
"Cartouches du projet \"%1\"",
|
|
"collection title when the project has a suitable title -- %1 is the project title"
|
|
)
|
|
);
|
|
final_title = final_title.arg(project_title);
|
|
}
|
|
}
|
|
return(final_title);
|
|
}
|
|
|
|
/**
|
|
@return the protocol used to mention this collection
|
|
*/
|
|
QString TitleBlockTemplatesProjectCollection::protocol() const
|
|
{
|
|
if (project_) {
|
|
int project_id = QETApp::projectId(project_);
|
|
if (project_id != -1) {
|
|
return(QString("project%1+embedtbt").arg(project_id));
|
|
}
|
|
}
|
|
// fall back on the parent method
|
|
return(TitleBlockTemplatesCollection::protocol());
|
|
}
|
|
|
|
/**
|
|
@return the parent project of this project collection
|
|
*/
|
|
QETProject *TitleBlockTemplatesProjectCollection::parentProject()
|
|
{
|
|
return(project_);
|
|
}
|
|
|
|
/**
|
|
@return the list of title block templates embedded within the project.
|
|
*/
|
|
QStringList TitleBlockTemplatesProjectCollection::templates()
|
|
{
|
|
return(titleblock_templates_xml_.keys());
|
|
}
|
|
|
|
/**
|
|
@param template_name Name of the requested template
|
|
@return the requested template, or 0 if there is no valid template of this
|
|
name within the project
|
|
*/
|
|
TitleBlockTemplate *TitleBlockTemplatesProjectCollection::getTemplate(const QString &template_name){
|
|
// Do we have already loaded this template?
|
|
if (titleblock_templates_.contains(template_name)) {
|
|
return(titleblock_templates_[template_name]);
|
|
}
|
|
|
|
// No? Do we even know of it?
|
|
if (!titleblock_templates_xml_.contains(template_name)) {
|
|
return(nullptr);
|
|
}
|
|
|
|
// Ok, we have its XML description, we have to generate a TitleBlockTemplate object
|
|
TitleBlockTemplate *titleblock_template = new TitleBlockTemplate(this);
|
|
if (titleblock_template -> loadFromXmlElement(titleblock_templates_xml_[template_name])) {
|
|
titleblock_templates_.insert(template_name, titleblock_template);
|
|
return(titleblock_template);
|
|
} else {
|
|
return(nullptr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
@param template_name Name of the requested template
|
|
@return the XML description of the requested template, or a null QDomElement
|
|
if the project does not have such an titleblock template
|
|
*/
|
|
QDomElement TitleBlockTemplatesProjectCollection::getTemplateXmlDescription(const QString &template_name) {
|
|
if (titleblock_templates_xml_.contains(template_name)) {
|
|
return(titleblock_templates_xml_[template_name]);
|
|
}
|
|
return(QDomElement());
|
|
}
|
|
|
|
/**
|
|
This methods allows adding or modifying a template embedded within the
|
|
project. This method emits the signal changed() if
|
|
necessary.
|
|
@param template_name Name / Identifier of the template - will be used to
|
|
determine whether the given description will be added or will replace an
|
|
existing one.
|
|
@param xml_elmt An \<titleblocktemplate\> XML element describing the
|
|
template. Its "name" attribute must equal to template_name.
|
|
@return false if a problem occurred, true otherwise
|
|
*/
|
|
bool TitleBlockTemplatesProjectCollection::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_elmt) {
|
|
// check basic stuff
|
|
if (xml_elmt.tagName() != "titleblocktemplate") {
|
|
return(false);
|
|
}
|
|
|
|
// we *require* a project (at least for the moment...)
|
|
if (!project_) return(false);
|
|
|
|
// we import the provided XML element in the project document
|
|
QDomElement import = xml_document_.importNode(xml_elmt, true).toElement();
|
|
|
|
// ensure the name stored in the XML description remains consistent with the provided template name
|
|
import.setAttribute("name", template_name);
|
|
|
|
// we either replace the previous description
|
|
if (titleblock_templates_xml_.contains(template_name)) {
|
|
QDomElement old_description = titleblock_templates_xml_[template_name];
|
|
if (!old_description.parentNode().isNull()) {
|
|
old_description.parentNode().replaceChild(import, old_description);
|
|
}
|
|
}
|
|
titleblock_templates_xml_.insert(template_name, import);
|
|
|
|
if (titleblock_templates_.contains(template_name)) {
|
|
titleblock_templates_[template_name] -> loadFromXmlElement(titleblock_templates_xml_[template_name]);
|
|
}
|
|
emit(changed(this, template_name));
|
|
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
This methods allows removing a template embedded within the project. This
|
|
method emits the signal changed() if necessary.
|
|
@param template_name Name of the template to be removed
|
|
*/
|
|
void TitleBlockTemplatesProjectCollection::removeTemplate(const QString &template_name) {
|
|
emit(aboutToRemove(this, template_name));
|
|
|
|
// remove the template itself
|
|
titleblock_templates_xml_.remove(template_name);
|
|
titleblock_templates_.remove(template_name);
|
|
|
|
// warn the rest of the world that the list of templates embedded within this project has changed
|
|
emit(changed(this, template_name));
|
|
}
|
|
|
|
/**
|
|
@param template_name Name of the requested template
|
|
@return the location object for the requested template
|
|
*/
|
|
TitleBlockTemplateLocation TitleBlockTemplatesProjectCollection::location(const QString &template_name) {
|
|
return(TitleBlockTemplateLocation(template_name, this));
|
|
}
|
|
|
|
/**
|
|
@return always false since a project collection is not stored on any
|
|
filesystem.
|
|
*/
|
|
bool TitleBlockTemplatesProjectCollection::hasFilePath()
|
|
{
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
@return always an empty string since a project collection is not stored on
|
|
any filesystem.
|
|
*/
|
|
QString TitleBlockTemplatesProjectCollection::filePath()
|
|
{
|
|
return(QString());
|
|
}
|
|
|
|
/**
|
|
@param template_name Either an empty QString to know whether the collection
|
|
itself is read only, or a specific template name.
|
|
@return true if the specified template is read only, false otherwise
|
|
*/
|
|
bool TitleBlockTemplatesProjectCollection::isReadOnly(const QString &template_name) const
|
|
{
|
|
Q_UNUSED(template_name)
|
|
if (project_) {
|
|
return(project_ -> isReadOnly());
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
@param xml_element XML element to be parsed to load title block templates
|
|
*/
|
|
void TitleBlockTemplatesProjectCollection::fromXml(const QDomElement &xml_element) {
|
|
foreach (QDomElement e, QET::findInDomElement(xml_element, "titleblocktemplates", "titleblocktemplate")) {
|
|
// each titleblock template must have a name
|
|
if (!e.hasAttribute("name")) continue;
|
|
QString titleblock_template_name = e.attribute("name");
|
|
|
|
// if several templates have the same name, we keep the first one encountered
|
|
if (titleblock_templates_xml_.contains(titleblock_template_name)) continue;
|
|
|
|
// we simply store the XML element describing the titleblock template,
|
|
// without any further analysis for the moment
|
|
titleblock_templates_xml_.insert(titleblock_template_name, e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Delete all title block templates not used within the parent project
|
|
*/
|
|
void TitleBlockTemplatesProjectCollection::deleteUnusedTitleBlocKTemplates()
|
|
{
|
|
if (!project_) return;
|
|
|
|
foreach (QString template_name, templates()) {
|
|
if (!project_ -> usesTitleBlockTemplate(location(template_name))) {
|
|
removeTemplate(template_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Constructor
|
|
@param path Path of the directory containing the collection
|
|
@param parent Parent QObject
|
|
*/
|
|
TitleBlockTemplatesFilesCollection::TitleBlockTemplatesFilesCollection(const QString &path, QObject *parent) :
|
|
TitleBlockTemplatesCollection(parent),
|
|
dir_(
|
|
path,
|
|
QString("*%1").arg(TITLEBLOCKS_FILE_EXTENSION),
|
|
QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
|
|
QDir::Readable | QDir::Files
|
|
)
|
|
{
|
|
if (dir_.exists()) {
|
|
watcher_.addPath(dir_.canonicalPath());
|
|
}
|
|
connect(&watcher_, SIGNAL(directoryChanged(const QString &)), this, SLOT(fileSystemChanged(const QString &)));
|
|
}
|
|
|
|
/**
|
|
Destructor
|
|
*/
|
|
TitleBlockTemplatesFilesCollection::~TitleBlockTemplatesFilesCollection()
|
|
{
|
|
}
|
|
|
|
/**
|
|
@return the canonical path of the directory hosting this collection.
|
|
*/
|
|
QString TitleBlockTemplatesFilesCollection::path(const QString &template_name) const
|
|
{
|
|
if (template_name.isEmpty()) {
|
|
return(dir_.canonicalPath());
|
|
} else {
|
|
return(dir_.absoluteFilePath(toFileName(template_name)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
@return the list of templates contained in this collection
|
|
*/
|
|
QStringList TitleBlockTemplatesFilesCollection::templates()
|
|
{
|
|
QStringList templates_names;
|
|
QRegularExpression replace_regexp(QString("%1$").arg(TITLEBLOCKS_FILE_EXTENSION));
|
|
foreach(QString name, dir_.entryList()) {
|
|
templates_names << name.replace(replace_regexp, "");
|
|
}
|
|
return(templates_names);
|
|
}
|
|
|
|
/**
|
|
@return the template which name is \a template_name, or 0 if the template
|
|
could not be loaded.
|
|
*/
|
|
TitleBlockTemplate *TitleBlockTemplatesFilesCollection::getTemplate(const QString &template_name) {
|
|
if (!templates().contains(template_name)) return(nullptr);
|
|
|
|
TitleBlockTemplate *tbtemplate = new TitleBlockTemplate();
|
|
QString tbt_file_path = path(template_name);
|
|
|
|
bool loading = tbtemplate -> loadFromXmlFile(tbt_file_path);
|
|
if (!loading) {
|
|
delete tbtemplate;
|
|
return(nullptr);
|
|
}
|
|
return(tbtemplate);
|
|
}
|
|
|
|
/**
|
|
@param template_name Name of a template (which has to already exist)
|
|
@return the XML description for the \a template_name template, or a null QDomElement if no such template exists.
|
|
*/
|
|
QDomElement TitleBlockTemplatesFilesCollection::getTemplateXmlDescription(const QString &template_name) {
|
|
QString xml_file_path = path(template_name);
|
|
|
|
QFileInfo xml_file_info(xml_file_path);
|
|
if (!xml_file_info.exists() || !xml_file_info.isReadable()) {
|
|
return(QDomElement());
|
|
}
|
|
|
|
QFile xml_file(xml_file_path);
|
|
if (!xml_file.open(QIODevice::ReadOnly)) {
|
|
return(QDomElement());
|
|
}
|
|
|
|
QDomDocument *xml_document = new QDomDocument();
|
|
if (!xml_document -> setContent(&xml_file)) {
|
|
delete xml_document;
|
|
return(QDomElement());
|
|
}
|
|
return(xml_document -> documentElement());
|
|
}
|
|
|
|
/**
|
|
Set the XML description of the \a template_name template to \a xml_element.
|
|
@param template_name Name of a template (which does not have to already exist)
|
|
@param xml_element XML element describing the template
|
|
*/
|
|
bool TitleBlockTemplatesFilesCollection::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_element) {
|
|
if (template_name.isEmpty()) return(false);
|
|
|
|
// prevent the watcher from emitting signals while we open and write to file
|
|
blockSignals(true);
|
|
|
|
QDomDocument doc;
|
|
doc.appendChild(doc.importNode(xml_element, true));
|
|
|
|
bool writing = QET::writeXmlFile(doc, path(template_name));
|
|
if (!writing) return(false);
|
|
|
|
// emit a single signal for the change
|
|
blockSignals(false);
|
|
emit(changed(this, template_name));
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
Remove the \a template_name template.
|
|
*/
|
|
void TitleBlockTemplatesFilesCollection::removeTemplate(const QString &template_name) {
|
|
emit(aboutToRemove(this, template_name));
|
|
// prevent the watcher from emitting signals while we open and write to file
|
|
blockSignals(true);
|
|
|
|
dir_.remove(toFileName(template_name));
|
|
|
|
// emit a single signal for the removal
|
|
blockSignals(false);
|
|
emit(changed(this, template_name));
|
|
}
|
|
|
|
/**
|
|
@param template_name Name of a template supposed to be contained within
|
|
this collection.
|
|
@return
|
|
*/
|
|
TitleBlockTemplateLocation TitleBlockTemplatesFilesCollection::location(const QString &template_name) {
|
|
return(TitleBlockTemplateLocation(template_name, this));
|
|
}
|
|
|
|
/**
|
|
@return always true since a files collection is always stored on a
|
|
filesystem.
|
|
*/
|
|
bool TitleBlockTemplatesFilesCollection::hasFilePath()
|
|
{
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
@return The filesystem path where this files collection is actually stored.
|
|
*/
|
|
QString TitleBlockTemplatesFilesCollection::filePath()
|
|
{
|
|
return(dir_.canonicalPath());
|
|
}
|
|
|
|
/**
|
|
@param template_name Either an empty QString to know whether the collection
|
|
itself is read only, or a specific template name.
|
|
@return true if the specified template is read only, false otherwise
|
|
*/
|
|
bool TitleBlockTemplatesFilesCollection::isReadOnly(const QString &template_name) const
|
|
{
|
|
if (template_name.isEmpty()) {
|
|
QFileInfo info(dir_.canonicalPath());
|
|
return(!info.isWritable());
|
|
} else {
|
|
QFileInfo info(dir_.absoluteFilePath(toFileName(template_name)));
|
|
return(!info.isWritable());
|
|
}
|
|
}
|
|
|
|
/**
|
|
@param file_name A file name
|
|
@return the template name for \a file_name
|
|
*/
|
|
QString TitleBlockTemplatesFilesCollection::toTemplateName(const QString &file_name) {
|
|
static QRegularExpression replace_regexp(QString("%1$").arg(TITLEBLOCKS_FILE_EXTENSION));
|
|
QString template_name(file_name);
|
|
return(template_name.replace(replace_regexp, ""));
|
|
}
|
|
|
|
/**
|
|
@param template_name A template name
|
|
@return the file name for \a template_name
|
|
*/
|
|
QString TitleBlockTemplatesFilesCollection::toFileName(const QString &template_name) {
|
|
return(QString("%1%2").arg(template_name).arg(TITLEBLOCKS_FILE_EXTENSION));
|
|
}
|
|
|
|
/**
|
|
Handle the changes occurring on the file system.
|
|
@param str Path of the directory that changed.
|
|
*/
|
|
void TitleBlockTemplatesFilesCollection::fileSystemChanged(const QString &str) {
|
|
Q_UNUSED(str);
|
|
dir_.refresh();
|
|
emit(changed(this));
|
|
}
|