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.
"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.
QVector<int>(Qt::DisplayRole) creates a vector of size 0 (since Qt::DisplayRole == 0), not a vector containing DisplayRole. Fixed
to {Qt::DisplayRole}.
The sam applies to QVector<int>(role) which gets changed to {role}.