Warning, /education/gcompris/src/core/DialogChooseLevel.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - DialogChooseLevel.qml
0002  *
0003  * SPDX-FileCopyrightText: 2018 Johnny Jazeix <jazeix@gmail.com>
0004  *
0005  * Authors:
0006  *   Johnny Jazeix <jazeix@gmail.com>
0007  *
0008  *   SPDX-License-Identifier: GPL-3.0-or-later
0009  */
0010 import QtQuick 2.12
0011 import GCompris 1.0
0012 
0013 /**
0014  * todo
0015  * @ingroup components
0016  *
0017  * todo
0018  *
0019  * @sa ApplicationSettings
0020  * @inherit QtQuick.Item
0021  */
0022 Rectangle {
0023     id: dialogChooseLevel
0024     visible: false
0025     focus: visible
0026 
0027     /* Public interface: */
0028 
0029     /**
0030      * type:string
0031      * The name of the activity in case of per-activity config.
0032      *
0033      * Will be autogenerated unless set by the caller.
0034      */
0035     property string activityName: currentActivity.name.split('/')[0]
0036 
0037     /// @cond INTERNAL_DOCS
0038 
0039     property bool isDialog: true
0040 
0041     /**
0042      * type:string
0043      * Title of the configuration dialog.
0044     */
0045     readonly property string title: currentActivity ? qsTr("%1 settings").arg(currentActivity.title) : ""
0046 
0047     property var difficultiesModel: []
0048     property QtObject currentActivity
0049 
0050     property var chosenLevels: []
0051 
0052     property var activityData
0053     onActivityDataChanged: loadData()
0054     /// @endcond
0055 
0056     /**
0057      * By default, we display configuration (this avoids to add code in each 
0058      * activity to set it by default).
0059      */
0060     property bool displayDatasetAtStart: !hasConfig
0061 
0062     /**
0063      * Emitted when the config dialog has been closed.
0064      */
0065     signal close
0066 
0067     /**
0068      * Emitted when the config dialog has been started.
0069      */
0070     signal start
0071 
0072     onStart: initialize()
0073 
0074     signal stop
0075 
0076     /**
0077      * Emitted when the settings are to be saved.
0078      *
0079      * The actual persisting of the settings in the settings file is done by
0080      * DialogActivityConfig. The activity has to take care to update its
0081      * internal state.
0082      */
0083     signal saveData
0084 
0085     signal startActivity
0086 
0087     /**
0088      * Emitted when the config settings have been loaded.
0089      */
0090     signal loadData
0091 
0092     property bool datasetButtonVisible: true
0093     property bool hasConfigOrDataset: hasConfig || hasDataset
0094     property bool hasConfig: currentActivity && currentActivity.hasConfig
0095     property bool hasDataset: currentActivity && currentActivity.hasDataset && datasetButtonVisible
0096 
0097     color: "#696da3"
0098 
0099     property bool inMenu: false
0100 
0101     onVisibleChanged: {
0102         if(visible) {
0103             configLoader.initializePanel()
0104         }
0105     }
0106 
0107     Keys.onPressed: {
0108         if(event.key === Qt.Key_Down) {
0109             scrollItem.down();
0110         } else if(event.key === Qt.Key_Up) {
0111             scrollItem.up();
0112         } else if(event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
0113             if(saveAndStartButton.visible) {
0114                 saveAndStartButton.clicked();
0115             } else {
0116                 saveButton.clicked();
0117             }
0118         } else if(datasetVisibleButton.enabled && optionsVisibleButton.enabled &&
0119                 (event.key === Qt.Key_Left || event.key === Qt.Key_Right)) {
0120             if(datasetVisibleButton.selected) {
0121                 optionsVisibleButton.clicked();
0122             } else {
0123                 datasetVisibleButton.clicked();
0124             }
0125         }
0126     }
0127 
0128     Keys.onEscapePressed: {
0129         cancelButton.clicked();
0130     }
0131 
0132     Keys.onReleased: {
0133         if(event.key === Qt.Key_Back) {
0134             cancelButton.clicked();
0135             event.accepted = true;
0136         }
0137     }
0138 
0139     onClose: activity.forceActiveFocus();
0140 
0141     function initialize() {
0142         // dataset information
0143         chosenLevels = currentActivity.currentLevels.slice()
0144         difficultiesModel = []
0145         for(var level in currentActivity.levels) {
0146             var data = currentActivity.getDataset(currentActivity.levels[level])
0147             difficultiesModel.push({
0148                 "level": currentActivity.levels[level],
0149                 "enabled": data.enabled,
0150                 "objective": data.objective,
0151                 "difficulty": data.difficulty,
0152                 "selectedInConfig": (chosenLevels.indexOf(currentActivity.levels[level]) != -1)
0153             })
0154         }
0155         difficultiesRepeater.model = difficultiesModel
0156 
0157         // Defaults to config if in an activity else to dataset if in menu
0158         if(displayDatasetAtStart) {
0159             datasetVisibleButton.clicked()
0160         }
0161         else {
0162             optionsVisibleButton.clicked()
0163         }
0164     }
0165 
0166     Column {
0167         id: titleColumn
0168         spacing: 10
0169         anchors.top: parent.top
0170         anchors.topMargin: 15
0171         anchors.horizontalCenter: parent.horizontalCenter
0172         width: dialogChooseLevel.width - 30
0173         Rectangle {
0174             id: titleRectangle
0175             color: "#e6e6e6"
0176             radius: 10 * ApplicationInfo.ratio
0177             width: parent.width
0178             height: title.height + 10 * 2
0179 
0180             GCText {
0181                 id: title
0182                 text: dialogChooseLevel.title
0183                 width: titleColumn.width - 10
0184                 anchors.horizontalCenter: titleRectangle.horizontalCenter
0185                 anchors.verticalCenter: titleRectangle.verticalCenter
0186                 horizontalAlignment: Text.AlignHCenter
0187                 verticalAlignment: Text.AlignVCenter
0188                 fontSize: 20
0189                 font.weight: Font.DemiBold
0190                 wrapMode: Text.WordWrap
0191             }
0192         }
0193 
0194         // Header buttons
0195         Row {
0196             id: datasetOptionsRow
0197             height: dialogChooseLevel.height / 12
0198             width: titleRectangle.width
0199             spacing: titleRectangle.width * 0.1
0200             GCButton {
0201                 id: datasetVisibleButton
0202                 text: qsTr("Dataset")
0203                 enabled: hasDataset
0204                 height: parent.height
0205                 width: titleRectangle.width * 0.45
0206                 opacity: enabled ? 1 : 0
0207                 theme: "settingsButton"
0208                 selected: datasetVisibleButton.selected
0209                 onClicked: { selected = true; }
0210                 // reset the view to original position when changing tab
0211                 onSelectedChanged: { flick.contentY = 0; }
0212             }
0213             GCButton {
0214                 id: optionsVisibleButton
0215                 text: qsTr("Options")
0216                 enabled: hasConfig
0217                 height: parent.height
0218                 width: titleRectangle.width * 0.45
0219                 opacity: enabled ? 1 : 0
0220                 theme: "settingsButton"
0221                 selected: !datasetVisibleButton.selected
0222                 onClicked: { datasetVisibleButton.selected = false; } //showOptions()
0223             }
0224         }
0225 
0226         // "Dataset"/"Options" content
0227         Rectangle {
0228             color: "#bdbed0"
0229             radius: 10 * ApplicationInfo.ratio
0230             width: dialogChooseLevel.width - 30
0231             height: dialogChooseLevel.height - (2 * parent.anchors.topMargin) - titleRectangle.height - datasetOptionsRow.height - saveAndPlayRow.height - (3 * parent.spacing)
0232             border.color: "white"
0233             border.width: 3 * ApplicationInfo.ratio
0234 
0235             Flickable {
0236                 id: flick
0237                 flickDeceleration: 1500
0238                 anchors.margins: 10 * ApplicationInfo.ratio
0239                 anchors.fill: parent
0240                 flickableDirection: Flickable.VerticalFlick
0241                 clip: true
0242                 contentHeight: contentItem.childrenRect.height + 40 * ApplicationInfo.ratio
0243 
0244                 Loader {
0245                     id: configLoader
0246                     visible: !datasetVisibleButton.selected
0247                     active: optionsVisibleButton.enabled
0248                     source: active ? "qrc:/gcompris/src/activities/"+activityName+"/ActivityConfig.qml" : ""
0249 
0250                     // Load configuration at start of activity
0251                     // in the menu, it's done when the visibility property
0252                     // of the dialog changes
0253                     onItemChanged: if(!inMenu) { initializePanel(); }
0254 
0255                     function initializePanel() {
0256                         if(item) {
0257                             // only connect once the signal to save data
0258                             if(item.background !== dialogChooseLevel) {
0259                                 item.background = dialogChooseLevel
0260                                 dialogChooseLevel.saveData.connect(save)
0261                             }
0262                             getInitialConfiguration()
0263                         }
0264                     }
0265                     function getInitialConfiguration() {
0266                         activityData = Qt.binding(function() { return item.dataToSave })
0267                         if(item) {
0268                             item.dataToSave = ApplicationSettings.loadActivityConfiguration(activityName)
0269                             item.setDefaultValues()
0270                         }
0271                     }
0272                     function save() {
0273                         item.saveValues()
0274                         ApplicationSettings.saveActivityConfiguration(activityName, item.dataToSave)
0275                     }
0276                 }
0277 
0278                 Column {
0279                     visible: datasetVisibleButton.selected
0280                     spacing: 10
0281 
0282                     Repeater {
0283                         id: difficultiesRepeater
0284                         delegate: Row {
0285                             height: datasetVisibleButton.selected ? objective.height : 0
0286                             visible: modelData.enabled
0287                             spacing: 10
0288                             Image {
0289                                 id: difficultyIcon
0290                                 source: "qrc:/gcompris/src/core/resource/difficulty" +
0291                                 modelData.difficulty + ".svg";
0292                                 sourceSize.height: objective.indicatorImageHeight
0293                                 sourceSize.width: height
0294                                 anchors.top: objective.top
0295                             }
0296                             GCDialogCheckBox {
0297                                 id: objective
0298                                 width: datasetOptionsRow.width - difficultyIcon.width - 2 * flick.anchors.margins - indicatorImageHeight
0299                                 text: modelData.objective
0300                                 checked: chosenLevels.indexOf(modelData.level) != -1
0301                                 onVisibleChanged: {
0302                                     if(visible) checked = (chosenLevels.indexOf(modelData.level) != -1)
0303                                 }
0304                                 onClicked: {
0305                                     if(checked) {
0306                                         chosenLevels.push(modelData.level)
0307                                     }
0308                                     else if(chosenLevels.length > 1) {
0309                                         chosenLevels.splice(chosenLevels.indexOf(modelData.level), 1)
0310                                     }
0311                                     else {
0312                                         // At least one must be selected
0313                                         checked = true;
0314                                     }
0315                                 }
0316                             }
0317                         }
0318                     }
0319                 }
0320             }
0321 
0322             // The scroll buttons
0323             GCButtonScroll {
0324                 id: scrollItem
0325                 anchors.right: parent.right
0326                 anchors.rightMargin: 5 * ApplicationInfo.ratio
0327                 anchors.bottom: flick.bottom
0328                 anchors.bottomMargin: 5 * ApplicationInfo.ratio
0329                 onUp: flick.flick(0, 1000)
0330                 onDown: flick.flick(0, -1000)
0331                 upVisible: flick.atYBeginning ? false : true
0332                 downVisible: flick.atYEnd ? false : true
0333             }
0334         }
0335         // Footer buttons
0336         Row {
0337             id: saveAndPlayRow
0338             height: dialogChooseLevel.height / 12
0339             width: titleRectangle.width
0340             spacing: titleRectangle.width * 0.05
0341             GCButton {
0342                 id: cancelButton
0343                 text: qsTr("Cancel")
0344                 height: parent.height
0345                 width: titleRectangle.width * 0.25
0346                 theme: "settingsButton"
0347                 onClicked: close();
0348             }
0349             GCButton {
0350                 id: saveButton
0351                 text: qsTr("Save")
0352                 height: parent.height
0353                 width: titleRectangle.width * 0.25
0354                 theme: "settingsButton"
0355                 onClicked: {
0356                     saveData();
0357                     if (inMenu === false) {
0358                         startActivity();
0359                     }
0360                     close();
0361                 }
0362             }
0363             GCButton {
0364                 id: saveAndStartButton
0365                 text: qsTr("Save and start")
0366                 height: parent.height
0367                 width: titleRectangle.width * 0.4
0368                 visible: inMenu === true
0369                 theme: "settingsButton"
0370                 onClicked: {
0371                     saveData();
0372                     startActivity();
0373                 }
0374             }
0375         }
0376     }
0377 }