// The contents of the date menu, in GNOME's order: date header, notifications, // calendar, weather. // // Kept separate from DateMenu.qml (the PanelWindow) so it can be dropped into a // FloatingWindow for testing — layer-shell surfaces cannot map outside a // wlroots compositor. import QtQuick import Quickshell import qs.config import qs.services import qs.widgets Item { id: root implicitWidth: 480 implicitHeight: content.implicitHeight + Theme.popoverPadding * 2 // Called by the window when it opens and closes, so the panel is always in // a known state rather than wherever the last visit left it. function prepare(): void { calendar.showToday(); } function reset(): void { notifications.reset(); } // Minutes precision: the header only shows a date, so this exists purely to // roll it over at midnight without a per-second wake. SystemClock { id: clock precision: SystemClock.Minutes } Column { id: content anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.margins: Theme.popoverPadding spacing: Theme.sectionSpacing // ── Header ────────────────────────────────────────────────────────── Item { width: parent.width height: 34 Text { anchors.left: parent.left anchors.leftMargin: 4 anchors.right: headerActions.left anchors.rightMargin: Theme.itemSpacing anchors.verticalCenter: parent.verticalCenter text: Qt.formatDateTime(clock.date, "dddd, MMMM d") color: Theme.fg elide: Text.ElideRight font.family: Theme.fontFamily // The day number changes in place at midnight. font.features: Theme.tabularFigures font.pixelSize: Theme.fontSizeTitle font.weight: Font.DemiBold } Row { id: headerActions anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter spacing: 6 // Labelled rather than icon-only: an unexplained crossed-out // bell is exactly the kind of thing a normal person has to // click to find out about. Rectangle { id: dndPill anchors.verticalCenter: parent.verticalCenter width: dndRow.implicitWidth + 20 height: 28 radius: Theme.pillRadius border.width: 0 color: { if (Notifs.doNotDisturb) return dndMouse.containsMouse ? Theme.alpha(Theme.accent, 0.42) : Theme.alpha(Theme.accent, 0.28); return dndMouse.containsMouse ? Theme.alpha(Theme.fg, 0.16) : Theme.alpha(Theme.fg, 0.08); } Behavior on color { ColorAnimation { duration: dndMouse.containsMouse ? Theme.durFast : Theme.durNormal } } Row { id: dndRow anchors.centerIn: parent spacing: 6 ThemedIcon { anchors.verticalCenter: parent.verticalCenter size: 14 icon: "notifications-disabled-symbolic" iconFallback: "user-invisible-symbolic" tint: Notifs.doNotDisturb ? Theme.accent : Theme.fgDim } Text { anchors.verticalCenter: parent.verticalCenter text: "Do Not Disturb" color: Notifs.doNotDisturb ? Theme.accent : Theme.fg font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall font.weight: Font.Medium } } MouseArea { id: dndMouse anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: Notifs.doNotDisturb = !Notifs.doNotDisturb } } Rectangle { id: clearPill anchors.verticalCenter: parent.verticalCenter width: clearLabel.implicitWidth + 20 height: 28 radius: Theme.pillRadius border.width: 0 // Hidden rather than disabled: there is nothing ambiguous // about an empty tray, so the control has no job. visible: Notifs.hasNotifications color: clearMouse.containsMouse ? Theme.alpha(Theme.fg, 0.16) : Theme.alpha(Theme.fg, 0.08) Behavior on color { ColorAnimation { duration: clearMouse.containsMouse ? Theme.durFast : Theme.durNormal } } Text { id: clearLabel anchors.centerIn: parent text: "Clear all" color: Theme.fg font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall font.weight: Font.Medium } MouseArea { id: clearMouse anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: Notifs.dismissAll() } } } } // ── Notifications ─────────────────────────────────────────────────── Rectangle { width: parent.width height: 1 border.width: 0 color: Theme.alpha(Theme.fg, 0.1) } MediaCard { id: media width: parent.width } Rectangle { width: parent.width height: 1 border.width: 0 visible: media.visible color: Theme.alpha(Theme.fg, 0.1) } NotificationList { id: notifications width: parent.width } // ── Calendar ──────────────────────────────────────────────────────── Rectangle { width: parent.width height: 1 border.width: 0 color: Theme.alpha(Theme.fg, 0.1) } CalendarGrid { id: calendar width: parent.width } // ── Weather ───────────────────────────────────────────────────────── // Separator and card share one condition so the panel does not end on a // rule with nothing under it. Rectangle { width: parent.width height: 1 border.width: 0 visible: Weather.available color: Theme.alpha(Theme.fg, 0.1) } WeatherCard { width: parent.width visible: Weather.available } } }