class OSCRemote(object): def __init__(self): self.editor_issue="1.3" # get command options self.command_options=remote_options() # get directory holding the code self.pp_dir=sys.path[0] if not os.path.exists(self.pp_dir+os.sep+"pp_oscremote.py"): tkMessageBox.showwarning("Pi Presents","Bad Application Directory") exit() # Initialise logging Monitor.log_path=self.pp_dir self.mon=Monitor() self.mon.init() Monitor.classes = ['OSCRemote','OSCConfig','OSCEditor'] Monitor.log_level = int(self.command_options['debug']) self.mon.log (self, "Pi Presents Remote is starting") self.mon.log (self," OS and separator " + os.name +' ' + os.sep) self.mon.log(self,"sys.path[0] - location of code: code "+sys.path[0]) self.setup_gui() # OSC config class self.osc_config=OSCConfig() self.init() #and start the system self.root.after(1000,self.run_app) self.root.mainloop() def init(self): self.osc_config_file = self.pp_dir + os.sep + 'pp_config' + os.sep + 'pp_oscremote.cfg' self.read_create_osc() self.pp_home_dir = self.osc_config.pp_home_dir self.pp_profiles_offset = self.osc_config.pp_profiles_offset self.mon.log(self,"Data Home from options is "+self.pp_home_dir) self.mon.log(self,"Current Profiles Offset from options is "+self.pp_profiles_offset) self.pp_profile_dir='' self.current_showlist=None self.current_show=None self.current_show_ref='' self.shows_display.delete(0,END) self.results.set('') def add_status(self,text): self.status_display.insert(END,text+'\n') self.status_display.see(END) def run_app(self): self.client=None self.server=None self.st=None # initialise OSC variables self.prefix='/pipresents' self.this_unit='/' + self.osc_config.this_unit_name self.add_status('this unit is: '+self.this_unit) self.controlled_unit='/'+self.osc_config.controlled_unit_1_name self.add_status('controlled unit is: '+self.controlled_unit) #connect client then start server to listen for replies self.init_client() self.add_status('connecting to controlled unit: '+self.osc_config.controlled_unit_1_ip+':'+self.osc_config.controlled_unit_1_port +' '+self.osc_config.controlled_unit_1_name) self.connect_client(self.osc_config.controlled_unit_1_ip,self.osc_config.controlled_unit_1_port) self.add_status('listening for replies on:'+self.osc_config.this_unit_ip+':'+self.osc_config.this_unit_port) self.init_server(self.osc_config.this_unit_ip,self.osc_config.this_unit_port,self.client) self.add_initial_handlers() self.start_server() # *************************************** # RESPOND TO BUTTONS # *************************************** def open_show(self): self.msg_path= '/core/open ' self.msg_arg_text= self.current_show_ref self.display_msg_text() def close_show(self): self.msg_path= '/core/close ' self.msg_arg_text=self.current_show_ref self.display_msg_text() def exit_pipresents(self): self.msg_path= '/core/exitpipresents' self.msg_arg_text='' self.display_msg_text() def play_event(self): self.msg_path= '/core/event' self.msg_arg_text = 'pp-play' self.display_msg_text() def pause_event(self): self.msg_path= '/core/event' self.msg_arg_text='pp-pause' self.display_msg_text() pass def stop_event(self): self.msg_path= '/core/event' self.msg_arg_text='pp-stop' self.display_msg_text() pass def up_event(self): self.msg_path= '/core/event' self.msg_arg_text='pp-up' self.display_msg_text() def down_event(self): self.msg_path= '/core/event' self.msg_arg_text='pp-down' self.display_msg_text() def output(self): self.msg_path= '/core/output' self.msg_arg_text='' self.display_msg_text() def loopback(self): self.msg_path= '/system/loopback' self.msg_arg_text='' self.display_msg_text() def server_info(self): self.msg_path= '/system/server-info' self.msg_arg_text='' self.display_msg_text() # and put the created text in the results box in the gui def display_msg_text(self): self.results.set(self.prefix+self.controlled_unit+self.msg_path+' '+self.msg_arg_text) #calback from the Send button # parses the message string into fields and sends - NO error checking def send_message(self): msg_text=self.results.get() self.add_status('Send message:'+msg_text) self.mon.log(self,'send message: ' + msg_text ) fields=msg_text.split() address = fields[0] arg_list=fields[1:] self.send(address,arg_list) # *************************************** # OSC CLIENT TO SEND MESSAGES # *************************************** def init_client(self): self.client = OSC.OSCClient() def connect_client(self,ip,port): self.mon.log(self,'connect to: '+ip+':'+str(port)) self.client.connect( (ip, int(port)) ) def send(self,address,arg_list): msg = OSC.OSCMessage() msg.setAddress(address) for arg in arg_list: msg.append(arg) self.client.send(msg) def disconnect_client(self): self.client.close() return # *************************************** # OSC SERVER TO LISTEN TO REPLIES # *************************************** def init_server(self,ip,port_text,client): self.mon.log(self,'Start Server: '+ip+':'+port_text) self.server = OSC.OSCServer((ip,int(port_text)),client) def start_server(self): self.st = threading.Thread( target = self.server.serve_forever ) self.st.start() def close_server(self): if self.server != None: self.server.close() self.mon.log(self, 'Waiting for Server-thread to finish') if self.st != None: self.st.join() ##!!! self.mon.log(self,'server thread closed') def add_initial_handlers(self): self.server.addMsgHandler('default', self.no_match_handler) self.server.addMsgHandler(self.prefix+self.this_unit+"/system/loopback-reply", self.loopback_reply_handler) self.server.addMsgHandler(self.prefix+self.this_unit+"/system/server-info-reply", self.server_info_reply_handler) def no_match_handler(self,addr, tags, stuff, source): text='' text+= "no match for new osc msg from %s" % OSC.getUrlStr(source)+'\n' text+= "with addr : %s" % addr+'\n' text+= "typetags %s" % tags+'\n' text+= "data %s" % stuff+'\n' self.add_status(text+'\n') def loopback_reply_handler(self,addr, tags, stuff, source): self.add_status('Loopback reply received from: '+ self.pretty_list(source)) def server_info_reply_handler(self,addr, tags, stuff, source): self.add_status('Server Information from: '+ self.pretty_list(source) + '\n ' + self.pretty_list(stuff)) def pretty_list(self,fields): text=' ' for field in fields: text += str(field) + ' ' return text # *************************************** # INIT EXIT MISC # *************************************** def e_edit_osc(self): self.disconnect_client() self.close_server() self.edit_osc() self.init() self.add_status('\n\n\nRESTART') self.run_app() def app_exit(self): self.disconnect_client() self.close_server() if self.root is not None: self.root.destroy() self.mon.finish() sys.exit() def show_help (self): tkMessageBox.showinfo("Help","Read 'manual.pdf'") def about (self): tkMessageBox.showinfo("About","Simple Remote Control for Pi Presents\n" +"Author: Ken Thompson" +"\nWebsite: http://pipresents.wordpress.com/") def setup_gui(self): # set up the gui # root is the Tkinter root widget self.root = Tk() self.root.title("Remote Control for Pi Presents") # self.root.configure(background='grey') self.root.resizable(False,False) # define response to main window closing self.root.protocol ("WM_DELETE_WINDOW", self.app_exit) # bind some display fields self.filename = StringVar() self.display_show = StringVar() self.results = StringVar() self.status = StringVar() # define menu menubar = Menu(self.root) profilemenu = Menu(menubar, tearoff=0, bg="grey", fg="black") profilemenu.add_command(label='Select', command = self.open_existing_profile) menubar.add_cascade(label='Profile', menu = profilemenu) toolsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Tools', menu = toolsmenu) osc_configmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='OSC', menu = osc_configmenu) osc_configmenu.add_command(label='Edit', command = self.e_edit_osc) helpmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Help', menu = helpmenu) helpmenu.add_command(label='Help', command = self.show_help) helpmenu.add_command(label='About', command = self.about) self.root.config(menu=menubar) #top frame top_frame=Frame(self.root,padx=5,pady=5) top_frame.pack(side=TOP) results_label = Label(top_frame, text="Message to Send",font="arial 12 bold") results_label.pack(side=LEFT) results_display=Entry(top_frame, textvariable=self.results, width=70) results_display.pack(side=LEFT,fill=BOTH, expand=1) send_button = Button(top_frame, width = 5, height = 1, text='Send', fg='black', command = self.send_message, bg="light grey") send_button.pack(side=RIGHT) #bottom frame bottom_frame=Frame(self.root,padx=5,pady=5) bottom_frame.pack(side=TOP, fill=BOTH, expand=1) left_frame=Frame(bottom_frame, padx=5) left_frame.pack(side=LEFT) right_frame=Frame(bottom_frame,padx=5,pady=5) right_frame.pack(side=LEFT) suplabel_frame=Frame(right_frame,pady=5) suplabel_frame.pack(side=TOP) commands_label = Label(suplabel_frame, text="Show Control",font="arial 12 bold") commands_label.pack() supervisor_frame=Frame(right_frame,pady=5) supervisor_frame.pack(side=TOP) # supervisor buttons add_button = Button(supervisor_frame, width = 5, height = 1, text='Open\nShow', fg='black', command = self.open_show, bg="light grey") add_button.pack(side=LEFT) add_button = Button(supervisor_frame, width = 5, height = 1, text='Close\nShow', fg='black', command = self.close_show, bg="light grey") add_button.pack(side=LEFT) add_button = Button(supervisor_frame, width = 10, height = 1, text='Exit\nPi Presents', fg='black', command = self.exit_pipresents, bg="light grey") add_button.pack(side=LEFT) # events buttons oplabel_frame=Frame(right_frame,pady=5) oplabel_frame.pack(side=TOP) operations_label = Label(oplabel_frame, text="Input Events", font="arial 12 bold") operations_label.pack() operations_frame=Frame(right_frame,pady=5) operations_frame.pack(side=TOP) add_button = Button(operations_frame, width = 5, height = 1, text='Play', fg='black', command = self.play_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width = 5, height = 1, text='Pause', fg='black', command = self.pause_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width = 5, height = 1, text='Stop', fg='black', command = self.stop_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width = 5, height = 1, text='Up', fg='black', command = self.up_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width = 5, height = 1, text='Down', fg='black', command = self.down_event, bg="light grey") add_button.pack(side=LEFT) # animate buttons animate_frame=Frame(right_frame,pady=5) animate_frame.pack(side=TOP) animate_label = Label(animate_frame, text="Control Outputs", font="arial 12 bold") animate_label.pack() animate_frame=Frame(right_frame,pady=5) animate_frame.pack(side=TOP) add_button = Button(animate_frame, width = 5, height = 1, text='Output', fg='black', command = self.output, bg="light grey") add_button.pack(side=LEFT) # system buttons systemlabel_frame=Frame(right_frame,pady=5) systemlabel_frame.pack(side=TOP) system_label = Label(systemlabel_frame, text="System", font="arial 12 bold") system_label.pack() system_frame=Frame(right_frame,pady=5) system_frame.pack(side=TOP) add_button = Button(system_frame, width = 5, height = 1, text='Loopback', fg='black', command = self.loopback, bg="light grey") add_button.pack(side=LEFT) add_button = Button(system_frame, width = 10, height = 1, text='Server Info', fg='black', command = self.server_info, bg="light grey") add_button.pack(side=LEFT) # define display of showlist shows_title_frame=Frame(left_frame) shows_title_frame.pack(side=TOP) shows_label = Label(shows_title_frame, text="Shows") shows_label.pack() shows_frame=Frame(left_frame) shows_frame.pack(side=TOP) scrollbar = Scrollbar(shows_frame, orient=VERTICAL) self.shows_display = Listbox(shows_frame, selectmode=SINGLE, height=12, width = 40, bg="white",activestyle=NONE, fg="black", yscrollcommand=scrollbar.set) scrollbar.config(command=self.shows_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.shows_display.pack(side=LEFT, fill=BOTH, expand=1) self.shows_display.bind("<ButtonRelease-1>", self.e_select_show) # status_frame status_frame=Frame(self.root,padx=5,pady=5) status_frame.pack(side=TOP, fill=BOTH, expand=1) status_label = Label(status_frame, text="Status",font="arial 12 bold") status_label.pack(side=LEFT) scrollbar = Scrollbar(status_frame, orient=VERTICAL) self.status_display=Text(status_frame,height=10, yscrollcommand=scrollbar.set) scrollbar.config(command=self.status_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.status_display.pack(side=LEFT,fill=BOTH, expand=1) # *************************************** # SHOWLIST # *************************************** def open_existing_profile(self): initial_dir=self.pp_home_dir+os.sep+"pp_profiles"+self.pp_profiles_offset if os.path.exists(initial_dir) is False: self.mon.err(self,"Profiles directory not found: " + initial_dir + "\n\nHint: Data Home option must end in pp_home") return dir_path=tkFileDialog.askdirectory(initialdir=initial_dir) # dir_path="C:\Users\Ken\pp_home\pp_profiles\\ttt" if len(dir_path)>0: self.open_profile(dir_path) def open_profile(self,dir_path): showlist_file = dir_path + os.sep + "pp_showlist.json" if os.path.exists(showlist_file) is False: self.mon.err(self,"Not a Profile: " + dir_path + "\n\nHint: Have you opened the profile directory?") return self.pp_profile_dir = dir_path self.root.title("Remote for Pi Presents - "+ self.pp_profile_dir) self.open_showlist(self.pp_profile_dir) def open_showlist(self,profile_dir): showlist_file = profile_dir + os.sep + "pp_showlist.json" if os.path.exists(showlist_file) is False: self.mon.err(self,"showlist file not found at " + profile_dir + "\n\nHint: Have you opened the profile directory?") self.app_exit() self.current_showlist=ShowList() self.current_showlist.open_json(showlist_file) if float(self.current_showlist.sissue()) != float(self.editor_issue): self.mon.err(self,"Version of profile does not match Remote: "+self.editor_issue) self.app_exit() self.refresh_shows_display() def refresh_shows_display(self): self.shows_display.delete(0,self.shows_display.size()) for index in range(self.current_showlist.length()): self.shows_display.insert(END, self.current_showlist.show(index)['title']+" ["+self.current_showlist.show(index)['show-ref']+"]") if self.current_showlist.show_is_selected(): self.shows_display.itemconfig(self.current_showlist.selected_show_index(),fg='red') self.shows_display.see(self.current_showlist.selected_show_index()) def e_select_show(self,event): print 'select show', self.current_showlist.length() if self.current_showlist is not None and self.current_showlist.length()>0: mouse_item_index=int(event.widget.curselection()[0]) self.current_showlist.select(mouse_item_index) self.current_show_ref=self.current_showlist.selected_show()['show-ref'] self.refresh_shows_display() else: self.current_show_ref='' # *************************************** # OSC CONFIGURATION # *************************************** def read_create_osc(self): if self.osc_config.read(self.osc_config_file) is False: self.osc_config.create(self.osc_config_file) eosc = OSCEditor(self.root, self.osc_config_file,'remote','Create OSC Remote Configuration') self.osc_config.read(self.osc_config_file) def edit_osc(self): if self.osc_config.read(self.osc_config_file) is False: self.osc_config.create(self.osc_config_file) eosc = OSCEditor(self.root, self.osc_config_file,'remote','Edit OSC Reomote Configuration')
class InputDevice(object): def __init__(self): # root is the Tkinter root widget self.root = Tk() self.root.title("Input Device Utility") # self.root.configure(background='grey') self.root.resizable(False, False) # define response to main window closing self.root.protocol("WM_DELETE_WINDOW", self.app_exit) self.my_device = '' self.my_device_display = StringVar() self.device_list = [] self.matches = 0 # overall display root_frame = Frame(self.root) root_frame.pack(side=LEFT) devices_frame = Frame(root_frame, padx=5, pady=10) devices_frame.pack(side=LEFT) devices_label = Label(devices_frame, text="Devices in dev/input") devices_label.pack(side=TOP) devices_list_frame = Frame(devices_frame, padx=5, pady=10) devices_list_frame.pack(side=TOP) selected_device_title = Label(devices_frame, text='Selected device') selected_device_title.pack(side=TOP) self.selected_device_var = StringVar() selected_device = Label(devices_frame, textvariable=self.selected_device_var, fg="red") selected_device.pack(side=TOP) events_frame = Frame(root_frame, padx=5, pady=10) events_frame.pack(side=LEFT) events_title = Label(events_frame, text='Received Events') events_title.pack(side=TOP) events_list_frame = Frame(events_frame, padx=5, pady=10) events_list_frame.pack(side=TOP) # list of devices scrollbar = Scrollbar(devices_list_frame, orient=VERTICAL) self.devices_display = Listbox(devices_list_frame, selectmode=SINGLE, height=20, width=60, bg="white", activestyle=NONE, fg="black", yscrollcommand=scrollbar.set) scrollbar.config(command=self.devices_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.devices_display.pack(side=LEFT, fill=BOTH, expand=1) self.devices_display.bind("<ButtonRelease-1>", self.e_select_device) # events display scrollbar = Scrollbar(events_list_frame, orient=VERTICAL) self.events_display = Text(events_list_frame, width=40, height=20, wrap='word', font="arial 11", padx=5, yscrollcommand=scrollbar.set) scrollbar.config(command=self.events_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.events_display.pack(side=LEFT, fill=BOTH, expand=1) self.events_display.config(state=NORMAL) self.events_display.delete(1.0, END) self.events_display.config(state=DISABLED) self.selected_device_index = -1 self.matches = 0 self.get_all_devices() self.refresh_devices_display() self.root.after(10, self.event_loop) # and enter Tkinter event loop self.root.mainloop() # *************************************** # INIT AND EXIT # *************************************** def app_exit(self): self.root.destroy() exit() def event_loop(self): if self.matches > 0: self.get_events() self.root.after(10, self.event_loop) def refresh_devices_display(self): self.devices_display.delete(0, self.devices_display.size()) for device in self.all_devices: self.devices_display.insert(END, device[0] + ' ' + device[1]) if self.selected_device_index >= 0: self.devices_display.itemconfig(self.selected_device_index, fg='red') self.devices_display.see(self.selected_device_index) def e_select_device(self, event): self.selected_device_index = -1 if len(self.all_devices) > 0: self.selected_device_index = int(event.widget.curselection()[0]) selected_device = self.all_devices[self.selected_device_index] self.selected_device_name = selected_device[0] self.selected_device_var.set(self.selected_device_name) self.get_matching_devices() self.refresh_devices_display() def get_all_devices(self): self.all_devices = [] devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()] for device in devices: self.all_devices.append([device.name, device.fn]) def get_matching_devices(self): self.matches = 0 self.matching_devices = [] devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()] for device in devices: if self.selected_device_name in device.name: device_ref = evdev.InputDevice(device.fn) self.matching_devices.append(device_ref) self.matches += 1 def get_events(self): r, w, x = select(self.matching_devices, [], [], 0) if r == []: return for event in r[0].read(): if event.type == evdev.ecodes.EV_KEY: key_event = evdev.categorize(event) if key_event.keystate == 1: key_text = 'Down' else: key_text = 'Up' # print key_event.keycode,key_text if type(key_event.keycode) is list: code_text = ', '.join(key_event.keycode) else: code_text = key_event.keycode self.events_display.config(state=NORMAL) self.events_display.insert(END, '\n' + code_text + ' ' + key_text) self.events_display.config(state=DISABLED) self.events_display.see(END)
class CenterFrame(BasePAFrame): """ фрейм со списком файлов """ def __init__(self, *args, **kwargs): self.w_frame_child = kwargs.pop('child_frame') BasePAFrame.__init__(self, *args, **kwargs) self.w_listbox_files = Listbox(self) self.w_scrollbar_files = Scrollbar(self) self.catalog = None self.catalog_files = [] def _pa_configure(self): BasePAFrame._pa_configure(self) self.w_listbox_files.config(yscrollcommand=self.w_scrollbar_files.set) self.w_scrollbar_files.config(command=self.w_listbox_files.yview) self.w_listbox_files.bind( '<<ListboxSelect>>', self.select_listbox_file) def _pa_layout(self): BasePAFrame._pa_layout(self) w_listbox_files_width = 0.95 self.w_listbox_files.place( relx=0, rely=0, relwidth=w_listbox_files_width, relheight=1) self.w_scrollbar_files.place( relx=w_listbox_files_width, rely=0, relwidth=1-w_listbox_files_width, relheight=1) def set_catalog(self, catalog=None): """ задаем новый каталог для отображения :param catalog: словарь { 'path': путь к каталогу } :return: """ try: current_index = self.w_listbox_files.curselection()[0] except IndexError: current_index = 0 if 0 < current_index < len(self.catalog_files): set_index = current_index + 1 else: set_index = current_index self.catalog = catalog self.catalog_files = [] self.w_listbox_files.delete(0, END) self.w_frame_child.set_file(None) if self.catalog is not None: catalog_path = self.catalog for file_name in os.listdir(catalog_path): file_path = os.path.join(catalog_path, file_name) if os.path.isfile(file_path): self.catalog_files.append({ 'name': file_name, 'path': file_path}) self.catalog_files.sort(key=lambda x: x['name']) catalog_files = [catalog['name'] for catalog in self.catalog_files] self.w_listbox_files.insert(END, *catalog_files) self.w_listbox_files.selection_set(set_index) self.w_listbox_files.see(set_index) self.w_listbox_files.event_generate("<<ListboxSelect>>") def update_catalog(self): self.set_catalog(self.catalog) def select_listbox_file(self, event): """ обработчик выбора файла в списке файлов :param event: :return: """ try: index = self.w_listbox_files.curselection()[0] file_ = self.catalog_files[index] except IndexError: return else: self.w_frame_child.set_file(file_)
class OSCRemote(object): def __init__(self): self.editor_issue = "1.3" # get command options self.command_options = remote_options() # get directory holding the code self.pp_dir = sys.path[0] if not os.path.exists(self.pp_dir + os.sep + "pp_oscremote.py"): tkMessageBox.showwarning("Pi Presents", "Bad Application Directory") exit() # Initialise logging Monitor.log_path = self.pp_dir self.mon = Monitor() self.mon.init() Monitor.classes = ['OSCRemote', 'OSCConfig', 'OSCEditor'] Monitor.log_level = int(self.command_options['debug']) self.mon.log(self, "Pi Presents Remote is starting") self.mon.log(self, " OS and separator " + os.name + ' ' + os.sep) self.mon.log(self, "sys.path[0] - location of code: code " + sys.path[0]) self.setup_gui() # OSC config class self.osc_config = OSCConfig() self.init() #and start the system self.root.after(1000, self.run_app) self.root.mainloop() def init(self): self.osc_config_file = self.pp_dir + os.sep + 'pp_config' + os.sep + 'pp_oscremote.cfg' self.read_create_osc() self.pp_home_dir = self.osc_config.pp_home_dir self.pp_profiles_offset = self.osc_config.pp_profiles_offset self.mon.log(self, "Data Home from options is " + self.pp_home_dir) self.mon.log( self, "Current Profiles Offset from options is " + self.pp_profiles_offset) self.pp_profile_dir = '' self.current_showlist = None self.current_show = None self.current_show_ref = '' self.shows_display.delete(0, END) self.results.set('') def add_status(self, text): self.status_display.insert(END, text + '\n') self.status_display.see(END) def run_app(self): self.client = None self.server = None self.st = None # initialise OSC variables self.prefix = '/pipresents' self.this_unit = '/' + self.osc_config.this_unit_name self.add_status('this unit is: ' + self.this_unit) self.controlled_unit = '/' + self.osc_config.controlled_unit_1_name self.add_status('controlled unit is: ' + self.controlled_unit) #connect client then start server to listen for replies self.init_client() self.add_status('connecting to controlled unit: ' + self.osc_config.controlled_unit_1_ip + ':' + self.osc_config.controlled_unit_1_port + ' ' + self.osc_config.controlled_unit_1_name) self.connect_client(self.osc_config.controlled_unit_1_ip, self.osc_config.controlled_unit_1_port) self.add_status('listening for replies on:' + self.osc_config.this_unit_ip + ':' + self.osc_config.this_unit_port) self.init_server(self.osc_config.this_unit_ip, self.osc_config.this_unit_port, self.client) self.add_initial_handlers() self.start_server() # *************************************** # RESPOND TO BUTTONS # *************************************** def open_show(self): self.msg_path = '/core/open ' self.msg_arg_text = self.current_show_ref self.display_msg_text() def close_show(self): self.msg_path = '/core/close ' self.msg_arg_text = self.current_show_ref self.display_msg_text() def exit_pipresents(self): self.msg_path = '/core/exitpipresents' self.msg_arg_text = '' self.display_msg_text() def play_event(self): self.msg_path = '/core/event' self.msg_arg_text = 'pp-play' self.display_msg_text() def pause_event(self): self.msg_path = '/core/event' self.msg_arg_text = 'pp-pause' self.display_msg_text() pass def stop_event(self): self.msg_path = '/core/event' self.msg_arg_text = 'pp-stop' self.display_msg_text() pass def up_event(self): self.msg_path = '/core/event' self.msg_arg_text = 'pp-up' self.display_msg_text() def down_event(self): self.msg_path = '/core/event' self.msg_arg_text = 'pp-down' self.display_msg_text() def output(self): self.msg_path = '/core/output' self.msg_arg_text = '' self.display_msg_text() def loopback(self): self.msg_path = '/system/loopback' self.msg_arg_text = '' self.display_msg_text() def server_info(self): self.msg_path = '/system/server-info' self.msg_arg_text = '' self.display_msg_text() # and put the created text in the results box in the gui def display_msg_text(self): self.results.set(self.prefix + self.controlled_unit + self.msg_path + ' ' + self.msg_arg_text) #calback from the Send button # parses the message string into fields and sends - NO error checking def send_message(self): msg_text = self.results.get() self.add_status('Send message:' + msg_text) self.mon.log(self, 'send message: ' + msg_text) fields = msg_text.split() address = fields[0] arg_list = fields[1:] self.send(address, arg_list) # *************************************** # OSC CLIENT TO SEND MESSAGES # *************************************** def init_client(self): self.client = OSC.OSCClient() def connect_client(self, ip, port): self.mon.log(self, 'connect to: ' + ip + ':' + str(port)) self.client.connect((ip, int(port))) def send(self, address, arg_list): msg = OSC.OSCMessage() msg.setAddress(address) for arg in arg_list: msg.append(arg) self.client.send(msg) def disconnect_client(self): self.client.close() return # *************************************** # OSC SERVER TO LISTEN TO REPLIES # *************************************** def init_server(self, ip, port_text, client): self.mon.log(self, 'Start Server: ' + ip + ':' + port_text) self.server = OSC.OSCServer((ip, int(port_text)), client) def start_server(self): self.st = threading.Thread(target=self.server.serve_forever) self.st.start() def close_server(self): if self.server != None: self.server.close() self.mon.log(self, 'Waiting for Server-thread to finish') if self.st != None: self.st.join() ##!!! self.mon.log(self, 'server thread closed') def add_initial_handlers(self): self.server.addMsgHandler('default', self.no_match_handler) self.server.addMsgHandler( self.prefix + self.this_unit + "/system/loopback-reply", self.loopback_reply_handler) self.server.addMsgHandler( self.prefix + self.this_unit + "/system/server-info-reply", self.server_info_reply_handler) def no_match_handler(self, addr, tags, stuff, source): text = '' text += "no match for new osc msg from %s" % OSC.getUrlStr( source) + '\n' text += "with addr : %s" % addr + '\n' text += "typetags %s" % tags + '\n' text += "data %s" % stuff + '\n' self.add_status(text + '\n') def loopback_reply_handler(self, addr, tags, stuff, source): self.add_status('Loopback reply received from: ' + self.pretty_list(source)) def server_info_reply_handler(self, addr, tags, stuff, source): self.add_status('Server Information from: ' + self.pretty_list(source) + '\n ' + self.pretty_list(stuff)) def pretty_list(self, fields): text = ' ' for field in fields: text += str(field) + ' ' return text # *************************************** # INIT EXIT MISC # *************************************** def e_edit_osc(self): self.disconnect_client() self.close_server() self.edit_osc() self.init() self.add_status('\n\n\nRESTART') self.run_app() def app_exit(self): self.disconnect_client() self.close_server() if self.root is not None: self.root.destroy() self.mon.finish() sys.exit() def show_help(self): tkMessageBox.showinfo("Help", "Read 'manual.pdf'") def about(self): tkMessageBox.showinfo( "About", "Simple Remote Control for Pi Presents\n" + "Author: Ken Thompson" + "\nWebsite: http://pipresents.wordpress.com/") def setup_gui(self): # set up the gui # root is the Tkinter root widget self.root = Tk() self.root.title("Remote Control for Pi Presents") # self.root.configure(background='grey') self.root.resizable(False, False) # define response to main window closing self.root.protocol("WM_DELETE_WINDOW", self.app_exit) # bind some display fields self.filename = StringVar() self.display_show = StringVar() self.results = StringVar() self.status = StringVar() # define menu menubar = Menu(self.root) profilemenu = Menu(menubar, tearoff=0, bg="grey", fg="black") profilemenu.add_command(label='Select', command=self.open_existing_profile) menubar.add_cascade(label='Profile', menu=profilemenu) toolsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Tools', menu=toolsmenu) osc_configmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='OSC', menu=osc_configmenu) osc_configmenu.add_command(label='Edit', command=self.e_edit_osc) helpmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Help', menu=helpmenu) helpmenu.add_command(label='Help', command=self.show_help) helpmenu.add_command(label='About', command=self.about) self.root.config(menu=menubar) #top frame top_frame = Frame(self.root, padx=5, pady=5) top_frame.pack(side=TOP) results_label = Label(top_frame, text="Message to Send", font="arial 12 bold") results_label.pack(side=LEFT) results_display = Entry(top_frame, textvariable=self.results, width=70) results_display.pack(side=LEFT, fill=BOTH, expand=1) send_button = Button(top_frame, width=5, height=1, text='Send', fg='black', command=self.send_message, bg="light grey") send_button.pack(side=RIGHT) #bottom frame bottom_frame = Frame(self.root, padx=5, pady=5) bottom_frame.pack(side=TOP, fill=BOTH, expand=1) left_frame = Frame(bottom_frame, padx=5) left_frame.pack(side=LEFT) right_frame = Frame(bottom_frame, padx=5, pady=5) right_frame.pack(side=LEFT) suplabel_frame = Frame(right_frame, pady=5) suplabel_frame.pack(side=TOP) commands_label = Label(suplabel_frame, text="Show Control", font="arial 12 bold") commands_label.pack() supervisor_frame = Frame(right_frame, pady=5) supervisor_frame.pack(side=TOP) # supervisor buttons add_button = Button(supervisor_frame, width=5, height=1, text='Open\nShow', fg='black', command=self.open_show, bg="light grey") add_button.pack(side=LEFT) add_button = Button(supervisor_frame, width=5, height=1, text='Close\nShow', fg='black', command=self.close_show, bg="light grey") add_button.pack(side=LEFT) add_button = Button(supervisor_frame, width=10, height=1, text='Exit\nPi Presents', fg='black', command=self.exit_pipresents, bg="light grey") add_button.pack(side=LEFT) # events buttons oplabel_frame = Frame(right_frame, pady=5) oplabel_frame.pack(side=TOP) operations_label = Label(oplabel_frame, text="Input Events", font="arial 12 bold") operations_label.pack() operations_frame = Frame(right_frame, pady=5) operations_frame.pack(side=TOP) add_button = Button(operations_frame, width=5, height=1, text='Play', fg='black', command=self.play_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width=5, height=1, text='Pause', fg='black', command=self.pause_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width=5, height=1, text='Stop', fg='black', command=self.stop_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width=5, height=1, text='Up', fg='black', command=self.up_event, bg="light grey") add_button.pack(side=LEFT) add_button = Button(operations_frame, width=5, height=1, text='Down', fg='black', command=self.down_event, bg="light grey") add_button.pack(side=LEFT) # animate buttons animate_frame = Frame(right_frame, pady=5) animate_frame.pack(side=TOP) animate_label = Label(animate_frame, text="Control Outputs", font="arial 12 bold") animate_label.pack() animate_frame = Frame(right_frame, pady=5) animate_frame.pack(side=TOP) add_button = Button(animate_frame, width=5, height=1, text='Output', fg='black', command=self.output, bg="light grey") add_button.pack(side=LEFT) # system buttons systemlabel_frame = Frame(right_frame, pady=5) systemlabel_frame.pack(side=TOP) system_label = Label(systemlabel_frame, text="System", font="arial 12 bold") system_label.pack() system_frame = Frame(right_frame, pady=5) system_frame.pack(side=TOP) add_button = Button(system_frame, width=5, height=1, text='Loopback', fg='black', command=self.loopback, bg="light grey") add_button.pack(side=LEFT) add_button = Button(system_frame, width=10, height=1, text='Server Info', fg='black', command=self.server_info, bg="light grey") add_button.pack(side=LEFT) # define display of showlist shows_title_frame = Frame(left_frame) shows_title_frame.pack(side=TOP) shows_label = Label(shows_title_frame, text="Shows") shows_label.pack() shows_frame = Frame(left_frame) shows_frame.pack(side=TOP) scrollbar = Scrollbar(shows_frame, orient=VERTICAL) self.shows_display = Listbox(shows_frame, selectmode=SINGLE, height=12, width=40, bg="white", activestyle=NONE, fg="black", yscrollcommand=scrollbar.set) scrollbar.config(command=self.shows_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.shows_display.pack(side=LEFT, fill=BOTH, expand=1) self.shows_display.bind("<ButtonRelease-1>", self.e_select_show) # status_frame status_frame = Frame(self.root, padx=5, pady=5) status_frame.pack(side=TOP, fill=BOTH, expand=1) status_label = Label(status_frame, text="Status", font="arial 12 bold") status_label.pack(side=LEFT) scrollbar = Scrollbar(status_frame, orient=VERTICAL) self.status_display = Text(status_frame, height=10, yscrollcommand=scrollbar.set) scrollbar.config(command=self.status_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.status_display.pack(side=LEFT, fill=BOTH, expand=1) # *************************************** # SHOWLIST # *************************************** def open_existing_profile(self): initial_dir = self.pp_home_dir + os.sep + "pp_profiles" + self.pp_profiles_offset if os.path.exists(initial_dir) is False: self.mon.err( self, "Profiles directory not found: " + initial_dir + "\n\nHint: Data Home option must end in pp_home") return dir_path = tkFileDialog.askdirectory(initialdir=initial_dir) # dir_path="C:\Users\Ken\pp_home\pp_profiles\\ttt" if len(dir_path) > 0: self.open_profile(dir_path) def open_profile(self, dir_path): showlist_file = dir_path + os.sep + "pp_showlist.json" if os.path.exists(showlist_file) is False: self.mon.err( self, "Not a Profile: " + dir_path + "\n\nHint: Have you opened the profile directory?") return self.pp_profile_dir = dir_path self.root.title("Remote for Pi Presents - " + self.pp_profile_dir) self.open_showlist(self.pp_profile_dir) def open_showlist(self, profile_dir): showlist_file = profile_dir + os.sep + "pp_showlist.json" if os.path.exists(showlist_file) is False: self.mon.err( self, "showlist file not found at " + profile_dir + "\n\nHint: Have you opened the profile directory?") self.app_exit() self.current_showlist = ShowList() self.current_showlist.open_json(showlist_file) if float(self.current_showlist.sissue()) != float(self.editor_issue): self.mon.err( self, "Version of profile does not match Remote: " + self.editor_issue) self.app_exit() self.refresh_shows_display() def refresh_shows_display(self): self.shows_display.delete(0, self.shows_display.size()) for index in range(self.current_showlist.length()): self.shows_display.insert( END, self.current_showlist.show(index)['title'] + " [" + self.current_showlist.show(index)['show-ref'] + "]") if self.current_showlist.show_is_selected(): self.shows_display.itemconfig( self.current_showlist.selected_show_index(), fg='red') self.shows_display.see(self.current_showlist.selected_show_index()) def e_select_show(self, event): print 'select show', self.current_showlist.length() if self.current_showlist is not None and self.current_showlist.length( ) > 0: mouse_item_index = int(event.widget.curselection()[0]) self.current_showlist.select(mouse_item_index) self.current_show_ref = self.current_showlist.selected_show( )['show-ref'] self.refresh_shows_display() else: self.current_show_ref = '' # *************************************** # OSC CONFIGURATION # *************************************** def read_create_osc(self): if self.osc_config.read(self.osc_config_file) is False: self.osc_config.create(self.osc_config_file) eosc = OSCEditor(self.root, self.osc_config_file, 'remote', 'Create OSC Remote Configuration') self.osc_config.read(self.osc_config_file) def edit_osc(self): if self.osc_config.read(self.osc_config_file) is False: self.osc_config.create(self.osc_config_file) eosc = OSCEditor(self.root, self.osc_config_file, 'remote', 'Edit OSC Reomote Configuration')
class AutocompleteEntry(Entry): def __init__(self, autocompleteList, *args, **kwargs): # Listbox length self.listboxLength = kwargs.pop('listboxLength', 12) self.listboxFontSize = tkFont.Font(size=18) # Custom matches function if 'matchesFunction' in kwargs: self.matchesFunction = kwargs['matchesFunction'] del kwargs['matchesFunction'] else: def matches(fieldValue, acListEntry): pattern = re.compile('.*' + re.escape(fieldValue) + '.*', re.IGNORECASE) return re.match(pattern, acListEntry) self.matchesFunction = matches Entry.__init__(self, *args, **kwargs) self.focus() self.autocompleteList = autocompleteList self.var = self["textvariable"] if self.var == '': self.var = self["textvariable"] = StringVar() self.var.trace('w', self.changed) self.bind("<Return>", self.selection) self.bind("<Up>", self.moveUp) self.bind("<Down>", self.moveDown) self.listboxUp = False def update_content_text(self, event): w = event.widget try: index = int(w.curselection()[0]) except IndexError: return value = w.get(index) clipboard_content = autocompleteList.get(value)[0] content['text'] = clipboard_content def changed(self, name, index, mode): if self.var.get() == '': if self.listboxUp: content['text'] = '' self.listbox.destroy() self.listboxUp = False else: words = self.comparison() if words: if not self.listboxUp: self.listbox = Listbox(width=self["width"], height=self.listboxLength, font=self.listboxFontSize) self.listbox.bind('<<ListboxSelect>>', self.update_content_text) self.listbox.bind("<Return>", self.selection) self.listbox.place(x=self.winfo_x(), y=self.winfo_y() + self.winfo_height()) self.listboxUp = True self.listbox.delete(0, END) for w in words: self.listbox.insert(END, w) self.listbox.see(0) # Scroll! self.listbox.selection_set(first=0) value = self.listbox.get(ACTIVE) clipboard_content = autocompleteList.get(value)[0] content['text'] = clipboard_content else: if self.listboxUp: content['text'] = '' self.listbox.destroy() self.listboxUp = False def selection(self, event): if self.listboxUp: self.var.set(self.listbox.get(ACTIVE)) value = self.listbox.get(ACTIVE) data = autocompleteList.get(value) content = data[0] is_command = data[1] is_website = data[2] if is_command == '1': self.execute(content) elif is_website == '1': self.open_website(content) self.listbox.destroy() self.listboxUp = False self.icursor(END) self.copy_value(content) self.quit() def open_website(self, url): webbrowser.open(url) def execute(self, command): p = subprocess.Popen(command, bufsize=2048, shell=True, stdin=subprocess.PIPE) (output, err) = p.communicate() p_status = p.wait() def copy_value(self, value): clipboard.copy(value) def moveUp(self, event): if self.listboxUp: if self.listbox.curselection() == (): index = '0' else: index = self.listbox.curselection()[0] if index != '0': self.listbox.selection_clear(first=index) index = str(int(index) - 1) self.listbox.see(index) # Scroll! self.listbox.selection_set(first=index) self.listbox.activate(index) self.listbox.event_generate("<<ListboxSelect>>", when="tail") def moveDown(self, event): if self.listboxUp: if self.listbox.curselection() == (): index = '0' else: index = self.listbox.curselection()[0] if index != END: self.listbox.selection_clear(first=index) index = str(int(index) + 1) self.listbox.see(index) self.listbox.selection_set(first=index) self.listbox.activate(index) self.listbox.event_generate("<<ListboxSelect>>", when="tail") def quit(self): root.quit() def comparison(self): return [ w for w in self.autocompleteList if self.matchesFunction(self.var.get(), w) ]
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.padx = 3 self.pady = 3 self.grid() self.results = [] self.playlists = [] self.vids = [] self.__createWidgets() def __createWidgets(self): self.__searchFields() self.__resultArea() self.__buttons() self.__markdownArea() self.bind('<Return>', self.search_button) def __buttons(self): self.resultSelect = Button(text='OK', state=DISABLED) self.resultSelect.grid(row=5, column=4, sticky=E, padx=self.padx, pady=self.pady) self.status = Label(text="", bd=1, relief=SUNKEN, anchor=W) self.status.grid(row=9, column=0, columnspan=10, sticky=N + E + S + W) self.__vidButtons() self.__rmVidButtons() self.resultSelect.grid_forget() def __searchFields(self): Label(text="User", anchor=E).grid(row=0, column=0, padx=self.padx, pady=self.pady, sticky=W) self.user_entry = Entry() self.user_entry.grid(row=0, column=1, padx=self.padx, pady=self.pady, sticky=W) Label(text="Search terms").grid(row=0, column=3, padx=self.padx, pady=self.pady, sticky=W) self.search_terms = Entry() self.search_terms.grid(row=0, column=4, padx=self.padx, pady=self.pady, sticky=W) Label(text="playlist id").grid(row=1, column=3, padx=self.padx, pady=self.pady, sticky=W) self.playlist_id = Entry() self.playlist_id.grid(row=1, column=4, padx=self.padx, pady=self.pady, sticky=W) self.search_button = Button(text="Search", command=self.__search) self.search_button.grid(row=2, column=4, padx=self.padx, pady=self.pady, sticky=E) def __resultArea(self): self.result_label = Label(text="Results") self.result_label.grid(row=2, column=0, padx=self.padx, pady=self.pady, sticky=W) self.resultshowbut = Button(text="View", command=self.__showResults) self.resultshowbut.grid(row=2, column=1, sticky=W) self.yScroll = Scrollbar(orient=VERTICAL) self.xScroll = Scrollbar(orient=HORIZONTAL) self.listbox = Listbox(xscrollcommand=self.xScroll.set, yscrollcommand=self.yScroll.set, selectmode=SINGLE) self.xScroll.config(command=self.listbox.xview) self.yScroll.config(command=self.listbox.yview) def __showResults(self): self.resultshowbut.config(text="Hide", command=self.__hideResults) self.yScroll.grid(row=3, column=5, sticky=N + S) self.xScroll.grid(row=4, column=0, sticky=E + W, columnspan=5) self.listbox.grid(row=3, column=0, sticky=N + S + E + W, columnspan=5) self.markdownarea.config(height=10) def __hideResults(self): self.resultshowbut.config(text="View", command=self.__showResults) self.yScroll.grid_forget() self.xScroll.grid_forget() self.listbox.grid_forget() self.markdownarea.config(height=30) def __markdownArea(self): self.markdownlabel = Label(text="Markdown") self.mdyScroll = Scrollbar(orient=VERTICAL) self.mdxScroll = Scrollbar(orient=HORIZONTAL) self.markdownarea = Text(wrap=WORD, height=10, yscrollcommand=self.mdyScroll.set, xscrollcommand=self.mdxScroll.set) self.copymarkdown = Button(text="Copy To Clipboard", command=self.__copyMarkdown) self.mdxScroll.config(command=self.markdownarea.xview) self.mdyScroll.config(command=self.markdownarea.yview) def __vidButtons(self): self.modtitle = Button(text='Modify titles', command=self.__modTitles) #self.modtitle.grid(row=5, column=0, sticky=W, columnspan=2, # padx=self.padx, pady=self.pady) self.getcaps = Button(text="Get captions", command=self.__getCaptions) self.getcaps.grid(row=5, column=2, columnspan=3, sticky=E, padx=self.padx, pady=self.pady) def __rmVidButtons(self): self.modtitle.grid_remove() self.getcaps.grid_remove() self.bind('<Return>', self.search_button) def __search(self): user = self.user_entry.get() playlist = self.playlist_id.get() searchterms = self.search_terms.get() self.__showResults() self.resultSelect.config(state=DISABLED) self.__rmVidButtons() self.__rmMarkdown() if not self.__validparams(user, searchterms, playlist): return False if len(playlist) > 0: self.__searchPlaylist(playlist) return self.__searchUser(user, searchterms) def __showMarkdown(self): self.markdownlabel.grid(row=5, column=0, padx=self.padx, pady=self.pady, sticky=W) self.markdownarea.grid(row=6, column=0, columnspan=5, padx=self.padx, pady=self.pady, sticky=N + S + E + W) self.mdyScroll.grid(row=6, column=5, sticky=N + S) self.mdxScroll.grid(row=7, column=0, sticky=E + W, columnspan=5) self.copymarkdown.grid(row=8, column=2, columnspan=3, sticky=E, padx=self.padx, pady=self.pady) def __rmMarkdown(self): self.markdownarea.grid_forget() self.markdownlabel.grid_forget() self.copymarkdown.grid_forget() self.mdyScroll.grid_forget() self.mdxScroll.grid_forget() def __searchPlaylist(self, playlistid): self.__getvids(playlistid) def __searchUser(self, user, searchterms): self.listbox.delete(0, END) self.__status("Searching for%splaylists by user \"%s\"" % ( " \"%s\" " % searchterms if len(searchterms) else " ", user)) self.playlists = [] try: self.playlists = lib.yt.search.PlaylistSearch(user=user, search=searchterms).query() except HTTPError: self.__status("User %s does not exist at youtube" % user) return if self.playlists is None or len(self.playlists) == 0: self.__status("Search returned no results") return self.__populateResults([v['title'] for v in self.playlists]) self.resultSelect.config(command=self.__getVidsFromSelected, state=NORMAL) self.__status("") self.resultSelect.grid(row=5, column=4, sticky=E, padx=self.padx, pady=self.pady) def __populateResults(self, values): self.listbox.delete(0, END) for i, val in enumerate(values): self.listbox.insert(i, val) self.listbox.activate(0) self.listbox.selection_set(0) def __getVidsFromSelected(self): selected = int(self.listbox.curselection()[0]) self.__getvids(self.playlists[selected]['id']) def __getvids(self, playlistid): self.playlist_id.delete(0, END) self.playlist_id.insert(0, playlistid) self.resultSelect.grid_forget() title = playlistid if len(self.playlists) > 0: for playlist in self.playlists: if playlist['id'] == playlistid: title = playlist['title'] break self.__status("Getting videos for %s" % title) self.listbox.delete(0, END) try: self.vids = lib.yt.search.PlaylistVideoSearch( id=playlistid).query() self.__populateResults([v['title'] for v in self.vids]) self.__status("%d Videos found" % len(self.vids)) self.__vidButtons() self.bind('<Return>', self.getcaps) except HTTPError: self.__status("No videos found! is %s a valid playlist?" % playlistid) def __status(self, msg): if len(msg) > 75: msg = msg[:70] + '...' self.status.config(text=msg) self.status.update_idletasks() def __trackSelect(self, vid, tracks, preftrack=None): pref = self.__prefAvailable(preftrack, tracks) if pref is None: sel = lib.trackSelect.TrackSelect(self, vid=vid, tracks=tracks) if sel.result is None: self.__status("skipped") tracks = None else: tracks = [sel.result[0]] if sel.preflang is not None: preftrack['lang'] = sel.preflang if sel.prefname is not None: preftrack['name'] = sel.prefname else: tracks = pref return tracks, preftrack def __getCaptions(self): preftrack = {'name': None, 'lang': None} self.listbox.delete(0, END) self.markdownarea.delete(1.0, END) self.__showMarkdown() for i, vid in enumerate(self.vids): nocapmsg = '[%02d] --NO CAPTIONS-- %s' % (i + 1, vid['title']) tracks = lib.yt.search.CaptionSearch(id=vid['id']).query() self.vids[i]['text'] = '' if len(tracks) == 0: self.__status('No captions available for %s' % self.vids[i]['title']) self.listbox.insert(END, nocapmsg) elif len(tracks) > 1: sel = self.__trackSelect(vid, tracks, preftrack) if sel[0] is None: msg = '[%02d] --SKIPPED-- %s' % (i + 1, vid['title']) self.listbox.insert(END, msg) self.listbox.see(END) continue tracks = sel[0] if len(tracks) == 1: self.__trackCaps(i, tracks, nocapmsg) self.__status('') self.__hideResults() def __trackCaps(self, vidIndex, tracks, nocapmsg): i = vidIndex vid = self.vids[i] msg = '%02d of %02d Getting captions for %s' % ( i + 1, len(self.vids), self.vids[i]['title']) self.__status(msg) self.listbox.insert(END, msg) self.vids[i]['text'] = lib.markdown.heading(vid['title']) captions = lib.yt.search.GetCaptions(id=vid['id'], lang=tracks[0]['lang'], name=tracks[0]['name']) captions.query() captiontext = captions.textOnly() sleep(0.2) msg = nocapmsg if captiontext is not None and len(captiontext) > 0: self.vids[i]['text'] += (lib.markdown.to_utf8(captiontext) + '\n\n') msg = '[%02d] --DONE-- %s' % (i + 1, vid['title']) self.listbox.delete(END, END) self.listbox.insert(END, msg) self.listbox.see(END) self.markdownarea.insert(END, self.vids[i]['text']) self.markdownarea.see(END) def __prefAvailable(self, preftrack, tracks): if preftrack['lang'] is None: return None pref = None for track in tracks: if (track['lang'] == preftrack['lang'] and track['name'] == preftrack['name']): return [track] if track['lang'] == preftrack['lang'] and pref is None: pref = [track] return pref def __modTitles(self): pass def __validparams(self, user, searchterms, playlist): if len(user) == 0 and len(playlist) == 0: msg = "Either a valid youtube user or playlist id must be given." tkMessageBox.showwarning("missing information", msg) return False if len(user) > 0 and not self.__validstring(user): msg = "The user given contains invalid characters" tkMessageBox.showwarning('Bad user', msg) return False if len(playlist) > 0 and not self.__validstring(playlist): msg = "The playlist given contains invalid characters" tkMessageBox.showwarning('Bad playlist', msg) return False if len(searchterms) > 0 and not self.__validstring(searchterms, True): msg = "The search terms given contain invalid characters" tkMessageBox.showwarning('Bad search', msg) return False return True def __validstring(self, s, spacechar=False): validchars = string.letters + string.digits + string.punctuation if spacechar: validchars += ' ' for c in s: if c not in validchars: return False return True def __copyMarkdown(self): self.markdownarea.clipboard_clear() self.markdownarea.clipboard_append(self.markdownarea.get(1.0, END))
class Combobox_Autocomplete(Entry, object): def __init__(self, master, list_of_items=None, autocomplete_function=None, listbox_width=None, listbox_height=7, ignorecase_match=False, startswith_match=True, vscrollbar=True, hscrollbar=True, **kwargs): if hasattr(self, "autocomplete_function"): if autocomplete_function is not None: raise ValueError( "Combobox_Autocomplete subclass has 'autocomplete_function' implemented" ) else: if autocomplete_function is not None: self.autocomplete_function = autocomplete_function else: if list_of_items is None: raise ValueError( "If not guiven complete function, list_of_items can't be 'None'" ) if ignorecase_match: if startswith_match: def matches_function(entry_data, item): return item.startswith(entry_data) else: def matches_function(entry_data, item): return item in entry_data self.autocomplete_function = lambda entry_data: [ item for item in self.list_of_items if matches_function(entry_data, item) ] else: if startswith_match: def matches_function(escaped_entry_data, item): if re.match(escaped_entry_data, item, re.IGNORECASE): return True else: return False else: def matches_function(escaped_entry_data, item): if re.search(escaped_entry_data, item, re.IGNORECASE): return True else: return False def autocomplete_function(entry_data): escaped_entry_data = re.escape(entry_data) return [ item for item in self.list_of_items if matches_function(escaped_entry_data, item) ] self.autocomplete_function = autocomplete_function self._listbox_height = int(listbox_height) self._listbox_width = listbox_width self.list_of_items = list_of_items self._use_vscrollbar = vscrollbar self._use_hscrollbar = hscrollbar kwargs.setdefault("background", "white") if "textvariable" in kwargs: self._entry_var = kwargs["textvariable"] else: self._entry_var = kwargs["textvariable"] = StringVar() Entry.__init__(self, master, **kwargs) self._trace_id = self._entry_var.trace('w', self._on_change_entry_var) self._listbox = None self.bind("<Tab>", self._on_tab) self.bind("<Up>", self._previous) self.bind("<Down>", self._next) self.bind('<Control-n>', self._next) self.bind('<Control-p>', self._previous) self.bind("<Return>", self._update_entry_from_listbox) self.bind("<Escape>", lambda event: self.unpost_listbox()) def _on_tab(self, event): self.post_listbox() return "break" def _on_change_entry_var(self, name, index, mode): entry_data = self._entry_var.get() if entry_data == '': self.unpost_listbox() self.focus() else: values = self.autocomplete_function(entry_data) if values: if self._listbox is None: self._build_listbox(values) else: self._listbox.delete(0, END) height = min(self._listbox_height, len(values)) self._listbox.configure(height=height) for item in values: self._listbox.insert(END, item) else: self.unpost_listbox() self.focus() def _build_listbox(self, values): listbox_frame = Frame() self._listbox = Listbox(listbox_frame, background="white", selectmode=SINGLE, activestyle="none", exportselection=False) self._listbox.grid(row=0, column=0, sticky=N + E + W + S) self._listbox.bind("<ButtonRelease-1>", self._update_entry_from_listbox) self._listbox.bind("<Return>", self._update_entry_from_listbox) self._listbox.bind("<Escape>", lambda event: self.unpost_listbox()) self._listbox.bind('<Control-n>', self._next) self._listbox.bind('<Control-p>', self._previous) if self._use_vscrollbar: vbar = Scrollbar(listbox_frame, orient=VERTICAL, command=self._listbox.yview) vbar.grid(row=0, column=1, sticky=N + S) self._listbox.configure( yscrollcommand=lambda f, l: autoscroll(vbar, f, l)) if self._use_hscrollbar: hbar = Scrollbar(listbox_frame, orient=HORIZONTAL, command=self._listbox.xview) hbar.grid(row=1, column=0, sticky=E + W) self._listbox.configure( xscrollcommand=lambda f, l: autoscroll(hbar, f, l)) listbox_frame.grid_columnconfigure(0, weight=1) listbox_frame.grid_rowconfigure(0, weight=1) x = -self.cget("borderwidth") - self.cget("highlightthickness") y = self.winfo_height() - self.cget("borderwidth") - self.cget( "highlightthickness") if self._listbox_width: width = self._listbox_width else: width = self.winfo_width() listbox_frame.place(in_=self, x=x, y=y, width=width) height = min(self._listbox_height, len(values)) self._listbox.configure(height=height) for item in values: self._listbox.insert(END, item) def post_listbox(self): if self._listbox is not None: return entry_data = self._entry_var.get() if entry_data == '': return values = self.autocomplete_function(entry_data) if values: self._build_listbox(values) def unpost_listbox(self): if self._listbox is not None: self._listbox.master.destroy() self._listbox = None def get_value(self): return self._entry_var.get() def set_value(self, text, close_dialog=False): self._set_var(text) if close_dialog: self.unpost_listbox() self.icursor(END) self.xview_moveto(1.0) def _set_var(self, text): self._entry_var.trace_vdelete("w", self._trace_id) self._entry_var.set(text) self._trace_id = self._entry_var.trace('w', self._on_change_entry_var) def _update_entry_from_listbox(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if current_selection: text = self._listbox.get(current_selection) self._set_var(text) self._listbox.master.destroy() self._listbox = None self.focus() self.icursor(END) self.xview_moveto(1.0) return "break" def _previous(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if len(current_selection) == 0: self._listbox.selection_set(0) self._listbox.activate(0) else: index = int(current_selection[0]) self._listbox.selection_clear(index) if index == 0: index = END else: index -= 1 self._listbox.see(index) self._listbox.selection_set(first=index) self._listbox.activate(index) return "break" def _next(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if len(current_selection) == 0: self._listbox.selection_set(0) self._listbox.activate(0) else: index = int(current_selection[0]) self._listbox.selection_clear(index) if index == self._listbox.size() - 1: index = 0 else: index += 1 self._listbox.see(index) self._listbox.selection_set(index) self._listbox.activate(index) return "break"
class App(object): def __init__(self): self.w_window = Tk() self.w_listbox_tracks = Listbox(self.w_window) self.w_label_base_path = Label( self.w_window, highlightbackground='red', highlightthickness=1, ) self.w_btn_next = Button( self.w_window, text=u'Следующая', command=self.btn_next, ) self.w_btn_pause = Button( self.w_window, text=u'Пауза/Играть', command=self.btn_pause, ) self.w_btn_stop = Button( self.w_window, text=u'Стоп', command=self.btn_stop, ) self.w_btn_plus = Button( self.w_window, text=u'+', command=self.btn_plus, ) self.w_btn_minus = Button( self.w_window, text=u'-', command=self.btn_minus, ) self.buttons = ( self.w_btn_next, self.w_btn_pause, self.w_btn_stop, self.w_btn_plus, self.w_btn_minus, ) self.music_path = '' self.musics = getattr(settings, 'musics', {}) self.musics_map = {} self.media_instance = vlc.get_default_instance() self.player = self.media_instance.media_player_new() self.media = self.media_instance.media_new(u'') self.mediaManager = self.media.event_manager() self.mark5 = self.mark4 = self.mark3 = self.mark2 = 0 self.current_play_path = u'' # для исключения ошибки, get_position не всегда равен 1 self._last_pos = 2 self.worked = False def _nur_configure(self): self.w_window.protocol('WM_DELETE_WINDOW', self.end) self.w_label_base_path.bind('<Double-Button-1>', self.set_new_path) self.w_listbox_tracks.bind('<Double-Button-1>', self.select_music) self.w_window.minsize(width=settings.MAIN_WINDOW_MIN_WIDTH, height=settings.MAIN_WINDOW_MIN_HEIGHT) self.w_window.geometry(u'{0}x{1}+{2}+{3}'.format( settings.MAIN_WINDOW_WIDTH, settings.MAIN_WINDOW_HEIGHT, settings.MAIN_WINDOW_X, settings.MAIN_WINDOW_Y)) def _nur_layout(self): rel_label_height = 0.1 rel_btns_height = 0.1 rel_btns_width = 1.0 / len(self.buttons) rel_btns_y = 1 - rel_btns_height rel_listbox_heigth = 1 - rel_label_height - rel_btns_height self.w_label_base_path.place( relx=0, rely=0, relwidth=1, relheight=rel_label_height, ) self.w_listbox_tracks.place( relx=0, rely=rel_label_height, relwidth=1, relheight=rel_listbox_heigth, ) x = 0 for btn in self.buttons: btn.place( relx=x, rely=rel_btns_y, relwidth=rel_btns_width, relheight=rel_btns_height, ) x += rel_btns_width def start(self): self._nur_configure() self._nur_layout() self.set_new_path() self.w_window.mainloop() def end(self): self.write_settings() self.w_window.destroy() def write_settings(self): with open(settings.CONFIG_FILE_PATH, 'w') as f: json.dump( { 'MUSIC_PATH': self.music_path, 'musics': self.musics, 'VOLUME': self.player.audio_get_volume() }, f, indent=4) def set_new_path(self, event=None): if event: self.music_path = askdirectory( title=u'Выберите папку с музыкой', initialdir=self.music_path) or self.music_path else: self.music_path = settings.MUSIC_PATH self.w_label_base_path['text'] = self.music_path self._load_musics() def _get_musics(self): _musics = {} for root, dirs, files in os.walk(self.music_path): for fil in files: if fil.endswith('.mp3'): file_path = os.path.join(root, fil) _musics[file_path] = { 'file_name': fil, 'album': (file_path.replace(self.music_path, '').replace(fil, '')), } return _musics def _load_musics(self): for mus_path, meta in self._get_musics().iteritems(): if mus_path not in self.musics: self.musics[mus_path] = meta meta['last_positions'] = [1.0] self.__load_musics() def __load_musics(self): self.musics_map = [(mus_path, u'{album}{file_name}'.format(**mus_meta)) for mus_path, mus_meta in self.musics.iteritems()] self.musics_map.sort(key=lambda x: x[1]) self.musics_map = [(item[0], u'{0} - {2} - {1}'.format( index, item[1], (sum(self.musics[item[0]]['last_positions']) / len(self.musics[item[0]]['last_positions'])))) for index, item in enumerate(self.musics_map)] self.w_listbox_tracks.delete(0, END) self.w_listbox_tracks.insert( END, *(title for mus_path, title in self.musics_map)) def select_music(self, event=None): self.calculate_mark() try: index = self.w_listbox_tracks.curselection()[0] self.current_play_path, music_title = self.musics_map[index] except IndexError: return else: self.player.stop() self.media = self.media_instance.media_new(self.current_play_path) self.mediaManager = self.media.event_manager() self.player.set_media(self.media) self.player.play() self.player.audio_set_volume(settings.VOLUME) if not self.worked: self.worked = True self.w_window.after(3000, self.after) # self.player.set_position(0.9) def btn_pause(self): self.player.pause() self.worked = not self.worked print self.worked if self.worked: self.w_window.after(3000, self.after) def btn_stop(self): self.player.stop() self.worked = False def btn_plus(self): volume = self.player.audio_get_volume() if volume < 100: self.player.audio_set_volume(volume + 10) def btn_minus(self): volume = self.player.audio_get_volume() if volume > 0: self.player.audio_set_volume(volume - 10) def btn_next(self): if not self.musics: return self.calculate_mark() if self.mark5 < 10: mark = 0.8 self.mark5 += 1 elif self.mark4 < 8: mark = 0.6 self.mark4 += 1 elif self.mark3 < 6: mark = 0.4 self.mark3 += 1 elif self.mark2 < 4: mark = 0.2 self.mark2 += 1 else: mark = 0 self.mark5 = self.mark4 = self.mark3 = self.mark2 = 0 self.write_settings() self.__load_musics() music_path = random.choice([ path for path, meta in self.musics.iteritems() if sum(meta['last_positions']) / len(meta['last_positions']) > mark ]) for index, music in enumerate(self.musics_map): if music[0] == music_path: break self.w_listbox_tracks.selection_clear(0, END) self.w_listbox_tracks.activate(index) self.w_listbox_tracks.selection_set(index) self.w_listbox_tracks.see(index) self.select_music() def calculate_mark(self): try: self.musics[self.current_play_path]['last_positions'].append( self.player.get_position()) except KeyError: pass else: self.musics[self.current_play_path]['last_positions'] = ( self.musics[self.current_play_path]['last_positions'][-10:]) def after(self): pos = self.player.get_position() if pos in (1.0, self._last_pos): self.btn_next() self._last_pos = pos if self.worked: self.w_window.after(3000, self.after)
class Combobox_Autocomplete(Entry, object): def __init__(self, master, list_of_items=None, autocomplete_function=None, listbox_width=None, listbox_height=7, ignorecase_match=False, startswith_match=True, vscrollbar=True, hscrollbar=True, **kwargs): if hasattr(self, "autocomplete_function"): if autocomplete_function is not None: raise ValueError("Combobox_Autocomplete subclass has 'autocomplete_function' implemented") else: if autocomplete_function is not None: self.autocomplete_function = autocomplete_function else: if list_of_items is None: raise ValueError("If not guiven complete function, list_of_items can't be 'None'") if ignorecase_match: if startswith_match: def matches_function(entry_data, item): return item.startswith(entry_data) else: def matches_function(entry_data, item): return item in entry_data self.autocomplete_function = lambda entry_data: [item for item in self.list_of_items if matches_function(entry_data, item)] else: if startswith_match: def matches_function(escaped_entry_data, item): if re.match(escaped_entry_data, item, re.IGNORECASE): return True else: return False else: def matches_function(escaped_entry_data, item): if re.search(escaped_entry_data, item, re.IGNORECASE): return True else: return False def autocomplete_function(entry_data): escaped_entry_data = re.escape(entry_data) return [item for item in self.list_of_items if matches_function(escaped_entry_data, item)] self.autocomplete_function = autocomplete_function self._listbox_height = int(listbox_height) self._listbox_width = listbox_width self.list_of_items = list_of_items self._use_vscrollbar = vscrollbar self._use_hscrollbar = hscrollbar kwargs.setdefault("background", "white") if "textvariable" in kwargs: self._entry_var = kwargs["textvariable"] else: self._entry_var = kwargs["textvariable"] = StringVar() Entry.__init__(self, master, **kwargs) self._trace_id = self._entry_var.trace('w', self._on_change_entry_var) self._listbox = None self.bind("<Tab>", self._on_tab) self.bind("<Up>", self._previous) self.bind("<Down>", self._next) self.bind('<Control-n>', self._next) self.bind('<Control-p>', self._previous) self.bind("<Return>", self._update_entry_from_listbox) self.bind("<Escape>", lambda event: self.unpost_listbox()) def _on_tab(self, event): self.post_listbox() return "break" def _on_change_entry_var(self, name, index, mode): entry_data = self._entry_var.get() if entry_data == '': self.unpost_listbox() self.focus() else: values = self.autocomplete_function(entry_data) if values: if self._listbox is None: self._build_listbox(values) else: self._listbox.delete(0, END) height = min(self._listbox_height, len(values)) self._listbox.configure(height=height) for item in values: self._listbox.insert(END, item) else: self.unpost_listbox() self.focus() def _build_listbox(self, values): listbox_frame = Frame() self._listbox = Listbox(listbox_frame, background="white", selectmode=SINGLE, activestyle="none", exportselection=False) self._listbox.grid(row=0, column=0,sticky = N+E+W+S) self._listbox.bind("<ButtonRelease-1>", self._update_entry_from_listbox) self._listbox.bind("<Return>", self._update_entry_from_listbox) self._listbox.bind("<Escape>", lambda event: self.unpost_listbox()) self._listbox.bind('<Control-n>', self._next) self._listbox.bind('<Control-p>', self._previous) if self._use_vscrollbar: vbar = Scrollbar(listbox_frame, orient=VERTICAL, command= self._listbox.yview) vbar.grid(row=0, column=1, sticky=N+S) self._listbox.configure(yscrollcommand= lambda f, l: autoscroll(vbar, f, l)) if self._use_hscrollbar: hbar = Scrollbar(listbox_frame, orient=HORIZONTAL, command= self._listbox.xview) hbar.grid(row=1, column=0, sticky=E+W) self._listbox.configure(xscrollcommand= lambda f, l: autoscroll(hbar, f, l)) listbox_frame.grid_columnconfigure(0, weight= 1) listbox_frame.grid_rowconfigure(0, weight= 1) x = -self.cget("borderwidth") - self.cget("highlightthickness") y = self.winfo_height()-self.cget("borderwidth") - self.cget("highlightthickness") if self._listbox_width: width = self._listbox_width else: width=self.winfo_width() listbox_frame.place(in_=self, x=x, y=y, width=width) height = min(self._listbox_height, len(values)) self._listbox.configure(height=height) for item in values: self._listbox.insert(END, item) def post_listbox(self): if self._listbox is not None: return entry_data = self._entry_var.get() if entry_data == '': return values = self.autocomplete_function(entry_data) if values: self._build_listbox(values) def unpost_listbox(self): if self._listbox is not None: self._listbox.master.destroy() self._listbox = None def get_value(self): return self._entry_var.get() def set_value(self, text, close_dialog=False): self._set_var(text) if close_dialog: self.unpost_listbox() self.icursor(END) self.xview_moveto(1.0) def _set_var(self, text): self._entry_var.trace_vdelete("w", self._trace_id) self._entry_var.set(text) self._trace_id = self._entry_var.trace('w', self._on_change_entry_var) def _update_entry_from_listbox(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if current_selection: text = self._listbox.get(current_selection) self._set_var(text) self._listbox.master.destroy() self._listbox = None self.focus() self.icursor(END) self.xview_moveto(1.0) return "break" def _previous(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if len(current_selection)==0: self._listbox.selection_set(0) self._listbox.activate(0) else: index = int(current_selection[0]) self._listbox.selection_clear(index) if index == 0: index = END else: index -= 1 self._listbox.see(index) self._listbox.selection_set(first=index) self._listbox.activate(index) return "break" def _next(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if len(current_selection)==0: self._listbox.selection_set(0) self._listbox.activate(0) else: index = int(current_selection[0]) self._listbox.selection_clear(index) if index == self._listbox.size() - 1: index = 0 else: index +=1 self._listbox.see(index) self._listbox.selection_set(index) self._listbox.activate(index) return "break"
class InputDevice(object): def __init__(self): # root is the Tkinter root widget self.root = Tk() self.root.title("Input Device Utility") # self.root.configure(background='grey') self.root.resizable(False,False) # define response to main window closing self.root.protocol ("WM_DELETE_WINDOW", self.app_exit) self.my_device ='' self.my_device_display = StringVar() self.device_list=[] self.matches=0 # overall display root_frame=Frame(self.root) root_frame.pack(side=LEFT) devices_frame=Frame(root_frame,padx=5,pady=10) devices_frame.pack(side=LEFT) devices_label = Label(devices_frame, text="Devices in dev/input") devices_label.pack(side=TOP) devices_list_frame=Frame(devices_frame,padx=5,pady=10) devices_list_frame.pack(side=TOP) selected_device_title=Label(devices_frame,text='Selected device') selected_device_title.pack(side=TOP) self.selected_device_var=StringVar() selected_device=Label(devices_frame,textvariable=self.selected_device_var,fg="red") selected_device.pack(side=TOP) events_frame=Frame(root_frame,padx=5,pady=10) events_frame.pack(side=LEFT) events_title=Label(events_frame,text='Received Events') events_title.pack(side=TOP) events_list_frame=Frame(events_frame,padx=5,pady=10) events_list_frame.pack(side=TOP) # list of devices scrollbar = Scrollbar(devices_list_frame, orient=VERTICAL) self.devices_display = Listbox(devices_list_frame, selectmode=SINGLE, height=20, width = 60, bg="white",activestyle=NONE, fg="black", yscrollcommand=scrollbar.set) scrollbar.config(command=self.devices_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.devices_display.pack(side=LEFT, fill=BOTH, expand=1) self.devices_display.bind("<ButtonRelease-1>", self.e_select_device) # events display scrollbar = Scrollbar(events_list_frame, orient=VERTICAL) self.events_display = Text(events_list_frame,width=40,height=20, wrap='word', font="arial 11",padx=5,yscrollcommand=scrollbar.set) scrollbar.config(command=self.events_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.events_display.pack(side=LEFT, fill=BOTH, expand=1) self.events_display.config(state=NORMAL) self.events_display.delete(1.0, END) self.events_display.config(state=DISABLED) self.selected_device_index=-1 self.matches=0 self.get_all_devices() self.refresh_devices_display() self.root.after(10,self.event_loop) # and enter Tkinter event loop self.root.mainloop() # *************************************** # INIT AND EXIT # *************************************** def app_exit(self): self.root.destroy() exit() def event_loop(self): if self.matches>0: self.get_events() self.root.after(10,self.event_loop) def refresh_devices_display(self): self.devices_display.delete(0,self.devices_display.size()) for device in self.all_devices: self.devices_display.insert(END, device[0]+ ' ' +device[1]) if self.selected_device_index >= 0: self.devices_display.itemconfig(self.selected_device_index,fg='red') self.devices_display.see(self.selected_device_index) def e_select_device(self,event): self.selected_device_index=-1 if len(self.all_devices)>0: self.selected_device_index=int(event.widget.curselection()[0]) selected_device=self.all_devices[self.selected_device_index] self.selected_device_name=selected_device[0] self.selected_device_var.set(self.selected_device_name) self.get_matching_devices() self.refresh_devices_display() def get_all_devices(self): self.all_devices=[] devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()] for device in devices: self.all_devices.append([device.name,device.fn]) def get_matching_devices(self): self.matches=0 self.matching_devices=[] devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()] for device in devices: if self.selected_device_name in device.name: device_ref = evdev.InputDevice(device.fn) self.matching_devices.append(device_ref) self.matches+=1 def get_events(self): r,w,x = select(self.matching_devices, [], [],0) if r == []: return for event in r[0].read(): if event.type == evdev.ecodes.EV_KEY: key_event = evdev.categorize(event) if key_event.keystate == 1: key_text='Down' else: key_text='Up' # print key_event.keycode,key_text if type(key_event.keycode) is list: code_text=', '.join(key_event.keycode) else: code_text=key_event.keycode self.events_display.config(state=NORMAL) self.events_display.insert(END,'\n'+ code_text + ' ' + key_text) self.events_display.config(state=DISABLED) self.events_display.see(END)
class Combobox_Autocomplete(Entry, object): def __init__(self, master, list_of_items=None, autocomplete_function=None, listbox_width=None, listbox_height=7, ignorecase_match=False, startswith_match=True, vscrollbar=True, hscrollbar=True, **kwargs): if hasattr(self, "autocomplete_function"): if autocomplete_function is not None: raise ValueError("Combobox_Autocomplete subclass has 'autocomplete_function' implemented") else: if autocomplete_function is not None: self.autocomplete_function = autocomplete_function else: if list_of_items is None: raise ValueError("If not guiven complete function, list_of_items can't be 'None'") if ignorecase_match: if startswith_match: def matches_function(entry_data, item): return item.startswith(entry_data) else: def matches_function(entry_data, item): return item in entry_data self.autocomplete_function = lambda entry_data: [item for item in self.list_of_items if matches_function(entry_data, item)] else: if startswith_match: def matches_function(escaped_entry_data, item): if re.match(escaped_entry_data, item, re.IGNORECASE): return True else: return False else: def matches_function(escaped_entry_data, item): if re.search(escaped_entry_data, item, re.IGNORECASE): return True else: return False def autocomplete_function(entry_data): escaped_entry_data = re.escape(entry_data) return [item for item in self.list_of_items if matches_function(escaped_entry_data, item)] self.autocomplete_function = autocomplete_function self._listbox_height = int(listbox_height) self._listbox_width = listbox_width self.list_of_items = list_of_items self._use_vscrollbar = vscrollbar self._use_hscrollbar = hscrollbar kwargs.setdefault("background", "white") if "textvariable" in kwargs: self._entry_var = kwargs["textvariable"] else: self._entry_var = kwargs["textvariable"] = StringVar() Entry.__init__(self, master, **kwargs) self._trace_id = self._entry_var.trace('w', self._on_change_entry_var) self._listbox = None self.bind("<Tab>", self._on_tab) self.bind("<Up>", self._previous) self.bind("<Down>", self._next) self.bind('<Control-n>', self._next) self.bind('<Control-p>', self._previous) self.bind("<Return>", self._update_entry_from_listbox) self.bind("<Escape>", lambda event: self.unpost_listbox()) #self.bind("<FocusOut>", lambda event: self.unpost_listbox()) def _on_tab(self, event): #self.post_listbox() self.unpost_listbox() #frmbill.cbouom.focus() #self._update_entry_from_listbox() #self.unpost_listbox() # if self._listbox is not None: # self._listbox.master.destroy() # self._listbox = None return "break" def _on_change_entry_var(self, name, index, mode): entry_data = self._entry_var.get() if entry_data == '': #print('test111') self.unpost_listbox() self.focus() else: if len(entry_data) < 3: return True values = finditem(entry_data) #kk #self.autocomplete_function(entry_data) if values: if self._listbox is None: self._build_listbox(values) else: self._listbox.delete(0, END) height = min(self._listbox_height, len(values)) self._listbox.configure(height=height) for item in values: self._listbox.insert(END, item) else: self.unpost_listbox() self.focus() def _build_listbox(self, values): listbox_frame = Frame() self._listbox = Listbox(listbox_frame, background="white", selectmode=SINGLE, activestyle="none", exportselection=False) self._listbox.grid(row=0, column=0,sticky = N+E+W+S) self._listbox.bind("<ButtonRelease-1>", self._update_entry_from_listbox) self._listbox.bind("<Return>", self._update_entry_from_listbox) self._listbox.bind("<Escape>", lambda event: self.unpost_listbox()) self._listbox.bind('<Control-n>', self._next) self._listbox.bind('<Control-p>', self._previous) if self._use_vscrollbar: vbar = Scrollbar(listbox_frame, orient=VERTICAL, command= self._listbox.yview) vbar.grid(row=0, column=1, sticky=N+S) self._listbox.configure(yscrollcommand= lambda f, l: autoscroll(vbar, f, l)) if self._use_hscrollbar: hbar = Scrollbar(listbox_frame, orient=HORIZONTAL, command= self._listbox.xview) hbar.grid(row=1, column=0, sticky=E+W) self._listbox.configure(xscrollcommand= lambda f, l: autoscroll(hbar, f, l)) listbox_frame.grid_columnconfigure(0, weight= 1) listbox_frame.grid_rowconfigure(0, weight= 1) x = -self.cget("borderwidth") - self.cget("highlightthickness") y = self.winfo_height()-self.cget("borderwidth") - self.cget("highlightthickness") if self._listbox_width: width = self._listbox_width else: width=self.winfo_width() listbox_frame.place(in_=self, x=x, y=y, width=width) height = min(self._listbox_height, len(values)) self._listbox.configure(height=height) for item in values: self._listbox.insert(END, item) def post_listbox(self): if self._listbox is not None: return entry_data = self._entry_var.get() if entry_data == '': return values = self.autocomplete_function(entry_data) if values: self._build_listbox(values) def unpost_listbox(self): if self._listbox is not None: self._listbox.master.destroy() self._listbox = None def get_value(self): return self._entry_var.get() def set_value(self, text, close_dialog=False): self._set_var(text) if close_dialog: self.unpost_listbox() self.icursor(END) self.xview_moveto(1.0) def _set_var(self, text): self._entry_var.trace_vdelete("w", self._trace_id) self._entry_var.set(text) self._trace_id = self._entry_var.trace('w', self._on_change_entry_var) if len(text) > 0: find_price(text) #kk def _update_entry_from_listbox(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if current_selection: text = self._listbox.get(current_selection) self._set_var(text) self._listbox.master.destroy() self._listbox = None self.focus() self.icursor(END) self.xview_moveto(1.0) return "break" def _previous(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if len(current_selection)==0: self._listbox.selection_set(0) self._listbox.activate(0) else: index = int(current_selection[0]) self._listbox.selection_clear(index) if index == 0: index = END else: index -= 1 self._listbox.see(index) self._listbox.selection_set(first=index) self._listbox.activate(index) return "break" def _next(self, event): if self._listbox is not None: current_selection = self._listbox.curselection() if len(current_selection)==0: self._listbox.selection_set(0) self._listbox.activate(0) else: index = int(current_selection[0]) self._listbox.selection_clear(index) if index == self._listbox.size() - 1: index = 0 else: index +=1 self._listbox.see(index) self._listbox.selection_set(index) self._listbox.activate(index) return "break" # if __name__ == '__main__': # try: # from Tkinter import Tk # except ImportError: # from tkinter import Tk # list_of_items = ["Cordell Cannata", "Lacey Naples", "Zachery Manigault", "Regan Brunt", "Mario Hilgefort", "Austin Phong", "Moises Saum", "Willy Neill", "Rosendo Sokoloff", "Salley Christenberry", "Toby Schneller", "Angel Buchwald", "Nestor Criger", "Arie Jozwiak", "Nita Montelongo", "Clemencia Okane", "Alison Scaggs", "Von Petrella", "Glennie Gurley", "Jamar Callender", "Titus Wenrich", "Chadwick Liedtke", "Sharlene Yochum", "Leonida Mutchler", "Duane Pickett", "Morton Brackins", "Ervin Trundy", "Antony Orwig", "Audrea Yutzy", "Michal Hepp", "Annelle Hoadley", "Hank Wyman", "Mika Fernandez", "Elisa Legendre", "Sade Nicolson", "Jessie Yi", "Forrest Mooneyhan", "Alvin Widell", "Lizette Ruppe", "Marguerita Pilarski", "Merna Argento", "Jess Daquila", "Breann Bevans", "Melvin Guidry", "Jacelyn Vanleer", "Jerome Riendeau", "Iraida Nyquist", "Micah Glantz", "Dorene Waldrip", "Fidel Garey", "Vertie Deady", "Rosalinda Odegaard", "Chong Hayner", "Candida Palazzolo", "Bennie Faison", "Nova Bunkley", "Francis Buckwalter", "Georgianne Espinal", "Karleen Dockins", "Hertha Lucus", "Ike Alberty", "Deangelo Revelle", "Juli Gallup", "Wendie Eisner", "Khalilah Travers", "Rex Outman", "Anabel King", "Lorelei Tardiff", "Pablo Berkey", "Mariel Tutino", "Leigh Marciano", "Ok Nadeau", "Zachary Antrim", "Chun Matthew", "Golden Keniston", "Anthony Johson", "Rossana Ahlstrom", "Amado Schluter", "Delila Lovelady", "Josef Belle", "Leif Negrete", "Alec Doss", "Darryl Stryker", "Michael Cagley", "Sabina Alejo", "Delana Mewborn", "Aurelio Crouch", "Ashlie Shulman", "Danielle Conlan", "Randal Donnell", "Rheba Anzalone", "Lilian Truax", "Weston Quarterman", "Britt Brunt", "Leonie Corbett", "Monika Gamet", "Ingeborg Bello", "Angelique Zhang", "Santiago Thibeau", "Eliseo Helmuth"] # root = Tk() # root.geometry("300x200") # combobox_autocomplete = Combobox_Autocomplete(root, list_of_items, highlightthickness=1) # combobox_autocomplete.pack() # combobox_autocomplete.focus() # root.mainloop()
class TkView(object): def __init__(self, root): self.root = root self.columns = 26 button_play = Button(self.root, text="Play", command=self.callback_play) button_stop = Button(self.root, text="Stop", command=self.callback_stop) button_shutdown = Button(self.root, text="Shut down", command=self.callback_shutdown) button_close = Button(self.root, text="Close", command=self.callback_close) self.text = Text(self.root, height=1) scrollbar = Scrollbar(self.root, width=30) font = tkFont.Font(size=15) self.listbox = Listbox(self.root, yscrollcommand=scrollbar.set, selectmode=SINGLE, font=font) self.listbox.bind("<<ListboxSelect>>", self.callback_stream_selected) scrollbar.config(command=self.listbox.yview) button_stop.place(relx=0, rely=0) button_play.place(relx=0.18, rely=0) button_close.place(relx=0.5, rely=0) button_shutdown.place(relx=0.7, rely=0) scrollbar.place(relx=0.9, rely=0.2, relheight=0.7) self.listbox.place(relx=0, rely=0.2, relwidth=0.9, relheight=0.7) self.text.place(relx=0, rely=0.9) self.root.protocol("WM_DELETE_WINDOW", self.callback_close) def trim_line(self, line): ret = line[:(self.columns-3)] if len(line.strip()) > self.columns: return ret + '...' else: return ret def highlight_selected_stream(self): if self.selected_stream is not None: idx = self.stream_urls.index(self.selected_stream['url']) self.listbox.selection_set(idx) self.listbox.see(idx) def display_stream_names(self): def _insert_stream_name_txt(idx): txt = self.streams[idx]['name'] if txt != '': dbg("insert_stream_name_txt: insert loop: idx: %i" %idx) self.listbox.delete(idx) self.listbox.insert(idx, self.trim_line(txt)) for idx,stream in enumerate(self.streams): if self.streams[idx].has_key('name'): self.root.after_idle(_insert_stream_name_txt, idx) self.root.after_idle(self.highlight_selected_stream)
class HistWin(object): def __init__(self, top): currentTheme = idleConf.CurrentTheme() self.history_frame = Frame(top, height=1) self.top = top fg = idleConf.GetHighlight(currentTheme, 'normal', fgBg='fg') bg = idleConf.GetHighlight(currentTheme, 'normal', fgBg='bg') self.lst = Listbox(self.history_frame, foreground=fg, background=bg, height=5, selectmode=EXTENDED, exportselection=False) self.scroll = Scrollbar(self.history_frame, command=self.lst.yview) self.lst['yscrollcommand'] = self.scroll.set self.lst.bind('<ButtonRelease-1>', self.click) #self.search_box_text = Variable() #self.search_box_text.trace('w', self.search_text_changed) #self.search_box = Entry(self.history_frame, # foreground=fg, background=bg, # textvariable=self.search_box_text) self.history_frame.pack(side=TOP, fill=X) self.is_shown = False def attach_history(self, textwidget, hist): self.hist = hist self.hist.histwin = self for h in hist.history: self.store(h) self.lst.see('end') self.textwidget = textwidget self.textwidget.bind('<<history-window-toggle>>', self.history_window_toggle_event) def click(self, evt): selection = sorted(map(int, self.lst.curselection())) commands = [self.hist.history[x] for x in selection] commands = '\n'.join(commands) self.textwidget.delete("iomark", "end-1c") self.textwidget.insert("iomark", commands) def goto(self, pointer): self.lst.select_clear(0, END) self.lst.select_set(pointer) self.lst.see(0) self.lst.see(pointer) def hide(self): self.lst.pack_forget() self.scroll.pack_forget() self.history_frame['height'] = 1 self.is_shown = False def show(self): self.scroll.pack(side=RIGHT, fill=Y) self.lst.pack(side=TOP, fill=X) self.is_shown = True def toggle(self): if self.is_shown: self.hide() else: self.show() def store(self, source): self.lst.insert(END, source[:60].replace('\n', ' ').replace('\t', ' ')) def remove(self, idx): self.lst.delete(idx) def history_window_toggle_event(self, evt): """Opens a window containing the entire history of entered commands""" self.toggle() return "break"
class WikinewsExplorer: def __init__(self, master): self.currentFileName = "" self.entDir = "/dev/shm/wikinews/entities/" self.llDir= "/dev/shm/wikinews/lang_links/" self.boolFileLoad = False self.entFiles = [] self.llFiles = [] self.wikinewsBaseURL = "http://en.wikinews.org/?curid=" frame = Frame(master) frame.pack() frame.columnconfigure(1, weight=1) frame.columnconfigure(3, pad=7) frame.rowconfigure(3, weight=1) frame.rowconfigure(5, pad=7) self.lbEntFile = Label(frame, text="entities dir: ") self.lbEntFile.grid(row=0, column=0) self.lbLLFile = Label(frame, text="lang links dir: ") self.lbLLFile.grid(row=1, column=0) self.txtEntFile =Text(frame, height=1, width=40) self.txtEntFile.insert(INSERT, self.entDir) self.txtEntFile.grid(row=0, column=1) self.txtLLFile =Text(frame, height=1, width=40) self.txtLLFile.insert(INSERT, self.llDir) self.txtLLFile.grid(row=1, column=1) self.butLoad= Button(frame, text ="Load", command = self.readInputFiles) self.butLoad.grid(row=0, column=2, rowspan=2) self.scrollbar = Scrollbar(frame) self.lstArticles = Listbox(frame, yscrollcommand = self.scrollbar.set, width=50, height=20) self.lstArticles.grid( row=2, column=0, columnspan=2, sticky=W) self.lstArticles.bind("<<ListboxSelect>>", self.onArticleSelect) self.scrollbar.grid(row=2, column=3, sticky=W) self.scrollbar.config( command = self.lstArticles.yview ) self.butOpenBrowser = Button(frame, text="View article in browser", command=self.openInFirefox) self.butOpenBrowser.grid(row=3, column=0) self.lblSearchTitle = Label(frame, text="search article ID: ") self.lblSearchTitle.grid(row=4, column=0, sticky=E) self.txtSearchTitle = Text(frame, height=1, width=30) self.txtSearchTitle.grid(row=4, column=1) self.butSearchTitle = Button(frame, text="Go", command=self.searchTitle) self.butSearchTitle.grid(row=4, column=2, sticky=W) self.scrollbar2 = Scrollbar(frame) self.lstContent = Listbox(frame, yscrollcommand=self.scrollbar2.set, width=100, height=20) self.lstContent.grid(row=0, column=3, rowspan=5) self.lstContent.bind("<<ListboxSelect>>", self.onEntitySelect) self.scrollbar2.grid(row=0, column=3, sticky=W) self.scrollbar2.config( command = self.lstContent.yview ) self.scrollbar3 = Scrollbar(frame) self.lstWikiLinks = Listbox(frame, yscrollcommand=self.scrollbar3.set, width=70, height=13) self.lstWikiLinks.grid(row=5, column=3, sticky=W) self.scrollbar3.grid(row=5, column=3, sticky=W) self.scrollbar3.config( command = self.lstWikiLinks.yview ) def onEntitySelect(self, event): """ fetch entity info directly from wikipedia """ # enpty content box self.lstWikiLinks.delete(0, END) widg = event.widget index = int(widg.curselection()[0]) entityString = widg.get(index) print 'selected entity %d: "%s"' % (index, entityString) entityName = extractEntityName(entityString) self.lstWikiLinks.insert(END, "en.wikipedia.org/wiki/" + entityName) self.lstWikiLinks.insert(END, "======= links to the following wiki entities: ========================") url = "http://en.wikipedia.org/w/api.php?format=xml&action=query&titles=" + entityName +"&prop=links" print "HTTP request: ", url xmlResponseTree = None try: response = urllib2.urlopen(url).read() xmlResponseTree = ET.fromstring(response) except: print " \n ERROR: ", str(sys.exc_info()[0]) if xmlResponseTree != None: for link in xmlResponseTree.iter("pl"): # item = "en.wikipedia.org/wiki/" + self.lstWikiLinks.insert(END, link.attrib.get("title")) else: print " xml response tree empty " def onArticleSelect(self, event): # enpty content boxes self.lstContent.delete(0, END) self.lstWikiLinks.delete(0,END) widg = event.widget index = int(widg.curselection()[0]) fileName = widg.get(index) self.currentFileName = fileName print 'selected item %d: "%s"' % (index, fileName) # load the entity and lang-link files and display in the content box entFile = self.entDir + fileName llFile = self.llDir + fileName ents = open(entFile) lls = open(llFile) self.lstContent.insert(END, "===== contained Entities =================================") for ent in ents: self.lstContent.insert(END, ent.strip()) self.lstContent.insert(END, " ") self.lstContent.insert(END, "===== contained Language Links ===========================") for ll in lls: self.lstContent.insert(END, ll.strip()) ents.close() lls.close() def openInFirefox(self): wikinewsBase = self.wikinewsBaseURL articleID = self.lstArticles.get(ACTIVE).split("-")[0] """ commandLinux = "firefox " + wikinewsBase + articleID + " &" commandMacOS = "open -a firefox -g " + wikinewsBase + articleID commandWindows = 'firefox.exe \"' + wikinewsBase + articleID + '\"' if os.uname()[0] == "Linux": print "Linux: starting firefox" os.system(commandLinux) elif os.uname()[0] == "Mac": print "Mac: starting firefox" os.system(commandMacOS) elif os.name == "Windows": print "Windows: starting firefox" os.system(commandWindows) else: tkMessageBox.showinfo("Wikinews Explorer", "Strange OS detected: " + os.uname()[0] + "\n can't start Firefox") """ if not webbrowser.open_new(wikinewsBase + articleID): tkMessageBox.showinfo("Wikinews Explorer", "start browser") return def searchTitle(self): print "search: files loaded?", self.boolFileLoad targetString = self.txtSearchTitle.get(1.0, END).strip() if self.boolFileLoad: i = 0 for fileName in self.entFiles: if targetString.lower() in fileName.lower(): # focus first result and exit self.lstArticles.selection_set(i, i) self.lstArticles.see(i) print "--- found: ", i, " ", fileName break i += 1 else: tkMessageBox.showinfo("Wikinews Explorer", "Input files not loaded") def readInputFiles(self): self.entDir = self.txtEntFile.get(1.0, END).strip() self.llDir = self.txtLLFile.get(1.0, END).strip() if not os.path.exists(self.entDir): tkMessageBox.showinfo( "Wikinews Explorer", self.entDir + "\ndoes not exist") self.boolFileLoad = False return if not os.path.exists(self.llDir): self.boolFileLoad = False tkMessageBox.showinfo( "Wikinews Explorer", self.llDir + "\ndoes not exist") return # no return until here, it's fine self.entFiles = os.listdir(self.entDir) self.llFiles = os.listdir(self.llDir) if len(self.entFiles) != len(self.llFiles): tkMessageBox.showinfo("Wikinews Explorer", "something's wrong: \n article number mismatch: " + len(self.entFiles) + " != " + len(self.llFiles)) self.boolFileLoad = False return else: print "files count ok: ", str(len(self.entFiles)), " == ", str(len(self.llFiles)) for fileName in self.entFiles: self.lstArticles.insert(END, fileName) self.boolFileLoad = True # file loading ok print "files loaded?", self.boolFileLoad
class PPEditor(object): # *************************************** # INIT # *************************************** def __init__(self): self.editor_issue="1.3" # get command options self.command_options=ed_options() # get directory holding the code self.pp_dir=sys.path[0] if not os.path.exists(self.pp_dir+os.sep+"pp_editor.py"): tkMessageBox.showwarning("Pi Presents","Bad Application Directory") exit() # Initialise logging Monitor.log_path=self.pp_dir self.mon=Monitor() self.mon.init() Monitor.classes = ['PPEditor','EditItem','Validator'] Monitor.log_level = int(self.command_options['debug']) self.mon.log (self, "Pi Presents Editor is starting") self.mon.log (self," OS and separator " + os.name +' ' + os.sep) self.mon.log(self,"sys.path[0] - location of code: code "+sys.path[0]) # set up the gui # root is the Tkinter root widget self.root = Tk() self.root.title("Editor for Pi Presents") # self.root.configure(background='grey') self.root.resizable(False,False) # define response to main window closing self.root.protocol ("WM_DELETE_WINDOW", self.app_exit) # bind some display fields self.filename = StringVar() self.display_selected_track_title = StringVar() self.display_show = StringVar() # define menu menubar = Menu(self.root) profilemenu = Menu(menubar, tearoff=0, bg="grey", fg="black") profilemenu.add_command(label='Open', command = self.open_existing_profile) profilemenu.add_command(label='Validate', command = self.validate_profile) menubar.add_cascade(label='Profile', menu = profilemenu) ptypemenu = Menu(profilemenu, tearoff=0, bg="grey", fg="black") ptypemenu.add_command(label='Exhibit', command = self.new_exhibit_profile) ptypemenu.add_command(label='Media Show', command = self.new_mediashow_profile) ptypemenu.add_command(label='Art Media Show', command = self.new_artmediashow_profile) ptypemenu.add_command(label='Menu', command = self.new_menu_profile) ptypemenu.add_command(label='Presentation', command = self.new_presentation_profile) ptypemenu.add_command(label='Interactive', command = self.new_interactive_profile) ptypemenu.add_command(label='Live Show', command = self.new_liveshow_profile) ptypemenu.add_command(label='Art Live Show', command = self.new_artliveshow_profile) ptypemenu.add_command(label='RadioButton Show', command = self.new_radiobuttonshow_profile) ptypemenu.add_command(label='Hyperlink Show', command = self.new_hyperlinkshow_profile) ptypemenu.add_command(label='Blank', command = self.new_blank_profile) profilemenu.add_cascade(label='New from Template', menu = ptypemenu) showmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") showmenu.add_command(label='Delete', command = self.remove_show) showmenu.add_command(label='Edit', command = self.m_edit_show) showmenu.add_command(label='Copy To', command = self.copy_show) menubar.add_cascade(label='Show', menu = showmenu) stypemenu = Menu(showmenu, tearoff=0, bg="grey", fg="black") stypemenu.add_command(label='Menu', command = self.add_menushow) stypemenu.add_command(label='MediaShow', command = self.add_mediashow) stypemenu.add_command(label='LiveShow', command = self.add_liveshow) stypemenu.add_command(label='HyperlinkShow', command = self.add_hyperlinkshow) stypemenu.add_command(label='RadioButtonShow', command = self.add_radiobuttonshow) stypemenu.add_command(label='ArtMediaShow', command = self.add_artmediashow) stypemenu.add_command(label='ArtLiveShow', command = self.add_artliveshow) showmenu.add_cascade(label='Add', menu = stypemenu) medialistmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='MediaList', menu = medialistmenu) medialistmenu.add_command(label='Add', command = self.add_medialist) medialistmenu.add_command(label='Delete', command = self.remove_medialist) medialistmenu.add_command(label='Copy To', command = self.copy_medialist) trackmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") trackmenu.add_command(label='Delete', command = self.remove_track) trackmenu.add_command(label='Edit', command = self.m_edit_track) trackmenu.add_command(label='Add from Dir', command = self.add_tracks_from_dir) trackmenu.add_command(label='Add from File', command = self.add_track_from_file) menubar.add_cascade(label='Track', menu = trackmenu) typemenu = Menu(trackmenu, tearoff=0, bg="grey", fg="black") typemenu.add_command(label='Video', command = self.new_video_track) typemenu.add_command(label='Audio', command = self.new_audio_track) typemenu.add_command(label='Image', command = self.new_image_track) typemenu.add_command(label='Web', command = self.new_web_track) typemenu.add_command(label='Message', command = self.new_message_track) typemenu.add_command(label='Show', command = self.new_show_track) typemenu.add_command(label='Menu Track', command = self.new_menu_track) trackmenu.add_cascade(label='New', menu = typemenu) oscmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='OSC', menu = oscmenu) oscmenu.add_command(label='Create OSC configuration', command = self.create_osc) oscmenu.add_command(label='Edit OSC Configuration', command = self.edit_osc) oscmenu.add_command(label='Delete OSC Configuration', command = self.delete_osc) toolsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Tools', menu = toolsmenu) toolsmenu.add_command(label='Update All', command = self.update_all) optionsmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Options', menu = optionsmenu) optionsmenu.add_command(label='Edit', command = self.edit_options) helpmenu = Menu(menubar, tearoff=0, bg="grey", fg="black") menubar.add_cascade(label='Help', menu = helpmenu) helpmenu.add_command(label='Help', command = self.show_help) helpmenu.add_command(label='About', command = self.about) self.root.config(menu=menubar) top_frame=Frame(self.root) top_frame.pack(side=TOP) bottom_frame=Frame(self.root) bottom_frame.pack(side=TOP, fill=BOTH, expand=1) left_frame=Frame(bottom_frame, padx=5) left_frame.pack(side=LEFT) middle_frame=Frame(bottom_frame,padx=5) middle_frame.pack(side=LEFT) right_frame=Frame(bottom_frame,padx=5,pady=10) right_frame.pack(side=LEFT) updown_frame=Frame(bottom_frame,padx=5) updown_frame.pack(side=LEFT) tracks_title_frame=Frame(right_frame) tracks_title_frame.pack(side=TOP) tracks_label = Label(tracks_title_frame, text="Tracks in Selected Medialist") tracks_label.pack() tracks_frame=Frame(right_frame) tracks_frame.pack(side=TOP) shows_title_frame=Frame(left_frame) shows_title_frame.pack(side=TOP) shows_label = Label(shows_title_frame, text="Shows") shows_label.pack() shows_frame=Frame(left_frame) shows_frame.pack(side=TOP) shows_title_frame=Frame(left_frame) shows_title_frame.pack(side=TOP) medialists_title_frame=Frame(left_frame) medialists_title_frame.pack(side=TOP) medialists_label = Label(medialists_title_frame, text="Medialists") medialists_label.pack() medialists_frame=Frame(left_frame) medialists_frame.pack(side=LEFT) # define buttons add_button = Button(middle_frame, width = 5, height = 2, text='Edit\nShow', fg='black', command = self.m_edit_show, bg="light grey") add_button.pack(side=RIGHT) add_button = Button(updown_frame, width = 5, height = 1, text='Add', fg='black', command = self.add_track_from_file, bg="light grey") add_button.pack(side=TOP) add_button = Button(updown_frame, width = 5, height = 1, text='Edit', fg='black', command = self.m_edit_track, bg="light grey") add_button.pack(side=TOP) add_button = Button(updown_frame, width = 5, height = 1, text='Up', fg='black', command = self.move_track_up, bg="light grey") add_button.pack(side=TOP) add_button = Button(updown_frame, width = 5, height = 1, text='Down', fg='black', command = self.move_track_down, bg="light grey") add_button.pack(side=TOP) # define display of showlist scrollbar = Scrollbar(shows_frame, orient=VERTICAL) self.shows_display = Listbox(shows_frame, selectmode=SINGLE, height=12, width = 40, bg="white",activestyle=NONE, fg="black", yscrollcommand=scrollbar.set) scrollbar.config(command=self.shows_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.shows_display.pack(side=LEFT, fill=BOTH, expand=1) self.shows_display.bind("<ButtonRelease-1>", self.e_select_show) # define display of medialists scrollbar = Scrollbar(medialists_frame, orient=VERTICAL) self.medialists_display = Listbox(medialists_frame, selectmode=SINGLE, height=12, width = 40, bg="white",activestyle=NONE, fg="black",yscrollcommand=scrollbar.set) scrollbar.config(command=self.medialists_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.medialists_display.pack(side=LEFT, fill=BOTH, expand=1) self.medialists_display.bind("<ButtonRelease-1>", self.select_medialist) # define display of tracks scrollbar = Scrollbar(tracks_frame, orient=VERTICAL) self.tracks_display = Listbox(tracks_frame, selectmode=SINGLE, height=25, width = 40, bg="white",activestyle=NONE, fg="black",yscrollcommand=scrollbar.set) scrollbar.config(command=self.tracks_display.yview) scrollbar.pack(side=RIGHT, fill=Y) self.tracks_display.pack(side=LEFT,fill=BOTH, expand=1) self.tracks_display.bind("<ButtonRelease-1>", self.e_select_track) # initialise editor options class and OSC config class self.options=Options(self.pp_dir) # creates options file in code directory if necessary self.osc_config=OSCConfig() # initialise variables self.init() # and enter Tkinter event loop self.root.mainloop() # *************************************** # INIT AND EXIT # *************************************** def app_exit(self): self.root.destroy() exit() def init(self): self.options.read() self.pp_home_dir = self.options.pp_home_dir self.pp_profiles_offset = self.options.pp_profiles_offset self.initial_media_dir = self.options.initial_media_dir self.mon.log(self,"Data Home from options is "+self.pp_home_dir) self.mon.log(self,"Current Profiles Offset from options is "+self.pp_profiles_offset) self.mon.log(self,"Initial Media from options is "+self.initial_media_dir) self.pp_profile_dir='' self.osc_config_file = '' self.current_medialist=None self.current_showlist=None self.current_show=None self.shows_display.delete(0,END) self.medialists_display.delete(0,END) self.tracks_display.delete(0,END) # *************************************** # MISCELLANEOUS # *************************************** def edit_options(self): """edit the options then read them from file""" eo = OptionsDialog(self.root, self.options.options_file,'Edit Options') if eo.result is True: self.init() def show_help (self): tkMessageBox.showinfo("Help","Read 'manual.pdf'") def about (self): tkMessageBox.showinfo("About","Editor for Pi Presents Profiles\n" +"For profile version: " + self.editor_issue + "\nAuthor: Ken Thompson" +"\nWebsite: http://pipresents.wordpress.com/") def validate_profile(self): val =Validator() val.validate_profile(self.root,self.pp_dir,self.pp_home_dir,self.pp_profile_dir,self.editor_issue,True) # ************** # OSC CONFIGURATION # ************** def create_osc(self): if self.pp_profile_dir=='': return if self.osc_config.read(self.osc_config_file) is False: iodir=self.pp_profile_dir+os.sep+'pp_io_config' if not os.path.exists(iodir): os.makedirs(iodir) self.osc_config.create(self.osc_config_file) def edit_osc(self): if self.osc_config.read(self.osc_config_file) is False: # print 'no config file' return osc_ut=OSCUnitType(self.root,self.osc_config.this_unit_type) self.req_unit_type=osc_ut.result if self.req_unit_type != None: # print self.req_unit_type eosc = OSCEditor(self.root, self.osc_config_file,self.req_unit_type,'Edit OSC Configuration') def delete_osc(self): if self.osc_config.read(self.osc_config_file) is False: return os.rename(self.osc_config_file,self.osc_config_file+'.bak') # ************** # PROFILES # ************** def open_existing_profile(self): initial_dir=self.pp_home_dir+os.sep+"pp_profiles"+self.pp_profiles_offset if os.path.exists(initial_dir) is False: self.mon.err(self,"Profiles directory not found: " + initial_dir + "\n\nHint: Data Home option must end in pp_home") return dir_path=tkFileDialog.askdirectory(initialdir=initial_dir) # dir_path="C:\Users\Ken\pp_home\pp_profiles\\ttt" if len(dir_path)>0: self.open_profile(dir_path) def open_profile(self,dir_path): showlist_file = dir_path + os.sep + "pp_showlist.json" if os.path.exists(showlist_file) is False: self.mon.err(self,"Not a Profile: " + dir_path + "\n\nHint: Have you opened the profile directory?") return self.pp_profile_dir = dir_path self.root.title("Editor for Pi Presents - "+ self.pp_profile_dir) if self.open_showlist(self.pp_profile_dir) is False: self.init() return self.open_medialists(self.pp_profile_dir) self.refresh_tracks_display() self.osc_config_file=self.pp_profile_dir+os.sep+'pp_io_config'+os.sep+'osc.cfg' def new_profile(self,profile): d = Edit1Dialog(self.root,"New Profile","Name", "") if d .result is None: return name=str(d.result) if name == "": tkMessageBox.showwarning("New Profile","Name is blank") return to = self.pp_home_dir + os.sep + "pp_profiles"+ self.pp_profiles_offset + os.sep + name if os.path.exists(to) is True: tkMessageBox.showwarning( "New Profile","Profile exists\n(%s)" % to ) return shutil.copytree(profile, to, symlinks=False, ignore=None) self.open_profile(to) def new_exhibit_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_exhibit_1p3' self.new_profile(profile) def new_interactive_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_interactive_1p3' self.new_profile(profile) def new_menu_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_menu_1p3' self.new_profile(profile) def new_presentation_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_presentation_1p3' self.new_profile(profile) def new_blank_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep +"ppt_blank_1p3" self.new_profile(profile) def new_mediashow_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_mediashow_1p3' self.new_profile(profile) def new_liveshow_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_liveshow_1p3' self.new_profile(profile) def new_artmediashow_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_artmediashow_1p3' self.new_profile(profile) def new_artliveshow_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_artliveshow_1p3' self.new_profile(profile) def new_radiobuttonshow_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_radiobuttonshow_1p3' self.new_profile(profile) def new_hyperlinkshow_profile(self): profile = self.pp_dir+os.sep+'pp_resources'+os.sep+'pp_templates'+os.sep + 'ppt_hyperlinkshow_1p3' self.new_profile(profile) # *************************************** # Shows # *************************************** def open_showlist(self,profile_dir): showlist_file = profile_dir + os.sep + "pp_showlist.json" if os.path.exists(showlist_file) is False: self.mon.err(self,"showlist file not found at " + profile_dir + "\n\nHint: Have you opened the profile directory?") self.app_exit() self.current_showlist=ShowList() self.current_showlist.open_json(showlist_file) if float(self.current_showlist.sissue())<float(self.editor_issue) or (self.command_options['forceupdate'] is True and float(self.current_showlist.sissue()) == float(self.editor_issue)): self.update_profile() self.mon.err(self,"Version of profile has been updated to "+self.editor_issue+", please re-open") return False if float(self.current_showlist.sissue())>float(self.editor_issue): self.mon.err(self,"Version of profile is greater than editor, must exit") self.app_exit() self.refresh_shows_display() return True def save_showlist(self,showlist_dir): if self.current_showlist is not None: showlist_file = showlist_dir + os.sep + "pp_showlist.json" self.current_showlist.save_list(showlist_file) def add_mediashow(self): self.add_show(PPdefinitions.new_shows['mediashow']) def add_liveshow(self): self.add_show(PPdefinitions.new_shows['liveshow']) def add_radiobuttonshow(self): self.add_show(PPdefinitions.new_shows['radiobuttonshow']) def add_hyperlinkshow(self): self.add_show(PPdefinitions.new_shows['hyperlinkshow']) def add_artliveshow(self): self.add_show(PPdefinitions.new_shows['artliveshow']) def add_artmediashow(self): self.add_show(PPdefinitions.new_shows['artmediashow']) def add_menushow(self): self.add_show(PPdefinitions.new_shows['menu']) def add_start(self): self.add_show(PPdefinitions.new_shows['start']) def add_show(self,default): # append it to the showlist and then add the medialist if self.current_showlist is not None: d = Edit1Dialog(self.root,"AddShow","Show Reference", "") if d.result is None: return name=str(d.result) if name == "": tkMessageBox.showwarning("Add Show","Name is blank") return if self.current_showlist.index_of_show(name) != -1: tkMessageBox.showwarning("Add Show","A Show with this name already exists") return copied_show=self.current_showlist.copy(default,name) mediafile=self.add_medialist(name) if mediafile != '': copied_show['medialist']=mediafile self.current_showlist.append(copied_show) self.save_showlist(self.pp_profile_dir) self.refresh_shows_display() def remove_show(self): if self.current_showlist is not None and self.current_showlist.length()>0 and self.current_showlist.show_is_selected(): if tkMessageBox.askokcancel("Delete Show","Delete Show"): index= self.current_showlist.selected_show_index() self.current_showlist.remove(index) self.save_showlist(self.pp_profile_dir) self.refresh_shows_display() def show_refs(self): _show_refs=[] for index in range(self.current_showlist.length()): if self.current_showlist.show(index)['show-ref'] != "start": _show_refs.append(copy.deepcopy(self.current_showlist.show(index)['show-ref'])) return _show_refs def refresh_shows_display(self): self.shows_display.delete(0,self.shows_display.size()) for index in range(self.current_showlist.length()): self.shows_display.insert(END, self.current_showlist.show(index)['title']+" ["+self.current_showlist.show(index)['show-ref']+"]") if self.current_showlist.show_is_selected(): self.shows_display.itemconfig(self.current_showlist.selected_show_index(),fg='red') self.shows_display.see(self.current_showlist.selected_show_index()) def e_select_show(self,event): if self.current_showlist is not None and self.current_showlist.length()>0: mouse_item_index=int(event.widget.curselection()[0]) self.current_showlist.select(mouse_item_index) self.refresh_shows_display() def copy_show(self): if self.current_showlist is not None and self.current_showlist.show_is_selected(): self.add_show(self.current_showlist.selected_show()) def m_edit_show(self): self.edit_show(PPdefinitions.show_types,PPdefinitions.show_field_specs) def edit_show(self,show_types,field_specs): if self.current_showlist is not None and self.current_showlist.show_is_selected(): d=EditItem(self.root,"Edit Show",self.current_showlist.selected_show(),show_types,field_specs,self.show_refs(), self.initial_media_dir,self.pp_home_dir,'show') if d.result is True: self.save_showlist(self.pp_profile_dir) self.refresh_shows_display() # *************************************** # Medialists # *************************************** def open_medialists(self,profile_dir): self.medialists = [] for this_file in os.listdir(profile_dir): if this_file.endswith(".json") and this_file not in ('pp_showlist.json','schedule.json'): self.medialists = self.medialists + [this_file] self.medialists_display.delete(0,self.medialists_display.size()) for index in range (len(self.medialists)): self.medialists_display.insert(END, self.medialists[index]) self.current_medialists_index=-1 self.current_medialist=None def add_medialist(self,name=None): if name is None: d = Edit1Dialog(self.root,"Add Medialist","File", "") if d.result is None: return '' name=str(d.result) if name == "": tkMessageBox.showwarning("Add medialist","Name is blank") return '' if not name.endswith(".json"): name=name+(".json") path = self.pp_profile_dir + os.sep + name if os.path.exists(path) is True: tkMessageBox.showwarning("Add medialist","Medialist file exists\n(%s)" % path) return '' nfile = open(path,'wb') nfile.write("{") nfile.write("\"issue\": \""+self.editor_issue+"\",\n") nfile.write("\"tracks\": [") nfile.write("]") nfile.write("}") nfile.close() # append it to the list self.medialists.append(copy.deepcopy(name)) # add title to medialists display self.medialists_display.insert(END, name) # and set it as the selected medialist self.refresh_medialists_display() return name def copy_medialist(self,to_file=None): if self.current_medialist is not None: #from_file= self.current_medialist from_file= self.medialists[self.current_medialists_index] if to_file is None: d = Edit1Dialog(self.root,"Copy Medialist","File", "") if d.result is None: return '' to_file=str(d.result) if to_file == "": tkMessageBox.showwarning("Copy medialist","Name is blank") return '' success_file = self.copy_medialist_file(from_file,to_file) if success_file =='': return '' # append it to the list self.medialists.append(copy.deepcopy(success_file)) # add title to medialists display self.medialists_display.insert(END, success_file) # and reset selected medialist self.current_medialist=None self.refresh_medialists_display() self.refresh_tracks_display() return success_file else: return '' def copy_medialist_file(self,from_file,to_file): if not to_file.endswith(".json"): to_file+=(".json") to_path = self.pp_profile_dir + os.sep + to_file if os.path.exists(to_path) is True: tkMessageBox.showwarning("Copy medialist","Medialist file exists\n(%s)" % to_path) return '' from_path= self.pp_profile_dir + os.sep + from_file if os.path.exists(from_path) is False: tkMessageBox.showwarning("Copy medialist","Medialist file not found\n(%s)" % from_path) return '' shutil.copy(from_path,to_path) return to_file def remove_medialist(self): if self.current_medialist is not None: if tkMessageBox.askokcancel("Delete Medialist","Delete Medialist"): os.remove(self.pp_profile_dir+ os.sep + self.medialists[self.current_medialists_index]) self.open_medialists(self.pp_profile_dir) self.refresh_medialists_display() self.refresh_tracks_display() def select_medialist(self,event): """ user clicks on a medialst in a profile so try and select it. """ # needs forgiving int for possible tkinter upgrade if len(self.medialists)>0: self.current_medialists_index=int(event.widget.curselection()[0]) self.current_medialist=MediaList('ordered') if not self.current_medialist.open_list(self.pp_profile_dir+ os.sep + self.medialists[self.current_medialists_index],self.current_showlist.sissue()): self.mon.err(self,"medialist is a different version to showlist: "+ self.medialists[self.current_medialists_index]) self.app_exit() self.refresh_tracks_display() self.refresh_medialists_display() def refresh_medialists_display(self): self.medialists_display.delete(0,len(self.medialists)) for index in range (len(self.medialists)): self.medialists_display.insert(END, self.medialists[index]) if self.current_medialist is not None: self.medialists_display.itemconfig(self.current_medialists_index,fg='red') self.medialists_display.see(self.current_medialists_index) def save_medialist(self): basefile=self.medialists[self.current_medialists_index] # print type(basefile) # basefile=str(basefile) # print type(basefile) medialist_file = self.pp_profile_dir+ os.sep + basefile self.current_medialist.save_list(medialist_file) # *************************************** # Tracks # *************************************** def refresh_tracks_display(self): self.tracks_display.delete(0,self.tracks_display.size()) if self.current_medialist is not None: for index in range(self.current_medialist.length()): if self.current_medialist.track(index)['track-ref'] != '': track_ref_string=" ["+self.current_medialist.track(index)['track-ref']+"]" else: track_ref_string="" self.tracks_display.insert(END, self.current_medialist.track(index)['title']+track_ref_string) if self.current_medialist.track_is_selected(): self.tracks_display.itemconfig(self.current_medialist.selected_track_index(),fg='red') self.tracks_display.see(self.current_medialist.selected_track_index()) def e_select_track(self,event): if self.current_medialist is not None and self.current_medialist.length()>0: mouse_item_index=int(event.widget.curselection()[0]) self.current_medialist.select(mouse_item_index) self.refresh_tracks_display() def m_edit_track(self): self.edit_track(PPdefinitions.track_types,PPdefinitions.track_field_specs) def edit_track(self,track_types,field_specs): if self.current_medialist is not None and self.current_medialist.track_is_selected(): d=EditItem(self.root,"Edit Track",self.current_medialist.selected_track(),track_types,field_specs, self.show_refs(),self.initial_media_dir,self.pp_home_dir,'track') if d.result is True: self.save_medialist() self.refresh_tracks_display() def move_track_up(self): if self.current_medialist is not None and self.current_medialist.track_is_selected(): self.current_medialist.move_up() self.refresh_tracks_display() self.save_medialist() def move_track_down(self): if self.current_medialist is not None and self.current_medialist.track_is_selected(): self.current_medialist.move_down() self.refresh_tracks_display() self.save_medialist() def new_track(self,fields,values): if self.current_medialist is not None: # print '\nfields ', fields # print '\nvalues ', values new_track=copy.deepcopy(fields) # print ',\new track ',new_track self.current_medialist.append(new_track) # print '\nbefore values ',self.current_medialist.print_list() if values is not None: self.current_medialist.update(self.current_medialist.length()-1,values) self.current_medialist.select(self.current_medialist.length()-1) self.refresh_tracks_display() self.save_medialist() def new_message_track(self): self.new_track(PPdefinitions.new_tracks['message'],None) def new_video_track(self): self.new_track(PPdefinitions.new_tracks['video'],None) def new_audio_track(self): self.new_track(PPdefinitions.new_tracks['audio'],None) def new_web_track(self): self.new_track(PPdefinitions.new_tracks['web'],None) def new_image_track(self): self.new_track(PPdefinitions.new_tracks['image'],None) def new_show_track(self): self.new_track(PPdefinitions.new_tracks['show'],None) def new_menu_track(self): self.new_track(PPdefinitions.new_tracks['menu'],None) def remove_track(self): if self.current_medialist is not None and self.current_medialist.length()>0 and self.current_medialist.track_is_selected(): if tkMessageBox.askokcancel("Delete Track","Delete Track"): index= self.current_medialist.selected_track_index() self.current_medialist.remove(index) self.save_medialist() self.refresh_tracks_display() def add_track_from_file(self): if self.current_medialist is None: return # print "initial directory ", self.options.initial_media_dir files_path=tkFileDialog.askopenfilename(initialdir=self.options.initial_media_dir, multiple=True) # fix for tkinter bug files_path = self.root.tk.splitlist(files_path) for file_path in files_path: file_path=os.path.normpath(file_path) # print "file path ", file_path self.add_track(file_path) self.save_medialist() def add_tracks_from_dir(self): if self.current_medialist is None: return image_specs =[PPdefinitions.IMAGE_FILES,PPdefinitions.VIDEO_FILES,PPdefinitions.AUDIO_FILES, PPdefinitions.WEB_FILES,('All files', '*')] # last one is ignored in finding files in directory, for dialog box only directory=tkFileDialog.askdirectory(initialdir=self.options.initial_media_dir) # deal with tuple returned on Cancel if len(directory) == 0: return # make list of exts we recognise exts = [] for image_spec in image_specs[:-1]: image_list=image_spec[1:] for ext in image_list: exts.append(copy.deepcopy(ext)) for this_file in os.listdir(directory): (root_file,ext_file)= os.path.splitext(this_file) if ext_file.lower() in exts: file_path=directory+os.sep+this_file # print "file path before ", file_path file_path=os.path.normpath(file_path) # print "file path after ", file_path self.add_track(file_path) self.save_medialist() def add_track(self,afile): relpath = os.path.relpath(afile,self.pp_home_dir) # print "relative path ",relpath common = os.path.commonprefix([afile,self.pp_home_dir]) # print "common ",common if common.endswith("pp_home") is False: location = afile else: location = "+" + os.sep + relpath location = string.replace(location,'\\','/') # print "location ",location (root,title)=os.path.split(afile) (root,ext)= os.path.splitext(afile) if ext.lower() in PPdefinitions.IMAGE_FILES: self.new_track(PPdefinitions.new_tracks['image'],{'title':title,'track-ref':'','location':location}) elif ext.lower() in PPdefinitions.VIDEO_FILES: self.new_track(PPdefinitions.new_tracks['video'],{'title':title,'track-ref':'','location':location}) elif ext.lower() in PPdefinitions.AUDIO_FILES: self.new_track(PPdefinitions.new_tracks['audio'],{'title':title,'track-ref':'','location':location}) elif ext.lower() in PPdefinitions.WEB_FILES: self.new_track(PPdefinitions.new_tracks['web'],{'title':title,'track-ref':'','location':location}) else: self.mon.err(self,afile + " - cannot determine track type, use menu track>new") # ********************************************* # UPDATE PROFILE # ********************************************** def update_all(self): self.init() for profile_file in os.listdir(self.pp_home_dir+os.sep+'pp_profiles'+self.pp_profiles_offset): # self.mon.log (self,"Updating "+profile_file) self.pp_profile_dir = self.pp_home_dir+os.sep+'pp_profiles'+self.pp_profiles_offset + os.sep + profile_file if not os.path.exists(self.pp_profile_dir+os.sep+"pp_showlist.json"): tkMessageBox.showwarning("Pi Presents","Not a profile, skipping "+self.pp_profile_dir) else: self.current_showlist=ShowList() self.current_showlist.open_json(self.pp_profile_dir+os.sep+"pp_showlist.json") self.mon.log (self,"Version of profile "+ profile_file + ' is ' + self.current_showlist.sissue()) if float(self.current_showlist.sissue())<float(self.editor_issue): self.mon.log(self,"Version of profile "+profile_file+ " is being updated to "+self.editor_issue) self.update_profile() elif (self.command_options['forceupdate'] is True and float(self.current_showlist.sissue()) == float(self.editor_issue)): self.mon.log(self, "Forced updating of " + profile_file + ' to '+self.editor_issue) self.update_profile() elif float(self.current_showlist.sissue())>float(self.editor_issue): tkMessageBox.showwarning("Pi Presents", "Version of profile " +profile_file+ " is greater than editor, skipping") else: self.mon.log(self," Skipping Profile " + profile_file + " It is already up to date ") self.init() tkMessageBox.showwarning("Pi Presents","All profiles updated") def update_profile(self): self.update_medialists() # medialists and their tracks self.update_shows() #shows in showlist, also creates menu tracks for 1.2>1.3 def update_shows(self): # open showlist into a list of dictionaries self.mon.log (self,"Updating show ") ifile = open(self.pp_profile_dir + os.sep + "pp_showlist.json", 'rb') shows = json.load(ifile)['shows'] ifile.close() # special 1.2>1.3 create menu medialists with menu track from show #go through shows - if type = menu and version is greater copy its medialist to a new medialist with name = <show-ref>-menu1p3.json for show in shows: #create a new medialist medialist != show-ref as menus can't now share medialists if show['type']=='menu' and float(self.current_showlist.sissue())<float(self.editor_issue): to_file=show['show-ref']+'-menu1p3.json' from_file = show['medialist'] if to_file != from_file: self.copy_medialist_file(from_file,to_file) else: self.mon.warn(self, 'medialist file' + to_file + ' already exists, must exit with incomplete update') return False #update the reference to the medialist show['medialist']=to_file #delete show fields so they are recreated with new default content del show['controls'] # open the medialist and add the menu track then populate some of its fields from the show ifile = open(self.pp_profile_dir + os.sep + to_file, 'rb') tracks = json.load(ifile)['tracks'] ifile.close() new_track=copy.deepcopy(PPdefinitions.new_tracks['menu']) tracks.append(copy.deepcopy(new_track)) # copy menu parameters from menu show to menu track and init values of some self.transfer_show_params(show,tracks,'menu-track',("entry-colour","entry-font", "entry-select-colour", "hint-colour", "hint-font", "hint-text", "hint-x","hint-y", "menu-bullet", "menu-columns", "menu-direction", "menu-guidelines", "menu-horizontal-padding", "menu-horizontal-separation", "menu-icon-height", "menu-icon-mode", "menu-icon-width", "menu-rows", "menu-strip", "menu-strip-padding", "menu-text-height", "menu-text-mode", "menu-text-width", "menu-vertical-padding", "menu-vertical-separation", "menu-window")) # and save the medialist dic={'issue':self.editor_issue,'tracks':tracks} ofile = open(self.pp_profile_dir + os.sep + to_file, "wb") json.dump(dic,ofile,sort_keys=True,indent=1) # end for show in shows #update the fields in all shows replacement_shows=self.update_shows_in_showlist(shows) dic={'issue':self.editor_issue,'shows':replacement_shows} ofile = open(self.pp_profile_dir + os.sep + "pp_showlist.json", "wb") json.dump(dic,ofile,sort_keys=True,indent=1) return True def transfer_show_params(self,show,tracks,track_ref,fields): # find the menu track in medialist for index,track in enumerate(tracks): if track['track-ref']== 'menu-track': break #update some fields with new default content tracks[index]['links']=PPdefinitions.new_tracks['menu']['links'] #transfer values from show to track for field in fields: tracks[index][field]=show[field] # print show[field], tracks[index][field] pass def update_medialists(self): # UPDATE MEDIALISTS AND THEIR TRACKS for this_file in os.listdir(self.pp_profile_dir): if this_file.endswith(".json") and this_file not in ('pp_showlist.json','schedule.json'): self.mon.log (self,"Updating medialist " + this_file) # open a medialist and update its tracks ifile = open(self.pp_profile_dir + os.sep + this_file, 'rb') tracks = json.load(ifile)['tracks'] ifile.close() replacement_tracks=self.update_tracks(tracks) dic={'issue':self.editor_issue,'tracks':replacement_tracks} ofile = open(self.pp_profile_dir + os.sep + this_file, "wb") json.dump(dic,ofile,sort_keys=True,indent=1) def update_tracks(self,old_tracks): # get correct spec from type of field replacement_tracks=[] for old_track in old_tracks: # print '\nold track ',old_track track_type=old_track['type'] #update if new tracks has the track type otherwise skip if track_type in PPdefinitions.new_tracks: spec_fields=PPdefinitions.new_tracks[track_type] left_overs=dict() # go through track and delete fields not in spec for key in old_track.keys(): if key in spec_fields: left_overs[key]=old_track[key] # print '\n leftovers',left_overs replacement_track=copy.deepcopy(PPdefinitions.new_tracks[track_type]) # print '\n before update', replacement_track replacement_track.update(left_overs) # print '\nafter update',replacement_track replacement_tracks.append(copy.deepcopy(replacement_track)) return replacement_tracks def update_shows_in_showlist(self,old_shows): # get correct spec from type of field replacement_shows=[] for old_show in old_shows: show_type=old_show['type'] ## menu to menushow spec_fields=PPdefinitions.new_shows[show_type] left_overs=dict() # go through track and delete fields not in spec for key in old_show.keys(): if key in spec_fields: left_overs[key]=old_show[key] # print '\n leftovers',left_overs replacement_show=copy.deepcopy(PPdefinitions.new_shows[show_type]) replacement_show.update(left_overs) replacement_shows.append(copy.deepcopy(replacement_show)) return replacement_shows
class ConditionalsEditor: def __init__(self, my_window, conditionals, close_callback): #Tk.__init__(self) self.my_window = my_window self.my_window.title("Condition Editor") self.close_callback = close_callback self.conditionals = conditionals shared_pad_x = 3 shared_pad_y = 3 main_frame = Frame(self.my_window) main_frame.grid(column=0, row=0, sticky=(N, W, E, S)) image_path = "images" image_files = [ f for f in os.listdir(image_path) if os.path.isfile(os.path.join(image_path, f)) and f.endswith(".png") ] self.icons = {} for image_file in image_files: self.icons[os.path.splitext( os.path.basename(image_file))[0]] = PhotoImage( file=os.path.join(image_path, image_file)) up_down_button_frame = Frame(main_frame) self.up_button = Button(up_down_button_frame, state="disabled", text="Move up", image=self.icons["gtk-go-up"], command=self.up_pressed) self.up_button.grid(column=0, row=0, sticky=(E)) self.down_button = Button(up_down_button_frame, state="disabled", text="Move down", image=self.icons["gtk-go-down"], command=self.down_pressed) self.down_button.grid(column=0, row=1, sticky=(E)) up_down_button_frame.grid(column=0, row=0, sticky=(E)) condition_list = Frame(main_frame, relief=SUNKEN, borderwidth=1) condition_list.grid(column=1, row=0, sticky=(N, S, E, W), padx=shared_pad_x, pady=shared_pad_y, columnspan=1) self.condition_list_scrollbar = Scrollbar(condition_list) self.state_listbox = Listbox(condition_list, relief=FLAT, exportselection=False, borderwidth=0, highlightthickness=0, yscrollcommand=self.state_listbox_scroll, activestyle="none") self.state_listbox.grid(column=0, row=0, padx=0, sticky=(N, S)) self.state_listbox.bind("<<ListboxSelect>>", self.state_listbox_selected) self.condition_listbox = Listbox( condition_list, relief=FLAT, exportselection=False, borderwidth=0, highlightthickness=0, yscrollcommand=self.condition_listbox_scroll, activestyle="none") self.condition_listbox.grid(column=1, row=0, sticky=(N, S, E, W), padx=0) self.condition_listbox.bind("<<ListboxSelect>>", self.condition_listbox_selected) self.execution_target_listbox = Listbox( condition_list, relief=FLAT, exportselection=False, borderwidth=0, highlightthickness=0, yscrollcommand=self.execution_target_listbox_scroll, activestyle="none") self.execution_target_listbox.grid(column=2, row=0, padx=0, sticky=(N, S)) self.execution_target_listbox.bind( "<<ListboxSelect>>", self.execution_target_listbox_selected) self.condition_list_scrollbar.grid(column=3, row=0, sticky=(N, S)) self.condition_list_scrollbar.config( command=self.condition_list_scrollbar_callback) condition_list.grid_rowconfigure(0, weight=1) for conditional in self.conditionals: self.state_listbox.insert(END, conditional[0]) self.condition_listbox.insert(END, conditional[1]) self.execution_target_listbox.insert(END, conditional[2]) #for i in range(5): # self.state_listbox.insert(END, "Foo %d"%i) # self.condition_listbox.insert(END, "Bar %d"%i) # self.execution_target_listbox.insert(END, "Baz %d"%i) if_label = Label(main_frame, text="If:", padx=10) if_label.grid(column=0, row=1, sticky=(N, E)) self.if_text_variable = StringVar() if_entry = Entry(main_frame, textvariable=self.if_text_variable) if_entry.grid( column=1, row=1, sticky=(E, W), padx=shared_pad_x, pady=shared_pad_y, ) then_label = Label(main_frame, text="Then:", padx=10) then_label.grid(column=0, row=2, sticky=(N, E)) self.then_entry = Text(main_frame) self.then_entry.grid( column=1, row=2, sticky=(N, S, E, W), padx=shared_pad_x, rowspan=2, ) option_frame = Frame(main_frame) execution_target_label = Label(option_frame, text="Execution target:") execution_target_label.grid(column=0, row=0, sticky=(N, W), pady=(10, shared_pad_y)) self.execution_target = StringVar() self.execution_target.set("Debugger") debugger_radiobutton = Radiobutton(option_frame, text="Debugger", variable=self.execution_target, value="Debugger") debugger_radiobutton.grid(column=0, row=1, sticky=(N, W)) python_radiobutton = Radiobutton(option_frame, text="Python", variable=self.execution_target, value="Python") python_radiobutton.grid(column=0, row=2, sticky=(N, W)) state_label = Label(option_frame, text="State") state_label.grid(column=0, row=3, sticky=(N, W), pady=(10, shared_pad_y)) self.active_checkbutton = StringVar() self.active_checkbutton.set("Enabled") active_checkbutton = Checkbutton(option_frame, text="Enabled", variable=self.active_checkbutton, onvalue="Enabled", offvalue="Disabled") active_checkbutton.grid(column=0, row=4, sticky=(N, W)) option_frame.grid(column=0, row=3, sticky=(N, S, E, W), pady=5) button_frame = Frame(main_frame) self.add_button = Button(button_frame, state="disabled", text="Add", image=self.icons["gtk-add"], compound=LEFT) self.add_button.grid(column=0, row=0, sticky=(E)) self.update_button = Button(button_frame, state="disabled", text="Update", image=self.icons["gtk-edit"], compound=LEFT) self.update_button.grid(column=1, row=0, sticky=(E)) self.delete_button = Button(button_frame, state="disabled", text="Delete", image=self.icons["gtk-remove"], compound=LEFT) self.delete_button.grid(column=2, row=0, sticky=(E)) button_frame.grid(column=0, row=4, columnspan=2, sticky=(E), padx=shared_pad_x, pady=shared_pad_y) close_frame = Frame(main_frame) close_button = Button(close_frame, text="Close", image=self.icons["gtk-close"], compound=LEFT, command=self.on_closing) close_button.grid(column=0, row=0, sticky=(S, E)) close_frame.grid(column=0, row=5, columnspan=2, sticky=(S, E), padx=shared_pad_x, pady=(15, shared_pad_y)) self.my_window.grid_columnconfigure(0, weight=1) self.my_window.grid_rowconfigure(0, weight=1) main_frame.grid_columnconfigure(1, weight=1) main_frame.grid_rowconfigure(0, weight=1) main_frame.grid_rowconfigure(2, weight=0) main_frame.grid_rowconfigure(3, weight=1) main_frame.grid_rowconfigure(4, weight=1) main_frame.grid_rowconfigure(5, weight=1) condition_list.grid_columnconfigure(1, weight=1) button_frame.grid_rowconfigure(0, weight=1) self.my_window.protocol("WM_DELETE_WINDOW", self.on_closing) def on_closing(self): if self.close_callback is not None: self.close_callback() self.my_window.destroy() def up_pressed(self): index = self.state_listbox.curselection()[0] state_current = self.state_listbox.get(index) condition_current = self.condition_listbox.get(index) execution_target_current = self.execution_target_listbox.get(index) self.state_listbox.delete(index) self.condition_listbox.delete(index) self.execution_target_listbox.delete(index) self.state_listbox.insert(index - 1, state_current) self.condition_listbox.insert(index - 1, condition_current) self.execution_target_listbox.insert(index - 1, execution_target_current) self.conditionals.insert(index - 1, self.conditionals.pop(index)) self.state_listbox.selection_set(index - 1) self.condition_listbox.selection_set(index - 1) self.execution_target_listbox.selection_set(index - 1) self.state_listbox.see(index - 1) if index - 1 == 0: self.up_button.config(state="disabled") self.down_button.config(state="normal") def down_pressed(self): index = self.state_listbox.curselection()[0] state_current = self.state_listbox.get(index) condition_current = self.condition_listbox.get(index) execution_target_current = self.execution_target_listbox.get(index) self.state_listbox.delete(index) self.condition_listbox.delete(index) self.execution_target_listbox.delete(index) self.state_listbox.insert(index + 1, state_current) self.condition_listbox.insert(index + 1, condition_current) self.execution_target_listbox.insert(index + 1, execution_target_current) self.conditionals.insert(index + 1, self.conditionals.pop(index)) self.state_listbox.selection_set(index + 1) self.condition_listbox.selection_set(index + 1) self.execution_target_listbox.selection_set(index + 1) self.state_listbox.see(index + 1) if index + 1 == self.state_listbox.size() - 1: self.down_button.config(state="disabled") self.up_button.config(state="normal") def condition_list_scrollbar_callback(self, *args): self.state_listbox.yview(*args) self.condition_listbox.yview(*args) self.execution_target_listbox.yview(*args) def state_listbox_scroll(self, *args): self.condition_listbox.yview_moveto(args[0]) self.execution_target_listbox.yview_moveto(args[0]) self.condition_list_scrollbar.set(*args) def condition_listbox_scroll(self, *args): self.state_listbox.yview_moveto(args[0]) self.execution_target_listbox.yview_moveto(args[0]) def execution_target_listbox_scroll(self, *args): self.state_listbox.yview_moveto(args[0]) self.condition_listbox.yview_moveto(args[0]) def any_listbox_selected(self): self.up_button.config(state="normal") self.down_button.config(state="normal") if self.state_listbox.curselection( )[0] == self.state_listbox.size() - 1: self.down_button.config(state="disabled") if self.state_listbox.curselection()[0] == 0: self.up_button.config(state="disabled") self.delete_button.config(state="normal") self.then_entry.delete("1.0", END) self.then_entry.insert( END, self.conditionals[self.state_listbox.curselection()[0]][3]) self.if_text_variable.set( self.conditionals[self.state_listbox.curselection()[0]][1]) self.execution_target.set( self.conditionals[self.state_listbox.curselection()[0]][2]) self.active_checkbutton.set( self.conditionals[self.state_listbox.curselection()[0]][0]) def state_listbox_selected(self, event): index = self.state_listbox.curselection()[0] try: self.condition_listbox.selection_clear( self.condition_listbox.curselection()[0]) except IndexError: pass self.condition_listbox.selection_set(index) try: self.execution_target_listbox.selection_clear( self.execution_target_listbox.curselection()[0]) except IndexError: pass self.execution_target_listbox.selection_set(index) self.any_listbox_selected() def condition_listbox_selected(self, event): index = self.condition_listbox.curselection()[0] try: self.state_listbox.selection_clear( self.state_listbox.curselection()[0]) except IndexError: pass self.state_listbox.selection_set(index) try: self.execution_target_listbox.selection_clear( self.execution_target_listbox.curselection()[0]) except IndexError: pass self.execution_target_listbox.selection_set(index) self.any_listbox_selected() def execution_target_listbox_selected(self, event): index = self.execution_target_listbox.curselection()[0] try: self.state_listbox.selection_clear( self.state_listbox.curselection()[0]) except IndexError: pass self.state_listbox.selection_set(index) try: self.condition_listbox.selection_clear( self.condition_listbox.curselection()[0]) except IndexError: pass self.condition_listbox.selection_set(index) self.any_listbox_selected()
class TimingReport(Toplevel): def __init__(self, app, printer, settings, logger, *arg): self.app = app self.printer = printer self.settings = settings self.logger = logger self.afterID = None self.selection = None if not self.app.printing: self.logger.logMsg("Report only available while printing") return Toplevel.__init__(self, app, *arg) self.title("Layer by Layer Timing") self.protocol("WM_DELETE_WINDOW", self.doCancel) fUL = Frame(self) fUL.grid(row=1, column=1, rowspan=2, padx=10) l = Label(fUL, text="Choose layer:") l.pack() lbf = Frame(fUL) lbf.pack() self.lbLayers = Listbox(lbf) self.lbLayers.bind("<ButtonRelease-1>", self.clickLayers) self.sb = Scrollbar(lbf, orient=VERTICAL) self.sb.config(command=self.lbLayers.yview) self.lbLayers.config(yscrollcommand=self.sb.set) self.sb.pack(side=RIGHT, fill=Y) self.lbLayers.pack(side=LEFT, fill=BOTH, expand=1) rbf = LabelFrame(fUL, text="Time Format") rbf.pack() self.rbvTimeFmt = StringVar() self.rbvTimeFmt.set(TIME_WALL) rb = Radiobutton(rbf, text="Wall time", variable=self.rbvTimeFmt, value=TIME_WALL, command=self.doTimeFormat) rb.pack(anchor=W) rb = Radiobutton(rbf, text="From start", variable=self.rbvTimeFmt, value=TIME_START, command=self.doTimeFormat) rb.pack(anchor=W) rb = Radiobutton(rbf, text="From now", variable=self.rbvTimeFmt, value=TIME_NOW, command=self.doTimeFormat) rb.pack(anchor=W) fUR = Frame(self) fUR.grid(row=1, column=2, rowspan=2, padx=10) row = 1 lf = LabelFrame(fUR, text="Print Times: ") lf.grid(row=row, column=1) l = Label(lf, text="Start: ", width=12, justify=RIGHT) l.grid(row=1, column=1, padx=10, sticky=E) self.timePStart = Label(lf, text="", anchor=W, justify=LEFT) self.timePStart.grid(row=1, column=3, padx=10) l = Label(lf, text="Elapsed: ", width=12, justify=RIGHT) l.grid(row=2, column=1, padx=10, sticky=E) self.timeElapsed = Label(lf, text="", anchor=W, justify=LEFT) self.timeElapsed.grid(row=2, column=3, padx=10) l = Label(lf, text="Current: ", width=12, justify=RIGHT) l.grid(row=3, column=1, padx=10, sticky=E) self.timeNow = Label(lf, text="", anchor=W, justify=LEFT) self.timeNow.grid(row=3, column=3, padx=10) row += 1 lf = LabelFrame(fUR, text="Layer Start Time: ") lf.grid(row=row, column=1) l = Label(lf, text="original: ", width=12, justify=RIGHT) l.grid(row=1, column=1, padx=10, sticky=E) self.timeOStart = Label(lf, text="", anchor=W, justify=LEFT) self.timeOStart.grid(row=1, column=2, padx=10) l = Label(lf, text="revised: ", width=12, justify=RIGHT) l.grid(row=2, column=1, padx=10, sticky=E) self.timeRStart = Label(lf, text="", anchor=W, justify=LEFT) self.timeRStart.grid(row=2, column=2, padx=10) row += 1 lf = LabelFrame(fUR, text="Time in Layer: ") lf.grid(row=row, column=1) l = Label(lf, text="original: ", width=12, justify=RIGHT) l.grid(row=1, column=2, padx=10, sticky=E) self.timeOLayer = Label(lf, text="", anchor=W, justify=LEFT) self.timeOLayer.grid(row=1, column=3, padx=10) l = Label(lf, text="revised: ", width=12, justify=RIGHT) l.grid(row=2, column=2, padx=10, sticky=E) self.timeRLayer = Label(lf, text="", anchor=W, justify=LEFT) self.timeRLayer.grid(row=2, column=3, padx=10) row += 1 lf = LabelFrame(fUR, text="Layer Finish Time: ") lf.grid(row=row, column=1) l = Label(lf, text="original: ", width=12, justify=RIGHT) l.grid(row=1, column=2, padx=10, sticky=E) self.timeOFinish = Label(lf, text="", anchor=W, justify=LEFT) self.timeOFinish.grid(row=1, column=3, padx=10) l = Label(lf, text="revised: ", width=12, justify=RIGHT) l.grid(row=2, column=2, padx=10, sticky=E) self.timeRFinish = Label(lf, text="", anchor=W, justify=LEFT) self.timeRFinish.grid(row=2, column=3, padx=10) self.ticker() def doTimeFormat(self): self.showValues(); def ticker(self): if self.refresh(): self.afterID = self.app.master.after(5000, self.ticker) def refresh(self): if not self.app.printing: self.doCancel() return False if self.selection != None: currentZ = str(self.layerZ[self.selection]) firstZ = self.layerZ[0] else: currentZ = "" firstZ = None self.now = time.time() self.elapsed = self.now - self.app.startTime foundLayer = False line = self.printer.queueindex thisLayerLine = 0 thisLayerTime = 0.0 thisLayerStart = 0.0 for i in self.app.timeLayers: if i[0] >= line: nextLayerLine = i[0] foundLayer = True break thisLayerLine = i[0] thisLayerTime = i[1] thisLayerStart = i[2] - thisLayerTime if not foundLayer: self.doCancel() return False pct = (line-thisLayerLine)/float(nextLayerLine-thisLayerLine) thisLayerTime *= pct self.ratio = (thisLayerStart+thisLayerTime)/float(self.elapsed) if self.ratio == 0: self.logger.logMsg("Invalid ratio calculated") self.doCancel() return False self.layertime = [] self.layerfinish = [] self.layerZ = [] self.selection = None skipped = 0 for i in self.app.timeLayers: if i[0] >= thisLayerLine: if currentZ == str(i[3]): self.selection = len(self.layerZ) self.layerZ.append(i[3]) self.layertime.append(i[1]) self.layerfinish.append(i[2]) else: skipped += 1 if self.selection == None: self.selection = 0 if len(self.layerZ) == 0: self.logger.logMsg("Unable to find any unprinted layers") self.doCancel() return False if self.layerZ[0] != firstZ: # new first layer - update things self.lbLayers.delete(0, END) ln = skipped for i in self.layerZ: ln += 1 s = "%8.3f (%d)" % (i, ln) self.lbLayers.insert(END, s) self.lbLayers.selection_set(self.selection) self.lbLayers.see(self.selection) s = time.strftime('%H:%M:%S', time.localtime(self.app.startTime)) self.timePStart.config(text=s) s = formatElapsed(self.elapsed) self.timeElapsed.config(text=s) s = time.strftime('%H:%M:%S', time.localtime(self.now)) self.timeNow.config(text=s) self.showValues() return True def doCancel(self): self.app.closeTimingReport() def cleanup(self): if self.afterID != None: self.app.after_cancel(self.afterID) def clickLayers(self, *arg): try: s = int(self.lbLayers.curselection()[0]) except: s = 0 self.selection = s; self.showValues() def showValues(self): mode = self.rbvTimeFmt.get() f = self.layerfinish[self.selection] frev = f/self.ratio l = self.layertime[self.selection] lrev = l/self.ratio s = f-l srev = frev - lrev if mode == TIME_START: so = formatElapsed(s) sr = formatElapsed(srev) fo = formatElapsed(f) fr = formatElapsed(frev) elif mode == TIME_NOW: if s < self.elapsed: so = '< now' else: so = formatElapsed(s-self.elapsed) if srev-self.elapsed < 0: sr = '< now' else: sr = formatElapsed(srev-self.elapsed) if f < self.elapsed: fo = '< now' else: fo = formatElapsed(f-self.elapsed) if frev-self.elapsed < 0: fr = '< now' else: fr = formatElapsed(frev-self.elapsed) elif mode == TIME_WALL: so = time.strftime('%H:%M:%S', time.localtime(s+self.app.startTime)) sr = time.strftime('%H:%M:%S', time.localtime(srev+self.app.startTime)) fo = time.strftime('%H:%M:%S', time.localtime(f+self.app.startTime)) fr = time.strftime('%H:%M:%S', time.localtime(frev+self.app.startTime)) self.timeOStart.config(text=so) self.timeRStart.config(text=sr) self.timeOFinish.config(text=fo) self.timeRFinish.config(text=fr) so = formatElapsed(l) sr = formatElapsed(lrev) self.timeOLayer.config(text=so) self.timeRLayer.config(text=sr)
class ResultList(Frame): """ Result List widget """ def __init__(self, master=None): Frame.__init__(self, master, padx=3, pady=3) self.columnconfigure(0, weight=1, minsize=50) self.columnconfigure(1, weight=1000) self.columnconfigure(2, weight=1, minsize=10) self.__createWidgets() self.show() def __createWidgets(self): self.lbl = Label(text="") self.lbl.grid(row=1, column=0, columnspan=2, in_=self) self.__hide_button = Button(text="Hide", command=self.hide) self.__hide_button.grid(row=0, column=0, columnspan=2, in_=self) self.__yScroll = Scrollbar(orient=VERTICAL) self.list = Listbox(yscrollcommand=self.__yScroll.set, selectmode=SINGLE) self.__yScroll.config(command=self.list.yview) def show(self): self.__hide_button.config(text="Hide", command=self.hide) self.list.grid(row=2, column=0, columnspan=2, sticky=N + S + E + W, in_=self) self.__yScroll.grid(row=2, column=2, sticky=W + N + S, in_=self) def hide(self): self.__hide_button.config(text="Show", command=self.show) self.list.grid_forget() self.__yScroll.grid_forget() def clear(self): self.list.delete(0, END) def fill(self, valList): self.clear() for v in valList: self.list.insert(END, v) self.list.see(0) self.select(0) def append(self, val): self.list.insert(END, val) self.list.see(END) def select(self, index=0): self.list.selection_set(index) def selected(self): return int(self.list.curselection()[0]) def width(self, width): self.list.config(width=width)