From 0b48f0b200143881a47bc5f5efefd2671e9baf63 Mon Sep 17 00:00:00 2001 From: streetturtle Date: Sat, 1 Jun 2019 22:55:13 -0400 Subject: [PATCH] externalize config of batteryarc widget --- batteryarc-widget/README.md | 34 ++-- batteryarc-widget/batteryarc.lua | 307 +++++++++++++++++-------------- batteryarc-widget/warning.png | Bin 0 -> 13496 bytes 3 files changed, 189 insertions(+), 152 deletions(-) create mode 100644 batteryarc-widget/warning.png diff --git a/batteryarc-widget/README.md b/batteryarc-widget/README.md index cb73e09..d282b68 100644 --- a/batteryarc-widget/README.md +++ b/batteryarc-widget/README.md @@ -11,18 +11,27 @@ Depending of the battery status it could look following ways: - ![80_d](./80_d.png) - more than 40 percent - ![80_c](./80_c.png) - more than 40 percent, charging -Widget uses following beautiful variables with values: +If a battery level is low then warning popup will show up: -```lua -theme.widget_main_color = "#74aeab" -theme.widget_red = "#e53935" -theme.widget_yellow = "#c0ca33" -theme.widget_green = "#43a047" -theme.widget_black = "#000000" -theme.widget_transparent = "#00000000" -``` +![warning](./warning.png) + +## Customization + +It is possible to customize widget by providing a table with all or some of the following config parameters: + +| Name | Default | Description | +|---|---|---| +| `font` | Font | Play 6 | +| `arc_thickness` | Thickness of the arc | 2 | +| `text_color` | Color of text with the current charge | `beautiful.fg_color` | +| `low_level_color` | Arc color when battery charge is less that 15%| #e53935 | +| `medium_level_color` | Arc color when battery charge is between 15% and 40% | #c0ca33 | +| `full_level_color` | Arc color when battery charge is above 40% | `beautiful.fg_color` | +| `warning_msg_title` | Title of the warning popup | _Huston, we have a problem_ | +| `warning_msg_text` | Text of the warning popup | _Battery is dying_ | +| `warning_msg_position` | Position of the warning popup | `bottom_right` | +| `warning_msg_icon` | Icon of the warning popup| ~/.config/awesome/awesome-wm-widgets/batteryarc-widget/spaceman.jpg | -which means that you need to copy the code above and paste it in your **theme.lua**. Otherwise you can change colors directly in the widget. ## Installation @@ -35,11 +44,10 @@ s.mytasklist, -- Middle widget { -- Right widgets layout = wibox.layout.fixed.horizontal, ... - batteryarc_widget, + batteryarc_widget(), ... ``` -You can get the icon for warning popup [here](https://vk.com/images/stickers/1933/512.png) ## Troubleshooting -In case of any doubts or questions don't hesitate to raise an [issue](https://github.com/streetturtle/awesome-wm-widgets/issues/new). +In case of any doubts or questions please raise an [issue](https://github.com/streetturtle/awesome-wm-widgets/issues/new). diff --git a/batteryarc-widget/batteryarc.lua b/batteryarc-widget/batteryarc.lua index a15151f..cf10b81 100644 --- a/batteryarc-widget/batteryarc.lua +++ b/batteryarc-widget/batteryarc.lua @@ -16,151 +16,180 @@ local watch = require("awful.widget.watch") local HOME = os.getenv("HOME") -local text = wibox.widget { - id = "txt", - font = "Play 6", - align = 'center', -- align the text - valign = 'center', - widget = wibox.widget.textbox -} +local widget = {} -local text_with_background = wibox.container.background(text) +local function worker(args) -local batteryarc = wibox.widget { - text_with_background, - max_value = 1, - rounded_edge = true, - thickness = 2, - start_angle = 4.71238898, -- 2pi*3/4 - forced_height = 18, - forced_width = 18, - bg = "#ffffff11", - paddings = 2, - widget = wibox.container.arcchart, - set_value = function(self, value) - self.value = value - end, -} + local args = args or {} -local last_battery_check = os.time() + local font = args.font or 'Play 6' + local arc_thickness = args.thickness or 2 -watch("acpi -i", 10, - function(widget, stdout) - local batteryType + local text_color = args.text_color or beautiful.fg_color + local low_level_color = args.low_level_color or '#e53935' + local medium_level_color = args.medium_level_color or '#c0ca33' + local full_level_color = args.full_level_color or beautiful.fg_color - local battery_info = {} - local capacities = {} - for s in stdout:gmatch("[^\r\n]+") do - local status, charge_str, time = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?.*') - if string.match(s, 'rate information') then - -- ignore such line - elseif status ~= nil then - table.insert(battery_info, {status = status, charge = tonumber(charge_str)}) - else - local cap_str = string.match(s, '.+:.+last full capacity (%d+)') - table.insert(capacities, tonumber(cap_str)) - end - end + local warning_msg_title = args.warning_msg_title or 'Huston, we have a problem' + local warning_msg_text = args.warning_msg_text or 'Battery is dying' + local warning_msg_position = args.warning_msg_position or 'bottom_right' + local warning_msg_icon = args.warning_msg_icon or HOME .. '/.config/awesome/awesome-wm-widgets/batteryarc-widget/spaceman.jpg' - local capacity = 0 - for i, cap in ipairs(capacities) do - capacity = capacity + cap - end - - local charge = 0 - local status - for i, batt in ipairs(battery_info) do - if batt.charge >= charge then - -- use most charged battery status. This is arbitrary, and maybe another metric should be used - status = batt.status - end - - charge = charge + batt.charge * capacities[i] - end - - local charge_percentage - if capacity > 5 then - charge = charge / capacity - charge_percentage = charge / 100 - else - -- when widget.value is < 0.04, the widget shows a full circle (as widget.value=1) - charge_percentage = 0.05 - end - - widget.value = charge / 100 - - if status == 'Charging' then - text_with_background.bg = beautiful.widget_green - text_with_background.fg = beautiful.widget_black - else - text_with_background.bg = beautiful.widget_transparent - text_with_background.fg = beautiful.widget_main_color - end - - --- if battery is fully charged (100) there is not enough place for three digits, so we don't show any text - text.text = charge == 100 - and '' - or string.format('%d', charge) - - if charge < 15 then - batteryarc.colors = { beautiful.widget_red } - if status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then - -- if 5 minutes have elapsed since the last warning - last_battery_check = os.time() - - show_battery_warning() - end - elseif charge > 15 and charge < 40 then - batteryarc.colors = { beautiful.widget_yellow } - else - batteryarc.colors = { beautiful.widget_main_color } - end - end, - batteryarc) - --- Popup with battery info --- One way of creating a pop-up notification - naughty.notify -local notification -function show_battery_status() - awful.spawn.easy_async([[bash -c 'acpi']], - function(stdout, _, _, _) - naughty.destroy(notification) - notification = naughty.notify { - text = stdout, - title = "Battery status", - timeout = 5, - hover_timeout = 0.5, - width = 200, - } - end) -end - -batteryarc:connect_signal("mouse::enter", function() show_battery_status() end) -batteryarc:connect_signal("mouse::leave", function() naughty.destroy(notification) end) - --- Alternative to naughty.notify - tooltip. You can compare both and choose the preferred one - ---battery_popup = awful.tooltip({objects = {battery_widget}}) - --- To use colors from beautiful theme put --- following lines in rc.lua before require("battery"): --- beautiful.tooltip_fg = beautiful.fg_normal --- beautiful.tooltip_bg = beautiful.bg_normal - ---[[ Show warning notification ]] -function show_battery_warning() - naughty.notify { - icon = HOME .. "/.config/awesome/awesome-wm-widgets/batteryarc-widget/spaceman.jpg", - icon_size = 100, - text = "Battery is dying", -- switch text and title - title = "Huston, we have a problem", - timeout = 25, -- show the warning for a longer time - hover_timeout = 0.5, - position = "bottom_right", - bg = "#F06060", - fg = "#EEE9EF", - width = 300, + local text = wibox.widget { + id = "txt", + font = font, + align = 'center', -- align the text + valign = 'center', + widget = wibox.widget.textbox } + + local text_with_background = wibox.container.background(text) + + widget = wibox.widget { + text_with_background, + max_value = 1, + rounded_edge = true, + thickness = arc_thickness, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = 18, + forced_width = 18, + bg = "#ffffff11", + paddings = 2, + widget = wibox.container.arcchart, + set_value = function(self, value) + self.value = value + end, + } + + local last_battery_check = os.time() + + watch("acpi -i", 10, + function(widget, stdout) + local batteryType + + local battery_info = {} + local capacities = {} + for s in stdout:gmatch("[^\r\n]+") do + local status, charge_str, time = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?.*') + if string.match(s, 'rate information') then + -- ignore such line + elseif status ~= nil then + table.insert(battery_info, { status = status, charge = tonumber(charge_str) }) + else + local cap_str = string.match(s, '.+:.+last full capacity (%d+)') + table.insert(capacities, tonumber(cap_str)) + end + end + + local capacity = 0 + for i, cap in ipairs(capacities) do + capacity = capacity + cap + end + + local charge = 0 + local status + for i, batt in ipairs(battery_info) do + if batt.charge >= charge then + -- use most charged battery status. This is arbitrary, and maybe another metric should be used + status = batt.status + end + + charge = charge + batt.charge * capacities[i] + end + + local charge_percentage + if capacity > 5 then + charge = charge / capacity + charge_percentage = charge / 100 + else + -- when widget.value is < 0.04, the widget shows a full circle (as widget.value=1) + charge_percentage = 0.05 + end + + widget.value = charge / 100 + + if status == 'Charging' then + text_with_background.bg = full_level_color + text_with_background.fg = '#000000' + else + text_with_background.bg = '#00000000' + text_with_background.fg = text_color + end + + --- if battery is fully charged (100) there is not enough place for three digits, so we don't show any text + text.text = charge == 100 + and '' + or string.format('%d', charge) + + if charge < 15 then + widget.colors = { low_level_color } + if status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then + -- if 5 minutes have elapsed since the last warning + last_battery_check = os.time() + + show_battery_warning() + end + elseif charge > 15 and charge < 40 then + widget.colors = { medium_level_color } + else + widget.colors = { full_level_color } + end + end, + widget) + + -- Popup with battery info + -- One way of creating a pop-up notification - naughty.notify + local notification + function show_battery_status() + awful.spawn.easy_async([[bash -c 'acpi']], + function(stdout, _, _, _) + naughty.destroy(notification) + notification = naughty.notify { + text = stdout, + title = "Battery status", + timeout = 5, + hover_timeout = 0.5, + width = 200, + } + end) + end + + widget:connect_signal("mouse::enter", function() + show_battery_status() + end) + widget:connect_signal("mouse::leave", function() + naughty.destroy(notification) + end) + + -- Alternative to naughty.notify - tooltip. You can compare both and choose the preferred one + + --battery_popup = awful.tooltip({objects = {battery_widget}}) + + -- To use colors from beautiful theme put + -- following lines in rc.lua before require("battery"): + -- beautiful.tooltip_fg = beautiful.fg_normal + -- beautiful.tooltip_bg = beautiful.bg_normal + + --[[ Show warning notification ]] + function show_battery_warning() + naughty.notify { + icon = warning_msg_icon, + icon_size = 100, + text = warning_msg_text, + title = warning_msg_title, + timeout = 25, -- show the warning for a longer time + hover_timeout = 0.5, + position = warning_msg_position, + bg = "#F06060", + fg = "#EEE9EF", + width = 300, + } + end + + return widget + end -return batteryarc +return setmetatable(widget, { __call = function(_, ...) + return worker(...) +end }) diff --git a/batteryarc-widget/warning.png b/batteryarc-widget/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..55ca7902bcbcdce8c1229f2802281696550381b6 GIT binary patch literal 13496 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