mirror of
https://github.com/tomasriveral/nixos.git
synced 2026-08-12 10:30:44 +02:00
ported some quickshell stuff from rivendell-hyprdots
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import "." as Launcher
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
property bool isOpen: false
|
||||
property var lastUsedTimes: ({})
|
||||
|
||||
IpcHandler {
|
||||
target: "launcher"
|
||||
|
||||
function open() {
|
||||
root.isOpen = true;
|
||||
}
|
||||
|
||||
function close() {
|
||||
root.isOpen = false;
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
root.isOpen = !root.isOpen;
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
active: root.isOpen
|
||||
Launcher.Overlay {
|
||||
controller: root
|
||||
}
|
||||
}
|
||||
|
||||
// Empty function to define first reference to singleton
|
||||
function init() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import ".."
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
|
||||
required property var controller
|
||||
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
anchors {
|
||||
left: true
|
||||
right: true
|
||||
top: true
|
||||
bottom: true
|
||||
}
|
||||
color: "transparent"
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
||||
WlrLayershell.namespace: "shell:launcher"
|
||||
|
||||
Rectangle {
|
||||
id: main
|
||||
|
||||
anchors.centerIn: parent
|
||||
height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10)
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
width: 450
|
||||
color: Globals.isDarkTheme ? "#393536" : "#f3eac7"
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 7
|
||||
anchors.bottomMargin: 0
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
id: searchContainer
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: search.implicitHeight + 10
|
||||
color: Globals.isDarkTheme ? "#44000000" : "#11000000"
|
||||
|
||||
TextInput {
|
||||
id: search
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 4
|
||||
color: Globals.isDarkTheme ? "#D6C8A6" : "#403D3B"
|
||||
|
||||
font.family: "BigBlueTermPlusNerdFont"
|
||||
|
||||
focus: true
|
||||
Keys.forwardTo: [list]
|
||||
Keys.onEscapePressed: root.controller.isOpen = false
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
if (event.key == Qt.Key_J) {
|
||||
list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1;
|
||||
event.accepted = true;
|
||||
} else if (event.key == Qt.Key_K) {
|
||||
list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1;
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (list.currentItem) {
|
||||
list.currentItem.clicked(null);
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
list.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: list
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
cacheBuffer: 0 // works around QTBUG-131106
|
||||
//reuseItems: true
|
||||
|
||||
model: ScriptModel {
|
||||
values: DesktopEntries.applications.values.map(object => {
|
||||
const stxt = search.text.toLowerCase();
|
||||
const ntxt = object.name.toLowerCase();
|
||||
|
||||
let si = 0;
|
||||
let ni = 0;
|
||||
|
||||
let matches = [];
|
||||
let startMatch = -1;
|
||||
|
||||
for (let si = 0; si != stxt.length; ++si) {
|
||||
const sc = stxt[si];
|
||||
|
||||
while (true) {
|
||||
// Drop any entries with letters that don't exist in order
|
||||
if (ni == ntxt.length)
|
||||
return null;
|
||||
|
||||
const nc = ntxt[ni++];
|
||||
|
||||
if (nc == sc) {
|
||||
if (startMatch == -1)
|
||||
startMatch = ni;
|
||||
break;
|
||||
} else {
|
||||
if (startMatch != -1) {
|
||||
matches.push({
|
||||
index: startMatch,
|
||||
length: ni - startMatch
|
||||
});
|
||||
|
||||
startMatch = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startMatch != -1) {
|
||||
matches.push({
|
||||
index: startMatch,
|
||||
length: ni - startMatch + 1
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
object: object,
|
||||
matches: matches
|
||||
};
|
||||
}).filter(entry => entry !== null).sort((a, b) => {
|
||||
if (!search.text) {
|
||||
if (controller.lastUsedTimes[a.object.id])
|
||||
print(controller.lastUsedTimes[a.object.id]);
|
||||
let aDate = controller.lastUsedTimes[a.object.id] ?? new Date(0);
|
||||
let bDate = controller.lastUsedTimes[b.object.id] ?? new Date(0);
|
||||
return bDate - aDate;
|
||||
}
|
||||
|
||||
let ai = 0;
|
||||
let bi = 0;
|
||||
let s = 0;
|
||||
|
||||
while (ai != a.matches.length && bi != b.matches.length) {
|
||||
const am = a.matches[ai];
|
||||
const bm = b.matches[bi];
|
||||
|
||||
s = bm.length - am.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
s = am.index - bm.index;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
++ai;
|
||||
++bi;
|
||||
}
|
||||
|
||||
s = a.matches.length - b.matches.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
s = a.object.name.length - b.object.name.length;
|
||||
if (s != 0)
|
||||
return s;
|
||||
|
||||
return a.object.name.localeCompare(b.object.name);
|
||||
}).map(entry => entry.object)
|
||||
|
||||
onValuesChanged: list.currentIndex = 0
|
||||
}
|
||||
|
||||
topMargin: 7
|
||||
bottomMargin: list.count == 0 ? 0 : 7
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
|
||||
highlight: Rectangle {
|
||||
color: Globals.isDarkTheme ? "#20e0ffff" : "#11000000"
|
||||
}
|
||||
keyNavigationEnabled: true
|
||||
keyNavigationWraps: true
|
||||
highlightMoveVelocity: -1
|
||||
highlightMoveDuration: 100
|
||||
preferredHighlightBegin: list.topMargin
|
||||
preferredHighlightEnd: list.height - list.bottomMargin
|
||||
highlightRangeMode: ListView.ApplyRange
|
||||
snapMode: ListView.SnapToItem
|
||||
|
||||
readonly property real delegateHeight: 44
|
||||
|
||||
delegate: MouseArea {
|
||||
required property DesktopEntry modelData
|
||||
|
||||
implicitHeight: list.delegateHeight
|
||||
implicitWidth: ListView.view.width
|
||||
|
||||
onClicked: {
|
||||
controller.lastUsedTimes[modelData.id] = new Date();
|
||||
modelData.execute();
|
||||
root.controller.isOpen = false;
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: delegateLayout
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: 5
|
||||
}
|
||||
|
||||
IconImage {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
asynchronous: true
|
||||
implicitSize: 30
|
||||
source: Quickshell.iconPath(modelData.icon)
|
||||
}
|
||||
Text {
|
||||
text: modelData.name
|
||||
font.family: "BigBlueTermPlusNerdFont"
|
||||
color: Globals.isDarkTheme ? "#D6C8A6" : "#403D3B"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MultiEffect {
|
||||
source: main
|
||||
anchors.fill: main
|
||||
shadowBlur: 0
|
||||
shadowEnabled: true
|
||||
shadowColor: "#33000000"
|
||||
shadowVerticalOffset: 16
|
||||
shadowHorizontalOffset: 12
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user