You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
8.1 KiB

пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
пре 15 година
  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()