mirror of
https://github.com/celesrenata/end-4-flakes.git
synced 2026-06-10 04:09:25 -05:00
fix: add wayland dev headers and scanner for pywayland build on NixOS
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
ContentPage {
|
||||
forceWidth: true
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Distro")
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 20
|
||||
Layout.topMargin: 10
|
||||
Layout.bottomMargin: 10
|
||||
IconImage {
|
||||
implicitSize: 80
|
||||
source: Quickshell.iconPath(SystemInfo.logo)
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
// spacing: 10
|
||||
StyledText {
|
||||
text: SystemInfo.distroName
|
||||
font.pixelSize: Appearance.font.pixelSize.title
|
||||
}
|
||||
StyledText {
|
||||
font.pixelSize: Appearance.font.pixelSize.normal
|
||||
text: SystemInfo.homeUrl
|
||||
textFormat: Text.MarkdownText
|
||||
onLinkActivated: (link) => {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
PointingHandLinkHover {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 5
|
||||
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "auto_stories"
|
||||
mainText: Translation.tr("Documentation")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally(SystemInfo.documentationUrl)
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "support"
|
||||
mainText: Translation.tr("Help & Support")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally(SystemInfo.supportUrl)
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "bug_report"
|
||||
mainText: Translation.tr("Report a Bug")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally(SystemInfo.bugReportUrl)
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "policy"
|
||||
materialIconFill: false
|
||||
mainText: Translation.tr("Privacy Policy")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally(SystemInfo.privacyPolicyUrl)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
ContentSection {
|
||||
title: Translation.tr("Dotfiles")
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 20
|
||||
Layout.topMargin: 10
|
||||
Layout.bottomMargin: 10
|
||||
IconImage {
|
||||
implicitSize: 80
|
||||
source: Quickshell.iconPath("illogical-impulse")
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
// spacing: 10
|
||||
StyledText {
|
||||
text: Translation.tr("illogical-impulse")
|
||||
font.pixelSize: Appearance.font.pixelSize.title
|
||||
}
|
||||
StyledText {
|
||||
text: "https://github.com/end-4/dots-hyprland"
|
||||
font.pixelSize: Appearance.font.pixelSize.normal
|
||||
textFormat: Text.MarkdownText
|
||||
onLinkActivated: (link) => {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
PointingHandLinkHover {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
spacing: 5
|
||||
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "auto_stories"
|
||||
mainText: Translation.tr("Documentation")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://end-4.github.io/dots-hyprland-wiki/en/ii-qs/02usage/")
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "adjust"
|
||||
materialIconFill: false
|
||||
mainText: Translation.tr("Issues")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://github.com/end-4/dots-hyprland/issues")
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "forum"
|
||||
mainText: Translation.tr("Discussions")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://github.com/end-4/dots-hyprland/discussions")
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "favorite"
|
||||
mainText: Translation.tr("Donate")
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://github.com/sponsors/end-4")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import QtQuick
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
ContentPage {
|
||||
forceWidth: true
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Color generation")
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Shell & utilities")
|
||||
checked: Config.options.appearance.wallpaperTheming.enableAppsAndShell
|
||||
onCheckedChanged: {
|
||||
Config.options.appearance.wallpaperTheming.enableAppsAndShell = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Qt apps")
|
||||
checked: Config.options.appearance.wallpaperTheming.enableQtApps
|
||||
onCheckedChanged: {
|
||||
Config.options.appearance.wallpaperTheming.enableQtApps = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Shell & utilities theming must also be enabled")
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Terminal")
|
||||
checked: Config.options.appearance.wallpaperTheming.enableTerminal
|
||||
onCheckedChanged: {
|
||||
Config.options.appearance.wallpaperTheming.enableTerminal = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Shell & utilities theming must also be enabled")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
ContentPage {
|
||||
forceWidth: true
|
||||
ContentSection {
|
||||
title: Translation.tr("Policies")
|
||||
|
||||
ConfigRow {
|
||||
ColumnLayout {
|
||||
// Weeb policy
|
||||
ContentSubsectionLabel {
|
||||
text: Translation.tr("Weeb")
|
||||
}
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.policies.weeb
|
||||
configOptionName: "policies.weeb"
|
||||
onSelected: newValue => {
|
||||
Config.options.policies.weeb = newValue;
|
||||
}
|
||||
options: [
|
||||
{
|
||||
displayName: Translation.tr("No"),
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Yes"),
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Closet"),
|
||||
value: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
// AI policy
|
||||
ContentSubsectionLabel {
|
||||
text: Translation.tr("AI")
|
||||
}
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.policies.ai
|
||||
configOptionName: "policies.ai"
|
||||
onSelected: newValue => {
|
||||
Config.options.policies.ai = newValue;
|
||||
}
|
||||
options: [
|
||||
{
|
||||
displayName: Translation.tr("No"),
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Yes"),
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Local only"),
|
||||
value: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Bar")
|
||||
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.bar.cornerStyle
|
||||
configOptionName: "bar.cornerStyle"
|
||||
onSelected: newValue => {
|
||||
Config.options.bar.cornerStyle = newValue;
|
||||
}
|
||||
options: [
|
||||
{
|
||||
displayName: Translation.tr("Hug"),
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Float"),
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("Plain rectangle"),
|
||||
value: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Overall appearance")
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Borderless')
|
||||
checked: Config.options.bar.borderless
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.borderless = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Show background')
|
||||
checked: Config.options.bar.showBackground
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.showBackground = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Note: turning off can hurt readability")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Buttons")
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Screen snip")
|
||||
checked: Config.options.bar.utilButtons.showScreenSnip
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.utilButtons.showScreenSnip = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Color picker")
|
||||
checked: Config.options.bar.utilButtons.showColorPicker
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.utilButtons.showColorPicker = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Mic toggle")
|
||||
checked: Config.options.bar.utilButtons.showMicToggle
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.utilButtons.showMicToggle = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Keyboard toggle")
|
||||
checked: Config.options.bar.utilButtons.showKeyboardToggle
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.utilButtons.showKeyboardToggle = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Dark/Light toggle")
|
||||
checked: Config.options.bar.utilButtons.showDarkModeToggle
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.utilButtons.showDarkModeToggle = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Performance Profile toggle")
|
||||
checked: Config.options.bar.utilButtons.showPerformanceProfileToggle
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.utilButtons.showPerformanceProfileToggle = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Workspaces")
|
||||
tooltip: Translation.tr("Tip: Hide icons and always show numbers for\nthe classic illogical-impulse experience")
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Show app icons')
|
||||
checked: Config.options.bar.workspaces.showAppIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.showAppIcons = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Tint app icons')
|
||||
checked: Config.options.bar.workspaces.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Always show numbers')
|
||||
checked: Config.options.bar.workspaces.alwaysShowNumbers
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.workspaces.alwaysShowNumbers = checked;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Workspaces shown")
|
||||
value: Config.options.bar.workspaces.shown
|
||||
from: 1
|
||||
to: 30
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
Config.options.bar.workspaces.shown = value;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Number show delay when pressing Super (ms)")
|
||||
value: Config.options.bar.workspaces.showNumberDelay
|
||||
from: 0
|
||||
to: 1000
|
||||
stepSize: 50
|
||||
onValueChanged: {
|
||||
Config.options.bar.workspaces.showNumberDelay = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Tray")
|
||||
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Tint icons')
|
||||
checked: Config.options.bar.tray.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.tray.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Weather")
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Enable")
|
||||
checked: Config.options.bar.weather.enable
|
||||
onCheckedChanged: {
|
||||
Config.options.bar.weather.enable = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Battery")
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Low warning")
|
||||
value: Config.options.battery.low
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 5
|
||||
onValueChanged: {
|
||||
Config.options.battery.low = value;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Critical warning")
|
||||
value: Config.options.battery.critical
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 5
|
||||
onValueChanged: {
|
||||
Config.options.battery.critical = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Automatic suspend")
|
||||
checked: Config.options.battery.automaticSuspend
|
||||
onCheckedChanged: {
|
||||
Config.options.battery.automaticSuspend = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Automatically suspends the system when battery is low")
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Suspend at")
|
||||
value: Config.options.battery.suspend
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 5
|
||||
onValueChanged: {
|
||||
Config.options.battery.suspend = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Dock")
|
||||
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Enable")
|
||||
checked: Config.options.dock.enable
|
||||
onCheckedChanged: {
|
||||
Config.options.dock.enable = checked;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Hover to reveal")
|
||||
checked: Config.options.dock.hoverToReveal
|
||||
onCheckedChanged: {
|
||||
Config.options.dock.hoverToReveal = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Pinned on startup")
|
||||
checked: Config.options.dock.pinnedOnStartup
|
||||
onCheckedChanged: {
|
||||
Config.options.dock.pinnedOnStartup = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Tint app icons")
|
||||
checked: Config.options.dock.monochromeIcons
|
||||
onCheckedChanged: {
|
||||
Config.options.dock.monochromeIcons = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Sidebars")
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Keep right sidebar loaded')
|
||||
checked: Config.options.sidebar.keepRightSidebarLoaded
|
||||
onCheckedChanged: {
|
||||
Config.options.sidebar.keepRightSidebarLoaded = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("When enabled keeps the content of the right sidebar loaded to reduce the delay when opening,\nat the cost of around 15MB of consistent RAM usage. Delay significance depends on your system's performance.\nUsing a different kernel might help with this delay")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("On-screen display")
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Timeout (ms)")
|
||||
value: Config.options.osd.timeout
|
||||
from: 100
|
||||
to: 3000
|
||||
stepSize: 100
|
||||
onValueChanged: {
|
||||
Config.options.osd.timeout = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Overview")
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Enable")
|
||||
checked: Config.options.overview.enable
|
||||
onCheckedChanged: {
|
||||
Config.options.overview.enable = checked;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Scale (%)")
|
||||
value: Config.options.overview.scale * 100
|
||||
from: 1
|
||||
to: 100
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
Config.options.overview.scale = value / 100;
|
||||
}
|
||||
}
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Rows")
|
||||
value: Config.options.overview.rows
|
||||
from: 1
|
||||
to: 20
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
Config.options.overview.rows = value;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Columns")
|
||||
value: Config.options.overview.columns
|
||||
from: 1
|
||||
to: 20
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
Config.options.overview.columns = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Screenshot tool")
|
||||
|
||||
ConfigSwitch {
|
||||
text: Translation.tr('Show regions of potential interest')
|
||||
checked: Config.options.screenshotTool.showContentRegions
|
||||
onCheckedChanged: {
|
||||
Config.options.screenshotTool.showContentRegions = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Such regions could be images or parts of the screen that have some containment.\nMight not always be accurate.\nThis is done with an image processing algorithm run locally and no AI is used.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
|
||||
ContentPage {
|
||||
forceWidth: true
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Audio")
|
||||
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Earbang protection")
|
||||
checked: Config.options.audio.protection.enable
|
||||
onCheckedChanged: {
|
||||
Config.options.audio.protection.enable = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Prevents abrupt increments and restricts volume limit")
|
||||
}
|
||||
}
|
||||
ConfigRow {
|
||||
// uniform: true
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Max allowed increase")
|
||||
value: Config.options.audio.protection.maxAllowedIncrease
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 2
|
||||
onValueChanged: {
|
||||
Config.options.audio.protection.maxAllowedIncrease = value;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Volume limit")
|
||||
value: Config.options.audio.protection.maxAllowed
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 2
|
||||
onValueChanged: {
|
||||
Config.options.audio.protection.maxAllowed = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ContentSection {
|
||||
title: Translation.tr("AI")
|
||||
MaterialTextField {
|
||||
Layout.fillWidth: true
|
||||
placeholderText: Translation.tr("System prompt")
|
||||
text: Config.options.ai.systemPrompt
|
||||
wrapMode: TextEdit.Wrap
|
||||
onTextChanged: {
|
||||
Qt.callLater(() => {
|
||||
Config.options.ai.systemPrompt = text;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Battery")
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Low warning")
|
||||
value: Config.options.battery.low
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 5
|
||||
onValueChanged: {
|
||||
Config.options.battery.low = value;
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Critical warning")
|
||||
value: Config.options.battery.critical
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 5
|
||||
onValueChanged: {
|
||||
Config.options.battery.critical = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Automatic suspend")
|
||||
checked: Config.options.battery.automaticSuspend
|
||||
onCheckedChanged: {
|
||||
Config.options.battery.automaticSuspend = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Automatically suspends the system when battery is low")
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Suspend at")
|
||||
value: Config.options.battery.suspend
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 5
|
||||
onValueChanged: {
|
||||
Config.options.battery.suspend = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Networking")
|
||||
MaterialTextField {
|
||||
Layout.fillWidth: true
|
||||
placeholderText: Translation.tr("User agent (for services that require it)")
|
||||
text: Config.options.networking.userAgent
|
||||
wrapMode: TextEdit.Wrap
|
||||
onTextChanged: {
|
||||
Config.options.networking.userAgent = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Resources")
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Polling interval (ms)")
|
||||
value: Config.options.resources.updateInterval
|
||||
from: 100
|
||||
to: 10000
|
||||
stepSize: 100
|
||||
onValueChanged: {
|
||||
Config.options.resources.updateInterval = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Search")
|
||||
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Use Levenshtein distance-based algorithm instead of fuzzy")
|
||||
checked: Config.options.search.sloppy
|
||||
onCheckedChanged: {
|
||||
Config.options.search.sloppy = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Could be better if you make a ton of typos,\nbut results can be weird and might not work with acronyms\n(e.g. \"GIMP\" might not give you the paint program)")
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Prefixes")
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
|
||||
MaterialTextField {
|
||||
Layout.fillWidth: true
|
||||
placeholderText: Translation.tr("Action")
|
||||
text: Config.options.search.prefix.action
|
||||
wrapMode: TextEdit.Wrap
|
||||
onTextChanged: {
|
||||
Config.options.search.prefix.action = text;
|
||||
}
|
||||
}
|
||||
MaterialTextField {
|
||||
Layout.fillWidth: true
|
||||
placeholderText: Translation.tr("Clipboard")
|
||||
text: Config.options.search.prefix.clipboard
|
||||
wrapMode: TextEdit.Wrap
|
||||
onTextChanged: {
|
||||
Config.options.search.prefix.clipboard = text;
|
||||
}
|
||||
}
|
||||
MaterialTextField {
|
||||
Layout.fillWidth: true
|
||||
placeholderText: Translation.tr("Emojis")
|
||||
text: Config.options.search.prefix.emojis
|
||||
wrapMode: TextEdit.Wrap
|
||||
onTextChanged: {
|
||||
Config.options.search.prefix.emojis = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Web search")
|
||||
MaterialTextField {
|
||||
Layout.fillWidth: true
|
||||
placeholderText: Translation.tr("Base URL")
|
||||
text: Config.options.search.engineBaseUrl
|
||||
wrapMode: TextEdit.Wrap
|
||||
onTextChanged: {
|
||||
Config.options.search.engineBaseUrl = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Time")
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Format")
|
||||
tooltip: ""
|
||||
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.time.format
|
||||
configOptionName: "time.format"
|
||||
onSelected: newValue => {
|
||||
Config.options.time.format = newValue;
|
||||
}
|
||||
options: [
|
||||
{
|
||||
displayName: Translation.tr("24h"),
|
||||
value: "hh:mm"
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("12h am/pm"),
|
||||
value: "h:mm ap"
|
||||
},
|
||||
{
|
||||
displayName: Translation.tr("12h AM/PM"),
|
||||
value: "h:mm AP"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
|
||||
// Main Settings Window
|
||||
// Integrates transparency settings and other configuration options
|
||||
|
||||
ApplicationWindow {
|
||||
id: settingsWindow
|
||||
|
||||
title: "dots-hyprland Settings"
|
||||
width: 500
|
||||
height: 700
|
||||
visible: false
|
||||
|
||||
color: "#1e1e2e"
|
||||
|
||||
// Make window float and center it
|
||||
flags: Qt.Window | Qt.WindowStaysOnTopHint
|
||||
|
||||
Component.onCompleted: {
|
||||
// Center the window
|
||||
x = (Screen.width - width) / 2
|
||||
y = (Screen.height - height) / 2
|
||||
}
|
||||
|
||||
TabBar {
|
||||
id: tabBar
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 50
|
||||
|
||||
background: Rectangle {
|
||||
color: "#313244"
|
||||
}
|
||||
|
||||
TabButton {
|
||||
text: "Effects"
|
||||
width: implicitWidth
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.checked ? "#45475a" : "transparent"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: "#cdd6f4"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
TabButton {
|
||||
text: "Appearance"
|
||||
width: implicitWidth
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.checked ? "#45475a" : "transparent"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: "#cdd6f4"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
TabButton {
|
||||
text: "Keybinds"
|
||||
width: implicitWidth
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.checked ? "#45475a" : "transparent"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: "#cdd6f4"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
anchors.top: tabBar.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: 10
|
||||
|
||||
currentIndex: tabBar.currentIndex
|
||||
|
||||
// Effects Tab (Transparency & Blur)
|
||||
Item {
|
||||
TransparencyUI {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border.width: 0
|
||||
}
|
||||
}
|
||||
|
||||
// Appearance Tab (Future: themes, colors, etc.)
|
||||
Item {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#313244"
|
||||
radius: 8
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Appearance settings\n(Coming soon)"
|
||||
color: "#a6adc8"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keybinds Tab (Future: keybind customization)
|
||||
Item {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#313244"
|
||||
radius: 8
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Keybind settings\n(Coming soon)"
|
||||
color: "#a6adc8"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close button
|
||||
Button {
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 10
|
||||
|
||||
width: 30
|
||||
height: 30
|
||||
|
||||
text: "×"
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? "#f38ba8" : "#45475a"
|
||||
radius: 15
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: "white"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
onClicked: settingsWindow.close()
|
||||
}
|
||||
|
||||
// IPC Handler for external control
|
||||
IpcHandler {
|
||||
target: "settings"
|
||||
|
||||
function show() {
|
||||
settingsWindow.show()
|
||||
settingsWindow.raise()
|
||||
settingsWindow.requestActivate()
|
||||
}
|
||||
|
||||
function hide() {
|
||||
settingsWindow.hide()
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (settingsWindow.visible) {
|
||||
settingsWindow.hide()
|
||||
} else {
|
||||
settingsWindow.show()
|
||||
settingsWindow.raise()
|
||||
settingsWindow.requestActivate()
|
||||
}
|
||||
}
|
||||
|
||||
function showEffects() {
|
||||
tabBar.currentIndex = 0
|
||||
settingsWindow.show()
|
||||
settingsWindow.raise()
|
||||
settingsWindow.requestActivate()
|
||||
}
|
||||
|
||||
function showAppearance() {
|
||||
tabBar.currentIndex = 1
|
||||
settingsWindow.show()
|
||||
settingsWindow.raise()
|
||||
settingsWindow.requestActivate()
|
||||
}
|
||||
|
||||
function showKeybinds() {
|
||||
tabBar.currentIndex = 2
|
||||
settingsWindow.show()
|
||||
settingsWindow.raise()
|
||||
settingsWindow.requestActivate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
|
||||
ContentPage {
|
||||
baseWidth: lightDarkButtonGroup.implicitWidth
|
||||
forceWidth: true
|
||||
|
||||
Process {
|
||||
id: konachanWallProc
|
||||
property string status: ""
|
||||
command: ["bash", "-c", FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/random_konachan_wall.sh`)]
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
console.log(`Konachan wall proc output: ${data}`);
|
||||
konachanWallProc.status = data.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Colors & Wallpaper")
|
||||
|
||||
// Light/Dark mode preference
|
||||
ButtonGroup {
|
||||
id: lightDarkButtonGroup
|
||||
Layout.fillWidth: true
|
||||
LightDarkPreferenceButton {
|
||||
dark: false
|
||||
}
|
||||
LightDarkPreferenceButton {
|
||||
dark: true
|
||||
}
|
||||
}
|
||||
|
||||
// Material palette selection
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Material palette")
|
||||
ConfigSelectionArray {
|
||||
currentValue: Config.options.appearance.palette.type
|
||||
configOptionName: "appearance.palette.type"
|
||||
onSelected: (newValue) => {
|
||||
Config.options.appearance.palette.type = newValue;
|
||||
Quickshell.execDetached(["bash", "-c", `${Directories.wallpaperSwitchScriptPath} --noswitch`])
|
||||
}
|
||||
options: [
|
||||
{"value": "auto", "displayName": Translation.tr("Auto")},
|
||||
{"value": "scheme-content", "displayName": Translation.tr("Content")},
|
||||
{"value": "scheme-expressive", "displayName": Translation.tr("Expressive")},
|
||||
{"value": "scheme-fidelity", "displayName": Translation.tr("Fidelity")},
|
||||
{"value": "scheme-fruit-salad", "displayName": Translation.tr("Fruit Salad")},
|
||||
{"value": "scheme-monochrome", "displayName": Translation.tr("Monochrome")},
|
||||
{"value": "scheme-neutral", "displayName": Translation.tr("Neutral")},
|
||||
{"value": "scheme-rainbow", "displayName": Translation.tr("Rainbow")},
|
||||
{"value": "scheme-tonal-spot", "displayName": Translation.tr("Tonal Spot")}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Wallpaper selection
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Wallpaper")
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
RippleButtonWithIcon {
|
||||
id: rndWallBtn
|
||||
buttonRadius: Appearance.rounding.small
|
||||
materialIcon: "wallpaper"
|
||||
mainText: konachanWallProc.running ? Translation.tr("Be patient...") : Translation.tr("Random: Konachan")
|
||||
onClicked: {
|
||||
console.log(konachanWallProc.command.join(" "))
|
||||
konachanWallProc.running = true;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Random SFW Anime wallpaper from Konachan\nImage is saved to ~/Pictures/Wallpapers")
|
||||
}
|
||||
}
|
||||
RippleButtonWithIcon {
|
||||
materialIcon: "wallpaper"
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Pick wallpaper image on your system")
|
||||
}
|
||||
onClicked: {
|
||||
Quickshell.execDetached(`${Directories.wallpaperSwitchScriptPath}`)
|
||||
}
|
||||
mainContentComponent: Component {
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
StyledText {
|
||||
font.pixelSize: Appearance.font.pixelSize.small
|
||||
text: Translation.tr("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: Translation.tr("Alternatively use /dark, /light, /img in the launcher")
|
||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||
color: Appearance.colors.colSubtext
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ContentSection {
|
||||
title: Translation.tr("Decorations & Effects")
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Transparency")
|
||||
|
||||
ConfigRow {
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Enable")
|
||||
checked: Config.options.appearance.transparency
|
||||
onCheckedChanged: {
|
||||
Config.options.appearance.transparency = checked;
|
||||
}
|
||||
StyledToolTip {
|
||||
content: Translation.tr("Might look ass. Unsupported.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Fake screen rounding")
|
||||
|
||||
ButtonGroup {
|
||||
id: fakeScreenRoundingButtonGroup
|
||||
property int selectedPolicy: Config.options.appearance.fakeScreenRounding
|
||||
spacing: 2
|
||||
SelectionGroupButton {
|
||||
property int value: 0
|
||||
leftmost: true
|
||||
buttonText: Translation.tr("No")
|
||||
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
||||
onClicked: {
|
||||
Config.options.appearance.fakeScreenRounding = value;
|
||||
}
|
||||
}
|
||||
SelectionGroupButton {
|
||||
property int value: 1
|
||||
buttonText: Translation.tr("Yes")
|
||||
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
||||
onClicked: {
|
||||
Config.options.appearance.fakeScreenRounding = value;
|
||||
}
|
||||
}
|
||||
SelectionGroupButton {
|
||||
property int value: 2
|
||||
rightmost: true
|
||||
buttonText: Translation.tr("When not fullscreen")
|
||||
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
|
||||
onClicked: {
|
||||
Config.options.appearance.fakeScreenRounding = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Shell windows")
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Title bar")
|
||||
checked: Config.options.windows.showTitlebar
|
||||
onCheckedChanged: {
|
||||
Config.options.windows.showTitlebar = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Center title")
|
||||
checked: Config.options.windows.centerTitle
|
||||
onCheckedChanged: {
|
||||
Config.options.windows.centerTitle = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentSubsection {
|
||||
title: Translation.tr("Wallpaper parallax")
|
||||
|
||||
ConfigRow {
|
||||
uniform: true
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Depends on workspace")
|
||||
checked: Config.options.background.parallax.enableWorkspace
|
||||
onCheckedChanged: {
|
||||
Config.options.background.parallax.enableWorkspace = checked;
|
||||
}
|
||||
}
|
||||
ConfigSwitch {
|
||||
text: Translation.tr("Depends on sidebars")
|
||||
checked: Config.options.background.parallax.enableSidebar
|
||||
onCheckedChanged: {
|
||||
Config.options.background.parallax.enableSidebar = checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigSpinBox {
|
||||
text: Translation.tr("Preferred wallpaper zoom (%)")
|
||||
value: Config.options.background.parallax.workspaceZoom * 100
|
||||
from: 100
|
||||
to: 150
|
||||
stepSize: 1
|
||||
onValueChanged: {
|
||||
console.log(value/100)
|
||||
Config.options.background.parallax.workspaceZoom = value / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Services.SystemdUser
|
||||
|
||||
// Transparency and Blur Settings Module
|
||||
// Based on AGS configuration from ~/.config/ags/modules/sideright/centermodules/configure.js
|
||||
|
||||
Rectangle {
|
||||
id: transparencySettings
|
||||
|
||||
property bool globalTransparency: false
|
||||
property int terminalOpacity: 100
|
||||
property bool blurEnabled: false
|
||||
property bool blurXray: true
|
||||
property int blurSize: 8
|
||||
property int blurPasses: 4
|
||||
|
||||
// Storage paths (matching AGS structure)
|
||||
property string colorModeFile: StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/ags/user/colormode.txt"
|
||||
property string terminalTransparencyFile: StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/ags/user/generated/terminal/transparency"
|
||||
|
||||
color: "transparent"
|
||||
|
||||
Component.onCompleted: {
|
||||
loadSettings()
|
||||
}
|
||||
|
||||
// Load settings from files (AGS compatibility)
|
||||
function loadSettings() {
|
||||
// Load global transparency mode
|
||||
Process.exec("bash", ["-c", `mkdir -p $(dirname "${colorModeFile}")`])
|
||||
let colorModeResult = Process.exec("bash", ["-c", `sed -n '2p' "${colorModeFile}" 2>/dev/null || echo "opaque"`])
|
||||
globalTransparency = (colorModeResult.stdout.trim() === "transparent")
|
||||
|
||||
// Load terminal opacity
|
||||
Process.exec("bash", ["-c", `mkdir -p $(dirname "${terminalTransparencyFile}")`])
|
||||
let termOpacityResult = Process.exec("bash", ["-c", `cat "${terminalTransparencyFile}" 2>/dev/null || echo "100"`])
|
||||
terminalOpacity = parseInt(termOpacityResult.stdout.trim()) || 100
|
||||
|
||||
// Load Hyprland blur settings
|
||||
loadHyprlandSettings()
|
||||
}
|
||||
|
||||
function loadHyprlandSettings() {
|
||||
// Load blur enabled
|
||||
let blurResult = Process.exec("hyprctl", ["getoption", "-j", "decoration:blur:enabled"])
|
||||
try {
|
||||
let blurData = JSON.parse(blurResult.stdout)
|
||||
blurEnabled = blurData.int !== 0
|
||||
} catch (e) {
|
||||
console.log("Failed to load blur enabled setting:", e)
|
||||
}
|
||||
|
||||
// Load blur xray
|
||||
let xrayResult = Process.exec("hyprctl", ["getoption", "-j", "decoration:blur:xray"])
|
||||
try {
|
||||
let xrayData = JSON.parse(xrayResult.stdout)
|
||||
blurXray = xrayData.int !== 0
|
||||
} catch (e) {
|
||||
console.log("Failed to load blur xray setting:", e)
|
||||
}
|
||||
|
||||
// Load blur size
|
||||
let sizeResult = Process.exec("hyprctl", ["getoption", "-j", "decoration:blur:size"])
|
||||
try {
|
||||
let sizeData = JSON.parse(sizeResult.stdout)
|
||||
blurSize = sizeData.int
|
||||
} catch (e) {
|
||||
console.log("Failed to load blur size setting:", e)
|
||||
}
|
||||
|
||||
// Load blur passes
|
||||
let passesResult = Process.exec("hyprctl", ["getoption", "-j", "decoration:blur:passes"])
|
||||
try {
|
||||
let passesData = JSON.parse(passesResult.stdout)
|
||||
blurPasses = passesData.int
|
||||
} catch (e) {
|
||||
console.log("Failed to load blur passes setting:", e)
|
||||
}
|
||||
}
|
||||
|
||||
// Save and apply global transparency
|
||||
function setGlobalTransparency(enabled) {
|
||||
globalTransparency = enabled
|
||||
let mode = enabled ? "transparent" : "opaque"
|
||||
|
||||
// Save to colormode.txt (line 2)
|
||||
Process.exec("bash", ["-c", `mkdir -p $(dirname "${colorModeFile}")
|
||||
if [ ! -f "${colorModeFile}" ]; then
|
||||
echo "dark" > "${colorModeFile}"
|
||||
echo "${mode}" >> "${colorModeFile}"
|
||||
else
|
||||
sed -i "2s/.*/${mode}/" "${colorModeFile}"
|
||||
fi`])
|
||||
|
||||
// Apply color changes (equivalent to AGS switchcolor.sh)
|
||||
applyColorChanges()
|
||||
}
|
||||
|
||||
// Save and apply terminal opacity
|
||||
function setTerminalOpacity(opacity) {
|
||||
terminalOpacity = opacity
|
||||
|
||||
// Save to terminal transparency file
|
||||
Process.exec("bash", ["-c", `mkdir -p $(dirname "${terminalTransparencyFile}")
|
||||
echo "${opacity}" > "${terminalTransparencyFile}"`])
|
||||
|
||||
// Apply terminal colors (equivalent to AGS applycolor.sh term)
|
||||
applyTerminalColors()
|
||||
}
|
||||
|
||||
// Apply Hyprland blur settings
|
||||
function setBlurEnabled(enabled) {
|
||||
blurEnabled = enabled
|
||||
Process.exec("hyprctl", ["keyword", "decoration:blur:enabled", enabled ? "1" : "0"])
|
||||
}
|
||||
|
||||
function setBlurXray(enabled) {
|
||||
blurXray = enabled
|
||||
Process.exec("hyprctl", ["keyword", "decoration:blur:xray", enabled ? "1" : "0"])
|
||||
}
|
||||
|
||||
function setBlurSize(size) {
|
||||
blurSize = size
|
||||
Process.exec("hyprctl", ["keyword", "decoration:blur:size", size.toString()])
|
||||
}
|
||||
|
||||
function setBlurPasses(passes) {
|
||||
blurPasses = passes
|
||||
Process.exec("hyprctl", ["keyword", "decoration:blur:passes", passes.toString()])
|
||||
}
|
||||
|
||||
// Apply color changes (equivalent to AGS color generation)
|
||||
function applyColorChanges() {
|
||||
// This would call the equivalent of AGS color generation scripts
|
||||
Process.exec("bash", ["-c", `
|
||||
# Apply transparency mode to all shell elements
|
||||
# This is where we'd integrate with the quickshell theming system
|
||||
echo "Applying transparency mode: ${globalTransparency ? 'transparent' : 'opaque'}"
|
||||
|
||||
# Reload quickshell to apply changes
|
||||
quickshell ipc call settings reload || true
|
||||
`])
|
||||
}
|
||||
|
||||
// Apply terminal colors (equivalent to AGS applycolor.sh term)
|
||||
function applyTerminalColors() {
|
||||
let alpha = terminalOpacity / 100.0
|
||||
|
||||
Process.exec("bash", ["-c", `
|
||||
# Update foot terminal configuration with new opacity
|
||||
FOOT_CONFIG="$HOME/.config/foot/foot.ini"
|
||||
if [ -f "$FOOT_CONFIG" ]; then
|
||||
# Update alpha value in foot.ini
|
||||
sed -i "s/^alpha=.*/alpha=${alpha}/" "$FOOT_CONFIG" || echo "alpha=${alpha}" >> "$FOOT_CONFIG"
|
||||
fi
|
||||
|
||||
# Send terminal escape sequence to update running terminals
|
||||
# This matches the AGS terminal sequences functionality
|
||||
echo "Applied terminal opacity: ${terminalOpacity}%"
|
||||
`])
|
||||
}
|
||||
|
||||
// IPC Handler for external control
|
||||
IpcHandler {
|
||||
target: "transparencySettings"
|
||||
|
||||
function setTransparency(enabled) {
|
||||
transparencySettings.setGlobalTransparency(enabled)
|
||||
}
|
||||
|
||||
function setTerminalOpacity(opacity) {
|
||||
transparencySettings.setTerminalOpacity(opacity)
|
||||
}
|
||||
|
||||
function setBlur(enabled) {
|
||||
transparencySettings.setBlurEnabled(enabled)
|
||||
}
|
||||
|
||||
function setBlurXray(enabled) {
|
||||
transparencySettings.setBlurXray(enabled)
|
||||
}
|
||||
|
||||
function setBlurSize(size) {
|
||||
transparencySettings.setBlurSize(size)
|
||||
}
|
||||
|
||||
function setBlurPasses(passes) {
|
||||
transparencySettings.setBlurPasses(passes)
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
return {
|
||||
globalTransparency: transparencySettings.globalTransparency,
|
||||
terminalOpacity: transparencySettings.terminalOpacity,
|
||||
blurEnabled: transparencySettings.blurEnabled,
|
||||
blurXray: transparencySettings.blurXray,
|
||||
blurSize: transparencySettings.blurSize,
|
||||
blurPasses: transparencySettings.blurPasses
|
||||
}
|
||||
}
|
||||
|
||||
function reload() {
|
||||
transparencySettings.loadSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
|
||||
// Transparency and Blur UI Controls
|
||||
// Replicates the AGS configuration UI from configure.js
|
||||
|
||||
Rectangle {
|
||||
id: transparencyUI
|
||||
|
||||
property alias transparencySettings: settingsLoader.item
|
||||
|
||||
width: 400
|
||||
height: 600
|
||||
color: "#1e1e2e"
|
||||
radius: 12
|
||||
border.color: "#45475a"
|
||||
border.width: 1
|
||||
|
||||
// Load the settings module
|
||||
Loader {
|
||||
id: settingsLoader
|
||||
source: "TransparencySettings.qml"
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
spacing: 20
|
||||
|
||||
// Header
|
||||
Text {
|
||||
text: "Effects Configuration"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Global Transparency Section
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: transparencySection.height + 20
|
||||
color: "#313244"
|
||||
radius: 8
|
||||
|
||||
ColumnLayout {
|
||||
id: transparencySection
|
||||
anchors.fill: parent
|
||||
anchors.margins: 15
|
||||
spacing: 15
|
||||
|
||||
// Transparency Toggle
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
color: "#89b4fa"
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "◫"
|
||||
color: "white"
|
||||
font.pixelSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "Transparency"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Make shell elements transparent\nBlur is also recommended if you enable this"
|
||||
color: "#a6adc8"
|
||||
font.pixelSize: 11
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: transparencySwitch
|
||||
checked: transparencySettings ? transparencySettings.globalTransparency : false
|
||||
|
||||
onToggled: {
|
||||
if (transparencySettings) {
|
||||
transparencySettings.setGlobalTransparency(checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Terminal Opacity Slider (subcategory)
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: terminalOpacitySection.height + 10
|
||||
color: "#45475a"
|
||||
radius: 6
|
||||
Layout.leftMargin: 20
|
||||
|
||||
ColumnLayout {
|
||||
id: terminalOpacitySection
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 10
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
color: "#f9e2af"
|
||||
radius: 3
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "○"
|
||||
color: "black"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "Terminal Opacity"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Changes the opacity of the foot terminal"
|
||||
color: "#a6adc8"
|
||||
font.pixelSize: 10
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (transparencySettings ? transparencySettings.terminalOpacity : 100) + "%"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 12
|
||||
Layout.preferredWidth: 40
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: terminalOpacitySlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 1
|
||||
value: transparencySettings ? transparencySettings.terminalOpacity : 100
|
||||
|
||||
onValueChanged: {
|
||||
if (transparencySettings && Math.abs(value - transparencySettings.terminalOpacity) > 0.5) {
|
||||
transparencySettings.setTerminalOpacity(Math.round(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blur Section
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: blurSection.height + 20
|
||||
color: "#313244"
|
||||
radius: 8
|
||||
|
||||
ColumnLayout {
|
||||
id: blurSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: 15
|
||||
spacing: 15
|
||||
|
||||
// Blur Toggle
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
color: "#94e2d5"
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "◐"
|
||||
color: "black"
|
||||
font.pixelSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "Blur"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Enable blur on transparent elements\nDoesn't affect performance/power consumption unless you have transparent windows."
|
||||
color: "#a6adc8"
|
||||
font.pixelSize: 11
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: blurSwitch
|
||||
checked: transparencySettings ? transparencySettings.blurEnabled : false
|
||||
|
||||
onToggled: {
|
||||
if (transparencySettings) {
|
||||
transparencySettings.setBlurEnabled(checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blur Subcategory
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: blurSubcategory.height + 10
|
||||
color: "#45475a"
|
||||
radius: 6
|
||||
Layout.leftMargin: 20
|
||||
visible: transparencySettings ? transparencySettings.blurEnabled : false
|
||||
|
||||
ColumnLayout {
|
||||
id: blurSubcategory
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 15
|
||||
|
||||
// X-ray Toggle
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
color: "#f38ba8"
|
||||
radius: 3
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "⚡"
|
||||
color: "white"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "X-ray"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Make everything behind a window/layer except the wallpaper not rendered on its blurred surface\nRecommended to improve performance (if you don't abuse transparency/blur)"
|
||||
color: "#a6adc8"
|
||||
font.pixelSize: 10
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Switch {
|
||||
checked: transparencySettings ? transparencySettings.blurXray : true
|
||||
|
||||
onToggled: {
|
||||
if (transparencySettings) {
|
||||
transparencySettings.setBlurXray(checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blur Size
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
color: "#a6e3a1"
|
||||
radius: 3
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "◎"
|
||||
color: "black"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "Size"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Adjust the blur radius. Generally doesn't affect performance\nHigher = more color spread"
|
||||
color: "#a6adc8"
|
||||
font.pixelSize: 10
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
from: 1
|
||||
to: 1000
|
||||
value: transparencySettings ? transparencySettings.blurSize : 8
|
||||
|
||||
onValueChanged: {
|
||||
if (transparencySettings && value !== transparencySettings.blurSize) {
|
||||
transparencySettings.setBlurSize(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blur Passes
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
color: "#cba6f7"
|
||||
radius: 3
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "↻"
|
||||
color: "white"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "Passes"
|
||||
color: "#cdd6f4"
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Adjust the number of runs of the blur algorithm\nMore passes = more spread and power consumption\n4 is recommended\n2- would look weird and 6+ would look lame."
|
||||
color: "#a6adc8"
|
||||
font.pixelSize: 10
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
from: 1
|
||||
to: 10
|
||||
value: transparencySettings ? transparencySettings.blurPasses : 4
|
||||
|
||||
onValueChanged: {
|
||||
if (transparencySettings && value !== transparencySettings.blurPasses) {
|
||||
transparencySettings.setBlurPasses(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply/Reset buttons
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
||||
Button {
|
||||
text: "Reset to Defaults"
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
if (transparencySettings) {
|
||||
transparencySettings.setGlobalTransparency(false)
|
||||
transparencySettings.setTerminalOpacity(100)
|
||||
transparencySettings.setBlurEnabled(false)
|
||||
transparencySettings.setBlurXray(true)
|
||||
transparencySettings.setBlurSize(8)
|
||||
transparencySettings.setBlurPasses(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Reload Settings"
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
if (transparencySettings) {
|
||||
transparencySettings.loadSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IPC Handler for external control
|
||||
IpcHandler {
|
||||
target: "transparencyUI"
|
||||
|
||||
function show() {
|
||||
transparencyUI.visible = true
|
||||
}
|
||||
|
||||
function hide() {
|
||||
transparencyUI.visible = false
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
transparencyUI.visible = !transparencyUI.visible
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user