forked from Shinonome/dots-hyprland
Merge branch 'end-4:main' into darkmode-button-feat
This commit is contained in:
@@ -203,7 +203,7 @@ Singleton {
|
|||||||
|
|
||||||
animation: QtObject {
|
animation: QtObject {
|
||||||
property QtObject elementMove: QtObject {
|
property QtObject elementMove: QtObject {
|
||||||
property int duration: 500
|
property int duration: animationCurves.expressiveDefaultSpatialDuration
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
property list<real> bezierCurve: animationCurves.expressiveDefaultSpatial
|
property list<real> bezierCurve: animationCurves.expressiveDefaultSpatial
|
||||||
property int velocity: 650
|
property int velocity: 650
|
||||||
@@ -249,7 +249,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
property QtObject elementMoveFast: QtObject {
|
property QtObject elementMoveFast: QtObject {
|
||||||
property int duration: 200
|
property int duration: animationCurves.expressiveEffectsDuration
|
||||||
property int type: Easing.BezierSpline
|
property int type: Easing.BezierSpline
|
||||||
property list<real> bezierCurve: animationCurves.expressiveEffects
|
property list<real> bezierCurve: animationCurves.expressiveEffects
|
||||||
property int velocity: 850
|
property int velocity: 850
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ Singleton {
|
|||||||
|
|
||||||
property QtObject windows: QtObject {
|
property QtObject windows: QtObject {
|
||||||
property bool showTitlebar: true // Client-side decoration for shell apps
|
property bool showTitlebar: true // Client-side decoration for shell apps
|
||||||
|
property bool centerTitle: true
|
||||||
}
|
}
|
||||||
|
|
||||||
property QtObject hacks: QtObject {
|
property QtObject hacks: QtObject {
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ Singleton {
|
|||||||
property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/switchwall.sh`)
|
property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/switchwall.sh`)
|
||||||
// Cleanup on init
|
// Cleanup on init
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Hyprland.dispatch(`exec mkdir -p '${shellConfig}'`)
|
Quickshell.execDetached(["bash", "-c", `mkdir -p '${shellConfig}'`])
|
||||||
Hyprland.dispatch(`exec mkdir -p '${favicons}'`)
|
Quickshell.execDetached(["bash", "-c", `mkdir -p '${favicons}'`])
|
||||||
Hyprland.dispatch(`exec rm -rf '${coverArt}'; mkdir -p '${coverArt}'`)
|
Quickshell.execDetached(["bash", "-c", `rm -rf '${coverArt}'; mkdir -p '${coverArt}'`])
|
||||||
Hyprland.dispatch(`exec rm -rf '${booruPreviews}'; mkdir -p '${booruPreviews}'`)
|
Quickshell.execDetached(["bash", "-c", `rm -rf '${booruPreviews}'; mkdir -p '${booruPreviews}'`])
|
||||||
Hyprland.dispatch(`exec mkdir -p '${booruDownloads}' && mkdir -p '${booruDownloadsNsfw}'`)
|
Quickshell.execDetached(["bash", "-c", `mkdir -p '${booruDownloads}' && mkdir -p '${booruDownloadsNsfw}'`])
|
||||||
Hyprland.dispatch(`exec rm -rf '${latexOutput}'; mkdir -p '${latexOutput}'`)
|
Quickshell.execDetached(["bash", "-c", `rm -rf '${latexOutput}'; mkdir -p '${latexOutput}'`])
|
||||||
Hyprland.dispatch(`exec rm -rf '${cliphistDecode}'; mkdir -p '${cliphistDecode}'`)
|
Quickshell.execDetached(["bash", "-c", `rm -rf '${cliphistDecode}'; mkdir -p '${cliphistDecode}'`])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import Qt.labs.platform
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
@@ -71,7 +72,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
Hyprland.dispatch(`exec bash -c "[ -f '${imageDecodeFilePath}' ] && rm -f '${imageDecodeFilePath}'"`)
|
Quickshell.execDetached(["bash", "-c", `[ -f '${imageDecodeFilePath}' ] && rm -f '${imageDecodeFilePath}'`])
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
property bool uniform: false
|
||||||
|
spacing: 10
|
||||||
|
uniformCellSizes: uniform
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import "root:/services/"
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets/"
|
||||||
|
import "root:/modules/common/functions/color_utils.js" as ColorUtils
|
||||||
|
import "root:/modules/common/functions/file_utils.js" as FileUtils
|
||||||
|
|
||||||
|
Flow {
|
||||||
|
id: root
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 2
|
||||||
|
property list<var> options: []
|
||||||
|
property string configOptionName: ""
|
||||||
|
property var currentValue: null
|
||||||
|
|
||||||
|
signal selected(var newValue)
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.options
|
||||||
|
delegate: SelectionGroupButton {
|
||||||
|
id: paletteButton
|
||||||
|
required property var modelData
|
||||||
|
required property int index
|
||||||
|
onYChanged: {
|
||||||
|
if (index === 0) {
|
||||||
|
paletteButton.leftmost = true
|
||||||
|
} else {
|
||||||
|
var prev = root.children[index - 1]
|
||||||
|
var thisIsOnNewLine = prev && prev.y !== paletteButton.y
|
||||||
|
paletteButton.leftmost = thisIsOnNewLine
|
||||||
|
prev.rightmost = thisIsOnNewLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leftmost: index === 0
|
||||||
|
rightmost: index === root.options.length - 1
|
||||||
|
buttonText: modelData.displayName;
|
||||||
|
toggled: root.currentValue === modelData.value
|
||||||
|
onClicked: {
|
||||||
|
root.selected(modelData.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ import QtQuick.Controls
|
|||||||
RippleButton {
|
RippleButton {
|
||||||
id: root
|
id: root
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: contentItem.implicitHeight + 8 * 2
|
||||||
|
onClicked: checked = !checked
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
spacing: 10
|
spacing: 10
|
||||||
@@ -14,13 +16,13 @@ RippleButton {
|
|||||||
id: labelWidget
|
id: labelWidget
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: root.text
|
text: root.text
|
||||||
font.pixelSize: Appearance.font.pixelSize.normal
|
font.pixelSize: Appearance.font.pixelSize.small
|
||||||
color: Appearance.colors.colOnSecondaryContainer
|
color: Appearance.colors.colOnSecondaryContainer
|
||||||
}
|
}
|
||||||
StyledSwitch {
|
StyledSwitch {
|
||||||
id: switchWidget
|
id: switchWidget
|
||||||
down: root.down
|
down: root.down
|
||||||
scale: 0.75
|
scale: 0.6
|
||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
checked: root.checked
|
checked: root.checked
|
||||||
onClicked: root.clicked()
|
onClicked: root.clicked()
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ Flickable {
|
|||||||
id: root
|
id: root
|
||||||
property real baseWidth: 500
|
property real baseWidth: 500
|
||||||
property bool forceWidth: false
|
property bool forceWidth: false
|
||||||
|
property real bottomContentPadding: 100
|
||||||
|
|
||||||
default property alias data: contentColumn.data
|
default property alias data: contentColumn.data
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
contentHeight: contentColumn.implicitHeight
|
contentHeight: contentColumn.implicitHeight + root.bottomContentPadding // Add some padding at the bottom
|
||||||
implicitWidth: contentColumn.implicitWidth
|
implicitWidth: contentColumn.implicitWidth
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@@ -20,7 +21,6 @@ Flickable {
|
|||||||
width: root.forceWidth ? root.baseWidth : Math.max(root.baseWidth, implicitWidth)
|
width: root.forceWidth ? root.baseWidth : Math.max(root.baseWidth, implicitWidth)
|
||||||
anchors {
|
anchors {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
bottom: parent.bottom
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
margins: 10
|
margins: 10
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: sectionContent
|
id: sectionContent
|
||||||
spacing: 4
|
spacing: 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets/"
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
property string title: ""
|
||||||
|
default property alias data: sectionContent.data
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 4
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
ContentSubsectionLabel {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.title && root.title.length > 0
|
||||||
|
text: root.title
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
id: sectionContent
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets/"
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Subsection"
|
||||||
|
color: Appearance.colors.colSubtext
|
||||||
|
Layout.leftMargin: 4
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import "root:/modules/common/functions/color_utils.js" as ColorUtils
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell.Io
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ GroupButton {
|
|||||||
colBackground: Appearance.colors.colLayer2
|
colBackground: Appearance.colors.colLayer2
|
||||||
toggled: Appearance.m3colors.darkmode === dark
|
toggled: Appearance.m3colors.darkmode === dark
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`)
|
Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} --mode ${dark ? "dark" : "light"} --noswitch`])
|
||||||
}
|
}
|
||||||
contentItem: Item {
|
contentItem: Item {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import "root:/modules/common"
|
||||||
|
import "root:/modules/common/functions/color_utils.js" as ColorUtils
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls.Material
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Material 3 styled TextArea (filled style)
|
||||||
|
* https://m3.material.io/components/text-fields/overview
|
||||||
|
* Note: We don't use NativeRendering because it makes the small placeholder text look weird
|
||||||
|
*/
|
||||||
|
TextArea {
|
||||||
|
id: root
|
||||||
|
Material.theme: Material.System
|
||||||
|
Material.accent: Appearance.m3colors.m3primary
|
||||||
|
Material.primary: Appearance.m3colors.m3primary
|
||||||
|
Material.background: Appearance.m3colors.m3surface
|
||||||
|
Material.foreground: Appearance.m3colors.m3onSurface
|
||||||
|
Material.containerStyle: Material.Filled
|
||||||
|
renderType: Text.QtRendering
|
||||||
|
|
||||||
|
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
|
||||||
|
selectionColor: Appearance.colors.colSecondaryContainer
|
||||||
|
placeholderTextColor: Appearance.m3colors.m3outline
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
implicitHeight: 56
|
||||||
|
color: Appearance.m3colors.m3surface
|
||||||
|
topLeftRadius: 4
|
||||||
|
topRightRadius: 4
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
height: 1
|
||||||
|
color: root.focus ? Appearance.m3colors.m3primary :
|
||||||
|
root.hovered ? Appearance.m3colors.m3outline : Appearance.m3colors.m3outlineVariant
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
font {
|
||||||
|
family: Appearance?.font.family.main ?? "sans-serif"
|
||||||
|
pixelSize: Appearance?.font.pixelSize.small ?? 15
|
||||||
|
hintingPreference: Font.PreferFullHinting
|
||||||
|
}
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
}
|
||||||
@@ -14,6 +14,12 @@ RippleButton {
|
|||||||
parent.expanded = !parent.expanded;
|
parent.expanded = !parent.expanded;
|
||||||
}
|
}
|
||||||
buttonRadius: Appearance.rounding.full
|
buttonRadius: Appearance.rounding.full
|
||||||
|
|
||||||
|
rotation: root.parent.expanded ? 0 : -180
|
||||||
|
Behavior on rotation {
|
||||||
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: MaterialSymbol {
|
contentItem: MaterialSymbol {
|
||||||
id: icon
|
id: icon
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|||||||
@@ -94,12 +94,6 @@ Item { // Notification item area
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressAndHold: (mouse) => {
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(notificationObject.body)}'`)
|
|
||||||
notificationSummaryText.text = String.format(qsTr("{0} (copied)"), notificationObject.summary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onDraggingChanged: () => {
|
onDraggingChanged: () => {
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
root.qmlParent.dragIndex = root.index ?? root.parent.children.indexOf(root);
|
root.qmlParent.dragIndex = root.index ?? root.parent.children.indexOf(root);
|
||||||
@@ -291,7 +285,7 @@ Item { // Notification item area
|
|||||||
(contentItem.implicitWidth + leftPadding + rightPadding)
|
(contentItem.implicitWidth + leftPadding + rightPadding)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(notificationObject.body)}'`)
|
Quickshell.clipboardText = notificationObject.body
|
||||||
copyIcon.text = "inventory"
|
copyIcon.text = "inventory"
|
||||||
copyIconTimer.restart()
|
copyIconTimer.restart()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,7 @@ Scope {
|
|||||||
visible: GlobalStates.overviewOpen
|
visible: GlobalStates.overviewOpen
|
||||||
anchors {
|
anchors {
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
top: !ConfigOptions.bar.bottom ? parent.top : undefined
|
top: parent.top
|
||||||
bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: (event) => {
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ Item {
|
|||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.draggingTargetWorkspace === -1) {
|
if (root.draggingTargetWorkspace === -1) {
|
||||||
// Hyprland.dispatch(`exec qs ipc call overview close`)
|
|
||||||
GlobalStates.overviewOpen = false
|
GlobalStates.overviewOpen = false
|
||||||
Hyprland.dispatch(`workspace ${workspaceValue}`)
|
Hyprland.dispatch(`workspace ${workspaceValue}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,7 +303,9 @@ Item { // Wrapper
|
|||||||
clickActionName: "",
|
clickActionName: "",
|
||||||
type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`,
|
type: `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`);
|
Quickshell.execDetached(
|
||||||
|
["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
@@ -318,7 +320,7 @@ Item { // Wrapper
|
|||||||
clickActionName: "",
|
clickActionName: "",
|
||||||
type: "Emoji",
|
type: "Emoji",
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(entry.match(/^\s*(\S+)/)?.[1])}'`);
|
Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
@@ -334,7 +336,7 @@ Item { // Wrapper
|
|||||||
fontType: "monospace",
|
fontType: "monospace",
|
||||||
materialSymbol: 'calculate',
|
materialSymbol: 'calculate',
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(root.mathResult)}'`)
|
Quickshell.clipboardText = root.mathResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const commandResultObject = {
|
const commandResultObject = {
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ Scope {
|
|||||||
id: sessionTaskManager
|
id: sessionTaskManager
|
||||||
buttonIcon: "browse_activity"
|
buttonIcon: "browse_activity"
|
||||||
buttonText: qsTr("Task Manager")
|
buttonText: qsTr("Task Manager")
|
||||||
onClicked: { Hyprland.dispatch(`exec ${ConfigOptions.apps.taskManager}`); sessionRoot.hide() }
|
onClicked: { Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.taskManager}`]); sessionRoot.hide() }
|
||||||
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
||||||
KeyNavigation.left: sessionLogout
|
KeyNavigation.left: sessionLogout
|
||||||
KeyNavigation.down: sessionFirmwareReboot
|
KeyNavigation.down: sessionFirmwareReboot
|
||||||
@@ -131,7 +131,7 @@ Scope {
|
|||||||
id: sessionHibernate
|
id: sessionHibernate
|
||||||
buttonIcon: "downloading"
|
buttonIcon: "downloading"
|
||||||
buttonText: qsTr("Hibernate")
|
buttonText: qsTr("Hibernate")
|
||||||
onClicked: { Hyprland.dispatch("exec systemctl hibernate || loginctl hibernate"); sessionRoot.hide() }
|
onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl hibernate || loginctl hibernate`]); sessionRoot.hide() }
|
||||||
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
||||||
KeyNavigation.up: sessionLock
|
KeyNavigation.up: sessionLock
|
||||||
KeyNavigation.right: sessionShutdown
|
KeyNavigation.right: sessionShutdown
|
||||||
@@ -140,7 +140,7 @@ Scope {
|
|||||||
id: sessionShutdown
|
id: sessionShutdown
|
||||||
buttonIcon: "power_settings_new"
|
buttonIcon: "power_settings_new"
|
||||||
buttonText: qsTr("Shutdown")
|
buttonText: qsTr("Shutdown")
|
||||||
onClicked: { Hyprland.dispatch("exec systemctl poweroff || loginctl poweroff"); sessionRoot.hide() }
|
onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() }
|
||||||
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
||||||
KeyNavigation.left: sessionHibernate
|
KeyNavigation.left: sessionHibernate
|
||||||
KeyNavigation.right: sessionReboot
|
KeyNavigation.right: sessionReboot
|
||||||
@@ -150,7 +150,7 @@ Scope {
|
|||||||
id: sessionReboot
|
id: sessionReboot
|
||||||
buttonIcon: "restart_alt"
|
buttonIcon: "restart_alt"
|
||||||
buttonText: qsTr("Reboot")
|
buttonText: qsTr("Reboot")
|
||||||
onClicked: { Hyprland.dispatch("exec reboot || loginctl reboot"); sessionRoot.hide() }
|
onClicked: { Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() }
|
||||||
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
||||||
KeyNavigation.left: sessionShutdown
|
KeyNavigation.left: sessionShutdown
|
||||||
KeyNavigation.right: sessionFirmwareReboot
|
KeyNavigation.right: sessionFirmwareReboot
|
||||||
@@ -160,7 +160,7 @@ Scope {
|
|||||||
id: sessionFirmwareReboot
|
id: sessionFirmwareReboot
|
||||||
buttonIcon: "settings_applications"
|
buttonIcon: "settings_applications"
|
||||||
buttonText: qsTr("Reboot to firmware settings")
|
buttonText: qsTr("Reboot to firmware settings")
|
||||||
onClicked: { Hyprland.dispatch("exec systemctl reboot --firmware-setup || loginctl reboot --firmware-setup"); sessionRoot.hide() }
|
onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() }
|
||||||
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
|
||||||
KeyNavigation.up: sessionTaskManager
|
KeyNavigation.up: sessionTaskManager
|
||||||
KeyNavigation.left: sessionReboot
|
KeyNavigation.left: sessionReboot
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import "root:/services/"
|
|
||||||
import "root:/modules/common/"
|
|
||||||
import "root:/modules/common/widgets/"
|
|
||||||
|
|
||||||
ContentPage {
|
|
||||||
ContentSection {
|
|
||||||
title: "Policies"
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
spacing: 15
|
|
||||||
ColumnLayout { // Weeb policy
|
|
||||||
StyledText {
|
|
||||||
text: "Weeb"
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
|
||||||
ButtonGroup {
|
|
||||||
id: weebPolicyBtnGroup
|
|
||||||
property int selectedPolicy: ConfigOptions.policies.weeb
|
|
||||||
spacing: 2
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 0
|
|
||||||
leftmost: true
|
|
||||||
buttonText: "No"
|
|
||||||
toggled: (weebPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.weeb", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 1
|
|
||||||
buttonText: "Yes"
|
|
||||||
toggled: (weebPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.weeb", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 2
|
|
||||||
rightmost: true
|
|
||||||
buttonText: "Closet"
|
|
||||||
toggled: (weebPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.weeb", value);
|
|
||||||
}
|
|
||||||
StyledToolTip {
|
|
||||||
content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ColumnLayout { // AI policy
|
|
||||||
StyledText {
|
|
||||||
text: "AI"
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
|
||||||
ButtonGroup {
|
|
||||||
id: aiPolicyBtnGroup
|
|
||||||
property int selectedPolicy: ConfigOptions.policies.ai
|
|
||||||
spacing: 2
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 0
|
|
||||||
leftmost: true
|
|
||||||
buttonText: "No"
|
|
||||||
toggled: (aiPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.ai", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 1
|
|
||||||
buttonText: "Yes"
|
|
||||||
toggled: (aiPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.ai", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 2
|
|
||||||
rightmost: true
|
|
||||||
buttonText: "Local only"
|
|
||||||
toggled: (aiPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.ai", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import "root:/services/"
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets/"
|
||||||
|
|
||||||
|
ContentPage {
|
||||||
|
forceWidth: true
|
||||||
|
ContentSection {
|
||||||
|
title: "Policies"
|
||||||
|
|
||||||
|
ConfigRow {
|
||||||
|
ColumnLayout { // Weeb policy
|
||||||
|
ContentSubsectionLabel {
|
||||||
|
text: "Weeb"
|
||||||
|
}
|
||||||
|
ConfigSelectionArray {
|
||||||
|
currentValue: ConfigOptions.policies.weeb
|
||||||
|
configOptionName: "policies.weeb"
|
||||||
|
onSelected: (newValue) => {
|
||||||
|
ConfigLoader.setConfigValueAndSave("policies.weeb", newValue);
|
||||||
|
}
|
||||||
|
options: [
|
||||||
|
{ displayName: "No", value: 0 },
|
||||||
|
{ displayName: "Yes", value: 1 },
|
||||||
|
{ displayName: "Closet", value: 2 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout { // AI policy
|
||||||
|
ContentSubsectionLabel {
|
||||||
|
text: "AI"
|
||||||
|
}
|
||||||
|
ConfigSelectionArray {
|
||||||
|
currentValue: ConfigOptions.policies.ai
|
||||||
|
configOptionName: "policies.ai"
|
||||||
|
onSelected: (newValue) => {
|
||||||
|
ConfigLoader.setConfigValueAndSave("policies.ai", newValue);
|
||||||
|
}
|
||||||
|
options: [
|
||||||
|
{ displayName: "No", value: 0 },
|
||||||
|
{ displayName: "Yes", value: 1 },
|
||||||
|
{ displayName: "Local only", value: 2 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContentSection {
|
||||||
|
title: "Audio"
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Earbang protection"
|
||||||
|
checked: ConfigOptions.audio.protection.enable
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked);
|
||||||
|
}
|
||||||
|
StyledToolTip {
|
||||||
|
content: "Prevents abrupt increments and restricts volume limit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContentSection {
|
||||||
|
title: "AI"
|
||||||
|
MaterialTextField {
|
||||||
|
id: systemPromptField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
placeholderText: "System prompt"
|
||||||
|
text: ConfigOptions.ai.systemPrompt
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
onTextChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSection {
|
||||||
|
title: "Bar"
|
||||||
|
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Appearance"
|
||||||
|
ConfigRow {
|
||||||
|
uniform: true
|
||||||
|
ConfigSwitch {
|
||||||
|
text: 'Borderless'
|
||||||
|
checked: ConfigOptions.bar.borderless
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("bar.borderless", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigSwitch {
|
||||||
|
text: 'Show background'
|
||||||
|
checked: ConfigOptions.bar.showBackground
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("bar.showBackground", checked);
|
||||||
|
}
|
||||||
|
StyledToolTip {
|
||||||
|
content: "Note: turning off can hurt readability"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Buttons"
|
||||||
|
ConfigRow {
|
||||||
|
uniform: true
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Screen snip"
|
||||||
|
checked: ConfigOptions.bar.utilButtons.showScreenSnip
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showScreenSnip", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Color picker"
|
||||||
|
checked: ConfigOptions.bar.utilButtons.showColorPicker
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showColorPicker", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigRow {
|
||||||
|
uniform: true
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Mic toggle"
|
||||||
|
checked: ConfigOptions.bar.utilButtons.showMicToggle
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showMicToggle", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Keyboard toggle"
|
||||||
|
checked: ConfigOptions.bar.utilButtons.showKeyboardToggle
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showKeyboardToggle", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
import Quickshell.Hyprland
|
|
||||||
import "root:/services/"
|
|
||||||
import "root:/modules/common/"
|
|
||||||
import "root:/modules/common/widgets/"
|
|
||||||
import "root:/modules/common/functions/color_utils.js" as ColorUtils
|
|
||||||
import "root:/modules/common/functions/file_utils.js" as FileUtils
|
|
||||||
|
|
||||||
ContentPage {
|
|
||||||
baseWidth: lightDarkButtonGroup.implicitWidth
|
|
||||||
forceWidth: true
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: konachanWallProc
|
|
||||||
property string status: ""
|
|
||||||
command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)]
|
|
||||||
stdout: SplitParser {
|
|
||||||
onRead: data => {
|
|
||||||
console.log(`Konachan wall proc output: ${data}`);
|
|
||||||
konachanWallProc.status = data.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentSection {
|
|
||||||
title: "Colors & Wallpaper"
|
|
||||||
|
|
||||||
// Light/Dark mode preference
|
|
||||||
ButtonGroup {
|
|
||||||
id: lightDarkButtonGroup
|
|
||||||
Layout.fillWidth: true
|
|
||||||
LightDarkPreferenceButton {
|
|
||||||
dark: false
|
|
||||||
}
|
|
||||||
LightDarkPreferenceButton {
|
|
||||||
dark: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material palette selection
|
|
||||||
StyledText {
|
|
||||||
text: "Material palette"
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
|
||||||
Flow {
|
|
||||||
id: paletteFlow
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 2
|
|
||||||
property list<var> palettes: [
|
|
||||||
{"value": "auto", "displayName": "Auto"},
|
|
||||||
{"value": "scheme-content", "displayName": "Content"},
|
|
||||||
{"value": "scheme-expressive", "displayName": "Expressive"},
|
|
||||||
{"value": "scheme-fidelity", "displayName": "Fidelty"},
|
|
||||||
{"value": "scheme-fruit-salad", "displayName": "Fruit Salad"},
|
|
||||||
{"value": "scheme-monochrome", "displayName": "Monochrome"},
|
|
||||||
{"value": "scheme-neutral", "displayName": "Neutral"},
|
|
||||||
{"value": "scheme-rainbow", "displayName": "Rainbow"},
|
|
||||||
{"value": "scheme-tonal-spot", "displayName": "Tonal Spot"},
|
|
||||||
]
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: paletteFlow.palettes
|
|
||||||
delegate: SelectionGroupButton {
|
|
||||||
id: paletteButton
|
|
||||||
required property var modelData
|
|
||||||
required property int index
|
|
||||||
onYChanged: {
|
|
||||||
if (index === 0) {
|
|
||||||
paletteButton.leftmost = true
|
|
||||||
} else {
|
|
||||||
var prev = paletteFlow.children[index - 1]
|
|
||||||
var thisIsOnNewLine = prev && prev.y !== paletteButton.y
|
|
||||||
paletteButton.leftmost = thisIsOnNewLine
|
|
||||||
prev.rightmost = thisIsOnNewLine
|
|
||||||
}
|
|
||||||
}
|
|
||||||
leftmost: index === 0
|
|
||||||
rightmost: index === paletteFlow.palettes.length - 1
|
|
||||||
buttonText: modelData.displayName;
|
|
||||||
toggled: ConfigOptions.appearance.palette.type === modelData.value
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("appearance.palette.type", modelData.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wallpaper selection
|
|
||||||
StyledText {
|
|
||||||
text: "Wallpaper"
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
RippleButtonWithIcon {
|
|
||||||
id: rndWallBtn
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
buttonRadius: Appearance.rounding.small
|
|
||||||
materialIcon: "wallpaper"
|
|
||||||
mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan"
|
|
||||||
onClicked: {
|
|
||||||
console.log(konachanWallProc.command.join(" "))
|
|
||||||
konachanWallProc.running = true;
|
|
||||||
}
|
|
||||||
StyledToolTip {
|
|
||||||
content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RippleButtonWithIcon {
|
|
||||||
materialIcon: "wallpaper"
|
|
||||||
StyledToolTip {
|
|
||||||
content: "Pick wallpaper image on your system"
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`)
|
|
||||||
}
|
|
||||||
mainContentComponent: Component {
|
|
||||||
RowLayout {
|
|
||||||
spacing: 10
|
|
||||||
StyledText {
|
|
||||||
font.pixelSize: Appearance.font.pixelSize.small
|
|
||||||
text: "Choose file"
|
|
||||||
color: Appearance.colors.colOnSecondaryContainer
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
spacing: 3
|
|
||||||
KeyboardKey {
|
|
||||||
key: "Ctrl"
|
|
||||||
}
|
|
||||||
KeyboardKey {
|
|
||||||
key: ""
|
|
||||||
}
|
|
||||||
StyledText {
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
text: "+"
|
|
||||||
}
|
|
||||||
KeyboardKey {
|
|
||||||
key: "T"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
text: "Change any time later with /dark, /light, /img in the launcher"
|
|
||||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentSection {
|
|
||||||
title: "Shell style"
|
|
||||||
|
|
||||||
ColumnLayout { // Fake screen rounding
|
|
||||||
StyledText {
|
|
||||||
text: "Fake screen rounding"
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
|
||||||
ButtonGroup {
|
|
||||||
id: fakeScreenRoundingButtonGroup
|
|
||||||
property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding
|
|
||||||
spacing: 2
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 0
|
|
||||||
leftmost: true
|
|
||||||
buttonText: "No"
|
|
||||||
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 1
|
|
||||||
buttonText: "Yes"
|
|
||||||
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 2
|
|
||||||
rightmost: true
|
|
||||||
buttonText: "When not fullscreen"
|
|
||||||
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigSwitch {
|
|
||||||
text: "Transparency"
|
|
||||||
checked: ConfigOptions.appearance.transparency
|
|
||||||
onClicked: checked = !checked;
|
|
||||||
onCheckedChanged: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("appearance.transparency", checked);
|
|
||||||
}
|
|
||||||
StyledToolTip {
|
|
||||||
content: "Might look ass. Unsupported."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentSection {
|
|
||||||
title: "Shell windows"
|
|
||||||
|
|
||||||
ConfigSwitch {
|
|
||||||
text: "Title bar"
|
|
||||||
checked: ConfigOptions.windows.showTitlebar
|
|
||||||
onClicked: checked = !checked;
|
|
||||||
onCheckedChanged: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import "root:/services/"
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets/"
|
||||||
|
import "root:/modules/common/functions/color_utils.js" as ColorUtils
|
||||||
|
import "root:/modules/common/functions/file_utils.js" as FileUtils
|
||||||
|
|
||||||
|
ContentPage {
|
||||||
|
baseWidth: lightDarkButtonGroup.implicitWidth
|
||||||
|
forceWidth: true
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: konachanWallProc
|
||||||
|
property string status: ""
|
||||||
|
command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/colors/random_konachan_wall.sh`)]
|
||||||
|
stdout: SplitParser {
|
||||||
|
onRead: data => {
|
||||||
|
console.log(`Konachan wall proc output: ${data}`);
|
||||||
|
konachanWallProc.status = data.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSection {
|
||||||
|
title: "Colors & Wallpaper"
|
||||||
|
|
||||||
|
// Light/Dark mode preference
|
||||||
|
ButtonGroup {
|
||||||
|
id: lightDarkButtonGroup
|
||||||
|
Layout.fillWidth: true
|
||||||
|
LightDarkPreferenceButton {
|
||||||
|
dark: false
|
||||||
|
}
|
||||||
|
LightDarkPreferenceButton {
|
||||||
|
dark: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Material palette selection
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Material palette"
|
||||||
|
ConfigSelectionArray {
|
||||||
|
currentValue: ConfigOptions.appearance.palette.type
|
||||||
|
configOptionName: "appearance.palette.type"
|
||||||
|
onSelected: (newValue) => {
|
||||||
|
ConfigLoader.setConfigValueAndSave("appearance.palette.type", newValue);
|
||||||
|
}
|
||||||
|
options: [
|
||||||
|
{"value": "auto", "displayName": "Auto"},
|
||||||
|
{"value": "scheme-content", "displayName": "Content"},
|
||||||
|
{"value": "scheme-expressive", "displayName": "Expressive"},
|
||||||
|
{"value": "scheme-fidelity", "displayName": "Fidelity"},
|
||||||
|
{"value": "scheme-fruit-salad", "displayName": "Fruit Salad"},
|
||||||
|
{"value": "scheme-monochrome", "displayName": "Monochrome"},
|
||||||
|
{"value": "scheme-neutral", "displayName": "Neutral"},
|
||||||
|
{"value": "scheme-rainbow", "displayName": "Rainbow"},
|
||||||
|
{"value": "scheme-tonal-spot", "displayName": "Tonal Spot"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Wallpaper selection
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Wallpaper"
|
||||||
|
RowLayout {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
RippleButtonWithIcon {
|
||||||
|
id: rndWallBtn
|
||||||
|
buttonRadius: Appearance.rounding.small
|
||||||
|
materialIcon: "wallpaper"
|
||||||
|
mainText: konachanWallProc.running ? "Be patient..." : "Random: Konachan"
|
||||||
|
onClicked: {
|
||||||
|
console.log(konachanWallProc.command.join(" "))
|
||||||
|
konachanWallProc.running = true;
|
||||||
|
}
|
||||||
|
StyledToolTip {
|
||||||
|
content: "Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RippleButtonWithIcon {
|
||||||
|
materialIcon: "wallpaper"
|
||||||
|
StyledToolTip {
|
||||||
|
content: "Pick wallpaper image on your system"
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
Quickshell.execDetached(`${Directories.wallpaperSwitchScriptPath}`)
|
||||||
|
}
|
||||||
|
mainContentComponent: Component {
|
||||||
|
RowLayout {
|
||||||
|
spacing: 10
|
||||||
|
StyledText {
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.small
|
||||||
|
text: "Choose file"
|
||||||
|
color: Appearance.colors.colOnSecondaryContainer
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
spacing: 3
|
||||||
|
KeyboardKey {
|
||||||
|
key: "Ctrl"
|
||||||
|
}
|
||||||
|
KeyboardKey {
|
||||||
|
key: ""
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: "+"
|
||||||
|
}
|
||||||
|
KeyboardKey {
|
||||||
|
key: "T"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.topMargin: 5
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: "Alternatively use /dark, /light, /img in the launcher"
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||||
|
color: Appearance.colors.colSubtext
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSection {
|
||||||
|
title: "Decorations & Effects"
|
||||||
|
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Transparency"
|
||||||
|
|
||||||
|
ConfigRow {
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Enable"
|
||||||
|
checked: ConfigOptions.appearance.transparency
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("appearance.transparency", checked);
|
||||||
|
}
|
||||||
|
StyledToolTip {
|
||||||
|
content: "Might look ass. Unsupported."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Fake screen rounding"
|
||||||
|
|
||||||
|
ButtonGroup {
|
||||||
|
id: fakeScreenRoundingButtonGroup
|
||||||
|
property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding
|
||||||
|
spacing: 2
|
||||||
|
SelectionGroupButton {
|
||||||
|
property int value: 0
|
||||||
|
leftmost: true
|
||||||
|
buttonText: "No"
|
||||||
|
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
||||||
|
onClicked: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectionGroupButton {
|
||||||
|
property int value: 1
|
||||||
|
buttonText: "Yes"
|
||||||
|
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
||||||
|
onClicked: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectionGroupButton {
|
||||||
|
property int value: 2
|
||||||
|
rightmost: true
|
||||||
|
buttonText: "When not fullscreen"
|
||||||
|
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
||||||
|
onClicked: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSubsection {
|
||||||
|
title: "Shell windows"
|
||||||
|
|
||||||
|
ConfigRow {
|
||||||
|
uniform: true
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Title bar"
|
||||||
|
checked: ConfigOptions.windows.showTitlebar
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigSwitch {
|
||||||
|
text: "Center title"
|
||||||
|
checked: ConfigOptions.windows.centerTitle
|
||||||
|
onCheckedChanged: {
|
||||||
|
ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -185,7 +185,7 @@ Rectangle {
|
|||||||
buttonIcon: activated ? "inventory" : "content_copy"
|
buttonIcon: activated ? "inventory" : "content_copy"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(root.messageData?.content)}'`)
|
Quickshell.clipboardText = root.messageData?.content
|
||||||
copyButton.activated = true
|
copyButton.activated = true
|
||||||
copyIconTimer.restart()
|
copyIconTimer.restart()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ ColumnLayout {
|
|||||||
buttonIcon: activated ? "inventory" : "content_copy"
|
buttonIcon: activated ? "inventory" : "content_copy"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(segmentContent)}'`)
|
Quickshell.clipboardText = segmentContent
|
||||||
copyCodeButton.activated = true
|
copyCodeButton.activated = true
|
||||||
copyIconTimer.restart()
|
copyIconTimer.restart()
|
||||||
}
|
}
|
||||||
@@ -96,8 +96,10 @@ ColumnLayout {
|
|||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const downloadPath = FileUtils.trimFileProtocol(Directories.downloads)
|
const downloadPath = FileUtils.trimFileProtocol(Directories.downloads)
|
||||||
Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(segmentContent)}' > '${downloadPath}/code.${segmentLang || "txt"}'`)
|
Quickshell.execDetached(["bash", "-c",
|
||||||
Hyprland.dispatch(`exec notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}' -a Shell`)
|
`echo '${StringUtils.shellSingleQuoteEscape(segmentContent)}' > '${downloadPath}/code.${segmentLang || "txt"}'`
|
||||||
|
])
|
||||||
|
Quickshell.execDetached(["bash", "-c", `notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}' -a Shell`])
|
||||||
saveCodeButton.activated = true
|
saveCodeButton.activated = true
|
||||||
saveIconTimer.restart()
|
saveIconTimer.restart()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,9 @@ Button {
|
|||||||
buttonText: qsTr("Download")
|
buttonText: qsTr("Download")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.showActions = false
|
root.showActions = false
|
||||||
Hyprland.dispatch(`exec curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${qsTr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'`)
|
Quickshell.execDetached(["bash", "-c",
|
||||||
|
`curl '${root.imageData.file_url}' -o '${root.imageData.is_nsfw ? root.nsfwPath : root.downloadPath}/${root.fileName}' && notify-send '${qsTr("Download complete")}' '${root.downloadPath}/${root.fileName}' -a 'Shell'`
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ Scope {
|
|||||||
buttonIcon: "settings"
|
buttonIcon: "settings"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Hyprland.dispatch("global quickshell:sidebarRightClose")
|
Hyprland.dispatch("global quickshell:sidebarRightClose")
|
||||||
Hyprland.dispatch(`exec qs -p '${root.settingsQmlPath}'`)
|
Quickshell.execDetached(["qs", "-p", root.settingsQmlPath])
|
||||||
}
|
}
|
||||||
StyledToolTip {
|
StyledToolTip {
|
||||||
content: qsTr("Settings")
|
content: qsTr("Settings")
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ QuickToggleButton {
|
|||||||
toggleBluetooth.running = true
|
toggleBluetooth.running = true
|
||||||
}
|
}
|
||||||
altAction: () => {
|
altAction: () => {
|
||||||
Hyprland.dispatch(`exec ${ConfigOptions.apps.bluetooth}`)
|
Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.bluetooth}`])
|
||||||
Hyprland.dispatch("global quickshell:sidebarRightClose")
|
Hyprland.dispatch("global quickshell:sidebarRightClose")
|
||||||
}
|
}
|
||||||
Process {
|
Process {
|
||||||
id: toggleBluetooth
|
id: toggleBluetooth
|
||||||
|
|||||||
@@ -6,20 +6,27 @@ import Quickshell.Io
|
|||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
QuickToggleButton {
|
QuickToggleButton {
|
||||||
property bool enabled: false
|
id: root
|
||||||
buttonIcon: "gamepad"
|
buttonIcon: "gamepad"
|
||||||
toggled: enabled
|
toggled: toggled
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
enabled = !enabled
|
root.toggled = !root.toggled
|
||||||
if (enabled) {
|
if (root.toggled) {
|
||||||
// gameModeOn.running = true
|
Quickshell.execDetached(["bash", "-c", `hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`])
|
||||||
Hyprland.dispatch(`exec hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`)
|
|
||||||
} else {
|
} else {
|
||||||
Hyprland.dispatch("exec hyprctl reload")
|
Quickshell.execDetached(["hyprctl", "reload"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Process {
|
||||||
|
id: fetchActiveState
|
||||||
|
running: true
|
||||||
|
command: ["bash", "-c", `test "$(hyprctl getoption animations:enabled -j | jq ".int")" -ne 0`]
|
||||||
|
onExited: (exitCode, exitStatus) => {
|
||||||
|
console.log("Game mode toggle exited with code:", exitCode, "and status:", exitStatus)
|
||||||
|
root.toggled = exitCode !== 0 // Inverted because enabled = nonzero exit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledToolTip {
|
StyledToolTip {
|
||||||
content: qsTr("Game mode")
|
content: qsTr("Game mode")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ QuickToggleButton {
|
|||||||
toggleNetwork.running = true
|
toggleNetwork.running = true
|
||||||
}
|
}
|
||||||
altAction: () => {
|
altAction: () => {
|
||||||
Hyprland.dispatch(`exec ${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`)
|
Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`])
|
||||||
Hyprland.dispatch("global quickshell:sidebarRightClose")
|
Hyprland.dispatch("global quickshell:sidebarRightClose")
|
||||||
}
|
}
|
||||||
Process {
|
Process {
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ Singleton {
|
|||||||
property bool isCriticalAndNotCharging: isCritical && !isCharging
|
property bool isCriticalAndNotCharging: isCritical && !isCharging
|
||||||
|
|
||||||
onIsLowAndNotChargingChanged: {
|
onIsLowAndNotChargingChanged: {
|
||||||
if (available && isLowAndNotCharging) Hyprland.dispatch(`exec notify-send "Low battery" "Consider plugging in your device" -u critical -a "Shell"`)
|
if (available && isLowAndNotCharging)
|
||||||
|
Quickshell.execDetached(["bash", "-c", `notify-send "Low battery" "Consider plugging in your device" -u critical -a "Shell"`]);
|
||||||
}
|
}
|
||||||
|
|
||||||
onIsCriticalAndNotChargingChanged: {
|
onIsCriticalAndNotChargingChanged: {
|
||||||
if (available && isCriticalAndNotCharging) Hyprland.dispatch(`exec notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`)
|
if (available && isCriticalAndNotCharging)
|
||||||
|
Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,8 @@ Singleton {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("[ConfigLoader] Error reading file:", e);
|
console.error("[ConfigLoader] Error reading file:", e);
|
||||||
console.log("[ConfigLoader] File content was:", fileContent);
|
console.log("[ConfigLoader] File content was:", fileContent);
|
||||||
Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`)
|
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ Singleton {
|
|||||||
|
|
||||||
function saveConfig() {
|
function saveConfig() {
|
||||||
const plainConfig = ObjectUtils.toPlainObject(ConfigOptions)
|
const plainConfig = ObjectUtils.toPlainObject(ConfigOptions)
|
||||||
Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${root.filePath}'`)
|
Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${FileUtils.trimFileProtocol(root.filePath)}'`])
|
||||||
}
|
}
|
||||||
|
|
||||||
function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) {
|
function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) {
|
||||||
@@ -105,7 +104,7 @@ Singleton {
|
|||||||
} else {
|
} else {
|
||||||
root.applyConfig(configFileView.text())
|
root.applyConfig(configFileView.text())
|
||||||
if (!root.preventNextNotification) {
|
if (!root.preventNextNotification) {
|
||||||
// Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`)
|
// Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration reloaded")}' '${root.filePath}'`])
|
||||||
} else {
|
} else {
|
||||||
root.preventNextNotification = false;
|
root.preventNextNotification = false;
|
||||||
}
|
}
|
||||||
@@ -129,9 +128,9 @@ Singleton {
|
|||||||
if(error == FileViewError.FileNotFound) {
|
if(error == FileViewError.FileNotFound) {
|
||||||
console.log("[ConfigLoader] File not found, creating new file.")
|
console.log("[ConfigLoader] File not found, creating new file.")
|
||||||
root.saveConfig()
|
root.saveConfig()
|
||||||
Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration created")}" "${root.filePath}"`)
|
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration created")}' '${root.filePath}'`])
|
||||||
} else {
|
} else {
|
||||||
Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`)
|
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function enableNextTime() {
|
function enableNextTime() {
|
||||||
Hyprland.dispatch(`exec rm -f '${root.firstRunFilePath}'`)
|
Quickshell.execDetached(["rm", "-f", root.firstRunFilePath])
|
||||||
}
|
}
|
||||||
function disableNextTime() {
|
function disableNextTime() {
|
||||||
Hyprland.dispatch(`exec echo '${root.firstRunFileContent}' > '${root.firstRunFilePath}'`)
|
Quickshell.execDetached(["bash", "-c", `echo '${root.firstRunFileContent}' > '${root.firstRunFilePath}'`])
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFirstRun() {
|
function handleFirstRun() {
|
||||||
Hyprland.dispatch(`exec swww query | grep 'image' || '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`)
|
Quickshell.execDetached(["bash", "-c", `swww query | grep 'image' || '${Directories.wallpaperSwitchScriptPath}' '${root.defaultWallpaperPath}'`])
|
||||||
Hyprland.dispatch(`exec qs -p '${root.welcomeQmlPath}'`)
|
Quickshell.execDetached(["bash", "-c", `qs -p '${root.welcomeQmlPath}'`])
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
|
|||||||
@@ -20,23 +20,36 @@ Singleton {
|
|||||||
|
|
||||||
function releaseAllKeys() {
|
function releaseAllKeys() {
|
||||||
const keycodes = Array.from(Array(249).keys());
|
const keycodes = Array.from(Array(249).keys());
|
||||||
const releaseCommand = `ydotool key --key-delay 0 ${keycodes.map(keycode => `${keycode}:0`).join(" ")}`
|
Quickshell.execDetached([
|
||||||
Hyprland.dispatch(`exec ${releaseCommand}`)
|
"ydotool",
|
||||||
|
"key", "--key-delay", "0",
|
||||||
|
...keycodes.map(keycode => `${keycode}:0`)
|
||||||
|
])
|
||||||
root.shiftMode = 0; // Reset shift mode
|
root.shiftMode = 0; // Reset shift mode
|
||||||
}
|
}
|
||||||
|
|
||||||
function releaseShiftKeys() {
|
function releaseShiftKeys() {
|
||||||
const releaseCommand = `ydotool key --key-delay 0 ${root.shiftKeys.map(keycode => `${keycode}:0`).join(" ")}`
|
Quickshell.execDetached([
|
||||||
Hyprland.dispatch(`exec ${releaseCommand}`)
|
"ydotool",
|
||||||
|
"key", "--key-delay", "0",
|
||||||
|
...root.shiftKeys.map(keycode => `${keycode}:0`)
|
||||||
|
])
|
||||||
root.shiftMode = 0; // Reset shift mode
|
root.shiftMode = 0; // Reset shift mode
|
||||||
}
|
}
|
||||||
|
|
||||||
function press(keycode) {
|
function press(keycode) {
|
||||||
Hyprland.dispatch(`exec ydotool key --key-delay 0 ${keycode}:1`);
|
Quickshell.execDetached([
|
||||||
|
"ydotool",
|
||||||
|
"key", "--key-delay", "0",
|
||||||
|
`${keycode}:1`
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function release(keycode) {
|
function release(keycode) {
|
||||||
Hyprland.dispatch(`exec ydotool key --key-delay 0 ${keycode}:0`);
|
Quickshell.execDetached([
|
||||||
|
"ydotool",
|
||||||
|
"key", "--key-delay", "0",
|
||||||
|
`${keycode}:0`
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ ApplicationWindow {
|
|||||||
{
|
{
|
||||||
name: "Style",
|
name: "Style",
|
||||||
icon: "palette",
|
icon: "palette",
|
||||||
component: "modules/settings/Style.qml"
|
component: "modules/settings/StyleConfig.qml"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Behavior",
|
name: "General",
|
||||||
icon: "settings",
|
icon: "settings",
|
||||||
component: "modules/settings/BehaviorConfig.qml"
|
component: "modules/settings/GeneralConfig.qml"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "About",
|
name: "About",
|
||||||
@@ -66,6 +66,28 @@ ApplicationWindow {
|
|||||||
margins: contentPadding
|
margins: contentPadding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => {
|
||||||
|
console.log(`Key pressed: ${event.key}, Modifiers: ${event.modifiers}`);
|
||||||
|
if (event.modifiers === Qt.ControlModifier) {
|
||||||
|
if (event.key === Qt.Key_PageDown) {
|
||||||
|
root.currentPage = Math.min(root.currentPage + 1, root.pages.length - 1)
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
else if (event.key === Qt.Key_PageUp) {
|
||||||
|
root.currentPage = Math.max(root.currentPage - 1, 0)
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
else if (event.key === Qt.Key_Tab) {
|
||||||
|
root.currentPage = (root.currentPage + 1) % root.pages.length;
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
else if (event.key === Qt.Key_Backtab) {
|
||||||
|
root.currentPage = (root.currentPage - 1 + root.pages.length) % root.pages.length;
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item { // Titlebar
|
Item { // Titlebar
|
||||||
visible: ConfigOptions?.windows.showTitlebar
|
visible: ConfigOptions?.windows.showTitlebar
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -73,7 +95,12 @@ ApplicationWindow {
|
|||||||
implicitHeight: Math.max(titleText.implicitHeight, windowControlsRow.implicitHeight)
|
implicitHeight: Math.max(titleText.implicitHeight, windowControlsRow.implicitHeight)
|
||||||
StyledText {
|
StyledText {
|
||||||
id: titleText
|
id: titleText
|
||||||
anchors.centerIn: parent
|
anchors {
|
||||||
|
left: ConfigOptions.windows.centerTitle ? undefined : parent.left
|
||||||
|
horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
leftMargin: 12
|
||||||
|
}
|
||||||
color: Appearance.colors.colOnLayer0
|
color: Appearance.colors.colOnLayer0
|
||||||
text: "Settings"
|
text: "Settings"
|
||||||
font.pixelSize: Appearance.font.pixelSize.title
|
font.pixelSize: Appearance.font.pixelSize.title
|
||||||
@@ -120,7 +147,9 @@ ApplicationWindow {
|
|||||||
spacing: 10
|
spacing: 10
|
||||||
expanded: root.width > 900
|
expanded: root.width > 900
|
||||||
|
|
||||||
NavigationRailExpandButton {}
|
NavigationRailExpandButton {
|
||||||
|
focus: root.visible
|
||||||
|
}
|
||||||
|
|
||||||
FloatingActionButton {
|
FloatingActionButton {
|
||||||
id: fab
|
id: fab
|
||||||
@@ -175,7 +204,8 @@ ApplicationWindow {
|
|||||||
target: root
|
target: root
|
||||||
function onCurrentPageChanged() {
|
function onCurrentPageChanged() {
|
||||||
if (pageLoader.sourceComponent !== root.pages[root.currentPage].component) {
|
if (pageLoader.sourceComponent !== root.pages[root.currentPage].component) {
|
||||||
switchAnim.restart();
|
switchAnim.complete();
|
||||||
|
switchAnim.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +218,7 @@ ApplicationWindow {
|
|||||||
properties: "opacity"
|
properties: "opacity"
|
||||||
from: 1
|
from: 1
|
||||||
to: 0
|
to: 0
|
||||||
duration: 150
|
duration: 0
|
||||||
easing.type: Appearance.animation.elementMoveExit.type
|
easing.type: Appearance.animation.elementMoveExit.type
|
||||||
easing.bezierCurve: Appearance.animationCurves.emphasizedFirstHalf
|
easing.bezierCurve: Appearance.animationCurves.emphasizedFirstHalf
|
||||||
}
|
}
|
||||||
@@ -202,7 +232,7 @@ ApplicationWindow {
|
|||||||
properties: "opacity"
|
properties: "opacity"
|
||||||
from: 0
|
from: 0
|
||||||
to: 1
|
to: 1
|
||||||
duration: 250
|
duration: 0
|
||||||
easing.type: Appearance.animation.elementMoveEnter.type
|
easing.type: Appearance.animation.elementMoveEnter.type
|
||||||
easing.bezierCurve: Appearance.animationCurves.emphasizedLastHalf
|
easing.bezierCurve: Appearance.animationCurves.emphasizedLastHalf
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,12 @@ ApplicationWindow {
|
|||||||
implicitHeight: Math.max(welcomeText.implicitHeight, windowControlsRow.implicitHeight)
|
implicitHeight: Math.max(welcomeText.implicitHeight, windowControlsRow.implicitHeight)
|
||||||
StyledText {
|
StyledText {
|
||||||
id: welcomeText
|
id: welcomeText
|
||||||
anchors.centerIn: parent
|
anchors {
|
||||||
|
left: ConfigOptions.windows.centerTitle ? undefined : parent.left
|
||||||
|
horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
leftMargin: 12
|
||||||
|
}
|
||||||
color: Appearance.colors.colOnLayer0
|
color: Appearance.colors.colOnLayer0
|
||||||
text: "Yooooo hi there"
|
text: "Yooooo hi there"
|
||||||
font.pixelSize: Appearance.font.pixelSize.title
|
font.pixelSize: Appearance.font.pixelSize.title
|
||||||
@@ -86,10 +91,9 @@ ApplicationWindow {
|
|||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
Hyprland.dispatch(`exec rm '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`)
|
Quickshell.execDetached(["rm", root.firstRunFilePath])
|
||||||
} else {
|
} else {
|
||||||
console.log(`exec echo '${StringUtils.shellSingleQuoteEscape(root.firstRunFileContent)}' > '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`)
|
Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(root.firstRunFileContent)}' > '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`])
|
||||||
Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(root.firstRunFileContent)}' > '${StringUtils.shellSingleQuoteEscape(root.firstRunFilePath)}'`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +158,7 @@ ApplicationWindow {
|
|||||||
content: "Pick wallpaper image on your system"
|
content: "Pick wallpaper image on your system"
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Hyprland.dispatch(`exec ${Directories.wallpaperSwitchScriptPath}`)
|
Quickshell.execDetached([`${Directories.wallpaperSwitchScriptPath}`])
|
||||||
}
|
}
|
||||||
mainContentComponent: Component {
|
mainContentComponent: Component {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@@ -196,84 +200,40 @@ ApplicationWindow {
|
|||||||
ContentSection {
|
ContentSection {
|
||||||
title: "Policies"
|
title: "Policies"
|
||||||
|
|
||||||
RowLayout {
|
ConfigRow {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
spacing: 15
|
|
||||||
ColumnLayout { // Weeb policy
|
ColumnLayout { // Weeb policy
|
||||||
StyledText {
|
ContentSubsectionLabel {
|
||||||
text: "Weeb"
|
text: "Weeb"
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
}
|
||||||
ButtonGroup {
|
ConfigSelectionArray {
|
||||||
id: weebPolicyBtnGroup
|
currentValue: ConfigOptions.policies.weeb
|
||||||
property int selectedPolicy: ConfigOptions.policies.weeb
|
configOptionName: "policies.weeb"
|
||||||
spacing: 2
|
onSelected: (newValue) => {
|
||||||
SelectionGroupButton {
|
ConfigLoader.setConfigValueAndSave("policies.weeb", newValue);
|
||||||
property int value: 0
|
|
||||||
leftmost: true
|
|
||||||
buttonText: "No"
|
|
||||||
toggled: (weebPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.weeb", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 1
|
|
||||||
buttonText: "Yes"
|
|
||||||
toggled: (weebPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.weeb", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 2
|
|
||||||
rightmost: true
|
|
||||||
buttonText: "Closet"
|
|
||||||
toggled: (weebPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.weeb", value);
|
|
||||||
}
|
|
||||||
StyledToolTip {
|
|
||||||
content: "The Anime tab on the left sidebar would still\nbe available, but its tab button won't show"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
options: [
|
||||||
|
{ displayName: "No", value: 0 },
|
||||||
|
{ displayName: "Yes", value: 1 },
|
||||||
|
{ displayName: "Closet", value: 2 }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout { // AI policy
|
ColumnLayout { // AI policy
|
||||||
StyledText {
|
ContentSubsectionLabel {
|
||||||
text: "AI"
|
text: "AI"
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
}
|
}
|
||||||
ButtonGroup {
|
ConfigSelectionArray {
|
||||||
id: aiPolicyBtnGroup
|
currentValue: ConfigOptions.policies.ai
|
||||||
property int selectedPolicy: ConfigOptions.policies.ai
|
configOptionName: "policies.ai"
|
||||||
spacing: 2
|
onSelected: (newValue) => {
|
||||||
SelectionGroupButton {
|
ConfigLoader.setConfigValueAndSave("policies.ai", newValue);
|
||||||
property int value: 0
|
|
||||||
leftmost: true
|
|
||||||
buttonText: "No"
|
|
||||||
toggled: (aiPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.ai", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 1
|
|
||||||
buttonText: "Yes"
|
|
||||||
toggled: (aiPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.ai", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SelectionGroupButton {
|
|
||||||
property int value: 2
|
|
||||||
rightmost: true
|
|
||||||
buttonText: "Local only"
|
|
||||||
toggled: (aiPolicyBtnGroup.selectedPolicy === value)
|
|
||||||
onClicked: {
|
|
||||||
ConfigLoader.setConfigValueAndSave("policies.ai", value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
options: [
|
||||||
|
{ displayName: "No", value: 0 },
|
||||||
|
{ displayName: "Yes", value: 1 },
|
||||||
|
{ displayName: "Local only", value: 2 }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ depends=(
|
|||||||
hyprlock
|
hyprlock
|
||||||
hyprpicker
|
hyprpicker
|
||||||
nm-connection-editor
|
nm-connection-editor
|
||||||
quickshell
|
quickshell-git
|
||||||
swww
|
swww
|
||||||
translate-shell
|
translate-shell
|
||||||
wlogout
|
wlogout
|
||||||
|
|||||||
Reference in New Issue
Block a user