Shows the licensing/liability warning text agreed on in PR #513
(scorpio810) before the file picker opens. Import stays disabled
until the "I have read and accept these terms" checkbox is ticked.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Use QT_VERSION_CHECK to detect Qt6 at compile time and report
version 0.200.1 instead of 0.100.1 in that case, so Qt6 builds
are clearly distinguishable from Qt5 builds.
Clears the last five spots that stop master from compiling against Qt6
(all mirrored from the proven qt6-build line):
- qgimanager.h/.cpp: in Qt6 QVector is an alias for QList, so the
deprecated QList overloads of manage()/release() collide with the
QVector ones (same signature). Keep them on Qt5 only.
- diagramview.cpp: one unguarded QTextStream::setCodec() call (removed
in Qt6, which defaults to UTF-8).
- print/projectprintwindow.cpp: QApplication::desktop() was removed in
Qt6; use QWidget::screen() there, keep the old path on Qt5.
- titleblocktemplate.cpp: QDomDocument::setContent() returns a
ParseResult in Qt6 whose operator bool is explicit; static_cast keeps
the bool initialization working on both.
With these, master configures and builds to a running binary with
Qt 6.11 (mingw, BUILD_WITH_KF5=OFF); every change is guarded or
dual-safe, the Qt5 build is unaffected.
The name of the elements and folders of the collection are not displayed
until we hover the item with the mouse.
This due that QtConcurent::run was disabled at loading of collection in
the goal of use QtConcurrent::run with Qt6.
Run is made to run a function once.
Map is made to run a fonction for each item of a sequence (what we need
in this case).
Remove code of run and re-enable code for map.
- Add missing <QHash> include: QHash<QUuid, QVector<QPointF>> was
only forward-declared transitively under Qt5's heavier headers;
Qt6's leaner <QPainter> etc. no longer pull it in.
- Replace QPolygonF{points_} with QPolygonF(points_): under Qt6,
QPolygonF inherits QList<QPointF>'s constructors via 'using
QList<QPointF>::QList;', including the std::initializer_list<T>
one. Brace-init-list construction with a single argument first
considers only initializer-list constructors before falling
back to regular ones, which trips up overload resolution here
even though points_ is exactly a QList<QPointF> (QVector is a
plain alias for QList under Qt6). Plain parenthesised
construction sidesteps that resolution phase entirely and binds
directly to QPolygonF(const QList<QPointF>&).
QVector::size() (== QList::size() under Qt6) returns qsizetype
(64-bit), while 'level' is a plain int. std::min(level,
m_real_terminal.size()-1) therefore tries to deduce a single T
from two different argument types, which fails - GCC reports it
against the unrelated std::min(initializer_list<T>) overload,
but the real issue is the type mismatch between the two-argument
candidates. Under Qt5, QVector::size() returned int, so this
compiled fine.
Force T=int explicitly via std::min<int>(...) and cast size()
down to int (physical terminal counts are always tiny), matching
the pattern already used safely elsewhere in the codebase (e.g.
qetgraphicstableitem.cpp).
Since Qt 6.5, QDomDocument::setContent() returns a ParseResult
struct with an *explicit* operator bool(), so 'bool x =
doc.setContent(...)' (copy-initialization) no longer compiles -
explicit conversions aren't considered there.
This exact issue was already fixed in titleblocktemplate.cpp by
dropping the intermediate bool and testing the call directly in
the if condition (contextual bool conversion in an if() is fine
even for an explicit operator bool), but this second occurrence
in templatescollection.cpp used the same pattern and was missed.
Applying the same fix here for consistency.
templateview.h only included <QGraphicsView> but uses
QGraphicsGridLayout (tbgrid_ member) and QGraphicsLayoutItem
(indexOf/removeItem signatures) directly. Some Qt5 header
apparently pulled these in transitively; Qt6's leaner headers
don't, so the class fields/methods silently failed to resolve
and the compiler picked bogus 'int*' overloads instead.
Other files in the same directory already get these symbols
either via the <QtWidgets> umbrella header or a direct include,
so this was an isolated gap.
The Qt6 branch of the #if QT_VERSION guard swapped QRegExp for
QRegularExpression but kept calling QRegExp-only methods
(exactMatch()/cap()), which QRegularExpression doesn't have.
Use the correct QRegularExpression API instead: match() returns
a QRegularExpressionMatch, tested with hasMatch() and read with
captured(n).
- qetxml.h: add missing <QUuid> include (used in propertyUuid/
createXmlProperty signatures but never included directly).
- machine_info.cpp: fix ambiguous QString/int operator> in
send_info_to_debug() for it1/it2/it3; just count every
matching file found instead of the meaningless comparison.
The project panel's "copy and paste" action duplicates a folio through
an XML round-trip (toXml/fromXml), and Element::fromXml adopts the uuid
stored in the XML - so every element on the duplicated folio kept the
uuid of its source element. On-diagram copy/paste already handles this
(PasteDiagramCommand::redo() calls newUuid()), but the folio-duplicate
path bypasses that command.
Since element.uuid is the PRIMARY KEY of the project database, the
duplicated elements failed to insert ("UNIQUE constraint failed:
element.uuid" spam in the log) and silently disappeared from
nomenclature/summary tables, even though they are valid on the folio.
Renew the uuid of every element on the freshly duplicated folio, exactly
as the paste command does. In-memory links established during fromXml
are pointer-based and unaffected; the new uuids are written on save.
Clears the 9 non-deprecation warnings from the Qt6 build:
- qHash(QColor): hash rgba() (unambiguous QRgb) instead of name(), and
use the size_t seed signature on Qt6 (guarded for Qt5). Fixes the
ambiguous-overload warning in terminalstripmodel.h.
- Two qsizetype->int narrowings in brace-init: explicit static_cast<int>
(elementscene.cpp, terminalstrip.cpp).
- main.cpp: keep the QtConcurrent::run QFuture in a [[maybe_unused]]
variable (nodiscard).
- qetapp.cpp: guard the stylesheet load on QFile::open() succeeding
(nodiscard) instead of ignoring the result.
QVariant::canConvert(int) is deprecated in Qt6. Use the non-deprecated
canConvert<T>() template (canConvert<QString>() / canConvert<int>()),
which is available on Qt5 too. Clears the last 2 -Wdeprecated-
declarations warnings.
Three deprecated APIs have replacements that only exist in newer Qt6:
- QLocale::nativeCountryName() -> nativeTerritoryName() (Qt 6.2)
- QDomDocument::setContent() overload -> ParseResult (Qt 6.5)
- qt_ntfs_permission_lookup -> QNtfsPermissionCheckGuard RAII (Qt 6.6)
Each is wrapped in QT_VERSION_CHECK so Qt5 keeps the old path. Clears
4 -Wdeprecated-declarations warnings.
QString::count() (no-arg) is deprecated -> size(); QColor::setNamedColor()
is deprecated -> the QColor(QString) constructor. Both replacements are
non-deprecated on Qt5 too. Clears 2 -Wdeprecated-declarations warnings.
QSqlDatabase::exec(const QString&) is deprecated in Qt6. Route the
PRAGMA/CREATE TABLE statements through QSqlQuery(db).exec() instead.
Clears 11 -Wdeprecated-declarations warnings; same statements, same
database connection, no behavioural change.
QVariant::type() and the QVariant::Type enum are deprecated in Qt6.
Switch on userType() (non-deprecated, returns the QMetaType id and
works on Qt5 too) with QMetaType enum cases. Clears 6 -Wdeprecated-
declarations warnings; the numeric type ids are unchanged.
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.
NamesList::name() looked up the display name using the full locale from
langFromSetting() (e.g. "de_DE") and jumped straight to English if it was
absent. Element and folder names in the collection are keyed by 2-letter
codes (<name lang="de">), so a "de_DE" UI showed the whole collection in
English/French even though German names exist.
Try the base language ("de") before the English fallback, mirroring what
setLanguage() already does for the UI translations.
MOC on macOS does not resolve QGraphicsLayoutItem through the bulk
QtWidgets include, causing an 'Undefined interface' error at build time.
Adding an explicit include resolves this. Linux builds are unaffected. Thanks hairykiwi 8ef4e04
Check the QLockFile in staleFiles() before returning a no-KF5 recovery candidate, matching the KAutoSaveFile contract that actively owned autosave files are not stale.
Extend the no-KF5 Catch test so a child process keeps the autosave lock alive while allStaleFiles() runs, then verify recovery after the child is killed.
Assisted-by: pi coding agent / Mika (OpenAI GPT-5.5)
Provide a small KAutoSaveFile-compatible implementation for the no-KF5 build path and use it to keep the existing crash-recovery code active when BUILD_WITH_KF5=OFF.
The normal KF5 build still uses the KDE KAutoSaveFile implementation.
Assisted-by: pi coding agent / Mika (OpenAI GPT-5.5)
The BUILD_WITH_KF5 option was checked with DEFINED, so passing -DBUILD_WITH_KF5=OFF still entered the KF5 setup path.
Skip the KF5 setup when disabled and provide small Qt-only replacements for the KDE color widgets used by .ui files in that build mode.
Assisted-by: pi coding agent / Mika (OpenAI GPT-5.5)
m_first_move was initialized before _linestyle in the constructor
initializer list, but _linestyle is declared first in the class. Reorder
to match declaration order.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When an item type is selected for the first time the properties dock
expands, causing the QGraphicsView viewport to shrink. Qt recalculates
scene coordinates and fires one or more synthetic mouseMoveEvents before
the user has actually moved the mouse.
The original code used a single-shot m_first_move flag in
CustomElementGraphicPart, which absorbed exactly one spurious event.
PartText and PartDynamicTextField had no protection at all.
Fix: compare screen-coordinate displacement against
QApplication::startDragDistance() (~4 px). Screen coordinates are
stable across viewport resizes, so the check correctly rejects
synthetic dock-expansion events while allowing genuine drags.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Same root cause as ProjectPropertiesDialog: Qt::WindowModal only blocks the
direct parent window, leaving the rest of the MDI area live. If new_project
or close_project fires while the app settings dialog is open, any raw pointers
derived from the project list become stale. Switch to ApplicationModal to
block all windows for the duration of the dialog.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ProjectPropertiesDialog::exec() was using Qt::WindowModal, which only
blocks the parent ProjectView window. The MDI workspace and its other
subwindows remained interactive, so actions like new_project or
close_project could fire while the dialog's config pages still held raw
QETProject* pointers — leading to a SIGSEGV when Qt's event loop later
dispatched a signal through one of those stale pointers.
Detected by the 8-hour GUI fuzzer: action sequence add_diagram_page →
flood_wires ×18 → new_project while Project Properties was open
produced exit code -11 (SIGSEGV) on the first of 12,717 actions.
Switch to Qt::ApplicationModal so no window can receive input while the
dialog is open. Project Properties is a short-lived dialog; blocking
the whole application for its duration matches user expectation and
removes the lifetime hazard without requiring QPointer surgery across
four config-page classes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follow-up to the eventFilter fix: testing showed double-click works
when QET is already running, but a cold launch (app not running yet)
still opens an empty window. Finder/Launch Services can deliver the
QFileOpenEvent to the QApplication's native event loop before main()
reaches the point where QETApp is constructed and its real eventFilter
is installed -- there's a window between 'SingleApplication app(...)'
and 'QETApp qetapp;' during which the event can arrive and be lost.
Add a minimal EarlyFileOpenCatcher installed on app immediately after
it's constructed (before anything else can run an event loop). It only
buffers the file path. Once QETApp exists, main() swaps it out for the
real QETApp::eventFilter and drains anything that was buffered via
qetapp.openFiles(), so no cold-launch QFileOpenEvent is silently
dropped.
Confirmed by manual testing:
- 'open app --args file' on .qet/.elmt/.titleblock: OK (already worked)
- double-click while app already running: OK (already worked)
- double-click cold launch: previously opened an empty window, this
buffers and replays the event so it now opens the right editor.
Root cause (see issue #218 discussion):
- QETApp::eventFiltrer (Q_OS_DARWIN) was correct in intent but never
actually installed as an event filter anywhere, and its name didn't
match the QObject::eventFilter virtual signature, so even if it had
been installed it would never have been invoked as an override.
Confirmed dead code.
- main.cpp instead routed Finder's QFileOpenEvent through
MacOSXOpenEvent -> SingleApplication::sendMessage(), which is the
secondary-to-primary IPC channel. Called from within the primary
instance itself, sendMessage() fails silently and the file path is
dropped, which is exactly what double-click does (Finder doesn't spawn
a secondary process, the running instance receives the FileOpen event
directly).
- openFiles() takes a QETArguments, not a QStringList. The dead code's
openFiles(QStringList() << filename) only worked via an untested
implicit QStringList -> QList<QString> -> QETArguments conversion
chain.
Fix:
- Rename eventFiltrer -> eventFilter (qetapp.h/.cpp) so it's a proper
override of QObject::eventFilter, and make it public so main.cpp can
install it on QApplication.
- Build the QETArguments explicitly instead of relying on implicit
conversion.
- main.cpp: drop MacOSXOpenEvent entirely (include + instantiation),
install qetapp as the Q_OS_MACOS event filter on app right after
QETApp qetapp; is constructed and before app.exec(). No race window:
the event loop hasn't started, so no QFileOpenEvent can be delivered
before the filter is installed.
QETArguments::handleFileArgument() already sorts files by extension
(.elmt, titleblock, else project) and openFiles() already fans out to
openProjectFiles()/openElementFiles()/openTitleBlockTemplateFiles()
accordingly, so this single fix covers .qet, .elmt and .titleblock
double-click/drag-to-dock on macOS, not just .qet.
SingleApplication's sendMessage/receivedMessage flow (used for CLI args
on all platforms) is untouched; this only touches the Q_OS_MACOS block,
so there is no behavior change on Windows/Linux.
Follow-up (not included here): the macOS Info.plist (misc/Info.plist)
has an empty CFBundleShortVersionString, which may affect macOS's
willingness to retain file associations across app updates.
pugi::xml_document::load_file(const char*) calls fopen/fopen_s on Windows,
which uses the ANSI codepage — not UTF-8. This silently fails when the
collection path contains accented characters (é, ü, ñ, …) or is longer
than the narrow-API MAX_PATH limit, leaving the collection panel with no
element names or illustrations.
Switch both call sites to toStdWString().c_str() which invokes the
load_file(const wchar_t*) overload. On Windows pugixml calls _wfopen,
the wide Unicode API that handles all valid Unicode paths. On Linux/macOS
the same overload converts wchar_t to UTF-8 internally and calls fopen,
so behaviour is unchanged on those platforms.
Affected files:
sources/ElementsCollection/fileelementcollectionitem.cpp (qet_directory load)
sources/ElementsCollection/elementslocation.cpp (element .elmt load, both branches)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Resolve cmake/qet_compilation_vars.cmake conflict: keep both upstream's
cli_export.cpp/h and pdf_links.cpp/h and the EDZ source additions.
- 10-position grid alignment: pin_y values are multiples of 10 so terminals
snap cleanly to QET's default grid. group_gap raised to 10 (one full slot).
- Named connector groups get a header label (group name) placed in the gap
above the first pin, so the electrician sees block names (XDI, XPOW, …)
without reading individual terminal designations.
- Device-tag dynamic_text now uses 9pt LABEL_FONT and y = min_y - 9 so it
clears the element body and is legible at normal zoom.
- Add EPLAN Data Portal Terms of Use disclaimer to sources/import/edz/README.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>