Files
qelectrotech-source-mirror/tests/qttest/tst_collectionclosedproject.cpp
T
ispyisail 46d8588113 Fix a closed project staying in the element collection panel
A project opened before the element collection panel's first load is
queued until the load starts; one opened during a load goes into the
model being loaded. ElementsCollectionWidget::removeProject() only
removed the project from the model already shown, so a project closed
in either window stayed in the collection, and the next reload read the
freed project (crash in XmlElementCollection::root()).

removeProject() now also takes the project out of the queue and out of
the model being loaded. That model waits for its loading threads, which
read the project, and drops the project's items from the list applied
when the loading ends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:28:35 +13:00

82 lines
2.4 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
#include "qetapptest.h"
#include "ElementsCollection/elementscollectionmodel.h"
#include "ElementsCollection/elementscollectionwidget.h"
#include "qetproject.h"
#include <QTreeView>
// A project closed while the element collection panel has not loaded yet, or
// while it is loading, stayed in the collection: the next reload read the
// freed project (crash in XmlElementCollection::root() from
// ElementsCollectionWidget::reload()).
class tst_collectionclosedproject : public QObject
{
Q_OBJECT
/// The collection's tree (not the macros one): reload() disables it
/// until the loading has finished.
static QTreeView *loadingView(ElementsCollectionWidget &w)
{
for (QTreeView *v : w.findChildren<QTreeView *>())
if (!v->isEnabled()) return v;
return nullptr;
}
/// Reload and wait for the loading to finish.
static ElementsCollectionModel *reloadAndWait(ElementsCollectionWidget &w)
{
w.reload();
QTreeView *main_view = loadingView(w);
if (!main_view) return nullptr;
if (!QTest::qWaitFor([main_view]() { return main_view->isEnabled(); }, 300000))
return nullptr;
return qobject_cast<ElementsCollectionModel *>(main_view->model());
}
private slots:
void closedBeforeFirstLoad()
{
ElementsCollectionWidget w;
QETProject kept;
QETProject closed;
w.addProject(&kept);
w.addProject(&closed);
w.removeProject(&closed);
ElementsCollectionModel *model = reloadAndWait(w);
QVERIFY(model);
QVERIFY(model->project().contains(&kept));
QVERIFY2(!model->project().contains(&closed),
"a project closed before the first load is still in the collection");
}
void closedWhileLoading()
{
ElementsCollectionWidget w;
QETProject kept;
QETProject closed;
QVERIFY(reloadAndWait(w));
w.addProject(&kept);
w.addProject(&closed);
// A second load starts; the project is closed before it ends.
w.reload();
QTreeView *main_view = loadingView(w);
QVERIFY(main_view);
w.removeProject(&closed);
QTRY_VERIFY_WITH_TIMEOUT(main_view->isEnabled(), 300000);
auto *model = qobject_cast<ElementsCollectionModel *>(main_view->model());
QVERIFY(model);
QVERIFY(model->project().contains(&kept));
QVERIFY2(!model->project().contains(&closed),
"a project closed during a load is still in the collection");
}
};
QET_APP_TEST_MAIN(tst_collectionclosedproject)
#include "tst_collectionclosedproject.moc"