From 4741325f8b603ec09ad2889ad2863adc607085be Mon Sep 17 00:00:00 2001 From: James Arrowsmith Date: Thu, 5 Jan 2023 17:15:30 +1300 Subject: pacman-widget --- pacman-widget/README.md | 37 +++++ pacman-widget/icons/pacman-full.svg | 86 ++++++++++++ pacman-widget/icons/pacman.svg | 82 +++++++++++ pacman-widget/icons/upgrade.svg | 60 +++++++++ pacman-widget/pacman.lua | 254 +++++++++++++++++++++++++++++++++++ pacman-widget/screenshots/pacman.gif | Bin 0 -> 10520147 bytes pacman-widget/upgrade | 2 + 7 files changed, 521 insertions(+) create mode 100644 pacman-widget/README.md create mode 100644 pacman-widget/icons/pacman-full.svg create mode 100644 pacman-widget/icons/pacman.svg create mode 100644 pacman-widget/icons/upgrade.svg create mode 100644 pacman-widget/pacman.lua create mode 100644 pacman-widget/screenshots/pacman.gif create mode 100755 pacman-widget/upgrade diff --git a/pacman-widget/README.md b/pacman-widget/README.md new file mode 100644 index 0000000..f9c4325 --- /dev/null +++ b/pacman-widget/README.md @@ -0,0 +1,37 @@ +# Pacman widget for AwesomeWM + +This widget displays the number of upgradable Pacman packages. Clicking the icon reveals a scrollable list of available upgrades. A full system upgrade can be performed from the widget via Polkit. + +![](screenshots/pacman.gif) + +## Requirements +`lxpolkit` is the default [Polkit agent](https://wiki.archlinux.org/title/Polkit). + +The widget also uses the `checkupdates` script from the `pacman-contrib` package. + + +## Installation + +Clone the repo under **~/.config/awesome/** and add the following to **rc.lua**: + +```lua +local pacman_widget = require('pacman-widget.pacman') +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + -- default + pacman_widget(), + -- custom (shown with defaults) + pacman_widget { + interval = 600, -- Refresh every 10 minutes + popup_bg_color = '#222222', + popup_border_width = 1, + popup_border_color = '#7e7e7e', + popup_height = 10, -- 10 packages shown in scrollable window + popup_width = 300, + polkit_agent_path = '/usr/bin/lxpolkit' + }, +``` + diff --git a/pacman-widget/icons/pacman-full.svg b/pacman-widget/icons/pacman-full.svg new file mode 100644 index 0000000..50bb939 --- /dev/null +++ b/pacman-widget/icons/pacman-full.svg @@ -0,0 +1,86 @@ + + + + + + + + Gnome Symbolic Icon Theme + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + + + + + + + diff --git a/pacman-widget/icons/pacman.svg b/pacman-widget/icons/pacman.svg new file mode 100644 index 0000000..9c1cb2c --- /dev/null +++ b/pacman-widget/icons/pacman.svg @@ -0,0 +1,82 @@ + + + + + + + + Gnome Symbolic Icon Theme + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + + + + + + diff --git a/pacman-widget/icons/upgrade.svg b/pacman-widget/icons/upgrade.svg new file mode 100644 index 0000000..0a556ae --- /dev/null +++ b/pacman-widget/icons/upgrade.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + diff --git a/pacman-widget/pacman.lua b/pacman-widget/pacman.lua new file mode 100644 index 0000000..a547f6a --- /dev/null +++ b/pacman-widget/pacman.lua @@ -0,0 +1,254 @@ +local naughty = require("naughty") +local wibox = require("wibox") +local awful = require("awful") +local beautiful = require("beautiful") +local gears = require("gears") + +local DIR = os.getenv("HOME") .. "/.config/awesome/pacman-widget/" +local ICON_DIR = DIR .. "icons/" + +local pacman_widget = {} +local config = {} + +config.interval = 600 +config.popup_bg_color = "#222222" +config.popup_border_width = 1 +config.popup_border_color = "#7e7e7e" +config.popup_height = 10 +config.popup_width = 300 +config.polkit_agent_path = "/usr/bin/lxpolkit" + +local function worker(user_args) + local args, _config = user_args or {}, {} + for prop, value in pairs(config) do + _config[prop] = args[prop] or beautiful[prop] or value + end + + awful.spawn.once(_config.polkit_agent_path) + + pacman_widget = wibox.widget { + { + { + id = "icon", + resize = false, + widget = wibox.widget.imagebox, + }, + valign = "center", + layout = wibox.container.place, + }, + { + id = "txt", + font = font, + widget = wibox.widget.textbox + }, + spacing = 5, + layout = wibox.layout.fixed.horizontal, + } + function pacman_widget:set(new_value) + pacman_widget:get_children_by_id("txt")[1]:set_text(new_value) + pacman_widget:get_children_by_id("icon")[1]:set_image( + ICON_DIR .. (tonumber(new_value) > 0 and "pacman" or "pacman-full") .. ".svg" + ) + end + + local rows, ptr = wibox.layout.fixed.vertical(), 0 + rows:connect_signal("button::press", function(_,_,_,button) + if button == 4 then + if ptr > 0 then + rows.children[ptr].visible = true + ptr = ptr - 1 + end + elseif button == 5 then + if ptr < #rows.children and ((#rows.children - ptr) > _config.popup_height) then + ptr = ptr + 1 + rows.children[ptr].visible = false + end + end + end) + + local popup = awful.popup { + border_width = _config.popup_border_width, + border_color = _config.popup_border_color, + shape = gears.shape.rounded_rect, + visible = false, + ontop = true, + offset = { y = 5 }, + widget = {} + } + + pacman_widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() + if popup.visible then + popup.visible = false + else + popup.visible = true + popup:move_next_to(mouse.current_widget_geometry) + end + end) + ) + ) + + local upgr_opacity = 0.6 + local upgr_btn = wibox.widget { + { + image = ICON_DIR .. "upgrade.svg", + resize = false, + layout = wibox.widget.imagebox + }, + opacity = upgr_opacity, + layout = wibox.container.background + } + + local old_cursor, old_wibox + local busy, upgrading = false, false + upgr_btn:connect_signal("mouse::enter", function(c) + if not busy then + c:set_opacity(1) + c:emit_signal("widget::redraw_needed") + local wb = mouse.current_wibox + old_cursor, old_wibox = wb.cursor, wb + wb.cursor = "hand2" + end + end) + upgr_btn:connect_signal("mouse::leave", function(c) + if not busy then + c:set_opacity(upgr_opacity) + c:emit_signal("widget::redraw_needed") + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + end) + upgr_btn:connect_signal("button::press", function(c) + c:set_opacity(1) + c:emit_signal("widget::redraw_needed") + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + if not busy then + busy, one_shot = true, true + awful.spawn.with_line_callback("bash -c " .. DIR .. "upgrade", { + stdout = function() + if one_shot then + upgrading, one_shot = true, false + timer:emit_signal("timeout") + end + end, + stderr = function(line) + if (line ~= nil and line ~= "") then + notification = string.find(line, "warning") and + naughty.notify({ + title = "Warning!", + text = line, + timeout = 0 + }) + or + naughty.notify({ + preset = naughty.config.presets.critical, + title = "Error!", + text = line, + }) + end + end, + exit = function() + upgrading, busy = false, false + c:set_opacity(upgr_opacity) + c:emit_signal("widget::redraw_needed") + timer:emit_signal("timeout") + end, + }) + end + end) + + _, timer = awful.widget.watch([[bash -c "checkupdates 2>/dev/null"]], + _config.interval, + function(widget, stdout) + local upgrades_tbl = {} + for value in stdout:gmatch("([^\n]+)") do + upgrades_tbl[#upgrades_tbl+1] = value + end + widget:set(#upgrades_tbl) + + local popup_header_height, popup_row_height = 30, 20 + local header = wibox.widget { + { + nil, + { + markup = "" .. (upgrading and "Upgrading " .. #upgrades_tbl .. " Packages" or + (#upgrades_tbl == 0 and "No" or #upgrades_tbl) .. " Available Upgrades") .. "", + layout = wibox.widget.textbox, + }, + #upgrades_tbl > 0 and { + upgr_btn, + valign = "center", + layout = wibox.container.place, + }, + expand = "none", + layout = wibox.layout.align.horizontal, + }, + forced_height = popup_header_height, + left = 20, + right = 20, + layout = wibox.container.margin + } + + for k, v in ipairs(upgrades_tbl) do + for i = 1, #rows.children do + if v == rows.children[i]:get_txt() then goto continue end + end + local row = wibox.widget{ + { + id = "idx", + text = tostring(k), + widget = wibox.widget.textbox + }, + { + id = "txt", + text = v, + forced_height = popup_row_height, + paddings = 1, + widget = wibox.widget.textbox + }, + layout = wibox.layout.ratio.horizontal, + } + function row:get_txt() return row:get_children_by_id("txt")[1].text end + function row:set_idx(idx) row:get_children_by_id("idx")[1]:set_text(idx) end + row:ajust_ratio(2, 0.1, 0.9, 0) + rows:insert(k, row) + ::continue:: + end + + local height = popup_header_height + math.min(#upgrades_tbl, _config.popup_height) * popup_row_height + popup:setup { + { + { + { + { + header, + rows, + forced_height = height, + layout = wibox.layout.fixed.vertical + }, + content_fill_horizontal = true, + layout = wibox.container.place + }, + margins = 10, + layout = wibox.container.margin + }, + bg = _config.popup_bg_color, + layout = wibox.widget.background + }, + forced_width = _config.popup_width, + layout = wibox.layout.fixed.horizontal + } + end, + pacman_widget + ) + return pacman_widget +end + +return setmetatable(pacman_widget, { __call = function(_, ...) return worker(...) end }) + diff --git a/pacman-widget/screenshots/pacman.gif b/pacman-widget/screenshots/pacman.gif new file mode 100644 index 0000000..1c26bcc Binary files /dev/null and b/pacman-widget/screenshots/pacman.gif differ diff --git a/pacman-widget/upgrade b/pacman-widget/upgrade new file mode 100755 index 0000000..af2f9f7 --- /dev/null +++ b/pacman-widget/upgrade @@ -0,0 +1,2 @@ +#!/bin/bash +pkexec --disable-internal-agent pacman -Syu --noconfirm -- cgit v1.2.3 From 97d127b774eb3df39f18c0d6a56f9bd2a06302c7 Mon Sep 17 00:00:00 2001 From: James Arrowsmith Date: Thu, 19 Jan 2023 01:43:53 +1300 Subject: Fix luacheck warnings --- pacman-widget/pacman.lua | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/pacman-widget/pacman.lua b/pacman-widget/pacman.lua index a547f6a..3f6a930 100644 --- a/pacman-widget/pacman.lua +++ b/pacman-widget/pacman.lua @@ -8,7 +8,7 @@ local DIR = os.getenv("HOME") .. "/.config/awesome/pacman-widget/" local ICON_DIR = DIR .. "icons/" local pacman_widget = {} -local config = {} +local config, timer = {}, {} config.interval = 600 config.popup_bg_color = "#222222" @@ -38,19 +38,19 @@ local function worker(user_args) }, { id = "txt", - font = font, + font = args.font, widget = wibox.widget.textbox }, spacing = 5, layout = wibox.layout.fixed.horizontal, - } - function pacman_widget:set(new_value) + } + function pacman_widget.set(new_value) pacman_widget:get_children_by_id("txt")[1]:set_text(new_value) pacman_widget:get_children_by_id("icon")[1]:set_image( ICON_DIR .. (tonumber(new_value) > 0 and "pacman" or "pacman-full") .. ".svg" ) end - + local rows, ptr = wibox.layout.fixed.vertical(), 0 rows:connect_signal("button::press", function(_,_,_,button) if button == 4 then @@ -65,7 +65,7 @@ local function worker(user_args) end end end) - + local popup = awful.popup { border_width = _config.popup_border_width, border_color = _config.popup_border_color, @@ -83,7 +83,7 @@ local function worker(user_args) popup.visible = false else popup.visible = true - popup:move_next_to(mouse.current_widget_geometry) + popup:move_next_to(_G.mouse.current_widget_geometry) end end) ) @@ -106,13 +106,13 @@ local function worker(user_args) if not busy then c:set_opacity(1) c:emit_signal("widget::redraw_needed") - local wb = mouse.current_wibox + local wb = _G.mouse.current_wibox old_cursor, old_wibox = wb.cursor, wb wb.cursor = "hand2" end end) upgr_btn:connect_signal("mouse::leave", function(c) - if not busy then + if not busy then c:set_opacity(upgr_opacity) c:emit_signal("widget::redraw_needed") if old_wibox then @@ -129,28 +129,30 @@ local function worker(user_args) old_wibox = nil end if not busy then - busy, one_shot = true, true + busy = true + local one_shot = true awful.spawn.with_line_callback("bash -c " .. DIR .. "upgrade", { stdout = function() if one_shot then upgrading, one_shot = true, false - timer:emit_signal("timeout") + timer:emit_signal("timeout") end end, stderr = function(line) if (line ~= nil and line ~= "") then - notification = string.find(line, "warning") and + if string.find(line, "warning") then naughty.notify({ title = "Warning!", text = line, timeout = 0 }) - or + else naughty.notify({ preset = naughty.config.presets.critical, title = "Error!", text = line, }) + end end end, exit = function() @@ -163,21 +165,21 @@ local function worker(user_args) end end) - _, timer = awful.widget.watch([[bash -c "checkupdates 2>/dev/null"]], + timer = select(2, awful.widget.watch([[bash -c "checkupdates 2>/dev/null"]], _config.interval, function(widget, stdout) local upgrades_tbl = {} for value in stdout:gmatch("([^\n]+)") do - upgrades_tbl[#upgrades_tbl+1] = value + upgrades_tbl[#upgrades_tbl+1] = value end - widget:set(#upgrades_tbl) - + widget.set(#upgrades_tbl) + local popup_header_height, popup_row_height = 30, 20 local header = wibox.widget { { nil, { - markup = "" .. (upgrading and "Upgrading " .. #upgrades_tbl .. " Packages" or + markup = "" .. (upgrading and "Upgrading " .. #upgrades_tbl .. " Packages" or (#upgrades_tbl == 0 and "No" or #upgrades_tbl) .. " Available Upgrades") .. "", layout = wibox.widget.textbox, }, @@ -197,7 +199,7 @@ local function worker(user_args) for k, v in ipairs(upgrades_tbl) do for i = 1, #rows.children do - if v == rows.children[i]:get_txt() then goto continue end + if v == rows.children[i].get_txt() then goto continue end end local row = wibox.widget{ { @@ -214,8 +216,8 @@ local function worker(user_args) }, layout = wibox.layout.ratio.horizontal, } - function row:get_txt() return row:get_children_by_id("txt")[1].text end - function row:set_idx(idx) row:get_children_by_id("idx")[1]:set_text(idx) end + function row.get_txt() return row:get_children_by_id("txt")[1].text end + function row.set_idx(idx) row:get_children_by_id("idx")[1]:set_text(idx) end row:ajust_ratio(2, 0.1, 0.9, 0) rows:insert(k, row) ::continue:: @@ -246,7 +248,7 @@ local function worker(user_args) } end, pacman_widget - ) + )) return pacman_widget end -- cgit v1.2.3