|
|
- #!/usr/bin/env python
-
- import subprocess
- import cPickle
- import os.path
- import os
- import sys
- import pygtk
- pygtk.require('2.0')
- import gtk
-
- defaults={}
- actions={}
-
- #decorator truff
- def action(validator,name=None):
- if name is None:
- def wrapper(action):
- actions[action.__name__]=(action,validator)
- else:
- def wrapper(action):
- actions[name]=(action,validator)
- return wrapper
-
- #validator helper
- def has_child_dir(dirname,recursion=0):
- def wrapper(path):
- k=recursion
- ii=""
- while k>=0:
- if os.path.isdir(os.path.join(path,ii,dirname)): return True
- k-=1
- ii=os.path.join("..",ii)
- return False
- return wrapper
-
-
- def has_child_file(filename):
- def wrapper(path):
- return os.path.isfile(os.path.join(path,filename))
- return wrapper
-
- #do the work
- def load_paths(filename="~/.autojump_py",maxpath=10):
- dic_file=os.path.expanduser(filename)
-
- try:
- aj_file=open(dic_file)
- path_dict=cPickle.load(aj_file)
- aj_file.close()
- except IOError:
- pass
-
- path_dict=path_dict.items()
- path_dict.sort(key=lambda x: x[1],reverse=True)
-
- return [path for path,score in path_dict[:maxpath]]
-
- def load_settings_file(filename="~/.jumpapplet_py"):
- print "loading settings"
- global defaults
- dic_file=os.path.expanduser(filename)
-
- try:
- aj_file=open(dic_file,'r')
- defaults=cPickle.load(aj_file)
- aj_file.close()
- except IOError:
- print "no config file"
- pass
-
- if not "terminal" in defaults: defaults["terminal"]="gnome-terminal"
- if not "navigator" in defaults: defaults["navigator"]="nautilus"
- if not "maxpath" in defaults: defaults["maxpath"]=15
- if not "invert" in defaults: defaults["invert"]=False
- if not "collapse" in defaults: defaults["collapse"]=True
-
- create_actions()
-
- def save_settings_file(filename="~/.jumpapplet_py"):
- print "saving settings"
- dic_file=os.path.expanduser(filename)
-
- aj_file=open(dic_file,'w')
- cPickle.dump(defaults,aj_file)
- aj_file.close()
-
-
- def get_actions(path):
- return [(name,action) for name,(action,validator) in actions.items() if validator(path)]
-
- def popup(sender,button,activation):
- paths=load_paths(maxpath=defaults["maxpath"])
-
- if defaults["collapse"]:
- def collapse_home(path):
- return path.replace(os.path.expanduser('~'),"~")
- else:
- def collapse_home(path):
- return path
-
-
- menu=gtk.Menu()
- if defaults["invert"]:
- item=gtk.MenuItem("quit")
- item.connect("activate",quit)
- menu.append(item)
- item=gtk.MenuItem("settings")
- item.connect("activate",settings)
- menu.append(item)
-
- menu.append(gtk.SeparatorMenuItem())
-
- for path in reversed(paths):
- actions=get_actions(path)
- if not actions: continue
-
- item=gtk.MenuItem(collapse_home(path),use_underline=False)
- submenu=gtk.Menu()
- item.set_submenu(submenu)
- for name,action in actions:
- subitem=gtk.MenuItem(name)
- subitem.connect("activate",action,path)
- submenu.append(subitem)
- menu.append(item)
- else:
- for path in paths:
- actions=get_actions(path)
- if not actions: continue
-
- item=gtk.MenuItem(collapse_home(path),use_underline=False)
- submenu=gtk.Menu()
- item.set_submenu(submenu)
- for name,action in actions:
- subitem=gtk.MenuItem(name)
- subitem.connect("activate",action,path)
- submenu.append(subitem)
- menu.append(item)
-
- menu.append(gtk.SeparatorMenuItem())
-
- item=gtk.MenuItem("settings")
- item.connect("activate",settings)
- menu.append(item)
- item=gtk.MenuItem("quit")
- item.connect("activate",quit)
- menu.append(item)
-
- menu.show_all()
- menu.popup(None,None,gtk.status_icon_position_menu,button,activation,sender)
-
- def settings(sender):
- window=gtk.Window(gtk.WINDOW_TOPLEVEL)
- window.set_title("jump applet settings")
- window.set_border_width(3)
- window.set_resizable(False)
-
- vbox=gtk.Table(6,2)
- vbox.set_row_spacings(3)
- window.add(vbox)
- def add_string_setting(name,label,nsettings):
- label=gtk.Label(label+' ')
- label.set_alignment(1.,.5)
- entry=gtk.Entry()
- if name in defaults: entry.set_text(defaults[name])
-
- vbox.attach(label,0,1,nsettings,nsettings+1)
- vbox.attach(entry,1,2,nsettings,nsettings+1)
- return (name,entry)
-
- def add_integer_setting(name,label,nsettings):
- label=gtk.Label(label+' ')
- label.set_alignment(1.,.5)
- entry=gtk.SpinButton()
- entry.set_range(5,35)
- entry.set_numeric(True)
- entry.set_increments(1,5)
- entry.set_snap_to_ticks(True)
- if name in defaults: entry.set_value(defaults[name])
-
- vbox.attach(label,0,1,nsettings,nsettings+1)
- vbox.attach(entry,1,2,nsettings,nsettings+1)
- return (name,entry)
-
- def add_bool_setting(name,label,nsettings):
- entry=gtk.CheckButton(label=label,use_underline=False)
- if name in defaults: entry.set_active(defaults[name])
-
- vbox.attach(entry,0,2,nsettings,nsettings+1)
- return (name,entry)
-
- entries=[]
- entries.append(add_string_setting("terminal","terminal program",0))
- entries.append(add_string_setting("navigator","navigator program",1))
- entries.append(add_integer_setting("maxpath","number of directories",2))
- entries.append(add_bool_setting("invert","list directories in reverse order",3))
- entries.append(add_bool_setting("collapse","collapse home directory to ~",4))
- button=gtk.Button("save")
- button.connect("clicked",save_settings,entries,window)
- vbox.attach(button,0,2,5,6)
-
- window.show_all();
-
- def save_settings(sender,entries,window):
- window.hide_all()
- global defaults
- for name,entry in entries:
- try:
- defaults[name]=int(entry.get_text())
- except (ValueError,AttributeError):
- try:
- defaults[name]=entry.get_active()
- except AttributeError:
- defaults[name]=entry.get_text()
-
- save_settings_file()
- create_actions()
-
- def init():
- load_settings_file()
- if os.path.isfile("icon.png"): icon=gtk.status_icon_new_from_file("icon.png")
- elif os.path.isfile("/usr/share/autojump/icon.png"): icon=gtk.status_icon_new_from_file("/usr/share/autojump/icon.png")
- else: icon=gtk.status_icon_new_from_icon_name("help")
- icon.set_visible(True)
- icon.connect("popup-menu",popup)
-
- def quit(sender):
- gtk.main_quit()
-
- ######################################################
- #insert other actions here using the action decorator#
- ######################################################
- def create_actions():
- global actions
- actions={}
-
- @action(has_child_dir(".git",recursion=3))
- def gitk(sender,path):
- if not os.fork():
- os.chdir(path)
- subprocess.Popen(['gitk']).wait()
- sys.exit()
-
- @action(has_child_file("CMakeCache.txt"),"configure")
- def cmake(sender,path):
- if not os.fork():
- os.chdir(path)
- subprocess.Popen(['cmake-gui','.']).wait()
- sys.exit()
-
- @action(os.path.isdir)
- def terminal(sender,path):
- print "launch terminal '%s'" % defaults["terminal"]
- if not os.fork():
- try:
- if defaults["terminal"]=="konsole":
- subprocess.Popen([defaults["terminal"],"--workdir=%s"%path]).wait()
- else:
- os.chdir(path)
- subprocess.Popen([defaults["terminal"]]).wait()
- except OSError:
- pass
- sys.exit()
-
- @action(os.path.isdir)
- def navigator(sender,path):
- print "launch navigator '%s'" % defaults["navigator"]
- if not os.fork():
- try:
- subprocess.Popen([defaults["navigator"],path]).wait()
- except OSError:
- pass
- sys.exit()
-
- if __name__=='__main__':
- init()
- gtk.main()
|