[SoaS] sugar coating

tom-ipp develop at tom-ipp.info
Tue Jul 27 15:11:24 EDT 2010


Hi,
I wrote a small script in python which lets me "sugarcoat" linux
application for sugar.
In fact, you call the script with the name of an installed program (need
the .desktop file) and it returns an activity directory -> an icon
appears in the home view to launch that program.
The -l option will return you the programs installed
in /usr/share/applications
It looks for an svg icon, if not found the icon of the journal activity
is used.
It is based around the famous library libsugarize.so and the script
found here :
http://wiki.sugarlabs.org/go/Running_Linux_Applications_Under_Sugar
Tested with fedora 13, for the application cheese, fedora-abe and
fedora-supertux.
You put the script simpleSugarCoater.py in your home directory, with the
libsugarize.so.

Morally, the sugar coating is not the best thing to promote the sugar
platform. BUT we can't wait for the supertux developer to sugarize their
application and we all need supertux. So...
Comments welcomed.
Sincerely.
Thomas

The script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# build activity directory for launching linux application from sugar
# GNU General Public License v.3
# Author : Thomas Jacoviac
# Contact : develop at tom-ipp.info
#

import os
import shutil
import sys
import getopt
import xdg.DesktopEntry
import xdg.IconTheme
import xdg.BaseDirectory
import mimetypes

# == Declarations ==
activityPath = os.path.join(os.path.expanduser("~"), "Activities") #By
default, the directory will be created in the user's Activities
directory
defaultIcon =
"/usr/share/icons/sugar/scalable/apps/activity-journal.svg" # By
default, this icon will be used for the application

# == Internal functions ==
def sugarCoat(binary):
    global activityPath
    global defaultIcon
    
    iconName, execString = parseDesktopFile(binary) #Retrieve icon and
exec from desktop file
    iconPath = locateIcon(iconName)    
    createActivityDir(os.path.join(activityPath, binary + ".activity"))
# Create activity directory tree
    createInfoFile(activityPath, binary) # Create info file
    shutil.copy(iconPath, os.path.join(activityPath, binary +
".activity", "activity", "icon.svg")) # Copy icon to activity directory
    if createLauncherFile(activityPath, binary, execString):
sys.exit("Error with launcher creation") #Create launcher
    # Copy libsugarize.so in activity directory
    #TODO: More versatile location for distributing libsugarize.so
    shutil.copy("libsugarize.so", os.path.join(activityPath, binary +
".activity", "lib", "libsugarize.so"))

def parseDesktopFile(binary):
    dirs = xdg.BaseDirectory.xdg_data_dirs
    for dir in dirs:
        if os.path.isfile(os.path.join(dir + "/applications/" + binary +
".desktop")):
            desktopFileContent = xdg.DesktopEntry.DesktopEntry(filename
= os.path.join(dir + "/applications/" + binary + ".desktop"))
            execString = desktopFileContent.getExec()
            iconName = desktopFileContent.getIcon()
            return iconName, execString
    sys.exit("No .desktop file for this application")
    
def locateIcon(iconName):
    global defaultIcon
    iconPath = xdg.IconTheme.getIconPath(iconName, None, None, ["svg"])
#Get iconPath with xdg
    #TODO: Use xdg to magically find type, mimetypes is based on
filename suffix
    if mimetypes.guess_type(iconPath)[0] != "image/svg+xml": # Check if
icon is svg file
        #From
http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
        #apps should look in $HOME/.icons, /usr/share/icons
and /usr/share/pixmaps (in that order)
        dirs = [os.path.expanduser("~/.icons"), "/usr/share/icons",
"/usr/share/pixmaps"]
        for dir in dirs:
            for root, ds, files in os.walk(dir):
                for file in files:
                    if mimetypes.guess_type(file)[0] == "image/svg+xml":
                        if os.path.splitext(file)[0] == iconName:
                            iconPath = os.path.join(root, file)
                            return iconPath
        return defaultIcon # If no svg icon found, use default icon
    
def createLauncherFile(activityPath, binary, execString):
    launcherFile = open(os.path.join(activityPath, binary + ".activity",
"bin", "launcher.sh"), "w")
    launcherFile.write("#!/bin/sh\n")
    launcherFile.write("# from
http://wiki.sugarlabs.org/go/Running_Linux_Applications_Under_Sugar\n")
    launcherFile.write("\n")
    launcherFile.write("while [ -n \"$2\" ] ; do\n")
    launcherFile.write("    case \"$1\" in\n")
    launcherFile.write("        -b | --bundle-id)     export
SUGAR_BUNDLE_ID=\"$2\" ;;\n")
    launcherFile.write("        -a | --activity-id)   export
SUGAR_ACTIVITY_ID=\"$2\" ;;\n")
    launcherFile.write("        -o | --object-id)     export
SUGAR_OBJECT_ID=\"$2\" ;;\n")
    launcherFile.write("        -u | --uri)           export SUGAR_URI=
\"$2\" ;;\n")
    launcherFile.write("        *) echo unknown argument $1 $2  ;;\n")
    launcherFile.write("    esac\n")
    launcherFile.write("    shift;shift\n")
    launcherFile.write("done\n")
    launcherFile.write("export LD_PRELOAD=
\"$SUGAR_BUNDLE_PATH/lib/libsugarize.so\"\n")
    launcherFile.write("export NET_WM_NAME=\"" + binary + "\"\n")
    launcherFile.write("exec " + execString + "\n")
    launcherFile.close
    launcherFile.flush() #For xo creation we need to ensure that file is
written on disk
    os.fsync(launcherFile.fileno()) #idem
    os.chmod(os.path.join(activityPath, binary + ".activity", "bin",
"launcher.sh"), 0755)
   
def createActivityDir(directory):
    if not os.path.isdir(directory) : os.makedirs(directory)
    if not os.path.isdir(os.path.join(directory, "activity")):
os.mkdir(os.path.join(directory, "activity"))
    if not os.path.isdir(os.path.join(directory, "bin")):
os.mkdir(os.path.join(directory, "bin"))
    if not os.path.isdir(os.path.join(directory, "lib")):
os.mkdir(os.path.join(directory, "lib"))
    return

def createInfoFile(activityPath, appName):
    infoFile = open(os.path.join(activityPath, appName + ".activity",
"activity", "activity.info"), "w")
    infoFile.write("[Activity]\n")
    infoFile.write("name = " + appName + "\n")
    infoFile.write("activity_version = 1\n")
    infoFile.write("service_name = info.tom-ipp.sugar." + appName +
"\n")
    infoFile.write("license = GPLv3\n")
    infoFile.write("icon = icon\n")
    infoFile.write("exec = launcher.sh\n")
    infoFile.write("show_launcher = yes\n")
    infoFile.close()
    return

# == Man page for the script ==
def usage():
    print "----------------- Usage
----------------------------------------"
    print "sugarCoater.py create an activity directory, including
launcher,"
    print "for a standard linux application"
    print "Usage: sugarCoater [options] application"
    print "-h --help          Prints this"
    print "-l --list          Lists applications installed"
    
# == Main function ==
def main(argv):
    try:                                
        opts, command = getopt.getopt(argv, "hl", ["help", "list"])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
        
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            sys.exit()
        if opt in ("-l", "--list"):
            listApps = []
            for app in sorted(os.listdir("/usr/share/applications/")): 
                if os.path.splitext(app)[1] == ".desktop":
                    listApps.append(os.path.splitext(app)[0])
                    print os.path.splitext(app)[0]
            sys.exit()
            
    if not command:
        print "You need to provide the application you want to
sugarcoat."
        print "Use -l or --list option to look in your's
$XDG_DATA_DIRS :"
        print xdg.BaseDirectory.xdg_data_dirs
        sys.exit(2)
    
    sugarCoat(command[0])

if __name__ == "__main__":
    main(sys.argv[1:])



More information about the SoaS mailing list