[education/gcompris] /: core, add command-line option to set the difficulty.

Johnny Jazeix null at kde.org
Wed Mar 15 21:45:26 GMT 2023


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);
 



More information about the kde-doc-english mailing list