1 #!/usr/bin/env python 2 3 ''' 4 Sample-launcher application. 5 ''' 6 7 # local modules 8 from common import splitfn 9 10 # built-in modules 11 import sys 12 import webbrowser 13 import Tkinter as tk 14 from glob import glob 15 from subprocess import Popen 16 from ScrolledText import ScrolledText 17 18 19 #from IPython.Shell import IPShellEmbed 20 #ipshell = IPShellEmbed() 21 22 exclude_list = ['demo', 'common'] 23 24 class LinkManager: 25 def __init__(self, text, url_callback = None): 26 self.text = text 27 self.text.tag_config("link", foreground="blue", underline=1) 28 self.text.tag_bind("link", "<Enter>", self._enter) 29 self.text.tag_bind("link", "<Leave>", self._leave) 30 self.text.tag_bind("link", "<Button-1>", self._click) 31 32 self.url_callback = url_callback 33 self.reset() 34 35 def reset(self): 36 self.links = {} 37 def add(self, action): 38 # add an action to the manager. returns tags to use in 39 # associated text widget 40 tag = "link-%d" % len(self.links) 41 self.links[tag] = action 42 return "link", tag 43 44 def _enter(self, event): 45 self.text.config(cursor="hand2") 46 def _leave(self, event): 47 self.text.config(cursor="") 48 def _click(self, event): 49 for tag in self.text.tag_names(tk.CURRENT): 50 if tag.startswith("link-"): 51 proc = self.links[tag] 52 if callable(proc): 53 proc() 54 else: 55 if self.url_callback: 56 self.url_callback(proc) 57 58 class App: 59 def __init__(self): 60 root = tk.Tk() 61 root.title('OpenCV Demo') 62 63 self.win = win = tk.PanedWindow(root, orient=tk.HORIZONTAL, sashrelief=tk.RAISED, sashwidth=4) 64 self.win.pack(fill=tk.BOTH, expand=1) 65 66 left = tk.Frame(win) 67 right = tk.Frame(win) 68 win.add(left) 69 win.add(right) 70 71 scrollbar = tk.Scrollbar(left, orient=tk.VERTICAL) 72 self.demos_lb = demos_lb = tk.Listbox(left, yscrollcommand=scrollbar.set) 73 scrollbar.config(command=demos_lb.yview) 74 scrollbar.pack(side=tk.RIGHT, fill=tk.Y) 75 demos_lb.pack(side=tk.LEFT, fill=tk.BOTH, expand=1) 76 77 self.samples = {} 78 for fn in glob('*.py'): 79 name = splitfn(fn)[1] 80 if fn[0] != '_' and name not in exclude_list: 81 demos_lb.insert(tk.END, name) 82 self.samples[name] = fn 83 demos_lb.bind('<<ListboxSelect>>', self.on_demo_select) 84 85 self.cmd_entry = cmd_entry = tk.Entry(right) 86 cmd_entry.bind('<Return>', self.on_run) 87 run_btn = tk.Button(right, command=self.on_run, text='Run', width=8) 88 89 self.text = text = ScrolledText(right, font=('arial', 12, 'normal'), width = 30, wrap='word') 90 self.linker = linker = LinkManager(text, self.on_link) 91 self.text.tag_config("header1", font=('arial', 14, 'bold')) 92 self.text.tag_config("header2", font=('arial', 12, 'bold')) 93 text.config(state='disabled') 94 95 text.pack(fill='both', expand=1, side=tk.BOTTOM) 96 cmd_entry.pack(fill='x', side='left' , expand=1) 97 run_btn.pack() 98 99 def on_link(self, url): 100 print url 101 webbrowser.open(url) 102 103 def on_demo_select(self, evt): 104 name = self.demos_lb.get( self.demos_lb.curselection()[0] ) 105 fn = self.samples[name] 106 loc = {} 107 execfile(fn, loc) 108 descr = loc.get('__doc__', 'no-description') 109 110 self.linker.reset() 111 self.text.config(state='normal') 112 self.text.delete(1.0, tk.END) 113 self.format_text(descr) 114 self.text.config(state='disabled') 115 116 self.cmd_entry.delete(0, tk.END) 117 self.cmd_entry.insert(0, fn) 118 119 def format_text(self, s): 120 text = self.text 121 lines = s.splitlines() 122 for i, s in enumerate(lines): 123 s = s.rstrip() 124 if i == 0 and not s: 125 continue 126 if s and s == '='*len(s): 127 text.tag_add('header1', 'end-2l', 'end-1l') 128 elif s and s == '-'*len(s): 129 text.tag_add('header2', 'end-2l', 'end-1l') 130 else: 131 text.insert('end', s+'\n') 132 133 def add_link(start, end, url): 134 for tag in self.linker.add(url): 135 text.tag_add(tag, start, end) 136 self.match_text(r'http://\S+', add_link) 137 138 def match_text(self, pattern, tag_proc, regexp=True): 139 text = self.text 140 text.mark_set('matchPos', '1.0') 141 count = tk.IntVar() 142 while True: 143 match_index = text.search(pattern, 'matchPos', count=count, regexp=regexp, stopindex='end') 144 if not match_index: 145 break 146 end_index = text.index( "%s+%sc" % (match_index, count.get()) ) 147 text.mark_set('matchPos', end_index) 148 if callable(tag_proc): 149 tag_proc(match_index, end_index, text.get(match_index, end_index)) 150 else: 151 text.tag_add(tag_proc, match_index, end_index) 152 153 def on_run(self, *args): 154 cmd = self.cmd_entry.get() 155 print 'running:', cmd 156 Popen(sys.executable + ' ' + cmd, shell=True) 157 158 def run(self): 159 tk.mainloop() 160 161 162 if __name__ == '__main__': 163 App().run() 164