Warning, /education/gcompris/src/core/GCDialog.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - GCDialog.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
0013 /**
0014 * A QML component for GCompris dialogs.
0015 * @ingroup components
0016 *
0017 * Contains the following basic layout elements: Title (message), a GCompris
0018 * cancel button (GCButtonCancel) at the top right and two optional buttons.
0019 *
0020 * Can be conveniently instantiated dynamically in conjunction with
0021 * showMessageDialog from core.js.
0022 *
0023 * GCDialog should now be used wherever you'd use a QtQuick dialog. It has
0024 * been decided to implement dialogs ourselves in GCompris because of
0025 * missing translations of labels of Qt's standard buttons for some language
0026 * supported by GCompris, as well as integration problems on some OSes
0027 * (Sailfish OS).
0028 *
0029 * @inherit QtQuick.Item
0030 * @sa showMessageDialog
0031 */
0032 Rectangle {
0033 id: gcdialog
0034 color: "#B2808080"
0035 property int baseMargins: 5 * ApplicationInfo.ratio
0036
0037 /**
0038 * type:string
0039 * Heading instruction text.
0040 */
0041 property alias message: instructionTxt.textIn
0042
0043 /**
0044 * type:string
0045 * Label of the first button.
0046 */
0047 property alias button1Text: button1.text
0048
0049 /**
0050 * type:string
0051 * Label of the second button.
0052 */
0053 property alias button2Text: button2.text
0054
0055 /**
0056 * type:bool
0057 * Check is the dialog can be destroyed
0058 */
0059 property bool isDestructible: true
0060
0061 /**
0062 * type:bool
0063 * Set to true after clicking on one of the options
0064 */
0065 property bool alreadyClicked: false
0066
0067 /**
0068 * Emitted when the dialog should be started.
0069 *
0070 * Triggers fading in.
0071 */
0072 signal start
0073
0074 /**
0075 * Emitted when the dialog should be stopped.
0076 *
0077 * Triggers fading out.
0078 */
0079 signal stop
0080
0081 /**
0082 * Emitted when the dialog has stopped.
0083 */
0084 signal close
0085
0086 /**
0087 * Emitted when the first button has been clicked.
0088 */
0089 signal button1Hit
0090
0091 /**
0092 * Emitted when the second button has been clicked.
0093 */
0094 signal button2Hit
0095
0096 /**
0097 * type:Component
0098 * Content component which holds the optional content
0099 * after instructionText
0100 */
0101 property Component content
0102
0103 focus: true
0104 opacity: 0
0105
0106 onVisibleChanged: {
0107 if(visible) {
0108 gcdialog.forceActiveFocus();
0109 parent.Keys.enabled = false;
0110 }
0111 }
0112
0113 anchors {
0114 fill: parent
0115 }
0116
0117 onStart: {
0118 opacity = 1;
0119 gcdialog.forceActiveFocus();
0120 parent.Keys.enabled = false;
0121 alreadyClicked = false;
0122 }
0123 onStop: {
0124 opacity = 0;
0125 parent.Keys.enabled = true;
0126 parent.forceActiveFocus();
0127 }
0128 onClose: {
0129 if(isDestructible)
0130 destroy();
0131 }
0132
0133 Behavior on opacity { NumberAnimation { duration: 200 } }
0134 onOpacityChanged: opacity === 0 ? close() : null
0135
0136 z: 1500
0137
0138 MultiPointTouchArea {
0139 // Just to catch mouse events
0140 anchors.fill: parent
0141 }
0142
0143 /* Message */
0144 Item {
0145 id: instruction
0146 anchors {
0147 horizontalCenter: parent.horizontalCenter
0148 top: parent.top
0149 topMargin: buttonCancel.height + 2 * gcdialog.baseMargins
0150 bottom: parent.bottom
0151 bottomMargin: gcdialog.baseMargins
0152 }
0153 width: parent.width * 0.8
0154
0155 Rectangle {
0156 id: instructionTxtBg
0157 anchors.top: instruction.top
0158 width: parent.width
0159 height: instruction.height - button1.height * 3 - gcdialog.baseMargins * 3
0160 radius: gcdialog.baseMargins
0161 border.width: 2 * ApplicationInfo.ratio
0162 border.color: "white"
0163 color: "#EEEEEEEE"
0164
0165 Flickable {
0166 id: instructionFlick
0167 flickDeceleration: 1500
0168 anchors.fill: parent
0169 anchors.margins: gcdialog.baseMargins
0170 flickableDirection: Flickable.VerticalFlick
0171 clip: true
0172 contentHeight: instructionTxt.height + extraLoader.height + 15 * ApplicationInfo.ratio
0173
0174 GCText {
0175 id: instructionTxt
0176 fontSize: regularSize
0177 color: "#191919"
0178 anchors.horizontalCenter: parent.horizontalCenter
0179 // need to remove the anchors (left and right) else sometimes text is hidden on the side
0180 width: instructionFlick.width
0181 wrapMode: TextEdit.WordWrap
0182 textFormat: TextEdit.RichText
0183 text: style + "<body>" + textIn + "</body>"
0184 property string textIn
0185 property string style: "<HEAD><STYLE type='text/css'>A {color: #191919;}</STYLE></HEAD>"
0186 }
0187 Loader {
0188 id: extraLoader
0189 anchors.top: instructionTxt.bottom
0190 anchors.topMargin: gcdialog.baseMargins
0191 active: gcdialog.content != null
0192 sourceComponent: gcdialog.content
0193 width: instructionFlick.width
0194 }
0195 }
0196 // The scroll buttons
0197 GCButtonScroll {
0198 id: scrollInstructions
0199 opacity: 0.7
0200 visible: instructionFlick.contentHeight > instructionFlick.height
0201 anchors.right: parent.right
0202 anchors.rightMargin: 5 * ApplicationInfo.ratio
0203 anchors.bottom: parent.bottom
0204 anchors.bottomMargin: 5 * ApplicationInfo.ratio
0205 onUp: instructionFlick.flick(0, 1000)
0206 onDown: instructionFlick.flick(0, -1000)
0207 upVisible: instructionFlick.atYBeginning ? false : true
0208 downVisible: instructionFlick.atYEnd ? false : true
0209 }
0210 }
0211
0212 Rectangle {
0213 id: buttonSelector
0214 width: gcdialog.width
0215 height: button1.height + gcdialog.baseMargins * 2
0216 color: "#803ACAFF"
0217 visible: false
0218 }
0219
0220 GCButton {
0221 id: button1
0222 width: parent.width
0223 height: (visible ? 60 : 30) * ApplicationInfo.ratio
0224 anchors {
0225 horizontalCenter: parent.horizontalCenter
0226 top: instructionTxtBg.bottom
0227 topMargin: 10
0228 }
0229 theme: "highContrast"
0230 visible: text != ""
0231 property bool selected: false;
0232 enabled: !gcdialog.alreadyClicked
0233 onClicked: {
0234 gcdialog.alreadyClicked = true;
0235 gcdialog.button1Hit()
0236 gcdialog.stop()
0237 }
0238 }
0239
0240 GCButton {
0241 id: button2
0242 width: parent.width
0243 height: (visible ? 60 : 30) * ApplicationInfo.ratio
0244 anchors {
0245 horizontalCenter: parent.horizontalCenter
0246 top: button1.bottom
0247 topMargin: 10
0248 }
0249 theme: "highContrast"
0250 visible: text != ""
0251 property bool selected: false;
0252 enabled: !gcdialog.alreadyClicked
0253 onClicked: {
0254 gcdialog.alreadyClicked = true;
0255 gcdialog.button2Hit()
0256 gcdialog.stop()
0257 }
0258 }
0259
0260 states: [
0261 State {
0262 name: "button1Selected"
0263 when: button1.selected
0264 PropertyChanges {
0265 target: buttonSelector
0266 anchors.centerIn: button1
0267 visible: true
0268 }
0269 },
0270 State {
0271 name: "button2Selected"
0272 when: button2.selected
0273 PropertyChanges {
0274 target: buttonSelector
0275 anchors.centerIn: button2
0276 visible: true
0277 }
0278 }
0279 ]
0280 }
0281
0282 Keys.onEscapePressed: {
0283 buttonCancel.close();
0284 }
0285
0286 Keys.onTabPressed: {
0287 return;
0288 }
0289
0290 Keys.onPressed: {
0291 if(event.key === Qt.Key_Up || event.key === Qt.Key_Left) {
0292 if(button2.visible && !button1.selected && !button2.selected) {
0293 button2.selected = true;
0294 } else if(button2.visible) {
0295 button2.selected = !button2.selected;
0296 button1.selected = !button1.selected;
0297 } else if(button1.visible) {
0298 button1.selected = true;
0299 }
0300 }
0301 if(event.key === Qt.Key_Down || event.key === Qt.Key_Right) {
0302 if(button1.visible && !button1.selected && !button2.selected) {
0303 button1.selected = true;
0304 } else if(button2.visible) {
0305 button1.selected = !button1.selected;
0306 button2.selected = !button2.selected;
0307 } else if(button1.visible) {
0308 button1.selected = true;
0309 }
0310 }
0311 if(event.key === Qt.Key_Enter || event.key === Qt.Key_Return || event.key === Qt.Key_Space) {
0312 event.accepted = true;
0313 if(button1.selected) {
0314 button1.clicked();
0315 } else if(button2.selected) {
0316 button2.clicked();
0317 } else {
0318 buttonCancel.close();
0319 }
0320 }
0321 }
0322
0323 Keys.onReleased: {
0324 if(event.key === Qt.Key_Back) {
0325 buttonCancel.close();
0326 event.accepted = true;
0327 }
0328 }
0329
0330 // The cancel button
0331 GCButtonCancel {
0332 id: buttonCancel
0333 anchors.margins: 5 * ApplicationInfo.ratio
0334 onClose: {
0335 if(button2.visible)
0336 button2.clicked();
0337 else if(button1.visible)
0338 button1.clicked();
0339 else
0340 parent.stop();
0341 }
0342 }
0343 }