From 8eb2024bb197defc496bfcbc52000940cd9eab82 Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Sun, 4 Oct 2026 01:04:44 +0200 Subject: [PATCH] Fix jump to element search. --- .../autoNum/elementautonumschemecommand.cpp | 46 +++++++++++++++---- sources/autoNum/elementautonumschemecommand.h | 1 + sources/diagramcommands.cpp | 2 +- sources/qetproject.cpp | 5 +- sources/ui/jumptoelementdialog.cpp | 5 ++ tests/qttest/CMakeLists.txt | 12 ----- tests/qttest/tst_elementautonumids.cpp | 33 +++++++++++++ tests/qttest/tst_resaveunchanged.cpp | 3 -- 8 files changed, 81 insertions(+), 26 deletions(-) diff --git a/sources/autoNum/elementautonumschemecommand.cpp b/sources/autoNum/elementautonumschemecommand.cpp index 9e7ffd518..11a4dd1a3 100644 --- a/sources/autoNum/elementautonumschemecommand.cpp +++ b/sources/autoNum/elementautonumschemecommand.cpp @@ -861,6 +861,31 @@ QString ElementAutoNumSchemeCommand::schemeForFormula(const QETProject *project, return matches.first(); } +/** + @brief ElementAutoNumSchemeCommand::followedScheme + @return the title of the scheme of @p project which an element with the + information @p info follows, empty if none. + + The id names it, but only counts when the scheme has the formula the + element has: an id which comes from another project (a copy of the + project edited since, two projects which both have a numbering of the + same name...) may name a scheme here which is not the same numbering. +*/ +QString ElementAutoNumSchemeCommand::followedScheme(const QETProject *project, + const DiagramContext &info) +{ + if (!project) { + return QString(); + } + const QString title = project->elementAutoNumTitle( + QUuid(info.value(QETInformation::ELMT_FORMULA_ID).toString())); + if (title.isEmpty() + || project->elementAutoNumFormula(title) != info.value(QETInformation::ELMT_FORMULA).toString()) { + return QString(); + } + return title; +} + /** @brief ElementAutoNumSchemeCommand::writeCopiedSchemes Add to the copy @p root the definition of every element numbering scheme @@ -944,9 +969,13 @@ QList ElementAutoNumSchemeCommand::missingF } for (const Scheme &scheme : copied) { - if (!followed.contains(scheme.id) - || !project->elementAutoNumTitle(scheme.id).isEmpty() - || !schemeForFormula(project, autonum::numerotationContextToFormula(scheme.context)).isEmpty()) { + const QString formula = autonum::numerotationContextToFormula(scheme.context); + const QString by_id = project->elementAutoNumTitle(scheme.id); + //Present: under its id with the same formula, or under another id + //(another name, other project) with the same formula + const bool present = (!by_id.isEmpty() && project->elementAutoNumFormula(by_id) == formula) + || !schemeForFormula(project, formula).isEmpty(); + if (!followed.contains(scheme.id) || present) { continue; } missing << scheme; @@ -984,8 +1013,7 @@ QMap> ElementAutoNumSchemeCommand::pastedSchemes( if (formula.isEmpty()) { continue; } - QString title = project->elementAutoNumTitle( - QUuid(info.value(QETInformation::ELMT_FORMULA_ID).toString())); + QString title = followedScheme(project, info); if (title.isEmpty()) { title = schemeForFormula(project, formula); } @@ -1000,8 +1028,9 @@ QMap> ElementAutoNumSchemeCommand::pastedSchemes( @brief ElementAutoNumSchemeCommand::linkPasted Make the formula_id of pasted @p elements name a scheme of @p project, as QETProject does for the elements of a file it loads: an id which - names one is kept; otherwise the scheme with the element's formula (see - schemeForFormula()), else none. Labels are not touched. + names one with the element's formula is kept (see followedScheme()); + otherwise the scheme with the element's formula (see schemeForFormula()), + else none. Labels are not touched. */ void ElementAutoNumSchemeCommand::linkPasted(const QETProject *project, const QList &elements) @@ -1020,8 +1049,7 @@ void ElementAutoNumSchemeCommand::linkPasted(const QETProject *project, } continue; } - const QUuid id(info.value(QETInformation::ELMT_FORMULA_ID).toString()); - if (!project->elementAutoNumTitle(id).isEmpty()) { + if (!followedScheme(project, info).isEmpty()) { continue; } const QString title = schemeForFormula(project, formula); diff --git a/sources/autoNum/elementautonumschemecommand.h b/sources/autoNum/elementautonumschemecommand.h index 8ca0c1baa..c0a69838c 100644 --- a/sources/autoNum/elementautonumschemecommand.h +++ b/sources/autoNum/elementautonumschemecommand.h @@ -166,6 +166,7 @@ class ElementAutoNumSchemeCommand : public QUndoCommand QUndoCommand *parent = nullptr); static QString schemeForFormula(const QETProject *project, const QString &formula); + static QString followedScheme(const QETProject *project, const DiagramContext &info); static void writeCopiedSchemes(QDomDocument &document, QDomElement &root, const QETProject *project, diff --git a/sources/diagramcommands.cpp b/sources/diagramcommands.cpp index 23d792df3..bc27c80ed 100644 --- a/sources/diagramcommands.cpp +++ b/sources/diagramcommands.cpp @@ -268,7 +268,7 @@ void PasteDiagramCommand::redo() const DiagramContext &info = e->elementInformations(); if (e->linkType() == Element::Slave || (e->linkType() & Element::AllReport) || info.value(QETInformation::ELMT_FORMULA).toString().isEmpty() - || !project->elementAutoNumTitle(QUuid(info.value(QETInformation::ELMT_FORMULA_ID).toString())).isEmpty() + || !ElementAutoNumSchemeCommand::followedScheme(project, info).isEmpty() || pasted_schemes_has(pasted_schemes, e)) { continue; } diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index cc1817ce0..74fb18481 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -2338,7 +2338,10 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project) //Saved before schemes had an id: derive one, the //same on every load of the file. m_legacy_element_autonums = true; - id = derivedItemUuid(QStringLiteral("element_autonum"), title); + //Of this project: another project may have a numbering of the + //same name, which is not the same numbering + id = derivedItemUuid(QStringLiteral("element_autonum"), + m_uuid.toString() + QLatin1Char('\n') + title); } m_element_autonum.insert(title, nc); m_element_autonum_id.insert(title, id); diff --git a/sources/ui/jumptoelementdialog.cpp b/sources/ui/jumptoelementdialog.cpp index 566a93305..79e81e024 100644 --- a/sources/ui/jumptoelementdialog.cpp +++ b/sources/ui/jumptoelementdialog.cpp @@ -16,6 +16,7 @@ along with QElectroTech. If not, see . */ #include "jumptoelementdialog.h" +#include "../qetinformation.h" #include "../diagram.h" #include "../diagramview.h" @@ -99,6 +100,10 @@ void JumpToElementDialog::buildCandidates() search_parts << label << name; const DiagramContext infos = element->elementInformations(); for (const QString &key : infos.keys()) { + //An internal id, not something the user can read or type + if (key == QETInformation::ELMT_FORMULA_ID) { + continue; + } search_parts << infos.value(key).toString(); } candidate.search_text = search_parts.join(QLatin1Char(' ')).toLower(); diff --git a/tests/qttest/CMakeLists.txt b/tests/qttest/CMakeLists.txt index ae8b70e77..ebfc51f6b 100644 --- a/tests/qttest/CMakeLists.txt +++ b/tests/qttest/CMakeLists.txt @@ -729,15 +729,3 @@ add_executable( add_test(NAME tst_xrefpos COMMAND tst_xrefpos) target_include_directories(tst_xrefpos PRIVATE ${QET_DIR}/sources) target_link_libraries(tst_xrefpos PRIVATE Qt::Test Qt::Widgets Qt::Xml pugixml::pugixml) - -# Qt 6.4.2 writes the attributes of an element in an order that changes from -# one process to the next, so a project saved twice by two runs of the binary -# differs in bytes only (seen on projects without any numbering, too). A fixed -# hash seed makes the order stable; it changes nothing for a newer Qt. -if(Qt6_VERSION VERSION_LESS 6.5.0) - foreach(qet_test tst_resaveunchanged tst_elementautonumids) - if(TEST ${qet_test}) - set_tests_properties(${qet_test} PROPERTIES ENVIRONMENT "QT_HASH_SEED=0") - endif() - endforeach() -endif() diff --git a/tests/qttest/tst_elementautonumids.cpp b/tests/qttest/tst_elementautonumids.cpp index 28ebf6253..2b213da82 100644 --- a/tests/qttest/tst_elementautonumids.cpp +++ b/tests/qttest/tst_elementautonumids.cpp @@ -267,6 +267,39 @@ private slots: QVERIFY2(read(first) == read(second), "the second save changed the file"); } + // The id given to a numbering of a file written before the ids is the + // file's own: two projects which both have a numbering of the same name + // do not get the same id, or a paste from one into the other would + // take the other's numbering for the same one. + void derivedIdsBelongToTheirProject() + { + QFile in(QStringLiteral(QET_EXAMPLES_DIR "/industrial.qet")); + QVERIFY(in.open(QIODevice::ReadOnly)); + QDomDocument doc; + QVERIFY(doc.setContent(&in)); + doc.documentElement().setAttribute(QStringLiteral("title"), QStringLiteral("Another project")); + const QString other = m_dir.filePath(QStringLiteral("another-project.qet")); + QFile out(other); + QVERIFY(out.open(QIODevice::WriteOnly)); + out.write(doc.toByteArray()); + out.close(); + + const QString first = resave(QStringLiteral(QET_EXAMPLES_DIR "/industrial.qet")); + const QString second = resave(other); + QVERIFY2(!first.isEmpty() && !second.isEmpty(), "--resave failed"); + const Saved a = parse(read(first)); + const Saved b = parse(read(second)); + QVERIFY(a.scheme_id.contains(QStringLiteral("Equipment"))); + QVERIFY(b.scheme_id.contains(QStringLiteral("Equipment"))); + QVERIFY(!a.scheme_id.value(QStringLiteral("Equipment")).isNull()); + QVERIFY2(a.scheme_id.value(QStringLiteral("Equipment")) != b.scheme_id.value(QStringLiteral("Equipment")), + "two projects gave the same id to their numbering of the same name"); + // each keeps its own ids when saved again + const QString again = resave(second); + QVERIFY(!again.isEmpty()); + QCOMPARE(parse(read(again)).scheme_id, b.scheme_id); + } + // Rename, refused rename and removal, an edit that keeps the numbers, // an edit that renumbers, and undo/redo: through the scripting API, // which goes through the same ElementAutoNumSchemeCommand as the UI. diff --git a/tests/qttest/tst_resaveunchanged.cpp b/tests/qttest/tst_resaveunchanged.cpp index bc333ea44..042a934d6 100644 --- a/tests/qttest/tst_resaveunchanged.cpp +++ b/tests/qttest/tst_resaveunchanged.cpp @@ -122,9 +122,6 @@ private slots: // (#973), and a value with accents comes back as it went in. void singleSpaceValueKept() { -#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) - QSKIP("QDomDocument::PreserveSpacingOnlyNodes needs Qt 6.5 (see QETProject::openFile)"); -#endif QByteArray xml = read(QStringLiteral(QET_EXAMPLES_DIR "/Projet_vierge.qet")); QVERIFY(xml.contains("")); xml.replace("",