passwordmanager/qml/EntriesPage.qml

182 lines
6.4 KiB
QML
Raw Permalink Normal View History

import QtQuick 2.15
import QtQuick.Layouts 1.2
import QtQml.Models 2.2
import QtQuick.Controls 2.4 as Controls
import org.kde.kirigami 2.5 as Kirigami
Kirigami.ScrollablePage {
id: page
2018-06-14 23:19:28 +02:00
property var main: undefined
property alias entryModel: delegateModel.model
property alias rootIndex: delegateModel.rootIndex
Layout.fillWidth: true
title: {
var currentEntryName = entryModel.data(rootIndex)
return currentEntryName ? currentEntryName : ""
}
2023-03-04 17:27:38 +01:00
actions:[
Kirigami.Action {
icon.name: "list-add"
text: qsTr("Add account")
visible: !nativeInterface.hasEntryFilter
enabled: !nativeInterface.hasEntryFilter
onTriggered: insertEntry("Account")
2018-09-10 20:43:58 +02:00
shortcut: "Ctrl+A"
2023-03-04 17:27:38 +01:00
},
Kirigami.Action {
icon.name: "edit-paste"
text: qsTr("Paste account")
visible: !nativeInterface.hasEntryFilter
enabled: nativeInterface.canPaste && !nativeInterface.hasEntryFilter
2018-06-12 22:20:43 +02:00
onTriggered: {
var pastedEntries = nativeInterface.pasteEntries(rootIndex)
if (pastedEntries.length < 1) {
showPassiveNotification(
qsTr("Unable to paste the entries here"))
return
}
showPassiveNotification(qsTr("Pasted %1").arg(
pastedEntries.join(", ")))
2018-06-12 22:20:43 +02:00
}
2018-09-10 20:43:58 +02:00
shortcut: StandardKey.Paste
2023-03-04 17:27:38 +01:00
},
Kirigami.Action {
icon.name: "folder-add"
text: qsTr("Add category")
visible: !nativeInterface.hasEntryFilter
enabled: !nativeInterface.hasEntryFilter
onTriggered: insertEntry("Node")
2018-09-10 20:43:58 +02:00
shortcut: "Ctrl+Shift+A"
}
2023-03-04 17:27:38 +01:00
]
2018-06-12 22:02:37 +02:00
// dialog to confirm deletion of an entry
BasicDialog {
id: confirmDeletionDialog
property string entryDesc: "?"
property int entryIndex: -1
standardButtons: Controls.Dialog.Ok | Controls.Dialog.Cancel
title: qsTr("Delete %1?").arg(entryDesc)
onAccepted: entryModel.removeRows(this.entryIndex, 1, rootIndex)
contentItem: ColumnLayout {
Controls.Label {
text: " "
}
}
function confirmDeletion(entryName, entryIndex) {
var isNode = entryModel.isNode(entryModel.index(entryIndex, 0,
rootIndex))
var entryType = isNode ? qsTr("category ") : qsTr("account ")
this.entryIndex = entryIndex
this.entryDesc = entryType + entryName
2018-12-08 20:51:19 +01:00
// skip dialog if undo is supported
if (nativeInterface.undoStack) {
entryModel.removeRows(entryIndex, 1, rootIndex)
showPassiveNotification(qsTr("Deleted %1").arg(entryDesc))
return
}
this.open()
}
}
2018-06-12 22:02:37 +02:00
// dialog to rename an entry
BasicDialog {
id: renameDialog
property string entryDesc: "?"
property int entryIndex: -1
property alias newEntryName: entryNameTextField.text
property bool entryNew: false
standardButtons: newEntryName.length
> 0 ? Controls.Dialog.Ok | Controls.Dialog.Cancel : Controls.Dialog.Cancel
title: entryNew ? qsTr("Name for new %1").arg(entryDesc) : qsTr(
"Rename %1").arg(entryDesc)
onAccepted: {
entryModel.setData(entryModel.index(this.entryIndex, 0, rootIndex),
newEntryName)
}
onRejected: {
if (this.entryNew) {
entryModel.removeRows(this.entryIndex, 1, rootIndex)
}
}
contentItem: ColumnLayout {
Controls.TextField {
id: entryNameTextField
Layout.preferredWidth: renameDialog.availableWidth
placeholderText: qsTr("enter new name here")
Keys.onPressed: (event) => renameDialog.acceptOnReturn(event)
}
}
function renameEntry(entryName, entryIndex) {
var isNode = entryModel.isNode(entryModel.index(entryIndex, 0,
rootIndex))
var entryType = isNode ? qsTr("category ") : qsTr("account ")
this.entryIndex = entryIndex
this.entryNew = entryName === null
if (this.entryNew) {
this.entryDesc = entryType
this.newEntryName = ""
} else {
this.entryDesc = entryType + entryName
this.newEntryName = entryName
}
entryNameTextField.forceActiveFocus()
this.open()
}
}
// list view to display one hierarchy level of entry model
ListView {
id: entriesListView
2018-06-12 22:02:37 +02:00
anchors.fill: parent
2018-06-14 23:46:18 +02:00
moveDisplaced: Transition {
YAnimator {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
}
}
reuseItems: true
model: DelegateModel {
id: delegateModel
delegate: EntryDelegate {
width: entriesListView.width
view: entriesListView
onMoveRequested:
(oldIndex, newIndex) => {
entryModel.moveRows(rootIndex, oldIndex, 1, rootIndex, oldIndex < newIndex ? newIndex + 1 : newIndex)
}
}
2018-06-14 23:46:18 +02:00
function isNode(rowNumber) {
return entryModel.isNode(entryModel.index(rowNumber, 0,
rootIndex))
}
function handleEntryClicked(rowNumber, entryName) {
var modelIndex = entryModel.index(rowNumber, 0, rootIndex)
if (entryModel.isNode(modelIndex)) {
root.pushStackEntry(entryModel, modelIndex)
} else {
nativeInterface.currentAccountIndex = modelIndex
2018-09-09 01:49:32 +02:00
root.pushAccountEdit()
}
}
}
}
function insertEntry(entryType) {
var newIndex = entryModel.rowCount(rootIndex)
entryModel["setInsertTypeTo" + entryType]()
entryModel.insertRows(newIndex, 1, rootIndex)
renameDialog.renameEntry(null, newIndex)
}
}