forked from Shinonome/dots-hyprland
wbar: add updates indicator
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
sodipodi:docname="arrow-sync.svg"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="25.868323"
|
||||||
|
inkscape:cx="14.245222"
|
||||||
|
inkscape:cy="12.447657"
|
||||||
|
inkscape:window-width="1498"
|
||||||
|
inkscape:window-height="1020"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg1" />
|
||||||
|
<path
|
||||||
|
d="m 19.947024,13.17933 a 0.75,0.75 0 0 0 -0.907212,0.549312 7.251,7.251 0 0 1 -13.334866,1.873667 l 0.8908023,0.350894 a 0.75,0.75 0 0 0 0.6494514,-1.347747 l -0.100442,-0.04793 -2.6316174,-1.036623 a 0.75,0.75 0 0 0 -0.9241627,0.322228 l -0.047921,0.100457 -1.0366214,2.631619 a 0.75,0.75 0 0 0 1.3468323,0.649854 l 0.048321,-0.09951 0.3887326,-0.986859 A 8.75,8.75 0 0 0 20.494492,14.087329 0.75,0.75 0 0 0 19.946102,13.179722 Z M 21.068469,6.4543893 A 0.75,0.75 0 0 0 20.096388,6.8770607 L 19.707652,7.863919 A 8.75,8.75 0 0 0 3.5868012,9.5848274 0.75043107,0.75043107 0 1 0 5.0290446,10.000183 7.251,7.251 0 0 1 18.290631,8.3993655 l -0.8904,-0.3499798 a 0.75,0.75 0 1 0 -0.549014,1.3956769 l 2.631617,1.0366214 a 0.75,0.75 0 0 0 0.972088,-0.422667 L 21.491544,7.4273949 A 0.75,0.75 0 0 0 21.068874,6.455308 Z"
|
||||||
|
fill="#212121"
|
||||||
|
id="path1" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -537,6 +537,12 @@ Singleton {
|
|||||||
property bool secondPrecision: false
|
property bool secondPrecision: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property JsonObject updates: JsonObject {
|
||||||
|
property int checkInterval: 120 // minutes
|
||||||
|
property int adviseUpdateThreshold: 75 // packages
|
||||||
|
property int stronglyAdviseUpdateThreshold: 200 // packages
|
||||||
|
}
|
||||||
|
|
||||||
property JsonObject wallpaperSelector: JsonObject {
|
property JsonObject wallpaperSelector: JsonObject {
|
||||||
property bool useSystemFileDialog: false
|
property bool useSystemFileDialog: false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ BarPopup {
|
|||||||
id: root
|
id: root
|
||||||
default property var menuData
|
default property var menuData
|
||||||
property var model: [
|
property var model: [
|
||||||
{iconName: "start-here", text: "Start", action: () => {print("hello")}}
|
{ iconName: "start-here", text: "Start", action: () => {print("hello")} },
|
||||||
|
{ type : "separator" },
|
||||||
]
|
]
|
||||||
|
readonly property bool hasIcons: model.some(item => item.iconName !== undefined && item.iconName !== "")
|
||||||
padding: 2
|
padding: 2
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
@@ -21,18 +23,35 @@ BarPopup {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.model
|
model: root.model
|
||||||
delegate: WButton {
|
delegate: DelegateChooser {
|
||||||
id: btn
|
role: "type"
|
||||||
Layout.fillWidth: true
|
DelegateChoice {
|
||||||
|
roleValue: "separator"
|
||||||
|
Rectangle {
|
||||||
|
Layout.topMargin: 2
|
||||||
|
Layout.bottomMargin: 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: 1
|
||||||
|
color: Looks.colors.bg0Border
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: undefined
|
||||||
|
WButton {
|
||||||
|
id: btn
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
required property var modelData
|
required property var modelData
|
||||||
icon.name: modelData.iconName ? modelData.iconName : ""
|
forceShowIcon: root.hasIcons
|
||||||
monochromeIcon: modelData.monochromeIcon ?? true
|
icon.name: modelData.iconName ? modelData.iconName : ""
|
||||||
text: modelData.text ? modelData.text : ""
|
monochromeIcon: modelData.monochromeIcon ?? true
|
||||||
|
text: modelData.text ? modelData.text : ""
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (modelData.action) modelData.action();
|
if (modelData.action) modelData.action();
|
||||||
root.close();
|
root.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ Loader {
|
|||||||
fill: realContent
|
fill: realContent
|
||||||
margins: -border.width
|
margins: -border.width
|
||||||
}
|
}
|
||||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
|
border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency)
|
||||||
border.width: root.ambientShadowWidth
|
border.width: root.ambientShadowWidth
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: realContent.radius + border.width
|
radius: realContent.radius + border.width
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs
|
||||||
|
import qs.services
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.waffle.looks
|
||||||
|
|
||||||
|
BarButton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
visible: Updates.available && Updates.updateAdvised
|
||||||
|
|
||||||
|
padding: 4
|
||||||
|
contentItem: Item {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
implicitWidth: iconContent.implicitWidth
|
||||||
|
implicitHeight: iconContent.implicitHeight
|
||||||
|
|
||||||
|
FluentIcon {
|
||||||
|
id: iconContent
|
||||||
|
anchors.centerIn: parent
|
||||||
|
icon: "arrow-sync"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
margins: 1
|
||||||
|
}
|
||||||
|
implicitWidth: 8
|
||||||
|
implicitHeight: implicitWidth
|
||||||
|
radius: height / 2
|
||||||
|
color: Updates.updateStronglyAdvised ? Looks.colors.warning : Looks.colors.accent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BarToolTip {
|
||||||
|
extraVisibleCondition: root.shouldShowTooltip
|
||||||
|
text: Translation.tr("Get the latest features and security improvements with\nthe newest feature update.\n\n%1 packages").arg(Updates.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,6 +68,7 @@ Rectangle {
|
|||||||
shown: Config.options.waffles.bar.leftAlignApps
|
shown: Config.options.waffles.bar.leftAlignApps
|
||||||
sourceComponent: WidgetsButton {}
|
sourceComponent: WidgetsButton {}
|
||||||
}
|
}
|
||||||
|
UpdatesButton {}
|
||||||
SystemButton {}
|
SystemButton {}
|
||||||
TimeButton {}
|
TimeButton {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,13 @@ AppButton {
|
|||||||
id: contextMenu
|
id: contextMenu
|
||||||
|
|
||||||
model: [
|
model: [
|
||||||
|
...((root.desktopEntry?.actions.length > 0) ? root.desktopEntry.actions.map(action =>({
|
||||||
|
iconName: action.icon,
|
||||||
|
text: action.name,
|
||||||
|
action: () => {
|
||||||
|
action.execute()
|
||||||
|
}
|
||||||
|
})).concat({ type: "separator" }) : []),
|
||||||
{
|
{
|
||||||
iconName: root.iconName,
|
iconName: root.iconName,
|
||||||
text: root.desktopEntry ? root.desktopEntry.name : StringUtils.toTitleCase(appEntry.appId),
|
text: root.desktopEntry ? root.desktopEntry.name : StringUtils.toTitleCase(appEntry.appId),
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ PopupWindow {
|
|||||||
fill: contentItem
|
fill: contentItem
|
||||||
margins: -border.width
|
margins: -border.width
|
||||||
}
|
}
|
||||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
|
border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: Looks.radius.large + border.width
|
radius: Looks.radius.large + border.width
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ Singleton {
|
|||||||
property real shadowTransparency: 0.6
|
property real shadowTransparency: 0.6
|
||||||
colors: QtObject {
|
colors: QtObject {
|
||||||
id: colors
|
id: colors
|
||||||
|
property color ambientShadow: ColorUtils.transparentize("#000000", 0.4)
|
||||||
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
|
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
|
||||||
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
|
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
|
||||||
property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
|
property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
|
||||||
@@ -34,6 +35,7 @@ Singleton {
|
|||||||
property color fg1: root.dark ? "#D1D1D1" : "#626262"
|
property color fg1: root.dark ? "#D1D1D1" : "#626262"
|
||||||
property color danger: "#C42B1C"
|
property color danger: "#C42B1C"
|
||||||
property color dangerActive: "#B62D1F"
|
property color dangerActive: "#B62D1F"
|
||||||
|
property color warning: "#FF9900"
|
||||||
// property color accent: root.dark ? "#A5C6D8" : "#5377A3"
|
// property color accent: root.dark ? "#A5C6D8" : "#5377A3"
|
||||||
property color accent: Appearance.m3colors.m3primary
|
property color accent: Appearance.m3colors.m3primary
|
||||||
property color accentUnfocused: root.dark ? "#989898" : "#848484"
|
property color accentUnfocused: root.dark ? "#989898" : "#848484"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Button {
|
|||||||
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
|
||||||
|
|
||||||
property alias monochromeIcon: buttonIcon.monochrome
|
property alias monochromeIcon: buttonIcon.monochrome
|
||||||
|
property bool forceShowIcon: false
|
||||||
|
|
||||||
property var altAction: () => {}
|
property var altAction: () => {}
|
||||||
property var middleClickAction: () => {}
|
property var middleClickAction: () => {}
|
||||||
@@ -71,12 +72,12 @@ Button {
|
|||||||
spacing: 12
|
spacing: 12
|
||||||
FluentIcon {
|
FluentIcon {
|
||||||
id: buttonIcon
|
id: buttonIcon
|
||||||
|
visible: root.icon.name !== "" || root.forceShowIcon
|
||||||
monochrome: true
|
monochrome: true
|
||||||
implicitSize: 16
|
implicitSize: 16
|
||||||
Layout.leftMargin: 6
|
Layout.leftMargin: 6
|
||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
visible: root.icon.name !== ""
|
|
||||||
icon: root.icon.name
|
icon: root.icon.name
|
||||||
}
|
}
|
||||||
WText {
|
WText {
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import qs.modules.waffle.looks
|
|||||||
PopupToolTip {
|
PopupToolTip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real padding: 2
|
property real visualMargin: 11
|
||||||
verticalPadding: padding
|
verticalPadding: visualMargin
|
||||||
horizontalPadding: padding
|
horizontalPadding: visualMargin
|
||||||
|
|
||||||
contentItem: Item {
|
contentItem: Item {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
implicitWidth: realContent.implicitWidth + root.verticalPadding * 2
|
implicitWidth: realContent.implicitWidth + 2 * 2
|
||||||
implicitHeight: realContent.implicitHeight + root.horizontalPadding * 2
|
implicitHeight: realContent.implicitHeight + 2 * 2
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: ambientShadow
|
id: ambientShadow
|
||||||
@@ -26,7 +26,7 @@ PopupToolTip {
|
|||||||
fill: realContent
|
fill: realContent
|
||||||
margins: -border.width
|
margins: -border.width
|
||||||
}
|
}
|
||||||
border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency)
|
border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: realContent.radius + border.width
|
radius: realContent.radius + border.width
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.functions
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System updates service. Currently only supports Arch.
|
||||||
|
*/
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool available: false
|
||||||
|
property int count: 0
|
||||||
|
|
||||||
|
readonly property bool updateAdvised: available && count > Config.options.updates.adviseUpdateThreshold
|
||||||
|
readonly property bool updateStronglyAdvised: available && count > Config.options.updates.stronglyAdviseUpdateThreshold
|
||||||
|
|
||||||
|
function load() {}
|
||||||
|
function refresh() {
|
||||||
|
if (!available) return;
|
||||||
|
print("[Updates] Checking for system updates")
|
||||||
|
checkUpdatesProc.running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: Config.options.updates.checkInterval * 60 * 1000
|
||||||
|
repeat: true
|
||||||
|
running: Config.ready
|
||||||
|
onTriggered: {
|
||||||
|
print("[Updates] Periodic update check due")
|
||||||
|
root.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: checkAvailabilityProc
|
||||||
|
running: true
|
||||||
|
command: ["which", "checkupdates"]
|
||||||
|
onExited: (exitCode, exitStatus) => {
|
||||||
|
root.available = (exitCode === 0);
|
||||||
|
root.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: checkUpdatesProc
|
||||||
|
command: ["bash", "-c", "checkupdates | wc -l"]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
root.count = parseInt(text.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,6 +49,7 @@ ShellRoot {
|
|||||||
ConflictKiller.load()
|
ConflictKiller.load()
|
||||||
Cliphist.refresh()
|
Cliphist.refresh()
|
||||||
Wallpapers.load()
|
Wallpapers.load()
|
||||||
|
Updates.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load enabled stuff
|
// Load enabled stuff
|
||||||
|
|||||||
Reference in New Issue
Block a user