255 lines
7.8 KiB
Lua
255 lines
7.8 KiB
Lua
|
--[[
|
||
|
|
||
|
Awesome-Freedesktop
|
||
|
Freedesktop.org compliant desktop entries and menu
|
||
|
|
||
|
Desktop section
|
||
|
|
||
|
Licensed under GNU General Public License v2
|
||
|
* (c) 2016, Luke Bonham
|
||
|
* (c) 2009-2015, Antonio Terceiro
|
||
|
|
||
|
--]]
|
||
|
|
||
|
local awful = require("awful")
|
||
|
local theme = require("beautiful")
|
||
|
local utils = require("menubar.utils")
|
||
|
local wibox = require("wibox")
|
||
|
|
||
|
local capi = capi
|
||
|
local io = io
|
||
|
local ipairs = ipairs
|
||
|
local mouse = mouse
|
||
|
local os = os
|
||
|
local string = string
|
||
|
local table = table
|
||
|
|
||
|
-- Desktop icons
|
||
|
-- freedesktop.desktop
|
||
|
local desktop = {
|
||
|
-- Default desktop basic icons
|
||
|
baseicons = {
|
||
|
[1] = {
|
||
|
label = "This PC",
|
||
|
icon = "computer",
|
||
|
onclick = "computer://"
|
||
|
},
|
||
|
[2] = {
|
||
|
label = "Home",
|
||
|
icon = "user-home",
|
||
|
onclick = os.getenv("HOME")
|
||
|
},
|
||
|
[3] = {
|
||
|
label = "Trash",
|
||
|
icon = "user-trash",
|
||
|
onclick = "trash://"
|
||
|
}
|
||
|
},
|
||
|
-- Default parameters
|
||
|
iconsize = { width = 48, height = 48 },
|
||
|
labelsize = { width = 140, height = 20 },
|
||
|
margin = { x = 20, y = 20 },
|
||
|
}
|
||
|
|
||
|
-- MIME types list
|
||
|
local mime_types = {}
|
||
|
|
||
|
-- Icons positioning
|
||
|
local desktop_current_pos = {}
|
||
|
|
||
|
-- @return iterator on input pipe
|
||
|
local function pipelines(...)
|
||
|
local f = assert(io.popen(...))
|
||
|
return function ()
|
||
|
local data = f:read()
|
||
|
if data == nil then f:close() end
|
||
|
return data
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Adds an icon to desktop
|
||
|
-- @param args settings from desktop.add_icons
|
||
|
-- @param label icon string label
|
||
|
-- @param icon icon string file path
|
||
|
-- @param onclick function to execute on click
|
||
|
function desktop.add_single_icon(args, label, icon, onclick)
|
||
|
local s = args.screen
|
||
|
|
||
|
-- define icon dimensions and position
|
||
|
if not desktop_current_pos[s] then
|
||
|
desktop_current_pos[s] = { x = (capi.screen[s].geometry.x + args.iconsize.width + args.margin.x), y = 40 }
|
||
|
end
|
||
|
|
||
|
local totheight = (icon and args.iconsize.height or 0) + (label and args.labelsize.height or 0)
|
||
|
if totheight == 0 then return end
|
||
|
|
||
|
if desktop_current_pos[s].y + totheight > capi.screen[s].geometry.height - 40 then
|
||
|
desktop_current_pos[s].x = desktop_current_pos[s].x + args.labelsize.width + args.iconsize.width + args.margin.x
|
||
|
desktop_current_pos[s].y = 40
|
||
|
end
|
||
|
|
||
|
local common = { screen = s, bg = "#00000000", visible = true, type = "desktop" }
|
||
|
|
||
|
-- create icon container
|
||
|
if icon then
|
||
|
common.width = args.iconsize.width
|
||
|
common.height = args.iconsize.height
|
||
|
common.x = desktop_current_pos[s].x
|
||
|
common.y = desktop_current_pos[s].y
|
||
|
|
||
|
icon = wibox.widget {
|
||
|
image = icon,
|
||
|
resize = false,
|
||
|
widget = wibox.widget.imagebox
|
||
|
}
|
||
|
|
||
|
icon:buttons(awful.button({ }, 1, nil, onclick))
|
||
|
|
||
|
icon_container = wibox(common)
|
||
|
icon_container:set_widget(icon)
|
||
|
|
||
|
desktop_current_pos[s].y = desktop_current_pos[s].y + args.iconsize.height + 5
|
||
|
end
|
||
|
|
||
|
-- create label container
|
||
|
if label then
|
||
|
common.width = args.labelsize.width
|
||
|
common.height = args.labelsize.height
|
||
|
common.x = desktop_current_pos[s].x - (args.labelsize.width/2) + args.iconsize.width/2
|
||
|
common.y = desktop_current_pos[s].y
|
||
|
|
||
|
caption = wibox.widget {
|
||
|
text = label,
|
||
|
align = "center",
|
||
|
forced_width = common.width,
|
||
|
forced_height = common.height,
|
||
|
ellipsize = "middle",
|
||
|
widget = wibox.widget.textbox
|
||
|
}
|
||
|
|
||
|
caption:buttons(awful.button({ }, 1, onclick))
|
||
|
caption_container = wibox(common)
|
||
|
caption_container:set_widget(caption)
|
||
|
end
|
||
|
|
||
|
desktop_current_pos[s].y = desktop_current_pos[s].y + args.labelsize.height + args.margin.y
|
||
|
end
|
||
|
|
||
|
-- Adds base icons (This PC, Trash, etc) to desktop
|
||
|
-- @param args settings from desktop.add_icons
|
||
|
function desktop.add_base_icons(args)
|
||
|
for _,base in ipairs(args.baseicons) do
|
||
|
desktop.add_single_icon(args, base.label, utils.lookup_icon(base.icon), function()
|
||
|
awful.spawn(string.format("%s '%s'", args.open_with, base.onclick))
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Looks up a suitable icon for filename
|
||
|
-- @param filename string file name
|
||
|
-- @return icon file path (string)
|
||
|
function desktop.lookup_file_icon(filename)
|
||
|
-- load system MIME types
|
||
|
if #mime_types == 0 then
|
||
|
for line in io.lines("/etc/mime.types") do
|
||
|
if not line:find("^#") then
|
||
|
local parsed = {}
|
||
|
for w in line:gmatch("[^%s]+") do
|
||
|
table.insert(parsed, w)
|
||
|
end
|
||
|
if #parsed > 1 then
|
||
|
for i = 2, #parsed do
|
||
|
mime_types[parsed[i]] = parsed[1]:gsub("/", "-")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- try to search a possible icon among standards
|
||
|
local extension = filename:match("%a+$")
|
||
|
local mime = mime_types[extension] or ""
|
||
|
local mime_family = mime:match("^%a+") or ""
|
||
|
|
||
|
local possible_filenames = {
|
||
|
mime, "gnome-mime-" .. mime,
|
||
|
mime_family, "gnome-mime-" .. mime_family,
|
||
|
extension
|
||
|
}
|
||
|
|
||
|
for i, filename in ipairs(possible_filenames) do
|
||
|
local icon = utils.lookup_icon(filename)
|
||
|
if icon then return icon end
|
||
|
end
|
||
|
|
||
|
-- if we don"t find ad icon, then pretend is a plain text file
|
||
|
return utils.lookup_icon("text-x-generic")
|
||
|
end
|
||
|
|
||
|
-- Parse subdirectories and files list from input directory
|
||
|
-- @input dir directory to parse (string)
|
||
|
-- @return files table with found entries
|
||
|
function desktop.parse_dirs_and_files(dir)
|
||
|
local files = {}
|
||
|
local paths = pipelines('find '..dir..' -maxdepth 1 -type d | tail -1')
|
||
|
for path in paths do
|
||
|
if path:match("[^/]+$") then
|
||
|
local file = {}
|
||
|
file.filename = path:match("[^/]+$")
|
||
|
file.path = path
|
||
|
file.show = true
|
||
|
file.icon = utils.lookup_icon("folder")
|
||
|
table.insert(files, file)
|
||
|
end
|
||
|
end
|
||
|
local paths = pipelines('find '..dir..' -maxdepth 1 -type f')
|
||
|
for path in paths do
|
||
|
if not path:find("%.desktop$") then
|
||
|
local file = {}
|
||
|
file.filename = path:match("[^/]+$")
|
||
|
file.path = path
|
||
|
file.show = true
|
||
|
file.icon = desktop.lookup_file_icon(file.filename)
|
||
|
table.insert(files, file)
|
||
|
end
|
||
|
end
|
||
|
return files
|
||
|
end
|
||
|
|
||
|
-- Adds subdirectories and files icons from args.dir
|
||
|
-- @param args settings from desktop.add_icons
|
||
|
function desktop.add_dirs_and_files_icons(args)
|
||
|
for _, file in ipairs(desktop.parse_dirs_and_files(args.dir)) do
|
||
|
if file.show then
|
||
|
local label = args.showlabels and file.filename or nil
|
||
|
local onclick = function () awful.spawn(string.format("%s '%s'", args.open_with, file.path)) end
|
||
|
desktop.add_single_icon(args, label, file.icon, onclick)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Main function, adds base, directory and files icons
|
||
|
-- @param args user defined settings, with fallback on defaults
|
||
|
function desktop.add_icons(args)
|
||
|
args = args or {}
|
||
|
args.screen = args.screen or mouse.screen
|
||
|
args.dir = args.dir or os.getenv("HOME") .. "/Desktop"
|
||
|
args.showlabels = args.showlabel or true
|
||
|
args.open_with = args.open_with or "xdg_open"
|
||
|
args.baseicons = args.baseicons or desktop.baseicons
|
||
|
args.iconsize = args.iconsize or desktop.iconsize
|
||
|
args.labelsize = args.labelsize or desktop.labelsize
|
||
|
args.margin = args.margin or desktop.margin
|
||
|
|
||
|
-- trying to fallback on Adwaita if theme.icon_theme is not defined
|
||
|
-- if Adwaita is missing too, no icons will be shown
|
||
|
if not theme.icon_theme then
|
||
|
theme.icon_theme = args.icon_theme or "Adwaita"
|
||
|
end
|
||
|
|
||
|
desktop.add_base_icons(args)
|
||
|
desktop.add_dirs_and_files_icons(args)
|
||
|
end
|
||
|
|
||
|
return desktop
|