forked from Shinonome/dots-hyprland
new folder for services, fancy calendar month button
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import "root:/services"
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import "root:/services"
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import "root:/services"
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import "root:/services"
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
|
||||
@@ -164,6 +164,7 @@ Singleton {
|
||||
property QtObject elementDecel: QtObject {
|
||||
property int duration: 180
|
||||
property int type: Easing.OutCirc
|
||||
property int velocity: 650
|
||||
}
|
||||
property QtObject menuDecel: QtObject {
|
||||
property int duration: 350
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.Pipewire
|
||||
pragma Singleton
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property var sink: Pipewire.defaultAudioSink
|
||||
property var source: Pipewire.defaultAudioSource
|
||||
|
||||
PwObjectTracker {
|
||||
objects: [Pipewire.defaultAudioSink, Pipewire.defaultAudioSource]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell;
|
||||
import Quickshell.Io;
|
||||
import QtQuick;
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property int updateInterval: 1000
|
||||
property string bluetoothDeviceName: ""
|
||||
property string bluetoothDeviceAddress: ""
|
||||
property bool bluetoothEnabled: false
|
||||
property bool bluetoothConnected: false
|
||||
|
||||
function update() {
|
||||
updateBluetoothDevice.running = true
|
||||
updateBluetoothStatus.running = true
|
||||
updateBluetoothEnabled.running = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 10
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
update()
|
||||
interval = root.updateInterval
|
||||
}
|
||||
}
|
||||
|
||||
// Check if Bluetooth is enabled (controller powered on)
|
||||
Process {
|
||||
id: updateBluetoothEnabled
|
||||
command: ["sh", "-c", "bluetoothctl show | grep -q 'Powered: yes' && echo 1 || echo 0"]
|
||||
running: true
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
root.bluetoothEnabled = (parseInt(data) === 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the name and address of the first connected Bluetooth device
|
||||
Process {
|
||||
id: updateBluetoothDevice
|
||||
command: ["sh", "-c", "bluetoothctl info | awk -F': ' '/Name: /{name=$2} /Device /{addr=$2} END{print name \":\" addr}'"]
|
||||
running: true
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
let parts = data.split(":")
|
||||
root.bluetoothDeviceName = parts[0] || ""
|
||||
root.bluetoothDeviceAddress = parts[1] || ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any device is connected
|
||||
Process {
|
||||
id: updateBluetoothStatus
|
||||
command: ["sh", "-c", "bluetoothctl info | grep -q 'Connected: yes' && echo 1 || echo 0"]
|
||||
running: true
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
root.bluetoothConnected = (parseInt(data) === 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
pragma Singleton
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property string brightness
|
||||
property int value: 0
|
||||
|
||||
function refresh() {
|
||||
getBrightness.running = true;
|
||||
}
|
||||
|
||||
onValueChanged: () => {
|
||||
if (value > 0) {
|
||||
increaseBrightness.running = true;
|
||||
root.value = 0;
|
||||
} else if (value < 0) {
|
||||
decreaseBrightness.running = true;
|
||||
root.value = 0;
|
||||
}
|
||||
getBrightness.running = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: getBrightness
|
||||
|
||||
command: ["sh", "-c", "brightnessctl -m i | cut -d, -f4"]
|
||||
running: true
|
||||
onExited: {
|
||||
running = false;
|
||||
}
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: (data) => {
|
||||
root.brightness = data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Process {
|
||||
id: decreaseBrightness
|
||||
|
||||
command: ["brightnessctl", "set", "5%-"]
|
||||
running: false
|
||||
onExited: {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: increaseBrightness
|
||||
|
||||
command: ["brightnessctl", "set", "5%+"]
|
||||
running: false
|
||||
onExited: {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
pragma Singleton
|
||||
|
||||
Singleton {
|
||||
property string time: Qt.formatDateTime(clock.date, "hh:mm")
|
||||
property string date: Qt.formatDateTime(clock.date, "dddd, dd/MM")
|
||||
property string month: Qt.formatDateTime(clock.date, "MMMM")
|
||||
property string year: Qt.formatDateTime(clock.date, "yyyy")
|
||||
property string uptime: "0h, 0m"
|
||||
|
||||
SystemClock {
|
||||
id: clock
|
||||
|
||||
precision: SystemClock.Minutes
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 10
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
fileUptime.reload()
|
||||
const textUptime = fileUptime.text()
|
||||
const uptimeSeconds = Number(textUptime.split(" ")[0] ?? 0)
|
||||
|
||||
// Convert seconds to days, hours, and minutes
|
||||
const days = Math.floor(uptimeSeconds / 86400)
|
||||
const hours = Math.floor((uptimeSeconds % 86400) / 3600)
|
||||
const minutes = Math.floor((uptimeSeconds % 3600) / 60)
|
||||
|
||||
// Build the formatted uptime string
|
||||
let formatted = ""
|
||||
if (days > 0) formatted += `${days}d`
|
||||
if (hours > 0) formatted += `${formatted ? ", " : ""}${hours}h`
|
||||
if (minutes > 0 || !formatted) formatted += `${formatted ? ", " : ""}${minutes}m`
|
||||
uptime = formatted
|
||||
interval = ConfigOptions.resources.updateInterval;
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: fileUptime
|
||||
|
||||
path: "/proc/uptime"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQml.Models
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Services.Mpris
|
||||
|
||||
Singleton {
|
||||
id: root;
|
||||
property MprisPlayer trackedPlayer: null;
|
||||
property MprisPlayer activePlayer: trackedPlayer ?? Mpris.players.values[0] ?? null;
|
||||
signal trackChanged(reverse: bool);
|
||||
|
||||
property bool __reverse: false;
|
||||
|
||||
property var activeTrack;
|
||||
|
||||
Instantiator {
|
||||
model: Mpris.players;
|
||||
|
||||
Connections {
|
||||
required property MprisPlayer modelData;
|
||||
target: modelData;
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.trackedPlayer == null || modelData.isPlaying) {
|
||||
root.trackedPlayer = modelData;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if (root.trackedPlayer == null || !root.trackedPlayer.isPlaying) {
|
||||
for (const player of Mpris.players.values) {
|
||||
if (player.playbackState.isPlaying) {
|
||||
root.trackedPlayer = player;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trackedPlayer == null && Mpris.players.values.length != 0) {
|
||||
trackedPlayer = Mpris.players.values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onPlaybackStateChanged() {
|
||||
if (root.trackedPlayer !== modelData) root.trackedPlayer = modelData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: activePlayer
|
||||
|
||||
function onPostTrackChanged() {
|
||||
root.updateTrack();
|
||||
}
|
||||
|
||||
function onTrackArtUrlChanged() {
|
||||
// console.log("arturl:", activePlayer.trackArtUrl)
|
||||
// root.updateTrack();
|
||||
if (root.activePlayer.uniqueId == root.activeTrack.uniqueId && root.activePlayer.trackArtUrl != root.activeTrack.artUrl) {
|
||||
// cantata likes to send cover updates *BEFORE* updating the track info.
|
||||
// as such, art url changes shouldn't be able to break the reverse animation
|
||||
const r = root.__reverse;
|
||||
root.updateTrack();
|
||||
root.__reverse = r;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onActivePlayerChanged: this.updateTrack();
|
||||
|
||||
function updateTrack() {
|
||||
//console.log(`update: ${this.activePlayer?.trackTitle ?? ""} : ${this.activePlayer?.trackArtists}`)
|
||||
this.activeTrack = {
|
||||
uniqueId: this.activePlayer?.uniqueId ?? 0,
|
||||
artUrl: this.activePlayer?.trackArtUrl ?? "",
|
||||
title: this.activePlayer?.trackTitle || "Unknown Title",
|
||||
artist: this.activePlayer?.trackArtist || "Unknown Artist",
|
||||
album: this.activePlayer?.trackAlbum || "Unknown Album",
|
||||
};
|
||||
|
||||
this.trackChanged(__reverse);
|
||||
this.__reverse = false;
|
||||
}
|
||||
|
||||
property bool isPlaying: this.activePlayer && this.activePlayer.isPlaying;
|
||||
property bool canTogglePlaying: this.activePlayer?.canTogglePlaying ?? false;
|
||||
function togglePlaying() {
|
||||
if (this.canTogglePlaying) this.activePlayer.togglePlaying();
|
||||
}
|
||||
|
||||
property bool canGoPrevious: this.activePlayer?.canGoPrevious ?? false;
|
||||
function previous() {
|
||||
if (this.canGoPrevious) {
|
||||
this.__reverse = true;
|
||||
this.activePlayer.previous();
|
||||
}
|
||||
}
|
||||
|
||||
property bool canGoNext: this.activePlayer?.canGoNext ?? false;
|
||||
function next() {
|
||||
if (this.canGoNext) {
|
||||
this.__reverse = false;
|
||||
this.activePlayer.next();
|
||||
}
|
||||
}
|
||||
|
||||
property bool canChangeVolume: this.activePlayer && this.activePlayer.volumeSupported && this.activePlayer.canControl;
|
||||
|
||||
property bool loopSupported: this.activePlayer && this.activePlayer.loopSupported && this.activePlayer.canControl;
|
||||
property var loopState: this.activePlayer?.loopState ?? MprisLoopState.None;
|
||||
function setLoopState(loopState: var) {
|
||||
if (this.loopSupported) {
|
||||
this.activePlayer.loopState = loopState;
|
||||
}
|
||||
}
|
||||
|
||||
property bool shuffleSupported: this.activePlayer && this.activePlayer.shuffleSupported && this.activePlayer.canControl;
|
||||
property bool hasShuffle: this.activePlayer?.shuffle ?? false;
|
||||
function setShuffle(shuffle: bool) {
|
||||
if (this.shuffleSupported) {
|
||||
this.activePlayer.shuffle = shuffle;
|
||||
}
|
||||
}
|
||||
|
||||
function setActivePlayer(player: MprisPlayer) {
|
||||
const targetPlayer = player ?? Mpris.players[0];
|
||||
console.log(`setactive: ${targetPlayer} from ${activePlayer}`)
|
||||
|
||||
if (targetPlayer && this.activePlayer) {
|
||||
this.__reverse = Mpris.players.indexOf(targetPlayer) < Mpris.players.indexOf(this.activePlayer);
|
||||
} else {
|
||||
// always animate forward if going to null
|
||||
this.__reverse = false;
|
||||
}
|
||||
|
||||
this.trackedPlayer = targetPlayer;
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
target: "mpris"
|
||||
|
||||
function pauseAll(): void {
|
||||
for (const player of Mpris.players.values) {
|
||||
if (player.canPause) player.pause();
|
||||
}
|
||||
}
|
||||
|
||||
function playPause(): void { root.togglePlaying(); }
|
||||
function previous(): void { root.previous(); }
|
||||
function next(): void { root.next(); }
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell;
|
||||
import Quickshell.Io;
|
||||
import Quickshell.Services.Pipewire;
|
||||
import QtQuick;
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property int updateInterval: 1000
|
||||
property string networkName: "";
|
||||
property int networkStrength;
|
||||
function update() {
|
||||
updateNetworkName.running = true
|
||||
updateNetworkStrength.running = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 10
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
update()
|
||||
interval = root.updateInterval;
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: updateNetworkName
|
||||
command: ["sh", "-c", "nmcli -t -f NAME c show --active | head -1"]
|
||||
running: true;
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
root.networkName = data
|
||||
// console.log("Network: " + data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: updateNetworkStrength
|
||||
running: true
|
||||
command: ["sh", "-c", "nmcli -f IN-USE,SIGNAL,SSID device wifi | awk '/^\*/{if (NR!=1) {print $2}}'"];
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
root.networkStrength = parseInt(data);
|
||||
// console.log("Network Strength: " + data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
Singleton {
|
||||
property double memoryTotal: 1
|
||||
property double memoryFree: 1
|
||||
property double memoryUsed: memoryTotal - memoryFree
|
||||
property double memoryUsedPercentage: memoryUsed / memoryTotal
|
||||
property double swapTotal: 1
|
||||
property double swapFree: 1
|
||||
property double swapUsed: swapTotal - swapFree
|
||||
property double swapUsedPercentage: swapUsed / swapTotal
|
||||
property double cpuUsage: 0
|
||||
property var previousCpuStats
|
||||
|
||||
Timer {
|
||||
interval: 10
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
// Reload files
|
||||
fileMeminfo.reload()
|
||||
fileStat.reload()
|
||||
|
||||
// Parse memory and swap usage
|
||||
const textMeminfo = fileMeminfo.text()
|
||||
memoryTotal = Number(textMeminfo.match(/MemTotal: *(\d+)/)?.[1] ?? 1)
|
||||
memoryFree = Number(textMeminfo.match(/MemAvailable: *(\d+)/)?.[1] ?? 0)
|
||||
swapTotal = Number(textMeminfo.match(/SwapTotal: *(\d+)/)?.[1] ?? 1)
|
||||
swapFree = Number(textMeminfo.match(/SwapFree: *(\d+)/)?.[1] ?? 0)
|
||||
|
||||
// Parse CPU usage
|
||||
const textStat = fileStat.text()
|
||||
const cpuLine = textStat.match(/^cpu\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/)
|
||||
if (cpuLine) {
|
||||
const stats = cpuLine.slice(1).map(Number)
|
||||
const total = stats.reduce((a, b) => a + b, 0)
|
||||
const idle = stats[3]
|
||||
|
||||
if (previousCpuStats) {
|
||||
const totalDiff = total - previousCpuStats.total
|
||||
const idleDiff = idle - previousCpuStats.idle
|
||||
cpuUsage = totalDiff > 0 ? (1 - idleDiff / totalDiff) : 0
|
||||
}
|
||||
|
||||
previousCpuStats = { total, idle }
|
||||
}
|
||||
interval = ConfigOptions.resources.updateInterval
|
||||
}
|
||||
}
|
||||
|
||||
FileView { id: fileMeminfo; path: "/proc/meminfo" }
|
||||
FileView { id: fileStat; path: "/proc/stat" }
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
pragma Singleton
|
||||
|
||||
Singleton {
|
||||
property string distroName: "Unknown"
|
||||
property string distroId: "unknown"
|
||||
property string distroIcon: "linux-symbolic"
|
||||
|
||||
Timer {
|
||||
interval: 1
|
||||
running: true
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
fileOsRelease.reload()
|
||||
const textOsRelease = fileOsRelease.text()
|
||||
|
||||
// Extract the friendly name (PRETTY_NAME field, fallback to NAME)
|
||||
const prettyNameMatch = textOsRelease.match(/^PRETTY_NAME="(.+?)"/m)
|
||||
const nameMatch = textOsRelease.match(/^NAME="(.+?)"/m)
|
||||
distroName = prettyNameMatch ? prettyNameMatch[1] : (nameMatch ? nameMatch[1].replace(/Linux/i, "").trim() : "Unknown")
|
||||
|
||||
// Extract the ID (LOGO field, fallback to "unknown")
|
||||
const logoMatch = textOsRelease.match(/^LOGO=(.+)$/m)
|
||||
distroId = logoMatch ? logoMatch[1].replace(/"/g, "") : "unknown"
|
||||
|
||||
// Update the distroIcon property based on distroId
|
||||
switch (distroId) {
|
||||
case "arch": distroIcon = "arch-symbolic"; break;
|
||||
case "endeavouros": distroIcon = "endeavouros-symbolic"; break;
|
||||
case "cachyos": distroIcon = "cachyos-symbolic"; break;
|
||||
case "nixos": distroIcon = "nixos-symbolic"; break;
|
||||
case "fedora": distroIcon = "fedora-symbolic"; break;
|
||||
case "linuxmint":
|
||||
case "ubuntu":
|
||||
case "zorin":
|
||||
case "popos": distroIcon = "ubuntu-symbolic"; break;
|
||||
case "debian":
|
||||
case "raspbian":
|
||||
case "kali": distroIcon = "debian-symbolic"; break;
|
||||
default: distroIcon = "linux-symbolic"; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: fileOsRelease
|
||||
path: "/etc/os-release"
|
||||
}
|
||||
}
|
||||
@@ -6,16 +6,25 @@ import QtQuick.Layouts
|
||||
|
||||
ToolTip {
|
||||
property string content
|
||||
parent: parent
|
||||
visible: parent.hovered
|
||||
property bool extraVisibleCondition: true
|
||||
padding: 7
|
||||
|
||||
visible: (extraVisibleCondition && parent.hovered)
|
||||
|
||||
background: Rectangle {
|
||||
color: Appearance.colors.colTooltip
|
||||
radius: Appearance.rounding.small
|
||||
width: tooltipText.width + 2 * padding
|
||||
width: tooltipTextObject.width + 2 * padding
|
||||
Behavior on opacity {
|
||||
OpacityAnimator {
|
||||
duration: Appearance.animation.elementDecel.duration
|
||||
easing.type: Appearance.animation.elementDecel.type
|
||||
}
|
||||
}
|
||||
opacity: visible ? 1 : 0
|
||||
}
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
id: tooltipTextObject
|
||||
text: content
|
||||
color: Appearance.colors.colOnTooltip
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
@@ -13,13 +13,13 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
radius: Appearance.rounding.normal
|
||||
color: Appearance.colors.colLayer1
|
||||
implicitHeight: 343 // TODO NO HARD CODE
|
||||
// implicitHeight: 343 // TODO NO HARD CODE
|
||||
height: calendarWidgetRow.height
|
||||
|
||||
RowLayout {
|
||||
id: calendarRow
|
||||
anchors.fill: parent
|
||||
// width: parent.width - 10 * 2
|
||||
height: parent.height - 10 * 2
|
||||
id: calendarWidgetRow
|
||||
anchors.fill: parent
|
||||
height: tabStack.height
|
||||
spacing: 10
|
||||
property int selectedTab: 0
|
||||
|
||||
@@ -36,11 +36,11 @@ Rectangle {
|
||||
{"name": "To Do", "icon": "done_outline"}
|
||||
]
|
||||
NavRailButton {
|
||||
toggled: calendarRow.selectedTab == index
|
||||
toggled: calendarWidgetRow.selectedTab == index
|
||||
buttonText: modelData.name
|
||||
buttonIcon: modelData.icon
|
||||
onClicked: {
|
||||
calendarRow.selectedTab = index
|
||||
calendarWidgetRow.selectedTab = index
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ Rectangle {
|
||||
StackLayout {
|
||||
id: tabStack
|
||||
Layout.fillWidth: true
|
||||
// Layout.fillHeight: true
|
||||
height: 358 // ???? wtf
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
property int realIndex: 0
|
||||
property int animationDuration: Appearance.animation.elementDecel.duration * 1.5
|
||||
@@ -65,6 +65,7 @@ Rectangle {
|
||||
height: calendarColumn.height
|
||||
property int monthShift: 0
|
||||
property var viewingDate: CalendarLayout.getDateInXMonthsTime(monthShift)
|
||||
property var calendarLayout: CalendarLayout.getCalendarLayout(viewingDate, monthShift === 0)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@@ -84,18 +85,13 @@ Rectangle {
|
||||
// Calendar header
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: false
|
||||
spacing: 5
|
||||
CalendarHeaderButton {
|
||||
buttonText: `${monthShift != 0 ? "• " : ""}${viewingDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")}`
|
||||
tooltipText: (monthShift === 0) ? "" : "Jump to current month"
|
||||
onClicked: {
|
||||
monthShift = 0;
|
||||
}
|
||||
content: StyledText {
|
||||
text: `${monthShift != 0 ? "• " : ""}${viewingDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")}`
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
color: Appearance.colors.colOnLayer1
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
@@ -106,9 +102,9 @@ Rectangle {
|
||||
onClicked: {
|
||||
monthShift--;
|
||||
}
|
||||
content: MaterialSymbol {
|
||||
contentItem: MaterialSymbol {
|
||||
text: "chevron_left"
|
||||
font.pixelSize: Appearance.font.pixelSize.large
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Appearance.colors.colOnLayer1
|
||||
}
|
||||
@@ -118,9 +114,9 @@ Rectangle {
|
||||
onClicked: {
|
||||
monthShift++;
|
||||
}
|
||||
content: MaterialSymbol {
|
||||
contentItem: MaterialSymbol {
|
||||
text: "chevron_right"
|
||||
font.pixelSize: Appearance.font.pixelSize.large
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Appearance.colors.colOnLayer1
|
||||
}
|
||||
@@ -147,16 +143,17 @@ Rectangle {
|
||||
// Real week rows
|
||||
Repeater {
|
||||
id: calendarRows
|
||||
model: CalendarLayout.getCalendarLayout(viewingDate, monthShift === 0)
|
||||
// model: calendarLayout
|
||||
model: 6
|
||||
delegate: RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillHeight: false
|
||||
spacing: 5
|
||||
Repeater {
|
||||
model: modelData
|
||||
model: Array(7).fill(modelData)
|
||||
delegate: CalendarDayButton {
|
||||
day: modelData.day
|
||||
isToday: modelData.today
|
||||
day: calendarLayout[modelData][index].day
|
||||
isToday: calendarLayout[modelData][index].today
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,10 +183,10 @@ Rectangle {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: calendarRow
|
||||
target: calendarWidgetRow
|
||||
function onSelectedTabChanged() {
|
||||
delayedStackSwitch.start()
|
||||
tabStack.realIndex = calendarRow.selectedTab
|
||||
tabStack.realIndex = calendarWidgetRow.selectedTab
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
@@ -197,7 +194,7 @@ Rectangle {
|
||||
interval: tabStack.animationDuration / 2
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
tabStack.currentIndex = calendarRow.selectedTab
|
||||
tabStack.currentIndex = calendarWidgetRow.selectedTab
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import "root:/services"
|
||||
import "./quickToggles/"
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
@@ -129,8 +130,8 @@ Scope {
|
||||
anchors.margins: 5
|
||||
spacing: 5
|
||||
|
||||
Network {}
|
||||
Bluetooth {}
|
||||
NetworkToggle {}
|
||||
BluetoothToggle {}
|
||||
NightLight {}
|
||||
GameMode {}
|
||||
IdleInhibitor {}
|
||||
|
||||
@@ -6,12 +6,19 @@ import QtQuick.Layouts
|
||||
|
||||
Button {
|
||||
id: button
|
||||
required default property Item content
|
||||
property string buttonText: ""
|
||||
property string tooltipText: ""
|
||||
property bool forceCircle: false
|
||||
|
||||
implicitHeight: 30
|
||||
implicitWidth: forceCircle ? implicitHeight : (contentItem.implicitWidth + 10 * 2)
|
||||
|
||||
Behavior on implicitWidth {
|
||||
SmoothedAnimation {
|
||||
velocity: Appearance.animation.elementDecel.velocity
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Appearance.rounding.full
|
||||
@@ -26,6 +33,15 @@ Button {
|
||||
}
|
||||
|
||||
}
|
||||
contentItem: content
|
||||
contentItem: StyledText {
|
||||
text: buttonText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Appearance.font.pixelSize.larger
|
||||
color: Appearance.colors.colOnLayer1
|
||||
}
|
||||
|
||||
StyledToolTip {
|
||||
content: tooltipText
|
||||
extraVisibleCondition: tooltipText.length > 0
|
||||
}
|
||||
}
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
import "../"
|
||||
import "root:/services"
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import QtQuick
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
import "root:/modules/common"
|
||||
import "root:/modules/common/widgets"
|
||||
import "root:/services"
|
||||
import "../"
|
||||
import Quickshell.Io
|
||||
import Quickshell
|
||||
Reference in New Issue
Block a user