This script has few features:
- Resides in system tray
- Clipboard history and reverting (last 10 entries)
- URL select -- download and run (this is a security hole)
- Your own launch scripts
Config example:
- submenu:Tablet
- Set buttons:/home/mic/.config/mictray/set_wacom.sh
- Update screen:/home/mic/.config/mictray/update_wacom_to_screen.sh
- endsubmenu
- Setup display:gnome-display-properties
- Chromium:chromium-browser
Source code:
- #!/usr/bin/python
- # This program is under GPLv3 license --
- # http://www.gnu.org/licenses/gpl-3.0.html
- #
- # If you think, that this script is usefull, please send me a postcard to
- # adress:
- # Michal Nanasi
- # Azalkova 1
- # 82101 Bratislava
- # Slovakia
- import gtk
- import tempfile
- import os
- import re
- import sys
- from threading import Thread
- class DownloadAndExecuteURL(Thread):
- def __init__(self,text):
- Thread.__init__(self)
- self.text=text
- def run(self):
- text=self.text
- name=tempfile.NamedTemporaryFile().name
- text=text.replace('&','%26')
- print("/usr/bin/wget --output-document="+name+" "+text)
- os.system("/usr/bin/wget --output-document="+name+" "+text+"; /usr/bin/xdg-open "+name)
- class URLMenu:
- def changeURL(self,url,index=0):
- if len(self.urls)>0:
- self.urls.pop(index);
- self.addURL(url);
- def addURL(self,url):
- self.urls.insert(0,url)
- if len(self.urls)>self.maxSize:
- self.urls.pop()
- self.changed=True
- cld=self.menu.get_children()
- for child in cld:
- self.menu.remove(child)
- for url in self.urls:
- item = gtk.MenuItem
- menuItem=gtk.MenuItem(url)
- self.menu.append(menuItem)
- menuItem.connect("activate", self.menuItemResponse,url)
- menuItem.show_all()
- self.menu.show_all()
- def getTop(self):
- if len(self.urls)==0:
- return None
- return self.urls[0]
- def menuItemResponse(self,widget,url):
- thread = DownloadAndExecuteURL(url)
- thread.start()
- def getMenu(self):
- return self.menu
- def __init__(self,maxSize=10):
- self.urls=list()
- self.menu=gtk.Menu()
- self.changed=True
- self.maxSize=maxSize
- class ClipboardMenu:
- def on_clipboard_owner_change(self, clipboard, event):
- item = self.clipboard.wait_for_text()
- if item != None:
- self.addText(item)
- self.clipboard_text = item
- elif self.clipboard_text != None:
- self.clipboard.set_text(self.clipboard_text)
- def derived(self,text1,text2):
- if text1 == None or text2 == None:
- return False
- if text1.count(text2)+text2.count(text1)>0:
- return True
- return False
- def addText(self,text):
- if self.urlMenu:
- if re.match("^https?://.*",text) or re.match("^s?ftp://.*",text):
- if self.derived(self.urlMenu.getTop(),text):
- self.urlMenu.changeURL(text,0)
- else:
- self.urlMenu.addURL(text)
- if self.derived(self.clipboard_text,text):
- self.boards[0]=text
- else:
- self.boards.insert(0,text);
- if len(self.boards)>self.maxSize:
- self.boards.pop();
- cld=self.menu.get_children()
- fir=2;
- for child in cld:
- if fir!=0:
- fir=fir-1
- else:
- self.menu.remove(child)
- for clip in self.boards:
- item = gtk.MenuItem
- cp = clip.replace("\n","")
- if len(cp)>20:
- cp = cp[0:19]+"..."
- menuItem=gtk.MenuItem(cp)
- self.menu.append(menuItem)
- menuItem.connect("activate", self.menuItemResponse,clip)
- menuItem.show_all()
- self.menu.show_all()
- def menuItemResponse(self,widget,clip):
- for text in self.boards:
- if text == clip:
- self.boards.remove(text)
- self.clipboard.set_text(clip)
- def getMenu(self):
- return self.menu
- def __init__(self,maxSize=10):
- self.menu=gtk.Menu()
- self.urlMenu = URLMenu()
- menuitem = gtk.MenuItem("URL")
- self.menu.append(menuitem)
- menuitem.set_submenu(self.urlMenu.getMenu())
- self.menu.append(gtk.SeparatorMenuItem())
- self.menu.show_all()
- self.boards=list()
- self.maxSize=maxSize
- self.clipboard = gtk.clipboard_get("PRIMARY")
- self.clipboard_text = self.clipboard.wait_for_text()
- self.clipboard.connect('owner-change', self.on_clipboard_owner_change)
- class ScriptMenu:
- def getMenu(self):
- return self.menu
- def menuItemResponse(self,widget,script):
- os.system(script+" & ");
- def __init__(self,config):
- self.menu=gtk.Menu()
- stack = list();
- stack.append(self.menu)
- f = open(config,"r")
- file = f.readlines()
- for line in file:
- m = stack[len(stack)-1]
- if re.match("^[ \t]*submenu:.*",line):
- #nove submenu
- (lol,sep,item) = line.partition(":")
- item=item.strip()
- menuitem = gtk.MenuItem(item)
- m.append(menuitem);
- m=gtk.Menu();
- menuitem.set_submenu(m)
- stack.append(m)
- elif re.match("^[\t]*endsubmenu[ \t]*",line):
- m.show_all();
- stack.pop();
- else:
- (item,sep,script) = line.partition(":")
- item=item.strip()
- script=script.strip()
- menuitem=gtk.MenuItem(item)
- m.append(menuitem)
- menuitem.connect("activate",self.menuItemResponse,script);
- menuitem.show_all();
- if len(stack)!=1:
- raise Exception('ERROR IN CONFUGURE FILE')
- self.menu.show_all();
- class ActionMenu:
- def getMenu(self):
- return self.menu
- def __init__(self):
- self.scriptmenu=ScriptMenu(os.getenv("HOME")+"/.config/mictray/scriptmenu.cfg")
- self.menu=self.scriptmenu.getMenu()
- self.menu.prepend(gtk.SeparatorMenuItem())
- self.ClMenu=ClipboardMenu()
- clmenuItem = gtk.MenuItem("Clipboard")
- self.menu.prepend(clmenuItem)
- clmenuItem.set_submenu(self.ClMenu.getMenu())
- self.menu.show_all()
- class StatusIcc:
- # activate callback
- def activate( self, widget, data=None):
- self.actionMenu.getMenu().popup(None, None, gtk.status_icon_position_menu, 0,0, widget)
- def show_hide(self, widget,response_id, data= None):
- if response_id == gtk.RESPONSE_YES:
- widget.hide()
- else:
- widget.hide()
- # destroyer callback
- def destroyer(self, widget,response_id, data= None):
- if response_id == gtk.RESPONSE_OK:
- gtk.main_quit()
- else:
- widget.hide()
- # popup callback
- def popup(self, button, widget, data=None):
- dialog = gtk.MessageDialog(
- parent = None,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT,
- type = gtk.MESSAGE_INFO,
- buttons = gtk.BUTTONS_OK_CANCEL,
- message_format = "Do you want to close this Status Icon program?")
- dialog.set_title("Popup Window")
- dialog.connect("response", self.destroyer)
- dialog.show()
- def __init__(self):
- # create a new Status Icon
- self.staticon = gtk.StatusIcon()
- self.staticon.set_from_stock(gtk.STOCK_ABOUT)
- self.staticon.set_blinking(False)
- self.actionMenu=ActionMenu();
- self.staticon.connect("activate", self.activate)
- self.staticon.connect("popup_menu", self.popup)
- self.staticon.set_visible(True)
- # invoking the main()
- gtk.main()
- if __name__ == "__main__":
- statusicon = StatusIcc()
