At the printer's own resolution (600-1200 dpi) symbols and texts were
replayed many times too big next to the wires and grid. Seen on a test
print to PDF; the same page now matches qet_export's PDF.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QElectroTech (LiveServer):
- print: folios to the default (or a named) printer with no print dialog,
always after asking the user (paper cannot be undone); or to a new PDF
file. Rendered as the PDF export draws a folio (no grid, no terminals).
- save_project (own file, or save as a new file, never over one) and
close_project (only without unsaved changes: never discards work).
- changes: the undo history, each step marked assistant or user, with
"since" to ask what changed after a point.
- snapshot: a copy of the open project as on screen, for a check to read,
without saving it or changing its file.
- qet.elementTextGeometry(): where a symbol's text is drawn on the folio.
qet MCP server:
- qet_live_print, qet_live_save_project, qet_live_close_project,
qet_live_changes, qet_live_layout_check (snapshot + qet_layout_check, no
"run this script?" window); write paths never overwrite.
- Layout rules from the house style, for file and live checks alike:
label_on_wire, four_way_junction, misaligned_branch.
- The element index is saved under ~/.cache/qet-mcp: a new server process
loads 8839 symbols in 0.4 s instead of parsing them for 6.9 s; the
change check is a third faster.
- qet_about lists the installation's standard symbols
(standard-symbols.json in QElectroTech's data folder) when there are any.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
openAndAddProject() asked "Créer une copie de sauvegarde ?" even when
called non-interactively, so open_project waited for an answer from the
user in front of the window. Only live mode opens projects that way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
open_project opens a .qet and makes it current, as File > Open does but
with no file dialog and no error windows: a missing, unreadable or
foreign file is refused in the answer. A project already open is only
made current. switch_project makes another open project current, by its
index or its file. status now lists every open project (index, title,
file, folios, unsaved changes, current), so the assistant sees what it
can switch to. MCP: qet_live_open_project, qet_live_switch_project; both
paths go through the workspace policy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An assistant in live mode could only work on the project already open.
new_project makes one as File > New does -- this installation's
new-folio defaults, optional title and number of folios -- and makes it
the current project, so the next request works on it. An optional
absolute path saves it at once, never over an existing file: QElectroTech
refuses, and the MCP server refuses before asking (a new never-overwrite
class in its path policy, so an "overwrite" flag cannot get round it).
Pages and links across pages already worked through scripts
(qet.addFolio, setFolioTitle, linkElements across folios); the tool's
description now says so.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A request with "timing": true gets queue, confirm and exec times in its
answer; with QET_LIVE_PERF_LOG set, QElectroTech also appends one JSON
line per request, with the time until the folio is next painted. The
qet MCP server logs its side of each live call to the same file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stacking added in #1287 tested the crosses' bounding rects, so
crosses whose frames or empty margins touched were raised although no
text was hidden (the list display case found in review). The texts each
cross really draws are now recorded while its geometry is built, and a
cross is raised only when one of its texts would be drawn over a text of
another one.
A new "Empiler les références dont les textes se chevauchent" checkbox
in the cross reference properties, per type, turns the stacking off;
the crosses of that type are then only centred, as before #1287. It is
saved in the project (xref attribute "stackoverlapping") and in the
settings, and is on when absent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The qet theme now lists Nuri's app icon PNGs under the name
qelectrotech, and the wizard loads its logo by that name instead of
the 256 px file path. The files stay in ico/breeze-icons/, where the
packaging scripts install them from.
Part of #1269.
ellipse-to-bezier, rect-to-bezier and rect-to-polyline are now drawn
pixel by pixel at 16 and 22 px, with the 1 px lines and hollow handles
of the line tool, and follow the theme's text color. The polyline is
simpler: at menu size the three-segment line with a handle on every
corner was too much detail to read, so it is now two segments rising
to a peak with a handle at each foot. Andre agreed to the redraw under
GPL-2.0-or-later.
Part of #1269.
Each folder now holds icons from one source: qet/ for QET's own SVGs,
breeze/ for KDE Breeze (with breeze/added/), flags/, colors/, and
themes/ for script output (with themes/generated/). The unused
128x128/terminalstrip.svg is removed. The generator, qrc files,
qeticons.cpp and ico/copyright follow the new paths. ico/README.md
lists each folder's source, script and license.
Part of #1269.
Cause: in list mode `drawAsContacts()` adds a margin (`adjust(-30, -4, 4, 4)`) to `boundingRect()`, and the horizontal test in `stackAtBottom()` uses that rect. Two lists overlapping only inside the empty margin (1.4 units in my log) count as overlapping. `gap` only changes how far the raised ones move, not which ones.
Fix: test the content only in list mode (`rect.adjust(30, 0, -4, 0)`), with the two margins as constants shared with `drawAsContacts()`.
Result: all references stay at the bottom (980 -> 980), none raised by mistake, also when moving an element sideways.
Checked: [to complete: same-column coils in list mode still stack, cross mode unchanged]
A text group kept at the bottom of the page, on a master element,
connects to its project's XRefPropertiesChanged with a lambda that has
no context object. The connection belongs to the project, so it
outlives the group: once the group is deleted (paste a coil, undo,
then make any other edit), changing a cross-reference setting in the
project properties calls QTimer::singleShot() on the freed group and
QElectroTech crashes.
Pass the group as the context of that connection and of the
linkedElementChanged one beside it, so Qt removes both when the group
goes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
startEdition() records the bounding rect, but the aligned point was only
restored in endEdition(), so a right/centre/bottom-aligned text grew from
its old left/top edge while being typed into and jumped into place when
the edition ended. Re-anchor after every content change during inline
edition.
endEdition() now always clears previous_text, which marks an edition in
progress. It used to stay set after an edition that left the text
unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
itemsBoundingRect() also counts hidden items. The text of a single-line
wire, and the wire texts hidden by "one text per potential", are never
positioned again and can sit far outside the drawing, so Zoom to content
zoomed out to include them. On photovoltaique.qet 14 such texts reach
x = -729 and the zoom covered 2421x924 instead of 1135x648.
Add Diagram::visibleItemsBoundingRect() and use it for Zoom to content,
the scene rect and the borderless export. Zoom to content now goes through
zoomToRect(), which re-centres after the scroll bars appear; before, the
view could stay scrolled to the top-left with part of the content cut off.
Fixes#1281
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A conductor draws a junction dot at each of its bends that lies on
another conductor. It only looked at the conductors on its own two
terminals, so a bend lying on a conductor of the same potential that
shares no terminal with it got no dot. Dragging the horizontal parts of
a chain of conductors onto one line, as in the report, does exactly that.
Look at every conductor of the potential on the folio instead
(relatedPotentialConductors(false)). The folio scene uses NoIndex, so a
scene lookup at each bend scans every item and made export of the
366-conductor Polonez example 60% slower; walking the potential costs
nothing measurable there (2.08 s vs 2.11 s) or on a 153-conductor
potential (0.97 s both).
The test for one other conductor moves into bendMakesJunction(). It
also stops a point being appended once per matching segment: master drew
the dot above K2 in the fixture ten times.
Across the 23 examples (133 folios) exported to SVG, 6 dots are added,
all at T-joints that had none, and none removed.
tst_junctiondots exports fixtures/junction_dot_shared_potential.qet and
checks for both dots; it fails on master with the dot above K3 missing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With "snap to bottom", each master's cross was centred under it at the
bottom of the folio on its own, so two coils in one column drew their
crosses on the same spot and the references printed over each other.
The crosses of a folio are now placed together: when two would overlap,
the one of the higher element goes above the other, so a column of
coils gets its crosses in the same order. Crosses that do not overlap
stay where they were. Moving an element sideways now re-places them
too, since it can move a cross into or out of another's column.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With SOURCE_DATE_EPOCH set, the document id came from the project's uuid
and a hash of the .qet file. A project generated again from the same
data has new uuids, so its PDF differed in the id alone (XMP DocumentID
and trailer /ID, 120 bytes) although every page was the same.
Qt now writes a fixed placeholder id, and once the file is written the
placeholder is replaced with an id derived from the bytes of the PDF:
the same pages give the same id. Same length, so no offset changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lupdate (run on qet_en.ts only) found strings added since the last
update that the English interface showed in French:
- wires per terminal (#1272, #1273): the rules in Settings > General
and Project properties, the experimental-feature warning, and the
tooltip on a terminal that refuses a conductor (both plural forms);
- Display > Show (#1268): the item kinds and the "%n kinds of items
hidden" status message;
- the 3D mouse settings page.
Terms follow the existing English: conductor (conducteur), terminal
(borne), sheet (folio), sheet reference (renvoi de folio). The menu
"Affichage" is "Display", so its "Afficher" submenu is "Show" rather
than lupdate's guess "Display". lrelease reports 3573 finished,
0 unfinished. Other languages are untouched.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qet_element_search matched every word as a substring of the names and
the path, so "NC contact" offered a remanence coil ("nc" in "remanence",
"contact" in its folder) and an outlet before any auxiliary contact,
"normally closed contact" found nothing, and "emergency stop" ranked a
maker's part and two assembly-plan drawings above the push button.
- A word of one or two letters must now be a whole word. Longer words,
and short ones with a digit, still match inside a word, so German
compounds ("schutz", "klemme") and "3p" find what they found before;
on 37 sample queries no result is lost.
- NO, N/O, "normally open", "normalement ouvert" are one word, and NC,
N/C, NF, "normally closed", "normalement fermé" another.
- Symbols under *_graphics, *_manufacturers_articles and
*_miscellaneous_unsorted come after every other match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Circle and ellipse had a blue square handle and the arc none; all three
now have hollow 3 px handles and 1 px lines, like draw-line. Breeze draws
transform-crop as a crop mark at 16 px and a dashed box at 22, so a 16 px
dashed box in ico/breeze-added/16/ replaces Breeze's 16 and 32 px art.