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>
switch runtime/sdk to org.kde.Platform/org.kde.Sdk 6.10
migrate qelectrotech module from qmake to cmake buildsystem
add config-opts: QT_VERSION_MAJOR=6, BUILD_WITH_KF=ON, BUILD_KF=OFF,
PACKAGE_TESTS=OFF, BUILD_PUGIXML=OFF, QET_EXPORT_PROJECT_DB=ON
drop fix-the-installation-paths.patch (qmake-only, obsolete under cmake)
re-attach fix-appdata.patch, previously unreferenced in sources
document open verification points for Qt6 private headers and the
SQLite driver, which have no Flatpak build-depends equivalent
QET_MIME_PACKAGE_PATH was "../share/mime/packages/", a path relative
to CMAKE_INSTALL_PREFIX. This only worked by accident with the old
default prefix (/usr/local -> ../share resolves to /usr/share/mime,
the conventional system location regardless of app prefix).
With -DCMAKE_INSTALL_PREFIX=/usr (as used by Debian/Ubuntu packaging),
the same "../share" escapes /usr entirely, landing at /share/mime
instead of /usr/share/mime, which breaks dh_install (file not found
under usr/) and would silently install the mime package definition
outside any path desktop environments actually scan.
Drop the "../" so the mime package path stays under the install
prefix, matching standard practice (/usr/share/mime/packages or
/usr/local/share/mime/packages).
FetchContent_Declare unconditionally tries to clone SingleApplication
from GitHub, which breaks offline builds (e.g. Debian/Ubuntu pbuilder
with FETCHCONTENT_FULLY_DISCONNECTED=ON, Launchpad PPA builds).
If the SingleApplication submodule is already checked out in the
source tree, point FETCHCONTENT_SOURCE_DIR_SINGLEAPPLICATION at it so
FetchContent skips the network step entirely and reuses the local
copy. Falls back to the existing git clone behavior otherwise, so
this is a no-op for setups that don't vendor the submodule.
Follow-up to #740, which fixed the slave-side "(n-Xn)" cross-reference
label. The master-side item - the small table/cross drawn next to a
report or master element, listing where each of its slaves is used -
was still missing from DXF export. Measured against examples/
industrial.qet with the PDF export as an oracle (renders the whole
scene, so it shows what should be there):
before after PDF
slave xrefs "(n-Xn)" 41 41 41 (already fixed, #740)
folio/position strings 358 403 403
DXF now matches the PDF exactly.
## Why this needed a different approach than #740
The slave label is a plain QGraphicsTextItem - one string, trivial to
walk and re-emit as a single DXF TEXT entity, which is what #740 did.
The master-side item (CrossRefItem) is not: it paints itself with
~600 lines of hand-written QPainter calls across three modes
(drawAsCross/drawAsContacts/drawAsPlcTable), including a header
table, contact symbols, and rules. Hand-porting that logic to emit
DXF primitives directly would mean maintaining two divergent
implementations of the same drawing that have to be kept in sync by
hand forever.
## Approach: a QPaintEngine that intercepts CrossRefItem's own paint()
DxfPaintEngine/DxfPaintDevice (sources/dxfpaintdevice.{h,cpp}) is a
QPaintEngine/QPaintDevice pair - the same mechanism QPrinter and
QSvgGenerator use to redirect QPainter output elsewhere. Constructing
a QPainter on a DxfPaintDevice and calling item->paint() on it produces
DXF entities instead of pixels, using the exact same drawing code that
already renders correctly on screen. CrossRefItem::paint() is
unmodified.
Scope is deliberately narrow - only the QPainter calls CrossRefItem's
paint() is observed to make: drawLines -> LINE, drawRects/drawPath's
fill case -> outline-only LWPOLYLINE (no HATCH support in v1 - DXF's
fill primitive is a separate, more involved entity type; documented as
a known limitation rather than attempted here), drawEllipse -> CIRCLE
or a flattened polygon for rotated ellipses, drawPath's arc case (from
drawArc/drawPie) -> chord-flattened LINE segments, drawPolygon ->
LWPOLYLINE, drawTextItem -> TEXT. drawPixmap is intentionally
unimplemented (qWarning + skip) since CrossRefItem never calls it -
this is not a general-purpose DXF paint engine, and isn't meant to be
in this PR.
CrossRefItem::paint() is protected, per the normal QGraphicsItem
contract - added a small paintForExport() wrapper rather than making
paint() itself public, or reaching around access control.
## Explicitly out of scope
QetShapeItem::toDXF() and QetGraphicsTableItem::toDXF() (both already
implemented and working) are untouched. Rewriting working exporters
onto this engine to prove an architectural point would be a large,
unrelated diff with no user-visible benefit - if that consolidation is
wanted later, it's a separate proposal once this engine has shipped
and proven out on the one item that currently has no DXF export at
all.
## Testing
Built clean on Qt5/Linux. Verified via the GUI export dialog
(Fichier > Exporter > DXF) against examples/industrial.qet, 50 folios:
export completes without error or crash, all 50 .dxf files are
structurally well-formed (balanced SECTION/ENDSEC, single EOF each),
and grepping the folio-position pattern gives the before/after/PDF
numbers above. Spot-checked several real label strings (e.g. "18-B18",
"20-A2") present as TEXT entity values in the output, not just an
artifact of the count matching.
- build-windows-qt6: install kwidgetsaddons/kcoreaddons/extra-cmake-modules,
switch -DBUILD_WITH_KF=OFF to ON, add -DBUILD_KF=OFF to use precompiled
MSYS2 packages instead of building KF6 from source via FetchContent
- build-windows: swap unsuffixed kwidgetsaddons/kcoreaddons (actually KF6
packages after MSYS2's renaming) for the -qt5 suffixed ones, add
-DBUILD_KF=OFF so the installed packages are actually consumed instead
of being ignored by the default FetchContent-from-source build
https://qelectrotech.org/bugtracker/view.php?id=335
## Bug
Element library icons (collection tree thumbnails, drag icon, preview
panels) render with a fully transparent background. Element definitions
almost always hardcode a black stroke color, on the assumption of the
white diagram sheet they are normally drawn on. Against a dark widget/
tree-view background (e.g. KDE Plasma dark theme), that black stroke
disappears entirely - reported as icons being "black and almost
invisible". scorpio810_mantis linked this to the same recurring family
as #231, #247, #267.
## Fix
ElementPictureFactory::pixmap() is the single shared point where every
consumer of these icons gets its QPixmap (collection tree via
ElementsCollectionCache -> Element::pixmap(), master/slave properties
tree, element properties preview, drag icon). Change its background
fill from fully transparent to opaque white - exactly what the element
already visually assumes in every context this pixmap is used, so it
is correct regardless of the surrounding widget's palette.
## Testing
Built both variants and compared under Xvfb using a simple, decisive
visual test: select the tree row (giving it a highlighted/colored
background) and compare what shows immediately around the icon's
glyph.
- Before: the icon's background matches the row's selection color -
confirms it is transparent, so on a dark unselected row the black
strokes would have the same problem.
- After: a solid white square is visible behind the glyph regardless
of the row's background color.
Note for the on-disk pixmap cache used by ElementsCollectionCache
(~/.local/share/QElectroTech/QElectroTech/elements_cache.sqlite):
existing cached PNGs predate this fix and will keep their transparent
background until regenerated. That cache already keys strictly on
path+uuid with no invalidation on QET version, so this is an existing
characteristic of that cache, not something introduced here.
Bugtracker #291: clicking Cancel on the open/save-element dialog before
the user collection finishes loading crashes the whole application with
an unhandled pointer exception.
ElementsCollectionModel::loadCollections() loads collections in the
background via QtConcurrent::map(m_items_list_to_setUp, setUpData) -
worker threads call setUpData() on each ElementCollectionItem
(a QStandardItem), which does setFlags()/setData() on it.
ElementDialog::execConfiguredDialog() deletes the dialog immediately
after exec() returns:
element_dialog->exec();
...
delete element_dialog;
That destroys the tree view and its ElementsCollectionModel, which as
a QStandardItemModel frees all its items in its destructor. Nothing
waited for the QtConcurrent::map() to finish first, so on Cancel before
loading completes, background threads were still calling setUpData()
on items the main thread had just freed - a use-after-free race.
Add an ElementsCollectionModel destructor that waits for the future
before QStandardItemModel's destructor runs. QFuture::waitForFinished()
on a default-constructed (never-started) future returns immediately, so
this is a no-op whenever loading already completed - the crash path is
the only one affected.
Fix print window clipping diagram when titleblock on right edge is hidden.
Fixes a frequently made mistake: confusing width and height when rotating something... 😉
Cross-references were missing from DXF exports, as reported on the
forum: https://qelectrotech.org/forum/viewtopic.php?id=2481
generateDxf() walks the scene and collects items by cast. A slave
element's cross-reference label ("(6-G15)", pointing back to its master)
is a plain QGraphicsTextItem hung off a DynamicElementTextItem as a
child, so it matches neither the IndependentTextItem nor the
DynamicElementTextItem branch and was dropped on the floor. Nothing was
wrong with the label itself; it was simply never collected.
Collect it through the existing DynamicElementTextItem::slaveXrefItem()
accessor and draw it with the same placement, rotation and multi-line
handling as the other text items, using defaultTextColor() since a bare
QGraphicsTextItem has no DiagramTextItem::color().
Measured on examples/industrial.qet, comparing against the PDF export
(which renders the whole scene and so shows everything):
before after PDF
slave xrefs "(n-Xn)" 0 41 41
folio/position strings 317 358 403
The slave cross-references now match the PDF exactly.
Still missing, and not addressed here: the master-side cross-reference
table drawn by CrossRefItem, which accounts for the remaining 45
strings. CrossRefItem is a QGraphicsObject that renders itself with
custom QPainter code in three different modes (drawAsCross,
drawAsContacts, drawAsPlcTable) including contact symbols and rules, so
giving it a DXF representation is a larger piece of work than this.