qtgrpc/examples/grpc/chat/client/Main.qml

240 lines
7.3 KiB
QML

// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma ComponentBehavior: Bound
import QtQml
import QtQuick
import QtQuick.Controls.Material
import QtQuick.Layouts
//! [client-qml-1]
import QtGrpc
import QtGrpcChat
import QtGrpcChat.Proto
//! [client-qml-1]
ApplicationWindow {
id: root
readonly property color darkColor: Qt.darker(color, 1.4)
readonly property color lightColor: Qt.lighter(color, 1.4)
Material.theme: Material.Dark
Material.accent: Material.Purple
width: 460
height: 740
title: qsTr("QtGrpcChat-Client")
visible: true
function handleStatus(status) : void {
switch (status.code) {
case QtGrpc.StatusCode.Ok:
statusDisplay.text = status.message === "" ? qsTr("OK") : status.message
statusDisplay.color = "#4CAF50"
break
case QtGrpc.StatusCode.Unavailable:
statusDisplay.text = qsTr("Server Unavailable")
statusDisplay.color = "#F44336"
break
default:
statusDisplay.text = status.message
statusDisplay.color = "#F44336"
break
}
statusDisplay.restart()
}
//! [client-qml-2]
Connections {
target: ChatEngine
function onChatStreamFinished(status) {
root.handleStatus(status)
loginView.clear()
}
function onChatStateChanged() {
if (ChatEngine.chatState === Backend.ChatState.Connected && mainView.depth === 1)
mainView.push("ChatView.qml")
else if (ChatEngine.chatState === Backend.ChatState.Disconnected && mainView.depth > 1)
mainView.pop()
}
function onRegisterFinished(status) {
root.handleStatus(status)
}
function onChatError(message) {
statusDisplay.text = message
statusDisplay.color = "yellow"
statusDisplay.restart()
}
}
//! [client-qml-2]
// Navigation header containing buttons and information text
header: Rectangle {
height: 40
color: Qt.darker(root.darkColor, 1.2)
RowLayout {
anchors.fill: parent
anchors.leftMargin: 15
anchors.rightMargin: 15
component NavigationButton: Button {
Material.roundedScale: Material.SmallScale
Layout.fillHeight: true
Layout.preferredWidth: 120
visible: mainView.depth > 1
enabled: mainView.depth > 1
clip: true
}
NavigationButton {
Layout.alignment: Qt.AlignLeft
text: "Logout"
onPressed: {
if (userStatusButton.checked)
userStatusButton.animateClick()
ChatEngine.logout()
}
}
Text {
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: Material.foreground
text: mainView.currentItem.viewInfoText
font.pointSize: 16
clip: true
}
NavigationButton {
id: userStatusButton
Layout.alignment: Qt.AlignRight
checkable: true
text: userStatusView.count + " ONLINE"
onPressed: userStatus.height = checked ? 0 : userStatusView.contentHeight
}
}
}
// Visualize online users
Item {
id: userStatus
width: parent.width * 0.75
anchors.horizontalCenter: parent.horizontalCenter
height: 0
z: 1
Behavior on height {
NumberAnimation { duration: 250 }
}
ListView {
id: userStatusView
anchors.fill: parent
model: ChatEngine.userStatusModel
interactive: false
clip: true
delegate: Rectangle {
id: userStatusDelegate
required property int index
required property string username
required property int status
height: 32
width: userStatusView.width
color: root.lightColor
topLeftRadius: index === 0 ? 8 : 0
topRightRadius: index === 0 ? 8 : 0
bottomLeftRadius: index === userStatusView.count - 1 ? 8 : 0
bottomRightRadius: index === userStatusView.count - 1 ? 8 : 0
Rectangle {
height: 2
width: parent.width
anchors.top: parent.top
color: Qt.lighter(parent.color, 1.4)
visible: userStatusDelegate.index > 0
}
Text {
text: parent.username
font.pointSize: 14
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: Material.foreground
}
Rectangle {
anchors.right: parent.right
anchors.margins: 25
anchors.verticalCenter: parent.verticalCenter
height: parent.height - 16
width: height
radius: height / 2
color: {
switch (parent.status) {
case UserStatus.Type.LOGIN:
return "#4CAF50"
case UserStatus.Type.ACTIVE:
return "#4CAF50"
case UserStatus.Type.INACTIVE:
return "#FF9800"
case UserStatus.Type.LOGOUT:
return "#F44336"
}
}
}
}
}
}
StatusDisplay {
id: statusDisplay
anchors {
top: parent.top
left: parent.left
right: parent.right
leftMargin: 75
rightMargin: 75
topMargin: root.height / 4
}
}
BusyIndicator {
id: busyIndicator
z: 2
width: parent.width / 3
height: width
anchors.centerIn: parent
running: ChatEngine.chatState === Backend.ChatState.Connecting
|| ChatEngine.chatState === Backend.ChatState.Disconnecting
}
StackView {
id: mainView
anchors.fill: parent
initialItem: Item {
readonly property string viewInfoText: "Login"
LoginView {
id: loginView
anchors {
fill: parent
leftMargin: 50
rightMargin: 50
topMargin: 100
bottomMargin: 100
}
color: root.darkColor
border.color: root.lightColor
}
}
}
}