1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00
Files
DankMaterialShell/quickshell/Modals/KeybindsModal.qml
2025-12-01 17:49:32 -05:00

257 lines
12 KiB
QML

import QtQuick
import qs.Common
import qs.Modals.Common
import qs.Services
import qs.Widgets
DankModal {
id: root
layerNamespace: "dms:keybinds"
useOverlayLayer: true
property real scrollStep: 60
property var activeFlickable: null
property real _maxW: Math.min(Screen.width * 0.92, 1200)
property real _maxH: Math.min(Screen.height * 0.92, 900)
modalWidth: _maxW
modalHeight: _maxH
onBackgroundClicked: close()
function scrollDown() {
if (!root.activeFlickable)
return;
let newY = root.activeFlickable.contentY + scrollStep;
newY = Math.min(newY, root.activeFlickable.contentHeight - root.activeFlickable.height);
root.activeFlickable.contentY = newY;
}
function scrollUp() {
if (!root.activeFlickable)
return;
let newY = root.activeFlickable.contentY - root.scrollStep;
newY = Math.max(0, newY);
root.activeFlickable.contentY = newY;
}
content: Component {
FocusScope {
anchors.fill: parent
focus: true
Keys.onPressed: event => {
switch (event.key) {
case Qt.Key_J:
if (!(event.modifiers & Qt.ControlModifier))
return;
root.scrollDown();
event.accepted = true;
break;
case Qt.Key_K:
if (!(event.modifiers & Qt.ControlModifier))
return;
root.scrollUp();
event.accepted = true;
break;
case Qt.Key_Down:
root.scrollDown();
event.accepted = true;
break;
case Qt.Key_Up:
root.scrollUp();
event.accepted = true;
break;
}
}
Column {
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingL
StyledText {
text: KeybindsService.keybinds.title || "Keybinds"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.primary
}
DankFlickable {
id: mainFlickable
width: parent.width
height: parent.height - parent.spacing - 40
contentWidth: rowLayout.implicitWidth
contentHeight: rowLayout.implicitHeight
clip: true
Component.onCompleted: root.activeFlickable = mainFlickable
property var rawBinds: KeybindsService.keybinds.binds || {}
property var categories: {
const processed = {};
for (const cat in rawBinds) {
const binds = rawBinds[cat];
const subcats = {};
let hasSubcats = false;
for (let i = 0; i < binds.length; i++) {
const bind = binds[i];
if (bind.subcat) {
hasSubcats = true;
if (!subcats[bind.subcat]) {
subcats[bind.subcat] = [];
}
subcats[bind.subcat].push(bind);
} else {
if (!subcats["_root"]) {
subcats["_root"] = [];
}
subcats["_root"].push(bind);
}
}
processed[cat] = {
hasSubcats: hasSubcats,
subcats: subcats,
subcatKeys: Object.keys(subcats)
};
}
return processed;
}
property var categoryKeys: Object.keys(categories)
function distributeCategories(cols) {
const columns = [];
for (let i = 0; i < cols; i++) {
columns.push([]);
}
for (let i = 0; i < categoryKeys.length; i++) {
columns[i % cols].push(categoryKeys[i]);
}
return columns;
}
Row {
id: rowLayout
width: mainFlickable.width
spacing: Theme.spacingM
property int numColumns: Math.max(1, Math.min(3, Math.floor(width / 350)))
property var columnCategories: mainFlickable.distributeCategories(numColumns)
Repeater {
model: rowLayout.numColumns
Column {
id: masonryColumn
width: (rowLayout.width - rowLayout.spacing * (rowLayout.numColumns - 1)) / rowLayout.numColumns
spacing: Theme.spacingM
Repeater {
model: rowLayout.columnCategories[index] || []
Column {
id: categoryColumn
width: parent.width
spacing: Theme.spacingXS
property string catName: modelData
property var catData: mainFlickable.categories[catName]
StyledText {
text: categoryColumn.catName
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold
color: Theme.primary
}
Rectangle {
width: parent.width
height: 1
color: Theme.primary
opacity: 0.3
}
Item {
width: 1
height: Theme.spacingXS
}
Column {
width: parent.width
spacing: Theme.spacingM
Repeater {
model: categoryColumn.catData?.subcatKeys || []
Column {
width: parent.width
spacing: Theme.spacingXS
property string subcatName: modelData
property var subcatBinds: categoryColumn.catData?.subcats?.[subcatName] || []
StyledText {
visible: parent.subcatName !== "_root"
text: parent.subcatName
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.primary
opacity: 0.7
}
Column {
width: parent.width
spacing: Theme.spacingXS
Repeater {
model: parent.parent.subcatBinds
Row {
width: parent.width
spacing: Theme.spacingS
StyledRect {
width: Math.min(140, parent.width * 0.42)
height: 22
radius: 4
opacity: 0.9
StyledText {
anchors.centerIn: parent
anchors.margins: 2
width: parent.width - 4
color: Theme.secondary
text: modelData.key || ""
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
isMonospace: true
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
}
}
StyledText {
width: parent.width - 150
text: modelData.desc || ""
font.pixelSize: Theme.fontSizeSmall
opacity: 0.9
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}