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 }