Files
qelectrotech-source-mirror/sources/ElementsCollection/xmlprojectelementcollectionitem.cpp
T
ispyisail 3a45625d69 Fix bugtracker #95: collections pane shows "Untitled project" for a titleless project
The root of a project's embedded collection showed "Projet sans titre"
whenever the project had no title, while the project panel shows the
file name. Fall back to the file name the same way, and only use
"Projet sans titre" for a project that has neither.

The name was also computed once, so changing the project title or saving
it under a new name left the pane stale until the collections were
reloaded. Update it on projectTitleChanged and projectFilePathChanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:24:17 +12:00

311 lines
8.6 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 "xmlprojectelementcollectionitem.h"
#include "../qeticons.h"
#include "../qetproject.h"
#include "xmlelementcollection.h"
#include <QFileInfo>
/**
@brief XmlProjectElementCollectionItem::XmlProjectElementCollectionItem
Constructor
*/
XmlProjectElementCollectionItem::XmlProjectElementCollectionItem()
{}
/**
@brief XmlProjectElementCollectionItem::isDir
@return true if this item represent a directory
*/
bool XmlProjectElementCollectionItem::isDir() const
{
if (m_dom_element.tagName() == "category") return true;
else return false;
}
/**
@brief XmlProjectElementCollectionItem::isElement
@return true if this item represent an element
*/
bool XmlProjectElementCollectionItem::isElement() const
{
if (m_dom_element.tagName() == "element") return true;
else return false;
}
/**
@brief XmlProjectElementCollectionItem::localName
@return the located name of this item
*/
QString XmlProjectElementCollectionItem::localName()
{
if (!text().isNull())
return text();
if (isCollectionRoot()) {
updateProjectName();
}
else {
ElementsLocation location (embeddedPath(), m_project);
setText(location.name());
}
return text();
}
/**
@brief XmlProjectElementCollectionItem::updateProjectName
Set the displayed name of the collection root from the project :
its title, or its file name when it has no title, like the project panel.
Does nothing if this item is not the root of the collection.
*/
void XmlProjectElementCollectionItem::updateProjectName()
{
if (!isCollectionRoot() || !m_project)
return;
if (!m_project->title().isEmpty())
setText(m_project->title());
else if (!m_project->filePath().isEmpty())
setText(QFileInfo(m_project->filePath()).completeBaseName());
else
setText(QObject::tr("Projet sans titre"));
}
/**
@brief XmlProjectElementCollectionItem::name
@return The collection name of this item
*/
QString XmlProjectElementCollectionItem::name() const
{
return m_dom_element.attribute("name");
}
/**
@brief XmlProjectElementCollectionItem::collectionPath
@return The path of this item relative to the collection.
*/
QString XmlProjectElementCollectionItem::collectionPath() const
{
ElementsLocation loc (embeddedPath(), m_project);
QString p = loc.projectCollectionPath();
if (p.isEmpty())
p = QObject::tr("Collection");
return p;
}
/**
@brief XmlProjectElementCollectionItem::embeddedPath
@return The embedde path of this item
The path is in form : embed://dir/subdir/myElement.elmt
*/
QString XmlProjectElementCollectionItem::embeddedPath() const
{
if (isCollectionRoot())
return "embed://";
else if (parent()){
XmlProjectElementCollectionItem *xpeci = static_cast<XmlProjectElementCollectionItem *>(parent());
if (xpeci->isCollectionRoot())
return xpeci->embeddedPath() + name();
else
return xpeci->embeddedPath() % "/" % name();
}
else
return QString();
}
/**
@brief XmlProjectElementCollectionItem::isCollectionRoot
@return true if this item represent the root of collection
*/
bool XmlProjectElementCollectionItem::isCollectionRoot() const
{
if (!parent())
return true;
else if (parent()->type() != XmlProjectElementCollectionItem::Type)
return true;
else
return false;
}
/**
@brief XmlProjectElementCollectionItem::addChildAtPath
Ask to this item item to add a new child with collection name collection_name
(the child must exist in the xml element collection)
@param collection_name : name of the child item to add.
*/
void XmlProjectElementCollectionItem::addChildAtPath(
const QString &collection_name)
{
if (collection_name.isEmpty())
return;
QString str (collection_name.endsWith(".elmt")? "element" : "category");
QDomElement child_element = m_dom_element.firstChildElement(str);
while (!child_element.isNull()) {
if (child_element.attribute("name") == collection_name) {
XmlProjectElementCollectionItem *xpeci = new XmlProjectElementCollectionItem ();
insertRow(rowForInsertItem(collection_name), xpeci);
xpeci->setXmlElement(child_element, m_project);
xpeci->setUpData();
return;
}
else
child_element = child_element.nextSiblingElement(str);
}
}
/**
@brief XmlProjectElementCollectionItem::project
@return the paretn project of the managed collection
*/
QETProject *XmlProjectElementCollectionItem::project() const
{
return m_project;
}
/**
@brief XmlProjectElementCollectionItem::setProject
Set the project for this item.
Use this method for set this item the root of the collection
@param project : project to manage the collection
@param set_data : if true, call setUpData for every child of this item
@param hide_element : bool
*/
void XmlProjectElementCollectionItem::setProject(QETProject *project,
bool set_data,
bool hide_element)
{
if (m_project)
return;
m_project = project;
m_dom_element = project->embeddedElementCollection()->root();
populate(set_data, hide_element);
}
/**
@brief XmlProjectElementCollectionItem::setUpData
SetUp the data of this item
*/
void XmlProjectElementCollectionItem::setUpData()
{
//Setup the displayed name
localName();
if (isDir()) {
setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
}
else
{
setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
//Set the local name and all informations of the element
//in the data Qt::UserRole+1, these data will be use for search.
ElementsLocation location(embeddedPath(), m_project);
DiagramContext context = location.elementInformations();
QStringList search_list;
for (QString key : context.keys()) {
search_list.append(context.value(key).toString());
}
search_list.append(localName());
setData(search_list.join(" "));
}
setToolTip(collectionPath());
}
/**
@brief XmlProjectElementCollectionItem::setUpIcon
SetUp the icon of this item.
Because icon use several memory, we use this method for setup icon instead setUpData.
*/
void XmlProjectElementCollectionItem::setUpIcon()
{
if (!icon().isNull())
return;
if (isCollectionRoot())
setIcon(QET::Icons::ProjectFileGP);
else if (isDir())
setIcon(QET::Icons::Folder);
else {
ElementsLocation loc(embeddedPath(), m_project);
setIcon(loc.icon());
}
}
/**
@brief XmlProjectElementCollectionItem::populate
Create the childs of this item
@param set_data : if true, call setUpData for every child of this item
@param hide_element : bool
*/
void XmlProjectElementCollectionItem::populate(bool set_data, bool hide_element)
{
QList <QDomElement> dom_category = m_project->embeddedElementCollection()->directories(m_dom_element);
std::sort(dom_category.begin(), dom_category.end(), [](QDomElement a, QDomElement b){return (a.attribute("name") < b.attribute("name"));});
foreach (QDomElement element, dom_category)
{
XmlProjectElementCollectionItem *xpeci = new XmlProjectElementCollectionItem();
appendRow(xpeci);
xpeci->setXmlElement(element, m_project, set_data, hide_element);
if (set_data)
xpeci->setUpData();
}
if (hide_element)
return;
QList <QDomElement> dom_elements = m_project->embeddedElementCollection()->elements(m_dom_element);
std::sort(dom_elements.begin(), dom_elements.end(), [](QDomElement a, QDomElement b){return (a.attribute("name") < b.attribute("name"));});
foreach (QDomElement element, dom_elements)
{
XmlProjectElementCollectionItem *xpeci = new XmlProjectElementCollectionItem();
appendRow(xpeci);
xpeci->setXmlElement(element, m_project, set_data);
if (set_data)
xpeci->setUpData();
}
}
/**
@brief XmlProjectElementCollectionItem::setXmlElement
Set the managed content of this item
@param element :
the dom element (directory or element), to be managed by this item
@param project : the parent project of managed collection
@param set_data : if true, call setUpData for every child of this item
@param hide_element : bool
*/
void XmlProjectElementCollectionItem::setXmlElement(const QDomElement& element,
QETProject *project,
bool set_data,
bool hide_element)
{
m_dom_element = element;
m_project = project;
populate(set_data, hide_element);
}