Shapes and images can now be resized, rotated, and skewed directly
on the canvas, not just moved. Both share one small transform
struct (rotation, then skew, then scale, anchored on a movable
pivot) and one handle widget, so a corner drag, an edge skew, or
grabbing the rotate handle behaves the same way and runs through
the same matrix math everywhere, instead of every item type
reinventing its own.
Shapes also gained a proper pen tool (bezier paths, corner/smooth/
symmetric nodes), arc support, and mirroring. Images gained
non-destructive cropping and colour-keyed transparency, both
remember their own settings, so reopening the dialog picks up
where you left off instead of starting over.
Properties dialogs for both were extended to match (position,
size, angle, skew), with undo/redo wired through for every handle
drag.
Old XML files can read easily as the transformation is only added
if needed and the old syntax is still used and understood if it is
not needed.
Elements already inherited QetGraphicsItem::isMovable()/setMovable() --
the same mechanism images and drawn shapes use for their "lock position"
checkbox -- but nothing exposed it in the element properties panel, and
Element::toXml()/fromXml() never persisted it.
- ElementPropertiesWidget::generalWidget(): add a "Verrouiller la
position" checkbox mirroring ShapeGraphicsItemPropertiesWidget's
m_lock_pos_cb, toggling the element's inherited setMovable().
- Element::toXml()/fromXml(): persist is_movable, same attribute name
and default-true behavior as DiagramImageItem/QetShapeItem.
Verified via headless --resave round-trip: is_movable="0" survives
load -> save unchanged, existing elements without the attribute default
to movable.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdWpDp3TrPKbHnv7YUcNJj
QPdfDocument::pagePointSize() (used for PDF page import) requires
Qt >= 6.4, and the QtPdf module itself is missing entirely on some
Qt6 distributions (e.g. the Flatpak org.kde.Platform runtime), since
it ships from the qtwebengine source tree rather than Qt6 core.
CMake: probe Pdf with find_package(... QUIET) instead of REQUIRED,
mirroring the existing GuiPrivate pattern. Define QET_HAS_QTPDF
only when the module is found AND Qt >= 6.4.
Replace the ad-hoc QT_VERSION_CHECK(6, 0, 0) / (6, 4, 0) guards in
qetdiagrameditor.cpp, diagrameventaddpdf.{h,cpp} and
pdfpagesdialog.{h,cpp} with #ifdef QET_HAS_QTPDF, so version and
module-availability checks live in one place.
Fixes the Flatpak build (missing Qt6Pdf) and the Windows/Debian CI
failures (QPdfDocument::pagePointSize undeclared on Qt < 6.4). The
PDF import toolbar action is now silently unavailable wherever
QtPdf isn't usable, instead of breaking the whole build.
Compiled into the binary but never instantiated -- searching the tree
for any reference outside its own three files finds nothing, and this
still holds on current master. Contains a latent bug that would be
user-visible if the widget were ever reachable
(on_tableDiagram_customContextMenuRequested compares QMenu::exec()'s
return value against one action but falls through to "select all" on
both the other action and on a plain dismiss, since exec() returns
nullptr on Escape/click-away and that's not equal to either QAction*),
which supports genuine disuse rather than temporary disconnection.
Removed the three files and their three explicit entries in
cmake/qet_compilation_vars.cmake (qelectrotech.pro globs sources/ui/*
so needs no change). Builds clean; no other file references
diagramselection.
Fixes#756.
- Add DPI selection (150/300/600) to the page selection dialog
- Add live page preview in the selection dialog
- Conditionally compile PDF import only for Qt6 (#if QT_VERSION)
- Add custom pdf-import icon (PDF document with + symbol)
- Register new icon in qelectrotech.qrc
- Qt5 builds: PDF import action is hidden, everything else works as before
Replace the flat QTableWidget with a QTreeWidget that groups actions under
one collapsible top-level node per category. Fix the search box so it also
matches the current key sequence (exactly), accepts multi-keyword queries
(AND, any word order) and is accent-insensitive, auto-expands matching
groups and shows an "N actions" count. Add a quick filter (all / bound /
unbound / conflicts) that combines with the text query. Conflict detection,
per-row reset, reset-all and persistence are preserved.
Co-Authored-By: Claude <noreply@anthropic.com>
"exclude_from_bom" is listed in QETInformation::elementInfoKeys() so the
project database can build the element_info table column for it, but it
is not a free-text property: ElementInfoWidget already gives it its own
"Exclure de la nomenclature" check box.
Because buildInterface() creates one ElementInfoPartWidget per key in
that list, the key also got a second, generic edit row. And since
translatedInfoKey() has no case for it and falls through to
"return QString()", that row carries no label at all - an anonymous edit
line at the bottom of the panel. currentInfo() then writes
exclude_from_bom unconditionally, so as soon as the user edits anything
the nameless row fills with "true"/"false".
Drop the key from the list buildInterface() iterates. The check box
remains the only way to set it, currentInfo() still writes it exactly as
before, elementInfoKeys() is untouched so the database schema and
elementquerywidget are unaffected, and predefinedKeys() already excluded
it from the custom-property rows.
Reported by plc-user on #642.
Fix crash changing dynamic text color and confirming with Enter (bugtracker #323)
Works like charm:
- color is updated immediately
- no additional errors or warnings
- no crash anymore!
plc-user on PR #693: the crash is fixed, but the color/font field and
the on-diagram text no longer update until you leave the properties
list and click in the diagram -- previously it updated as soon as you
clicked OK.
That's a side effect of the crash fix itself. The old, crashing code
returned a *live* QColorDialog as the item view's editor; clicking its
OK button called accept()/hide() on it, and hiding the active editor
happens to trip the base delegate's own focus-lost commit path -- so
the value applied immediately, racily, as a side effect of the same
mechanism that crashed on Enter. The fix (commit 4bd9b6b21) replaced
that with running the dialog synchronously inside createEditor() and
returning an inert placeholder with the result stashed in a property.
Correct for the crash, but it also removed that accidental commit
trigger: the placeholder never had focus to lose, so nothing tells
the view to read the value back until some unrelated interaction
(clicking away) incidentally triggers it.
Fix: explicitly emit commitData()/closeEditor() for the resolved
editor, deferred via QTimer::singleShot(0, ...) since the view only
registers createEditor()'s return value as "the active editor" after
createEditor() itself returns -- emitting synchronously, before
returning, would target a widget the view doesn't know about yet.
Applied to both font and color, since both share the exact same
"resolve synchronously in createEditor(), return an inert
placeholder" shape and thus the exact same gap; font just hadn't been
reported.
Verified with the same standalone harness from the crash fix (real
QTreeView + DynamicTextItemDelegate + QAbstractItemView::edit()),
this time deliberately *not* sending the synthetic Enter keypress the
crash-fix verification needed: clicks the dialog's real OK button,
lets the event loop run, and confirms the picked color lands in the
model on its own. Also reconfirmed the crash fix itself still holds
(clean exit, no synthetic-Enter needed either way now) and did a full
Release build (504/504) with no new warnings.
QComboBox::currentIndexChanged(QString) still exists pre-Qt6.
TitleBlockTemplateLocationChooser: collections_ -> updateTemplates() (a virtual method; pointer-to-member dispatch still resolves to the
TitleBlockTemplateLocationSaver override at runtime as expected)
TitleBlockTemplateLocationSaver: templates_ -> updateNewName()
TitleBlockPropertiesWidget: m_tbt_cb -> changeCurrentTitleBlockTemplate(int)
XRefPropertiesWidget: m_type_cb -> typeChanged(), m_snap_to_cb ->enableOffsetSB(int), both connect (constructor) and disconnect(destructor)
Bugtracker #308: the "current date" preset for a project's default
title block doesn't persist. A later comment on the report pinpointed
it exactly: the setting falls back to "No date" unless the folio tab
remains active when saving settings, and the same happens in Project
Properties.
TitleBlockPropertiesWidget::properties() (and its near-duplicate
sibling propertiesAutoNum(), copy-pasted with the same bug) reads the
date radio buttons like this:
else if (ui->m_current_date_rb->isVisible() && ui->m_current_date_rb->isChecked()) {
prop.useDate = TitleBlockProperties::CurrentDate;
...
Both the New Project settings page and Project Properties embed this
widget as one page of a QTabWidget (NewDiagramPage, in
configpage/configpages.cpp). QWidget::isVisible() depends on the
whole ancestor chain being visible, not just the widget's own state --
switch to any other tab before clicking OK/Apply and this radio
button's isVisible() goes false even though it's still checked
underneath, silently falling through all three branches. The function
returns a default-constructed TitleBlockProperties for the date
fields (useDate = UseDateValue, date = QDate(), i.e. "no date"),
matching exactly what was reported.
Fix: use isHidden() instead, which reflects only this widget's own
explicit state and mirrors the read side's own check in
setProperties()/initDialog() just above it in the same file -- that
side already uses isHidden(), not isVisible(), for the identical
"is the current-date option even offered here" question.
Verified directly: a standalone Qt program constructing the real
NewDiagramPage, checking "current date", switching the tab widget
away from Folio to Conducteur (reproducing the report's exact
trigger), then calling applyConf() and reading back the QSettings
value. Against the original code this saves date="null"; with the
fix, date="now" -- the same scenario, same tab switch, only the one
line differs. Also confirmed a full Release build (504/504, CMake/
Ninja, Qt 5.15.18) with no new warnings.
Bugtracker #323: crash changing a label's color, but only when
confirmed via Enter -- clicking the dialog's own OK button with the
mouse doesn't crash. Reported on Windows 11 and Debian, with
"QObject::installEventFilter(): Cannot filter events for objects in
a different thread" immediately before the segfault.
Root cause: DynamicTextItemDelegate::createEditor()'s color case
constructed a QColorDialog and returned it directly as the item
view's editor widget for the color cell -- unlike every other case
in this same function, which returns a small inline widget
(QSpinBox, QComboBox, or, for the adjacent font case, a plain
placeholder). A QColorDialog is not designed to be used this way: it
is not one of the objectNames this delegate's own eventFilter()
special-cases, so Enter is handled by the base
QStyledItemDelegate::eventFilter() as an ordinary "commit and
destroy this small editor" trigger -- racing the dialog's own
internal OK-button accept/close path, which on Windows can hand off
to the native color picker. Clicking OK with the mouse doesn't go
through the same key-press path, which is why only Enter crashed.
Verified structurally: an embedded QColorDialog editor is a *child*
widget of the view's viewport rather than a proper top-level dialog
(confirmed with a standalone Qt program driving the real delegate
through QAbstractItemView::edit() -- searching QApplication's
top-level widgets never found it, only a search of the viewport's
children did), which is the same "used as something it isn't"
pattern, just observed a different way.
Fix: mirror the font case immediately above -- resolve the color via
the static, blocking QColorDialog::getColor() inside createEditor(),
and hand back a plain QWidget with the result stashed in two
properties (mirroring the font case's "ok" property) for
setModelData() to read. By the time the view processes any commit
trigger, the "editor" is an inert placeholder with no dialog state
left to race.
Verified end-to-end with the same standalone program: creates the
model item, triggers editing, finds the real (top-level, this time)
QColorDialog, clicks its actual OK button, confirms the color lands
on the placeholder's properties, sends the editor a synthetic Enter
keypress (the exact trigger from the bug report), and confirms the
final committed value in the model matches the picked color. Also
confirmed a full Release build (333/333) with no new warnings.
NewDiagramPage::applyConf() writes every other default to QSettings —
border, title block, conductors, folio reports and the guides — but the
cross-reference branch only fetched the properties into a local hash and
then dropped it on the floor. hash_xrp was never used.
The result: changing the cross-reference defaults under Settings > New
project has no effect. Nothing is written, no defaultxref* key ever
appears in the configuration file, and XRefProperties::defaultProperties()
keeps handing out the hardcoded fallbacks for every new project.
Write each of the four types (coil, protection, commutator, plc) with the
"diagrameditor/defaultxref" + key prefix that defaultProperties() already
reads back.