URI:
       # Fluxlaunch
       
       Fluxlaunch est un lanceur d'applications qui apparaît dans la zone de notification (systray).
       
       ```
       #!/usr/bin/env python3
       # -*- coding:Utf-8 -*- 
       
       
       """
       Auteur :      prx <prx@si3t.ch>  
       licence :     GPLv2
       
       Description : Met dans le systray des lanceurs d'application
       
       Code inspiré de unapplet : 
       http://download.tuxfamily.org/unapplet/
       Merci à Michael Lange <klappnase@tuxfamily.org>
       
       Dépendances : python3-pil python3-tk python3-pil.imagetk tk-tktray
       """
       
       
       import os
       from subprocess import Popen
       import tkinter
       from PIL import Image, ImageTk
       
       
       default_config="""#/path/to/icon command
       /usr/local/share/icons/Adwaita/16x16/categories/applications-internet.png,firefox
       /usr/local/share/icons/Adwaita/16x16/categories/applications-other.png,thunar
       """
       
       configfile = os.path.expanduser("~/.fluxlaunch.conf")
       
       
       def which(program):
           #https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python/377028#377028
           def is_exe(fpath):
               return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
       
           fpath, fname = os.path.split(program)
           if fpath:
               if is_exe(program):
                   return program
           else:
               for path in os.environ["PATH"].split(os.pathsep):
                   path = path.strip('"')
                   exe_file = os.path.join(path, program)
                   if is_exe(exe_file):
                       return exe_file
       
           return False
       
       
       def edit_config(cf):
           for editor in ["geany","gedit","scite","kate", "mousepad", "leafpad"]:
               EDITOR = which(editor)
               if EDITOR:
                   Popen([EDITOR, cf])
                   break
       
       
       
       
       
       def save_default():
           with open(configfile, "w") as default:
               default.write(default_config)
       
       def load_config():
           if not os.path.isfile(configfile):
               save_default()
           with open(configfile, "r") as config:
               c = config.readlines()
       
           conf = []
           for l in c:
               l = l.strip()
               if not l.startswith('#') and len(l) > 0:
                   a,b = l.split(',')
                   conf.append([a.strip(), b.strip()])
       
           return(conf)
       
       
       class Icon(tkinter.BaseWidget, tkinter.Wm):
           def __init__(self, master=None, cmd = None, cnf={}, **kw):
       
               if not master:
                   if tkinter._support_default_root:
                       if not tkinter._default_root:
                           tkinter._default_root = tkinter.Tk()
                       master = tkinter._default_root
               self.TktrayVersion = master.tk.call('package', 'require', 'tktray')
       
               # stolen from tkinter.Toplevel
               if kw:
                   cnf = tkinter._cnfmerge((cnf, kw))
               extra = ()
               for wmkey in ['screen', 'class_', 'class', 'visible', 'colormap']:
                   if wmkey in cnf.keys():
                       val = cnf[wmkey]
                       # TBD: a hack needed because some keys
                       # are not valid as keyword arguments
                       if wmkey[-1] == '_': opt = '-'+wmkey[:-1]
                       else: opt = '-'+wmkey
                       extra = extra + (opt, val)
                       del cnf[wmkey]
               tkinter.BaseWidget.__init__(self, master, 'tktray::icon', cnf, {}, extra)
               self.protocol("WM_DELETE_WINDOW", self.destroy)
       
               if cmd:
                   self.bind("<ButtonPress-1>", lambda x: Popen(cmd))
       
       
       
       class TrayApp():
           def __init__(self, conf):
               """
               conf : list of i
               i = [path/to/image cmd]
               """
       
               self.conf = conf
       
               self.root = tkinter.Tk()
               self.root.withdraw()
       
               self.menu = tkinter.Menu(self.root, tearoff=0)
               self.menu.add_command(label="Configurer", command=self.configure)
               self.menu.add_command(label="Quitter", command=self.root.destroy)
       
               for i in self.conf:
                   if not os.path.isfile(i[0]):
                       print("Can't find {}".format(i[0]))
                   else:
                       b = tkinter.Label(self.root)
                       img = Image.open(i[0])
                       b.img = ImageTk.PhotoImage(img)
                       icon = Icon(image=b.img, cmd=i[1])
                       icon.bind("<Button-3>", self.popup)
       
               self.root.mainloop()
       
           def popup(self,event):
               self.menu.post(event.x_root, event.y_root)
       
           def configure(self):
               edit_config(configfile)
       
       
       if __name__ == '__main__':
           print("Running fluxlaunch")
           print("edit {} to change configuration".format(configfile))
           conf = load_config()
       
           TrayApp(conf)
       ```
       
       Pour utiliser le script, enregistrez-le puis exécutez-le avec python3 :
       
       ```
       python3 fluxlaunch.py
       Running fluxlaunch
       edit /home/xavier/.fluxlaunch.conf to change configuration
       ```
       
       Il est nécessaire d'avoir les dépendances :
       
       ```
       python3-pil python3-tk python3-pil.imagetk tk-tktray
       ```
       
       Vous verrez apparaître quelques icônes dans le systray. Si ce n'est pas le cas, vous pouvez éditez le fichier ''~/.fluxlaunch.conf'' qui ressemble à ça :
       
       ```
       # /path/to/icon command
       /usr/share/icons/Adwaita/16x16/categories/applications-internet.png, firefox
       /usr/share/icons/Adwaita/16x16/categories/applications-other.png, thunar
       ```
       
       Très facile à comprendre, une icône par ligne suivie par la commande à lancer, les deux séparées d'une virgule.
       
       Au final, vous n'avez plus qu'à cliquer sur une des petites icônes du tray pour lancer la commande voulue.