Commit Graph

104 Commits

Author SHA1 Message Date
Laurent Trinques 4888ae87f3 Merge pull request #978 from Kellermorph/feature/refresh-all
fix: update composite text %{label} when folio changes
2026-09-22 07:53:36 +02:00
Kellermorph 8985babfe7 fix: update composite text %{label} when folio changes
DynamicElementTextItem::updateLabel() resolved %{label} in composite
text using the stale value from elementInformations()["label"], which
is only set once at load time and never updated when the folio/page
number changes.

Use element->actualLabel() instead, which resolves the label formula
(including %F, %f, %id) against the current folio at call time.
2026-09-21 21:45:03 +02:00
ispyisail 29d16c3337 Fix #591's resize handles: reachable only via Shift/right-click, wrong position
Two bugs reported by @arummler on #591 after merge:

  "It works but to select the text field one has to right click on
  it...I think there are competing handlers or something."
  "the drag elements should be on the border of the box. In the
  moment they appear directly left and right from the text."

Both reproduced headlessly (scripts/qet-gui-dialog.sh) against a fresh
build of current master and root-caused before touching anything.

Selection: DynamicElementTextItem::mousePressEvent() forwards a plain
click (no Shift) straight to parentElement()->mousePressEvent(), by
design and pre-existing -- it's what lets dragging a symbol by its own
label move the whole symbol rather than just the label. That's correct
and untouched here. But it means a plain click leaves the *parent*
selected, not the text, and #591's handles were wired only to the
text's own ItemSelectedHasChanged -- so they were only reachable via
Shift+click or a right-click's context menu (which happens to select
the item under the cursor for its own context menu, unrelated to the
Shift path), neither of which anyone reaches for to resize a text.
Confirmed with screenshots at each step, including that Shift+click
already reached the existing (if misplaced) handles correctly.

Fix: DynamicElementTextItem::refreshResizeHandlesVisibility() shows the
handles when either the text itself or its parent element is selected,
and Element gets an itemChange() override (it had none) that calls it
on each of its own texts when the element's own selection changes. Both
sides driven from itemChange(), Qt's own hook for exactly this and the
same one already used for the text's own selection.

First attempt drove this from paint() instead, since the PR's own
updateResizeHandlesPos() already runs there. That crashed reproducibly
(SIGABRT) on deselecting a text: paint() runs while QGraphicsScene
iterates its item list to draw it, and addResizeHandles()/
removeResizeHandles() mutate that list via QGraphicsScene::addItem()/
removeItem(), which cannot safely happen mid-iteration. Caught it with
the same headless repro before it went anywhere near a PR, moved the
logic to itemChange(), and re-ran the full sequence -- select, resize,
undo, deselect, twice through -- clean.

Position: updateResizeHandlesPos() placed the handles on frameRect(),
which is a box sized to the text's natural (idealWidth()) content and
then re-centred inside boundingRect() -- it does not grow with
textWidth(). Once a text has been widened, frameRect() stays tight
around the glyphs while boundingRect() -- the box QGraphicsView actually
outlines as the selection, and the box a user drags relative to -- grows
around it, leaving the handles stranded well inside the visible
selection border. Fix: position them on boundingRect() instead, which
does track textWidth(); confirmed by widening a text and checking the
handle lands exactly on the new edge rather than partway across it.

Verified headlessly end to end on the original report's own element
("motor off" on grafcet.qet, folio 1): a single plain left-click (no
Shift, no right-click) now shows both handles at the true box border;
dragging resizes correctly and the handle tracks the growing edge;
Ctrl+Z restores the -1 auto-width sentinel and the handles stay at the
reverted position; clicking away removes them; repeated twice with no
crash. Qt 6.10.2, ctest 12/12, no new warnings in either changed file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 07:30:39 +12:00
Laurent Trinques d7052e396b Merge pull request #591 from ispyisail/feature-dynamictext-drag-resize
Linux build and tests / Build and test (Qt 6, Debug) (push) Failing after 2m32s
Add drag-to-resize for dynamic element text width (#577 phase 1)
2026-09-21 12:19:22 +02:00
ispyisail bf7bff595e Merge branch 'master' into revive/591-dynamic-text-drag-resize
Bringing the drag-to-resize work up to date with current master (662
commits) before asking for review again. Both files auto-merged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CaKympWT3owLotCpEN2CFj
2026-09-19 11:30:31 +12:00
ispyisail 95d0e523fe Snap a device text to the grid when it is dragged (#923)
Dragging an element's text -- its label, article number, any of its
information fields -- moved it in free one-unit steps while everything
else in the editor snapped to the grid. Reported by pki791 in #923 for
labels moved with Shift.

QET moves a text with the mouse along five paths. Four snap and let Ctrl
place freely:

  DiagramTextItem::mouseMoveEvent        an independent text
  ElementTextItemGroup::mouseMoveEvent   a group of element texts
  ElementTextsMover::continueMovement    every OTHER selected element text
  QetGraphicsItem::setPos                elements, images, shapes

DynamicElementTextItem::mouseMoveEvent, the text actually under the
cursor, ended "setPos(new_pos)" with no grid and no modifier check. It is
otherwise the same function as the group's, which is why this reads as an
omission rather than a decision: the line this adds is that function's,
character for character.

The inconsistency was visible in one gesture. With two element texts
selected and one of them dragged, ElementTextsMover skips the driver item
and snaps the rest, so the text under the cursor was the only one on the
folio that did not land on the grid.

Verified on a virtual display (Xvfb + openbox) against a two-lamp fixture,
grid 10, reading the saved positions rather than the screen:

  Shift+drag the label      before (32.95, -11.55) -> (7.95, 23.45) off-grid
                            after                  -> (10, 20)      on-grid
  the co-selected label     (10, -10) -> (50, 20) on-grid, before and after
  Shift to grab, then Ctrl  -> (7.95, 23.45) off-grid, free placement kept

The last line matters: moving an element text needs Shift at press, and
the modifier is read at move time, so Ctrl still places freely -- press
with Shift, hold Ctrl to drag. Holding both from the press is a different
gesture, reserved by DiagramView::isCtrlShifting() for the view's mode
switch, and does not move the text at all. Nothing that was possible
before is lost.

Worth knowing when reviewing: 470 of the 492 element texts in the 24
example projects (95.5 %) sit off the grid today, because element
definitions place their default text at fractional offsets. The first
drag of almost any existing label will pull it onto the grid, by at most
half a grid step.

ctest 12/12, Qt 6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 08:06:45 +12:00
Kellermorph dad6206386 Address review feedback: parentGroup guard, ELMT_XREF constant, indentation
- Add !parentGroup() guard to stale xref removal in updateXref()
  to prevent deleting xref data that ElementTextItemGroup::updateXref()
  just stored for a grouped text item.
- Replace QStringLiteral("xref") with QETInformation::ELMT_XREF
  in linkelementcommand.cpp and masterelement.cpp.
- Fix indentation in plclinkwidget.cpp.
2026-09-16 11:49:49 +02:00
Kellermorph 9bfe18807f Fix undo not restoring PLC slave fields and stale connections on position change
Two additional bugs found after the initial xref cleanup:

1. Undo after unlink did not restore PLC variables (PLC_TYPE,
   PLC_ADDRESS, etc.) because PlcLinkWidget::on_m_unlink_pb_clicked()
   never stored the current group index in the LinkElementCommand.
   makeLink() only populates PLC fields when group_idx >= 0, so
   the slave was re-linked but appeared empty. Fixed by reading the
   group index from the master via groupIndexForElement() and calling
   setGroupIndex() before unlinking.

2. m_update_slave_Xref_connection was only cleared inside the
   if(m_slave_Xref_item) block in the updateXref() cleanup path.
   For AlignHCenter (Text field) position, no m_slave_Xref_item
   is ever created — the connections are stored in
   m_update_slave_Xref_connection but never cleaned up on unlink.
   On re-link, the old stale entries prevented new connections from
   being established. Fixed by clearing the list unconditionally
   in the cleanup path.
2026-09-14 16:19:37 +02:00
Kellermorph 00e75604b0 Clear stale xref data from PLC slave elementInformations on unlink and position change 2026-09-14 12:04:17 +02:00
ispyisail 9afba7091c Merge branch 'master' into fix-nonfinite-coordinate-validation 2026-09-12 23:07:47 +12:00
ispyisail d74317c87a Merge branch 'master' into fix/slave-xref-color-dark-theme-bug247
# Conflicts:
#	sources/qetgraphicsitem/dynamicelementtextitem.cpp
2026-09-12 22:42:11 +12: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
Kellermorph a494a8fd6c Add 'Text field' option for slave cross-reference positioning 2026-09-05 18:55:14 +02:00
Kellermorph cceddba44e Fix PLC cross-reference links and make cross-ref column clickable 2026-08-28 12:36:03 +02:00
ispyisail 68e507a522 Reject non-finite element/terminal coordinates on load (fixes #781, #782)
QString::toDouble() reports a successful conversion for "nan"/"inf"/
"-inf" -- confirmed directly -- so the existing conv_ok checks in
Element::valideXml() and Terminal::valideXml() never caught a
non-finite x/y. A NaN-positioned element reaching the scene can hang
QGraphicsScene::addItem() forever: an existing conductor's itemChange()
runs a collision test (calculateTextItemPosition() ->
QGraphicsItem::collidesWithPath()) whose underlying QPathClipper spins
without terminating when fed a NaN-valued QPainterPath, since NaN
breaks the ordering comparisons the clipping algorithm's termination
depends on (#781). Short of that, a non-finite value that doesn't
happen to trigger a collision test simply gets written straight back
out on save with nothing to stop it (#782).

Element::valideXml() and Terminal::valideXml() now also check
qIsFinite() on the parsed x/y, rejecting the whole item the same way a
missing attribute already does. DynamicElementTextItem::fromXml() has
no such reject-the-item gate (void return, no caller check), so its x/y
are clamped to 0 instead -- the same fallback the attribute lookup
already uses when x/y is missing entirely.

Verified against both original findings' exact repro steps:
- #781: Habitat-Unifilaire.qet with x="nan" on one element -- hung
  (SIGTERM'd by a 25s timeout) on an unfixed build, resaves cleanly
  (exit 0) on this one.
- #782: grafcet.qet with y="nan" on a dynamic_elmt_text -- the value
  passed straight through to the resaved file on an unfixed build;
  clamped to 0 on this one. The specific field is now stable (y="0" on
  two consecutive resaves) where it read "nan" both times before.
  (grafcet.qet has an unrelated, already-known, unmerged fix
  (PR #779) for element/terminal-order non-determinism, so a whole-file
  diff across resaves still differs for reasons unconnected to this
  change -- checked the specific once-NaN field in isolation instead.)
- Also checked -inf on affuteuse_250h.qet: same rejection, same result.

Full qet-dbcheck.py sweep of the unmutated example corpus (23
projects), 0 regressions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:23:05 +12:00
Kellermorph 6208c7e5df Add configurable distance between label and slave XRef 2026-08-22 12:03:35 +02:00
ispyisail f9cbf2365d Fix bugtracker #247: XRef slave reference hidden with dark themes
DynamicElementTextItem's slave cross-reference sub-item
(m_slave_Xref_item, the small "_(1-D3)_"-style text next to a slave
element pointing back to its master) hardcoded Qt::black in three
places: on creation, on hover-leave, and when restoring color after
text editing. The PARENT text item's color is a real, user-configurable
property (color()/setColor(), persisted in the diagram XML, exposed in
the text editor's color picker) -- but the slave-Xref sub-item never
used it, so a user applying a dark theme/stylesheet had no way to make
this specific text visible even by explicitly setting a text color,
unlike every other text item in the diagram.

Fix: use color() (the parent DynamicElementTextItem's own configured
color, inherited from DiagramTextItem) instead of the Qt::black
constant in all three places. This doesn't change the default
appearance (color() defaults to black, same as before) but makes the
slave-Xref text finally respect whatever color the user sets on the
parent text field, giving dark-theme users the same escape hatch
already available for all other diagram text.

Verified: clean rebuild, only the intended object file recompiled and
linked successfully.

Not verified: a live visual confirmation of the slave-Xref text
picking up a non-default color, since reproducing this requires
constructing a master/slave-linked element pair with composite text
containing %{label} in an actual multi-folio project, which was out of
scope for the time available. Confidence rests on this being a direct,
mechanical substitution of an existing, already-used accessor
(color()) for a hardcoded constant, applied identically to the exact
three call sites that previously hardcoded Qt::black for this item,
with no other logic changed.
2026-08-11 12:51:54 +12:00
Levi Jetzer 3424ba50bd Fix transform origin not applied on load or delayed activation
setTransformOriginPoint() was only applied inside
parentElementRotationChanged(), so loading an already-rotated element,
or enabling keep_visual_rotation while rotation_point_center was
already true, left the origin at (0, 0) until the next parent rotation.

Apply the origin directly in both setters so it's always in sync.

Added .ts files (de and en) to the commit
2026-08-08 20:06:32 +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
ispyisail 81449faffd Add drag-to-resize for dynamic element text width (#577 phase 1)
Adds two QetGraphicsHandlerItem grip handles at the left/right edges of a
selected DynamicElementTextItem's frameRect(), reusing the exact same
handle class, scene-event-filter wiring, and live-drag-then-undo-on-release
pattern QetShapeItem already uses for its own diagram-level resize handles
(sources/qetgraphicsitem/qetshapeitem.cpp).

- Handles are created/destroyed on ItemSelectedHasChanged, matching
  QetShapeItem's convention (and ElementPrimitiveDecorator's, for the
  element editor's own primitives).
- Position is recomputed in paint() rather than hooked to specific
  mutators, since textWidth/font/text/rotation can all move frameRect()
  and there's no single itemChange notification that covers all of them.
- The drag delta is resolved through mapFromScene() into the item's own
  local coordinates, so a rotated text box still resizes along its own
  baseline rather than along the scene's x-axis.
- setTextWidth() is called live during the drag for immediate visual
  feedback (matching how QetShapeItem's handlerMouseMoveEvent live-updates
  geometry); only on release is a QPropertyUndoCommand pushed -- the exact
  same command the properties-panel width spinbox already uses
  (sources/ui/dynamicelementtextmodel.cpp), so no new undo-command class
  or XML was needed.
- The original textWidth() value is preserved as-is (including -1, the
  "auto" sentinel) for the undo command's old_value, separately from the
  concrete baseline used for the live drag's delta math -- otherwise an
  undo would replace "auto width" with a synthesized fixed width instead
  of actually restoring the auto-sizing state.

Scoped to DynamicElementTextItem per the discussion's phase 1 (the
buildable, no-new-XML piece); IndependentTextItem and the element editor's
PartText/PartDynamicTextField have no serialized width property to resize
yet and are left as explicitly out-of-scope follow-ups.

Verified headlessly (Xvfb + xdotool + scrot): selecting an element's
label text shows the two handles, dragging one live-resizes the text
(confirmed via the properties panel's width field updating in real time),
and undo/redo correctly restores the exact original width including the
auto-width (-1) case.
2026-08-01 17:51:26 +12:00
Laurent Trinques 46cceb328e Merge pull request #582 from DieterMayerOSS/pr/font-legacy-format
Write font descriptions in a version-stable format (#553)
2026-07-31 10:30:49 +02:00
Dieter Mayer 68ffacc9e6 Salvage font descriptions written by Qt 6.11+ when parsing fails
QFont::fromString() of Qt 5.x and Qt <= 6.10 rejects the >= 19 field
descriptions QFont::toString() emits since Qt 6.11, silently leaving a
broken font at every read site. Add QETUtils::fontFromString(): try the
native parser first, and on failure re-compose the legacy 10/11 field
form from the known Qt 6.11 field layout (OpenType weight mapped back
to the legacy scale) so no font information stored in existing files is
lost. Also salvage the 21 field double-serialized descriptions left
behind by some historical builds (a complete legacy description
embedded as the family name of a second one) by taking the embedded
leading description, matching what the lenient parser of Qt 6.11+
resolves them to. All font read sites now go through the helper; on
failure the default font of the caller is left untouched instead of a
cleared family.

Verified end to end on a Qt 5.15 build: a project whose 53 font
attributes were rewritten into the 19 field Qt 6.11 format loads and
autosaves byte-identical to the original legacy file (family, sizes,
bold/italic/underline, style name all preserved), and a mixed file
containing the exact 21 field string from the issue comes back
normalized as "Caladea,9,-1,5,75,1,0,0,0,0,Bold Italic".

See issue #553.
2026-07-31 08:10:34 +02:00
Dieter Mayer 5da1fe5fc8 Write font descriptions in the stable Qt 5 10/11-field format
QFont::toString() is not stable across Qt versions: Qt 6.11 switched to
a 19-field format carrying OpenType weights, which QFont::fromString()
of Qt 5.x and Qt <= 6.10 rejects, leaving a broken font. Projects saved
by a Qt 6.11+ build were therefore unreadable by older builds.

Add QETUtils::fontToString() composing the legacy 10/11-field
description (weight mapped back to the legacy scale with the same
closest-match table Qt uses when parsing) and use it at every site that
stores a font description in a project, element, table config or
settings file. Every Qt version from 5.15 through 6.12-beta parses this
form correctly, so files stay readable by every QET build in
circulation.

See issue #553.
2026-07-30 21:45:36 +02:00
Kellermorph b3a8ae898e PLC Manager 2026-07-27 22:16:52 +02:00
Kellermorph 4e0c075575 Fix grid and guide startup behavior and update german translation 2026-06-16 17:41:03 +02:00
Kellermorph dc52105868 Fix: Wiring list filter and dynamic text timing 2026-05-26 18:31:37 +02:00
Kellermorph f416c2a97e New element: Line definition 2026-05-21 20:47:44 +02:00
Kellermorph 780cf8b054 Set default text color for slave Xref item 2026-03-31 19:57:45 +02:00
Laurent Trinques 4044d04cc5 One year
Auto-build doxygen docs / doxygen (push) Has been cancelled
Auto-build doxygen docs / deploy (push) Has been cancelled
2026-01-16 15:24:35 +01:00
joshua e26f7fdaaa refactor[deiagram editor]: mutualize code.
The features used to jump to linked element and xref now use the same
function.
2025-10-20 22:58:12 +02:00
achim f20ea041b6 correcting the visibility of Variables in CompositeText
When using composite text in report elements, the name of the variable
was displayed when inserting the reportElement into the drawing (e.g.
%{function}). This is corrected here.
Add missing variables to assignvariables.cpp
2025-08-02 22:16:12 +02:00
plc-user e2e84a56f7 limit movement to int-values to be able to re-position to original position 2025-02-28 07:40:59 +01:00
plc-user 565374f174 additional ControlModifier does not work here as expected 2025-02-28 07:36:53 +01:00
plc-user 7bdca47d8e use brackets to be more clear what is meant 2025-02-28 07:33:17 +01:00
Magnus Hellströmer 78ee65a21b Added option to only move dynamic texts 2025-02-19 21:33:29 +01:00
Peter Kessen 5351746dc7 Fix typo within settings entry 2025-02-18 20:13:10 +01:00
Laurent Trinques 43f0107eb1 Revert "Try Clazy fix-its"
Segfault on old Qt versions!
This reverts commit dba7caed30.
2025-02-14 16:17:58 +01:00
Laurent Trinques dba7caed30 Try Clazy fix-its
clazy is a compiler plugin which allows clang to understand Qt
semantics. You get more than 50 Qt related compiler warnings, ranging
from unneeded memory allocations to misusage of API, including fix-its
for automatic refactoring.

https://invent.kde.org/sdk/clazy
2025-02-14 15:52:23 +01:00
Laurent Trinques 77bfe84a4c One year 2025-01-04 13:37:40 +01:00
Laurent Trinques e73cf633ce 2023->2024 2024-03-29 10:09:48 +01:00
Laurent Trinques 9afef79629 Update Copyright date 2023-01-01 17:05:57 +01:00
luz paz 1994235bc5 Fix various typos in source documentation and comments (cont.)
Found via `codespell`
2022-12-04 20:46:32 +01:00
Laurent Trinques daeec311b2 Element::Thumbnail WIP 2022-05-16 08:59:25 +02:00
joshua 52e884b793 Minor fix : slave Xref item is not updated when variable %F is used 2021-06-28 21:31:15 +02:00
joshua 11b8ef927b Revert "Merge branch 'XMLPropertiesNew'"
**Break a lot of thing.**

This reverts commit 1db1800572, reversing
changes made to 4c563821e8.
2021-03-11 19:52:50 +01:00
Martin Marmsoler 9d4b90da1a Add userProperties 2021-03-04 19:18:28 +01:00
Martin ea364f9c4e merge 2021-02-23 17:35:55 +01:00
Laurent Trinques ef58f34c14 Update Copyright date 2021-02-20 12:13:46 +01:00
joshua 2513961cd6 Revert "Update Copyright date"
This reverts commit d04bccc384.
2021-02-06 19:00:48 +01:00
Laurent Trinques d04bccc384 Update Copyright date 2021-02-06 18:33:42 +01:00