Browse Source

Add Python 3 compatibility

Support Python 2 and Python 3 at the same time.
* Make sure modules are loaded with the correct names for each version
* Use a compatibility layer for GTK
* Make sure strings are encoded/decoded properly
pull/8/head
George Vlahavas 9 years ago
parent
commit
ab19431f3b
  1. 101
      src/xdgmenumaker

101
src/xdgmenumaker

@ -7,13 +7,28 @@ from __future__ import print_function
import os import os
import sys import sys
import getopt import getopt
import gtk
import xdg.DesktopEntry as dentry import xdg.DesktopEntry as dentry
import xdg.Exceptions as exc import xdg.Exceptions as exc
import xdg.BaseDirectory as bd import xdg.BaseDirectory as bd
import ConfigParser
from operator import attrgetter from operator import attrgetter
# ConfigParser in Python2 has been renamed to configparser (all lower case)
# in Python3. So, it's a good way to find out which Python version is being
# used.
python3 = False
try:
import ConfigParser as cp
except ImportError:
import configparser as cp
python3 = True
# Under Python3, load the gtk compatibility layer
if python3:
from gi import pygtkcompat
pygtkcompat.enable()
pygtkcompat.enable_gtk(version='3.0')
import gtk
seticon = False seticon = False
iconsize = 16 iconsize = 16
desktop = False desktop = False
@ -79,6 +94,7 @@ class MenuCategory:
de = dentry.DesktopEntry(filename=desktop_dir + de = dentry.DesktopEntry(filename=desktop_dir +
'xdgmenumaker-applications.directory') 'xdgmenumaker-applications.directory')
applications = de.getName().encode('utf-8') applications = de.getName().encode('utf-8')
apps_name = applications.decode()
applications_icon = de.getIcon() applications_icon = de.getIcon()
de = dentry.DesktopEntry(filename=desktop_dir + de = dentry.DesktopEntry(filename=desktop_dir +
'xdgmenumaker-accessories.directory') 'xdgmenumaker-accessories.directory')
@ -131,12 +147,12 @@ other_icon = de.getIcon()
terminal_app = os.getenv("XDGMENUMAKERTERM") terminal_app = os.getenv("XDGMENUMAKERTERM")
if not terminal_app: if not terminal_app:
try: try:
config = ConfigParser.SafeConfigParser() config = cp.SafeConfigParser()
config.read(os.path.expanduser('~/.config/xdgmenumaker.cfg')) config.read(os.path.expanduser('~/.config/xdgmenumaker.cfg'))
terminal_app = config.get('Terminal', 'terminal') terminal_app = config.get('Terminal', 'terminal')
# if there isn't, on debian and debian-likes, use the alternatives # if there isn't, on debian and debian-likes, use the alternatives
# system, otherwise default to xterm # system, otherwise default to xterm
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e: except (cp.NoSectionError, cp.NoOptionError) as e:
if (os.path.exists('/etc/alternatives/x-terminal-emulator') if (os.path.exists('/etc/alternatives/x-terminal-emulator')
and os.path.exists('/usr/bin/x-terminal-emulator')): and os.path.exists('/usr/bin/x-terminal-emulator')):
terminal_app = '/usr/bin/x-terminal-emulator' terminal_app = '/usr/bin/x-terminal-emulator'
@ -427,30 +443,32 @@ def fluxbox():
spacing = ' ' spacing = ' '
if seticon: if seticon:
app_icon = icon_full_path(applications_icon) app_icon = icon_full_path(applications_icon)
if app_icon is None: if app_icon is None:
print('[submenu] ({})'.format(applications)) print('[submenu] ({})'.format(apps_name))
else: else:
print('[submenu] ({}) <{}>'.format(applications, app_icon)) print('[submenu] ({}) <{}>'.format(apps_name, app_icon))
else: else:
print('[submenu] ({})'.format(applications)) print('[submenu] ({})'.format(apps_name))
else: else:
spacing = '' spacing = ''
for menu_category in menu(): for menu_category in menu():
category = menu_category.category category = menu_category.category
cat_name = category.decode()
if seticon: if seticon:
cat_icon = category_icon(category) cat_icon = category_icon(category)
cat_icon = icon_full_path(cat_icon) cat_icon = icon_full_path(cat_icon)
if cat_icon: if cat_icon:
print('{s}[submenu] ({c}) <{i}>'.format(s=spacing, c=category, print('{s}[submenu] ({c}) <{i}>'.format(s=spacing, c=cat_name,
i=cat_icon)) i=cat_icon))
else: else:
print('{s}[submenu] ({c})'.format(s=spacing, c=category)) print('{s}[submenu] ({c})'.format(s=spacing, c=cat_name))
else: else:
print('{s}[submenu] ({c})'.format(s=spacing, c=category)) print('{s}[submenu] ({c})'.format(s=spacing, c=cat_name))
for app in menu_category.applist: for app in menu_category.applist:
# closing parentheses need to be escaped, otherwise they are # closing parentheses need to be escaped, otherwise they are
# cropped out, along with everything that comes after them # cropped out, along with everything that comes after them
name = app.name.replace(')', '\)') name = app.name.decode().replace(')', '\)')
icon = app.icon icon = app.icon
command = app.command command = app.command
path = app.path path = app.path
@ -464,22 +482,23 @@ def fluxbox():
n=name, n=name,
c=command, c=command,
i=icon)) i=icon))
print('{s}[end] # ({c})'.format(s=spacing, c=category)) print('{s}[end] # ({c})'.format(s=spacing, c=cat_name))
if submenu: if submenu:
print('[end] # ({})'.format(applications)) print('[end] # ({})'.format(apps_name))
def windowmaker(): def windowmaker():
print('"{}" MENU'.format(applications)) print('"{}" MENU'.format(apps_name))
for menu_category in menu(): for menu_category in menu():
category = menu_category.category category = menu_category.category
print(' "{}" MENU'.format(category)) cat_name = category.decode()
print(' "{}" MENU'.format(cat_name))
for app in menu_category.applist: for app in menu_category.applist:
name = app.name name = app.name.decode()
command = app.command command = app.command
print(' "{n}" EXEC {c}'.format(n=name, c=command)) print(' "{n}" EXEC {c}'.format(n=name, c=command))
print(' "{}" END'.format(category)) print(' "{}" END'.format(cat_name))
print('"{}" END'.format(applications)) print('"{}" END'.format(apps_name))
def icewm(): def icewm():
@ -489,22 +508,23 @@ def icewm():
app_icon = icon_full_path(applications_icon) app_icon = icon_full_path(applications_icon)
if app_icon is None: if app_icon is None:
app_icon = "_none_" app_icon = "_none_"
print('menu "{a}" {i} {{'.format(a=applications, i=app_icon)) print('menu "{a}" {i} {{'.format(a=apps_name, i=app_icon))
else: else:
print('menu "{}" _none_ {{'.format(applications)) print('menu "{}" _none_ {{'.format(apps_name))
else: else:
spacing = '' spacing = ''
for menu_category in menu(): for menu_category in menu():
category = menu_category.category category = menu_category.category
cat_name = category.decode()
cat_icon = category_icon(category) cat_icon = category_icon(category)
cat_icon = icon_full_path(cat_icon) cat_icon = icon_full_path(cat_icon)
if seticon and cat_icon is not None: if seticon and cat_icon is not None:
print('{s}menu "{c}" {i} {{'.format(s=spacing, c=category, print('{s}menu "{c}" {i} {{'.format(s=spacing, c=cat_name,
i=cat_icon)) i=cat_icon))
else: else:
print('{s}menu "{c}" _none_ {{'.format(s=spacing, c=category)) print('{s}menu "{c}" _none_ {{'.format(s=spacing, c=cat_name))
for app in menu_category.applist: for app in menu_category.applist:
name = app.name name = app.name.decode()
icon = app.icon icon = app.icon
command = app.command command = app.command
if seticon and icon is not None: if seticon and icon is not None:
@ -529,26 +549,27 @@ def pekwmmenu():
if seticon: if seticon:
app_icon = icon_full_path(applications_icon) app_icon = icon_full_path(applications_icon)
print('{s}Submenu = "{a}" {{ Icon = "{i}"'.format(s=dspacing, print('{s}Submenu = "{a}" {{ Icon = "{i}"'.format(s=dspacing,
a=applications, a=apps_name,
i=app_icon)) i=app_icon))
else: else:
print('{s}Submenu = "{a}" {{'.format(s=dspacing, a=applications)) print('{s}Submenu = "{a}" {{'.format(s=dspacing, a=apps_name))
else: else:
spacing = '' spacing = ''
for menu_category in menu(): for menu_category in menu():
category = menu_category.category category = menu_category.category
cat_name = category.decode()
cat_icon = category_icon(category) cat_icon = category_icon(category)
cat_icon = icon_full_path(cat_icon) cat_icon = icon_full_path(cat_icon)
if seticon and cat_icon is not None: if seticon and cat_icon is not None:
print('{d}{s}Submenu = "{c}" {{ Icon = "{i}"'.format(d=dspacing, print('{d}{s}Submenu = "{c}" {{ Icon = "{i}"'.format(d=dspacing,
s=spacing, s=spacing,
c=category, c=cat_name,
i=cat_icon)) i=cat_icon))
else: else:
print('{d}{s}Submenu = "{c}" {{'.format(d=dspacing, s=spacing, print('{d}{s}Submenu = "{c}" {{'.format(d=dspacing, s=spacing,
c=category)) c=cat_name))
for app in menu_category.applist: for app in menu_category.applist:
name = app.name name = app.name.decode()
icon = app.icon icon = app.icon
# for some apps (like netbeans) the command is launched with # for some apps (like netbeans) the command is launched with
# /bin/sh "command" # /bin/sh "command"
@ -583,26 +604,27 @@ def jwm():
if seticon: if seticon:
app_icon = icon_full_path(applications_icon) app_icon = icon_full_path(applications_icon)
if app_icon is None: if app_icon is None:
print('<Menu label="{}">'.format(applications)) print('<Menu label="{}">'.format(apps_name))
else: else:
print('<Menu icon="{i}" label="{a}">'.format(i=app_icon, print('<Menu icon="{i}" label="{a}">'.format(i=app_icon,
a=applications)) a=apps_name))
else: else:
print('<Menu label="{}">'.format(applications)) print('<Menu label="{}">'.format(apps_name))
else: else:
spacing = '' spacing = ''
for menu_category in menu(): for menu_category in menu():
category = menu_category.category category = menu_category.category
cat_name = category.decode()
cat_icon = category_icon(category) cat_icon = category_icon(category)
cat_icon = icon_full_path(cat_icon) cat_icon = icon_full_path(cat_icon)
if seticon and cat_icon is not None: if seticon and cat_icon is not None:
print('{s}<Menu icon="{i}" label="{c}">'.format(s=spacing, print('{s}<Menu icon="{i}" label="{c}">'.format(s=spacing,
i=cat_icon, i=cat_icon,
c=category)) c=cat_name))
else: else:
print('{s}<Menu label="{c}">'.format(s=spacing, c=category)) print('{s}<Menu label="{c}">'.format(s=spacing, c=cat_name))
for app in menu_category.applist: for app in menu_category.applist:
name = app.name name = app.name.decode()
icon = app.icon icon = app.icon
command = app.command command = app.command
path = app.path path = app.path
@ -626,21 +648,22 @@ def compizboxmenu():
if seticon: if seticon:
app_icon = icon_strip(applications_icon) app_icon = icon_strip(applications_icon)
print('<menu icon="{i}" name="{a}">'.format(i=app_icon, print('<menu icon="{i}" name="{a}">'.format(i=app_icon,
a=applications)) a=apps_name))
else: else:
print('<menu name="{}">'.format(applications)) print('<menu name="{}">'.format(apps_name))
else: else:
spacing = '' spacing = ''
for menu_category in menu(ico_paths=False): for menu_category in menu(ico_paths=False):
category = menu_category.category category = menu_category.category
cat_name = category.decode()
cat_icon = category_icon(category) cat_icon = category_icon(category)
if seticon and cat_icon is not None: if seticon and cat_icon is not None:
print('{s}<menu icon="{i}" name="{c}">'.format( print('{s}<menu icon="{i}" name="{c}">'.format(
s=spacing, i=cat_icon, c=category)) s=spacing, i=cat_icon, c=cat_name))
else: else:
print('{s}<menu name="{c}">'.format(s=spacing, c=category)) print('{s}<menu name="{c}">'.format(s=spacing, c=cat_name))
for app in menu_category.applist: for app in menu_category.applist:
name = app.name.replace('&', '&amp;') name = app.name.decode().replace('&', '&amp;')
icon = app.icon icon = app.icon
command = app.command.replace("'", "'\\''").replace('&', '&amp;') command = app.command.replace("'", "'\\''").replace('&', '&amp;')
path = app.path path = app.path

Loading…
Cancel
Save