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

0001 /* GCompris - Bar.qml
0002  *
0003  * SPDX-FileCopyrightText: 2014-2016 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  * A QML component for GCompris' navigation bar.
0016  * @ingroup components
0017  *
0018  * The Bar is visible in all activities and the main menu screen. It can be
0019  * hidden by clicking on the 'toggle' region.
0020  *
0021  * It can consist of a couple of child-elements, mostly buttons, defined
0022  * in the BarEnumContent container. An activity can define which elements its bar should
0023  * present using the content property. In most cases it contains at least
0024  * BarEnumContent.help, BarEnumContent.home and BarEnumContent.level.
0025  *
0026  * Cf. the BarEnumContent container for a full list of available Bar elements.
0027  *
0028  * Cf. the Bar object used in Template.qml as an example of how a minimal
0029  * Bar implementation should look like.
0030  *
0031  * @sa BarButton, BarEnumContent
0032  * @inherit QtQuick.Item
0033  */
0034 Item {
0035     id: bar
0036 
0037     /**
0038       * type: real
0039       * Minimum size for BarZoom
0040       */
0041     readonly property real minWidth: (parent.width - 20 -
0042                                       10 * ApplicationInfo.ratio) / (totalWidth + textLength)
0043 
0044     /**
0045       * type: real
0046       * Maximum size for barZoom
0047       */
0048     readonly property real maxWidth: 1.2 * ApplicationInfo.ratio
0049 
0050     /**
0051       * type: real
0052       * Length of level String
0053       */
0054     property real textLength
0055 
0056     /**
0057       * type: real
0058       * The maximum size allowed for the bar
0059       */
0060     readonly property real maxBarWidth: (totalWidth+textLength) * maxWidth +
0061                                (numberOfButtons - 1) * 5 + 10 * ApplicationInfo.ratio
0062     /**
0063       * type: real
0064       * Font size for text level
0065       */
0066     readonly property real textSize: (parent.width<maxBarWidth) ? 32 * minWidth / maxWidth : 32
0067 
0068     /**
0069      * type:real
0070      * Zoom factor of the bar and its children.
0071      */
0072     property real barZoom: (parent.width<maxBarWidth) ? minWidth : maxWidth
0073 
0074     /**
0075       * type: real
0076       * Keeps track of the number of buttons that are displayed
0077       */
0078     property int numberOfButtons: 0
0079 
0080     //totalWidth has 66 as initial value because it will always have the "hideBar" button
0081     /**
0082       * type: real
0083       * Width of all the buttons
0084       */
0085     property real totalWidth: 66
0086 
0087     readonly property int fullButton: 66
0088     readonly property int halfButton: 30
0089 
0090     readonly property int fullButtonScaled: fullButton * barZoom
0091     readonly property int halfButtonScaled: halfButton * barZoom
0092 
0093     /**
0094      * type:BarEnumContent
0095      * Defines the content/children of the bar.
0096      *
0097      * @sa BarEnumContent
0098      */
0099     property BarEnumContent content
0100 
0101     /**
0102      * type:int
0103      * Current level to be shown in the level child.
0104      *
0105      * Set this to the current level of your activity.
0106      */
0107     property int level: 0
0108 
0109     /**
0110      * Emitted when the about button was clicked.
0111      */
0112     signal aboutClicked
0113 
0114     /**
0115      * Emitted when the help button was clicked.
0116      *
0117      * Show help dialog upon this signal.
0118      */
0119     signal helpClicked
0120 
0121     /**
0122      * Emitted when the config button was clicked.
0123      *
0124      * Should be implemented if an activity provides per-activity
0125      * configuration.
0126      */
0127     signal configClicked
0128 
0129     /**
0130      * Emitted when the next level button was clicked.
0131      *
0132      * Switch to the next level upon this signal.
0133      */
0134     signal nextLevelClicked
0135 
0136     /**
0137      * Emitted when the previous level button was clicked.
0138      *
0139      * Switch to the previous level upon this signal.
0140      */
0141     signal previousLevelClicked
0142 
0143     /**
0144      * Emitted when the repeat button was clicked.
0145      *
0146      * Implement if your activity needs to repeat audio voices.
0147      */
0148     signal repeatClicked
0149 
0150     /**
0151      * Emitted when the reload button was clicked.
0152      *
0153      * Implement if you want to support repeating a level from the beginning.
0154      */
0155     signal reloadClicked
0156 
0157     /**
0158      * Emitted when the hint button was clicked.
0159      *
0160      * Implement if your activity needs a hint to help children.
0161      */
0162     signal hintClicked
0163 
0164     /**
0165      * Emitted when the activity configuration button was clicked.
0166      *
0167      * Only in menu to change the activity configuration.
0168      */
0169     signal activityConfigClicked
0170 
0171     /**
0172      * Emitted when the home button was clicked.
0173      *
0174      * Should always be connected to the ActivityBase.home signal and thus
0175      * return to the home/main menu.
0176      */
0177     signal homeClicked
0178 
0179     /// @cond INTERNAL_DOCS
0180 
0181     /*
0182      * A list of all our possible buttons.
0183      *
0184      * bid = Button ID. And references the Component object of the button
0185      * This way we can have any visual object in the bar.
0186      */
0187     property var buttonList: [
0188         {
0189             'bid': exit,
0190             'contentId': content.exit,
0191             'allowed': !ApplicationSettings.isKioskMode
0192         },
0193         {
0194             'bid': about,
0195             'contentId': content.about,
0196             'allowed': true
0197         },
0198         {
0199             'bid': help,
0200             'contentId': content.help,
0201             'allowed': true
0202         },
0203         {
0204             'bid': home,
0205             'contentId': content.home,
0206             'allowed': true
0207         },
0208         {
0209             'bid': previous,
0210             'contentId': content.level,
0211             'allowed': true
0212         },
0213         {
0214             'bid': levelText,
0215             'contentId': content.level,
0216             'allowed': true
0217         },
0218         {
0219             'bid': next,
0220             'contentId': content.level,
0221             'allowed': true
0222         },
0223         {
0224             'bid': repeat,
0225             'contentId': content.repeat,
0226             'allowed': true
0227         },
0228         {
0229             'bid': reload,
0230             'contentId': content.reload,
0231             'allowed': true
0232         },
0233         {
0234             'bid': config,
0235             'contentId': content.config,
0236             'allowed': !ApplicationSettings.isKioskMode
0237         },
0238         {
0239             'bid': hint,
0240             'contentId': content.hint,
0241             'allowed': true
0242         },
0243         {
0244             'bid': activityConfigImage,
0245             'contentId': content.activityConfig,
0246             'allowed': !ApplicationSettings.isKioskMode
0247         },
0248         {
0249             'bid': downloadImage,
0250             'contentId': content.download,
0251             'allowed': true
0252         }
0253     ]
0254 
0255     /* internal? */
0256     property var buttonModel
0257 
0258     x: 0
0259     anchors.bottom: parent.bottom
0260     width: openBar.width
0261     height: openBar.height
0262     z: 1000
0263 
0264     function show(newContent) {
0265         content.value = newContent
0266     }
0267 
0268     Connections {
0269         target: DownloadManager
0270 
0271         onDownloadStarted: content.value |= content.download
0272         onAllDownloadsFinished: content.value &= ~content.download
0273         onError: content.value &= ~content.download
0274     }
0275 
0276     Image {
0277         id: openBar
0278         source: "qrc:/gcompris/src/core/resource/bar_open.svg";
0279         anchors.bottom: parent.bottom
0280         anchors.left: parent.left
0281         sourceSize.width: fullButtonScaled
0282         MouseArea {
0283             anchors.fill: parent
0284 
0285             onClicked: {
0286                 ApplicationSettings.isBarHidden = !ApplicationSettings.isBarHidden;
0287             }
0288         }
0289     }
0290 
0291     function computeWidth(bid) {
0292         if (bid===levelText) {
0293             return 0
0294         }
0295         else if (bid===previous||bid===next)
0296             return halfButton
0297         else return fullButton
0298     }
0299 
0300     function updateContent() {
0301         var newButtonModel = new Array()
0302         numberOfButtons = 0
0303         totalWidth = 66;
0304         for(var def in buttonList) {
0305             if((content.value & buttonList[def].contentId) &&
0306                buttonList[def].allowed) {
0307                 newButtonModel.push(buttonList[def])
0308                 totalWidth += computeWidth(buttonList[def].bid)
0309                 numberOfButtons++
0310             }
0311         }
0312         buttonModel = newButtonModel
0313     }
0314 
0315     Connections {
0316         target: content
0317         onValueChanged: updateContent()
0318     }
0319 
0320     onContentChanged: {
0321         updateContent()
0322     }
0323 
0324     Row {
0325         id: barRow
0326         spacing: 5
0327         anchors.bottom: parent.bottom
0328         anchors.bottomMargin: 10
0329         anchors.left: openBar.right
0330         anchors.leftMargin: 10 * ApplicationInfo.ratio
0331         property bool isHidden: false
0332         Repeater {
0333             model: buttonModel
0334             Loader {
0335                 sourceComponent: modelData.bid
0336             }
0337         }
0338 
0339         state: ApplicationSettings.isBarHidden ? "hidden" : "shown"
0340 
0341         states: [
0342             State {
0343                 name: "shown"
0344 
0345                 AnchorChanges {
0346                     target: barRow
0347                     anchors.top: undefined
0348                     anchors.bottom: parent.bottom
0349                 }
0350             },
0351             State {
0352                 name: "hidden"
0353 
0354                 AnchorChanges {
0355                     target: barRow
0356                     anchors.bottom: undefined
0357                     anchors.top: parent.bottom
0358                 }
0359             }
0360         ]
0361 
0362         transitions: Transition {
0363             SequentialAnimation {
0364                 ScriptAction { script: if(barRow.state === "shown") barRow.isHidden = false }
0365                 AnchorAnimation { duration: 800; easing.type: Easing.OutBounce }
0366                 ScriptAction { script: if(barRow.state === "hidden") barRow.isHidden = true }
0367             }
0368         }
0369         populate: Transition {
0370             NumberAnimation {
0371                 properties: "x,y"; from: 200;
0372                 duration: 1500; easing.type: Easing.OutBounce
0373             }
0374         }
0375         add: Transition {
0376             NumberAnimation {
0377                 properties: "x,y"; from: 200;
0378                 duration: 1500; easing.type: Easing.OutBounce
0379             }
0380         }
0381         move: Transition {
0382             NumberAnimation {
0383                 properties: "x,y"
0384                 duration: 1500; easing.type: Easing.OutBounce
0385             }
0386         }
0387     }
0388 
0389     // All the possible bar buttons are defined here
0390     // ---------------------------------------------
0391     Component {
0392         id: exit
0393         BarButton {
0394             source: "qrc:/gcompris/src/core/resource/bar_exit.svg";
0395             sourceSize.width: fullButtonScaled
0396             visible: barRow.isHidden === false
0397             onClicked: Core.quit(bar.parent);
0398         }
0399     }
0400     Component {
0401         id: about
0402         BarButton {
0403             source: "qrc:/gcompris/src/core/resource/bar_about.svg";
0404             sourceSize.width: fullButtonScaled
0405             visible: barRow.isHidden === false
0406             onClicked: bar.aboutClicked()
0407         }
0408     }
0409     Component {
0410         id: help
0411         BarButton {
0412             source: "qrc:/gcompris/src/core/resource/bar_help.svg";
0413             sourceSize.width: fullButtonScaled
0414             visible: barRow.isHidden === false
0415             onClicked: bar.helpClicked()
0416         }
0417     }
0418     Component {
0419         id: previous
0420         BarButton {
0421             source: "qrc:/gcompris/src/core/resource/bar_previous.svg";
0422             sourceSize.width: halfButtonScaled
0423             visible: barRow.isHidden === false
0424             onClicked: {
0425                 if(typeof bonus !== "undefined")
0426                     bonus.haltBonus();
0427                 bar.previousLevelClicked();
0428             }
0429         }
0430     }
0431     Component {
0432         id: levelText
0433         GCText {
0434             id: levelTextId
0435             text: "" + level
0436             fontSize: textSize
0437             font.weight: Font.DemiBold
0438             style: Text.Outline
0439             styleColor: "black"
0440             color: "white"
0441             visible: content.level & content.value && barRow.isHidden === false
0442             onTextChanged: {
0443                 if (level>9)
0444                     textLength = fullButtonScaled
0445                 else textLength = halfButtonScaled
0446             }
0447         }
0448     }
0449     Component {
0450         id: next
0451         BarButton {
0452             source: "qrc:/gcompris/src/core/resource/bar_next.svg";
0453             sourceSize.width: halfButtonScaled
0454             visible: barRow.isHidden === false
0455             onClicked: {
0456                 if(typeof bonus !== "undefined")
0457                     bonus.haltBonus();
0458                 bar.nextLevelClicked();
0459             }
0460         }
0461     }
0462     Component {
0463         id: repeat
0464         BarButton {
0465             source: "qrc:/gcompris/src/core/resource/bar_repeat.svg";
0466             sourceSize.width: fullButtonScaled
0467             visible: barRow.isHidden === false
0468             onClicked: bar.repeatClicked()
0469         }
0470     }
0471     Component {
0472         id: hint
0473         BarButton {
0474             source: "qrc:/gcompris/src/core/resource/bar_hint.svg";
0475             sourceSize.width: fullButtonScaled
0476             visible: barRow.isHidden === false
0477             onClicked: bar.hintClicked()
0478         }
0479     }
0480     Component {
0481         id: activityConfigImage
0482         BarButton {
0483             source: "qrc:/gcompris/src/core/resource/bar_activity_config.svg";
0484             sourceSize.width: fullButtonScaled
0485             visible: barRow.isHidden === false
0486             onClicked: bar.activityConfigClicked()
0487         }
0488     }
0489     Component {
0490         id: reload
0491         BarButton {
0492             source: "qrc:/gcompris/src/core/resource/bar_reload.svg";
0493             sourceSize.width: fullButtonScaled
0494             visible: barRow.isHidden === false
0495             onClicked: bar.reloadClicked()
0496         }
0497     }
0498     Component {
0499         id: config
0500         BarButton {
0501             source: "qrc:/gcompris/src/core/resource/bar_config.svg";
0502             sourceSize.width: fullButtonScaled
0503             visible: barRow.isHidden === false
0504             onClicked: bar.configClicked()
0505         }
0506     }
0507     Component {
0508         id: home
0509         BarButton {
0510             // Replace home icon with exit icon in case activity is started as standalone
0511             source: ActivityInfoTree.startingActivity != "" ?
0512                 "qrc:/gcompris/src/core/resource/bar_exit.svg" :
0513                 "qrc:/gcompris/src/core/resource/bar_home.svg";
0514             sourceSize.width: fullButtonScaled
0515             visible: barRow.isHidden === false
0516             onClicked: {
0517                 bar.homeClicked();
0518             }
0519         }
0520     }
0521     Component {
0522         id: downloadImage
0523         AnimatedImage {
0524             source: "qrc:/gcompris/src/core/resource/loader.gif"
0525             visible: barRow.isHidden === false
0526             MouseArea {
0527                 id: mouseArea
0528                 anchors.fill: parent
0529                 hoverEnabled: true
0530                 onClicked: {
0531                     var downloadDialog = Core.showDownloadDialog(activity, {});
0532                 }
0533             }
0534         }
0535     }
0536 
0537     /// @endcond
0538 }
0539