Commit Graph

696 Commits

Author SHA1 Message Date
ispyisail 2eed3acd3d Merge pull request #723 from IBSYSLevi/feature/cabinet-layout
Added width/height/depth properties to elements
2026-09-16 18:51:34 +12: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 061f07ef9e Merge branch 'master' into fix-informations-tab-visibility
# Conflicts:
#	sources/editor/ui/elementpropertieseditorwidget.cpp
2026-09-13 00:30:27 +12:00
ispyisail 88f5af08d7 Merge branch 'master' into fix/bugtracker-243-copy-from-readonly 2026-09-12 23:06:47 +12:00
ispyisail b18904415e Persist elementInformations for Slave elements too
Making the Informations tab visible for Slave elements is only half the
change: ElementScene::toXml() writes the <elementInformations> block for
Simple, Master, Terminal and Thumbnail, and Slave was not in that list. It
is the only place in the tree that writes that block, so the editor would
have shown an editable tab for a slave, accepted whatever the user typed
into it, and dropped it silently on save.

Visible in the shipped collection, which matches the condition exactly:
0 of 75 slave elements carry an <elementInformations> block, against 41 of
70 terminal elements.

Adding Slave is safe in both directions. ElementData::fromXml() reads
<elementInformations> unconditionally, with no check on the base type, so
existing slave elements are unaffected and newly written ones load back
correctly. It also makes populateTree()'s PLC-slave branch reachable for
the first time -- the five PLC info rows it adds are stored in
m_informations, so until now they could not have been saved either.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 22:33:04 +12:00
ispyisail 18477c22b5 Merge branch 'master' into fix/element-editor-info-tab-slave-terminal-663 2026-09-12 22:32:39 +12:00
Laurent Trinques a583b3c43c Merge pull request #688 from IBSYSLevi/fix/saving-coil-master
Fix: saving coil master
2026-09-08 08:35:00 +02:00
Laurent Trinques 1738c3ad6c Merge pull request #771 from Kellermorph/spinbox-crossref
Add configurable distance between label and slave XRef
2026-09-08 08:20:33 +02:00
Laurent Trinques 1793dcb9a8 Revert "Feature: Terminal potential grouping" 2026-09-07 15:44:12 +02:00
Laurent Trinques cc7aaf3538 Merge pull request #804 from IBSYSLevi/feature/terminal-potential-grouping
Feature: Terminal potential grouping
2026-09-07 15:08:00 +02:00
Jeff Patterson 825a1a594d Fix element editor Mirror and Flip to reflect the selection in place
Mirror (M) and Flip (F) in the element editor reflected the selected
parts across the element origin: every part's mirror() and flip()
negated the scene x or y coordinate. A part drawn to the right of the
origin landed the same distance to the left, so the selection jumped
to the other side of the canvas instead of turning around.

MirrorElementsCommand and FlipElementsCommand now compute the united
scene bounding rectangle of the selected items and reflect across the
vertical or horizontal line through its center. The center is snapped
to the nearest half of the diagram grid, so points that were on the
grid stay on the grid after the reflection. Terminals in particular
keep their grid alignment.

Each part's mirror() and flip() takes the axis coordinate as a
parameter with a default of 0, so the previous behavior remains
available to any other caller. The command stores the axis when it is
created and undo reapplies the same reflection, which is its own
inverse, so the existing undo path is unchanged.

Parts covered: PartArc, PartDynamicTextField, PartEllipse, PartLine,
PartPolygon, PartRectangle, PartTerminal, PartText.

Fixes #812
2026-09-06 06:48:45 -05:00
Kellermorph a494a8fd6c Add 'Text field' option for slave cross-reference positioning 2026-09-05 18:55:14 +02:00
Levi Jetzer 1e1039dd32 Address review
1. Drop dead prepareGeometryChange()/update() calls in
setPotential(), split unrelated terminaleditor.h re-indent into its
own change

2. Removed: setPotential() had prepareGeometryChange()/update() left over from
the label-display mechanism that was dropped before this PR
2026-09-04 13:12:21 +02:00
ispyisail 95d7b74e9e Merge remote-tracking branch 'upstream/master' into pr721-merge
# Conflicts:
#	sources/editor/ui/elementpropertieseditorwidget.cpp
2026-09-04 22:05:13 +12:00
Levi Jetzer 10bf0411bb Add "Potentiel" field to the terminal editor (element editor)
New QLineEdit (m_potential_le) between Type and Nom: an optional,
symbol-author-chosen grouping identifier shared by terminals that
belong to the same physical terminal within a multi-terminal block.

Stored as TerminalData::m_potential (new field, persisted as the
"potential" XML attribute, empty by default).
Used by relatedPotentialTerminal() in terminal.cpp: when
potential_isolating is enabled on a Terminal-type element, terminals
sharing a non-empty, matching potential value now stay electrically
linked to each other instead of every terminal in the block being
isolated from every other one.

Tooltip on the field for explanation
2026-09-02 19:30:26 +02:00
ispyisail 3ca5d4ab29 Fix GitHub issue #798: element editor crash on scroll-wheel zoom
ElementView applied scale() on every wheel notch with no bound on the
resulting view transform. Held down, the scroll-wheel zoom drives the
transform scale (m11) to floating-point overflow; the transform becomes
non-invertible, mapToScene() returns NaN and the next background paint
aborts the editor ("program closes completely" as reported on Windows).

Route zoomIn/zoomOut/zoomInSlowly/zoomOutSlowly through a new
scaleClamped() helper that only applies the scale while the result stays
within [m_min_zoom, m_max_zoom] (0.1 .. 200). Behaviour within that range
is unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdWpDp3TrPKbHnv7YUcNJj
2026-08-31 05:45:35 +12:00
Laurent Trinques 487b22f483 Merge pull request #769 from Kellermorph/layout-fix
Fix dock widget size/position not being restored on Qt6
2026-08-28 09:25:00 +02:00
Kellermorph 8f6f41ed19 Clean up readSettingsState() in all three editors
- Remove dead #if QT_VERSION conditionals (both branches were identical)
- Add settings.remove() guard on restoreState() failure consistently
  across all three editors (now safe since all run after show())
2026-08-23 18:25:23 +02:00
Kellermorph 61a160fa62 Fix restoreState() for QETElementEditor and QETTitleBlockTemplateEditor on Qt6
Apply the same split readSettings()/readSettingsState() pattern from
QETDiagramEditor to the other two main windows:
- QETElementEditor: split in constructor, call readSettingsState() after show()
- QETTitleBlockTemplateEditor: split readSettings(), callers call
  readSettingsState() after show() (newTemplate + 2x openTitleBlockTemplate)
- Remove destructive settings.remove() guards that would delete saved
  state on every Qt6 launch when restoreState() fails before show()

Co-authored-by: ispyisail
2026-08-23 10:37:52 +02:00
Kellermorph 4edd4932bb Fix PLC table dangling reference warning and row deletion 2026-08-22 16:42:13 +02:00
Kellermorph f6afd87522 Fix dock widget size/position not being restored on Qt6 2026-08-22 11:08:02 +02:00
plc-user 5db77fe40c Merge pull request #747 from ispyisail/fix/parttext-real-font-size-desync
Fix real_font_size_ desyncing from the actual font in PartText
2026-08-22 10:27:14 +02:00
Levi Jetzer 31feb7b7b0 Show the element editor's Informations tab for Terminal and Thumbnail
setTabVisible(1, ...) only allowed Simple and Master, but the tree
(updateTree()) and the actual write path (ElementScene::toXml()) both
already support elementInformations for Terminal and Thumbnail too --
three independent "is this type allowed" checks that were never
reconciled, leaving already-working support unreachable through the
UI for those two types. Slave stays excluded here, consistent with
having no elementInformations support at either of the other two
points either (separate, larger gap, not addressed here).
2026-08-21 16:23:41 +02:00
Levi Jetzer 622791f994 Remove auto_num_locked/potential_isolating/exclude_from_bom checkboxes'
"false" writes, delete key instead

Unchecking a checkbox previously wrote the key with value "false"
rather than omitting it -- behaviorally identical to every consumer
(all three do a case-sensitive == "true" comparison), but left dead
entries cluttering the .elmt file, inconsistent with how other
elementInformation fields (manufacturer, designation) are only present
when actually set. Now removes the key entirely when unchecked.
2026-08-21 15:59:06 +02:00
Levi Jetzer 7c941e4697 Guard numeric elementInformation fields against "." and normalize decimal comma
- ElementInfoWidget::currentInfo() now skips a field whose validator
  hasn't accepted its text (e.g. a lone "." mid-typing), which
  previously stored and later parsed to 0.
- New QETInformation::NumericInfoValidator rewrites "," to "." before
  validating, so 80,5 on a German/French keyboard no longer silently
  becomes 805. Used at both existing call sites.
- Restored the header's #1/#2/#3 doc comment (was reflowed into a
  run-on paragraph by a previous edit).
2026-08-21 15:16:36 +02:00
Levi Jetzer 884ec4bbb9 Add editable "auto_num_locked"/"potential_isolating"/"exclude_from_bom"
checkboxes to the element editor

These elementInformation keys were previously only editable on an
already-placed instance (via ElementInfoWidget on the diagram side).
Since elementInformation values are seeded from the .elmt file's own
<elementInformations> block at placement time, a symbol author had no
proper way to set these as the *default* for every future placement --
only a workaround via the generic, unvalidated key/value tree.

Adds dedicated checkboxes to ElementPropertiesEditorWidget, mirroring
ElementInfoWidget's own labels/behavior: auto_num_locked and
potential_isolating inside the existing terminal-only group
(m_terminal_gb, shown only for ElementData::Terminal), exclude_from_bom
always visible regardless of type. Written after the generic tree loop
so they take precedence over any stale raw entry for the same key.
No new storage or file format change -- purely a missing editor UI for
an already-existing mechanism.
2026-08-19 17:58:16 +02:00
ChuckNr11 9d81a9788f move position of element editor coord display to center of statusbar
for better visibility only
2026-08-19 12:00:43 +02:00
ChuckNr11 2803dcf8b8 Change live cursor-coordinate readout on running ESEvent
During an ESEvent, the mouse position was used without format with
`snapToGrid` to display the coordinates. However, since the `helpCross`
is positioned using `snapToGrid` during these events, the displayed
coordinates did not match the `helpCross` position.
The command for sending the coordinates has been moved to the
`ESEventInterface` to function 'updateHelpCross' and now transmits the
position of the intersection point of the helpCross lines.
2026-08-18 14:19:33 +02:00
Levi Jetzer fb0649ceee Fixed incorrect OR and AND checks 2026-08-14 22:23:25 +02:00
Kellermorph fe6191f26d Fix slave contact groups being trimmed to one when reopening element properties 2026-08-14 10:31:15 +02:00
ispyisail 3077527601 Fix real_font_size_ desyncing from the actual font in PartText
Follow-up to #158 / PR #501. While investigating that position bug,
found a second, separate one in the same area: PartText::setFont()
never updated real_font_size_, so it stayed frozen at whatever size the
item was constructed with.

That field isn't cosmetic - it's live data two other operations depend
on:

- startUserTransformation()/handleUserTransformation() use it as the
  base size when scaling the font as the user drags a resize handle.
  With it stale, dragging a handle after changing the size via the
  toolbar (or loading a file with a non-default size) scales from the
  wrong starting point - the resulting size has nothing to do with
  what's visibly on screen.
- flip() reads it directly to compute the repositioning offset, so a
  stale value also mis-positions the item on flip.

Fix: update real_font_size_ inside setFont(), the same place PR #501
already re-runs adjustItemPosition() for the same reason (font changed,
keep everything that depends on it in sync). fromXml() already routes
both its "size" and "font" attribute branches through setFont(), so
loaded elements pick this up for free.

Verified with a temporary instrumented build: typed a size into the
element editor's font-size field three times (9 -> 4 -> 48). Each
setFont() call's "before" value exactly matched the previous call's
"after" value, confirming real_font_size_ now tracks every change
instead of freezing at its construction-time value (9). Instrumentation
removed before committing.
2026-08-14 20:21:16 +12:00
Andre Rummler 6d05bc2f21 Remove all Qt version checks and branches for <5.15.12 as such versions are no longer supported. 2026-08-13 16:20:30 +02:00
Andre Rummler 7ba295a339 Remove all Qt version checks and branches for <5.14.0 as such versions are no longer supported. 2026-08-13 15:45:15 +02:00
Laurent Trinques 2186d2733f Merge pull request #709 from arummler/master-continue-qt6-migration
Qt6 migration beyond signal/slot
2026-08-13 10:55:47 +02:00
ispyisail 6f9f5f84c2 Fix bugtracker #243: allow copying out of a read-only element
Opening an element you cannot write -- anything from the QET collection,
for instance -- disabled Copy along with everything else, so there was no
way to reuse a primitive from it. The workaround was to save the whole
element into your own collection first, just to take one shape out of it.

Two actions stood in the way, and neither of them modifies anything:

- Select All and Invert Selection were in the list disabled outright when
  read only, so nothing could be selected in the first place;
- Copy was enabled only when "!m_read_only && selectedItems().count()", so
  even a mouse selection left it greyed out.

Both now work on a read-only element. Copy is safe there:
ElementScene::copy() serialises the current selection to the clipboard and
touches neither the element nor the file.

Cut, Paste, Paste-in-area, Delete, Rotate, Flip, Mirror, the depth actions
and the add-primitive tools stay disabled exactly as before, so the element
is still protected -- this only stops the editor from refusing to read out
what it is already displaying.

Verified with a chmod 444 element: Select All then Copy now work, the
clipboard receives the expected <definition> with all three primitives,
Cut/Paste/Delete remain greyed out, Save stays disabled, and the file is
untouched (same permissions, same checksum).
2026-08-13 11:28:51 +12:00
Andre Rummler c14d6a6dd6 In order to migrate to Qt6 all options for KF6 were added:
a) using a system provided KF6
b) downloading and compiling KF6
c) using the vendored-in re-creation of the functionality

The behaviour for both Qt5 and Qt6 is steered with the same two variables which were renamed to become version agnostic:
a) BUILD_WITH_KF=ON BUILD_KF=OFF
b) BUILD_WITH_KF=ON BUILD_KF=ON
c) BUILD_WITH_KF=OFF

The version is automatically derived from the chosen Qt major version.
2026-08-12 12:29:56 +02:00
Levi Jetzer 5dbb9f28de Fix numeric field validation gaps found in review
Address feedback on the width/height/depth elementInformation fields:

- The regex accepted "." alone as a complete value ([0-9]* permits
  zero digits on both sides), meaning a field could be committed with
  a literal "." saved to the XML. Require at least one digit either
  before or after the separator.
- The same pattern was duplicated verbatim in elementinfopartwidget.cpp
  and elementpropertieseditorwidget.cpp's EditorDelegate. Factored into
  QETInformation::numericInfoPattern(), a single shared definition both
  call sites now use.
- Tightened the pattern to at most 2 decimal places (down from 4) to
  match the precision actually meaningful for these fields.

Not changed, by design:
- Storage stays a plain string, consistent with every other numeric
  elementInformation field (quantity etc.) in this codebase -- values
  round-trip through XML text regardless, so a long/micron
  representation wouldn't avoid the string<->number conversion, only
  relocate it.
- No decimal-comma normalization needed: with the fixed pattern, only
  digits and "." are ever accepted at the keystroke level, so an
  alternate separator can't enter the field in the first place.
2026-08-12 08:43:42 +02:00
ispyisail 762bd7febf Fix bugtracker #333: selecting several dynamic texts overwrites their colours
Selecting more than one dynamic text field in the element editor silently
replaced every selected field's colour with the colour of the first one.
Nothing was clicked -- merely extending the selection destroyed the others'
colours, and the change went onto the undo stack as if the user had asked
for it.

Cause: updateForm() loads the current part's colour into the colour button
with m_color_kpb->setColor(). KColorButton::changed is emitted for a
programmatic setColor() just as it is for user interaction, and it is
connected to m_color_kpb_changed(), which applies the new colour to *every*
part in m_parts. So simply displaying the first part's colour wrote that
colour to all the others.

Every other widget in updateForm() is immune because it is wired to a
user-only signal -- on_m_x_sb_editingFinished(), on_m_frame_cb_clicked() --
which setValue() and setChecked() do not emit. The colour button is the one
control whose signal cannot distinguish the two, so block it while loading.

This also explains why the reporter saw it only when rubber-band selecting
bottom-to-top: the write happens only when the first part's colour differs
from what the button already shows, which depends on selection order.

Verified in the element editor with two dynamic texts, one red and one blue:
select the red one, then ctrl-click the blue one. Before: the blue text
turned red. After: both keep their colours. Changing the colour deliberately
with the button still applies to all selected texts, as intended.
2026-08-12 15:53:30 +12:00
Levi Jetzer 7347322221 Replace QDoubleValidator with QRegularExpressionValidator on width/height/depth fields
The selection properties dock (elementinfopartwidget.cpp) and the
element editor's information tree (elementpropertieseditorwidget.cpp's
EditorDelegate) both restrict the width/height/depth fields added for
cabinet layout support to numeric input via a validator.

QDoubleValidator follows the system/UI locale for its decimal
separator, which meant a comma was accepted as an intermediate state
and left the field impossible to leave in some contexts, even though
it was never a valid final value.

Switch both to a QRegularExpressionValidator matching
^[0-9]*\.?[0-9]{0,4}$: "." is a literal character in the pattern, not
locale-dependent, and [0-9] (rather than \d) excludes non-ASCII
digits. This guarantees a value entered this way can always be read
back with QString::toDouble() without locale handling. The check for
which keys are numeric (QETInformation::isNumericInfoKey) is shared
between both call sites; the validator setup itself stays local to
each, since QETInformation intentionally has no Qt Widgets dependency.

Also adds a placeholder ("ex. 80.5") and tooltip explaining the
expected format.
2026-08-11 18:01:10 +02:00
Levi Jetzer c23999acd1 Added width/height/depth properties to element definitions
Adds three new elementInformation keys — width, height, depth (in mm)
— alongside the existing manufacturer/manufacturer_reference fields.
These describe the physical dimensions of the device a symbol
represents, set once per element definition.

Values are restricted to plain decimal numbers via a QDoubleValidator
on the information tree's item delegate (fixed-point, "." as decimal
separator via QLocale::c(), independent of the UI language), so a
later consumer can always parse them with toDouble() without
additional sanitization.
2026-08-11 16:09:34 +02:00
ispyisail 7afc1eb56b Enable Information tab in element editor for Slave and Terminal basetypes
GitHub issue #663: the "Informations" tab in the element editor's
properties dialog was only made visible for Simple and Master basetypes
(setTabVisible gate in on_m_base_type_cb_currentIndexChanged), hiding it
entirely for Slave and Terminal Block elements.

This wasn't a data-model limitation: ElementData::m_informations is read
and written identically for every basetype (elementdata.cpp), and
updateTree() already special-cased Terminal as enabled and injected
PLC-specific info rows for PLC Slave elements - that logic was simply
unreachable because the tab itself was hidden for both types. Also
flipped updateTree()'s Slave case from setDisabled to setEnabled so the
tree is actually editable once visible, matching Terminal's existing
behavior.

This lets users attach manufacturer/part-number/reference metadata
directly to Terminal Block and Slave (e.g. multi-part contactor)
elements, as requested in the issue - useful when a Slave's part number
differs from its Master's (e.g. a contactor's auxiliary contact block
vs. its coil).

Not verified: interactive element-editor GUI testing wasn't performed
in this sandbox; verified via clean incremental build only.
2026-08-11 18:00:43 +12:00
Laurent Trinques 7f75500023 Merge pull request #694 from IBSYSLevi/feature/center-rotation-option-for-textfields
Feature added: Rotation point center property for dynamic text fields
2026-08-09 21:09:19 +02:00
Laurent Trinques cdf5cad1e5 Merge pull request #698 from arummler/master-modernize-signal-slot
Migrate string based signal/slot to method pointer
2026-08-09 21:08:28 +02:00
Kellermorph 5e02111600 Fix-PLC-Warnings 2026-08-09 18:27:20 +02:00
Andre Rummler c7ed3229d0 Migrating more SLOT() macros. 2026-08-09 12:30:15 +02:00
Andre Rummler 5adf61936b Merge branch 'master' into master-modernize-signal-slot 2026-08-08 23:13:42 +02:00
Andre Rummler 90950075bf Three connects paired a zero-argument signal with a slot that has a default-valued parameter (e.g. void applyEnable(bool = true)).
Default arguments aren't part of a function's pointer-to-member type, so &Class::slot has a type requiring the argument regardless of its
default value -- incompatible with a signal providing none, and &Class::slot alone won't compile against these signals at all.
When migrating to the modern member pointer connect, replaced  with a lambda that calls the slot with no arguments, letting
the default apply exactly as before.

- SelectAutonumW::applyEnable(bool = true), connected to each  NumPartEditorW's changed() signal in both setContext() and
  on_add_button_clicked(). The corresponding disconnect() in on_remove_button_clicked() is removed rather than reimplemented: a
  lambda-based connection can't be matched and removed by a  separately-written disconnect() call, and the explicit disconnect
  was already redundant -- the very next line deletes the part object, which Qt automatically disconnects on destruction (the same
  guarantee setContext()'s own qDeleteAll() cleanup already relies  on).
- PartText::adjustItemPosition(int = 0), connected to QTextDocument::contentsChanged().
- ExportDialog::slot_changeFilesExtension(bool = false), connected to ExportPropertiesWidget::formatChanged().
2026-08-08 21:39:31 +02:00
Andre Rummler a668ccfa90 Migrating the remaining signal/slot connects with an ambigious activated(int) via qOverload<int>,
since QComboBox::activated(QString) still exists pre-Qt6 and makes &QComboBox::activated alone ambiguous:

- StyleEditor: outline_color/line_style/size_weight/filling_color,
  both connect (activeConnections(true)) and disconnect
  (activeConnections(false)) branches. antialiasing's stateChanged(int)
  connect modernized alongside them (single signal, no disambiguation
  needed).
- TitleBlockTemplateCellWidget: cell_type_input_ (two connects to
  different slots), horiz_align_input_, vert_align_input_, logo_input_.

Also modernises QETApp's system tray connect.

In two cases stateChanged already replaced with version guarded checkStateChanged for future proofing.
2026-08-08 21:29:17 +02:00
Levi Jetzer 615e40dee2 Feature added: Rotation point center property for dynamic text fields
Now a new checkbox in the dynamictextfieldeditor is available (by default set to false for legacy) to make it possible to turn dynamic text fields around its own center.
This resolves an undesirable behaviour that occurs when the text alignment is retained

Including translation to english and german
2026-08-08 11:10:36 +02:00
Levi Jetzer d7c75ea5a5 Fixed saving coil master -> correction +
Added space for a better style ;)
2026-08-08 09:07:22 +02:00