caelestia/quickshell/pass/shell.qml
2026-01-06 16:58:34 +00:00

198 lines
6.3 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.LocalStorage
import Quickshell
import Quickshell.Widgets
import Quickshell.Io
import Qt.labs.folderlistmodel
Window {
id: launcher
title: "qs-pass"
visible: true
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
color: Qt.rgba(0.117, 0.118, 0.180, 0.5)
width: 560
height: 360
property string query: ""
property string passLocation: ""
Process {
id: passCopy
running: false
command: ["pass", "-c", passLocation]
stdout: StdioCollector {
onStreamFinished: Qt.quit()
}
}
Process {
id: userCopy
running: false
command: ["pass", "-c2", passLocation]
}
function copyPass() {
if(list.currentItem.fileIsDir==true) {
folderModel.folder = folderModel.folder+"/"+list.currentItem.fileBaseName
}
else {
passLocation = list.currentItem.filePath
passLocation = passLocation.replace("/home/ceres/.password-store/", "")
passLocation = passLocation.replace(".gpg", "")
passCopy.running = true
}
}
function copyUser() {
if(list.currentItem.fileIsDir==true) {
folderModel.folder = folderModel.folder+"/"+list.currentItem.fileBaseName
}
else {
passLocation = list.currentItem.filePath
passLocation = passLocation.replace("/home/ceres/.password-store/", "")
passLocation = passLocation.replace(".gpg", "")
userCopy.running = true
}
}
ColumnLayout {
anchors.fill: parent
spacing: 8
RowLayout {
IconImage {
Layout.leftMargin: 10
source: Quickshell.iconPath("password-copy", true)
Layout.preferredWidth: 25
Layout.preferredHeight: 25
}
TextField {
id: input
Layout.fillWidth: true
font.pixelSize: 18
color: "white"
focus: true
padding: 15
onTextChanged: {
launcher.query = text;
// reset selection to first item of the filtered list
list.currentIndex = folderModel.length > 0 ? 0 : -1;
}
background: Rectangle {
border.width: 0
color: "transparent"
}
// Quit
Keys.onEscapePressed: Qt.quit()
Keys.onPressed: event => {
const ctrl = event.modifiers & Qt.ControlModifier;
if (event.key == Qt.Key_Up || event.key == Qt.Key_P && ctrl) {
event.accepted = true;
if (list.currentIndex > 0)
list.currentIndex--;
} else if (event.key == Qt.Key_Down || event.key == Qt.Key_N && ctrl) {
event.accepted = true;
if (list.currentIndex < list.count - 1)
list.currentIndex++;
} else if (event.key == Qt.Key_U && ctrl) {
event.accepted = true;
launcher.copyUser();
} else if ([Qt.Key_Return, Qt.Key_Enter].includes(event.key)) {
event.accepted = true;
launcher.copyPass();
} else if (event.key == Qt.Key_C && ctrl) {
event.accepted = true;
Qt.quit();
}
}
}
}
FolderListModel {
function getQuery() {
return "*"+launcher.query+"*"
}
id: folderModel
folder: "file:///home/ceres/.password-store/"
showDirsFirst: true
caseSensitive: false
showDirs: launcher.query === "" ? true : false
nameFilters: [ getQuery() ]
}
ListView {
id: list
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
model: folderModel
currentIndex: folderModel.length > 0 ? 0 : -1
keyNavigationWraps: true
preferredHighlightBegin: 0
preferredHighlightEnd: height
highlightRangeMode: ListView.ApplyRange
highlightMoveDuration: 80
highlight: Rectangle {
radius: 4
opacity: 0.45
color: input.palette.highlight
}
delegate: Item {
id: entry
required property string fileBaseName
required property string filePath
required property int index
required property bool fileIsDir
width: ListView.view.width
height: 36
MouseArea {
anchors.fill: parent
onClicked: list.currentIndex = entry.index
onDoubleClicked: launcher.launchSelected()
}
Row {
anchors.fill: parent
anchors.margins: 8
spacing: 10
// IconImage {
// source: Quickshell.iconPath(modelData.icon, true)
// width: 23
// height: 23
// }
Text {
function genText() {
if(fileIsDir==true) {
return fileBaseName+"/"
}
else {
return fileBaseName
}
}
id: label
color: "white"
text: genText()
font.pointSize: 13
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
}
// Enter also works while ListView has focus
Keys.onReturnPressed: launcher.copyUser()
}
}
}