Displays the cursor's scene position (same grid units as the parts'
X/Y property spinboxes) in a permanent status bar label, updated on
every mouse move. Addresses the overlapping-node mis-click case from
the originating forum report: with a live readout, precise pointing
no longer requires guessing against nearby z-ordered points.
ElementScene::mouseMoveEvent already computed the (optionally
grid-snapped) scene position on every move; it now also emits it via
a new mouseMoved(QPointF) signal, which QETElementEditor's status bar
label subscribes to.
Implements the first pillar of #574: a "Shortcuts" preferences page letting
users rebind, search and reset every keyboard shortcut in the app.
What it does
- New ShortcutManager singleton: every one of the ~95 setShortcut()/
setShortcuts() call sites across qet.cpp, qetmainwindow.cpp,
elementspanelwidget.cpp, autonumberingdockwidget.cpp, richtexteditor.cpp,
qetdiagrameditor.cpp, qettemplateeditor.cpp and qetelementeditor.cpp now
calls registerAction(target, id, category, default_sequence) instead,
which applies the user's saved override (or the default) and remembers
the target for later editing.
- New ShortcutsConfigPage, added to the existing "Configurer QElectroTech"
dialog: a filterable table of every registered shortcut, grouped by
category, each with a QKeySequenceEdit and a per-row reset button, plus a
"reset all" button. Bindings are only persisted (via
ShortcutManager::setSequence()) when the dialog is accepted.
- Conflict detection: rows whose currently-edited sequence collides with
another row are highlighted with a tooltip naming the conflicting action.
- Overrides are stored under a "shortcuts/" QSettings group, one key per
id, keyed to match the id (not persisted at all when equal to the
hardcoded default), so a future QET version can safely raise a default
for anyone who never customized it.
Design notes
- Targets are handled generically via QObject rather than QAction, since one
call site (autonumberingdockwidget's "Configurer" button) is a
QPushButton, not a QAction. Both declare an identical "shortcut"
QKeySequence Q_PROPERTY, so registerAction() reads/writes it through the
property system instead of needing a separate code path.
- Several live targets can share one id at once -- QET allows multiple
windows of the same kind (diagram editor, element editor...) open
simultaneously, each constructing its own QAction with the same id.
setSequence() updates every live target for that id in one call, so a
rebind takes effect in all open windows immediately, without restart.
- A shortcut's description is captured from its target's text() the first
time that id is registered, then cached -- so the config page stays
correct even after the owning window is closed. One consequence: a
shortcut belonging to an on-demand window (element editor, title block
editor, rich text editor) only appears in the list once that window has
been opened at least once in the current session, since nothing has
registered its id yet otherwise.
Testing
Full CMake build (qmake CONFIG+=no_kf5, Qt 5.15) compiles clean with zero
errors and zero new warnings. Verified end-to-end in a real running session
(Xvfb + xdotool):
- The Shortcuts page appears in Configure QElectroTech with the right icon,
lists every always-registered shortcut with correct category/action name/
current binding.
- The filter box correctly narrows the list, and correctly returns nothing
for an action whose owning window hasn't been constructed yet this
session (confirming the on-demand-registration behavior above is working
as designed, not silently broken).
- Conflict detection correctly flagged a real pre-existing same-key overlap
between "Supprimer" (delete selection, Del) and "Supprimer ce folio"
(delete diagram from panel, Del) -- both highlighted with explanatory
tooltips.
- Rebound "Manuel en ligne" to Ctrl+Shift+M, clicked OK: persisted under
[shortcuts] in QElectroTech.conf, and the Aide menu's entry showed the new
binding immediately, no restart needed.
- Reopened the dialog: the rebind was still shown. Clicked its per-row
reset button, then OK: the settings key was removed entirely (not stored
as "F1"), correctly falling back to the hardcoded default.
Retrofitting the Tab/Shift+Tab, select-all (#585) and Ctrl+G jump-to-element
(#586) shortcuts through this registry is left for a follow-up once those
PRs land, to avoid re-merging still-open branches into this one.
Developed with assistance from Claude (Anthropic).
updateForm() called on_m_text_from_cb_activated() directly, intending
only to enable the sibling widget matching the combo box's current
index ("For enable the good widget"). But that slot also loops over
every currently selected part and pushes an undo command overwriting
textFrom on any part that doesn't match, since it's normally only
reached via the combo box's own activated(int) signal (real user
interaction, never fired by programmatic setCurrentIndex()).
updateForm() runs on every selection change, so during a rubber-band
drag over dynamic text fields with different sources, each time a new
field enters the selection, the representative part's textFrom gets
force-applied to every other selected part - converting e.g. a
UserText field to ElementInfo mid-drag, before the user has released
the mouse or interacted with the combo box at all.
Split the cosmetic widget-enable logic into updateTextFromWidgetsEnabled(),
called from updateForm(). on_m_text_from_cb_activated() keeps the
part-mutating loop, now only reached from real user activation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Static texts (PartText) gain an optional alignment, exposed via the
existing AlignmentTextDialog behind a new "Alignement" button in the
static text editor:
- The horizontal part aligns the lines of a multi-line text relative
to each other (centered block labels no longer need one hand-placed
text per line).
- The full alignment defines the anchor: when the content or font
changes later, the selected corner/center of the bounding rect keeps
its place instead of always growing right/down from the top-left
(same prepareAlignment/finishAlignment logic as DiagramTextItem).
Format: the <text> node takes the same optional Halignment/Valignment
attributes as dynamic_text, written only when they differ from the
historical top-left behaviour - existing .elmt files are untouched and
round-trip byte-identical. The saved x/y stay the baseline-left of the
text block in all cases; ElementPictureFactory only needs the line
alignment (the anchor is editor-side behaviour), so rendered elements
match the editor exactly.
German translations for the three new strings included (qet_de stays
complete, 2686/2686).
Verified headless: a project embedding a two-line text once with
Halignment=AlignHCenter and once without exports to SVG with the short
line centered under the long one (x 102.5 vs 126.5) in the aligned
block, and identical x for both lines in the legacy block. Editor-side
anchor behaviour follows the proven DiagramTextItem implementation but
was not manually exercised in the GUI yet.
Two further empty Qt6 guard branches found by ispyisail in
qelectrotech#553:
- Element editor parts list: the QGraphicsItem* was only stored into
the list item on Qt5, so on Qt6 selecting a part in the list silently
stopped selecting it on the canvas. QVariant::fromValue() works on
both (Qt itself declares the metatype), guard removed.
- Print dialog: setEnabledOptions() is a Qt4-era API removed in Qt6;
setOptions() is the modern spelling with the same replace-the-set
semantics and exists on both, guard removed.
Both builds (Qt 5.15.2 and Qt 6.11.1) compile clean.
(cherry picked from commit 759d1c078e23664482850bad2e91d668b93aadcf)
qAsConst was deprecated in Qt 6.6; std::as_const (C++17, already the
project standard) is the drop-in replacement. Clears 46 -Wdeprecated-
declarations warnings across 18 files. No behavioural change.
Extend TerminalData::Type enum with three new semantic values:
- No : Normally Open terminal of a switch (SW) contact
- Nc : Normally Closed terminal of a switch (SW) contact
- Common : Common terminal of a switch (SW) contact
Update typeToString() and typeFromString() accordingly.
Fully backward compatible: existing Generic/Inner/Outer types
are unchanged. Elements without typed terminals fall back
to the previous behavior (first 2 named terminals).
terminal: expose terminalType() as public accessor
Add Terminal::terminalType() returning the TerminalData::Type
of this terminal. This allows crossrefitem and other consumers
to filter terminals by semantic role (No, Nc, Common) without
accessing TerminalData internals directly.
terminaleditor: add No, Nc, Common entries to type combobox
Expose the three new TerminalData types (No, Nc, Common) in
the element editor UI so users can assign a semantic role to
each terminal of a SW contact element.
Also fix a pre-existing bug in updateForm() where m_type_cb
was incorrectly using m_orientation_cb->findData() instead
of m_type_cb->findData(), preventing the type from being
restored correctly when selecting a terminal.
terminaleditor: add No, Nc, Common entries to type combobox
Expose the three new TerminalData types (No, Nc, Common) in
the element editor UI so users can assign a semantic role to
each terminal of a SW contact element.
Also fix a pre-existing bug in updateForm() where m_type_cb
was incorrectly using m_orientation_cb->findData() instead
of m_type_cb->findData(), preventing the type from being
restored correctly when selecting a terminal.
Now that the problem with the translations of keyboard shortcuts has been resolved and rotation using the space bar works reliably in principle, I took a closer look at the rotation function itself in the element editor.
I noticed, for example, that arcs can be rotated at an angle of 15°. This doesn't really make sense, as the “arc” part doesn't have the “rotation” property. There is only width and height.
And somehow rotating arcs didn't work well: start- and span-angles weren't adjusted.
Lines and polygons can be rotated in 15° increments, which doesn't make much sense, if other parts that can only be rotated in 90° increments are selected at the same time.
To make a long story short:
I reworked the rotation functions of the graphical parts so that now all parts are rotated in 90° steps around the origin! This means that it is now possible to mark several parts and rotate them around the same point at the same time!
In addition, the functions for mirroring graphic parts at y-axis (shortcut "M") and flipping at x-axis (shortcut "F") have been implemented.
I have saved the text elements for later!
(or someone else)
If the version number of QElectroTech is requested in the forum in case of error messages or anomalies, the Qt version used is very often stated because the entry “About QElectroTech” does not appear very prominently in the help menu: The entry “About Qt” is used much more frequently because it appears eye-catchingly as the lowest entry. However, specifying the Qt version is often not helpful for troubleshooting: We need the QET version!
That's why I'm moving the “About QElectroTech” entry to the bottom, so that it is easier to see and find!
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