From 3f23e3dd2b904e28d6788f38188b1dbc2349bee2 Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Sat, 10 Oct 2026 09:42:59 +0200 Subject: [PATCH] Create the folder of the cable types file before writing into it The catalogue is written with QSaveFile, which cannot write into a folder that is not there. A fresh profile has no documents folder, and a path typed into the settings may name a folder which was never created, so the first write failed with "No such file or directory" and no way for the user to see that the folder was the problem rather than the file (non-blocking review comment by ispyisail). writeFile() makes the folder first, which covers every writer: creating the template, appending a type and editing one all go through it. Covered by tst_cabletypelist::aMissingFolderIsCreated, writing into /not/there/yet/qet_cable_types.csv. Verified in both directions: without the fix the test fails with 'createFile(path, &error) returned FALSE. (No such file or directory)', with it the file is created and reads back. --- sources/cablelist/cabletypelist.cpp | 16 ++++++++++++++++ tests/qttest/tst_cabletypelist.cpp | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/sources/cablelist/cabletypelist.cpp b/sources/cablelist/cabletypelist.cpp index cf57cbb3a..125087109 100644 --- a/sources/cablelist/cabletypelist.cpp +++ b/sources/cablelist/cabletypelist.cpp @@ -635,6 +635,22 @@ bool CableTypeList::writeFile(const QString &path, const CableTypeListData &data header_lines.append(data.columns); const QByteArray content = MaterialList::serializeCsv(header_lines, rows, data.separator); + //The folder may not be there yet: a fresh profile has no + //documents folder, and a path typed into the settings may name a + //folder which was never created. QSaveFile cannot write into a + //folder which does not exist, so without this the whole write + //fails and the message says nothing about the real reason. + const QString folder = QFileInfo(path).absolutePath(); + if (!folder.isEmpty() && !QDir(folder).exists() && !QDir().mkpath(folder)) + { + if (error) { + *error = QCoreApplication::translate( + "CableTypeList", + "Cannot create the folder %1 for the cable types file.").arg(folder); + } + return false; + } + QSaveFile file(path); if (!file.open(QIODevice::WriteOnly) || file.write(content) != content.size()) { diff --git a/tests/qttest/tst_cabletypelist.cpp b/tests/qttest/tst_cabletypelist.cpp index 77f36ad35..64b781d4e 100644 --- a/tests/qttest/tst_cabletypelist.cpp +++ b/tests/qttest/tst_cabletypelist.cpp @@ -142,6 +142,25 @@ class tst_cabletypelist : public QObject QStringLiteral("bl")})); } + //The folder a cable type file goes into may not exist yet: a fresh + //profile has no documents folder, and a path typed into the settings + //may name one which was never created. The write makes the folder + //rather than failing with a message which says nothing about why. + void aMissingFolderIsCreated() + { + const QString path = m_dir.filePath( + QStringLiteral("not/there/yet/qet_cable_types.csv")); + QVERIFY(!QFile::exists(path)); + + QString error; + QVERIFY2(CableTypeList::createFile(path, &error), qPrintable(error)); + QVERIFY2(QFile::exists(path), "the file was not created"); + + CableTypeListData data; + QVERIFY2(load(path, &data), "the file just created could not be read"); + QVERIFY(data.records.isEmpty()); + } + void labelLineAloneStillGivesTheType() { const QString path = write(QStringLiteral("hand.csv"),