mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-09-13 20:23:04 +02:00
Segfault on old Qt versions! This reverts commit dba7caed3035585af4b301ed87bd4131dcac994c.
572 lines
16 KiB
C++
572 lines
16 KiB
C++
/*
|
|
Copyright 2006-2025 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();
|
|
bool xml_parsing = xml_document -> setContent(&xml_file);
|
|
if (!xml_parsing) {
|
|
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));
|
|
}
|