Commit 65bf3aff authored by Karel Slaný's avatar Karel Slaný

Using a StackView for locking the application with PIN screen.

parent 5f6f2142
......@@ -47,7 +47,7 @@ ApplicationWindow {
// define all pages for stackview
property Component pageAboutApp: PageAboutApp {}
property Component pageAccountDetail: PageAccountDetail {}
property Component pageAccountList: PageAccountList {}
// property Component pageAccountList: PageAccountList {}
property Component pageMenuAccount: PageMenuAccount {}
property Component pageMenuDatovkaSettings: PageMenuDatovkaSettings {}
property Component pageMenuMessage: PageMenuMessage {}
......@@ -95,171 +95,193 @@ ApplicationWindow {
}
}
// page stack
Rectangle {
id: mainPage
StackView { // Page area.
id: mainStack
anchors.fill: parent
color: "transparent"
visible: true
StackView {
id: pageView
anchors.fill: parent
visible: true
initialItem: pageAccountList
}
}
Rectangle {
id: statusBar
visible: false
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
height: headerHeight * 0.5
color: datovkaPalette.alternateBase
BusyIndicator {
id: busyuIndicator
width: parent.height
height: parent.height
anchors.centerIn: parent
running: false
}
Text {
id: statusBarText
color: datovkaPalette.text
anchors.centerIn: parent
text: mainWindow.width + " x "+ mainWindow.height
Connections {
target: isds
onStatusBarTextChanged: {
statusBar.visible = isVisible
statusBarText.text = txt
busyuIndicator.running = busy
timerId.running = !busy
}
}
Connections {
target: files
onStatusBarTextChanged: {
statusBar.visible = true
statusBarText.text = txt
busyuIndicator.running = busy
timerId.running = !busy
initialItem: appArea
Component { /* Application workspace. */
id: appArea
Rectangle {
objectName: "appArea"
anchors.fill: parent
Rectangle { /* Application page stack. */
id: mainPage
anchors.fill: parent
color: "transparent"
visible: true
StackView {
id: pageView
anchors.fill: parent
visible: true
initialItem: PageAccountList {}
}
}
}
Connections {
target: settings
onStatusBarTextChanged: {
statusBar.visible = true
statusBarText.text = txt
busyuIndicator.running = busy
timerId.running = !busy
Rectangle {
id: statusBar
visible: false
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
height: headerHeight * 0.5
color: datovkaPalette.alternateBase
BusyIndicator {
id: busyuIndicator
width: parent.height
height: parent.height
anchors.centerIn: parent
running: false
}
Text {
id: statusBarText
color: datovkaPalette.text
anchors.centerIn: parent
text: mainWindow.width + " x "+ mainWindow.height
Connections {
target: isds
onStatusBarTextChanged: {
statusBar.visible = isVisible
statusBarText.text = txt
busyuIndicator.running = busy
timerId.running = !busy
}
}
Connections {
target: files
onStatusBarTextChanged: {
statusBar.visible = true
statusBarText.text = txt
busyuIndicator.running = busy
timerId.running = !busy
}
}
Connections {
target: settings
onStatusBarTextChanged: {
statusBar.visible = true
statusBarText.text = txt
busyuIndicator.running = busy
timerId.running = !busy
}
}
}
Timer {
id: timerId
interval: statusBarTimer;
running: false;
repeat: false
onTriggered: {
timerId.running = false
statusBar.visible = false
statusBarText.text = ""
}
}
}
}
}
Timer {
id: timerId
interval: statusBarTimer;
running: false;
repeat: false
onTriggered: {
timerId.running = false
statusBar.visible = false
statusBarText.text = ""
}
}
}
Rectangle {
id: pinScreen
visible: false
anchors.fill: parent
color: "transparent"
Column {
spacing: formItemVerticalSpacing
anchors.centerIn: parent
TextField {
id: pinCodeInput
//focus: true // Forcing focus here causes troubles on mobile devices.
echoMode: TextInput.Password
passwordMaskDelay: 500 // milliseconds
inputMethodHints: Qt.ImhDigitsOnly
placeholderText: qsTr("Enter PIN code")
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: TextInput.AlignHCenter
function verifyPin() {
settings.verifyPin(pinCodeInput.text.toString())
}
Component { /* Pin lock screen. */
id: lockScreen
Rectangle {
objectName: "lockScreen"
anchors.fill: parent
color: "transparent"
Column {
spacing: formItemVerticalSpacing
anchors.centerIn: parent
TextField {
id: pinCodeInput
//focus: true // Forcing focus here causes troubles on mobile devices.
echoMode: TextInput.Password
passwordMaskDelay: 500 // milliseconds
inputMethodHints: Qt.ImhDigitsOnly
placeholderText: qsTr("Enter PIN code")
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: TextInput.AlignHCenter
function verifyPin() {
settings.verifyPin(pinCodeInput.text.toString())
}
onEditingFinished: {
// This function is called repeatedly when switching
// windows. The condition should reduce PIN verification
// calls.
if (pinCodeInput.text.length > 0) {
verifyPin()
onEditingFinished: {
// This function is called repeatedly when switching
// windows. The condition should reduce PIN verification
// calls.
if (pinCodeInput.text.length > 0) {
verifyPin()
}
}
}
}
}
Text {
id: wrongPin
font.bold: true
visible: false
color: datovkaPalette.text
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Wrong PIN code!")
}
Row {
spacing: formButtonHorizontalSpacing
anchors.horizontalCenter: parent.horizontalCenter
Button {
text: qsTr("Enter")
onClicked: {
pinCodeInput.verifyPin()
Text {
id: wrongPin
font.bold: true
visible: false
color: datovkaPalette.text
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Wrong PIN code!")
}
Row {
spacing: formButtonHorizontalSpacing
anchors.horizontalCenter: parent.horizontalCenter
Button {
text: qsTr("Enter")
onClicked: {
pinCodeInput.verifyPin()
}
}
}
Rectangle {
id: blankField
width: formItemVerticalSpacing
height: headerHeight
color: "transparent"
anchors.horizontalCenter: parent.horizontalCenter
}
Image{
id: datovkaLogo
anchors.horizontalCenter: parent.horizontalCenter
width: imgHeight * 1.4
height: imgHeight * 1.4
source: "qrc:/datovka.png"
}
Text {
id: versionLabel
anchors.horizontalCenter: parent.horizontalCenter
color: datovkaPalette.text
text: qsTr("Version") + ": " + settings.appVersion()
}
}
}
Rectangle {
id: blankField
width: formItemVerticalSpacing
height: headerHeight
color: "transparent"
anchors.horizontalCenter: parent.horizontalCenter
}
Image{
id: datovkaLogo
anchors.horizontalCenter: parent.horizontalCenter
width: imgHeight * 1.4
height: imgHeight * 1.4
source: "qrc:/datovka.png"
}
Text {
id: versionLabel
anchors.horizontalCenter: parent.horizontalCenter
color: datovkaPalette.text
text: qsTr("Version") + ": " + settings.appVersion()
}
}
Connections {
target: settings
onSendPinReply: {
if (success) {
Qt.inputMethod.hide()
mainPage.visible = true
pinScreen.visible = false
Connections {
target: settings
onSendPinReply: {
if (success) {
Qt.inputMethod.hide()
if (mainStack.currentItem.objectName == "lockScreen") {
mainStack.pop(StackView.Immediate)
}
}
wrongPin.visible = !success
pinCodeInput.text = ""
}
}
wrongPin.visible = !success
pinCodeInput.text = ""
}
}
Connections {
target: locker
onLockApp: {
mainPage.visible = false
pinScreen.visible = true
if (mainStack.currentItem.objectName == "appArea") {
/* Lock application area. */
mainStack.push(lockScreen, StackView.Immediate)
}
}
}
}
Item {
id: backButton
/* Android back button. */
focus: true
Keys.onReleased: {
if (event.key === Qt.Key_Back) {
......@@ -274,6 +296,7 @@ ApplicationWindow {
}
}
}
Text {
id: dummyText
text: ""
......
......@@ -28,6 +28,11 @@ Component {
id: aboutApp
Item {
id: aboutLayout
/* These properties must be set by caller. */
property var pageView
property var statusBar
property int myWidht: aboutLayout.width - 2 * defaultMargin
Rectangle {
id: header
......
......@@ -30,6 +30,8 @@ Component {
id: acntDetailPage
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string acntName
property string userName
......
......@@ -38,6 +38,16 @@ Component {
id: pageAccountList
Item {
id: mainPage
/* These properties must be set by caller. */
//property var pageView
//property var statusBar
/*
* TODO -- Is there a way how to pas the pageView as a property?
* This pageView property is not passed because the page is created
* within the StackView.
*/
Component.onCompleted: {
if (accountList.count == 0) {
accountList.visible = false
......@@ -62,7 +72,10 @@ Component {
MouseArea {
anchors.fill: parent
onClicked: {
pageView.push(pageAboutApp, StackView.Immediate)
pageView.push(pageAboutApp, {
"pageView": pageView,
"statusBar": statusBar
}, StackView.Immediate)
}
}
}
......@@ -92,7 +105,10 @@ Component {
MouseArea {
anchors.fill: parent
onClicked: {
pageView.push(pageMenuDatovkaSettings, StackView.Immediate)
pageView.push(pageMenuDatovkaSettings, {
"pageView": pageView,
"statusBar": statusBar
}, StackView.Immediate)
}
}
}
......@@ -108,7 +124,12 @@ Component {
MouseArea {
anchors.fill: parent
onClicked: {
pageView.push(pageSettingsAccount, {"acntName": "", "userName": ""}, StackView.Immediate)
pageView.push(pageSettingsAccount, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": "",
"userName": ""
}, StackView.Immediate)
}
}
}
......@@ -200,7 +221,12 @@ Component {
anchors.fill: parent
onClicked: {
statusBar.visible = false
pageView.push(pageMenuAccount, {"acntName": rAcntName, "userName": rUserName}, StackView.Immediate)
pageView.push(pageMenuAccount, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": rAcntName,
"userName": rUserName
}, StackView.Immediate)
}
}
}
......@@ -282,7 +308,13 @@ Component {
anchors.fill: parent
onClicked: {
statusBar.visible = false
pageView.push(pageMessageList, {"acntName": rAcntName, "userName": rUserName, "msgType": MessageType.TYPE_RECEIVED}, StackView.Immediate)
pageView.push(pageMessageList, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": rAcntName,
"userName": rUserName,
"msgType": MessageType.TYPE_RECEIVED
}, StackView.Immediate)
}
}
Rectangle {
......@@ -344,7 +376,13 @@ Component {
anchors.fill: parent
onClicked: {
statusBar.visible = false
pageView.push(pageMessageList, {"acntName": rAcntName, "userName": rUserName, "msgType": MessageType.TYPE_SENT}, StackView.Immediate)
pageView.push(pageMessageList, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": rAcntName,
"userName": rUserName,
"msgType": MessageType.TYPE_SENT
}, StackView.Immediate)
}
}
Rectangle {
......
......@@ -34,6 +34,8 @@ Component {
id: mainLayout
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string acntName
property string userName
......@@ -170,9 +172,19 @@ Component {
anchors.fill: parent
onClicked: {
if (index == 0) {
pageView.replace(pageSettingsAccount, {"acntName": acntName, "userName": userName}, StackView.Immediate)
pageView.replace(pageSettingsAccount, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": acntName,
"userName": userName
}, StackView.Immediate)
} else if (index == 1) {
pageView.replace(pageAccountDetail, {"acntName": acntName, "userName": userName}, StackView.Immediate)
pageView.replace(pageAccountDetail, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": acntName,
"userName": userName
}, StackView.Immediate)
} else if (index == 2) {
files.deleteFileDb(userName)
} else if (index == 3) {
......
......@@ -32,6 +32,11 @@ Component {
id: menuDatovkamainSettings
Item {
id: mainLayout
/* These properties must be set by caller. */
property var pageView
property var statusBar
property int myWidht: mainLayout.width - 2 * defaultMargin
Rectangle {
id: header
......@@ -157,15 +162,32 @@ Component {
anchors.fill: parent
onClicked: {
if (index == 1) {
pageView.replace(pageSettingsAccount, {"acntName": "", "userName": ""}, StackView.Immediate)
pageView.replace(pageSettingsAccount, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": "",
"userName": ""
}, StackView.Immediate)
} else if (index == 2) {
pageView.replace(pageSettingsGeneral, StackView.Immediate)
pageView.replace(pageSettingsGeneral, {
"pageView": pageView,
"statusBar": statusBar
}, StackView.Immediate)
} else if (index == 3) {
pageView.replace(pageSettingsSync, StackView.Immediate)
pageView.replace(pageSettingsSync, {
"pageView": pageView,
"statusBar": statusBar
}, StackView.Immediate)
} else if (index == 4) {
pageView.replace(pageSettingsStorage, StackView.Immediate)
pageView.replace(pageSettingsStorage, {
"pageView": pageView,
"statusBar": statusBar
}, StackView.Immediate)
} else if (index == 5) {
pageView.replace(pageSettingsPin, StackView.Immediate)
pageView.replace(pageSettingsPin, {
"pageView": pageView,
"statusBar": statusBar
}, StackView.Immediate)
} else {
pageView.pop(StackView.Immediate)
}
......
......@@ -35,6 +35,8 @@ Component {
id: mainLayout
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string acntName
property string userName
property int msgType
......
......@@ -35,6 +35,8 @@ Component {
id: mainLayout
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string acntName
property string userName
property int msgType
......
......@@ -35,6 +35,8 @@ Component {
id: mainLayout
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string acntName
property string userName
property int msgType
......
......@@ -35,6 +35,8 @@ Component {
id: msgDetailPage
/* These properties must be set by caller. */
property var pageView
property var statusBar
property string acntName
property string userName
property int msgType
......@@ -126,7 +128,14 @@ Component {
MouseArea {
anchors.fill: parent
onClicked: {
pageView.push(pageMenuMessageDetail, {"acntName": acntName, "userName": userName, "msgType": msgType, "msgId": msgId}, StackView.Immediate)
pageView.push(pageMenuMessageDetail, {
"pageView": pageView,
"statusBar": statusBar,
"acntName": acntName,
"userName": userName,
"msgType": msgType,
"msgId": msgId
}, StackView.Immediate)
}
}
}
......@@ -170,7 +179,11 @@ Component {
target: files
onPushNewMessageDeatilPage: {
statusBar.visible = false
pageView.push(pageZfoMessageDetail, {"zfoId": zfoId}, StackView.Immediate)
pageView.push(pageZfoMessageDetail, {