calendar
This commit is contained in:
+134
-128
@@ -9,147 +9,153 @@ import qs.Helpers
|
||||
import qs.Daemons
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
|
||||
readonly property int vPadding: 6
|
||||
required property Wrapper popouts
|
||||
required property PanelWindow bar
|
||||
readonly property int vPadding: 6
|
||||
required property Wrapper popouts
|
||||
required property PanelWindow bar
|
||||
|
||||
function checkPopout(x: real): void {
|
||||
const ch = childAt(x, height / 2) as WrappedLoader;
|
||||
function checkPopout(x: real): void {
|
||||
const ch = childAt(x, height / 2) as WrappedLoader;
|
||||
|
||||
if (!ch) {
|
||||
popouts.hasCurrent = false;
|
||||
return;
|
||||
}
|
||||
if (!ch) {
|
||||
popouts.hasCurrent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const id = ch.id;
|
||||
const top = ch.x;
|
||||
const item = ch.item;
|
||||
const itemWidth = item.implicitWidth;
|
||||
const id = ch.id;
|
||||
const top = ch.x;
|
||||
const item = ch.item;
|
||||
const itemWidth = item.implicitWidth;
|
||||
|
||||
|
||||
if (id === "audio" && Config.barConfig.popouts.audio) {
|
||||
popouts.currentName = "audio";
|
||||
popouts.currentCenter = Qt.binding( () => item.mapToItem(root, itemWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
} else if ( id === "resources" && Config.barConfig.popouts.resources ) {
|
||||
popouts.currentName = "resources";
|
||||
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
} else if ( id === "tray" && Config.barConfig.popouts.tray ) {
|
||||
const index = Math.floor((( x - top ) / item.implicitWidth ) * item.items.count );
|
||||
const trayItem = item.items.itemAt( index );
|
||||
if ( trayItem ) {
|
||||
popouts.currentName = `traymenu${ index }`;
|
||||
popouts.currentCenter = Qt.binding( () => trayItem.mapToItem( root, trayItem.implicitWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
} else {
|
||||
popouts.hasCurrent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id === "audio" && Config.barConfig.popouts.audio) {
|
||||
popouts.currentName = "audio";
|
||||
popouts.currentCenter = Qt.binding( () => item.mapToItem(root, itemWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
} else if ( id === "resources" && Config.barConfig.popouts.resources ) {
|
||||
popouts.currentName = "resources";
|
||||
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
} else if ( id === "tray" && Config.barConfig.popouts.tray ) {
|
||||
const index = Math.floor((( x - top ) / item.implicitWidth ) * item.items.count );
|
||||
const trayItem = item.items.itemAt( index );
|
||||
if ( trayItem ) {
|
||||
popouts.currentName = `traymenu${ index }`;
|
||||
popouts.currentCenter = Qt.binding( () => trayItem.mapToItem( root, trayItem.implicitWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
} else {
|
||||
popouts.hasCurrent = false;
|
||||
}
|
||||
} else if ( id === "clock" && Config.barConfig.popouts.clock ) {
|
||||
Calendar.displayYear = new Date().getFullYear();
|
||||
Calendar.displayMonth = new Date().getMonth();
|
||||
popouts.currentName = "calendar";
|
||||
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
|
||||
popouts.hasCurrent = true;
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: Config.barConfig.entries
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: Config.barConfig.entries
|
||||
|
||||
DelegateChooser {
|
||||
role: "id"
|
||||
DelegateChooser {
|
||||
role: "id"
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: "spacer"
|
||||
delegate: WrappedLoader {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "workspaces"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: Workspaces {
|
||||
bar: root.bar
|
||||
}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "audio"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: AudioWidget {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "tray"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: TrayWidget {
|
||||
bar: root.bar
|
||||
}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "resources"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: Resources {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "updates"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: UpdatesWidget {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "notifBell"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: NotifBell {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "clock"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: Clock {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "activeWindow"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: WindowTitle {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "spacer"
|
||||
delegate: WrappedLoader {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "workspaces"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: Workspaces {
|
||||
bar: root.bar
|
||||
}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "audio"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: AudioWidget {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "tray"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: TrayWidget {
|
||||
bar: root.bar
|
||||
}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "resources"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: Resources {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "updates"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: UpdatesWidget {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "notifBell"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: NotifBell {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "clock"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: Clock {}
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "activeWindow"
|
||||
delegate: WrappedLoader {
|
||||
sourceComponent: WindowTitle {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component WrappedLoader: Loader {
|
||||
required property bool enabled
|
||||
required property string id
|
||||
required property int index
|
||||
component WrappedLoader: Loader {
|
||||
required property bool enabled
|
||||
required property string id
|
||||
required property int index
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillHeight: true
|
||||
|
||||
function findFirstEnabled(): Item {
|
||||
const count = repeater.count;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = repeater.itemAt(i);
|
||||
if (item?.enabled)
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function findFirstEnabled(): Item {
|
||||
const count = repeater.count;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = repeater.itemAt(i);
|
||||
if (item?.enabled)
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findLastEnabled(): Item {
|
||||
for (let i = repeater.count - 1; i >= 0; i--) {
|
||||
const item = repeater.itemAt(i);
|
||||
if (item?.enabled)
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function findLastEnabled(): Item {
|
||||
for (let i = repeater.count - 1; i >= 0; i--) {
|
||||
const item = repeater.itemAt(i);
|
||||
if (item?.enabled)
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
|
||||
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
|
||||
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
|
||||
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
|
||||
|
||||
visible: enabled
|
||||
active: enabled
|
||||
}
|
||||
visible: enabled
|
||||
active: enabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Components
|
||||
import qs.Config
|
||||
import qs.Helpers
|
||||
|
||||
RowLayout {
|
||||
spacing: 12
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 40
|
||||
Layout.preferredHeight: 40
|
||||
color: "transparent"
|
||||
radius: 1000
|
||||
|
||||
CustomText {
|
||||
text: "◀"
|
||||
font.pointSize: 12
|
||||
color: DynamicColors.palette.m3onSurface
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
onClicked: {
|
||||
if (Calendar.displayMonth === 0) {
|
||||
Calendar.displayMonth = 11;
|
||||
Calendar.displayYear -= 1;
|
||||
} else {
|
||||
Calendar.displayMonth -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomText {
|
||||
text: new Date(Calendar.displayYear, Calendar.displayMonth, 1).toLocaleDateString(
|
||||
Qt.locale(),
|
||||
"MMMM yyyy"
|
||||
)
|
||||
font.weight: 600
|
||||
font.pointSize: 14
|
||||
color: DynamicColors.palette.m3onSurface
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 40
|
||||
Layout.preferredHeight: 40
|
||||
color: "transparent"
|
||||
radius: 1000
|
||||
|
||||
CustomText {
|
||||
text: "▶"
|
||||
font.pointSize: 12
|
||||
color: DynamicColors.palette.m3onSurface
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
onClicked: {
|
||||
if (Calendar.displayMonth === 11) {
|
||||
Calendar.displayMonth = 0;
|
||||
Calendar.displayYear += 1;
|
||||
} else {
|
||||
Calendar.displayMonth += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Components
|
||||
import qs.Config
|
||||
import qs.Helpers
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property Item wrapper
|
||||
|
||||
implicitWidth: layout.childrenRect.width + layout.anchors.margins * 2
|
||||
implicitHeight: layout.childrenRect.height + layout.anchors.margins * 2
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
anchors.centerIn: parent
|
||||
anchors.margins: 16
|
||||
spacing: 16
|
||||
|
||||
// Header with month/year and navigation
|
||||
CalendarHeader {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
}
|
||||
|
||||
// Calendar grid
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
spacing: 12
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
Layout.preferredWidth: weekNumberColumn.width
|
||||
spacing: 8
|
||||
|
||||
Item {
|
||||
Layout.preferredHeight: dayOfWeekRow.height
|
||||
}
|
||||
|
||||
WeekNumberColumn {
|
||||
id: weekNumberColumn
|
||||
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredHeight: weekNumbers.values.length * 44
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
spacing: 8
|
||||
|
||||
DayOfWeekRow {
|
||||
id: dayOfWeekRow
|
||||
locale: Qt.locale()
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 30
|
||||
}
|
||||
|
||||
MonthGrid {
|
||||
locale: Qt.locale()
|
||||
|
||||
wrapper: root.wrapper
|
||||
Layout.preferredWidth: childrenRect.width
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Components
|
||||
import qs.Config
|
||||
import qs.Helpers
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
required property var locale
|
||||
|
||||
spacing: 4
|
||||
|
||||
Repeater {
|
||||
model: 7
|
||||
|
||||
Item {
|
||||
required property int index
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 30
|
||||
|
||||
readonly property string dayName: {
|
||||
// Get the day name for this column
|
||||
const dayIndex = (index + Calendar.weekStartDay) % 7;
|
||||
return root.locale.dayName(dayIndex, Locale.ShortFormat);
|
||||
}
|
||||
|
||||
CustomText {
|
||||
anchors.centerIn: parent
|
||||
|
||||
text: parent.dayName
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: DynamicColors.palette.m3onSurfaceVariant
|
||||
opacity: 0.8
|
||||
font.weight: 500
|
||||
font.pointSize: 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Components
|
||||
import qs.Config
|
||||
import qs.Helpers
|
||||
|
||||
GridLayout {
|
||||
id: root
|
||||
|
||||
required property var locale
|
||||
required property Item wrapper
|
||||
|
||||
columns: 7
|
||||
rowSpacing: 4
|
||||
columnSpacing: 4
|
||||
uniformCellWidths: true
|
||||
uniformCellHeights: true
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
target: root
|
||||
duration: MaterialEasing.expressiveEffectsTime
|
||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: ScriptModel {
|
||||
values: Calendar.getWeeksForMonth(Calendar.displayMonth, Calendar.displayYear)
|
||||
|
||||
Behavior on values {
|
||||
SequentialAnimation {
|
||||
id: switchAnim
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
property: "opacity"
|
||||
from: 1.0
|
||||
to: 0.0
|
||||
}
|
||||
Anim {
|
||||
property: "scale"
|
||||
from: 1.0
|
||||
to: 0.8
|
||||
}
|
||||
}
|
||||
PropertyAction {}
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
property: "opacity"
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
}
|
||||
Anim {
|
||||
property: "scale"
|
||||
from: 0.8
|
||||
to: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
Layout.preferredWidth: 40
|
||||
Layout.preferredHeight: width
|
||||
|
||||
|
||||
radius: 1000
|
||||
color: {
|
||||
if (modelData.isToday) {
|
||||
console.log(width);
|
||||
return DynamicColors.palette.m3primaryContainer;
|
||||
}
|
||||
return "transparent";
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
CustomText {
|
||||
anchors.centerIn: parent
|
||||
|
||||
text: parent.modelData.day.toString()
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
opacity: parent.modelData.isCurrentMonth ? 1.0 : 0.4
|
||||
color: {
|
||||
if (parent.modelData.isToday) {
|
||||
return DynamicColors.palette.m3onPrimaryContainer;
|
||||
}
|
||||
return DynamicColors.palette.m3onSurface;
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 200 }
|
||||
}
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200 }
|
||||
}
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
color: DynamicColors.palette.m3onSurface
|
||||
onClicked: {
|
||||
console.log(`Selected date: ${parent.modelData.day}/${parent.modelData.month + 1}/${parent.modelData.year}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Components
|
||||
import qs.Config
|
||||
import qs.Helpers
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
spacing: 4
|
||||
|
||||
readonly property var weekNumbers: Calendar.getWeekNumbers(Calendar.displayMonth, Calendar.displayYear)
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: root.weekNumbers
|
||||
}
|
||||
|
||||
Item {
|
||||
id: weekItem
|
||||
Layout.preferredHeight: 40
|
||||
Layout.preferredWidth: 20
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
required property int index
|
||||
required property var modelData
|
||||
|
||||
CustomText {
|
||||
id: weekText
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
text: weekItem.modelData
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: DynamicColors.palette.m3onSurfaceVariant
|
||||
opacity: 0.5
|
||||
font.pointSize: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import Quickshell
|
||||
import Quickshell.Services.SystemTray
|
||||
import QtQuick
|
||||
import qs.Config
|
||||
import qs.Modules.Calendar
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -69,6 +70,13 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Popout {
|
||||
name: "calendar"
|
||||
sourceComponent: CalendarPopup {
|
||||
wrapper: root.wrapper
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Popout: Loader {
|
||||
|
||||
@@ -62,7 +62,6 @@ WlSessionLockSurface {
|
||||
onTextChanged: text = ""
|
||||
}
|
||||
|
||||
|
||||
ScreencopyView {
|
||||
id: background
|
||||
|
||||
@@ -84,14 +83,11 @@ WlSessionLockSurface {
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
CachingImage {
|
||||
id: backgroundImage
|
||||
anchors.fill: parent
|
||||
asynchronous: false
|
||||
cache: false
|
||||
source: WallpaperPath.currentWallpaperPath
|
||||
sourceSize.width: root.screen.width
|
||||
sourceSize.height: root.screen.height
|
||||
path: WallpaperPath.currentWallpaperPath
|
||||
visible: Config.lock.useWallpaper
|
||||
|
||||
Component.onCompleted: {
|
||||
|
||||
Reference in New Issue
Block a user