#1 Le 04/08/2012, à 08:39
- brunix
Notification utilisable dans vos script ou en ligne de commande
Je vous propose une petite procédure en python permettant d'afficher une zone de notification ( indépendante de la zone de notification des menus ou docks )
Cette zone possède de nombreuse options dont :
La possibilité d'ajouter jusqu'à quatre ligne de menu ( le menu apparaît lorsque vous cliquez sur la zone )
Chaque ligne de menu peut déclencher une action ( ou commande ).
Voir l'aide en ligne pour le reste des options.
Pour le tester ( Dans un terminal ) :
- Ouvrir un fichier : gedit ~/notifymenu.py
- Copier / coller le contenu du code ci-dessous et enregistrer le fichier.
- Rendre ce fichier exécutable : chmod 755 ~/notifymenu.py
- Afficher l'aide en ligne : ~/notifymenu.py --help
- L'éxécuter sans option en ligne de commande : ~/notifymenu.py
Note : Vous aurez probablement un message d'avertissement ( sans importance ) si vous n'avez pas renseigner un chemin et un nom d'icône à utiliser.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
####################################################################################
# Write by : brunix
####################################################################################
import gtk , pango
import os , sys , signal , time
from multiprocessing import Process , Queue
####################################################################################
# ----------------------------------------------------------------------------------
from optparse import OptionParser
parser = OptionParser()
parser.add_option( "--icon", dest="icon", default="", type="string", help="[ Path and file name icon ]")
parser.add_option( "--timeout", dest="timeout", default=10 , type="int", help="[ ( Seconds ) min. 5 , max. : 600 ] ( default : 10 )" )
parser.add_option( "--color", dest="color", default="grey", type="string", help="[ color : white,yellow,cyan,grey,blue,red,black ]")
parser.add_option( "--position", dest="position", type="string" , default="2" , help="[ Right rotation , start top right : 1 to 8 ]" )
parser.add_option( "--opacity", dest="opacity", type="string" , default="8" , help="[ 1 to 8 ]" )
parser.add_option( "--alerter", dest="alerter", action="store_true" , default=False , help="[ Display notification under mouse position ]" )
parser.add_option( "--above", dest="above", action="store_true" , default=False , help="[ keep notification above windows ]" )
parser.add_option( "--distance", dest="distance", default=20 , type="int", help="[ distance of edge of screen ]" )
parser.add_option( "--nodaemon", dest="nodaemon", action="store_true" , default=False , help="[ Do not daemonize ]" )
parser.add_option( "--title", dest="title", default="" , type="string", help="[ Title notification ( bold ) ]" )
parser.add_option( "--text", dest="text", default="" , type="string", help="[ Text notification ] ( Max. lines : 4 )" )
parser.add_option( "--menu1", dest="menu1", default="", type="string", help="[ First menu text for action1 ]")
parser.add_option( "--action1", dest="action1", default="6", type="string", help="[ Executable file ] ( default : Print stdout 6 )")
parser.add_option( "--menu2", dest="menu2", default="", type="string", help="[ Second menu text for action2 ]")
parser.add_option( "--action2", dest="action2", default="7", type="string", help="[ Executable file ] ( default : Print stdout 7 )")
parser.add_option( "--menu3", dest="menu3", default="", type="string", help="[ Third menu text for action3 ]")
parser.add_option( "--action3", dest="action3", default="8", type="string", help="[ Executable file ] ( default : Print stdout 8 )")
parser.add_option( "--menu4", dest="menu4", default="", type="string", help="[ Fourth menu text for action4 ]")
parser.add_option( "--action4", dest="action4", default="9", type="string", help="[ Executable file ] ( default : Print stdout 9 )")
(options, args) = parser.parse_args()
opacity = "0." + str( options.opacity )
options.opacity = float( opacity )
textcolor = "black"
if options.color == "green" :
options.color == "#002B3B"
elif options.color == "white" :
options.color == "#EFECCA"
elif options.color == "cyan" :
options.color == "#006D80"
elif options.color == "grey" :
options.color == "#1F2A36"
elif options.color == "blue" :
options.color == "#046380"
elif options.color == "red" :
options.color == "#B80404"
elif options.color == "yellow" :
options.color == "#FFF168"
elif options.color == "black" :
options.color == "#D8DADA"
textcolor = "white"
else :
options.color = "cyan"
color = gtk.gdk.color_parse( options.color )
if options.timeout > 600 :
options.timeout = 600
if options.timeout < 5 :
options.timeout = 5
# ----------------------------------------------------------------------------------
options.title = options.title.replace( "\\n" , "\n" );
options.text = options.text.replace( "\\n" , "\n" );
####################################################################################
# ----------------------------------------------------------------------------------
class notifalert:
def __init__(self):
# -----------------------------------------------------------
# Gtk menu
# ---------
winweight = 210; winhight = 90
# -----------------------------------------------------------
# Gtk menu
# ---------
self.menu = gtk.Menu()
# -----
# Create elements of menu
# -----
if options.menu1 != "" :
self.menu_item1 = gtk.MenuItem( options.menu1 )
self.menu_item1.connect( "activate", self.on_launch, options.action1 )
self.menu.append(self.menu_item1)
self.menu_item1.show()
if options.menu2 != "" :
self.menu_item2 = gtk.MenuItem( options.menu2 )
self.menu_item2.connect( "activate", self.on_launch, options.action2 )
self.menu.append(self.menu_item2)
self.menu_item2.show()
if options.menu3 != "" :
self.menu_item3 = gtk.MenuItem( options.menu3 )
self.menu_item3.connect( "activate", self.on_launch, options.action3 )
self.menu.append(self.menu_item3)
self.menu_item3.show()
if options.menu4 != "" :
self.menu_item4 = gtk.MenuItem( options.menu4 )
self.menu_item4.connect( "activate", self.on_launch, options.action4 )
self.menu.append(self.menu_item4)
self.menu_item4.show()
textmenu = ""
if options.menu1 + options.menu2 + options.menu3 + options.menu4 != "" :
textmenu = " MENU "
# -----------------------------------------------------------
# Quit definition elements
# ------------------------
self.bquit = gtk.ToolButton( gtk.STOCK_YES )
self.bquit.connect("clicked", self.on_launch , "5" )
self.bquit.show()
self.quittext = gtk.Label()
markup = "<span foreground='" + textcolor + "'><i>Validation</i></span>"
self.quittext.set_markup(markup)
self.quittext.show()
self.textmenu = gtk.Label()
markup = "<span background='#CC0000' foreground='#FFFFFF' ><i><b>" + textmenu + "</b></i></span>"
self.textmenu.set_markup(markup)
self.textmenu.show()
self.quithbox = gtk.HBox( True , 3 )
self.quithbox.show()
self.quithbox.add( self.quittext )
self.quithbox.add( self.bquit )
self.quithbox.add( self.textmenu )
# -----------------------------------------------------------
# Icon
# ----
self.image = gtk.Image()
if options.icon == "" :
self.image.set_from_stock( gtk.STOCK_INFO , 5 )
else :
self.image.set_from_file( options.icon )
self.image.show()
self.imageframe = gtk.Frame()
self.imageframe.set_shadow_type( gtk.SHADOW_NONE )
self.imageframe.add( self.image )
self.imageframe.show()
# -----------------------------------------------------------
# Labels
# ------
self.iconhbox = gtk.HPaned()
self.iconhbox.add1( self.imageframe )
if options.title + options.text != "" :
winweight = 360
winhight = 120
self.text = gtk.Label()
self.text.set_justify( gtk.JUSTIFY_CENTER )
markup = "<span foreground='" + textcolor + "'><i>";
if options.title != "" :
markup += "<b>" + options.title + " " + "</b>\n"
markup += options.text
markup += "</i></span>"
self.text.set_markup( markup )
self.text.show()
self.iconhbox.add2( self.text )
# -----------------------------------------------------------
# Groups elements
# ---------------
self.iconhbox.show()
self.itemsvbox = gtk.VBox( False , 2 )
self.itemsvbox.add( self.quithbox )
self.itemsvbox.add( self.iconhbox )
self.itemsvbox.show()
# -----------------------------------------------------------
# Event box
# ---------
self.event_box = gtk.EventBox()
self.event_box.set_events( gtk.gdk.EXPOSE )
self.event_box.connect_object( "event" , self.button_press , self.menu )
self.event_box.show()
self.event_box.add( self.itemsvbox )
# -----------------------------------------------------------
# Master frame
# ------------
self.frame = gtk.AspectFrame()
self.frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
self.frame.show()
self.frame.add( self.event_box )
# -----------------------------------------------------------
# Color objects
# -------------
self.event_box.modify_bg( gtk.STATE_NORMAL , color )
self.frame.modify_bg( gtk.STATE_NORMAL , color )
# -----------------------------------------------------------
# Window
# ------
self.window = gtk.Window()
self.window.set_focus_on_map( False )
self.window.add( self.frame )
self.window.set_keep_above( options.above )
self.window.set_skip_taskbar_hint( True )
self.window.set_decorated( False )
self.window.set_opacity( options.opacity )
self.event_box.set_size_request( winweight , winhight )
self.window.set_size_request( winweight , winhight + 15 )
if options.alerter :
self.window.set_position( gtk.WIN_POS_MOUSE )
else :
self.window.set_position( gtk.WIN_POS_NONE )
width, height = self.window.get_size()
w = 0; h = 0; sw = 0; sh = 0; space = options.distance
if options.position == "1" :
sh = space; sw = -space; w = gtk.gdk.screen_width() - width
elif options.position == "2" :
sw = -space; w = gtk.gdk.screen_width() - width; h = ( gtk.gdk.screen_height() - height ) / 2
elif options.position == "3" :
sw = -space; sh = -space; w = gtk.gdk.screen_width() - width; h = gtk.gdk.screen_height() - height
elif options.position == "4" :
sh = -space; w = ( gtk.gdk.screen_width() - width ) / 2; h = gtk.gdk.screen_height() - height
elif options.position == "5" :
sh = -space; sw = space; h = gtk.gdk.screen_height() - height
elif options.position == "6" :
sw = space; h = ( gtk.gdk.screen_height() - height ) / 2
elif options.position == "7" :
sw = space; sh = space;
elif options.position == "8" :
sh = space; w = ( gtk.gdk.screen_width() - width ) / 2
else :
print "Invalid position definition"
sys.exit( 1 )
self.window.move( w + ( sw ) , h + ( sh ) )
self.window.show()
# -----------------------------------------------------------
# -----------------------------------------------------------
# Controls events on press mouse buttons
# --------------------------------------
def button_press(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS:
widget.popup( None , None , None , event.button , event.time )
return True # -- Handle do stop here
return False # -- No handle do bypass
# -------
# On action kill parent process ( timer )
# -------
def on_launch( self , widget , data ) :
self.window.destroy()
if data != "5" and data != "6" and data != "7" and data != "8" and data != "9" :
os.system(data); data = "0";
q.put( data )
gtk.main_quit()
# ===================================================================
def displayer( q ) :
notifalert()
gtk.main()
sys.exit(0)
# --------------------------------------------------------------------------------
def fcontroler( q , p ) :
rc = 5
while options.timeout > 0 :
time.sleep( 1 )
options.timeout = options.timeout - 1
if not q.empty() :
rc = q.get()
if rc == "5" :
p.terminate()
else :
break
q.put( rc )
p.terminate()
# ===================================================================
# --------------------------------------------------------------------------------
# Main
# ----
if __name__ == "__main__":
if not options.nodaemon : # Fork process
pid = os.fork()
if pid == 0 :
p = 0
else:
sys.exit(0)
# ===================================================================
q = Queue()
pdisplayer = Process( target= displayer , args=( q , ) )
pdisplayer.start()
pfcontroler = Process( target= fcontroler , args=( q , pdisplayer ) )
pfcontroler.start()
pfcontroler.join()
i = q.get()
if i != 5 :
pfcontroler.terminate()
print i
sys.exit( 0 )
# --------------------------------------------------------------------------------
Hors ligne