From 64869810cd82ba8f27c56bdfa950acd2ff381e9c Mon Sep 17 00:00:00 2001 From: hairykiwi <174199+hairykiwi@users.noreply.github.com> Date: Sun, 18 Oct 2026 12:59:19 +0100 Subject: [PATCH 1/2] Guard elements-panel project-open auto-select against a detached item - ElementsPanel::addProject auto-selects the first diagram via setCurrentItem(qtwi_project->child(0)). When a project is opened before the panel's first reload() has created its title-block collection items, indexOfTopLevelItem(common_tbt_collection_item_) returns -1 and the preceding insertChild() leaves qtwi_project detached from the tree model. - The unguarded auto-select leaves a detached/invalid current item -- an intermittent SIGSEGV in QTreeModel::index()/parent() on some builds; on current master with Qt 6.11.2 the test shows the invalid selection without a fault. Calling setCurrentItem() on an item the QTreeModel does not own is unsafe; guard the auto-select with qtwi_project->treeWidget() so it runs only when the item is attached. - No behavioural change in the normal case: reload() re-adds the project attached shortly after and performs the selection then. - Pre-existing since a82f6de23 ("Add highlight current page in ProjectView"). Assisted-by: Claude Code Signed-off-by: hairykiwi <174199+hairykiwi@users.noreply.github.com> --- sources/elementspanel.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sources/elementspanel.cpp b/sources/elementspanel.cpp index 1eac9c8ff..349f1e9b6 100644 --- a/sources/elementspanel.cpp +++ b/sources/elementspanel.cpp @@ -156,9 +156,11 @@ QTreeWidgetItem *ElementsPanel::addProject(QETProject *project, if (first_add){ qtwi_project -> setExpanded(true); - // on adding an project select first diagram - setCurrentItem(qtwi_project -> child(0)); - qtwi_project -> child(0)->setSelected(true); + // on adding a project select first diagram, once the project item is attached + if (qtwi_project -> treeWidget()) { + setCurrentItem(qtwi_project -> child(0)); + qtwi_project -> child(0)->setSelected(true); + } } else { // 2. Check whether we can restore the previous selection From 959695ed5c42d9911090198a4006ae76f41f4f7f Mon Sep 17 00:00:00 2001 From: hairykiwi <174199+hairykiwi@users.noreply.github.com> Date: Sun, 18 Oct 2026 13:01:27 +0100 Subject: [PATCH 2/2] Add regression test for elements-panel project-open auto-select crash - tst_elementspanelprojectopen drives ElementsPanel::projectWasOpened() -- the slot the application connects to a project being opened -- on a fresh panel whose first reload() has not run, reproducing the detached-item ordering deterministically offscreen. - On master without the guard the test fails: the auto-select leaves currentItem() pointing at an item whose treeWidget() is not the panel (and on some builds crashes in QTreeModel). With the guard it passes: no item is selected while the project is detached. - Registered via qet_add_app_test(), which links the application code and runs a real QETApp offscreen. Generated-by: Claude Code Signed-off-by: hairykiwi <174199+hairykiwi@users.noreply.github.com> --- tests/qttest/CMakeLists.txt | 5 +++ tests/qttest/tst_elementspanelprojectopen.cpp | 44 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 tests/qttest/tst_elementspanelprojectopen.cpp diff --git a/tests/qttest/CMakeLists.txt b/tests/qttest/CMakeLists.txt index 6dd92f413..5355ea699 100644 --- a/tests/qttest/CMakeLists.txt +++ b/tests/qttest/CMakeLists.txt @@ -290,6 +290,11 @@ qet_add_app_test(tst_folioimageload tst_folioimageload.cpp) # selection has nothing to edit for a moment (#1439). qet_add_app_test(tst_selectionpanelheight tst_selectionpanelheight.cpp) +# Opening a project before the elements panel's first reload() left its tree +# item detached, and selecting the item's first child crashed in QTreeModel +# (pre-existing since a82f6de23). +qet_add_app_test(tst_elementspanelprojectopen tst_elementspanelprojectopen.cpp) + # SVG export with smaller pictures (--svg-small-pictures, the export dialog's # option): a picture drawn at a tenth of its size is stored at four times # that, a small one whole; without the option every picture is whole. diff --git a/tests/qttest/tst_elementspanelprojectopen.cpp b/tests/qttest/tst_elementspanelprojectopen.cpp new file mode 100644 index 000000000..41cb1b8cf --- /dev/null +++ b/tests/qttest/tst_elementspanelprojectopen.cpp @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "qetapptest.h" + +#include "elementspanel.h" +#include "projectview.h" +#include "qetproject.h" + +// projectWasOpened() adds the project to the elements panel. Before the panel's +// first reload() the project's tree item is left detached (treeWidget() == +// nullptr), and selecting its first child crashed in QTreeModel +// (pre-existing since a82f6de23). +class tst_elementspanelprojectopen : public QObject +{ + Q_OBJECT + + private slots: + void addProjectBeforeReloadDoesNotCrash() + { + // A real one-folio project from the running app; diagrams() + // builds the lazy folio, so the project item will have a child. + QETDiagramEditor *editor = QetAppTest::editor(); + QVERIFY(editor); + QVERIFY(editor->newProject()); + ProjectView *pv = editor->currentProjectView(); + QVERIFY(pv); + QETProject *project = pv->project(); + QVERIFY(project); + QVERIFY(!project->diagrams().isEmpty()); + + // Fresh panel: reload() has not run, so the project item is inserted detached. + ElementsPanel panel; + + // Without the guard this selects a detached item; with it, nothing is selected. + panel.projectWasOpened(project); + + QTreeWidgetItem *current = panel.currentItem(); + QVERIFY2(current == nullptr || current->treeWidget() == &panel, + "the panel selected a detached item it does not own"); + } +}; + +QET_APP_TEST_MAIN(tst_elementspanelprojectopen) + +#include "tst_elementspanelprojectopen.moc"