Warning, /education/gcompris/src/core/ActivityBase.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - ActivityBase.qml
0002 *
0003 * SPDX-FileCopyrightText: 2014 Bruno Coudoin <bruno.coudoin@gcompris.net>
0004 *
0005 * Authors:
0006 * Bruno Coudoin <bruno.coudoin@gcompris.net>
0007 *
0008 * SPDX-License-Identifier: GPL-3.0-or-later
0009 */
0010 import QtQuick 2.12
0011 import GCompris 1.0
0012 import "qrc:/gcompris/src/core/core.js" as Core
0013
0014 /**
0015 * The base QML component for activities in GCompris.
0016 * @ingroup components
0017 *
0018 * Each activity should be derived from this component. It is responsible for
0019 *
0020 * * Activity common key handling,
0021 * * unified audio handling,
0022 * * screen switching dynamics (from/to Menu/DialogHelp/etc.)
0023 *
0024 * The following common keys are handled so far:
0025 *
0026 * * @c Ctrl+w: Exit the current activity and return to the menu,
0027 * or close the application if on the menu page.
0028 * * @c Back: Same as above.
0029 * * @c Escape: Same as above.
0030 *
0031 * Cf. Template.qml for a sample skeleton activity.
0032 *
0033 * Cf.
0034 * [the wiki](https://gcompris.net/wiki/Qt_Quick_development_process#Adding_a_new_activity)
0035 * for further information about creating a new activity.
0036 *
0037 * @inherit QtQuick.Item
0038 */
0039 Item {
0040 id: page
0041
0042 /**
0043 * type:Item
0044 * Parent object.
0045 */
0046 property Item main: parent
0047
0048 /**
0049 * type:Component
0050 * The top-level component containing the visible viewport of an activity.
0051 *
0052 * Put all you want to present the user into this container. Mostly
0053 * implemented using a Rectangle or Image component, itself
0054 * containing further graphical elements. You are pretty free of doing
0055 * whatever you want inside this component.
0056 *
0057 * Also common elements as Bar, Score, DialogHelp, etc. should be placed
0058 * inside this element.
0059 */
0060 property Component pageComponent
0061
0062 /**
0063 * type:QtObject
0064 * Reference to the menu activity.
0065 *
0066 * Populated automatically during activity-loading.
0067 */
0068 property QtObject menu
0069
0070 /**
0071 * type:QtObject
0072 * Reference to the ActivityInfo object of the activity.
0073 *
0074 * Populated automatically during activity-loading.
0075 */
0076 property QtObject activityInfo
0077
0078 /**
0079 * type:GCAudio
0080 * The global audio item for voices.
0081 *
0082 * Because of problems synchronizing multiple Audio objects between
0083 * global/menu/main and individual activities, activities should refrain
0084 * from implementing additional Audio elements.
0085 *
0086 * Instead append to this global object to play your voices after the
0087 * intro music.
0088 * @sa GCAudio audioVoices
0089 */
0090 property GCAudio audioVoices
0091
0092 /**
0093 * type:GCSfx
0094 * The global audio item for audio effects.
0095 *
0096 * Use it to play your effects.
0097 * @sa GCSfx audioEffects
0098 */
0099 property GCSfx audioEffects
0100
0101 /**
0102 * type:GCAudio
0103 * The global audio item for background music.
0104 *
0105 * @sa GCAudio backgroundMusic
0106 */
0107 property GCAudio backgroundMusic
0108
0109 /**
0110 * type:string
0111 * The resource folder for the current activity. The resources
0112 * of each activity needs to be stored with the same pattern.
0113 * "qrc:/gcompris/src/activities/" + activity name + "/resource/"
0114 *
0115 */
0116 property string resourceUrl: (activityInfo && activityInfo.name) ? "qrc:/gcompris/src/activities/" + activityInfo.name.split('/')[0] + "/resource/": ""
0117
0118 /**
0119 * type: bool
0120 * It tells whether the activity is a musical activity or not(if the activity contains it's own audio effects).
0121 *
0122 * If the activity is a musical activity, on starting it the background music pauses and when the activity is quit, background music resumes.
0123 *
0124 * Set it as true if the activity is musical.
0125 */
0126 property bool isMusicalActivity: false
0127
0128 /**
0129 * type:int
0130 * The current level for this activity.
0131 */
0132 property int currentLevel: 0
0133
0134 property alias datasetLoader: datasetLoader
0135 property var levelFolder
0136
0137 /**
0138 * type:Loading
0139 * The global loading object.
0140 *
0141 * Start it to signal heavy computation in case of GUI freezes.
0142 * @sa Loading
0143 */
0144 property Loading loading
0145
0146 /**
0147 * type: bool
0148 * Check if the activity is the menu or not.
0149 * Set by default to false for all activities,
0150 * and only set to true inside Menu.qml
0151 */
0152 property bool isMenu: false
0153
0154 /**
0155 * Emitted when the user wants to return to the Home/Menu screen.
0156 */
0157 signal home
0158
0159 /**
0160 * Emitted when the user wants to return several views back in the
0161 * page stack.
0162 */
0163 signal back(Item to)
0164
0165 /**
0166 * Emitted every time the activity has been started.
0167 *
0168 * Initialize your activity upon this signal.
0169 */
0170 signal start
0171
0172 /**
0173 * Emitted when the activity is about to stop
0174 *
0175 * Shutdown whatever you need to upon this signal.
0176 */
0177 signal stop
0178
0179 /**
0180 * Connected to stop signal
0181 * Used to stop all the voices and sounds from the activity
0182 */
0183 signal stopSounds
0184
0185 /**
0186 * Emitted when dialog @p dialog should be shown
0187 *
0188 * Emit this signal when you want to show another dialog, e.g. on
0189 * Bar.onHelpClicked
0190 *
0191 * @param dialog Dialog to show.
0192 */
0193 signal displayDialog(Item dialog)
0194
0195 /**
0196 * Emitted when multiple @p dialogs should be pushed on the page-stack
0197 *
0198 * Emit this signal when you want to stack >1 views. The last one will be
0199 * shown the intermediated ones will be kept on the page stack for later
0200 * pop() calls.
0201 *
0202 * @param dialogs Array of dialogs to push;
0203 */
0204 signal displayDialogs(var dialogs)
0205
0206 //Initially hide it to avoid components appearing on the menu while the activity is loading.
0207 visible: false
0208
0209 Component.onCompleted: {
0210 page.stop.connect(stopSounds);
0211 }
0212 onStopSounds: {
0213 if(!isMenu) {
0214 audioEffects.stop();
0215 audioVoices.clearQueue();
0216 audioVoices.stop();
0217 }
0218 }
0219
0220 onBack: menu ? menu.back(to) : ""
0221 onHome: menu ? menu.home() : ""
0222 onDisplayDialog: menu ? menu.displayDialog(dialog) : ""
0223 onDisplayDialogs: menu ? menu.displayDialogs(dialogs) : ""
0224
0225 Keys.forwardTo: activity.children
0226 Keys.onEscapePressed: home();
0227 Keys.onPressed: {
0228 if (event.modifiers === Qt.ControlModifier && event.key === Qt.Key_W) {
0229 // Ctrl+W exit the current activity
0230 home();
0231 }
0232 }
0233 Keys.onReleased: {
0234 if (event.key === Qt.Key_Back) {
0235 event.accepted = true;
0236 home();
0237 }
0238 }
0239
0240 Loader {
0241 id: activity
0242 sourceComponent: pageComponent
0243 anchors.fill: parent
0244 }
0245
0246 onLevelFolderChanged: {
0247 if(levelFolder === undefined || levelFolder.length === 0) {
0248 return
0249 }
0250
0251 datasetLoader.data = []
0252 var data = [];
0253 // sorting levelFolders in numeric manner
0254 levelFolder.sort(function(a, b) { return (parseInt(a) - parseInt(b)) });
0255 for(var level in levelFolder /*todo maybe we don't need anymore levelFolder and we can use activityInfo.currentLevels*/) {
0256 var id = levelFolder[level];
0257 var dataset = activityInfo.getDataset(id);
0258 if(dataset) {
0259 data = data.concat(dataset.data);
0260 }
0261 }
0262 datasetLoader.data = data
0263 //datasetLoader.start()
0264 }
0265
0266 // todo Maybe not needed anymore
0267 Loader {
0268 id: datasetLoader
0269 asynchronous: false
0270
0271 property var dataFiles: []
0272 property var currentFile
0273 property var data: []
0274 signal start
0275 signal stop
0276
0277 onStart: {
0278 var file = dataFiles.shift()
0279 currentFile = file
0280 source = file.file.toString()
0281 }
0282
0283 onLoaded: {
0284 data = data.concat(item.data)
0285
0286 if(dataFiles.length != 0) {
0287 start()
0288 }
0289 else {
0290 stop()
0291 }
0292 }
0293 onStop: {
0294 //print("stop", JSON.stringify(data))
0295 source = ""
0296 // Core.shuffle(data) do we want to shuffle??? Should depend on the activity (if we want increasing levels) or teachers (random multiplication tables for example)
0297 }
0298 }
0299 }