From 1ce94fc0f5311c8d9d7dc50de239a827279edcd9 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 11 Sep 2018 10:41:57 +0200 Subject: Qt Labs Settings: warn if failed to initialize internal QSettings instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First, warn the user that the QSettings instance failed to initialize if there was an error. Then, if the error was QSettings::AccessError, print the specific application identifiers that weren't set so they know what they have to do. For example: QML Settings: Failed to initialize QSettings instance. Status code is: 1 QML Settings: The following application identifiers have not been set: QVector("organizationName", "organizationDomain") In my case, the QSettings instance wasn't created on Windows because organizationName wasn't set. Change-Id: I7970209e09b78f785730422c45978775311b96ac Reviewed-by: Jan Arve Sæther --- src/imports/settings/qqmlsettings.cpp | 22 +++++++++++++++ tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp | 34 +++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/imports/settings/qqmlsettings.cpp b/src/imports/settings/qqmlsettings.cpp index 2271774643..54ff64a3a9 100644 --- a/src/imports/settings/qqmlsettings.cpp +++ b/src/imports/settings/qqmlsettings.cpp @@ -39,10 +39,12 @@ #include "qqmlsettings_p.h" #include +#include #include #include #include #include +#include #include #include @@ -269,6 +271,26 @@ QSettings *QQmlSettingsPrivate::instance() const if (!settings) { QQmlSettings *q = const_cast(q_func()); settings = new QSettings(q); + if (settings->status() != QSettings::NoError) { + // TODO: can't print out the enum due to the following error: + // error: C2666: 'QQmlInfo::operator <<': 15 overloads have similar conversions + qmlWarning(q) << "Failed to initialize QSettings instance. Status code is: " << int(settings->status()); + + if (settings->status() == QSettings::AccessError) { + QVector missingIdentifiers; + if (QCoreApplication::organizationName().isEmpty()) + missingIdentifiers.append(QLatin1String("organizationName")); + if (QCoreApplication::organizationDomain().isEmpty()) + missingIdentifiers.append(QLatin1String("organizationDomain")); + if (QCoreApplication::applicationName().isEmpty()) + missingIdentifiers.append(QLatin1String("applicationName")); + + if (!missingIdentifiers.isEmpty()) + qmlWarning(q) << "The following application identifiers have not been set: " << missingIdentifiers; + } + return settings; + } + if (!category.isEmpty()) settings->beginGroup(category); if (initialized) diff --git a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp index b353d23539..b0be799bd5 100644 --- a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp +++ b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp @@ -53,6 +53,7 @@ private slots: void categories(); void siblings(); void initial(); + void noApplicationIdentifiersSet(); }; // ### Replace keyValueMap("foo", "bar") with QVariantMap({{"foo", "bar"}}) @@ -147,10 +148,6 @@ void tst_QQmlSettings::initTestCase() { QQmlDataTest::initTestCase(); - QCoreApplication::setApplicationName("tst_QQmlSettings"); - QCoreApplication::setOrganizationName("QtProject"); - QCoreApplication::setOrganizationDomain("qt-project.org"); - qmlRegisterType("Qt.test", 1, 0, "CppObject"); } @@ -158,6 +155,10 @@ void tst_QQmlSettings::init() { QSettings settings; settings.clear(); + + QCoreApplication::setApplicationName("tst_QQmlSettings"); + QCoreApplication::setOrganizationName("QtProject"); + QCoreApplication::setOrganizationDomain("qt-project.org"); } void tst_QQmlSettings::cleanup() @@ -481,6 +482,31 @@ void tst_QQmlSettings::initial() QCOMPARE(settings->property("value").toString(), QStringLiteral("initial")); } +void tst_QQmlSettings::noApplicationIdentifiersSet() +{ +#ifdef Q_OS_MACOS + QSKIP("macOS doesn't complain about empty application identifiers"); +#endif + + QCoreApplication::setApplicationName(QString()); + QCoreApplication::setOrganizationName(QString()); + QCoreApplication::setOrganizationDomain(QString()); + + QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*QML Settings: Failed to initialize QSettings instance. Status code is: 1")); + // Can't set an empty applicationName because QCoreApplication won't allow it, which is why it's not listed here. + QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*QML Settings: The following application identifiers have not been set: QVector\\(\"organizationName\", \"organizationDomain\"\\)")); + + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("basic.qml")); + QScopedPointer root(component.create()); + QVERIFY(root.data()); + // The value of the QML property will be true because it defaults to it... + QVERIFY(root->property("success").toBool()); + QSettings settings; + // ... but the settings' value should be false because it was never loaded. + QVERIFY(!settings.value("success").toBool()); +} + QTEST_MAIN(tst_QQmlSettings) #include "tst_qqmlsettings.moc" -- cgit v1.2.3