-- This file is part of Reno desktop. -- -- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -- -- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see . -- Asynchronous XDG data aggregator (library) local menu_utils = require("menubar.utils") local awful = require("awful") local gears = require("gears") local json = require("dkjson") local lib = {} function lib.init_xdg_struct() -- Global xdg data struct local xdg = { directory_integrity = {}, directory_listings = {}, apps = {}, categories = { Other = { icon = "applications-other", apps = {} }, Wine = { icon = "wine", apps = {} } } } return xdg end function lib.load_xdg_cache() -- Load cached applications local cache_file = io.open(gears.filesystem.get_xdg_cache_home()..".reno_xdg_cache.json","r") local cache if cache_file then cache = json.decode(cache_file:read("*a")) cache_file:close() end return cache end function lib.add_categories(xdg, categories) -- Add missing category entries as defined by awesome for _,v in pairs(categories) do xdg.categories[v.app_type] = { name = v.name, icon = v.icon_name, apps = {} } end end function lib.async_process_dirs(xdg, dirs, cache, on_dir_done) -- Asynchronous scanning process for _,v in pairs(dirs) do xdg.directory_listings[v] = {} awful.spawn.with_line_callback("find "..tostring(v).." -maxdepth 1 -name *.desktop",{ stdout = function(line) -- Assume the cache is valid for a listed file if cache and cache.directory_listings[v][line] then xdg.directory_listings[v][line] = true xdg.apps[line] = cache.apps[line] xdg.categories[cache.apps[line].category].apps[line] = cache.apps[line] return end local data = menu_utils.parse_desktop_file(line) if data.NoDisplay then return end local appdata = { name = data.Name, category = "Other", exec = data.Exec, icon = (data.Icon and menu_utils.lookup_icon(data.Icon)), description = data.Comment } -- Match first available cateogry for sorting for _,vv in pairs(data.Categories or {"Other"}) do if xdg.categories[vv] then appdata.category = vv break end -- Oh how do I love those Wine applications and their categories if vv:match("^Wine") then appdata.category = "Wine" break end end -- Open terminal apps in the terminal (duh) if data.Terminal then appdata.exec = global.terminal.." -e "..appdata.exec end -- Just for you, Wine - special case because you're being a shit if (appdata.exec and appdata.exec:find("%W?wine ")) then appdata.category = "Wine" end xdg.apps[line] = appdata xdg.categories[appdata.category].apps[line] = appdata -- Add the file to the listing of cached ones xdg.directory_listings[v][line] = true end, output_done = function(...) on_dir_done(v,...) end }) end end function lib.generate_meta_patch(xdg) local patch = {apps = {}} for k,v in pairs(xdg.apps) do patch.apps[k] = {} for kk,vv in pairs(v) do patch.apps[k][kk] = vv end patch.apps[k].name = nil patch.apps[k].category = nil patch.apps[k].exec = nil patch.apps[k].icon = nil patch.apps[k].description = nil end return patch end function lib.apply_meta_patch(xdg,patch) for k,v in pairs(patch.apps) do if xdg.apps[k] then for kk,vv in pairs(v) do xdg.apps[k][kk] = vv end end end end return lib