e372ea5
#!/usr/bin/python2
e372ea5
"""Menu Generator for Fluxbox
e372ea5
e372ea5
Generates a menu for Fluxbox using the freedesktop.org standards
e372ea5
e372ea5
Usage: fluxbox-fdo-menugen.py [options]
e372ea5
e372ea5
Options:
e372ea5
  -l ..., --lang=...      create the menu using a language. Default = $LANG
e372ea5
  -h, --help              show this help
e372ea5
  -f ..., --file=...      output the menu into a file. Default = ~/.fluxbox/menu
e372ea5
  --with-icons         do not put icons for applications in the menu
e372ea5
  --stdout                output the menu to standard output
e372ea5
e372ea5
"""
e372ea5
e372ea5
__author__ = "Rudolf Kastl , Antonio Gomes"
e372ea5
__version__ = "$Revision: 1.0 $"
e372ea5
__date__ = "$Date: 2005/04/09 17:46:19 $"
e372ea5
__license__ = "GPL"
e372ea5
e372ea5
e372ea5
import os,re,sys,glob,getopt
e372ea5
import xdg.Menu,xdg.DesktopEntry,xdg.IconTheme
e372ea5
e372ea5
def usage():
e372ea5
	print __doc__
e372ea5
e372ea5
def header(wm="fluxbox"):
e372ea5
	return """
e372ea5
[begin] (Fluxbox)
e372ea5
	[exec] (Web Browser) {htmlview}
e372ea5
	[exec] (Email) {evolution}
e372ea5
	[exec] (Terminal) {gnome-terminal}
e372ea5
	[exec] (Irc) {xchat}
e372ea5
	[separator]\n"""
e372ea5
e372ea5
def footer(wm="fluxbox"):
e372ea5
	return """
e372ea5
	[submenu] (Fluxbox Menu)
e372ea5
		[config] (Configure)
e372ea5
		[submenu] (System Styles) {Choose a style...}
e372ea5
			[stylesdir] (/usr/share/fluxbox/styles)
e372ea5
			[stylesdir] (/usr/share/commonbox/styles/)
e372ea5
		[end]
e372ea5
		[submenu] (User Styles) {Choose a style...}
e372ea5
			[stylesdir] (~/.fluxbox/styles)
e372ea5
		[end]
e372ea5
		[workspaces]   (Workspace List)
e372ea5
		[submenu] (Tools)
e372ea5
			[exec] (Window name) {xprop WM_CLASS|cut -d \" -f 2|xmessage -file - -center}
e372ea5
			[exec] (Screenshot - JPG) {import screenshot.jpg && display -resize 50% screenshot.jpg}
e372ea5
			[exec] (Screenshot - PNG) {import screenshot.png && display -resize 50% screenshot.png}
e372ea5
			[exec] (Run) {fbrun }
e372ea5
			[exec] (Regen Menu) {fluxbox-generate_menu --with-icons}
e372ea5
		[end]
e372ea5
		[submenu] (Window)
e372ea5
			[restart] (kde) {startkde}
e372ea5
			[restart] (openbox) {openbox}
e372ea5
			[restart] (gnome) {gnome-session}
e372ea5
		[end]
e372ea5
		[exec] (Lock screen) {xscreensaver-command -lock}
e372ea5
		[commanddialog] (Fluxbox Command)
e372ea5
		[reconfig] (Reload config)
e372ea5
		[restart] (Restart)
e372ea5
		[separator]
e372ea5
		[exit] (Exit)
e372ea5
	[end]
e372ea5
[end]\n"""	
e372ea5
e372ea5
def checkWm(entry, wm="fluxbox"):
e372ea5
	if entry.DesktopEntry.getOnlyShowIn() != []:
e372ea5
		entry.Show = False
e372ea5
	if entry.DesktopEntry.getNotShowIn() != []:
e372ea5
		if isinstance(entry, xdg.Menu.MenuEntry):
e372ea5
			if wm in entry.DesktopEntry.getNotShowIn():
e372ea5
				entry.Show = False
e372ea5
			else:
e372ea5
				entry.Show = True 
e372ea5
	
e372ea5
#def findIcon(icon):
e372ea5
#	"""Finds the path and filename for the given icon name
e372ea5
#		e.g. gaim --> /usr/share/pixmaps/gaim.png
e372ea5
#		e.g. fart.png --> /usr/share/pixmaps/fart.png
e372ea5
#	"""
e372ea5
#	if os.path.isfile(icon): return icon
e372ea5
#	paths = ["~/.icons","/usr/share/pixmaps","/usr/share/icons"]
e372ea5
#	for path in paths:
e372ea5
#		for dirpath , dirnames, filenames in os.walk(os.path.expanduser(path)):
e372ea5
#			for filename in filenames:
e372ea5
#				pattern = '^%s\.(png|jpg|gif|xpm)' % icon # matches <filename>.<something>
e372ea5
#				if icon == filename or re.search(pattern, filename):
e372ea5
#					return os.path.join(dirpath,filename)
e372ea5
e372ea5
e372ea5
def findIcon(icon):
e372ea5
	"""Finds the path and filename for the given icon name
e372ea5
		e.g. gaim --> /usr/share/pixmaps/gaim.png
e372ea5
		e.g. fart.png --> /usr/share/pixmaps/fart.png
e372ea5
	"""
e372ea5
	global paths
e372ea5
	global locs
e372ea5
e372ea5
	# Case Icon=/path/to/file.extension
e372ea5
	if os.path.isfile(icon): return icon
e372ea5
e372ea5
e372ea5
	# Case Icon=file.extension	
e372ea5
e372ea5
	if re.search("^\w+.*\.\w{3}$",icon):
e372ea5
		names=[icon]
e372ea5
	# Case Icon=file
e372ea5
	elif re.search("^\w+.*$",icon):
e372ea5
		names=[icon+".png",icon+".xpm",icon+".jpg"]
e372ea5
	else:
e372ea5
		names=[]
e372ea5
e372ea5
	for path in paths:	
e372ea5
		for name in names:
e372ea5
			if (os.path.isfile(path+name)):
e372ea5
				locs.append(path)
e372ea5
				return (path+name).encode('utf8')
e372ea5
e372ea5
e372ea5
def parseMenu(menu,depth=1):
e372ea5
	global wm
e372ea5
	global use_icons
e372ea5
	if use_icons:
e372ea5
		print "%s[submenu] (%s) <%s> " % ( (depth*"\t"), menu.getName().encode('utf8'), findIcon(menu.getIcon()) )
e372ea5
	else:
e372ea5
		print "%s[submenu] (%s) " % ( (depth*"\t"), menu.getName().encode('utf8'), )
e372ea5
	depth += 1
e372ea5
	for entry in menu.getEntries():
e372ea5
		if isinstance(entry, xdg.Menu.Menu):
e372ea5
			parseMenu(entry,depth)
e372ea5
		elif isinstance(entry, xdg.Menu.MenuEntry):
e372ea5
			checkWm(entry,wm)
e372ea5
			if entry.Show == False: continue
e372ea5
			if use_icons:
e372ea5
				print "%s[exec] (%s) {%s} <%s> " % ( (depth*"\t"), entry.DesktopEntry.getName().encode("utf8"), entry.DesktopEntry.getExec().split()[0], findIcon(entry.DesktopEntry.getIcon()) )
e372ea5
			else:
e372ea5
				print "%s[exec] (%s) {%s} " % ( (depth*"\t"), entry.DesktopEntry.getName().encode("utf8"), entry.DesktopEntry.getExec().split()[0] )
e372ea5
		elif isinstance(entry,xdg.Menu.Separator):
e372ea5
			print "%s[separator]" % (depth*"\t")
e372ea5
		elif isinstance(entry.xdg.Menu.Header):
e372ea5
			print "%s%s" % ( (depth*"\t"), entry.Name )
e372ea5
	depth -= 1
e372ea5
	print "%s[end]" % (depth*"\t")
e372ea5
e372ea5
e372ea5
def main(argv):
e372ea5
# Setting the default values
e372ea5
	global locs
e372ea5
	locs=[]
e372ea5
	global wm
e372ea5
	wm = "fluxbox"
e372ea5
	global file
e372ea5
	file = "~/.fluxbox/menu"
e372ea5
	global use_icons
e372ea5
	use_icons = False
e372ea5
	lang = os.getenv("LANG","C")
e372ea5
	file = os.path.expanduser("~/.fluxbox/menu")
e372ea5
	
e372ea5
	try:
e372ea5
		opts, args = getopt.getopt(argv, "hf:dl:d", ["help","lang=","file=","with-icons","stdout"])
e372ea5
	except getopt.GetoptError:
e372ea5
		usage()
e372ea5
		sys.exit(2)
e372ea5
	for opt, arg in opts:
e372ea5
		if opt in ("-h", "--help"):
e372ea5
			usage()
e372ea5
			sys.exit()
e372ea5
		elif opt in ("-l", "--lang"):
e372ea5
			lang = arg
e372ea5
		elif opt in ("-f", "--file"):
e372ea5
			file = os.path.expanduser(arg)
e372ea5
		elif opt == '--with-icons':
e372ea5
			use_icons = True		
e372ea5
			global paths
e372ea5
			locations = \
e372ea5
			['/usr/share/pixmaps/', \
e372ea5
			'/usr/share/icons/hicolor/24x24/apps/', \
e372ea5
			'/usr/share/icons/hicolor/32x32/apps/', \
e372ea5
			'/usr/share/icons/hicolor/48x48/apps/', \
e372ea5
			'/usr/share/icons/hicolor/24x24/stock/generic/', \
e372ea5
			'/usr/share/icons/HighContrastLargePrintInverse/48x48/apps/', \
e372ea5
			'/usr/share/icons/crystalsvg/16x16/apps/', \
e372ea5
			'/usr/share/icons/crystalsvg/32x32/apps/', \
e372ea5
			'/usr/share/icons/crystalsvg/48x48/apps/', \
e372ea5
			'/usr/share/icons/crystalsvg/48x48/devices/', \
e372ea5
			'/usr/share/icons/', \
e372ea5
			'/usr/share/icons/hicolor/32x32/apps/', \
e372ea5
			'/usr/share/icons/Bluecurve/24x24/stock/', \
e372ea5
			'/usr/share/icons/Bluecurve/48x48/filesystems/']
e372ea5
			paths=locations
e372ea5
#			for path in locations:
e372ea5
#				paths+=glob.glob(path+"/*/")+glob.glob(path+"/*/*/")
e372ea5
#			print paths
e372ea5
		elif opt == '--stdout':
e372ea5
			file = sys.stdout
e372ea5
e372ea5
e372ea5
	fsock = open(file,'w')
e372ea5
	saveout = sys.stdout
e372ea5
	sys.stdout = fsock
e372ea5
e372ea5
	menu=xdg.Menu.parse()
e372ea5
# is done automatically now
e372ea5
#	menu.setLocale(lang)
e372ea5
e372ea5
	print header()
e372ea5
	parseMenu(menu)
e372ea5
	print footer()
e372ea5
e372ea5
	sys.stdout = saveout
e372ea5
#	print menu
e372ea5
if __name__ == "__main__":
e372ea5
	main(sys.argv[1:])
e372ea5
e372ea5
#WindowMaker Reminder
e372ea5
#>>> p=re.compile("(\).*),(\s*\))")
e372ea5
#>>> p.search("((ola),(ola),)").groups()
e372ea5
#('),(ola)', ')')
e372ea5