add new calendar widget with ics file support, fix some bugs and added some game rules so steam games fullscreen isn't as annoying
1
awesome/src/assets/icons/calendar/add_ical.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,19H5V8H19M16,1V3H8V1H6V3H5C3.89,3 3,3.89 3,5V19C3,20.1 3.9,21 5,21H19C20.1,21 21,20.1 21,19V5C21,3.89 20.1,3 19,3H18V1" /></svg>
|
||||
|
After Width: | Height: | Size: 201 B |
1
awesome/src/assets/icons/calendar/add_task.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" /></svg>
|
||||
|
After Width: | Height: | Size: 120 B |
1
awesome/src/assets/icons/calendar/calendar.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7,10H12V15H7M19,19H5V8H19M19,3H18V1H16V3H8V1H6V3H5C3.89,3 3,3.9 3,5V19C3,20.1 3.9,21 5,21H19C20.1,21 21,20.1 21,19V5C21,3.9 20.1,3 19,3Z" /></svg>
|
||||
|
After Width: | Height: | Size: 216 B |
3
awesome/src/assets/icons/calendar/chevron-left.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="#f5f5f5" d="M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 160 B |
3
awesome/src/assets/icons/calendar/chevron-right.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="#f5f5f5" d="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 292 KiB |
@@ -235,7 +235,7 @@ return gears.table.join(
|
||||
awful.key(
|
||||
{},
|
||||
"XF86AudioMute",
|
||||
function()
|
||||
function(c)
|
||||
awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle")
|
||||
awesome.emit_signal("widget::volume_osd:rerun")
|
||||
end,
|
||||
@@ -244,11 +244,11 @@ return gears.table.join(
|
||||
awful.key(
|
||||
{},
|
||||
"XF86MonBrightnessUp",
|
||||
function()
|
||||
function(c)
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"xfpm-power-backlight-helper --get-brightness",
|
||||
"pkexec xfpm-power-backlight-helper --get-brightness",
|
||||
function(stdout)
|
||||
awful.spawn(awful.util.getdir("config") .. "src/scripts/backlight.sh set " ..
|
||||
awful.spawn("pkexec xfpm-power-backlight-helper --set-brightness " ..
|
||||
tostring(tonumber(stdout) + BACKLIGHT_SEPS))
|
||||
awesome.emit_signal("brightness::update")
|
||||
end
|
||||
@@ -259,11 +259,12 @@ return gears.table.join(
|
||||
awful.key(
|
||||
{},
|
||||
"XF86MonBrightnessDown",
|
||||
function()
|
||||
function(c)
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"xfpm-power-backlight-helper --get-brightness",
|
||||
"pkexec xfpm-power-backlight-helper --get-brightness",
|
||||
function(stdout)
|
||||
awful.spawn(awful.util.getdir("config") .. "src/scripts/backlight.sh set " ..
|
||||
awful.spawn(
|
||||
"pkexec xfpm-power-backlight-helper --set-brightness " ..
|
||||
tostring(tonumber(stdout) - BACKLIGHT_SEPS))
|
||||
awesome.emit_signal("brightness::update")
|
||||
end
|
||||
|
||||
@@ -38,18 +38,25 @@ awful.rules.rules = {
|
||||
titlebars_enabled = true
|
||||
}
|
||||
},
|
||||
{
|
||||
id = "games",
|
||||
rule_any = {
|
||||
class = {
|
||||
'Wine',
|
||||
'dolphin-emu',
|
||||
'Steam',
|
||||
'Citra',
|
||||
"steam_app_.%d+",
|
||||
"gta5.exe",
|
||||
},
|
||||
name = { 'Steam' }
|
||||
},
|
||||
properties = {
|
||||
skip_decoration = true,
|
||||
placement = awful.placement.centered
|
||||
tag = "9",
|
||||
switchtotag = true,
|
||||
fullscreen = true,
|
||||
screen = screen[1],
|
||||
floating = true,
|
||||
},
|
||||
focus = true,
|
||||
callback = function(c)
|
||||
awful.screen.focused()
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,9 +95,6 @@ tag.connect_signal(
|
||||
---@param icon_override_hover string | nil the hover effect color
|
||||
function Hover_signal(widget, bg_override, fg_override, border_override, icon_override, icon_override_hover)
|
||||
local old_wibox, old_cursor, old_bg, old_fg, old_border
|
||||
|
||||
local r, g, b
|
||||
|
||||
widget.bg = widget.bg or "#000000"
|
||||
widget.fg = widget.fg or "#000000"
|
||||
widget.border_color = widget.border_color or "#000000"
|
||||
@@ -107,62 +104,72 @@ function Hover_signal(widget, bg_override, fg_override, border_override, icon_ov
|
||||
widget.icon = widget:get_children_by_id("icon")[1]
|
||||
end
|
||||
|
||||
--[[ local r_timed_bg = rubato.timed { duration = 0.5 }
|
||||
local g_timed_bg = rubato.timed { duration = 0.5 }
|
||||
local b_timed_bg = rubato.timed { duration = 0.5 }
|
||||
local _, rb, gb, bb = widget.bg:get_rgba()
|
||||
local _, rf, gf, bf = widget.fg:get_rgba()
|
||||
local rbo, gbo, bbo = color.utils.hex_to_rgba(widget.border_color)
|
||||
|
||||
local r_timed_bg = rubato.timed { duration = 0.3, pos = math.floor(rb * 255) }
|
||||
local g_timed_bg = rubato.timed { duration = 0.3, pos = math.floor(gb * 255) }
|
||||
local b_timed_bg = rubato.timed { duration = 0.3, pos = math.floor(bb * 255) }
|
||||
|
||||
local r_timed_fg = rubato.timed { duration = 0.3, pos = math.floor(rf * 255) }
|
||||
local g_timed_fg = rubato.timed { duration = 0.3, pos = math.floor(gf * 255) }
|
||||
local b_timed_fg = rubato.timed { duration = 0.3, pos = math.floor(bf * 255) }
|
||||
|
||||
local r_timed_border = rubato.timed { duration = 0.3, pos = math.floor(rbo) }
|
||||
local g_timed_border = rubato.timed { duration = 0.3, pos = math.floor(gbo) }
|
||||
local b_timed_border = rubato.timed { duration = 0.3, pos = math.floor(bbo) }
|
||||
|
||||
local function update_bg()
|
||||
widget:set_bg("#" .. color.utils.rgba_to_hex { r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos })
|
||||
end
|
||||
|
||||
local function update_fg()
|
||||
widget:set_fg("#" .. color.utils.rgba_to_hex { r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos })
|
||||
end
|
||||
|
||||
local function update_border()
|
||||
widget:set_border_color("#" .. color.utils.rgba_to_hex { r_timed_border.pos, g_timed_border.pos, b_timed_border.pos })
|
||||
end
|
||||
|
||||
r_timed_bg:subscribe(update_bg)
|
||||
g_timed_bg:subscribe(update_bg)
|
||||
b_timed_bg:subscribe(update_bg)
|
||||
|
||||
r_timed_fg:subscribe(update_fg)
|
||||
g_timed_fg:subscribe(update_fg)
|
||||
b_timed_fg:subscribe(update_fg)
|
||||
|
||||
r_timed_border:subscribe(update_border)
|
||||
g_timed_border:subscribe(update_border)
|
||||
b_timed_border:subscribe(update_border)
|
||||
|
||||
local function set_bg(newbg)
|
||||
r_timed_bg.target, g_timed_bg.target, b_timed_bg.target = color.utils.hex_to_rgba(newbg)
|
||||
end ]]
|
||||
r_timed_bg.target, g_timed_bg.target, b_timed_bg.target = newbg[1], newbg[2], newbg[3]
|
||||
end
|
||||
|
||||
local mouse_enter = function()
|
||||
_, r, g, b, _ = widget.bg:get_rgba()
|
||||
old_bg = RGB_to_hex(r, g, b)
|
||||
if bg_override or old_bg then
|
||||
widget:set_bg(bg_override or old_bg .. "dd")
|
||||
local function set_fg(newfg)
|
||||
r_timed_fg.target, g_timed_fg.target, b_timed_fg.target = newfg[1], newfg[2], newfg[3]
|
||||
end
|
||||
_, r, g, b, _ = widget.fg:get_rgba()
|
||||
old_fg = RGB_to_hex(r, g, b)
|
||||
if fg_override or old_fg then
|
||||
widget:set_fg(fg_override or old_fg .. "dd")
|
||||
|
||||
local function set_border(newborder)
|
||||
r_timed_border.target, g_timed_border.target, b_timed_border.target = newborder[1], newborder[2], newborder[3]
|
||||
end
|
||||
|
||||
local _, rbg, gbg, bbg, abg = widget.bg:get_rgba()
|
||||
old_bg = RGB_to_hex(rbg, gbg, bbg)
|
||||
local _, rfg, gfg, bfg, afg = widget.fg:get_rgba()
|
||||
old_fg = RGB_to_hex(rfg, gfg, bfg)
|
||||
old_border = widget.border_color
|
||||
if border_override or old_border then
|
||||
widget.border_color = border_override or old_border .. "dd"
|
||||
end
|
||||
if icon and widget.icon and icon_override and icon_override_hover then
|
||||
widget.icon.image = gears.color.recolor_image(icon, icon_override_hover)
|
||||
end
|
||||
local w = mouse.current_wibox
|
||||
if w then
|
||||
old_cursor, old_wibox = w.cursor, w
|
||||
w.cursor = "hand1"
|
||||
end
|
||||
end
|
||||
|
||||
--[[ local button_press = function()
|
||||
if old_bg or bg_override then
|
||||
if bg_override then
|
||||
bg_override = bg_override .. "bb"
|
||||
end
|
||||
widget.bg = bg_override or old_bg .. "bb"
|
||||
end
|
||||
if fg_override or old_fg then
|
||||
if fg_override then
|
||||
fg_override = fg_override .. "bb"
|
||||
end
|
||||
widget.fg = fg_override or old_fg .. "bb"
|
||||
end
|
||||
local rborder, gborder, bborder = color.utils.hex_to_rgba(old_border)
|
||||
|
||||
local function match_hex(hex1, hex2)
|
||||
local r1, g1, b1 = color.utils.hex_to_rgba(hex1)
|
||||
local r2, g2, b2 = color.utils.hex_to_rgba(hex2)
|
||||
return math.abs(r1 - r2) <= 100 and math.abs(g1 - g2) <= 100 and math.abs(b1 - b2) <= 100
|
||||
end
|
||||
|
||||
--[[
|
||||
local button_release = function()
|
||||
if old_bg or bg_override then
|
||||
if bg_override then
|
||||
@@ -179,14 +186,18 @@ function Hover_signal(widget, bg_override, fg_override, border_override, icon_ov
|
||||
end ]]
|
||||
|
||||
local mouse_leave = function()
|
||||
|
||||
if old_bg then
|
||||
widget:set_bg(old_bg)
|
||||
local r, g, b = color.utils.hex_to_rgba(old_bg)
|
||||
set_bg({ r, g, b })
|
||||
end
|
||||
if old_fg then
|
||||
widget:set_fg(old_fg)
|
||||
local r, g, b = color.utils.hex_to_rgba(old_fg)
|
||||
set_fg({ r, g, b })
|
||||
end
|
||||
if old_border then
|
||||
widget.border_color = old_border
|
||||
local r, g, b = color.utils.hex_to_rgba(old_border)
|
||||
set_border({ r, g, b })
|
||||
end
|
||||
if old_wibox then
|
||||
old_wibox.cursor = old_cursor
|
||||
@@ -197,8 +208,76 @@ function Hover_signal(widget, bg_override, fg_override, border_override, icon_ov
|
||||
end
|
||||
end
|
||||
|
||||
local mouse_enter = function()
|
||||
_, rbg, gbg, bbg, abg = widget.bg:get_rgba()
|
||||
if not match_hex(RGB_to_hex(rbg, gbg, bbg), old_bg) then
|
||||
old_bg = RGB_to_hex(rbg, gbg, bbg)
|
||||
set_bg({ rbg * 0.9 * 255, gbg * 0.9 * 255, bbg * 0.9 * 255 })
|
||||
end
|
||||
if old_bg then
|
||||
if bg_override then
|
||||
rbg, gbg, bbg = color.utils.hex_to_rgba(bg_override)
|
||||
set_bg({ rbg, gbg, bbg })
|
||||
else
|
||||
set_bg({ rbg * 0.9 * 255, gbg * 0.9 * 255, bbg * 0.9 * 255 })
|
||||
end
|
||||
end
|
||||
|
||||
_, rfg, gfg, bfg, afg = widget.fg:get_rgba()
|
||||
if not match_hex(RGB_to_hex(rfg, gfg, bfg), old_fg) then
|
||||
old_fg = RGB_to_hex(rfg, gfg, bfg)
|
||||
set_fg({ rfg * 0.9 * 255, gfg * 0.9 * 255, bfg * 0.9 * 255 })
|
||||
end
|
||||
if fg_override or old_fg then
|
||||
if fg_override then
|
||||
rfg, gfg, bfg = color.utils.hex_to_rgba(fg_override)
|
||||
set_fg({ rfg, gfg, bfg })
|
||||
else
|
||||
set_fg({ rfg * 0.9 * 255, gfg * 0.9 * 255, bfg * 0.9 * 255 })
|
||||
end
|
||||
end
|
||||
|
||||
if not match_hex(old_border, widget.border_color) then
|
||||
old_border = widget.border_color
|
||||
rborder, gborder, bborder = color.utils.hex_to_rgba(old_border)
|
||||
end
|
||||
if border_override or old_border then
|
||||
if border_override then
|
||||
rborder, gborder, bborder = color.utils.hex_to_rgba(border_override)
|
||||
set_border({ rborder, gborder, bborder })
|
||||
else
|
||||
set_border({ rborder * 0.9, gborder * 0.9, bborder * 0.9 })
|
||||
end
|
||||
end
|
||||
if icon and widget.icon and icon_override and icon_override_hover then
|
||||
widget.icon.image = gears.color.recolor_image(icon, icon_override_hover)
|
||||
end
|
||||
local w = mouse.current_wibox
|
||||
if w then
|
||||
old_cursor, old_wibox = w.cursor, w
|
||||
w.cursor = "hand1"
|
||||
end
|
||||
--widget:connect_signal("mouse::leave", mouse_leave)
|
||||
end
|
||||
|
||||
local button_press = function()
|
||||
--[[ if old_bg or bg_override then
|
||||
if bg_override then
|
||||
bg_override = bg_override .. "bb"
|
||||
end
|
||||
widget.bg = bg_override or old_bg .. "bb"
|
||||
end
|
||||
if fg_override or old_fg then
|
||||
if fg_override then
|
||||
fg_override = fg_override .. "bb"
|
||||
end
|
||||
widget.fg = fg_override or old_fg .. "bb"
|
||||
end ]]
|
||||
--widget:disconnect_signal("mouse::leave", mouse_leave)
|
||||
end
|
||||
|
||||
widget:connect_signal("mouse::enter", mouse_enter)
|
||||
--widget:connect_signal("button::press", button_press)
|
||||
widget:connect_signal("button::press", button_press)
|
||||
--widget:connect_signal("button::release", button_release)
|
||||
widget:connect_signal("mouse::leave", mouse_leave)
|
||||
end
|
||||
|
||||
@@ -18,6 +18,8 @@ local gshape = require('gears.shape')
|
||||
local gobject = require('gears.object')
|
||||
local mousegrabber = mousegrabber
|
||||
|
||||
local rubato = require("src.lib.rubato")
|
||||
|
||||
local overflow = { mt = {} }
|
||||
|
||||
-- Determine the required space to draw the layout's children and, if necessary,
|
||||
@@ -305,6 +307,9 @@ end
|
||||
-- @tparam number scroll_factor The scroll factor.
|
||||
-- @propemits true false
|
||||
|
||||
overflow.rubato_timed = rubato.timed { duration = 0.2 }
|
||||
|
||||
local first_call = true
|
||||
function overflow:set_scroll_factor(factor)
|
||||
local current = self._private.scroll_factor
|
||||
local interval = self._private.used_in_dir - self._private.avail_in_dir
|
||||
@@ -318,12 +323,24 @@ function overflow:set_scroll_factor(factor)
|
||||
return
|
||||
end
|
||||
|
||||
self._private.scroll_factor = math.min(1, math.max(factor, 0))
|
||||
|
||||
local function update_scroll()
|
||||
self._private.scroll_factor = overflow.rubato_timed.pos
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::scroll_factor", factor)
|
||||
end
|
||||
|
||||
-- Make sure it only subscribes once
|
||||
if first_call then
|
||||
overflow.rubato_timed:subscribe(update_scroll)
|
||||
--first_call = false
|
||||
end
|
||||
|
||||
-- Set the target to the new target + remaining target from last scroll. This makes it scroll faster and correctly.
|
||||
overflow.rubato_timed.target = math.min(1,
|
||||
math.max(factor + (overflow.rubato_timed.target - overflow.rubato_timed.pos), 0))
|
||||
end
|
||||
|
||||
function overflow:get_scroll_factor()
|
||||
return self._private.scroll_factor
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ return function(s)
|
||||
spacing = dpi(10),
|
||||
layout = require("src.lib.overflow_widget.overflow").vertical,
|
||||
scrollbar_width = 0,
|
||||
step = dpi(50),
|
||||
step = dpi(100),
|
||||
id = "scroll_bar",
|
||||
},
|
||||
spacing = dpi(10),
|
||||
|
||||
1085
awesome/src/modules/calendar/calendar.lua
Normal file
@@ -3,6 +3,7 @@
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
-- Awesome Libs
|
||||
local awful = require("awful")
|
||||
local async = require("async")
|
||||
local dpi = require("beautiful").xresources.apply_dpi
|
||||
local Gio = require("lgi").Gio
|
||||
local gears = require("gears")
|
||||
@@ -25,7 +26,7 @@ return function(screen)
|
||||
---@param size number The size of the widget
|
||||
---@return widox.widget | nil The widget or nil if the program is not found
|
||||
local function create_dock_element(program, size)
|
||||
if not program then return end
|
||||
|
||||
local dock_element = wibox.widget {
|
||||
{
|
||||
{
|
||||
@@ -164,15 +165,14 @@ return function(screen)
|
||||
end
|
||||
|
||||
local prog = json:decode(data:read("a"))
|
||||
if (not prog) or prog == "" then return end
|
||||
data:close()
|
||||
for _, pr in ipairs(prog) do
|
||||
local indicators = { layout = wibox.layout.flex.horizontal, spacing = dpi(5) }
|
||||
local col = Theme_config.dock.indicator_bg
|
||||
for _, c in ipairs(client.get()) do
|
||||
local icon_name = pr.icon
|
||||
if not c.class then return end
|
||||
if icon_name:match(string.lower(c.class)) or c.class:match(string.lower(icon_name)) or
|
||||
(string.lower(c.name) == string.lower(icon_name)) or c.name:match(string.lower(icon_name)) then
|
||||
if icon_name:match(string.lower(c.class or c.name)) or c.class:match(string.lower(icon_name)) or
|
||||
c.name:match(string.lower(icon_name)) then
|
||||
if c == client.focus then
|
||||
col = Theme_config.dock.indicator_focused_bg
|
||||
elseif c.urgent then
|
||||
@@ -253,9 +253,7 @@ return function(screen)
|
||||
return
|
||||
end
|
||||
local dock_data = json:decode(data:read("a"))
|
||||
if (not dock_data) or dock_data == "" then
|
||||
return
|
||||
end
|
||||
data:close()
|
||||
for _, program in ipairs(dock_data) do
|
||||
table.insert(dock_elements, create_dock_element(program, User_config.dock_icon_size))
|
||||
end
|
||||
|
||||
@@ -27,5 +27,6 @@ awful.screen.connect_for_each_screen(
|
||||
require("src.modules.notification-center.init")(s)
|
||||
require("src.modules.window_switcher.init")(s)
|
||||
require("src.modules.application_launcher.init")(s)
|
||||
require("src.modules.calendar.calendar")(s)
|
||||
end
|
||||
)
|
||||
|
||||
@@ -130,11 +130,46 @@ return function(s)
|
||||
widget = wibox.container.place,
|
||||
}
|
||||
|
||||
local rubato = require("src.lib.rubato")
|
||||
|
||||
local rubato_timed = rubato.timed { duration = 1, pos = 0 }
|
||||
|
||||
local toggle_button = wibox.widget {
|
||||
{
|
||||
left_button,
|
||||
right_button,
|
||||
widget = wibox.layout.flex.horizontal
|
||||
id = "background",
|
||||
widget = wibox.widget {
|
||||
fit = function(_, width, height)
|
||||
return width, height
|
||||
end,
|
||||
draw = function(_, _, cr, width, height)
|
||||
-- Clear for next drawing
|
||||
--cr:set_operator(cairo.Operator.CLEAR);
|
||||
local function move_dnd()
|
||||
cr:set_source(gears.color(Theme_config.notification_center.dnd.bg));
|
||||
cr:paint();
|
||||
cr:set_source(gears.color(Theme_config.notification_center.dnd.disabled))
|
||||
cr:move_to(rubato_timed.pos, 0)
|
||||
local x = rubato_timed.pos
|
||||
local y = 5
|
||||
local newwidth = width / 2 - 10
|
||||
local newheight = height - 10
|
||||
|
||||
local radius = height / 6.0
|
||||
local degrees = math.pi / 180.0;
|
||||
|
||||
cr:new_sub_path()
|
||||
cr:arc(x + newwidth - radius, y + radius, radius, -90 * degrees, 0 * degrees)
|
||||
cr:arc(x + newwidth - radius, y + newheight - radius, radius, 0 * degrees, 90 * degrees)
|
||||
cr:arc(x + radius, y + newheight - radius, radius, 90 * degrees, 180 * degrees)
|
||||
cr:arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees)
|
||||
cr:close_path()
|
||||
cr:fill()
|
||||
end
|
||||
|
||||
rubato_timed:subscribe(move_dnd)
|
||||
rubato_timed.target = width / 2 + 5
|
||||
end
|
||||
}
|
||||
},
|
||||
active = false,
|
||||
widget = wibox.container.background,
|
||||
@@ -152,22 +187,20 @@ return function(s)
|
||||
"button::press",
|
||||
function()
|
||||
if toggle_button.active then
|
||||
left_button.visible = true
|
||||
right_button.visible = false
|
||||
toggle_button.active = not toggle_button.active
|
||||
toggle_button.border_color = Theme_config.notification_center.dnd.border_disabled
|
||||
User_config.dnd = false
|
||||
rubato_timed.target = 5
|
||||
else
|
||||
left_button.visible = false
|
||||
right_button.visible = true
|
||||
toggle_button.active = not toggle_button.active
|
||||
toggle_button.border_color = Theme_config.notification_center.dnd.border_enabled
|
||||
User_config.dnd = true
|
||||
rubato_timed.target = 50
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
local dnd = wibox.widget { -- Clear all button
|
||||
local dnd = wibox.widget {
|
||||
{
|
||||
{
|
||||
{
|
||||
@@ -348,12 +381,22 @@ return function(s)
|
||||
end
|
||||
)
|
||||
|
||||
local function mouse_leave()
|
||||
notification_center.visible = false
|
||||
end
|
||||
|
||||
awesome.connect_signal("notification_center::block_mouse_events", function()
|
||||
notification_center:disconnect_signal("mouse::leave", mouse_leave)
|
||||
end)
|
||||
|
||||
awesome.connect_signal("notification_center::unblock_mouse_events", function()
|
||||
notification_center:connect_signal("mouse::leave", mouse_leave)
|
||||
end)
|
||||
|
||||
-- Hide notification_center when mouse leaves it
|
||||
notification_center:connect_signal(
|
||||
"mouse::leave",
|
||||
function()
|
||||
notification_center.visible = false
|
||||
end
|
||||
mouse_leave
|
||||
)
|
||||
|
||||
-- Clear all notifications on button press
|
||||
|
||||
@@ -15,7 +15,7 @@ local icondir = awful.util.getdir("config") .. "src/assets/icons/notifications/"
|
||||
local nl = {}
|
||||
|
||||
nl.notification_list = { layout = require("src.lib.overflow_widget.overflow").vertical, scrollbar_width = 0,
|
||||
step = dpi(20), spacing = dpi(20) }
|
||||
step = dpi(100), spacing = dpi(20) }
|
||||
|
||||
-- @param {table} notification
|
||||
-- @return {widget} notifications_list
|
||||
|
||||
@@ -90,6 +90,14 @@ return function()
|
||||
margins = dpi(10)
|
||||
}
|
||||
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
|
||||
awesome.connect_signal(
|
||||
"update::cpu_usage",
|
||||
function(cpu_usage)
|
||||
@@ -160,7 +168,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"update::cpu_temp",
|
||||
function(cpu_temp)
|
||||
@@ -239,7 +253,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"update::ram_widget",
|
||||
function(MemTotal, _, MemAvailable)
|
||||
@@ -312,7 +332,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"update::gpu_usage",
|
||||
function(gpu_usage)
|
||||
@@ -383,7 +409,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"update::gpu_temp",
|
||||
function(gpu_temp)
|
||||
@@ -472,7 +504,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"audio::get",
|
||||
function(muted, volume)
|
||||
@@ -563,7 +601,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"microphone::get",
|
||||
function(muted, volume)
|
||||
@@ -647,22 +691,20 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"brightness::get",
|
||||
function(brightness)
|
||||
local icon = icondir .. "brightness/brightness"
|
||||
if brightness >= 0 and brightness < 34 then
|
||||
icon = icon .. "-low"
|
||||
elseif brightness >= 34 and brightness < 67 then
|
||||
icon = icon .. "-medium"
|
||||
elseif brightness >= 67 then
|
||||
icon = icon .. "-high"
|
||||
end
|
||||
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(icon .. ".svg",
|
||||
"update::backlight",
|
||||
function(backlight, backlight_icon)
|
||||
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(backlight_icon,
|
||||
Theme_config.notification_center.status_bar.backlight_color)
|
||||
tooltip.text = "Backlight: " .. brightness .. "%"
|
||||
rubato_timer.target = brightness
|
||||
tooltip.text = "Backlight: " .. backlight .. "%"
|
||||
rubato_timer.target = backlight
|
||||
end
|
||||
)
|
||||
elseif widget == "battery" then
|
||||
@@ -728,7 +770,13 @@ return function()
|
||||
preferred_alignments = "middle",
|
||||
margins = dpi(10)
|
||||
}
|
||||
w:connect_signal("mouse::enter", function()
|
||||
awesome.emit_signal("notification_center::block_mouse_events")
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
awesome.emit_signal("notification_center::unblock_mouse_events")
|
||||
end)
|
||||
awesome.connect_signal(
|
||||
"update::battery_widget",
|
||||
function(battery, battery_icon)
|
||||
|
||||
@@ -68,11 +68,13 @@ return function(s)
|
||||
Theme_config.volume_controller.device_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_headphones_selected_bg
|
||||
device.fg = Theme_config.volume_controller.device_headphones_selected_fg
|
||||
Hover_signal(device)
|
||||
else
|
||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
||||
Theme_config.volume_controller.device_headphones_selected_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_bg
|
||||
device.fg = Theme_config.volume_controller.device_headphones_fg
|
||||
Hover_signal(device)
|
||||
end
|
||||
end
|
||||
)
|
||||
@@ -85,16 +87,17 @@ return function(s)
|
||||
Theme_config.volume_controller.device_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_headphones_selected_bg
|
||||
device.fg = Theme_config.volume_controller.device_headphones_selected_fg
|
||||
Hover_signal(device)
|
||||
else
|
||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
||||
Theme_config.volume_controller.device_headphones_selected_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_bg
|
||||
device.fg = Theme_config.volume_controller.device_headphones_fg
|
||||
Hover_signal(device)
|
||||
end
|
||||
end
|
||||
)
|
||||
awesome.emit_signal("update::bg_sink", node)
|
||||
Hover_signal(device)
|
||||
else
|
||||
device:connect_signal(
|
||||
"button::press",
|
||||
@@ -115,11 +118,13 @@ return function(s)
|
||||
Theme_config.volume_controller.device_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_microphone_selected_bg
|
||||
device.fg = Theme_config.volume_controller.device_microphone_selected_fg
|
||||
Hover_signal(device)
|
||||
else
|
||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
||||
Theme_config.volume_controller.device_microphone_selected_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_bg
|
||||
device.fg = Theme_config.volume_controller.device_microphone_fg
|
||||
Hover_signal(device)
|
||||
end
|
||||
end
|
||||
)
|
||||
@@ -132,16 +137,17 @@ return function(s)
|
||||
Theme_config.volume_controller.device_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_microphone_selected_bg
|
||||
device.fg = Theme_config.volume_controller.device_microphone_selected_fg
|
||||
Hover_signal(device)
|
||||
else
|
||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
||||
Theme_config.volume_controller.device_microphone_selected_icon_color)
|
||||
device.bg = Theme_config.volume_controller.device_bg
|
||||
device.fg = Theme_config.volume_controller.device_microphone_fg
|
||||
Hover_signal(device)
|
||||
end
|
||||
end
|
||||
)
|
||||
awesome.emit_signal("update::bg_source", node)
|
||||
Hover_signal(device)
|
||||
end
|
||||
return device
|
||||
end
|
||||
|
||||
@@ -144,6 +144,52 @@ Theme_config.tasklist = {
|
||||
]] --
|
||||
|
||||
--#region Module Settings
|
||||
Theme_config.calendar = {
|
||||
bg = color["Grey900"],
|
||||
fg = color["Grey100"],
|
||||
border_color = color["Grey800"],
|
||||
border_width = dpi(2),
|
||||
day = {
|
||||
today_border_color = color["Blue200"],
|
||||
bg = color["Grey900"],
|
||||
bg_focus = color["Teal200"],
|
||||
bg_unfocus = color["Grey900"],
|
||||
fg = color["Grey100"],
|
||||
fg_focus = color["Grey900"],
|
||||
fg_unfocus = color["Grey600"],
|
||||
border_color = color["Grey800"],
|
||||
border_width = dpi(2),
|
||||
shape = function(cr, width, height)
|
||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
||||
end,
|
||||
},
|
||||
task = {
|
||||
bg = color["Purple200"],
|
||||
fg = color["Grey900"],
|
||||
shape = function(cr, width, height)
|
||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
||||
end,
|
||||
},
|
||||
weekdays = {
|
||||
bg = color["Grey900"],
|
||||
fg = color["Blue200"]
|
||||
},
|
||||
add_ical = {
|
||||
bg = color["Red200"],
|
||||
fg = color["Grey900"],
|
||||
shape = function(cr, width, height)
|
||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
||||
end,
|
||||
},
|
||||
add_task = {
|
||||
bg = color["LightBlue200"],
|
||||
fg = color["Grey900"],
|
||||
shape = function(cr, width, height)
|
||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
||||
Theme_config.notification = {
|
||||
border_color = color["Grey800"],
|
||||
border_width = dpi(4),
|
||||
|
||||
@@ -20,9 +20,11 @@ User_config = {
|
||||
"picom --experimental-backends",
|
||||
"xfce4-power-manager",
|
||||
"light-locker --lock-on-suspend --lock-on-lid &",
|
||||
"spotify",
|
||||
"discord",
|
||||
"/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1",
|
||||
"setxkbmap -option caps:swapescape",
|
||||
"protonmail-bridge"
|
||||
"jamesdsp"
|
||||
},
|
||||
|
||||
--[[
|
||||
@@ -45,7 +47,7 @@ User_config = {
|
||||
"MEDIA_PLAYER"
|
||||
More information at: https://lazka.github.io/pgi-docs/UPowerGlib-1.0/enums.html#UPowerGlib.DeviceKind.KEYBOARD
|
||||
]] --
|
||||
battery_kind = "BATTERY",
|
||||
battery_kind = "LINE_POWER",
|
||||
|
||||
--[[
|
||||
If your battery is not found you can specify its path here.
|
||||
@@ -191,8 +193,8 @@ User_config = {
|
||||
"ram_usage",
|
||||
"microphone",
|
||||
"volume",
|
||||
"backlight",
|
||||
"battery"
|
||||
"gpu_temp",
|
||||
"gpu_usage"
|
||||
},
|
||||
|
||||
--[[
|
||||
@@ -275,8 +277,10 @@ User_config = {
|
||||
"Tasklist"
|
||||
},
|
||||
right_bar = {
|
||||
"Battery",
|
||||
"Bluetooth",
|
||||
"Gpu Usage",
|
||||
"Gpu Temperature",
|
||||
"Cpu Usage",
|
||||
"Cpu Temperature",
|
||||
"Audio",
|
||||
"Keyboard Layout",
|
||||
"Date",
|
||||
|
||||
@@ -17,7 +17,6 @@ Gtk.IconTheme.set_custom_theme(gtk_theme, User_config.icon_theme)
|
||||
---@param app Gio.AppInfo
|
||||
---@return string path
|
||||
function Get_gicon_path(app)
|
||||
if not app then return "" end
|
||||
local icon_info = gtk_theme:lookup_by_gicon(app, 64, 0)
|
||||
if icon_info then
|
||||
local path = icon_info:get_filename()
|
||||
@@ -37,12 +36,12 @@ function Get_icon(class, name)
|
||||
name = string.lower(name or "")
|
||||
for _, app in ipairs(app_list) do
|
||||
local desktop_app_info = Gio.DesktopAppInfo.new(app_info.get_id(app))
|
||||
local icon_string = Gio.DesktopAppInfo.get_string(desktop_app_info, "Name")
|
||||
local icon_string = Gio.DesktopAppInfo.get_string(desktop_app_info, "Icon")
|
||||
if icon_string then
|
||||
icon_string = string.lower(icon_string)
|
||||
if icon_string:match(class) or class:match(icon_string) then
|
||||
return Get_gicon_path(app_info.get_icon(app))
|
||||
elseif (icon_string == name) or icon_string:match(name) or name:match(icon_string) then
|
||||
elseif icon_string:match(name) or name:match(icon_string) then
|
||||
return Get_gicon_path(app_info.get_icon(app))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ local awful = require("awful")
|
||||
BACKLIGHT_MAX_BRIGHTNESS = 0
|
||||
BACKLIGHT_SEPS = 0
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"xfpm-power-backlight-helper --get-max-brightness",
|
||||
"pkexec xfpm-power-backlight-helper --get-max-brightness",
|
||||
function(stdout)
|
||||
BACKLIGHT_MAX_BRIGHTNESS = tonumber(stdout)
|
||||
BACKLIGHT_SEPS = BACKLIGHT_MAX_BRIGHTNESS / 100
|
||||
@@ -15,7 +15,7 @@ awesome.connect_signal(
|
||||
"brightness::update",
|
||||
function()
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"xfpm-power-backlight-helper --get-brightness",
|
||||
"pkexec xfpm-power-backlight-helper --get-brightness",
|
||||
function(value)
|
||||
awesome.emit_signal("brightness::get", math.floor((tonumber(value) - 1) / (BACKLIGHT_MAX_BRIGHTNESS - 1) * 100))
|
||||
awesome.emit_signal("brightness::rerun")
|
||||
@@ -23,5 +23,3 @@ awesome.connect_signal(
|
||||
)
|
||||
end
|
||||
)
|
||||
|
||||
awesome.emit_signal("brightness::update")
|
||||
|
||||
@@ -5,4 +5,4 @@ require("src.tools.helpers.ram")
|
||||
require("src.tools.helpers.gpu_usage")
|
||||
require("src.tools.helpers.gpu_temp")
|
||||
require("src.tools.helpers.audio")
|
||||
require("src.tools.helpers.backlight")
|
||||
--require("src.tools.helpers.backlight")
|
||||
|
||||
332
awesome/src/tools/ical_parser.lua
Normal file
@@ -0,0 +1,332 @@
|
||||
local ical = {}
|
||||
ical.VCALENDAR = {}
|
||||
ical._private = {}
|
||||
ical._private.parser = {}
|
||||
|
||||
--[[
|
||||
The structure of ical looks like this:
|
||||
ical = {
|
||||
VCALENDAR = {
|
||||
PRODID = "...",
|
||||
VERSION = "...",
|
||||
CALSCALE = "...",
|
||||
METHOD = "...",
|
||||
X-WR-CALNAME = "...",
|
||||
X-WR-CALDESC = "...",
|
||||
X-WR-TIMEZONE = "...",
|
||||
VTIMEZONE = {
|
||||
TZID = "...",
|
||||
TZURL = "...",
|
||||
X-LIC-LOCATION = "...",
|
||||
STANDARD = {
|
||||
TZOFFSETFROM = "...",
|
||||
TZOFFSETTO = "...",
|
||||
TZNAME = "...",
|
||||
DTSTART = "...",
|
||||
TZRDATE = "...",
|
||||
TZRULE = "...",
|
||||
TZUNTIL = "...",
|
||||
TZPERIOD = "...",
|
||||
},
|
||||
DAYLIGHT = {
|
||||
TZOFFSETFROM = "...",
|
||||
TZOFFSETTO = "...",
|
||||
TZNAME = "...",
|
||||
DTSTART = "...",
|
||||
TZRDATE = "...",
|
||||
TZRULE = "...",
|
||||
TZUNTIL = "...",
|
||||
TZPERIOD = "...",
|
||||
},
|
||||
},
|
||||
VEVENT = {
|
||||
UID = "...",
|
||||
DTSTAMP = "...",
|
||||
DTSTART = "...",
|
||||
DTEND = "...",
|
||||
SUMMARY = "...",
|
||||
DESCRIPTION = "...",
|
||||
LOCATION = "...",
|
||||
RRULE = "...",
|
||||
RDATE = "...",
|
||||
EXDATE = "...",
|
||||
CLASS = "...",
|
||||
STATUS = "...",
|
||||
TRANSP = "...",
|
||||
SEQUENCE = "...",
|
||||
ORGANIZER = "...",
|
||||
ATTENDEE = "...",
|
||||
CATEGORIES = "...",
|
||||
PRIORITY = "...",
|
||||
URL = "...",
|
||||
UID = "...",
|
||||
DTSTAMP = "...",
|
||||
]]
|
||||
|
||||
---Takes a path to an .ical file then parses it into a lua table and returns it
|
||||
---@param path string Path to the .ical file
|
||||
---@return table | nil calendar New calendar table or nil on error
|
||||
function ical.new(path)
|
||||
local handler = io.open(path, "r")
|
||||
if not handler then return end
|
||||
|
||||
-- Check if the line is a BEGIN:VCALENDAR
|
||||
local v, k = handler:read("l"):match("([A-Z]+):([A-Z]+)")
|
||||
|
||||
if v:match("BEGIN") and k:match("VCALENDAR") then
|
||||
table.insert(ical.VCALENDAR, ical._private.parser.VCALENDAR(handler))
|
||||
return ical
|
||||
end
|
||||
return ical
|
||||
end
|
||||
|
||||
function ical._private.parser.VEVENT(handler)
|
||||
local VEVENT = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VEVENT") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("CREATED") then
|
||||
VEVENT.CREATED = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("LAST-MODIFIED") then
|
||||
VEVENT.LAST_MODIFIED = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("DTSTAMP") then
|
||||
VEVENT.DTSTAMP = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("UID") then
|
||||
VEVENT.UID = k
|
||||
elseif v:match("SUMMARY") then
|
||||
VEVENT.SUMMARY = k
|
||||
elseif v:match("RRULE") then
|
||||
VEVENT.RRULE = {
|
||||
FREQ = k:match("FREQ=([A-Z]+)"),
|
||||
UNTIL = ical._private.parser.to_datetime(k:match("UNTIL=([TZ0-9]+)")),
|
||||
WKST = k:match("WKST=([A-Z]+)"),
|
||||
COUNT = k:match("COUNT=([0-9]+)"),
|
||||
INTERVAL = k:match("INTERVAL=([0-9]+)")
|
||||
}
|
||||
elseif v:match("DTSTART") then
|
||||
VEVENT.DTSTART = {
|
||||
DTSTART = ical._private.parser.to_datetime(k),
|
||||
TZID = v:match("TZID=([a-zA-Z-\\/]+)"),
|
||||
VALUE = v:match("VALUE=([A-Z]+)")
|
||||
}
|
||||
elseif v:match("DTEND") then
|
||||
VEVENT.DTEND = {
|
||||
DTEND = ical._private.parser.to_datetime(k),
|
||||
TZID = v:match("TZID=([a-zA-Z-\\/]+)"),
|
||||
VALUE = v:match("VALUE=([A-Z]+)")
|
||||
}
|
||||
elseif v:match("TRANSP") then
|
||||
VEVENT.TRANSP = k
|
||||
elseif v:match("LOCATION") then
|
||||
VEVENT.LOCATION = k
|
||||
elseif v:match("DESCRIPTION") then
|
||||
VEVENT.DESCRIPTION = k
|
||||
elseif v:match("URL") then
|
||||
VEVENT.URL = {
|
||||
URL = k,
|
||||
VALUE = v:match("VALUE=([A-Z]+)")
|
||||
}
|
||||
elseif v:match("BEGIN") then
|
||||
if k:match("VALARM") then
|
||||
VEVENT.VALARM = ical._private.parser.VALARM(handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--VEVENT.duration = VEVENT.DTSTART.DTSTART - VEVENT.DTEND.DTEND
|
||||
|
||||
return VEVENT
|
||||
end
|
||||
|
||||
function ical._private.parser.alarm_to_time(alarm)
|
||||
if not alarm then return end
|
||||
--Parse alarm into a time depending on its value. The value will be -PT15M where - mean before and with no leading - it means after. PT can be ignored and 15 is the time M then the unit where M is minute, H is out etc
|
||||
local time = alarm:match("([-]?[0-9]+)[A-Z]")
|
||||
local unit = alarm:match("[-]?[A-Z][A-Z][0-9]+([A-Z]*)")
|
||||
|
||||
return time .. unit
|
||||
end
|
||||
|
||||
function ical._private.parser.VALARM(handler)
|
||||
local VALARM = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VALARM") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("ACTION") then
|
||||
VALARM.ACTION = k
|
||||
elseif v:match("TRIGGER;VALUE=DURATION") then
|
||||
VALARM.TRIGGER = {
|
||||
VALUE = v:match("VALUE=(.*):"),
|
||||
TRIGGER = ical._private.parser.alarm_to_time(k)
|
||||
}
|
||||
elseif v:match("DESCRIPTION") then
|
||||
VALARM.DESCRIPTION = k
|
||||
end
|
||||
end
|
||||
|
||||
return VALARM
|
||||
end
|
||||
|
||||
function ical._private.parser.VCALENDAR(handler)
|
||||
local VCALENDAR = {}
|
||||
VCALENDAR.VEVENT = {}
|
||||
VCALENDAR.VTIMEZONE = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VCALENDAR") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v and k then
|
||||
if v:match("PRODID") then
|
||||
VCALENDAR.PRODID = k
|
||||
elseif v:match("VERSION") then
|
||||
VCALENDAR.VERSION = k
|
||||
elseif v:match("BEGIN") then
|
||||
if k:match("VTIMEZONE") then
|
||||
VCALENDAR.VTIMEZONE = ical._private.parser.VTIMEZONE(handler)
|
||||
elseif k:match("VEVENT") then
|
||||
table.insert(VCALENDAR.VEVENT, ical._private.parser.VEVENT(handler))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
handler:close()
|
||||
return VCALENDAR
|
||||
end
|
||||
|
||||
function ical._private.parser.VTIMEZONE(handler)
|
||||
local VTIMEZONE = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VTIMEZONE") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("TZID") then
|
||||
VTIMEZONE.TZID = k
|
||||
end
|
||||
if v:match("BEGIN") then
|
||||
if k:match("DAYLIGHT") then
|
||||
VTIMEZONE.DAYLIGHT = ical._private.parser.DAYLIGHT(handler)
|
||||
elseif k:match("STANDARD") then
|
||||
VTIMEZONE.STANDARD = ical._private.parser.STANDARD(handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return VTIMEZONE
|
||||
end
|
||||
|
||||
function ical._private.parser.DAYLIGHT(handler)
|
||||
local DAYLIGHT = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:DAYLIGHT") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("TZOFFSETFROM") then
|
||||
DAYLIGHT.TZOFFSETFROM = ical._private.parser.offset(k)
|
||||
elseif v:match("TZOFFSETTO") then
|
||||
DAYLIGHT.TZOFFSETTO = ical._private.parser.offset(k)
|
||||
elseif v:match("TZNAME") then
|
||||
DAYLIGHT.TZNAME = k
|
||||
elseif v:match("DTSTART") then
|
||||
DAYLIGHT.DTSTART = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("RRULE") then
|
||||
DAYLIGHT.RRULE = {
|
||||
FREQ = k:match("FREQ=([A-Z]+)"),
|
||||
BYDAY = k:match("BYDAY=([%+%-0-9A-Z,]+)"),
|
||||
BYMONTH = k:match("BYMONTH=([0-9]+)")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return DAYLIGHT
|
||||
end
|
||||
|
||||
---Parses the STANDARD property into a table
|
||||
---@param handler table
|
||||
---@return table STANDARD The STANDARD property as a table
|
||||
function ical._private.parser.STANDARD(handler)
|
||||
local STANDARD = {}
|
||||
|
||||
-- Read each line until END:STANDARD is read
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:STANDARD") then
|
||||
break
|
||||
end
|
||||
|
||||
-- Break down each line into the property:value
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("TZOFFSETFROM") then
|
||||
STANDARD.TZOFFSETFROM = ical._private.parser.offset(k)
|
||||
elseif v:match("TZOFFSETTO") then
|
||||
STANDARD.TZOFFSETTO = ical._private.parser.offset(k)
|
||||
elseif v:match("TZNAME") then
|
||||
STANDARD.TZNAME = k
|
||||
elseif v:match("DTSTART") then
|
||||
STANDARD.DTSTART = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("RRULE") then
|
||||
STANDARD.RRULE = {
|
||||
FREQ = k:match("FREQ=([A-Z]+)"),
|
||||
BYDAY = k:match("BYDAY=([%+%-0-9A-Z,]+)"),
|
||||
BYMONTH = k:match("BYMONTH=([0-9]+)")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return STANDARD
|
||||
end
|
||||
|
||||
---Parse the ical date time format into an os.time integer and the utc
|
||||
---@param datetime string The datetime from the ical
|
||||
---@return date|nil time Parsed os.time()
|
||||
---@return unknown|nil utc UTC identifier
|
||||
function ical._private.parser.to_datetime(datetime)
|
||||
if not datetime then return end
|
||||
local dt, utc = {}, nil
|
||||
|
||||
dt.year, dt.month, dt.day = datetime:match("^(%d%d%d%d)(%d%d)(%d%d)")
|
||||
dt.hour, dt.min, dt.sec, utc = datetime:match("T(%d%d)(%d%d)(%d%d)(Z?)")
|
||||
|
||||
if (dt.hour == nil) or (dt.min == nil) or (dt.sec == nil) then
|
||||
dt.hour, dt.min, dt.sec, utc = 0, 0, 0, nil
|
||||
end
|
||||
|
||||
for k, v in pairs(dt) do dt[k] = tonumber(v) end
|
||||
return dt, utc
|
||||
end
|
||||
|
||||
function ical._private.parser.offset(offset)
|
||||
local s, h, m = offset:match("([+-])(%d%d)(%d%d)")
|
||||
if s == "+" then s = 1 else s = -1 end
|
||||
return s * (tonumber(h) * 3600 + tonumber(m) * 60)
|
||||
end
|
||||
|
||||
return ical
|
||||
@@ -62,5 +62,13 @@ return function()
|
||||
-- Signals
|
||||
Hover_signal(date_widget)
|
||||
|
||||
date_widget:buttons {
|
||||
gears.table.join(
|
||||
awful.button({}, 1, function()
|
||||
awesome.emit_signal("calendar::toggle", date_widget)
|
||||
end)
|
||||
)
|
||||
}
|
||||
|
||||
return date_widget
|
||||
end
|
||||
|
||||
@@ -214,6 +214,8 @@ return function(s)
|
||||
keymap = keymap
|
||||
}
|
||||
|
||||
Hover_signal(kb_layout_item)
|
||||
|
||||
awesome.connect_signal(
|
||||
"update::background:kblayout",
|
||||
function()
|
||||
|
||||