diff options
| -rw-r--r-- | todo-widget/README.md | 21 | ||||
| -rw-r--r-- | todo-widget/todo.gif | bin | 0 -> 203168 bytes | |||
| -rw-r--r-- | todo-widget/todo.lua | 272 | 
3 files changed, 293 insertions, 0 deletions
| diff --git a/todo-widget/README.md b/todo-widget/README.md new file mode 100644 index 0000000..9c26eb9 --- /dev/null +++ b/todo-widget/README.md @@ -0,0 +1,21 @@ +# ToDo Widget (in progress) + +This widgets displays a list of to do items and allows to mark item as done, delete item and create new ones: + + + +# Installation + +Clone repo under **~/.config/awesome/** and add the widget in **rc.lua**: + +```lua +local todo_widget = require("awesome-wm-widgets.todo-widget.todo") +... +s.mytasklist, -- Middle widget +	{ -- Right widgets +    	layout = wibox.layout.fixed.horizontal, +		... +        -- default         +        todo_widget(), +		...       +```
\ No newline at end of file diff --git a/todo-widget/todo.gif b/todo-widget/todo.gifBinary files differ new file mode 100644 index 0000000..7160e21 --- /dev/null +++ b/todo-widget/todo.gif diff --git a/todo-widget/todo.lua b/todo-widget/todo.lua new file mode 100644 index 0000000..ee459cf --- /dev/null +++ b/todo-widget/todo.lua @@ -0,0 +1,272 @@ +------------------------------------------------- +-- ToDo Widget for Awesome Window Manager +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/todo-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local json = require("json") +local spawn = require("awful.spawn") +local naughty = require("naughty") +local gears = require("gears") +local beautiful = require("beautiful") +local gfs = require("gears.filesystem") +local gs = require("gears.string") + +local HOME_DIR = os.getenv("HOME") + +local STORAGE = HOME_DIR .. '/.cache/awmw/todo-widget/todos.json' +local GET_TODO_ITEMS = 'bash -c "cat ' .. STORAGE .. '"' + +local rows  = { layout = wibox.layout.fixed.vertical } + +local todo_widget = {} + +todo_widget.widget = wibox.widget { +    { +        { +            id = "icon", +            widget = wibox.widget.imagebox +        }, +        id = "margin", +        margins = 4, +        layout = wibox.container.margin +    }, +    { +        id = "txt", +        widget = wibox.widget.textbox +    }, +    layout = wibox.layout.fixed.horizontal, +    set_text = function(self, new_value) +        self.txt.text = new_value +    end, +    set_icon = function(self, new_value) +        self.margin.icon.image = new_value +    end +} + +function todo_widget:update_counter(todos) +    local todo_count = 0 +    for _,p in ipairs(todos) do +        if not p.status then +            todo_count = todo_count + 1 +        end +    end + +    todo_widget.widget:set_text(todo_count) +end + +local popup = awful.popup{ +    bg = beautiful.bg_normal, +    ontop = true, +    visible = false, +    shape = gears.shape.rounded_rect, +    border_width = 1, +    border_color = beautiful.bg_focus, +    maximum_width = 400, +    offset = { y = 5 }, +    widget = {} +} + +local add_button = wibox.widget { +    { +        { +            image = '/usr/share/icons/Arc/actions/symbolic/list-add-symbolic.svg', +            resize = false, +            widget = wibox.widget.imagebox +        }, +        top = 11, +        left = 8, +        right = 8, +        layout = wibox.container.margin +    }, +    shape = function(cr, width, height) +        gears.shape.circle(cr, width, height, 12) +    end, +    widget = wibox.container.background +} + +add_button:connect_signal("button::press", function(c) +    local pr = awful.widget.prompt() + +    table.insert(rows, wibox.widget { +        { +            { +                pr.widget, +                spacing = 8, +                layout = wibox.layout.align.horizontal +            }, +            margins = 8, +            layout = wibox.container.margin +        }, +        bg = beautiful.bg_normal, +        widget = wibox.container.background +    }) +    awful.prompt.run{ +        prompt = "<b>New item</b>: ", +        bg = beautiful.bg_normal, +        bg_cursor = beautiful.fg_urgent, +        textbox = pr.widget, +        exe_callback = function(input_text) +            if not input_text or #input_text == 0 then return end +            spawn.easy_async(GET_TODO_ITEMS, function(stdout) +                local res = json.decode(stdout) +                table.insert(res.todo_items, {todo_item = input_text, status = false}) +                spawn.easy_async_with_shell("echo '" .. json.encode(res) .. "' > " .. STORAGE, function() +                    spawn.easy_async(GET_TODO_ITEMS, function(stdout) update_widget(stdout) end) +                end) +            end) +        end +    } +    popup:setup(rows) +end) +add_button:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) +add_button:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + +local function worker(args) + +    local args = args or {} + +    local icon = args.icon or '/usr/share/icons/Arc/status/symbolic/checkbox-checked-symbolic.svg' + +    todo_widget.widget:set_icon(icon) + +    function update_widget(stdout) +        local result = json.decode(stdout) +        if result == nil or result == '' then result = {} end +        todo_widget:update_counter(result.todo_items) + +        for i = 0, #rows do rows[i]=nil end + +        local first_row = wibox.widget { +            { +                {widget = wibox.widget.textbox}, +                { +                    markup = '<span size="large" font_weight="bold" color="#ffffff">ToDo</span>', +                    align = 'center', +                    forced_width = 350, -- for horizontal alignment +                    forced_height = 40, +                    widget = wibox.widget.textbox +                }, +                add_button, +                spacing = 8, +                layout = wibox.layout.fixed.horizontal +            }, +            bg = beautiful.bg_normal, +            widget = wibox.container.background +        } + +        table.insert(rows, first_row) + + +        for i, todo_item in ipairs(result.todo_items) do + +            local checkbox = wibox.widget { +                checked       = todo_item.status, +                color         = beautiful.bg_normal, +                paddings      = 2, +                shape         = gears.shape.circle, +                forced_width = 20, +                forced_height = 20, +                check_color = beautiful.fg_urgent, +                widget        = wibox.widget.checkbox +            } + +            checkbox:connect_signal("button::press", function(c) +                c:set_checked(not c.checked) +                todo_item.status = not todo_item.status +                result.todo_items[i] = todo_item +                spawn.easy_async_with_shell("echo '" .. json.encode(result) .. "' > " .. STORAGE) +                todo_widget:update_counter(result.todo_items) +            end) + +            local trash_button = wibox.widget { +                { +                    {    image = '/usr/share/icons/Arc/actions/symbolic/window-close-symbolic.svg', +                        resize = false, +                        widget = wibox.widget.imagebox +                    }, +                    margins = 5, +                    layout = wibox.container.margin +                }, +                border_width = 1, +                shape = function(cr, width, height) +                    gears.shape.circle(cr, width, height, 10) +                end, +                widget = wibox.container.background +            } + +            trash_button:connect_signal("button::press", function(c) +                table.remove(result.todo_items, i) +                spawn.easy_async_with_shell("printf '" .. json.encode(result) .. "' > /home/pmakhov/.cache/awmw/todo-widget/todos.json") +                spawn.easy_async(GET_TODO_ITEMS, function(stdout) update_widget(stdout) end) +            end) + +            local row = wibox.widget { +                { +                    { +                        { +                             +                            checkbox, +                            valign = 'center', +                            layout = wibox.container.place, +                        }, +                        { +                            { +                                text = todo_item.todo_item, +                                align = 'left', +                                widget = wibox.widget.textbox +                            }, +                            left = 10, +                            layout = wibox.container.margin +                        }, +                        { +                            trash_button, +                            valign = 'center', +                            layout = wibox.container.place, +                        }, +                        spacing = 8, +                        layout = wibox.layout.align.horizontal +                    }, +                    margins = 8, +                    layout = wibox.container.margin +                }, +                bg = beautiful.bg_normal, +                widget = wibox.container.background +            } + +            row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) +            row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + +            table.insert(rows, row) +        end + +        popup:setup(rows) +    end + +    todo_widget.widget:buttons( +            awful.util.table.join( +                    awful.button({}, 1, function() +                        if popup.visible then +                            popup.visible = not popup.visible +                        else +                            popup:move_next_to(mouse.current_widget_geometry) +                        end +                    end) +            ) +    ) + +    spawn.easy_async(GET_TODO_ITEMS, function(stdout) update_widget(stdout) end) + +    return todo_widget.widget +end + +if not gfs.file_readable(STORAGE) then +    spawn.easy_async(string.format([[bash -c "dirname %s | xargs mkdir -p && echo '{\"todo_items\":{}}' > %s"]], STORAGE, STORAGE)) +end + +return setmetatable(todo_widget, { __call = function(_, ...) return worker(...) end }) | 
