mirror of
https://github.com/belsabbagh/dotfiles.git
synced 2026-04-11 17:47:09 +00:00
quickshell and hyprland additions
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
import qs.services
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import QtQuick.Layouts
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
width: 200
|
||||
height: 80
|
||||
radius: Metrics.radius("verylarge")
|
||||
color: Appearance.m3colors.m3surfaceContainerHigh
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
readonly property bool adapterPresent: Bluetooth.defaultAdapter !== null
|
||||
readonly property bool enabled: Bluetooth.defaultAdapter?.enabled ?? false
|
||||
readonly property var activeDevice: Bluetooth.activeDevice
|
||||
|
||||
readonly property string iconName: Bluetooth.icon
|
||||
|
||||
readonly property string statusText: {
|
||||
if (!adapterPresent)
|
||||
return "No adapter";
|
||||
if (!enabled)
|
||||
return "Disabled";
|
||||
if (activeDevice)
|
||||
return activeDevice.name;
|
||||
return Bluetooth.defaultAdapter.discovering
|
||||
? "Scanning…"
|
||||
: "Enabled";
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: iconBg
|
||||
width: 50
|
||||
height: 50
|
||||
radius: Metrics.radius("verylarge")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Metrics.margin("small")
|
||||
|
||||
color: {
|
||||
if (!enabled)
|
||||
return Appearance.m3colors.m3surfaceContainerHigh;
|
||||
if (activeDevice)
|
||||
return Appearance.m3colors.m3primaryContainer;
|
||||
return Appearance.m3colors.m3secondaryContainer;
|
||||
}
|
||||
|
||||
MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
iconSize: Metrics.iconSize(35)
|
||||
icon: iconName
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: iconBg.right
|
||||
anchors.leftMargin: Metrics.margin("small")
|
||||
spacing: Metrics.spacing(2)
|
||||
|
||||
StyledText {
|
||||
text: "Bluetooth"
|
||||
font.pixelSize: Metrics.fontSize("large")
|
||||
elide: Text.ElideRight
|
||||
width: root.width - iconBg.width - 30
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: statusText
|
||||
font.pixelSize: Metrics.fontSize("small")
|
||||
color: Appearance.m3colors.m3onSurfaceVariant
|
||||
elide: Text.ElideRight
|
||||
width: root.width - iconBg.width - 30
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (!adapterPresent)
|
||||
return;
|
||||
|
||||
Bluetooth.defaultAdapter.enabled =
|
||||
!Bluetooth.defaultAdapter.enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
import qs.services
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Services.Pipewire
|
||||
import Quickshell.Widgets
|
||||
import QtQuick.Controls
|
||||
|
||||
|
||||
StyledSlider {
|
||||
id: brightnessSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 1
|
||||
stepSize: 0.01
|
||||
property var monitor: Brightness.monitors.length > 0 ? Brightness.monitors[0] : null
|
||||
value: monitor ? monitor.brightness : 0.5
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
property real level: brightnessSlider.value * 100
|
||||
|
||||
onMoved: if (monitor) {
|
||||
monitor.setBrightness(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
import qs.modules.functions
|
||||
import qs.services
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick.Layouts
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
width: 150
|
||||
height: 50
|
||||
radius: Metrics.radius("verylarge")
|
||||
color: Appearance.m3colors.m3surfaceContainerHigh
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
property bool flightMode
|
||||
property string flightModeText: flightMode ? "Enabled" : "Disabled"
|
||||
|
||||
Process {
|
||||
id: toggleflightModeProc
|
||||
running: false
|
||||
command: []
|
||||
|
||||
function toggle() {
|
||||
flightMode = !flightMode;
|
||||
const cmd = flightMode ? "off" : "on";
|
||||
toggleflightModeProc.command = ["bash", "-c", `nmcli radio all ${cmd}`];
|
||||
toggleflightModeProc.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: iconBg
|
||||
width: 50
|
||||
height: 50
|
||||
radius: Metrics.radius("large")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Metrics.margin(10)
|
||||
color: !flightMode ? Appearance.m3colors.m3surfaceContainerHigh : Appearance.m3colors.m3primaryContainer
|
||||
|
||||
MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
iconSize: Metrics.iconSize(35)
|
||||
icon: "flight"
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: iconBg.right
|
||||
anchors.leftMargin: Metrics.margin(10)
|
||||
|
||||
StyledText {
|
||||
text: "Flight Mode"
|
||||
font.pixelSize: Metrics.fontSize(20)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: flightModeText
|
||||
font.pixelSize: Metrics.fontSize("small")
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: true
|
||||
onClicked: toggleflightModeProc.toggle()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import qs.config
|
||||
import qs.modules.functions
|
||||
import qs.modules.interface.notifications
|
||||
import qs.modules.components
|
||||
import qs.services
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
|
||||
Layout.fillWidth: true
|
||||
radius: Metrics.radius("normal")
|
||||
color: Appearance.m3colors.m3surfaceContainer
|
||||
|
||||
ClippingRectangle {
|
||||
color: Appearance.colors.colLayer1
|
||||
radius: Metrics.radius("normal")
|
||||
implicitHeight: 90
|
||||
anchors.fill: parent
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
spacing: Metrics.margin("small")
|
||||
|
||||
ClippingRectangle {
|
||||
implicitWidth: 140
|
||||
implicitHeight: 140
|
||||
Layout.leftMargin: Metrics.margin("large")
|
||||
radius: Metrics.radius("normal")
|
||||
clip: true
|
||||
color: Appearance.colors.colLayer2
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Mpris.artUrl
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
cache: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: Metrics.margin("small")
|
||||
spacing: Metrics.spacing(2)
|
||||
|
||||
Text {
|
||||
text: Mpris.albumTitle
|
||||
elide: Text.ElideRight
|
||||
Layout.maximumWidth: 190
|
||||
font.family: Metrics.fontFamily("title")
|
||||
font.pixelSize: Metrics.fontSize("hugeass")
|
||||
font.bold: true
|
||||
color: Appearance.colors.colOnLayer2
|
||||
}
|
||||
|
||||
Text {
|
||||
text: Mpris.albumArtist
|
||||
elide: Text.ElideRight
|
||||
Layout.maximumWidth: 160
|
||||
font.family: Metrics.fontFamily("main")
|
||||
font.pixelSize: Metrics.fontSize("normal")
|
||||
color: Appearance.colors.colSubtext
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: Metrics.spacing(12)
|
||||
|
||||
Process {
|
||||
id: control
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
onClicked: Quickshell.execDetached(["playerctl", "previous"])
|
||||
|
||||
background: Rectangle {
|
||||
radius: Metrics.radius("large")
|
||||
color: Appearance.colors.colLayer2
|
||||
}
|
||||
|
||||
contentItem: MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
icon: "skip_previous"
|
||||
font.pixelSize: Metrics.fontSize(24)
|
||||
color: Appearance.colors.colOnLayer2
|
||||
fill: 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.preferredWidth: 42
|
||||
Layout.preferredHeight: 42
|
||||
onClicked: Quickshell.execDetached(["playerctl", "play-pause"])
|
||||
|
||||
background: Rectangle {
|
||||
radius: Metrics.radius("full")
|
||||
color: Appearance.colors.colPrimary
|
||||
}
|
||||
|
||||
contentItem: MaterialSymbol {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
icon: "play_arrow"
|
||||
font.pixelSize: Metrics.fontSize(36)
|
||||
color: Appearance.colors.colOnPrimary
|
||||
fill: 1
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
onClicked: Quickshell.execDetached(["playerctl", "next"])
|
||||
|
||||
background: Rectangle {
|
||||
radius: Metrics.radius("large")
|
||||
color: Appearance.colors.colLayer2
|
||||
}
|
||||
|
||||
contentItem: MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
icon: "skip_next"
|
||||
font.pixelSize: Metrics.fontSize(24)
|
||||
color: Appearance.colors.colOnLayer2
|
||||
fill: 1
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: Metrics.margin(15)
|
||||
Layout.fillWidth: true
|
||||
spacing: Metrics.spacing(12)
|
||||
|
||||
Text {
|
||||
text: Mpris.formatTime(Mpris.positionSec)
|
||||
font.pixelSize: Metrics.fontSize("smallest")
|
||||
color: Appearance.colors.colSubtext
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 20
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Metrics.radius("full")
|
||||
color: Appearance.colors.colLayer2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * (Mpris.lengthSec > 0 ? Mpris.positionSec / Mpris.lengthSec : 0)
|
||||
radius: Metrics.radius("full")
|
||||
color: Appearance.colors.colPrimary
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Text {
|
||||
text: Mpris.formatTime(Mpris.lengthSec)
|
||||
font.pixelSize: Metrics.fontSize("smallest")
|
||||
color: Appearance.colors.colSubtext
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
import qs.modules.functions
|
||||
import qs.services
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import QtQuick.Layouts
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
width: 150
|
||||
height: 50
|
||||
radius: Metrics.radius("verylarge")
|
||||
color: Appearance.m3colors.m3surfaceContainerHigh
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
// Service bindings
|
||||
readonly property bool wifiEnabled: Network.wifiEnabled
|
||||
readonly property bool hasActive: Network.active !== null
|
||||
readonly property string iconName: Network.icon
|
||||
readonly property string titleText: Network.label
|
||||
readonly property string statusText: Network.status
|
||||
|
||||
// Icon background
|
||||
StyledRect {
|
||||
id: iconBg
|
||||
width: 50
|
||||
height: 50
|
||||
radius: Metrics.radius("large")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Metrics.margin(10)
|
||||
|
||||
color: {
|
||||
if (!wifiEnabled)
|
||||
return Appearance.m3colors.m3surfaceContainerHigh;
|
||||
if (hasActive)
|
||||
return Appearance.m3colors.m3primaryContainer;
|
||||
return Appearance.m3colors.m3secondaryContainer;
|
||||
}
|
||||
|
||||
MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
icon: iconName
|
||||
iconSize: Metrics.iconSize(35)
|
||||
}
|
||||
}
|
||||
|
||||
// Labels
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: iconBg.right
|
||||
anchors.leftMargin: Metrics.margin(10)
|
||||
spacing: Metrics.spacing(2)
|
||||
|
||||
StyledText {
|
||||
text: titleText
|
||||
font.pixelSize: Metrics.fontSize(20)
|
||||
elide: Text.ElideRight
|
||||
width: root.width - iconBg.width - 30
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: statusText
|
||||
font.pixelSize: Metrics.fontSize("small")
|
||||
color: Appearance.m3colors.m3onSurfaceVariant
|
||||
elide: Text.ElideRight
|
||||
width: root.width - iconBg.width - 30
|
||||
}
|
||||
}
|
||||
|
||||
// Interaction
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: Network.toggleWifi()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool nightTime
|
||||
width: 200
|
||||
height: 80
|
||||
radius: Metrics.radius("childish")
|
||||
color: !nightTime ? Appearance.m3colors.m3surfaceContainer : Appearance.m3colors.m3paddingContainer
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
Layout.margins: 0
|
||||
|
||||
MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
iconSize: Metrics.iconSize(35)
|
||||
icon: "coffee"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
nightTime = !nightTime;
|
||||
nightTime ? Quickshell.execDetached(["gammastep", "-O", "4000"]) : Quickshell.execDetached(["killall", "gammastep"]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.modules.functions
|
||||
import qs.modules.interface.notifications
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
|
||||
Layout.fillWidth: true
|
||||
radius: Metrics.radius("normal")
|
||||
color: Appearance.colors.colLayer1
|
||||
property bool dndActive: Config.runtime.notifications.doNotDisturb
|
||||
|
||||
function toggleDnd() {
|
||||
Config.updateKey("notifications.doNotDisturb", !dndActive);
|
||||
}
|
||||
|
||||
StyledButton {
|
||||
id: clearButton
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: Metrics.margin(10)
|
||||
anchors.rightMargin: Metrics.margin(10)
|
||||
icon: "clear_all"
|
||||
text: "Clear"
|
||||
implicitHeight: 40
|
||||
implicitWidth: 100
|
||||
secondary: true
|
||||
|
||||
onClicked: {
|
||||
for (let i = 0; i < NotifServer.history.length; i++) {
|
||||
let n = NotifServer.history[i];
|
||||
if (n?.notification) n.notification.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledButton {
|
||||
id: silentButton
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: Metrics.margin(10)
|
||||
anchors.rightMargin: clearButton.implicitWidth + Metrics.margin(15)
|
||||
text: "Silent"
|
||||
icon: "do_not_disturb_on"
|
||||
implicitHeight: 40
|
||||
implicitWidth: 100
|
||||
secondary: true
|
||||
checkable: true
|
||||
checked: Config.runtime.notifications.doNotDisturb
|
||||
|
||||
onClicked: {
|
||||
toggleDnd()
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.bottomMargin: Metrics.margin(15)
|
||||
anchors.leftMargin: Metrics.margin(15)
|
||||
text: NotifServer.history.length + " Notifications"
|
||||
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: "No notifications"
|
||||
visible: NotifServer.history.length < 1
|
||||
font.pixelSize: Metrics.fontSize("huge")
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: notifList
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: clearButton.top
|
||||
anchors.margins: Metrics.margin(10)
|
||||
|
||||
clip: true
|
||||
spacing: Metrics.spacing(8)
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
ScrollBar.vertical: ScrollBar { }
|
||||
|
||||
model: Config.runtime.notifications.enabled
|
||||
? NotifServer.history
|
||||
: []
|
||||
|
||||
delegate: NotificationChild {
|
||||
width: notifList.width
|
||||
title: model.summary
|
||||
body: model.body
|
||||
image: model.image || model.appIcon
|
||||
rawNotif: model
|
||||
buttons: model.actions.map((action) => ({
|
||||
"label": action.text,
|
||||
"onClick": () => action.invoke()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
readonly property bool isDark: Config.runtime.appearance.theme === "dark"
|
||||
property string themestatusicon: isDark ? "dark_mode" : "light_mode"
|
||||
|
||||
width: 200
|
||||
height: 80
|
||||
radius: Metrics.radius("childish")
|
||||
color: Appearance.m3colors.m3paddingContainer
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
Layout.margins: 0
|
||||
|
||||
MaterialSymbol {
|
||||
anchors.centerIn: parent
|
||||
iconSize: Metrics.iconSize(35)
|
||||
icon: themestatusicon
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
Quickshell.execDetached(["nucleus", "ipc", "call", "global", "toggleTheme"]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import qs.config
|
||||
import qs.modules.components
|
||||
import qs.services
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Services.Pipewire
|
||||
import Quickshell.Widgets
|
||||
import QtQuick.Controls
|
||||
|
||||
|
||||
StyledSlider {
|
||||
id: volSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 1
|
||||
stepSize: 0.01
|
||||
value: sink ? sink.volume : 0
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
property real level: volSlider.value * 100
|
||||
|
||||
PwObjectTracker {
|
||||
objects: [Pipewire.defaultAudioSink]
|
||||
}
|
||||
|
||||
property var sink: Pipewire.defaultAudioSink?.audio
|
||||
|
||||
|
||||
onMoved: {
|
||||
if (sink) sink.volume = value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user