9337 Commits

Author SHA1 Message Date
Laurent Trinques 2785e25569 Merge pull request #863 from ispyisail/fix/bugtracker-97-recent-files-menu
Fix bugtracker #97: "Recently opened" never updates during a session
2026-09-14 09:09:45 +02:00
Laurent Trinques c8e4396b2a Merge pull request #864 from ispyisail/fix/bugtracker-238-summary-order
Fix bugtracker #238: summary table ordered by its columns, not by folio
2026-09-14 09:04:25 +02:00
ispyisail 0147453494 Fix bugtracker #238: summary table ordered by its columns, not by folio
SummaryQueryWidget::queryStr() built its ORDER BY from the columns the user
chose to display, in the order they chose them:

    column   += key;
    order_by += key;

So a summary whose first column is Title came out sorted alphabetically by
title, and one starting with Author sorted by author. A table of contents
lists the folios of a project; its order is the project's order, not
whatever the first column happens to be.

It now orders by "pos", the folio position that project_summary_view already
exposes from diagram.pos. That column is an INTEGER, so the sort is numeric
and folio 10 does not land between folio 1 and folio 2. One row per folio
means pos fully determines the order, so no secondary key is needed.

Demonstrated against a stand-in view holding four folios:

    ORDER BY title, pos   Apple(2) Banana(3) Mango(10) Zebra(1)
    ORDER BY pos          Zebra(1) Apple(2) Banana(3) Mango(10)

The hand-written query path (m_edit_sql_query_cb) returns before this and is
untouched, so anyone wanting a different order still has one.

ctest 4/4, Qt 5.15.18.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 15:30:44 +12:00
ispyisail 181bbb7f21 Fix bugtracker #97: "Recently opened" never updates during a session
The File > Recently-opened submenu was filled once, at editor construction,
by copying the QActions that RecentFiles' menu happened to hold at that
moment:

    recentfile->addActions(QETApp::projectsRecentFiles()->menu()->actions());

RecentFiles::buildMenu() runs on every fileWasOpened(), clears its menu and
creates fresh QActions. The editor's copy therefore never gained an entry,
and the list only ever looked correct after a restart.

The submenu is now the RecentFiles menu itself. QMenu::addMenu() adds the
submenu's menuAction() rather than reparenting it, so several editor windows
can share the one live menu, which is what an application-wide recent-files
list should do anyway.

Measured with a temporary probe comparing the live menu against what the
File menu actually shows, after one file had been opened in the same
session:

    without the fix   live=1  shownInFileMenu=0
    with the fix      live=1  shownInFileMenu=1

ctest 4/4, GUI starts clean with the menu bar intact. Qt 5.15.18.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 15:25:51 +12:00
ispyisail 3665ec1bcd Fix bugtracker #108: the junction dot vanishes on a wide conductor
Conductor::paint() drew every junction as a fixed 3.0-unit ellipse,
regardless of how wide the conductor carrying it is. The conductor width is
user-settable from 0.4 to 20.0, so at anything above about 3.0 the dot is
narrower than the line it sits on and disappears entirely -- exactly when a
junction most needs to be legible.

The dot now scales with m_properties.cond_size, floored at the historic 3.0
so nothing changes at or below the default width of 1.0. Only the wide
conductors the report is about are affected.

cond_size is used rather than the pen width because the pen is inflated by 4
while the mouse is over the conductor; the junction should not grow on
hover.

Measured with a temporary trace over examples/741.qet: at the default width
the diameter stays 3.00, and with condsize="5" it becomes 15.00. Visually,
a PNG export of that widened project shows two junctions that were invisible
under the line rendering as clear dots. ctest 4/4, Qt 5.15.18.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 15:15:39 +12:00
ispyisail fcd2a4e0e0 Fix bugtracker #248: opening a file while QET is running does nothing
QET::splitWithSpaces() split on QRegularExpression("[^\\]?(?:\\\\)* ").
That is not a valid pattern: "[^\\]" opens a character class whose "\\]" is
an escaped bracket, so the class is never closed. QRegularExpression
reported isValid() == false, QString::split() warned "invalid
QRegularExpression object", and the function returned an EMPTY list for
every input.

It is the receiving half of the SingleApplication handshake: a secondary
instance sends "launched-with-args: " + joinWithSpaces(args) (main.cpp) and
the running instance parses it in QETApp::receiveMessage() before calling
openFiles(). With the split always empty, the running instance received no
arguments at all -- so opening a project while QET was already running
silently did nothing.

The bug is reported against filenames containing spaces, which is how it
was noticed, but it is not limited to them: plain names failed identically.

A corrected regex is not available. The separator is a space preceded by an
even-length run of backslashes, and PCRE2 has no variable-length lookbehind,
so the run cannot be expressed in a lookbehind and anything that matches it
by consumption eats the character before the space -- which is what the
"[^\\]?" was for. Scanning the string explicitly is correct and easier to
read.

tests/qttest/tst_qetstrings.cpp asserts the round trip
splitWithSpaces(joinWithSpaces(x)) == x over plain names, embedded spaces,
embedded backslashes, a trailing backslash and a mixture, plus the specific
regression that a plain argument list does not come back empty.

Verified the test fails without the fix: 9 of 11 cases fail on the old
implementation and all 11 pass with it. Full suite 5/5, Qt 5.15.18.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 14:55:17 +12:00
Kellermorph 3c1c29f6c3 connect searchfield 2026-09-13 21:32:34 +02:00
Kellermorph cafc5bcf6d Add Hide linked elements checkbox to PLC link widget 2026-09-13 20:36:59 +02:00
Laurent Trinques 3cbb930751 Update pl translations, thanks Pawel 2026-09-13 17:04:41 +02:00
Laurent Trinques 51209d30b6 Merge pull request #855 from Kellermorph/copy-paste-fix
Clear PLC slave data on paste
2026-09-13 13:32:09 +02:00
Kellermorph 9c55d36d55 Clear PLC slave data on paste 2026-09-13 12:58:43 +02:00
Laurent Trinques 3ac557570c Merge pull request #853 from Kellermorph/fix-template-placing
Fix macro drag-and-drop placement and preview for Qt6
2026-09-13 12:27:51 +02:00
Kellermorph 0c2cf409f8 Fix macro drag-and-drop placement and preview for Qt6 2026-09-13 10:09:44 +02:00
Laurent Trinques 467a14df71 Merge pull request #849 from ispyisail/fix/bom-include-slave-terminal
Fix terminal and contact blocks missing from the parts list
2026-09-13 09:34:30 +02:00
Laurent Trinques 1b6768fcec Merge pull request #851 from ispyisail/feature/autonum-import-from-project
New feature: reuse automatic numbering rules from another project
2026-09-13 07:19:41 +02:00
ispyisail a6fd42ac5f Import automatic numbering rules from another project
Forum #3186 / issue #850: a user who has built up conductor and element
numbering rules in one project has no way to reuse them in the next one.
The only answer today is to open both .qet files in a text editor and copy
the XML across by hand.

Adds an "Import from another project..." button to the auto-numbering page
of the project properties dialog. It offers every numbering found in the
chosen file, per category, with names that already exist here unticked by
default and a "replace same-named numberings" option for when that is what
the user wants.

The source file is parsed as plain XML rather than opened as a QETProject.
Opening it would run the whole load path, including the modal dialog raised
for a file written by a different version of QElectroTech -- a dialog the
user has no reason to see, since nothing but the <newdiagrams> block is
being read.

Two supporting changes:

  - readValuesFromProject() clears the three combo boxes before filling
    them. It only ran once before; it now runs again after an import, and
    without the clear every name appeared twice.

  - FolioAutonumberingW::setContext() likewise replaces its list instead
    of appending to it. It has a single caller, the line above.

This deliberately does not attempt the project-template feature also raised
on the forum thread. That needs decisions about where templates live and
what else they carry, and is better settled in a discussion first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 09:56:25 +12:00
Laurent Trinques ce17b5c984 Update EN translations files 2026-09-12 17:51:44 +02:00
Laurent Trinques b46a4cfc2a Update FR EN translations files 2026-09-12 17:47:50 +02:00
Laurent Trinques 00d8822583 Remove again .pro now use /usr/lib/qt6/bin/lupdate -no-obsolete sources/ -ts lang/qet_*.ts
to generate new translation update on *TS files
2026-09-12 17:36:45 +02:00
Laurent Trinques 8edda68e96 Restore .pro files for lupdate translation 2026-09-12 17:20:49 +02:00
Laurent Trinques ad9a47602d Delete ols .pro and unused macOS script based on Qt5 2026-09-12 17:12:26 +02:00
ispyisail b034d3c5b3 Include slave and terminal elements in the bill of materials
A slave and a terminal are both routinely separately orderable hardware. A
circuit breaker can carry ten or twenty auxiliary blocks, each with its own
order code, and a terminal block is a purchased part in its own right.
Neither was reaching the bill of materials.

Decided in discussion #847: @IBSYSLevi -- "I would not expect that a defined
piece of hardware is excluded from BOM when not specifically defined as so" --
with use cases from @jozi332 covering Siemens breakers with ten to twenty
auxiliary blocks and PLC cards carrying per-channel data.

Two filters had to change, which is easy to miss: BomExport::defaultQuery()
and, upstream of it, the WHERE clause of element_nomenclature_view itself.
Changing only the query does nothing for slaves, because the view had already
removed them. Terminals were already in the view, so they appeared as soon as
the query allowed them -- which made a half-finished change look like it had
worked.

Measured on examples/industrial.qet, which holds 96 terminals and 41 slaves:
258 rows before, 354 with terminals, 395 with both. A slave given a
manufacturer and part number now appears in the export; previously it could
not, at any setting.

Nothing that should stay out of a bill of materials is newly included. The
folio report arrows and the conductor definition are still excluded because
they are not hardware, and anything else -- a relay's own auxiliary contact,
which is not orderable separately -- is kept out with exclude_from_bom, which
the view already honours and which #721 and #765 made settable on the symbol
itself.

tst_smart_device is updated rather than weakened. @enesgursoy6110 wrote it in
#830 to prove the filter works, inserting rows designated "Must not be
exported"; the slave and terminal rows now carry real designations and are
asserted present, and a folio report arrow takes over as the negative case,
so the test still proves filtering happens -- at the boundary we now want.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 02:00:50 +12:00
ispyisail dd08b3daa5 Merge pull request #848 from arummler/fix_debug_message
Guard debug output in titleblocktemplate
2026-09-13 00:58:35 +12:00
ispyisail 2bdad43371 Merge pull request #846 from ispyisail/fix/titleblock-template-save-order
Write embedded title block templates in a stable order
2026-09-13 00:52:39 +12:00
Andre Rummler c05033d44c Guard debug output. 2026-09-12 14:50:22 +02:00
ispyisail 15c893de89 Merge pull request #765 from IBSYSLevi/feature/Add-existing-editor-properties-to-element
Editable auto_num_locked/potential_isolating/exclude_from_bom in the element editor
2026-09-13 00:36:02 +12:00
ispyisail 3e7dd15392 Merge pull request #767 from IBSYSLevi/fix/element-editor-informations-tab-visibility
Fix Informations tab visibility to match existing Terminal/Thumbnail support
2026-09-13 00:35:02 +12:00
ispyisail 061f07ef9e Merge branch 'master' into fix-informations-tab-visibility
# Conflicts:
#	sources/editor/ui/elementpropertieseditorwidget.cpp
2026-09-13 00:30:27 +12:00
ispyisail cb0d8c8f63 Write embedded title block templates in a stable order
Fifth site of the hash-ordering defect fixed in #844.
TitleBlockTemplatesProjectCollection::templates() returns
titleblock_templates_xml_.keys(), a QHash, and QETProject::toXml() iterated
it directly. A project embedding more than one template therefore wrote the
<titleblocktemplate> children in a different order on every save.

examples/affuteuse_250h.qet embeds three -- A4_1, DIN_A4 and DIN_A4_copy --
and two saves of it produced "DIN_A4 A4_1 DIN_A4_copy" and
"DIN_A4_copy A4_1 DIN_A4". It was the last of the two projects #844 could not
make reproducible.

Worth recording because the first reading of that diff was wrong: seeing
name="DIN_A4" on one side and name="DIN_A4_copy" on the other looked like the
save path renaming a template, which would have been far more serious -- a
diagram referring to it by name would have been left dangling. The file
simply contains both, and they had swapped places.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 00:06:31 +12:00
ispyisail f9d063bd38 Merge pull request #821 from enesgursoy6110/fix/shortcut-conflict-scope
Scope shortcut conflicts to overlapping editors
2026-09-13 00:00:54 +12:00
ispyisail fab5571ea2 Merge pull request #845 from ispyisail/revert-759-shortcut-scope
Revert #759, so #821 can land instead
2026-09-12 23:56:44 +12:00
ispyisail a0acf878a2 Revert "Merge pull request #759 from ispyisail/fix-shortcut-conflict-scope"
This reverts merge commit 3d5799773, restoring shortcutsconfigpage.cpp to
its state before it.

#759 and #821 fix the same issue (#757). #821 was opened on 8 September and
is the better fix; #759 was merged on 12 September without checking whether a
PR for it already existed, and its merge is what left #821 conflicting with
master. Reverting is the way to let the right change land.

#759 keys conflict detection on the row's category, which is a tr() string.
#821 keys on the shortcut ID prefix, which is stable and untranslated, and
encodes the overlaps the category cannot express: main-window actions are
live while any editor is open, and the depth.* actions are installed into
both the diagram and the element editor.

Checked against the registry rather than by reading -- 94 registered actions
plus the four depth.* ones registered through QObject::tr. On the shipped
defaults the two behave identically: all 24 shared sequences are legitimate
cross-editor duplicates and neither flags them. They diverge on shortcuts a
user assigns, where #759 misses four classes of real conflict that #821
catches: a diagram or element editor action given the main window's F1, and
a diagram or element action given a depth.* sequence.

The reason #759 looked adequate is that the scope prefix currently maps
one-to-one onto the translated category for all seven scopes, so same-scope
detection comes out the same either way. It fails only where scopes overlap,
which is the case #821 exists to handle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:51:41 +12:00
ispyisail 21588a9c10 Merge pull request #844 from ispyisail/fix/save-reproducible-ordering
Make saving a project reproducible: sort four hash-ordered XML writes
2026-09-12 23:45:10 +12:00
ispyisail fcbea2dafd Write model header roles in a stable order
Fourth and last instance of the ordering defect, and the inner half of the
one fixed in the previous commit. ProjectDBModel::toXml() builds each
section's role list from m_header_data.value(key).keys(), and m_header_data
is a QHash<int, QHash<int, QVariant>> -- so both levels are randomised per
process. Sorting the sections left the roles inside each section still
arriving shuffled, which showed up as <data> children with the same
section="0" swapping places between two saves.

With this, save idempotence across the shipped examples goes from 6 of 23 to
22 of 24.

The two that remain fail for unrelated reasons, not for ordering:
schema_indus.qet stores no uuid attribute on its elements at all, so
fromXml() invents a fresh one on every load; and affuteuse_250h.qet loses a
title block logo's storage attribute and renames a title block template on
save. Both are separate defects.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:31:26 +12:00
ispyisail 1272b9db06 Write model header data sections in a stable order
Third instance of the ordering defect the two previous commits fixed, and
the one that was still making five of the shipped examples save
irreproducibly after those: QETXML::modelHeaderDataToXml() iterates
data_hash.keys() directly, and data_hash is a QHash<int, QList<int>> whose
key order is randomised per process. The <data> children of <header_data>
therefore came out in a different order on every save, which is what a
diff of two saves of industrial.qet showed -- the same EditRole, FontRole
and TextAlignmentRole entries, shuffled.

Sorting the section list fixes it. The roles within a section are a QList
and were already written in a stable order, so they are left alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:27:46 +12:00
ispyisail 6e8d821853 Write the three auto-numbering collections in a stable order
Same defect as the <xref> ordering fixed in the previous commit, in the same
function and left behind by it: conductorAutoNum(), folioAutoNum() and
elementAutoNum() are QHash, whose key order is randomised per process, and
all three were iterated directly. A project holding more than one scheme in
any of the three categories therefore wrote those children in a different
order on every save, so opening and saving without an edit produced a file
that differed from the original, and differed again next time.

Three of the shipped examples are affected: Projet_vierge.qet has 8 conductor
schemes, industrial.qet has 4 element and 2 folio schemes, and
tableau_domestique.qet has 2 element schemes.

Sorting the key list is the same remedy already applied to the xrefs, and
changes nothing else: the same children are written, with the same contents.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:22:32 +12:00
ispyisail e64c0618c8 Break ties in the element sort key, so equal positions save in a stable order
Diagram::toXml() sorts elements by position alone. That is not a total
order: two elements can sit at the same x/y. lmdg.qet has a pair of
text elements both at 780,350, their sort keys are identical, and
std::stable_sort then falls back to the order QGraphicsScene handed us,
which varies between runs. The two swapped places on every save.

Appending the uuid gives a total order. This keeps the reasoning in the
existing comment intact rather than contradicting it: that comment warns
against sorting *by* uuid, because an element with no persisted uuid
attribute is given a fresh random one by fromXml() on every load. As a
tiebreaker the uuid is only consulted when two positions are equal, so
elements carrying a persisted uuid -- the colliding pair in lmdg.qet
included -- become deterministic, and a collision between two legacy
elements is no better ordered than before, but no worse.

Measured with tests/determinism, on top of the xref ordering fix:

  before both fixes      I1 0/23
  xref ordering only     I1 5/23
  with this as well      I1 6/23   (lmdg.qet newly reproducible)

No regressions against the baseline, I3 stays 23/23. Also checked
lmdg.qet directly three times rather than once, since the failure is
nondeterministic by nature and a single passing run proves nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:21:56 +12:00
ispyisail 3af551583c Write default XRef properties in a stable order
QETProject::toXml() iterated defaultXRefProperties().keys() straight into
the document. That is a QHash, and Qt randomises hash iteration order per
process, so every save wrote the <xref> children in a different sequence.

Saving an unchanged project therefore produced a different file each
time. The content was identical -- same size, same elements -- but the
order moved, so version control showed spurious changes on every save and
comparing two saved files showed differences that were not there.

Sorting the keys before writing makes a save reproducible. This is the
same class of problem, and the same fix, as the sort already applied to
Diagram::toXml()'s <elements> and <conductors> blocks.

Measured with tests/determinism (resave twice, compare):

  before: I1 idempotent save 0/23
  after:  I1 idempotent save 5/23

with ArduinoLCD, ShellyParts, convertisseur, schema_indus and
schema_unifilaire_voltaique2 newly reproducible, and no regressions
against the baseline.

Not the only remaining source of save instability -- the other 18
projects still fail I1 for other reasons. This fixes the hash-ordering
source only.

Note this is not a Qt6 regression. The Qt5 build happened to produce a
favourable hash order for four projects and Qt6 does not, but both were
writing an unspecified order; only the dice changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:21:55 +12:00
ispyisail b274170cff Merge pull request #828 from ispyisail/fix/slot-count-from-groups
Take the slot count from the contact groups when an element declares them
2026-09-12 23:19:12 +12:00
ispyisail bd7d60021c Merge branch 'master' into fix/slot-count-from-groups 2026-09-12 23:14:56 +12:00
ispyisail 12f443dd89 Merge pull request #792 from ispyisail/fix-nonfinite-coordinate-validation
Fix #781, #782: reject non-finite element/terminal coordinates on load
2026-09-12 23:08:08 +12:00
ispyisail 9afba7091c Merge branch 'master' into fix-nonfinite-coordinate-validation 2026-09-12 23:07:47 +12:00
ispyisail 3d5799773e Merge pull request #759 from ispyisail/fix-shortcut-conflict-scope
Scope shortcut conflict detection to the category (fixes #757)
2026-09-12 23:07:36 +12:00
ispyisail 9c3ab588a4 Merge branch 'master' into fix-shortcut-conflict-scope 2026-09-12 23:07:27 +12:00
ispyisail 3a26cc4b86 Merge pull request #733 from ispyisail/fix/bugtracker-243-copy-from-readonly
Fix bugtracker #243: allow copying out of a read-only element
2026-09-12 23:07:09 +12:00
ispyisail 88f5af08d7 Merge branch 'master' into fix/bugtracker-243-copy-from-readonly 2026-09-12 23:06:47 +12:00
ispyisail 29e4817254 Merge pull request #724 from ispyisail/fix/wire-name-export-double-count-forum3125
Fix wire-name export doubling every conductor's count
2026-09-12 23:06:35 +12:00
ispyisail c8b5901296 Merge branch 'master' into fix/wire-name-export-double-count-forum3125 2026-09-12 23:06:15 +12:00
ispyisail f8cb997f3b Merge pull request #719 from ispyisail/fix/titleblock-bare-variable-detection-bug245
Fix bugtracker #245: bare %name custom variables not detected in title blocks
2026-09-12 23:06:03 +12:00
ispyisail 1e8f5d8a72 Merge branch 'master' into fix/titleblock-bare-variable-detection-bug245 2026-09-12 23:05:41 +12:00