mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
feat: New Notepad widget w/Autosave
- IPC: qs -c dms ipc call notepad toggle
This commit is contained in:
@@ -37,6 +37,7 @@ Singleton {
|
||||
property int wallpaperCyclingInterval: 300 // seconds (5 minutes)
|
||||
property string wallpaperCyclingTime: "06:00" // HH:mm format
|
||||
property string lastBrightnessDevice: ""
|
||||
property string notepadContent: ""
|
||||
|
||||
Component.onCompleted: {
|
||||
loadSettings()
|
||||
@@ -104,6 +105,7 @@ Singleton {
|
||||
!== undefined ? settings.wallpaperCyclingTime : "06:00"
|
||||
lastBrightnessDevice = settings.lastBrightnessDevice
|
||||
!== undefined ? settings.lastBrightnessDevice : ""
|
||||
notepadContent = settings.notepadContent !== undefined ? settings.notepadContent : ""
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -137,7 +139,8 @@ Singleton {
|
||||
"wallpaperCyclingMode": wallpaperCyclingMode,
|
||||
"wallpaperCyclingInterval": wallpaperCyclingInterval,
|
||||
"wallpaperCyclingTime": wallpaperCyclingTime,
|
||||
"lastBrightnessDevice": lastBrightnessDevice
|
||||
"lastBrightnessDevice": lastBrightnessDevice,
|
||||
"notepadContent": notepadContent
|
||||
}, null, 2))
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ DankModal {
|
||||
property int selectedIndex: -1
|
||||
property bool keyboardNavigationActive: false
|
||||
property bool backButtonFocused: false
|
||||
property bool saveMode: false // Enable save functionality
|
||||
property string defaultFileName: "" // Default filename for save mode
|
||||
|
||||
FolderListModel {
|
||||
id: folderModel
|
||||
@@ -624,6 +626,72 @@ DankModal {
|
||||
}
|
||||
}
|
||||
|
||||
// Save functionality - positioned at bottom in save mode
|
||||
Row {
|
||||
id: saveRow
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: Theme.spacingL
|
||||
height: saveMode ? 40 : 0
|
||||
visible: saveMode
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankTextField {
|
||||
id: fileNameInput
|
||||
width: parent.width - saveButton.width - Theme.spacingM
|
||||
height: 36
|
||||
text: defaultFileName
|
||||
placeholderText: "Enter filename..."
|
||||
ignoreLeftRightKeys: false // Allow arrow key navigation
|
||||
focus: saveMode // Auto-focus when in save mode
|
||||
|
||||
Component.onCompleted: {
|
||||
if (saveMode) {
|
||||
Qt.callLater(() => {
|
||||
forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (text.trim() !== "") {
|
||||
var fullPath = currentPath + "/" + text.trim();
|
||||
fileSelected(fullPath);
|
||||
fileBrowserModal.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: saveButton
|
||||
width: 80
|
||||
height: 36
|
||||
color: fileNameInput.text.trim() !== "" ? Theme.primary : Theme.surfaceVariant
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: "Save"
|
||||
color: fileNameInput.text.trim() !== "" ? Theme.primaryText : Theme.surfaceVariantText
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
stateColor: Theme.primary
|
||||
cornerRadius: Theme.cornerRadius
|
||||
enabled: fileNameInput.text.trim() !== ""
|
||||
onClicked: {
|
||||
if (fileNameInput.text.trim() !== "") {
|
||||
var fullPath = currentPath + "/" + fileNameInput.text.trim();
|
||||
fileSelected(fullPath);
|
||||
fileBrowserModal.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileBrowserKeyboardHints {
|
||||
id: keyboardHints
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
399
Modals/NotepadModal.qml
Normal file
399
Modals/NotepadModal.qml
Normal file
@@ -0,0 +1,399 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: root
|
||||
|
||||
property bool notepadModalVisible: false
|
||||
property bool fileDialogOpen: false
|
||||
property string currentFileName: "" // Track the currently loaded file
|
||||
|
||||
function show() {
|
||||
notepadModalVisible = true;
|
||||
shouldHaveFocus = Qt.binding(() => {
|
||||
return notepadModalVisible && !fileDialogOpen;
|
||||
});
|
||||
open();
|
||||
}
|
||||
|
||||
function hide() {
|
||||
notepadModalVisible = false;
|
||||
// Clear filename when closing (so it doesn't persist between sessions)
|
||||
currentFileName = "";
|
||||
close();
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (notepadModalVisible)
|
||||
hide();
|
||||
else
|
||||
show();
|
||||
}
|
||||
|
||||
visible: notepadModalVisible
|
||||
width: 700
|
||||
height: 500
|
||||
enableShadow: true
|
||||
onShouldHaveFocusChanged: {
|
||||
console.log("Notepad: shouldHaveFocus changed to", shouldHaveFocus, "modalVisible:", notepadModalVisible, "dialogOpen:", fileDialogOpen);
|
||||
}
|
||||
onBackgroundClicked: hide()
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
id: contentItem
|
||||
|
||||
anchors.fill: parent
|
||||
property alias textArea: textArea
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onNotepadModalVisibleChanged() {
|
||||
if (root.notepadModalVisible) {
|
||||
Qt.callLater(() => {
|
||||
textArea.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Row {
|
||||
width: parent.width - closeButton.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Column {
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: "Notepad"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: currentFileName
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceTextMedium
|
||||
visible: currentFileName !== ""
|
||||
elide: Text.ElideMiddle
|
||||
maximumLineCount: 1
|
||||
width: 200
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: SessionData.notepadContent.length > 0 ? `${SessionData.notepadContent.length} characters` : "Empty"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceTextMedium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: closeButton
|
||||
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: root.hide()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: parent.height - 80
|
||||
color: Theme.surface
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
clip: true
|
||||
|
||||
TextArea {
|
||||
id: textArea
|
||||
|
||||
text: SessionData.notepadContent
|
||||
placeholderText: "Start typing your notes here..."
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
selectByMouse: true
|
||||
selectByKeyboard: true
|
||||
wrapMode: TextArea.Wrap
|
||||
focus: root.notepadModalVisible
|
||||
activeFocusOnTab: true
|
||||
|
||||
onTextChanged: {
|
||||
if (text !== SessionData.notepadContent) {
|
||||
SessionData.notepadContent = text;
|
||||
saveTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: (event) => {
|
||||
root.hide();
|
||||
event.accepted = true;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.notepadModalVisible) {
|
||||
Qt.callLater(() => {
|
||||
forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 32
|
||||
spacing: Theme.spacingL
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankActionButton {
|
||||
iconName: "save"
|
||||
iconSize: Theme.iconSize - 2
|
||||
iconColor: Theme.primary
|
||||
hoverColor: Theme.primaryHover
|
||||
onClicked: {
|
||||
console.log("Notepad: Opening save dialog, releasing modal focus");
|
||||
root.allowFocusOverride = true;
|
||||
root.shouldHaveFocus = false;
|
||||
fileDialogOpen = true;
|
||||
saveBrowser.open();
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Save to file"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceTextMedium
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankActionButton {
|
||||
iconName: "folder_open"
|
||||
iconSize: Theme.iconSize - 2
|
||||
iconColor: Theme.secondary
|
||||
hoverColor: Theme.secondaryHover
|
||||
onClicked: {
|
||||
console.log("Notepad: Opening load dialog, releasing modal focus");
|
||||
root.allowFocusOverride = true;
|
||||
root.shouldHaveFocus = false;
|
||||
fileDialogOpen = true;
|
||||
loadBrowser.open();
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Load file"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceTextMedium
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
height: 1
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: saveTimer.running ? "Auto-saving..." : "Auto-saved"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: saveTimer.running ? Theme.primary : Theme.surfaceTextMedium
|
||||
opacity: SessionData.notepadContent.length > 0 ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: saveTimer
|
||||
|
||||
interval: 1000
|
||||
repeat: false
|
||||
onTriggered: SessionData.saveSettings()
|
||||
}
|
||||
|
||||
FileBrowserModal {
|
||||
id: saveBrowser
|
||||
|
||||
browserTitle: "Save Notepad File"
|
||||
browserIcon: "save"
|
||||
browserType: "notepad_save"
|
||||
fileExtensions: ["*.txt", "*.*"]
|
||||
allowStacking: true
|
||||
saveMode: true
|
||||
defaultFileName: "note.txt"
|
||||
|
||||
onFileSelected: (path) => {
|
||||
fileDialogOpen = false;
|
||||
selectedFilePath = path;
|
||||
const content = textArea.text;
|
||||
if (content.length > 0) {
|
||||
writeFileProcess.command = ["sh", "-c", `echo '${content.replace(/'/g, "'\\''")}' > '${path}'`];
|
||||
writeFileProcess.running = true;
|
||||
}
|
||||
close();
|
||||
// Restore modal focus
|
||||
root.allowFocusOverride = false;
|
||||
root.shouldHaveFocus = Qt.binding(() => {
|
||||
return root.notepadModalVisible && !fileDialogOpen;
|
||||
});
|
||||
// Restore focus to TextArea after dialog closes
|
||||
Qt.callLater(() => {
|
||||
textArea.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
|
||||
onDialogClosed: {
|
||||
fileDialogOpen = false;
|
||||
// Restore modal focus
|
||||
root.allowFocusOverride = false;
|
||||
root.shouldHaveFocus = Qt.binding(() => {
|
||||
return root.notepadModalVisible && !fileDialogOpen;
|
||||
});
|
||||
// Restore focus to TextArea after dialog closes
|
||||
Qt.callLater(() => {
|
||||
textArea.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
|
||||
property string selectedFilePath: ""
|
||||
}
|
||||
|
||||
FileBrowserModal {
|
||||
id: loadBrowser
|
||||
|
||||
browserTitle: "Load Notepad File"
|
||||
browserIcon: "folder_open"
|
||||
browserType: "notepad_load"
|
||||
fileExtensions: ["*.txt", "*.*"]
|
||||
allowStacking: true
|
||||
|
||||
onFileSelected: (path) => {
|
||||
fileDialogOpen = false;
|
||||
// Clean the file path - remove file:// prefix if present
|
||||
var cleanPath = path.toString().replace(/^file:\/\//, '');
|
||||
// Extract filename from path
|
||||
var fileName = cleanPath.split('/').pop();
|
||||
currentFileName = fileName;
|
||||
console.log("Notepad: Loading file from path:", cleanPath);
|
||||
readFileProcess.command = ["cat", cleanPath];
|
||||
readFileProcess.running = true;
|
||||
close();
|
||||
// Restore modal focus
|
||||
root.allowFocusOverride = false;
|
||||
root.shouldHaveFocus = Qt.binding(() => {
|
||||
return root.notepadModalVisible && !fileDialogOpen;
|
||||
});
|
||||
// Restore focus to TextArea after dialog closes
|
||||
Qt.callLater(() => {
|
||||
textArea.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
|
||||
onDialogClosed: {
|
||||
fileDialogOpen = false;
|
||||
// Restore modal focus
|
||||
root.allowFocusOverride = false;
|
||||
root.shouldHaveFocus = Qt.binding(() => {
|
||||
return root.notepadModalVisible && !fileDialogOpen;
|
||||
});
|
||||
// Restore focus to TextArea after dialog closes
|
||||
Qt.callLater(() => {
|
||||
textArea.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: writeFileProcess
|
||||
|
||||
command: []
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode === 0)
|
||||
console.log("Notepad: File saved successfully");
|
||||
else
|
||||
console.warn("Notepad: Failed to save file, exit code:", exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: readFileProcess
|
||||
|
||||
command: []
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
console.log("Notepad: File content loaded, length:", text.length);
|
||||
textArea.text = text;
|
||||
SessionData.notepadContent = text;
|
||||
SessionData.saveSettings();
|
||||
console.log("Notepad: File loaded and saved to session");
|
||||
}
|
||||
}
|
||||
|
||||
onExited: (exitCode) => {
|
||||
console.log("Notepad: File read process exited with code:", exitCode);
|
||||
if (exitCode !== 0) {
|
||||
console.warn("Notepad: Failed to load file, exit code:", exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -151,6 +151,12 @@ Item {
|
||||
"text": "Keyboard Layout Name",
|
||||
"description": "Displays the active keyboard layout and allows switching",
|
||||
"icon": "keyboard",
|
||||
}, {
|
||||
"id": "notepadButton",
|
||||
"text": "Notepad",
|
||||
"description": "Quick access to notepad",
|
||||
"icon": "assignment",
|
||||
"enabled": true
|
||||
}]
|
||||
property var defaultLeftWidgets: [{
|
||||
"id": "launcherButton",
|
||||
|
||||
@@ -107,6 +107,12 @@ Item {
|
||||
"description": "Access to notifications and do not disturb",
|
||||
"icon": "notifications",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "notepadButton",
|
||||
"text": "Notepad",
|
||||
"description": "Quick access to notepad",
|
||||
"icon": "assignment",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "battery",
|
||||
"text": "Battery",
|
||||
@@ -419,9 +425,9 @@ Item {
|
||||
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets)
|
||||
|
||||
if (!SettingsData.topBarRightWidgets)
|
||||
SettingsData.setTopBarRightWidgets(
|
||||
defaultRightWidgets)["left""center""right"].forEach(
|
||||
sectionId => {
|
||||
SettingsData.setTopBarRightWidgets(defaultRightWidgets)
|
||||
|
||||
["left", "center", "right"].forEach(sectionId => {
|
||||
var widgets = []
|
||||
if (sectionId === "left")
|
||||
widgets = SettingsData.topBarLeftWidgets.slice()
|
||||
|
||||
67
Modules/TopBar/NotepadButton.qml
Normal file
67
Modules/TopBar/NotepadButton.qml
Normal file
@@ -0,0 +1,67 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool isActive: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property real widgetHeight: 30
|
||||
property real barHeight: 48
|
||||
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
|
||||
|
||||
signal clicked
|
||||
|
||||
width: notepadIcon.width + horizontalPadding * 2
|
||||
height: widgetHeight
|
||||
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
|
||||
color: {
|
||||
if (SettingsData.topBarNoBackground) return "transparent"
|
||||
const baseColor = notepadArea.containsMouse
|
||||
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
id: notepadIcon
|
||||
anchors.centerIn: parent
|
||||
name: "assignment"
|
||||
size: Theme.iconSize - 6
|
||||
color: notepadArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Theme.primary
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: SettingsData.topBarNoBackground ? 0 : 4
|
||||
anchors.topMargin: SettingsData.topBarNoBackground ? 0 : 4
|
||||
visible: SessionData.notepadContent.length > 0
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: notepadArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: {
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,6 +341,8 @@ PanelWindow {
|
||||
return true
|
||||
case "vpn":
|
||||
return true
|
||||
case "notepadButton":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -394,6 +396,8 @@ PanelWindow {
|
||||
return keyboardLayoutNameComponent
|
||||
case "vpn":
|
||||
return vpnComponent
|
||||
case "notepadButton":
|
||||
return notepadButtonComponent
|
||||
default:
|
||||
return null
|
||||
}
|
||||
@@ -1152,6 +1156,36 @@ PanelWindow {
|
||||
|
||||
KeyboardLayoutName {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notepadButtonComponent
|
||||
|
||||
NotepadButton {
|
||||
isActive: notepadModalLoader.item ? notepadModalLoader.item.visible : false
|
||||
widgetHeight: root.widgetHeight
|
||||
barHeight: root.effectiveBarHeight
|
||||
section: {
|
||||
if (parent && parent.parent === leftSection)
|
||||
return "left"
|
||||
if (parent && parent.parent === rightSection)
|
||||
return "right"
|
||||
if (parent && parent.parent === centerSection)
|
||||
return "center"
|
||||
return "right"
|
||||
}
|
||||
popupTarget: {
|
||||
notepadModalLoader.active = true
|
||||
return notepadModalLoader.item
|
||||
}
|
||||
parentScreen: root.screen
|
||||
onClicked: {
|
||||
notepadModalLoader.active = true
|
||||
if (notepadModalLoader.item) {
|
||||
notepadModalLoader.item.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ https://github.com/user-attachments/assets/5ad934bb-e7aa-4c04-8d40-149181bd2d29
|
||||
- **Dock** A dock with pinned apps support, recent apps support, and currently running application support.
|
||||
- **Control Center** A full control center with user profile information, network, bluetooth, audio input/output, display controls, and night mode automation.
|
||||
- **Lock Screen** Using quickshell's WlSessionLock
|
||||
- **Notepad** A simple text notepad/scratchpad with auto-save to session data and file export/import functionality.
|
||||
|
||||
**Features:**
|
||||
|
||||
@@ -299,6 +300,9 @@ binds {
|
||||
Mod+Comma hotkey-overlay-title="Settings" {
|
||||
spawn "qs" "-c" "dms" "ipc" "call" "settings" "toggle";
|
||||
}
|
||||
Mod+P hotkey-overlay-title="Notepad" {
|
||||
spawn "qs" "-c" "dms" "ipc" "call" "notepad" "toggle";
|
||||
}
|
||||
Super+Alt+L hotkey-overlay-title="Lock Screen" {
|
||||
spawn "qs" "-c" "dms" "ipc" "call" "lock" "lock";
|
||||
}
|
||||
@@ -358,6 +362,7 @@ bind = SUPER, V, exec, qs -c dms ipc call clipboard toggle
|
||||
bind = SUPER, M, exec, qs -c dms ipc call processlist toggle
|
||||
bind = SUPER, N, exec, qs -c dms ipc call notifications toggle
|
||||
bind = SUPER, comma, exec, qs -c dms ipc call settings toggle
|
||||
bind = SUPER, P, exec, qs -c dms ipc call notepad toggle
|
||||
bind = SUPERALT, L, exec, qs -c dms ipc call lock lock
|
||||
bind = SUPER, X, exec, qs -c dms ipc call powermenu toggle
|
||||
|
||||
@@ -389,6 +394,7 @@ qs -c dms ipc call audio mute
|
||||
# Launch applications
|
||||
```bash
|
||||
qs -c dms ipc call spotlight toggle
|
||||
qs -c dms ipc call notepad toggle
|
||||
qs -c dms ipc call processlist toggle
|
||||
qs -c dms ipc call powermenu toggle
|
||||
```
|
||||
|
||||
12
docs/IPC.md
12
docs/IPC.md
@@ -392,6 +392,14 @@ Power menu modal control for system power actions.
|
||||
- `close` - Hide power menu modal
|
||||
- `toggle` - Toggle power menu modal visibility
|
||||
|
||||
### Target: `notepad`
|
||||
Notepad/scratchpad modal control for quick note-taking.
|
||||
|
||||
**Functions:**
|
||||
- `open` - Show notepad modal
|
||||
- `close` - Hide notepad modal
|
||||
- `toggle` - Toggle notepad modal visibility
|
||||
|
||||
### Target: `file`
|
||||
File browser controls for selecting wallpapers and profile images.
|
||||
|
||||
@@ -422,6 +430,9 @@ qs -c dms ipc call processlist toggle
|
||||
# Show power menu
|
||||
qs -c dms ipc call powermenu toggle
|
||||
|
||||
# Open notepad
|
||||
qs -c dms ipc call notepad toggle
|
||||
|
||||
# Open file browsers
|
||||
qs -c dms ipc call file browse wallpaper
|
||||
qs -c dms ipc call file browse profile
|
||||
@@ -437,6 +448,7 @@ These IPC commands are designed to be used with window manager keybindings. Exam
|
||||
binds {
|
||||
Mod+Space { spawn "qs" "-c" "dms" "ipc" "call" "spotlight" "toggle"; }
|
||||
Mod+V { spawn "qs" "-c" "dms" "ipc" "call" "clipboard" "toggle"; }
|
||||
Mod+P { spawn "qs" "-c" "dms" "ipc" "call" "notepad" "toggle"; }
|
||||
Mod+X { spawn "qs" "-c" "dms" "ipc" "call" "powermenu" "toggle"; }
|
||||
XF86AudioRaiseVolume { spawn "qs" "-c" "dms" "ipc" "call" "audio" "increment" "3"; }
|
||||
XF86MonBrightnessUp { spawn "qs" "-c" "dms" "ipc" "call" "brightness" "increment" "5" ""; }
|
||||
|
||||
37
shell.qml
37
shell.qml
@@ -283,6 +283,16 @@ ShellRoot {
|
||||
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: notepadModalLoader
|
||||
|
||||
active: false
|
||||
|
||||
NotepadModal {
|
||||
id: notepadModal
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: powerMenuModalLoader
|
||||
|
||||
@@ -373,6 +383,33 @@ ShellRoot {
|
||||
target: "processlist"
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
notepadModalLoader.active = true
|
||||
if (notepadModalLoader.item)
|
||||
notepadModalLoader.item.show()
|
||||
|
||||
return "NOTEPAD_OPEN_SUCCESS"
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (notepadModalLoader.item)
|
||||
notepadModalLoader.item.hide()
|
||||
|
||||
return "NOTEPAD_CLOSE_SUCCESS"
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
notepadModalLoader.active = true
|
||||
if (notepadModalLoader.item)
|
||||
notepadModalLoader.item.toggle()
|
||||
|
||||
return "NOTEPAD_TOGGLE_SUCCESS"
|
||||
}
|
||||
|
||||
target: "notepad"
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: SettingsData.getFilteredScreens("toast")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user