[frameworks/kcoreaddons] /: Don't let fromAppStreamFile() modify the application data
David Faure <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 0a767016dbb83cc8423037a084ab9fc0c45eb0da by David Faure.
Committed on 25/07/2026 at 17:53.
Pushed by dfaure into branch 'master'.
Don't let fromAppStreamFile() modify the application data
It looks like a factory, but it filled in s_registry->m_appData, so
reading AppStream data changed the application identity: a <provides>
entry overwrites the component name, and the next setApplicationData()
call (KMainWindow does one per window) pushes that into
QCoreApplication::applicationName().
In KMail this renamed the application from "kmail2" to "kmail" while it
was running, so every window created afterwards looked for its .rc file
under the wrong component and came up with just the ui_standards.rc
menus.
Fill in a copy instead; callers that want the result to become the
application data still call setApplicationData() themselves.
M +14 -0 autotests/kaboutdatatest.cpp
M +6 -6 src/lib/kaboutdata.cpp
https://invent.kde.org/frameworks/kcoreaddons/-/commit/0a767016dbb83cc8423037a084ab9fc0c45eb0da
diff --git a/autotests/kaboutdatatest.cpp b/autotests/kaboutdatatest.cpp
index 285f47ec..3f545244 100644
--- a/autotests/kaboutdatatest.cpp
+++ b/autotests/kaboutdatatest.cpp
@@ -47,6 +47,7 @@ private Q_SLOTS:
void testProductName();
void testAppStream();
void testAppStreamLocalized();
+ void testAppStreamKeepsApplicationData();
};
static const char AppName[] = "app";
@@ -471,6 +472,19 @@ void KAboutDataTest::testAppStreamLocalized()
"<p>"Cool" (untranslated) Features:</p><ul><li><em>Important</em> untranslated feature release change 1.</li><li>Not so <em>important</em> untranslated feature release change 2.</li><li>Feature release change 3.</li></ul>"_L1);
}
+// Reading AppStream data must not modify the application data, in particular not its
+// component name, which QCoreApplication::applicationName() is kept in sync with.
+void KAboutDataTest::testAppStreamKeepsApplicationData()
+{
+ KAboutData::setApplicationData(KAboutData(u"myapp"_s, u"My App"_s));
+ QCOMPARE(QCoreApplication::applicationName(), "myapp"_L1);
+
+ std::ignore = KAboutData::fromAppStreamFile(QFINDTESTDATA("data/org.kde.coreaddons.test-app.xml"_L1));
+
+ QCOMPARE(KAboutData::applicationData().componentName(), "myapp"_L1);
+ QCOMPARE(QCoreApplication::applicationName(), "myapp"_L1);
+}
+
QTEST_MAIN(KAboutDataTest)
#include "kaboutdatatest.moc"
diff --git a/src/lib/kaboutdata.cpp b/src/lib/kaboutdata.cpp
index 52eef2db..c37648c9 100644
--- a/src/lib/kaboutdata.cpp
+++ b/src/lib/kaboutdata.cpp
@@ -1533,12 +1533,12 @@ struct {
KAboutData KAboutData::fromAppStreamFile(const QString &appStreamFileName)
{
- KAboutData *aboutData = s_registry->m_appData;
- if (!aboutData) {
- aboutData = new KAboutData(QCoreApplication::applicationName(), QString(), QString());
- aboutData->setBugAddress(QByteArray());
- s_registry->m_appData = aboutData;
- }
+ // Start from the application data, but fill in a copy: writing to the application data here
+ // would change the application identity behind the caller's back. In particular a <provides>
+ // entry overwrites the component name, which the next setApplicationData() call then pushes
+ // into QCoreApplication::applicationName().
+ KAboutData result = KAboutData::applicationData();
+ KAboutData *aboutData = &result;
QFile appStreamFile(appStreamFileName);
if (appStreamFile.fileName().isEmpty() || !appStreamFile.open(QFile::ReadOnly)) {