mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-15 10:04:13 +02:00
Change a wire's properties by uuid without building its folios (stage D5)
Scripts get conductorPropertyByUuid() and setConductorPropertyByUuid(), the wire named by its uuid (conductorUuids()) rather than by a symbol's terminal. A change goes to every wire at the wire's potential, as setConductorProperty() does. When those wires are all on folios not built, none is numbered by a formula, and what changes in each is what a .qetz database holds in its own columns (number, function, voltage, colour and section of the wire, cable, bus), it goes through the project database: the store and the conductor rows, undoable by uuid. The potential is followed in the database (projectDataBase::potentialWires(): through wire ends, folio reports and terminal blocks, as Conductor::relatedPotentialConductors() follows it; a terminal block that isolates its terminals answers nothing). Building a wire takes its change (Conductor::fromXml()); a .qetz save writes it in the database, the folio file copied; a folio written from its XML gets it there; a .qet builds. Anything else builds the folio, as before. tst_lazyfolios: every wire's potential from the database = as followed, 1 342 of 1 342 (industrial, eager and from a .qetz); a cable set by uuid on a 14-wire potential builds no folio, reaches every wire, saves as when built, undoes, shows once built (fails when building ignores the change, and when the .qetz writer does). The test's run limit is raised (500 s -> 1 500 s, ctest 1 800 s): under load it ran past 500 s. ctest 96/96 both ways. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1317,6 +1317,77 @@ QString projectDataBase::terminalName(const QUuid &terminal, const QUuid &elemen
|
||||
return query.exec() && query.next() ? query.value(0).toString() : QString();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::potentialWires
|
||||
@return the wires at the potential of @p wire, @p wire included, read
|
||||
from the conductor, element and link tables as they are (see
|
||||
elementTypesOnFolios()), followed as Conductor::relatedPotentialConductors()
|
||||
follows them over every folio: through a wire's ends, from a folio
|
||||
report to the terminals of the first symbol it is linked to, and from a
|
||||
terminal block's terminal to its others. Nothing when a terminal block
|
||||
on the way isolates its terminals (their groups are in its definition,
|
||||
not in the database) or @p wire has no row.
|
||||
*/
|
||||
std::optional<QSet<QUuid>> projectDataBase::potentialWires(const QUuid &wire) const
|
||||
{
|
||||
using Node = std::pair<QString, QString>; //element uuid, terminal uuid
|
||||
QHash<QString, std::pair<Node, Node>> ends;
|
||||
QHash<Node, QStringList> wires_at;
|
||||
QHash<QString, QList<Node>> nodes_of;
|
||||
{
|
||||
QSqlQuery query(m_data_base);
|
||||
query.exec(QStringLiteral("SELECT uuid, terminal1_element_uuid, terminal1_uuid, "
|
||||
"terminal2_element_uuid, terminal2_uuid FROM conductor"));
|
||||
while (query.next()) {
|
||||
const Node a{query.value(1).toString(), query.value(2).toString()};
|
||||
const Node b{query.value(3).toString(), query.value(4).toString()};
|
||||
const QString uuid = query.value(0).toString();
|
||||
ends.insert(uuid, {a, b});
|
||||
for (const Node &n : {a, b}) {
|
||||
wires_at[n] << uuid;
|
||||
if (!nodes_of.value(n.first).contains(n)) nodes_of[n.first] << n;
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto start = ends.constFind(wire.toString());
|
||||
if (start == ends.constEnd()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
QHash<QString, ElementData::Type> kinds;
|
||||
{
|
||||
QSqlQuery query(m_data_base);
|
||||
query.exec(QStringLiteral("SELECT uuid, type FROM element"));
|
||||
while (query.next())
|
||||
kinds.insert(query.value(0).toString(), ElementData::typeFromString(query.value(1).toString()));
|
||||
}
|
||||
QSet<QUuid> wires;
|
||||
QSet<Node> seen;
|
||||
QList<Node> todo{start->first, start->second};
|
||||
while (!todo.isEmpty()) {
|
||||
const Node node = todo.takeLast();
|
||||
if (seen.contains(node)) continue;
|
||||
seen.insert(node);
|
||||
for (const QString &w : wires_at.value(node)) {
|
||||
if (wires.contains(QUuid(w))) continue;
|
||||
wires.insert(QUuid(w));
|
||||
const auto e = ends.value(w);
|
||||
todo << e.first << e.second;
|
||||
}
|
||||
const ElementData::Type kind = kinds.value(node.first, ElementData::Simple);
|
||||
if (kind & ElementData::AllReport) {
|
||||
const QList<QUuid> partners = linkedSymbols(QUuid(node.first));
|
||||
if (!partners.isEmpty())
|
||||
todo << nodes_of.value(partners.first().toString());
|
||||
} else if (kind & ElementData::Terminal) {
|
||||
if (QET::infoFlagIsTrue(m_element_information.value(QUuid(node.first))
|
||||
.value(QStringLiteral("potential_isolating")).toString()))
|
||||
return std::nullopt;
|
||||
todo << nodes_of.value(node.first);
|
||||
}
|
||||
}
|
||||
return wires;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::linkedSymbols
|
||||
@return the symbols @p element is linked to, read from the link table
|
||||
@@ -1467,9 +1538,111 @@ QSet<QUuid> projectDataBase::foliosWithUnbuiltEdits() const
|
||||
{
|
||||
QSet<QUuid> folios;
|
||||
for (const auto &edit : m_unbuilt_edits) folios.insert(edit.folio);
|
||||
for (const auto &edit : m_unbuilt_wire_edits) folios.insert(edit.folio);
|
||||
return folios;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::unbuiltWire
|
||||
@return true if the wire @p wire is on a folio not built (lazy folios):
|
||||
it has a row and its properties are stored, and no wire built holds its
|
||||
uuid. @p folio is set to its folio.
|
||||
*/
|
||||
bool projectDataBase::unbuiltWire(const QUuid &wire, QUuid *folio) const
|
||||
{
|
||||
if (placedConductorCount(wire) != 0 || !hasConductorProperties(wire)) {
|
||||
return false;
|
||||
}
|
||||
QSqlQuery query(m_data_base);
|
||||
query.prepare(QStringLiteral("SELECT diagram_uuid FROM conductor WHERE uuid = :uuid"));
|
||||
query.bindValue(QStringLiteral(":uuid"), wire.toString());
|
||||
if (!query.exec() || !query.next()) {
|
||||
return false;
|
||||
}
|
||||
if (folio) *folio = QUuid(query.value(0).toString());
|
||||
return !query.next();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::editUnbuiltConductorProperties
|
||||
Give the wire @p wire, on a folio not built (unbuiltWire()), the
|
||||
properties @p properties as Conductor::setProperties() would: the store,
|
||||
its rows and its conductor row's text. Building it takes them
|
||||
(takeUnbuiltWireEdit()); a .qetz saves them in its database (QETProject::
|
||||
toXml()), anything else builds its folio to save.
|
||||
*/
|
||||
void projectDataBase::editUnbuiltConductorProperties(const QUuid &wire, const ConductorProperties &properties)
|
||||
{
|
||||
QUuid folio;
|
||||
if (!unbuiltWire(wire, &folio)) {
|
||||
return;
|
||||
}
|
||||
m_unbuilt_wire_edits.insert(wire, {properties, folio});
|
||||
if (!storeConductorProperties(wire, properties)) {
|
||||
return;
|
||||
}
|
||||
m_content_changed = true;
|
||||
if (!m_update_blocked) {
|
||||
m_update_conductor_query.bindValue(QStringLiteral(":uuid"), wire.toString());
|
||||
m_update_conductor_query.bindValue(QStringLiteral(":text"), properties.text);
|
||||
if (!m_update_conductor_query.exec()) {
|
||||
qDebug() << "projectDataBase::editUnbuiltConductorProperties update error : " << m_update_conductor_query.lastError();
|
||||
}
|
||||
}
|
||||
emit dataBaseUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::takeUnbuiltWireEdit
|
||||
@return the properties @p wire was given while its folio was not built,
|
||||
forgotten here: the wire being built takes them
|
||||
*/
|
||||
std::optional<ConductorProperties> projectDataBase::takeUnbuiltWireEdit(const QUuid &wire)
|
||||
{
|
||||
const auto edit = m_unbuilt_wire_edits.constFind(wire);
|
||||
if (edit == m_unbuilt_wire_edits.constEnd()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const ConductorProperties properties = edit->properties;
|
||||
m_unbuilt_wire_edits.erase(edit);
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::unbuiltWireEditsOnFolio
|
||||
@return the properties given to the wires of the folio @p folio while it
|
||||
was not built, by wire
|
||||
*/
|
||||
QHash<QUuid, ConductorProperties> projectDataBase::unbuiltWireEditsOnFolio(const QUuid &folio) const
|
||||
{
|
||||
QHash<QUuid, ConductorProperties> edits;
|
||||
for (auto it = m_unbuilt_wire_edits.cbegin() ; it != m_unbuilt_wire_edits.cend() ; ++it)
|
||||
if (it->folio == folio) edits.insert(it.key(), it->properties);
|
||||
return edits;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::setPlacedConductorProperties
|
||||
Give the wire @p wire its properties @p properties: through the wire when
|
||||
it is built, through the store when it is not (unbuiltWire()). What
|
||||
undoing and redoing a change of wires not built does, the wires having
|
||||
perhaps been built since.
|
||||
@return false if neither can
|
||||
*/
|
||||
bool projectDataBase::setPlacedConductorProperties(const QUuid &wire, const ConductorProperties &properties)
|
||||
{
|
||||
const QList<QPointer<Conductor>> placed = m_placed_conductors.values(wire);
|
||||
if (placed.size() == 1 && placed.first()) {
|
||||
placed.first()->setProperties(properties);
|
||||
return true;
|
||||
}
|
||||
if (placed.isEmpty() && unbuiltWire(wire)) {
|
||||
editUnbuiltConductorProperties(wire, properties);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief projectDataBase::unbuiltEditsOnFolio
|
||||
@return the information changed through the store of the symbols on the
|
||||
|
||||
Reference in New Issue
Block a user