Git commit b14ec28be263528256b90c242db36f83675ead01 by Johnny Jazeix. Committed on 15/03/2023 at 20:51. Pushed by jjazeix into branch 'master'.
core, add command-line option to set the difficulty. gcompris-qt --difficulty x to set to x difficulty (x between 1 and 6) or gcompris-qt --difficulty x-y to set difficulty between x and y (x and between 1 and 6, x < y). If there is any error parsing the difficulty, an error is displayed and GCompris leaves. M +4 -0 docs/docbook/index.docbook M +2 -0 src/activities/menu/ConfigurationItem.qml M +6 -3 src/core/ActivityInfoTree.cpp M +14 -2 src/core/ActivityInfoTree.h M +13 -5 src/core/ApplicationSettings.cpp M +22 -0 src/core/ApplicationSettings.h M +2 -2 src/core/GComprisPlugin.cpp M +32 -0 src/core/main.cpp https://invent.kde.org/education/gcompris/commit/b14ec28be263528256b90c242db36f83675ead01 diff --git a/docs/docbook/index.docbook b/docs/docbook/index.docbook index 3203a9fab..dadb6e5ba 100644 --- a/docs/docbook/index.docbook +++ b/docs/docbook/index.docbook @@ -306,6 +306,10 @@ or make it show real car images instead of filled rectangles (traffic).</para> <entry>Specify the activity when starting GCompris.</entry> </row> <row> +<entry>--difficulty {value|min-max}</entry> +<entry>For the session, force the GCompris activities difficulties to be at either value or between min and max values. The values must be between 1 and 6, and if the format is min-max, the min value must be lower than the max value. If it is not the case GCompris will not start.</entry> +</row> +<row> <entry>--export-activities-as-sql</entry> <entry>Export activities as SQL.</entry> </row> diff --git a/src/activities/menu/ConfigurationItem.qml b/src/activities/menu/ConfigurationItem.qml index a0bf13535..b96a6809c 100644 --- a/src/activities/menu/ConfigurationItem.qml +++ b/src/activities/menu/ConfigurationItem.qml @@ -371,6 +371,7 @@ Item { GCText { text: qsTr("Difficulty filter:") fontSize: mediumSize + visible: !ApplicationSettings.filterLevelOverridedByCommandLineOption width: dialogConfig.contentWidth height: 50 * ApplicationInfo.ratio } @@ -379,6 +380,7 @@ Item { id: difficultyFlow width: dialogConfig.contentWidth spacing: 5 * ApplicationInfo.ratio + visible: !ApplicationSettings.filterLevelOverridedByCommandLineOption property int starsSize: Math.floor(dialogConfig.contentWidth * 0.11) Image { diff --git a/src/core/ActivityInfoTree.cpp b/src/core/ActivityInfoTree.cpp index a6b68ba32..aeb8f94fa 100644 --- a/src/core/ActivityInfoTree.cpp +++ b/src/core/ActivityInfoTree.cpp @@ -19,6 +19,7 @@ #include <QTextStream> QString ActivityInfoTree::m_startingActivity = ""; +ActivityInfoTree *ActivityInfoTree::m_instance = nullptr; ActivityInfoTree::ActivityInfoTree(QObject *parent) : QObject(parent), @@ -256,7 +257,7 @@ QObject *ActivityInfoTree::menuTreeProvider(QQmlEngine *engine, QJSEngine *scrip { Q_UNUSED(scriptEngine) - ActivityInfoTree *menuTree = new ActivityInfoTree(nullptr); + ActivityInfoTree *menuTree = getInstance(); QQmlComponent componentRoot(engine, QUrl("qrc:/gcompris/src/activities/menu/ActivityInfo.qml")); QObject *objectRoot = componentRoot.create(); @@ -351,12 +352,14 @@ void ActivityInfoTree::filterBySearch(const QString &text) Q_EMIT menuTreeChanged(); } -void ActivityInfoTree::minMaxFiltersChanged(quint32 levelMin, quint32 levelMax, bool emitChanged) +void ActivityInfoTree::minMaxFiltersChanged(quint32 levelMin, quint32 levelMax, bool doSynchronize) { for (ActivityInfo *activity: qAsConst(m_menuTreeFull)) { activity->enableDatasetsBetweenDifficulties(levelMin, levelMax); } - ApplicationSettings::getInstance()->sync(); + if (doSynchronize) { + ApplicationSettings::getInstance()->sync(); + } } QVariantList ActivityInfoTree::allCharacters() diff --git a/src/core/ActivityInfoTree.h b/src/core/ActivityInfoTree.h index 25ffe64a5..fe9a9b1fe 100644 --- a/src/core/ActivityInfoTree.h +++ b/src/core/ActivityInfoTree.h @@ -28,6 +28,13 @@ class ActivityInfoTree : public QObject Q_PROPERTY(QString startingActivity MEMBER m_startingActivity NOTIFY startingActivityChanged) public: + static ActivityInfoTree *getInstance() + { + if (!m_instance) { + m_instance = new ActivityInfoTree(); + } + return m_instance; + } QQmlListProperty<ActivityInfo> menuTree(); ActivityInfo *getRootMenu() const; void setRootMenu(ActivityInfo *rootMenu); @@ -42,15 +49,20 @@ public: static void setStartingActivity(const QString &startingActivity) { m_startingActivity = startingActivity; } -protected Q_SLOTS: +protected: + static ActivityInfoTree *m_instance; + +public Q_SLOTS: + Q_INVOKABLE void minMaxFiltersChanged(quint32 levelMin, quint32 levelMax, bool doSynchronize = true); Q_INVOKABLE void filterByTag(const QString &tag, const QString &category = "", bool emitChanged = true); + +protected Q_SLOTS: Q_INVOKABLE void filterEnabledActivities(bool emitChanged = true); // create a tree from the whole list of activities with the activities created between the two versions Q_INVOKABLE void filterCreatedWithinVersions(int firstVersion, int lastVersion, bool emitChanged = true); Q_INVOKABLE void filterBySearch(const QString &text); Q_INVOKABLE void filterByDifficulty(quint32 levelMin, quint32 levelMax); - Q_INVOKABLE void minMaxFiltersChanged(quint32 levelMin, quint32 levelMax, bool emitChanged = true); Q_INVOKABLE void setCurrentActivityFromName(const QString &name); Q_SIGNALS: diff --git a/src/core/ApplicationSettings.cpp b/src/core/ApplicationSettings.cpp index 8f023292f..5f79e82fe 100644 --- a/src/core/ApplicationSettings.cpp +++ b/src/core/ApplicationSettings.cpp @@ -206,8 +206,10 @@ ApplicationSettings::~ApplicationSettings() m_config.setValue(PREVIOUS_WIDTH_KEY, m_previousWidth); m_config.setValue(VIRTUALKEYBOARD_KEY, m_isVirtualKeyboard); m_config.setValue(ENABLE_AUTOMATIC_DOWNLOADS, m_isAutomaticDownloadsEnabled); - m_config.setValue(FILTER_LEVEL_MIN, m_filterLevelMin); - m_config.setValue(FILTER_LEVEL_MAX, m_filterLevelMax); + if (!m_filterLevelOverridedByCommandLineOption) { + m_config.setValue(FILTER_LEVEL_MIN, m_filterLevelMin); + m_config.setValue(FILTER_LEVEL_MAX, m_filterLevelMax); + } m_config.setValue(KIOSK_KEY, m_isKioskMode); m_config.setValue(SECTION_VISIBLE, m_sectionVisible); m_config.setValue(EXIT_CONFIRMATION, m_exitConfirmation); @@ -348,14 +350,18 @@ void ApplicationSettings::notifyAutomaticDownloadsEnabledChanged() void ApplicationSettings::notifyFilterLevelMinChanged() { - updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MIN, m_filterLevelMin); qDebug() << "filterLevelMin set to: " << m_filterLevelMin; + if (!m_filterLevelOverridedByCommandLineOption) { + updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MIN, m_filterLevelMin); + } } void ApplicationSettings::notifyFilterLevelMaxChanged() { - updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MAX, m_filterLevelMax); qDebug() << "filterLevelMax set to: " << m_filterLevelMax; + if (!m_filterLevelOverridedByCommandLineOption) { + updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MAX, m_filterLevelMax); + } } void ApplicationSettings::notifyKioskModeChanged() @@ -478,7 +484,9 @@ bool ApplicationSettings::isFavorite(const QString &activity) void ApplicationSettings::setCurrentLevels(const QString &activity, const QStringList &level, bool sync) { - updateValueInConfig(LEVELS_GROUP_KEY, activity, level, sync); + if (!m_filterLevelOverridedByCommandLineOption) { + updateValueInConfig(LEVELS_GROUP_KEY, activity, level, sync); + } } QStringList ApplicationSettings::currentLevels(const QString &activity) diff --git a/src/core/ApplicationSettings.h b/src/core/ApplicationSettings.h index 3e7558d1b..b9233b7a1 100644 --- a/src/core/ApplicationSettings.h +++ b/src/core/ApplicationSettings.h @@ -161,6 +161,12 @@ class ApplicationSettings : public QObject */ Q_PROPERTY(quint32 filterLevelMax READ filterLevelMax WRITE setFilterLevelMax NOTIFY filterLevelMaxChanged) + /** + * Boolean to know if the difficulty level filter has been set via command-line option. + * In this case, we hide the possibility to change the level in the configuration and we never override the levels in the GCompris config file. + */ + Q_PROPERTY(bool filterLevelOverridedByCommandLineOption READ filterLevelOverridedByCommandLineOption WRITE setFilterLevelOverridedByCommandLineOption NOTIFY filterLevelOverridedByCommandLineOptionChanged) + /** * Whether kiosk mode is currently active. */ @@ -405,6 +411,13 @@ public: Q_EMIT filterLevelMaxChanged(); } + bool filterLevelOverridedByCommandLineOption() const { return m_filterLevelOverridedByCommandLineOption; } + void setFilterLevelOverridedByCommandLineOption(const bool newValue) + { + m_filterLevelOverridedByCommandLineOption = newValue; + Q_EMIT filterLevelOverridedByCommandLineOptionChanged(); + } + bool isKioskMode() const { return m_isKioskMode; } void setKioskMode(const bool newMode) { @@ -527,6 +540,13 @@ public: */ Q_INVOKABLE bool useExternalWordset(); + void setDifficultyFromCommandLine(quint32 newFilterLevelMin, quint32 newFilterLevelMax) + { + m_filterLevelOverridedByCommandLineOption = true; + setFilterLevelMin(newFilterLevelMin); + setFilterLevelMax(newFilterLevelMax); + } + protected Q_SLOTS: Q_INVOKABLE void notifyAudioVoicesEnabledChanged(); @@ -624,6 +644,7 @@ Q_SIGNALS: void automaticDownloadsEnabledChanged(); void filterLevelMinChanged(); void filterLevelMaxChanged(); + void filterLevelOverridedByCommandLineOptionChanged(); void kioskModeChanged(); void sectionVisibleChanged(); void exitConfirmationChanged(); @@ -666,6 +687,7 @@ private: qreal m_fontLetterSpacing; quint32 m_filterLevelMin; quint32 m_filterLevelMax; + bool m_filterLevelOverridedByCommandLineOption = false; bool m_defaultCursor; bool m_noCursor; QString m_locale; diff --git a/src/core/GComprisPlugin.cpp b/src/core/GComprisPlugin.cpp index 250835793..064648776 100644 --- a/src/core/GComprisPlugin.cpp +++ b/src/core/GComprisPlugin.cpp @@ -35,8 +35,8 @@ void GComprisPlugin::registerTypes(const char *uri) qmlRegisterSingletonType<ApplicationInfo>(uri, versionMajor, versionMinor, "ApplicationInfo", ApplicationInfo::applicationInfoProvider); - qmlRegisterSingletonType<QObject>(uri, versionMajor, versionMinor, - "ActivityInfoTree", ActivityInfoTree::menuTreeProvider); + qmlRegisterSingletonType<ActivityInfoTree>(uri, versionMajor, versionMinor, + "ActivityInfoTree", ActivityInfoTree::menuTreeProvider); qmlRegisterType<Dataset>(uri, versionMajor, versionMinor, "Data"); qmlRegisterType<ActivityInfo>(uri, versionMajor, versionMinor, "ActivityInfo"); qmlRegisterSingletonType<ApplicationSettings>(uri, versionMajor, versionMinor, diff --git a/src/core/main.cpp b/src/core/main.cpp index bb9cc10f8..65cc4ab27 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -208,6 +208,10 @@ int main(int argc, char *argv[]) QObject::tr("Outputs all the available activities on the standard output.")); parser.addOption(clListActivities); + QCommandLineOption clDifficultyRange("difficulty", + QObject::tr("Specify the range of the activity difficulties to display for the session. Either a single value (2), or a range (3-6). Values must be between 1 and 6."), "difficulty"); + parser.addOption(clDifficultyRange); + parser.process(app); GComprisPlugin plugin; @@ -331,6 +335,34 @@ int main(int argc, char *argv[]) menuTree->listActivities(); return 0; } + // Start on specific difficulties + if (parser.isSet(clDifficultyRange)) { + QString difficultyRange = parser.value(clDifficultyRange); + QStringList levels = difficultyRange.split(QStringLiteral("-")); + quint32 minDifficulty = levels[0].toUInt(); + quint32 maxDifficulty = minDifficulty; + // If we have a range, take the second value as max difficulty + if (levels.size() > 1) { + maxDifficulty = levels[1].toUInt(); + } + if (minDifficulty > maxDifficulty) { + qWarning() << "Minimal level must be lower than maximum level"; + return -1; + } + if (minDifficulty < 1 || minDifficulty > 6) { + qWarning() << "Minimal level must between 1 and 6"; + return -1; + } + if (maxDifficulty < 1 || maxDifficulty > 6) { + qWarning() << "Maximal level must between 1 and 6"; + return -1; + } + + qDebug() << QStringLiteral("Setting difficulty between %1 and %2").arg(minDifficulty).arg(maxDifficulty); + ApplicationSettings::getInstance()->setDifficultyFromCommandLine(minDifficulty, maxDifficulty); + ActivityInfoTree::getInstance()->minMaxFiltersChanged(minDifficulty, maxDifficulty, false); + ActivityInfoTree::getInstance()->filterByTag("favorite"); + } QObject *topLevel = engine.rootObjects().value(0);
