Commit Graph

10463 Commits

Author SHA1 Message Date
Laurent Trinques 8b680af938 Merge pull request #1471 from ispyisail/fix/lazy-refused-opens-eager
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m41s
Fix lazy folios opening older projects slower than without them
2026-10-13 12:47:40 +02:00
Laurent Trinques 7c2a09f2bc Merge pull request #1470 from ispyisail/perf/qetz-picture-load
Speed up opening .qetz projects that hold large pictures
2026-10-13 12:42:15 +02:00
Laurent Trinques 132eefb8b8 Merge pull request #1467 from ispyisail/fix/qetz-zip-entry-date
Fix the dates of the files inside a .qetz project
2026-10-13 12:41:42 +02:00
ispyisail 00e200b504 Remove references to notes that are not in this repository
Comments added with the lazy folios cited planning notes kept outside the
QElectroTech repository, which a reader of the source cannot open. The
sentences now stand on their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:03:14 +13:00
ispyisail 1c4618c8dd Open with every folio built when the database must come from them
With QET_LAZY_FOLIOS=1, a project whose database cannot be filled from
the file (folios or symbols with no saved uuid, two symbols sharing one,
a folio number using %autonum, wires naming their ends the older way)
had its folios left unbuilt, then built all at once while the database
was filled from them. That is slower than building them as they are
read: a 17 MB project reported on the pull request took 24.8 s to open
instead of 19.2 s, and most files saved by an older version have no
folio uuids.

The file is now checked for those reasons before the folios are read;
when one applies the project opens as without QET_LAZY_FOLIOS. The rarer
reasons, which need the definitions or every folio's links, still fall
back as before.

tst_lazyfolios opens a copy of industrial.qet with one symbol's uuid
given to another, and checks no folio is built after reading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:02:55 +13:00
ispyisail 1ad3c8e2b2 Speed up opening .qetz projects with large pictures
A .qetz keeps each folio picture as a PNG file. On opening, join() put
every picture back into the document as base64 text, and the folio then
decoded that text again, twice. On a project with 20 pictures of 7 MB
(140 MB of PNG, the shape of the project on PR #1462) that cost about
8 of the 12 seconds the open took:

  QDomDocument::createTextNode() on the base64   3.9 s
  DiagramImageItem::fromXml(), base64 decoded    3.9 s (2 x 1.9 s)
  the PNG decoding itself                        0.3 s

join() now takes an optional map. Given one, each picture stays a file:
the <image> keeps its qetz-file attribute and the bytes go in the map.
QETProject keeps the map for as long as the project is open, and
Diagram::fromXml() hands a picture's bytes to the new
DiagramImageItem::fromXml(element, picture). Kept, not cleared after
the load, so a folio built later finds its pictures too; the bytes are
shared with the PNG cache of the pictures built from them, so this costs
almost no memory. readDocument() without a map, as the automatic
numbering import uses it, still gives the whole document.

fromXml() of a .qet picture also decodes its base64 once instead of
twice: the first text node, which the PNG cache already used. e.text()
also collects <image_base>'s text, but loadFromData() stops at the end
of the first picture, so the picture shown is the same.

Measured, same file, 3 runs each, offscreen:
  .qetz  11.8 s -> 3.8 s, peak memory 1034 MB -> 655 MB
  .qet   15.7 s -> 13.6 s
Resaving either file with either binary gives the same bytes, a cropped
and colour-keyed picture included, and every folio exports to the same
PNG pixels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:02:47 +13:00
Laurent Trinques aa503aec81 Merge pull request #1468 from qelectrotech/resolve-1461
Speed up opening big projects with lazy folios
2026-10-13 11:10:10 +02:00
Laurent Trinques 77e2a9bfc5 Speed up opening big projects with lazy folios 2026-10-13 11:01:21 +02:00
ispyisail c240e4e6f7 Fix the dates of the files inside a .qetz project
miniz is built with MINIZ_NO_TIME so that saving the same project twice
gives the same bytes. Without a clock it writes 0 as each entry's DOS
date: day 0 of month 0, 1980, which is not a date. Unzip tools show it
as 30 Nov 1979, others fail the conversion and show 13 Dec 1901
(reported on PR #1462).

Write 1 Jan 1980 00:00, the first valid DOS date, into the local and
central header of every entry once the archive is built. The bytes stay
reproducible, and miniz stays unmodified. Using the save time instead
was rejected: two saves would no longer give the same file, and miniz
converts through the local time zone, so even a fixed time_t would
differ between machines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:49:34 +13:00
Laurent Trinques a78e95be2c Merge pull request #1462 from ispyisail/feat/qetz-container
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m8s
Add the zipped project format (.qetz) as a save option
2026-10-13 08:08:11 +02:00
ispyisail 2651114866 Merge pull request #1434 from bhangart/test/image-handle-escape
Test Escape during a picture's handle drag
2026-10-13 16:29:53 +13:00
ispyisail 4b4b9a2ad0 Merge pull request #1435 from bhangart/fix/line-pivot-follows-resize
Keep a line's pivot at its centre when one of its ends is dragged
2026-10-13 16:29:20 +13:00
ispyisail 9dc03005da Merge pull request #1457 from ankostis/fix1376-no-bom-transfer
Skip boolean `"exclude_from_bom"' when pasting element infos
2026-10-13 16:22:08 +13:00
ispyisail fd34a10897 Merge master (cce75f430) into feat/qetz-container
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGxcrnd2rTYfHjwTdP79zo
2026-10-13 07:44:40 +13:00
Laurent Trinques b8dd03923a TerminalStripItem add pdfRefs
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m53s
2026-10-12 16:02:26 +02:00
Kostis Anagnostopoulos 12a695a503 fix #1375 don't paste bool info 'exclude_from_bom', >
it can never be "empty" so it is always overridden on target elements.
2026-10-11 21:49:11 +03:00
Laurent Trinques cce75f4306 Update Brazilian translations files
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 14m57s
2026-10-11 17:02:34 +02:00
Laurent Trinques 1f70ddb666 Update TS files
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m40s
2026-10-11 13:40:29 +02:00
Laurent Trinques 9f5406bd8c Terminal strip: add a label filter to the free terminals table 2026-10-11 13:31:30 +02:00
Laurent Trinques 6f4171c926 Cable: use begin/endFilterChange() on Qt >= 6.9, invalidateFilter() on older Qt
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m51s
2026-10-11 05:40:03 +02:00
Laurent Trinques e335aa2e55 Merge branch 'test-1438' 2026-10-11 05:15:26 +02:00
ispyisail ee0593ce7d Merge pull request #1432 from bhangart/feature/image-crop-on-folio
Crop a picture directly on the folio
2026-10-11 16:12:14 +13:00
Laurent Trinques 78ac5222c0 Cable: use invalidateFilter() instead of begin/endFilterChange (Qt 6.8 compat) 2026-10-11 05:04:50 +02:00
Laurent Trinques 1cd8fadbc4 Reapply "Add cable management: drawing, cores, numbering, cross-references and cable list"
This reverts commit 2bb3343d2d.
2026-10-11 05:00:01 +02:00
ispyisail e52b89cb84 Save As: a name typed as .qetz is a .qetz whatever the selected type
Typing "plan.qetz" over the selected "untitled" of "untitled.qet" gives
"plan.qetz.qet" with the GTK dialog, which saved a plain .qet named
.qetz.qet. Every trailing .qet/.qetz is stripped, and the project is
zipped when the .qetz file type is chosen or the typed name says .qetz.
Checked in the GUI: Save As, "saved.qetz" typed, writes saved.qetz, a
zip; launching on it shows the project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:29 +13:00
ispyisail a44e816d59 Keep terminal strips in a .qetz project's database too
The project's terminal strips -- strip information, the terminals of
each physical terminal by level, bridges and what they bridge -- move to
four tables of project.sqlite, when rebuilding them from the rows gives
the same XML exactly (as QElectroTech writes them). Anything else, or
strips that carry text a save would not write, stays in project.xml.

Test: tst_qetcontainer::terminalStripsInDatabase (two strips with a
bridge and a two-level terminal on industrial.qet's own terminals: out
of project.xml, back exactly; stays in the XML when the rebuild is
broken). Outside ctest: a strip fixture saved as .qetz then .qet by
QElectroTech equals its straight resave, and the strips are rows any
SQLite tool reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:29 +13:00
ispyisail 739061b0f0 Test that a .qetz whose database hides a view behind a table name is refused
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:29 +13:00
ispyisail cbaf40000c Keep a .qetz project's engineering data in project.sqlite
Fourth stage of the zipped project file (#1440), format 2: what an
engineer would put in a list -- folio title-block fields and
properties, project properties, a symbol's uuid, type, prefix,
information and links, a wire's ends, number, function, colour,
section, cable and bus -- moves out of the XML into project.sqlite in
the .qetz, and lives only there. The folio files keep where things are
drawn. On opening it goes back into the document before the usual
reader runs, so nothing else in QElectroTech changes yet (the program
reading the database directly is the next step of the roadmap).

Each moved item keeps a key in the XML (qetz-key: its uuid where
unique); each moved block leaves a marker where it was, which keeps the
whitespace around it apart. A block of a shape this does not model
stays in the XML. A file is untrusted: the database is read with
trusted_schema off, query_only, and only from names that are plain
tables. Format 2 readers still open format 1; a format 1 reader
refuses format 2.

Tests (tst_qetcontainer): every example back exactly, whitespace
included; databaseHoldsTheData (industrial.qet: the folio files hold no
information, links, wire numbers or properties; the row counts match).
Outside ctest: 341 of 341 projects QET can open give the same .qet
through a format 2 .qetz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:29 +13:00
ispyisail fac09253a0 Open and save projects as .qetz (zipped, opt-in)
Third stage of the zipped project file (#1440). A project is saved as a
.qetz when its file name ends in .qetz -- Save As offers it as a second
file type, and --resave, --set-titleblock, the script API's save() and
the live-mode snapshot follow the name too. Saving a .qet project still
writes a .qet; nothing changes unless the user picks .qetz.

Opening recognises a .qetz by its content (a zip), not its name, and
reads it as bytes: text mode would alter it on Windows. The project
document is joined back and read by the same code as a .qet. Crash
backups stay plain XML. Drag and drop, the open dialog and the
numbering import accept .qetz; the database export names its file from
the project's name without assuming ".qet".

Parts are now written without added indentation (one line each): the
symbol definitions are kept as read, whitespace included, and parts
that gained indentation made the next save differ (five forum projects).

Tests: tst_resaveunchanged::containerSavesTheSameProject (four examples
saved as .qetz, then as .qet, equal the straight .qet; pictures checked
to fail without the fix), tst_qetcontainer::noWhitespaceAdded. Outside
ctest: 341 of 341 projects QET can open (examples, bugtracker, GitHub,
forum) give the same .qet through a .qetz; 181.6 MB of .qet became
36.9 MB of .qetz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:29 +13:00
ispyisail a475383915 Split a project into the parts of a .qetz file and join it back
Second stage of the zipped project file (#1440): QetContainer::split()
turns a project document into the entries of a .qetz -- mimetype first
and stored, a manifest with the format and the oldest format allowed to
read it, project.xml with each part replaced by <qetz-part file=.../>,
one file per folio, per symbol definition and per title block template,
and folio pictures as PNG files named by their SHA-256, stored once
each. join() puts it back and refuses a file of a later format, a
missing part or anything that is not a .qetz.

A picture leaves its folio only if its base64 comes back exactly, so
nothing here can change a project. Parts are written as QET writes a
.qet and read as it reads one. Still nothing opens or saves a .qetz.

Test: tst_qetcontainer, every example split, zipped, unzipped and
joined back to the same document (whitespace between elements aside);
pictures out of the folios once each; later format and missing part
refused. With QET_CONTAINER_CORPUS it also runs on a folder of projects:
341 of 341 readable projects collected from the bugtracker, GitHub and
the forum come back the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:16 +13:00
ispyisail d7ac633043 Add a zip reader and writer for .qetz projects (bundled miniz)
First stage of the zipped project file discussed in #1440 (and #865):
the zip itself, nothing reads or writes a project with it yet.

miniz 3.1.2 (MIT, one .c and one .h, no zlib) is bundled unmodified in
sources/container/miniz, as the LZMA SDK is for .edz files, so builds
need nothing new. QetZip wraps it: plain ZIP with Deflate, entries stored
where asked (pictures, the mimetype entry), written through QSaveFile so
a failed save keeps the previous file, without timestamps so that the
same project gives the same bytes. Reading refuses unsafe or repeated
entry names, encrypted entries and archives over 2 GB once unpacked.

Test: tst_qetzip (round trip, same bytes twice, names refused both ways,
truncated and non-zip input). A written archive also passes unzip -t and
Python's zipfile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-11 06:24:16 +13:00
Laurent Trinques 124a889be3 Add new QET_release_notes_0.100_to_master.md, thanks arummler
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 1m56s
2026-10-10 17:43:40 +02:00
Laurent Trinques 7f6753696b Merge pull request #1453 from qelectrotech/revert-1438-wiring-manager
Revert "Add cable management: drawing, cores, numbering, cross-references and cable list"
2026-10-10 16:50:07 +02:00
Laurent Trinques 2bb3343d2d Revert "Add cable management: drawing, cores, numbering, cross-references and cable list" 2026-10-10 16:49:39 +02:00
Laurent Trinques 738ffbfc36 Merge pull request #1438 from Kellermorph/wiring-manager
Add cable management: drawing, cores, numbering, cross-references and cable list
2026-10-10 16:33:12 +02:00
Laurent Trinques 0fe88758aa Terminal strip: add resistor, varistor, test socket and reversed diode types
Add ElementData::TTResistor, TTVaristor, TTTestSocket and TTDiodeReversed
(xml values "resistor", "varistor", "test_socket", "diode_reversed"),
selectable in the element editor, the terminal strip editor and the free
terminal editor, and drawn in the terminal strip plan.
2026-10-10 16:03:47 +02:00
Laurent Trinques b089c5b245 Terminal strip: remove the circles at the end of connections and wires
Draw the top/bottom connections of the terminals and the wires under
the cable as plain lines, without the small circle at their end.
2026-10-10 15:46:14 +02:00
Kellermorph 9771ca96c9 Make the cable feature speak English like the rest of the interface
English has been the source language of the program for a while now
(upstream: "Make English the source language ..."), the cable feature
came in with French ones: about 200 translatable strings over 30 files,
the two settings pages built from .ui files, four comments and one test
which asserted the old wording (blocking review comment by ispyisail).

The wording follows what the code base already uses where it exists:
Plant (=) and Location (+) as qetinformation.cpp names those element
information, Designation for the field the cable form calls its BMK,
Length, Sheet for folio, Automatic numbering, Cross-reference, and Right
aligned / Centred / Left aligned the way cabletextformatdialog.cpp
already spells the three alignment entries.

Two things are more than a word-for-word swap:

- xrefpropertieswidget.cpp:291 wrote the label of the master field on
  every type change with a hardcoded tr("Maitre"), so the English
  "Master" coming from the .ui was overwritten for every type, cable or
  not: a real bug next to being French. The wording now comes back from
  the .ui and only a cable renames the field to "Text:", so the two
  cannot drift apart again.

- tst_cabletypelist kept asserting that a new catalogue is *labelled*
  in French. That label line is the translated header and reads English
  now. The test still reads files with French headers on purpose:
  headerAliasMap() keeps the five old French labels as aliases next to
  the English ones, so catalogues written by earlier builds, including
  the one the reviewer reads her own types from, keep loading.

The .ts files are deliberately not regenerated here. Upstream
regenerates them on master, as it did for the language change itself,
and a translation is keyed on the source string: while the sources were
French a German user saw French in the cable dialogs, and an English
source string with no translation yet shows as it is.

Build clean, ctest 92/93, the one failure being the pre-existing
headless tst_menubarkeyboard.
2026-10-10 13:48:45 +02:00
ispyisail 2f751f1762 Merge pull request #1451 from ispyisail/fix/mcp-search-collection-scheme
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m1s
Fix symbol search paths for the user collection (#1450)
2026-10-10 22:51:35 +13:00
ispyisail 1457851c56 qet-mcp: give search results the scheme of the collection searched (#1450)
qet_element_search returned common:// for every folder, so a symbol found
in the user or company collection could not be placed by qet_edit. The
scheme now follows the folder: custom:// and company:// for the
collections qet-assistant.json names, common:// for any other directory.

The sandboxed run is also given those two collections. On Linux it
replaces XDG_DATA_HOME, so custom:// failed there even when written by
hand; it worked on macOS, where Qt does not read that variable.

The qet_edit schema no longer says an absolute .elmt path works anywhere:
QElectroTech places one only from inside a collection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:26:19 +13:00
ispyisail c0b9963bf8 Merge pull request #1449 from ispyisail/fix/report-arrow-without-terminal
Fix a crash opening a project with a report arrow that has no terminal
2026-10-10 22:04:42 +13:00
Beat Hangartner ec5246f6db Use relative paths for the crop texts' locations in qet_fr.ts
The six <location> lines the crop translation added pointed into
the folder the branch was built in. They are relative to lang/ now,
like the others in the file, with the current line numbers. No text
or translation changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 11:01:29 +02:00
Beat Hangartner 446479e8d2 Fix a crop in progress outliving an undo or the picture's removal
While a picture was being cropped on the folio:

- Ctrl+Z or Ctrl+Y of an earlier crop of the same picture left the
  crop handles where they were, 10 px beside the frame for a crop
  that starts at (10, 10).
- undoing the picture's insertion dropped the crop but left the
  picture as the folio's keyboard item, also after a redo put it
  back.

setImageSource() and leaving the scene now end the crop without
applying it. Nothing is pushed on the undo stack from there, since
both can run inside an undo command. Delete and cut are unchanged:
they deselect the picture first, which applies the crop as its own
undo step before theirs.

No file-format change. Not covered by an automated test: crop mode
needs a folio and its view, which a test can only get from the
application object library of #1431. Checked with a throw-away test
on a local merge of both branches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 11:01:29 +02:00
Beat Hangartner 8261524208 Put the Escape comment back on m_drag_cancelled
The comment "Escape pressed: ignore the rest of this mouse gesture"
explains m_drag_cancelled. The crop commit moved it onto the
declaration of dragCropHandle(), added below it. No code changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 10:54:42 +02:00
ispyisail ada516d103 Merge remote-tracking branch 'upstream/master' into fix/report-arrow-without-terminal
# Conflicts:
#	tests/qttest/tst_resaveunchanged.cpp
2026-10-10 21:12:49 +13:00
ispyisail 420e211383 Merge pull request #1444 from ispyisail/fix/table-chain-deleted-folio
Fix a split table going blank and crashing after a folio is deleted
2026-10-10 21:12:06 +13:00
Laurent Trinques fb226d435e Terminal strip: add an anti-parallel diodes terminal type
Add ElementData::TTAntiParallelDiodes (xml value "antiparallel_diodes"),
selectable in the element editor, the terminal strip editor and the free
terminal editor, and drawn in the terminal strip plan as two diodes wired
in opposite directions between the top and the bottom of the terminal.
2026-10-10 10:01:12 +02:00
ispyisail 5b98f1a1e9 Skip the folio-deletion test where --run is not built
CI builds without Qt Qml, so --run is not compiled in and the test's
QElectroTech opened the project and waited until the 180 s timeout.
The test now skips when QET_HAS_SCRIPTING is not defined, as the other
--run tests are left out of such builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Wga9B92BNurDEtxxtCDxf
2026-10-10 20:56:25 +13:00
ispyisail 8d8a998f75 Merge pull request #1445 from ispyisail/fix/db-stale-after-edits
Fix the project database going stale after folio, symbol and wire edits
2026-10-10 20:54:01 +13:00
Laurent Trinques daa648099b Terminal strip: save the layout (font, cell sizes...) in the project
The default terminal strip layout was rebuilt at every project load,
so the font size set in the layout editor was reset to 15 px.
Add TerminalStripLayoutPattern::toXml/fromXml and
TerminalStripLayoutsHandler::toXml/fromXml, write a
<terminal_strip_layout> element in QETProject::toXml() and read it
before the diagrams are loaded. Projects without it keep the defaults.
2026-10-10 09:49:42 +02:00