Warning, /education/gcompris/src/activities/calendar/Calendar.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - Calendar.qml
0002  *
0003  * SPDX-FileCopyrightText: 2017 Amit Sagtani <asagtani06@gmail.com>
0004  *
0005  * Authors:
0006  *   Amit Sagtani <asagtani06@gmail.com>
0007  *
0008  *   SPDX-License-Identifier: GPL-3.0-or-later
0009  */
0010 
0011 import QtQuick 2.12
0012 import QtQuick.Controls 2.12
0013 import QtQuick.Layouts 1.12
0014 import Qt.labs.calendar 1.0
0015 import GCompris 1.0
0016 
0017 import "calendar.js" as Activity
0018 import "calendar_dataset.js" as Dataset
0019 import "../../core"
0020 
0021 ActivityBase {
0022     id: activity
0023     property var dataset: Dataset
0024     onStart: focus = true
0025     onStop: {}
0026 
0027     pageComponent: Image {
0028         id: background
0029         signal start
0030         signal stop
0031         fillMode: Image.PreserveAspectCrop
0032         source: "qrc:/gcompris/src/activities/fifteen/resource/background.svg"
0033         sourceSize.width: width
0034         sourceSize.height: height
0035 
0036         Component.onCompleted: {
0037             activity.start.connect(start)
0038             activity.stop.connect(stop)
0039         }
0040 
0041         // Add here the QML items you need to access in javascript
0042         QtObject {
0043             id: items
0044             property Item main: activity.main
0045             property alias background: background
0046             property GCSfx audioEffects: activity.audioEffects
0047             property int currentLevel: activity.currentLevel
0048             property alias bonus: bonus
0049             property alias errorRectangle: errorRectangle
0050             property alias calendar: calendar
0051             property alias okButton: okButton
0052             property alias questionItem: questionItem
0053             property alias score: score
0054             property alias answerChoices: answerChoices
0055             property alias okButtonParticles: okButtonParticles
0056             property bool horizontalLayout: background.width >= background.height * 1.5
0057             property alias daysOfTheWeekModel: daysOfTheWeekModel
0058             property bool buttonsBlocked: false
0059         }
0060 
0061         onStart: { Activity.start(items, dataset) }
0062         onStop: { Activity.stop() }
0063         Keys.onPressed: (answerChoices.visible) ? answerChoices.handleKeys(event) : handleKeys(event);
0064 
0065         Rectangle {
0066             id: calendarBox
0067             width: items.horizontalLayout ? (answerChoices.visible ? parent.width * 0.75 : parent.width * 0.80) :
0068                                             (answerChoices.visible ? parent.width * 0.65 : parent.width * 0.85)
0069             height: items.horizontalLayout ? parent.height * 0.68 : parent.height - bar.height - questionItemBackground.height - okButton.height * 1.5
0070             anchors.top: questionItem.bottom
0071             anchors.topMargin: 5
0072             anchors.rightMargin: answerChoices.visible ? 100 : undefined
0073             anchors.horizontalCenterOffset: answerChoices.visible ? 80 : 0
0074             anchors.horizontalCenter: parent.horizontalCenter
0075             color: "black"
0076             opacity: 0.3
0077         }
0078 
0079         Rectangle {
0080             id: navigationBar
0081             anchors.top: calendarBox.top
0082             anchors.horizontalCenter: calendarBox.horizontalCenter
0083             anchors.topMargin: calendarBox.height * 0.02
0084             height: calendarBox.height * 0.96 * 0.12
0085             width: calendar.width
0086             color: "#f2f2f2"
0087 
0088             BarButton {
0089                 id: previousMonth
0090                 height: parent.height * 0.8
0091                 width: previousMonth.height
0092                 sourceSize.height: previousMonth.height
0093                 sourceSize.width: previousMonth.width
0094                 anchors.verticalCenter: parent.verticalCenter
0095                 anchors.left: parent.left
0096                 anchors.leftMargin: parent.height * 0.1
0097                 source: "qrc:/gcompris/src/core/resource/scroll_down.svg"
0098                 rotation: 90
0099                 visible: calendar.navigationBarVisible && (calendar.currentDate.getFullYear() > calendar.minimumDate.getFullYear() || (calendar.currentDate.getFullYear() == calendar.minimumDate.getFullYear() && calendar.currentDate.getMonth() > calendar.minimumDate.getMonth()))
0100                 onClicked: {
0101                     if(!items.buttonsBlocked)
0102                         calendar.showPreviousMonth();
0103                 }
0104             }
0105             GCText {
0106                 id: dateText
0107                 visible: calendar.navigationBarVisible
0108                 text: grid.title
0109                 color: "#373737"
0110                 horizontalAlignment: Text.AlignHCenter
0111                 fontSizeMode: Text.Fit
0112                 anchors.verticalCenter: parent.verticalCenter
0113                 anchors.left: previousMonth.right
0114                 anchors.leftMargin: 2
0115                 anchors.right: nextMonth.left
0116                 anchors.rightMargin: 2
0117             }
0118             BarButton {
0119                 id: nextMonth
0120                 height: previousMonth.height
0121                 width: nextMonth.height
0122                 sourceSize.height: nextMonth.height
0123                 sourceSize.width: nextMonth.width
0124                 anchors.verticalCenter: parent.verticalCenter
0125                 anchors.right: parent.right
0126                 anchors.rightMargin: previousMonth.anchors.leftMargin
0127                 source: "qrc:/gcompris/src/core/resource/scroll_down.svg"
0128                 rotation: 270
0129                 visible: calendar.navigationBarVisible && (calendar.currentDate.getFullYear() < calendar.maximumDate.getFullYear() || (calendar.currentDate.getFullYear() == calendar.maximumDate.getFullYear() && calendar.currentDate.getMonth() < calendar.maximumDate.getMonth()));
0130                 onClicked: {
0131                     if(!items.buttonsBlocked)
0132                         calendar.showNextMonth();
0133                 }
0134             }
0135         }
0136 
0137         Rectangle {
0138             anchors.fill: calendar
0139             color: "#F2F2F2"
0140         }
0141         GridLayout {
0142             id: calendar
0143             width: calendarBox.width * 0.96
0144             height: calendarBox.height * 0.96 - navigationBar.height
0145             anchors.top: navigationBar.bottom
0146             anchors.horizontalCenter: calendarBox.horizontalCenter
0147             columns: 1
0148             rowSpacing: -5
0149             property bool navigationBarVisible
0150             property var minimumDate
0151             property var maximumDate
0152             property date currentDate: new Date()
0153             property int selectedDay
0154             onSelectedDayChanged: {
0155                 var date = new Date(calendar.currentDate);
0156                 date.setDate(selectedDay);
0157                 calendar.currentDate = date;
0158                 Activity.daySelected = selectedDay;
0159             }
0160 
0161             function showPreviousMonth() {
0162                 var date = new Date(calendar.currentDate);
0163                 date.setMonth(date.getMonth()-1);
0164                 if(minimumDate.getTime() <= date.getTime()) {
0165                        calendar.currentDate = date;
0166                 }
0167             }
0168             function showNextMonth() {
0169                 var date = new Date(calendar.currentDate);
0170                 date.setMonth(date.getMonth()+1);
0171                 if(date.getTime()<= maximumDate.getTime()) {
0172                        calendar.currentDate = date;
0173                 }
0174             }
0175             function selectPreviousDay() {
0176                 addDaysToCurrentDate(-1);
0177             }
0178             function selectNextDay() {
0179                 addDaysToCurrentDate(1);
0180             }
0181             function selectPreviousWeek() {
0182                 addDaysToCurrentDate(-7);
0183             }
0184             function selectNextWeek() {
0185                 addDaysToCurrentDate(7);
0186             }
0187             function addDaysToCurrentDate(daysToAdd) {
0188                 var date = new Date(calendar.currentDate);
0189                 date.setDate(date.getDate()+daysToAdd);
0190                 if(minimumDate.getTime() <= date.getTime() &&
0191                    date.getTime()<= maximumDate.getTime()) {
0192                     calendar.currentDate = date;
0193                     calendar.selectedDay = calendar.currentDate.getDate();
0194                 }
0195             }
0196             function selectFirstDayOfMonth() {
0197                 var date = new Date(calendar.currentDate);
0198                 date.setDate(1);
0199                 calendar.currentDate = date;
0200                 calendar.selectedDay = calendar.currentDate.getDate();
0201             }
0202             function selectLastDayOfMonth() {
0203                 // on some months, it goes to the next month...
0204                 if(calendar.currentDate.getDate() == 31) return;
0205                 var date = new Date(calendar.currentDate);
0206                 date.setMonth(calendar.currentDate.getMonth()+1);
0207                 date.setDate(0);
0208                 calendar.currentDate = date;
0209                 calendar.selectedDay = calendar.currentDate.getDate();
0210             }
0211 
0212             DayOfWeekRow {
0213                 id: dayOfWeekRow
0214                 locale: grid.locale
0215                 font.bold: false
0216                 spacing: 2
0217                 delegate: Rectangle {
0218                     color: "lightgray"
0219                     height: 50
0220                     width: 50
0221                     radius: 5
0222                     Label {
0223                         text: grid.locale.dayName((grid.locale.firstDayOfWeek+index) % 7, Locale.ShortFormat)
0224                         font.family: GCSingletonFontLoader.fontLoader.name
0225                         fontSizeMode: Text.Fit
0226                         minimumPixelSize: 1
0227                         font.pixelSize: items.horizontalLayout ? parent.height * 0.7 : parent.width * 0.2
0228                         color: "#373737"
0229                         anchors.centerIn: parent
0230                     }
0231                 }
0232                 Layout.fillWidth: true
0233             }
0234 
0235             MonthGrid {
0236                 id: grid
0237                 locale: Qt.locale(ApplicationInfo.localeShort)
0238                 month: parent.currentDate.getMonth()
0239                 year: parent.currentDate.getFullYear()
0240                 spacing: 0
0241 
0242                 readonly property int gridLineThickness: 1
0243 
0244                 Layout.fillWidth: true
0245                 Layout.fillHeight: true
0246 
0247                 delegate: MonthGridDelegate {
0248                     id: gridDelegate
0249                     visibleMonth: grid.month
0250                 }
0251             }
0252         }
0253 
0254         function handleKeys(event) {
0255             if(items.buttonsBlocked) {
0256                 return;
0257             }
0258             if(event.key === Qt.Key_Space && okButton.enabled) {
0259                 Activity.checkAnswer()
0260                 event.accepted = true
0261             }
0262             if(event.key === Qt.Key_Enter && okButton.enabled) {
0263                 Activity.checkAnswer()
0264                 event.accepted = true
0265             }
0266             if(event.key === Qt.Key_Return && okButton.enabled) {
0267                 Activity.checkAnswer()
0268                 event.accepted = true
0269             }
0270             if(event.key === Qt.Key_Home) {
0271                 calendar.selectFirstDayOfMonth();
0272                 event.accepted = true;
0273             }
0274             if(event.key === Qt.Key_End) {
0275                 calendar.selectLastDayOfMonth();
0276                 event.accepted = true;
0277             }
0278             if(event.key === Qt.Key_PageUp) {
0279                 calendar.showPreviousMonth();
0280                 event.accepted = true;
0281             }
0282             if(event.key === Qt.Key_PageDown) {
0283                 calendar.showNextMonth();
0284                 event.accepted = true;
0285             }
0286             if(event.key === Qt.Key_Left) {
0287                 calendar.selectPreviousDay();
0288                 event.accepted = true;
0289             }
0290             if(event.key === Qt.Key_Up) {
0291                 calendar.selectPreviousWeek();
0292                 event.accepted = true;
0293             }
0294             if(event.key === Qt.Key_Down) {
0295                 calendar.selectNextWeek();
0296                 event.accepted = true;
0297             }
0298             if(event.key === Qt.Key_Right) {
0299                 calendar.selectNextDay();
0300                 event.accepted = true;
0301             }
0302         }
0303 
0304         ListModel {
0305             id: daysOfTheWeekModel
0306             ListElement { text: qsTr("Sunday"); dayIndex: 0 }
0307             ListElement { text: qsTr("Monday"); dayIndex: 1 }
0308             ListElement { text: qsTr("Tuesday"); dayIndex: 2 }
0309             ListElement { text: qsTr("Wednesday"); dayIndex: 3 }
0310             ListElement { text: qsTr("Thursday"); dayIndex: 4 }
0311             ListElement { text: qsTr("Friday"); dayIndex: 5 }
0312             ListElement { text: qsTr("Saturday"); dayIndex: 6 }
0313         }
0314 
0315         // Creates a table consisting of days of weeks.
0316         GridView {
0317             id: answerChoices
0318             model: daysOfTheWeekModel
0319             anchors.top: calendarBox.top
0320             anchors.left: questionItem.left
0321             anchors.topMargin: 5
0322             interactive: false
0323 
0324             property bool keyNavigation: false
0325 
0326             width: calendarBox.x - anchors.rightMargin
0327             height: (calendar.height / 6.5) * 7
0328             cellWidth: calendar.width * 0.5
0329             cellHeight: calendar.height / 6.5
0330             keyNavigationWraps: true
0331             anchors.rightMargin: 10 * ApplicationInfo.ratio
0332             delegate: ChoiceTable {
0333                 width: answerChoices.width
0334                 height: answerChoices.height / 7
0335                 choices.text: text
0336                 anchors.rightMargin: 2
0337             }
0338             Keys.enabled: answerChoices.visible
0339             function handleKeys(event) {
0340                 if(items.buttonsBlocked) {
0341                     return;
0342                 }
0343                 if(event.key === Qt.Key_Down) {
0344                     keyNavigation = true
0345                     answerChoices.moveCurrentIndexDown()
0346                 }
0347                 if(event.key === Qt.Key_Up) {
0348                     keyNavigation = true
0349                     answerChoices.moveCurrentIndexUp()
0350                 }
0351                 if(event.key === Qt.Key_Enter) {
0352                     keyNavigation = true
0353                     Activity.dayOfWeekSelected = model.get(currentIndex).dayIndex
0354                     answerChoices.currentItem.select()
0355                 }
0356                 if(event.key === Qt.Key_Space) {
0357                     keyNavigation = true
0358                     Activity.dayOfWeekSelected = model.get(currentIndex).dayIndex
0359                     answerChoices.currentItem.select()
0360                 }
0361                 if(event.key === Qt.Key_Return) {
0362                     keyNavigation = true
0363                     Activity.dayOfWeekSelected = model.get(currentIndex).dayIndex
0364                     answerChoices.currentItem.select()
0365                 }
0366             }
0367 
0368             highlight: Rectangle {
0369                 width: parent.width * 1.2
0370                 height: parent.height / 7
0371                 anchors.horizontalCenter: parent.horizontalCenter
0372                 color: "#e99e33"
0373                 border.width: 2
0374                 border.color: "#f2f2f2"
0375                 radius: 5
0376                 visible: answerChoices.keyNavigation
0377                 y: answerChoices.currentItem.y
0378                 Behavior on y {
0379                     SpringAnimation {
0380                         spring: 3
0381                         damping: 0.2
0382                     }
0383                 }
0384             }
0385             highlightFollowsCurrentItem: false
0386             focus: answerChoices.visible
0387         }
0388 
0389         Rectangle {
0390             id: questionItemBackground
0391             color: "#373737"
0392             border.width: 2
0393             border.color: "#f2f2f2"
0394             radius: 10
0395             opacity: 0.85
0396             z: 10
0397             anchors {
0398                 horizontalCenter: parent.horizontalCenter
0399                 bottomMargin: 10
0400             }
0401             width: parent.width - 20
0402             height: parent.height * 0.1
0403         }
0404 
0405         // Displays the question.
0406         GCText {
0407             id: questionItem
0408             anchors.fill: questionItemBackground
0409             anchors.bottom: questionItemBackground.bottom
0410             fontSizeMode: Text.Fit
0411             wrapMode: Text.Wrap
0412             z: 10
0413             color: "white"
0414             verticalAlignment: Text.AlignVCenter
0415             horizontalAlignment: Text.AlignHCenter
0416         }
0417 
0418         ErrorRectangle {
0419             id: errorRectangle
0420             imageSize: okButton.width
0421             function releaseControls() {
0422                 items.buttonsBlocked = false;
0423             }
0424             states: [
0425                 State {
0426                     when: answerChoices.visible
0427                     PropertyChanges {
0428                         target: errorRectangle
0429                         x: answerChoices.x + answerChoices.currentItem.x
0430                         y: answerChoices.y + answerChoices.currentItem.y
0431                         width: answerChoices.currentItem.width
0432                         height: answerChoices.currentItem.height
0433                         radius: answerChoices.currentItem.radius
0434                         scale: answerChoices.currentItem.scale
0435                     }
0436                 },
0437                 State {
0438                     when: !answerChoices.visible
0439                     PropertyChanges {
0440                         target: errorRectangle
0441                         x: calendarBox.x
0442                         y: calendarBox.y
0443                         width: calendarBox.width
0444                         height: calendarBox.height
0445                         radius: calendarBox.radius
0446                         scale: calendarBox.scale
0447                     }
0448                 }
0449             ]
0450         }
0451 
0452         // Answer Submission button.
0453         BarButton {
0454             id: okButton
0455             source: "qrc:/gcompris/src/core/resource/bar_ok.svg"
0456             height: bar.height * 0.8
0457             width: okButton.height
0458             sourceSize.width: okButton.width
0459             sourceSize.height: okButton.height
0460             enabled: !items.buttonsBlocked
0461             z: 10
0462             anchors.top: calendarBox.bottom
0463             anchors.right: calendarBox.right
0464             anchors.margins: items.horizontalLayout ? 30 : 6
0465             ParticleSystemStarLoader {
0466                 id: okButtonParticles
0467                 clip: false
0468             }
0469             onClicked: {
0470                 Activity.checkAnswer()
0471             }
0472         }
0473 
0474         DialogHelp {
0475             id: dialogHelp
0476             onClose: home()
0477         }
0478 
0479         Bar {
0480             id: bar
0481             level: items.currentLevel + 1
0482             content: BarEnumContent { value: help | home | level }
0483             onHelpClicked: {
0484                 displayDialog(dialogHelp)
0485             }
0486             onPreviousLevelClicked: Activity.previousLevel()
0487             onNextLevelClicked: Activity.nextLevel()
0488             onHomeClicked: activity.home()
0489         }
0490 
0491         Bonus {
0492             id: bonus
0493             Component.onCompleted: win.connect(Activity.nextLevel)
0494         }
0495 
0496         Score {
0497             id: score
0498             height: okButton.height
0499             width: height
0500             anchors.top: calendarBox.bottom
0501             anchors.bottom: undefined
0502             anchors.left:  undefined
0503             anchors.right: answerChoices.visible ? calendarBox.right : okButton.left
0504             anchors.margins: items.horizontalLayout ? 30 : 8
0505             onStop: { Activity.nextSubLevel(); }
0506         }
0507     }
0508 }