A command line tool that generates XDG menus for several window managers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

302 lines
8.5 KiB

#!/usr/bin/env python
import os
import sys
import getopt
import gtk
import xdg.DesktopEntry as dentry
import xdg.Exceptions as exc
import xdg.BaseDirectory as bd
from operator import attrgetter
seticon = False
desktop = False
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-applications.directory')
applications = de.getName().encode('utf-8')
applications_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-accessories.directory')
accessories = de.getName().encode('utf-8')
accessories_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-development.directory')
development = de.getName().encode('utf-8')
development_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-education.directory')
education = de.getName().encode('utf-8')
education_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-games.directory')
games = de.getName().encode('utf-8')
games_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-graphics.directory')
graphics = de.getName().encode('utf-8')
graphics_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-multimedia.directory')
multimedia = de.getName().encode('utf-8')
multimedia_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-network.directory')
network = de.getName().encode('utf-8')
network_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-office.directory')
office = de.getName().encode('utf-8')
office_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-settings.directory')
settings = de.getName().encode('utf-8')
settings_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-system.directory')
system = de.getName().encode('utf-8')
system_icon = de.getIcon()
de = dentry.DesktopEntry(filename = '/usr/share/desktop-directories/xdgmenumaker-other.directory')
other = de.getName().encode('utf-8')
other_icon = de.getIcon()
def main(argv):
global desktop
global seticon
try:
opts, args = getopt.getopt(argv, "hif:", ["help", "icons" ,"format="])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit(0)
elif opt in ("-i", "--icons"):
seticon = True
elif opt in ("-f", "--format"):
desktop = arg
if desktop is False:
usage()
sys.exit('ERROR: You must specify the output format with -f')
elif desktop == "fluxbox":
fluxboxmenu()
elif desktop == "windowmaker":
seticon = False
windowmakermenu()
else:
usage()
sys.exit(2)
def usage():
print 'USAGE:', os.path.basename(sys.argv[0]), '[OPTIONS]'
print
print 'OPTIONS:'
print ' -f, --format the output format to use. Valid options are fluxbox and windowmaker'
print ' -i, --icons enable support for icons in the menus. Only works with fluxbox'
print ' -h, --help show this help message'
print ' You have to specify the output format using the -f switch.'
print
print 'EXAMPLES:'
print ' xdgmenumaker -f windowmaker'
print ' xdgmenumaker -i -f fluxbox'
class MenuEntry:
def __init__(self, category, name, icon, command):
self.category = category
self.name = name
self.icon = icon
self.command = command
def __repr__(self):
return repr((self.category, self.name, self.icon, self.command))
def icon_full_path(icon):
icon = os.path.basename(icon)
if icon.endswith('.png'):
icon = icon.replace('.png', '')
elif icon.endswith('.svg'):
icon = icon.replace('.svg', '')
elif icon.endswith('.xpm'):
icon = icon.replace('.xpm', '')
icon_theme = gtk.icon_theme_get_default()
icon = icon_theme.lookup_icon(icon, 16, gtk.ICON_LOOKUP_NO_SVG)
if icon:
icon = icon.get_filename()
return icon
def get_entry_info(desktopfile):
global desktop
global seticon
show = True
de = dentry.DesktopEntry(filename = desktopfile)
name = de.getName().encode('utf-8')
if seticon == True:
# strip the directory and extension from the icon name
icon = de.getIcon()
icon = icon_full_path(icon)
else:
icon = None
hidden = de.getHidden()
if hidden == True:
show = False
nodisplay = de.getNoDisplay()
if nodisplay == True:
show = False
# removing any %U or %F from the exec line
command = de.getExec().partition('%')[0]
terminal = de.getTerminal()
if terminal is True:
command = 'xterm -e '+command
# cleaning up categories and keeping only registered freedesktop.org main categories
categories = de.getCategories()
if 'AudioVideo' in categories:
category = multimedia
elif 'Audio' in categories:
category = multimedia
elif 'Video' in categories:
category = multimedia
elif 'Development' in categories:
category = development
elif 'Education' in categories:
category = education
elif 'Game' in categories:
category = games
elif 'Graphics' in categories:
category = graphics
elif 'Network' in categories:
category = network
elif 'Office' in categories:
category = office
elif 'System' in categories:
category = system
elif 'Settings' in categories:
category = settings
elif 'Utility' in categories:
category = accessories
else:
category = other
onlyshowin = de.getOnlyShowIn()
notshowin = de.getNotShowIn()
# none of the freedesktop registered environments are supported by this anyway
# http://standards.freedesktop.org/menu-spec/latest/apb.html
if onlyshowin != []:
show = False
if desktop in notshowin:
show = False
if show == True:
return [category, name, icon, command]
else:
return None
def sortedcategories(applist):
categories = []
for e in applist:
categories.append(e.category)
categories = sorted(set(categories))
return categories
def desktopfilelist():
dirs = []
# some directories are mentioned twice in bd.xdg_data_dirs, once
# with and once without a trailing /
for i in bd.xdg_data_dirs:
dirs.append(i.rstrip('/'))
dirs = set(dirs)
filelist = []
for d in dirs:
print d
xdgdir = d+'/applications'
if os.path.isdir(xdgdir):
for i in os.listdir(xdgdir):
if i.endswith('.desktop'):
filelist.append(xdgdir+'/'+i)
return filelist
def menu():
applist = []
for desktopfile in desktopfilelist():
try:
if desktopfile.endswith('.desktop'):
e = get_entry_info(desktopfile)
if e is not None:
applist.append(MenuEntry(e[0], e[1], e[2], e[3]))
except exc.ParsingError:
pass
sortedapplist = sorted(applist, key=attrgetter('category', 'name'))
menu = []
for c in sortedcategories(applist):
appsincategory = []
for i in sortedapplist:
if i.category == c:
appsincategory.append([i.name, i.icon, i.command])
menu.append([c, appsincategory])
return menu
def category_icon(category):
if category == accessories:
icon = accessories_icon
elif category == development:
icon = development_icon
elif category == education:
icon = education_icon
elif category == games:
icon = games_icon
elif category == graphics:
icon = graphics_icon
elif category == multimedia:
icon = multimedia_icon
elif category == network:
icon = network_icon
elif category == office:
icon = office_icon
elif category == settings:
icon = settings_icon
elif category == system:
icon = system_icon
elif category == other:
icon = other_icon
else:
icon = None
return icon
def fluxboxmenu():
global seticon
if seticon == True:
app_icon = icon_full_path(applications_icon)
print '[submenu] ('+applications+') <'+app_icon+'>'
else:
print '[submenu] ('+applications+')'
for i in menu():
category = i[0]
if seticon == True:
cat_icon = category_icon(category)
cat_icon = icon_full_path(cat_icon)
if cat_icon:
print ' [submenu] ('+category+') <'+cat_icon+'>'
else:
print ' [submenu] ('+category+')'
else:
print ' [submenu] ('+category+')'
for j in i[1]:
name = j[0]
icon = j[1]
command = j[2]
if icon is None:
print ' [exec] ('+name+') {'+command+'}'
else:
print ' [exec] ('+name+') {'+command+'} <'+icon+'>'
print ' [end] # ('+category+')'
print '[end] # ('+applications+')'
def windowmakermenu():
print '"'+applications+'" MENU'
for i in menu():
category = i[0]
print ' "'+category+'" MENU'
for j in i[1]:
name = j[0]
command = j[2]
print ' "'+name+'" EXEC '+command
print ' "'+category+'" END'
print '"'+applications+'" END'
if __name__ == "__main__":
main(sys.argv[1:])