Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

277 lignes
8.1 KiB

il y a 15 ans
  1. #!/usr/bin/env python
  2. import subprocess
  3. import cPickle
  4. import os.path
  5. import os
  6. import sys
  7. import pygtk
  8. pygtk.require('2.0')
  9. import gtk
  10. defaults={}
  11. actions={}
  12. #decorator truff
  13. def action(validator,name=None):
  14. if name is None:
  15. def wrapper(action):
  16. actions[action.__name__]=(action,validator)
  17. else:
  18. def wrapper(action):
  19. actions[name]=(action,validator)
  20. return wrapper
  21. #validator helper
  22. def has_child_dir(dirname,recursion=0):
  23. def wrapper(path):
  24. k=recursion
  25. ii=""
  26. while k>=0:
  27. if os.path.isdir(os.path.join(path,ii,dirname)): return True
  28. k-=1
  29. ii=os.path.join("..",ii)
  30. return False
  31. return wrapper
  32. def has_child_file(filename):
  33. def wrapper(path):
  34. return os.path.isfile(os.path.join(path,filename))
  35. return wrapper
  36. #do the work
  37. def load_paths(filename="~/.autojump_py",maxpath=10):
  38. dic_file=os.path.expanduser(filename)
  39. try:
  40. aj_file=open(dic_file)
  41. path_dict=cPickle.load(aj_file)
  42. aj_file.close()
  43. except IOError:
  44. pass
  45. path_dict=path_dict.items()
  46. path_dict.sort(key=lambda x: x[1],reverse=True)
  47. return [path for path,score in path_dict[:maxpath]]
  48. def load_settings_file(filename="~/.jumpapplet_py"):
  49. print "loading settings"
  50. global defaults
  51. dic_file=os.path.expanduser(filename)
  52. try:
  53. aj_file=open(dic_file,'r')
  54. defaults=cPickle.load(aj_file)
  55. aj_file.close()
  56. except IOError:
  57. print "no config file"
  58. pass
  59. if not "terminal" in defaults: defaults["terminal"]="gnome-terminal"
  60. if not "navigator" in defaults: defaults["navigator"]="nautilus"
  61. if not "maxpath" in defaults: defaults["maxpath"]=15
  62. if not "invert" in defaults: defaults["invert"]=False
  63. if not "collapse" in defaults: defaults["collapse"]=True
  64. create_actions()
  65. def save_settings_file(filename="~/.jumpapplet_py"):
  66. print "saving settings"
  67. dic_file=os.path.expanduser(filename)
  68. aj_file=open(dic_file,'w')
  69. cPickle.dump(defaults,aj_file)
  70. aj_file.close()
  71. def get_actions(path):
  72. return [(name,action) for name,(action,validator) in actions.items() if validator(path)]
  73. def popup(sender,button,activation):
  74. paths=load_paths(maxpath=defaults["maxpath"])
  75. if defaults["collapse"]:
  76. def collapse_home(path):
  77. return path.replace(os.path.expanduser('~'),"~")
  78. else:
  79. def collapse_home(path):
  80. return path
  81. menu=gtk.Menu()
  82. if defaults["invert"]:
  83. item=gtk.MenuItem("quit")
  84. item.connect("activate",quit)
  85. menu.append(item)
  86. item=gtk.MenuItem("settings")
  87. item.connect("activate",settings)
  88. menu.append(item)
  89. menu.append(gtk.SeparatorMenuItem())
  90. for path in reversed(paths):
  91. actions=get_actions(path)
  92. if not actions: continue
  93. item=gtk.MenuItem(collapse_home(path),use_underline=False)
  94. submenu=gtk.Menu()
  95. item.set_submenu(submenu)
  96. for name,action in actions:
  97. subitem=gtk.MenuItem(name)
  98. subitem.connect("activate",action,path)
  99. submenu.append(subitem)
  100. menu.append(item)
  101. else:
  102. for path in paths:
  103. actions=get_actions(path)
  104. if not actions: continue
  105. item=gtk.MenuItem(collapse_home(path),use_underline=False)
  106. submenu=gtk.Menu()
  107. item.set_submenu(submenu)
  108. for name,action in actions:
  109. subitem=gtk.MenuItem(name)
  110. subitem.connect("activate",action,path)
  111. submenu.append(subitem)
  112. menu.append(item)
  113. menu.append(gtk.SeparatorMenuItem())
  114. item=gtk.MenuItem("settings")
  115. item.connect("activate",settings)
  116. menu.append(item)
  117. item=gtk.MenuItem("quit")
  118. item.connect("activate",quit)
  119. menu.append(item)
  120. menu.show_all()
  121. menu.popup(None,None,gtk.status_icon_position_menu,button,activation,sender)
  122. def settings(sender):
  123. window=gtk.Window(gtk.WINDOW_TOPLEVEL)
  124. window.set_title("jump applet settings")
  125. window.set_border_width(3)
  126. window.set_resizable(False)
  127. vbox=gtk.Table(6,2)
  128. vbox.set_row_spacings(3)
  129. window.add(vbox)
  130. def add_string_setting(name,label,nsettings):
  131. label=gtk.Label(label+' ')
  132. label.set_alignment(1.,.5)
  133. entry=gtk.Entry()
  134. if name in defaults: entry.set_text(defaults[name])
  135. vbox.attach(label,0,1,nsettings,nsettings+1)
  136. vbox.attach(entry,1,2,nsettings,nsettings+1)
  137. return (name,entry)
  138. def add_integer_setting(name,label,nsettings):
  139. label=gtk.Label(label+' ')
  140. label.set_alignment(1.,.5)
  141. entry=gtk.SpinButton()
  142. entry.set_range(5,35)
  143. entry.set_numeric(True)
  144. entry.set_increments(1,5)
  145. entry.set_snap_to_ticks(True)
  146. if name in defaults: entry.set_value(defaults[name])
  147. vbox.attach(label,0,1,nsettings,nsettings+1)
  148. vbox.attach(entry,1,2,nsettings,nsettings+1)
  149. return (name,entry)
  150. def add_bool_setting(name,label,nsettings):
  151. entry=gtk.CheckButton(label=label,use_underline=False)
  152. if name in defaults: entry.set_active(defaults[name])
  153. vbox.attach(entry,0,2,nsettings,nsettings+1)
  154. return (name,entry)
  155. entries=[]
  156. entries.append(add_string_setting("terminal","terminal program",0))
  157. entries.append(add_string_setting("navigator","navigator program",1))
  158. entries.append(add_integer_setting("maxpath","number of directories",2))
  159. entries.append(add_bool_setting("invert","list directories in reverse order",3))
  160. entries.append(add_bool_setting("collapse","collapse home directory to ~",4))
  161. button=gtk.Button("save")
  162. button.connect("clicked",save_settings,entries,window)
  163. vbox.attach(button,0,2,5,6)
  164. window.show_all();
  165. def save_settings(sender,entries,window):
  166. window.hide_all()
  167. global defaults
  168. for name,entry in entries:
  169. try:
  170. defaults[name]=int(entry.get_text())
  171. except (ValueError,AttributeError):
  172. try:
  173. defaults[name]=entry.get_active()
  174. except AttributeError:
  175. defaults[name]=entry.get_text()
  176. save_settings_file()
  177. create_actions()
  178. def init():
  179. load_settings_file()
  180. if os.path.isfile("icon.png"): icon=gtk.status_icon_new_from_file("icon.png")
  181. elif os.path.isfile("/usr/share/autojump/icon.png"): icon=gtk.status_icon_new_from_file("/usr/share/autojump/icon.png")
  182. else: icon=gtk.status_icon_new_from_icon_name("help")
  183. icon.set_visible(True)
  184. icon.connect("popup-menu",popup)
  185. def quit(sender):
  186. gtk.main_quit()
  187. ######################################################
  188. #insert other actions here using the action decorator#
  189. ######################################################
  190. def create_actions():
  191. global actions
  192. actions={}
  193. @action(has_child_dir(".git",recursion=3))
  194. def gitk(sender,path):
  195. if not os.fork():
  196. os.chdir(path)
  197. subprocess.Popen(['gitk']).wait()
  198. sys.exit()
  199. @action(has_child_file("CMakeCache.txt"),"configure")
  200. def cmake(sender,path):
  201. if not os.fork():
  202. os.chdir(path)
  203. subprocess.Popen(['cmake-gui','.']).wait()
  204. sys.exit()
  205. @action(os.path.isdir)
  206. def terminal(sender,path):
  207. print "launch terminal '%s'" % defaults["terminal"]
  208. if not os.fork():
  209. try:
  210. if defaults["terminal"]=="konsole":
  211. subprocess.Popen([defaults["terminal"],"--workdir=%s"%path]).wait()
  212. else:
  213. os.chdir(path)
  214. subprocess.Popen([defaults["terminal"]]).wait()
  215. except OSError:
  216. pass
  217. sys.exit()
  218. @action(os.path.isdir)
  219. def navigator(sender,path):
  220. print "launch navigator '%s'" % defaults["navigator"]
  221. if not os.fork():
  222. try:
  223. subprocess.Popen([defaults["navigator"],path]).wait()
  224. except OSError:
  225. pass
  226. sys.exit()
  227. if __name__=='__main__':
  228. init()
  229. gtk.main()