diff --git a/kaidan_qml.qrc b/kaidan_qml.qrc
index 48c8f96..664fac1 100644
--- a/kaidan_qml.qrc
+++ b/kaidan_qml.qrc
@@ -1,36 +1,38 @@
src/qml/main.qml
src/qml/RosterPage.qml
src/qml/LoginPage.qml
src/qml/ChatPage.qml
src/qml/AboutDialog.qml
src/qml/GlobalDrawer.qml
src/qml/EmptyChatPage.qml
+ src/qml/QrScannerPage.qml
src/qml/elements/SubRequestAcceptSheet.qml
src/qml/elements/RosterAddContactSheet.qml
src/qml/elements/RosterRemoveContactSheet.qml
+
src/qml/elements/RosterListItem.qml
src/qml/elements/MessageCounter.qml
src/qml/elements/ChatMessage.qml
src/qml/elements/ChatMessageImage.qml
src/qml/elements/RoundImage.qml
src/qml/elements/IconButton.qml
src/qml/elements/FileChooser.qml
src/qml/elements/FileChooserDesktop.qml
src/qml/elements/FileChooserMobile.qml
src/qml/elements/SendMediaSheet.qml
src/qml/elements/MediaPreviewImage.qml
src/qml/elements/MediaPreviewOther.qml
src/qml/elements/EmojiPicker.qml
src/qml/elements/TextAvatar.qml
src/qml/settings/SettingsItem.qml
src/qml/settings/SettingsPage.qml
src/qml/settings/SettingsSheet.qml
src/qml/settings/ChangePassword.qml
misc/qtquickcontrols2.conf
diff --git a/src/qml/LoginPage.qml b/src/qml/LoginPage.qml
index ec5b973..e545cdb 100644
--- a/src/qml/LoginPage.qml
+++ b/src/qml/LoginPage.qml
@@ -1,164 +1,172 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kaidan. If not, see .
*/
import QtQuick 2.7
import QtQuick.Controls 2.0 as Controls
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.5 as Kirigami
import im.kaidan.kaidan 1.0
Kirigami.Page {
title: qsTr("Log in")
+ actions.contextualActions: [
+ Kirigami.Action {
+ text: qsTr("Log in using a QR-Code")
+ icon.name: "view-barcode"
+ onTriggered: pageStack.layers.push(qrScannerPage)
+ }
+ ]
+
ColumnLayout {
anchors.fill: parent
Kirigami.Heading {
text: qsTr("Log in to your XMPP account")
wrapMode: Text.WordWrap
Layout.fillWidth: true
horizontalAlignment: Qt.AlignHCenter
}
ColumnLayout {
width: parent.width
Layout.fillWidth: true
// For desktop or tablet devices
Layout.alignment: Qt.AlignCenter
Layout.maximumWidth: Kirigami.Units.gridUnit * 25
// JID field
Controls.Label {
id: jidLabel
text: qsTr("Your Jabber-ID:")
}
Controls.TextField {
id: jidField
text: kaidan.jid
placeholderText: qsTr("user@example.org")
Layout.fillWidth: true
selectByMouse: true
inputMethodHints: Qt.ImhEmailCharactersOnly
}
// Password field
Controls.Label {
text: qsTr("Your Password:")
}
Controls.TextField {
id: passField
text: kaidan.password
echoMode: TextInput.Password
selectByMouse: true
Layout.fillWidth: true
}
// Connect button
Controls.Button {
id: connectButton
Layout.fillWidth: true
Kirigami.Theme.backgroundColor: Material.accent
text: qsTr("Connect")
states: [
State {
name: "connecting"
PropertyChanges {
target: connectButton
enabled: false
text: "" + qsTr("Connecting…") + ""
}
}
]
onClicked: {
// connect to given account data
kaidan.jid = jidField.text.toLowerCase()
kaidan.password = passField.text
kaidan.mainConnect()
}
}
// connect when return was pressed
Keys.onPressed: {
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
connectButton.clicked()
}
}
}
// placeholder
Item {
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
}
}
function handleConnectionState(state) {
if (state === Enums.StateConnecting) {
connectButton.state = "connecting"
} else {
connectButton.state = ""
}
}
function handleConnectionError() {
var error = kaidan.disconnReason
if (error === Enums.ConnAuthenticationFailed) {
passiveNotification(qsTr("Invalid username or password."))
} else if (error === Enums.ConnNotConnected) {
passiveNotification(qsTr("Cannot connect to the server. Please check your internet connection."))
} else if (error === Enums.ConnTlsNotAvailable) {
passiveNotification(qsTr("The server doesn't support secure connections."))
} else if (error === Enums.ConnTlsFailed) {
passiveNotification(qsTr("Error while trying to connect securely."))
} else if (error === Enums.ConnDnsError) {
passiveNotification(qsTr("Could not resolve the server's address. Please check your JID again."))
} else if (error === Enums.ConnConnectionRefused) {
passiveNotification(qsTr("Could not connect to the server."))
} else if (error === Enums.ConnNoSupportedAuth) {
passiveNotification(qsTr("Authentification protocol not supported by the server."))
} else {
passiveNotification(qsTr("An unknown error occured; see log for details."))
}
}
Component.onCompleted: {
kaidan.connectionStateChanged.connect(handleConnectionState)
kaidan.disconnReasonChanged.connect(handleConnectionError)
}
Component.onDestruction: {
kaidan.connectionStateChanged.disconnect(handleConnectionState)
kaidan.disconnReasonChanged.disconnect(handleConnectionError)
}
}
diff --git a/src/qml/QrScannerPage.qml b/src/qml/QrScannerPage.qml
new file mode 100644
index 0000000..9f4dc0c
--- /dev/null
+++ b/src/qml/QrScannerPage.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.0
+import org.kde.kirigami 2.2 as Kirigami
+import QtMultimedia 5.9
+
+Kirigami.Page {
+ leftPadding: 0
+ rightPadding: 0
+ topPadding: 0
+ bottomPadding: 0
+
+ title: qsTr("Scan QR code")
+
+ VideoOutput {
+ id: viewfinder
+ anchors.fill: parent
+ source: camera
+ }
+
+ Camera {
+ id: camera
+ captureMode: Camera.CaptureVideo
+ }
+}
diff --git a/src/qml/main.qml b/src/qml/main.qml
index 4bf541d..9840bc1 100644
--- a/src/qml/main.qml
+++ b/src/qml/main.qml
@@ -1,131 +1,132 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kaidan. If not, see .
*/
import QtQuick 2.7
import QtQuick.Controls.Material 2.0
import org.kde.kirigami 2.3 as Kirigami
import StatusBar 0.1
import im.kaidan.kaidan 1.0
import "elements"
import "settings"
Kirigami.ApplicationWindow {
id: root
StatusBar {
color: Material.color(Material.Green, Material.Shade700)
}
// Global and Contextual Drawers
globalDrawer: GlobalDrawer {}
contextDrawer: Kirigami.ContextDrawer {
id: contextDrawer
}
AboutDialog {
id: aboutDialog
focus: true
x: (parent.width - width) / 2
y: (parent.height - height) / 2
}
SubRequestAcceptSheet {
id: subReqAcceptSheet
}
// when the window was closed, disconnect from jabber server
onClosing: {
kaidan.mainDisconnect()
}
// load all pages
Component {id: chatPage; ChatPage {}}
Component {id: loginPage; LoginPage {}}
Component {id: rosterPage; RosterPage {}}
Component {id: emptyChatPage; EmptyChatPage {}}
Component {id: settingsPage; SettingsPage {}}
+ Component {id: qrScannerPage; QrScannerPage {}}
function passiveNotification(text) {
showPassiveNotification(text, "long")
}
function openLogInPage() {
// close all pages (we don't know on which page we're on,
// thus we don't use replace)
while (pageStack.depth > 0)
pageStack.pop()
// toggle global drawer
globalDrawer.enabled = false
globalDrawer.visible = false
// push new page
pageStack.push(loginPage)
}
function closeLogInPage() {
// toggle global drawer
globalDrawer.enabled = true
// replace page with roster page
pageStack.replace(rosterPage)
if (!Kirigami.Settings.isMobile)
pageStack.push(emptyChatPage)
}
function handleSubRequest(from, message) {
kaidan.vCardRequested(from)
subReqAcceptSheet.from = from
subReqAcceptSheet.message = message
subReqAcceptSheet.open()
}
Component.onCompleted: {
kaidan.passiveNotificationRequested.connect(passiveNotification)
kaidan.newCredentialsNeeded.connect(openLogInPage)
kaidan.logInWorked.connect(closeLogInPage)
kaidan.subscriptionRequestReceived.connect(handleSubRequest)
// push roster page (trying normal start up)
pageStack.push(rosterPage)
if (!Kirigami.Settings.isMobile)
pageStack.push(emptyChatPage)
// Annouce that we're ready and the back-end can start with connecting
kaidan.start()
}
Component.onDestruction: {
kaidan.passiveNotificationRequested.disconnect(passiveNotification)
kaidan.newCredentialsNeeded.disconnect(openLogInPage)
kaidan.logInWorked.disconnect(closeLogInPage)
kaidan.subscriptionRequestReceived.disconnect(handleSubRequest)
}
}