passwordmanager/qml/main.qml

204 lines
6.8 KiB
QML

import QtQuick 2.7
import QtQuick.Controls 2.1 as Controls
import QtQuick.Layouts 1.2
import QtQuick.Dialogs 1.3
import org.kde.kirigami 2.4 as Kirigami
Kirigami.ApplicationWindow {
id: root
property alias showPasswordsOnFocus: showPasswordsOnFocusSwitch.checked
header: Kirigami.ApplicationHeader {
}
globalDrawer: Kirigami.GlobalDrawer {
id: leftMenu
title: qsTr("Password Manager")
titleIcon: "qrc://icons/hicolor/scalable/apps/passwordmanager.svg"
visible: !nativeInterface.fileOpen
topContent: ColumnLayout {
Layout.fillWidth: true
Controls.MenuSeparator {
padding: 0
topPadding: 8
bottomPadding: 0
Layout.fillWidth: true
}
Controls.Label {
padding: 8
wrapMode: Controls.Label.Wrap
fontSizeMode: Text.HorizontalFit
minimumPixelSize: 10
font.pixelSize: 20
Layout.fillWidth: true
text: nativeInterface.fileOpen ? nativeInterface.fileName : qsTr(
"No file opened")
}
}
actions: [
Kirigami.Action {
text: qsTr("Create new file")
iconName: "document-new"
onTriggered: fileDialog.createNew()
},
Kirigami.Action {
text: qsTr("Open existing file")
iconName: "document-open"
onTriggered: fileDialog.openExisting()
},
Kirigami.Action {
text: qsTr("Recently opened ...")
iconName: "document-open-recent"
children: createFileActions(nativeInterface.recentFiles)
},
Kirigami.Action {
text: "Save modifications"
enabled: nativeInterface.fileOpen
iconName: "document-save"
onTriggered: nativeInterface.save()
},
Kirigami.Action {
text: "Change password"
enabled: nativeInterface.fileOpen
iconName: "dialog-password"
onTriggered: enterPasswordDialog.askForNewPassword(
"Change password for " + nativeInterface.filePath)
},
Kirigami.Action {
text: "Close file"
enabled: nativeInterface.fileOpen
iconName: "document-close"
onTriggered: nativeInterface.close()
}
]
Controls.Switch {
text: qsTr("Use native file dialog")
checked: nativeInterface.useNativeFileDialog
visible: nativeInterface.supportsNativeFileDialog
onCheckedChanged: nativeInterface.useNativeFileDialog = checked
}
Controls.Switch {
id: showPasswordsOnFocusSwitch
text: qsTr("Show passwords on focus")
checked: true
}
Controls.Label {
wrapMode: Controls.Label.Wrap
Layout.fillWidth: true
text: nativeInterface.fileOpen ? nativeInterface.filePath : qsTr(
"No file opened")
}
}
contextDrawer: Kirigami.ContextDrawer {
id: contextDrawer
}
Component.onCompleted: nativeInterface.init()
PasswordDialog {
id: enterPasswordDialog
}
FileDialog {
id: fileDialog
title: selectExisting ? qsTr("Select an existing file") : qsTr(
"Select path for new file")
property bool selectExisting: true
onAccepted: {
if (fileUrls.length < 1) {
return
}
nativeInterface.handleFileSelectionAccepted(fileUrls[0],
this.selectExisting)
}
onRejected: nativeInterface.handleFileSelectionCanceled()
function show() {
if (nativeInterface.showNativeFileDialog(this.selectExisting)) {
return
}
// fallback to the Qt Quick file dialog if a native implementation is not available
this.open()
}
function openExisting() {
this.selectExisting = true
this.show()
}
function createNew() {
this.selectExisting = false
this.show()
}
}
Connections {
target: nativeInterface
onFileError: {
showPassiveNotification(errorMessage)
}
onPasswordRequired: {
enterPasswordDialog.askForExistingPassword(
qsTr("Password required to open %1").arg(
nativeInterface.filePath))
leftMenu.resetMenu()
}
onFileOpenChanged: {
clearStack()
if (!nativeInterface.fileOpen) {
showPassiveNotification(qsTr("%1 closed").arg(
nativeInterface.fileName))
return
}
var entryModel = nativeInterface.entryModel
var rootIndex = entryModel.index(0, 0)
pushStackEntry(entryModel, rootIndex)
showPassiveNotification(qsTr("%1 opened").arg(
nativeInterface.fileName))
}
onFileSaved: {
showPassiveNotification(qsTr("%1 saved").arg(
nativeInterface.fileName))
}
onNewNotification: {
showPassiveNotification(message)
}
}
Component {
id: fileActionComponent
Kirigami.Action {
property string filePath
text: filePath.substring(filePath.lastIndexOf('/') + 1)
onTriggered: nativeInterface.load(filePath)
}
}
Component {
id: entriesComponent
EntriesPage {
main: root
}
}
function clearStack() {
pageStack.pop(root.pageStack.initialPage, Controls.StackView.Immediate)
}
function pushStackEntry(entryModel, rootIndex) {
pageStack.push(entriesComponent.createObject(root, {
"entryModel": entryModel,
"rootIndex": rootIndex,
"title": entryModel.data(
rootIndex)
}))
}
function createFileActions(files) {
return files.map(function (filePath) {
return this.createObject(root, {
"filePath": filePath
})
}, fileActionComponent)
}
}