def loadplaylist(self): progress_dialog = tk.Toplevel() progress_dialog.title("Loading Playlist") bar = Progressbar(progress_dialog, orient="horizontal", length=500, value=0, mode="determinate") bar.grid(row=4, columnspan=2) thread = threading.Thread(target=self.threadedPlaylistLoad, args=(bar, progress_dialog)) thread.start()
class App(Tk): def __init__(self): Tk.__init__(self) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.progress_bar = None self.prog_win = None self.working_folder = None self.main_container = Frame( self, highlightbackground="black", highlightcolor="black", highlightthickness=1 ) self.frames = {} self.main_container.grid(row=0, column=0, sticky="nsew") self.main_container.grid_rowconfigure(0, weight=1) self.main_container.grid_columnconfigure(0, weight=1) for F in (Steps, DTType, UploadMul, AnnotateMul, PreDataMul, TrainingMul, Upload, Annotate, SingleDetection, SingleTracking, Mul_Object_Detection, References): frame = F(self.main_container, self) self.frames[F] = frame frame.grid(row=0, column=0, sticky="nsew") self.show_frame(Steps) def show_frame(self, frame): self.frames[frame].tkraise() self.frames[frame].event_generate("<<ShowFrame>>") def show_progress(self, start): if start: self.prog_win = Toplevel(self.main_container, padx=8, pady=8) self.prog_win.transient(self) self.prog_win.title('Working...') self.prog_win.resizable(0, 0) self.progress_bar = Progressbar(self.prog_win, orient=HORIZONTAL, mode='indeterminate', length=250, takefocus=True) self.progress_bar.grid() self.progress_bar.start() else: self.progress_bar.stop() self.prog_win.destroy()
def layout_gui(self): master = self.master s = Style() s.theme_use('default') s.configure('TProgressbar', thickness=50) helv36 = tkFont.Font(family='Helvetica', size=36, weight='bold') b = Button(master, text="Quit", command=self.quit, width=10, height=2) b['font'] = helv36 b.grid(row=0, column=0) pb = Progressbar(master, orient=VERTICAL, length=100, mode='determinate', style='TProgressbar') pb['value'] = 50 pb.grid(row=0, column=1)
class FrProgres(LabelFrame): def __init__(self, title, txt): LabelFrame.__init__(self, text=title) # Bar of global progress Label(self, text = 'Global progress').grid(row=1, column = 0) self.proglob = Progressbar(self, orient = HORIZONTAL, max = 50, length = 200, mode = 'determinate') # Bar of attributes progress Label(self, text = 'Attributes progress').grid(row=3, column = 0) self.progatt = Progressbar(self, orient = HORIZONTAL, max = 50, length = 200, mode = 'determinate') # Widgets placement self.proglob.grid(row=2, column = 0, sticky = N+S+W+E, padx = 2, pady = 2) self.progatt.grid(row=4, column = 0, sticky = N+S+W+E, padx = 2, pady = 2)
class Application(Frame): def run(self): appid = self.var_appid.get().strip() if len(appid) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入公众账号ID") return mch_id = self.var_mch_id.get().strip() if len(mch_id) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入商户号") return mch_key = self.var_mch_key.get().strip() if len(mch_key) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入商户密钥") return bill_date_from = self.var_bill_date_from.get().strip() if len(bill_date_from) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入开始日期") return path = self.var_path.get().strip() if len(path) == 0: tkMessageBox.showinfo(title=u"错误", message="请选择输出目录") return sub_mch_id = self.txt_sub_mch_id.get(1.0, END) if len(sub_mch_id) > 0: sub_mch_ids = list(set(sub_mch_id.split())) else: sub_mch_ids = [] # save settings config.save(appid, mch_id, mch_key, sub_mch_id, path) bill_date_to = self.var_bill_date_to.get().strip() if len(bill_date_to) == 0: bill_date_to = (datetime.now() + timedelta(days=-1)).strftime("%Y%m%d") s = datetime.strptime(bill_date_from, "%Y%m%d") e = datetime.strptime(bill_date_to, "%Y%m%d") def work_proc(self, path, s, e, sub_mch_ids, event): self.btn_run.config(state='disabled') days = (e - s).days + 1 max = days * (len(sub_mch_ids) if len(sub_mch_ids) > 0 else 1) self.prg_bar.config({'maximum': max}) while s <= e: if len(sub_mch_ids) > 0: for sub_mch_id in sub_mch_ids: r = download_bill(mch_key, appid, mch_id, s, sub_mch_id) self.save_bill(r, s, mch_id, sub_mch_id) self.prg_bar.step() else: r = download_bill(mch_key, appid, mch_id, s) self.save_bill(r, s, mch_id) self.prg_bar.step() s += timedelta(days=1) self.btn_run.config(state='normal') event.set() self.running = True work_thread = threading.Thread(target=work_proc, args=(self, path, s, e, sub_mch_ids, self.event)) work_thread.start() def save_bill(self, text, bill_date, mch_id, sub_mch_id=None): bill_date = bill_date.strftime("%Y%m%d") if text.startswith('<xml>'): f = '%s_%s_%s.xml' % ( bill_date, mch_id, sub_mch_id) if sub_mch_id else '%s_%s_.xml' % (bill_date, mch_id) else: f = '%s_%s_%s.csv' % ( bill_date, mch_id, sub_mch_id) if sub_mch_id else '%s_%s_.csv' % (bill_date, mch_id) fullname = os.path.join(self.var_path.get().strip(), f) with open(fullname, 'wb') as csv: csv.write(text) def select_path(self): self.var_path.set(tkFileDialog.askdirectory()) def createWidgets(self, settings): row = 0 # 公众号ID self.lbl_appid = Label(self, text=u"公众帐号ID", fg='red') self.lbl_appid.grid(column=0, row=row, sticky=(E, N)) self.var_appid = StringVar(self, value=settings.get('appid')) self.txt_appid = Entry(self, textvariable=self.var_appid, width=60, font=self.font) self.txt_appid.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 商户号 self.lbl_mch_id = Label(self, text=u"商户号", fg='red') self.lbl_mch_id.grid(column=0, row=row, sticky=(E, N)) self.var_mch_id = StringVar(self, value=settings.get('mch_id')) self.txt_mch_id = Entry(self, textvariable=self.var_mch_id, width=60, font=self.font) self.txt_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 商户密钥 self.lbl_mch_key = Label(self, text=u"商户密钥", fg='red') self.lbl_mch_key.grid(column=0, row=row, sticky=(E, N)) self.var_mch_key = StringVar(self, value=settings.get('mch_key')) self.txt_mch_key = Entry(self, textvariable=self.var_mch_key, width=60, font=self.font) self.txt_mch_key.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 子商户号 self.lbl_sub_mch_id = Label(self, text=u"子商户号") self.lbl_sub_mch_id.grid(column=0, row=row, sticky=(E, N)) self.txt_sub_mch_id = Text(self, height=5, width=60, font=self.font) if settings.get('sub_mch_id'): self.txt_sub_mch_id.insert(END, settings.get('sub_mch_id')) self.txt_sub_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 开始日期 self.lbl_bill_date_from = Label(self, text=u"开始日期", fg='red') self.lbl_bill_date_from.grid(column=0, row=row, sticky=(E, N)) self.var_bill_date_from = StringVar() self.var_bill_date_from.set( (datetime.now() - timedelta(days=1)).strftime("%Y%m%d")) self.txt_bill_date_from = Entry(self, width=8, textvariable=self.var_bill_date_from, font=self.font) self.txt_bill_date_from.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 结束日期 self.lbl_bill_date_to = Label(self, text=u"结束日期") self.lbl_bill_date_to.grid(column=0, row=row, sticky=(E, N)) self.var_bill_date_to = StringVar() self.txt_bill_date_to = Entry(self, width=8, textvariable=self.var_bill_date_to, font=self.font) self.txt_bill_date_to.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 输出目录 self.lbl_path = Label(self, text=u"输出目录", fg='red') self.lbl_path.grid(column=0, row=row, sticky=(E, N)) path = settings.get('path') self.var_path = StringVar( self, value=path if path else os.path.dirname(os.path.abspath(cur_path))) self.txt_path = Entry(self, textvariable=self.var_path, width=55, font=self.font) self.txt_path.grid(column=1, row=row, sticky=(W, N, E)) self.btn_select_path = Button(self, text=u"...", command=self.select_path) self.btn_select_path.grid(column=2, row=row, sticky=(E)) row += 1 # 进度条 self.prg_bar = Progressbar(self) self.prg_bar.grid(column=0, row=row, columnspan=3, sticky=(W, E), pady=(10, 0)) row += 1 # 执行按钮 buttonFrame = Frame(self) buttonFrame.grid(column=0, row=row, columnspan=3, pady=(15, 0), sticky=(W, E)) self.btn_run = Button(buttonFrame, width=20, text=u"下载", fg='blue', command=self.run) self.btn_run.pack() def loop(self): if self.running and self.event.is_set(): self.running = False self.event.clear() tkMessageBox.showinfo(title=u"成功", message="账单下载结束") subprocess.call('explorer "%s"' % self.var_path.get().strip().replace('/', '\\'), shell=True) self.master.after(100, self.loop) def __init__(self, master=None): Frame.__init__(self, master) self.font = tkFont.nametofont("TkDefaultFont") self.font.configure(family='MS Gothic', size=9) self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=10) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) settings = config.load() self.createWidgets(settings) self.event = threading.Event() self.running = False self.loop()
class JobList(Frame): # NOTE: job_params contains information about a Job in the Joblist # NOTE: plot_args contains information about plotting information, which occurs after the jobs have been and the data files have been created def __init__(self, parent=None, **kwargs): Frame.__init__(self, parent) self.parent = parent self.job_list_yscroll = Scrollbar(self, orient=Tkinter.VERTICAL) self.job_list_xscroll = Scrollbar(self, orient=Tkinter.HORIZONTAL) self.job_list = Listbox(self, xscrollcommand=self.job_list_xscroll, yscrollcommand=self.job_list_yscroll) self.job_list_xscroll['command'] = self.job_list.xview self.job_list_yscroll['command'] = self.job_list.yview self.new_job_frame = Frame(self) add_icon_filename = kwargs['add_icon_filename'] if 'add_icon_filename' in kwargs else None if add_icon_filename == None: self.add_job_button = Button(self.new_job_frame, text='Add Job', command=self.on_add) else: add_icon = PhotoImage(file=add_icon_filename) self.add_job_button = Button(self.new_job_frame, text='Add Job', compound='bottom', image=add_icon, command=self.on_add) self.remove_job_button = Button(self.new_job_frame, text='Remove Job', command=self.on_remove) self.progress_frame = Frame(self) self.progress_value = Tkinter.IntVar() self.progress_bar = Progressbar(self.progress_frame, variable=self.progress_value) self.button_frame = Frame(self) self.process_button = ProcessButton(parent=self.button_frame, start_jobs=self.start_jobs) self.quit_button = QuitButton(parent=self.button_frame, close_other_windows=self.close_top_level_windows) self.run_job = kwargs['run_job'] if 'run_job' in kwargs else None self.create_plots = kwargs['create_plots'] if 'create_plots' in kwargs else None self.log_filename = kwargs['log_filename'] if 'log_filename' in kwargs else None self.bind('<<AskToClearJobs>>', self.ask_to_clear_jobs) self.bind('<<AskToPlotGraphs>>', self.ask_to_plot_graphs) self.bind('<<CreatePlotGUI>>', self.create_plot_gui) self.parent.bind('<ButtonPress>', self.on_press) self.parent.bind('<Configure>', self.on_resize) self.reinit_variables() self.top_level_windows = list() # NOTE: Because there seems to be an issue resizing child widgets when the top level (Tk) widget is being resized, # the resize option will be disabled for this window self.parent.resizable(width=False, height=False) self.lift() def reinit_variables(self): self.job_params = dict() self.last_job_id = -1 self.job_outcomes = list() self.plot_args = list() self.on_button = False def add_job_params(self, input_args): self.job_params = input_args # Add each element to the job list for job in self.job_params: self.add_job(job) def add_job(self, job): try: index_end = job['input_directory'].rindex('/') index_start = job['input_directory'].rindex('/', 0, index_end) input_directory_text = job['input_directory'] list_text = 'Job ' + str(job['job_id']) + ' \'' + input_directory_text + '\'' if job['start'] != None: list_text += ' ' + str(job['start']) if job['end'] != None: list_text += ' to' if job['end'] != None: list_text += ' ' + str(job['end']) if job['job_id'] > self.last_job_id: self.last_job_id = job['job_id'] self.job_list.insert(Tkinter.END, list_text) # Add the list text to the job params as an optional parameter to read later to display in a future Graph GUI (or for any other useful purpose) job['list_text'] = list_text # The line number is used wrt the GUI to indicate which job in the job list is being currently executed. job['line_number'] = self.job_list.size() - 1 #print str(job['line_number']) self.job_params[job['job_id']] = job except KeyError as ke: # Should show some error message indicating that there is a problem. pass #print str(self.job_params) #print 'Added Job ' + str(job['job_id']) def ask_to_clear_jobs(self, event): for job in self.job_params.itervalues(): line_number = job['line_number'] self.job_list.itemconfig(line_number, foreground='black') # Update parent to refresh widget appearance self.parent.update() # Reactivate process button self.process_button.config(state = Tkinter.NORMAL) # Note: Display a pop-up that tells the user that the job is done and asks if the job list should be cleared. clearList = msg.askyesno(title='Jobs Finished', message='All jobs have been completed. Would you like to clear the job list?', master=self) if clearList: self.clear_list() def ask_to_plot_graphs(self, event): # TODO: Add a dialog that also asks to create a graph of the 'Other Type Of Plot' plotGraphs = msg.askyesno(title='Plot Graphs', message='Create plots of data?', master=self) if not plotGraphs: return # TODO: Iterate through the jobs to display to the user an interface that asks if they want to graphs of the outputs if self.create_plots != None: output_files_list = list() for job_outcome in self.job_outcomes: for output_outcomes in job_outcome[2]: (station, output_directory, output_files) = output_outcomes for output_files_tuple in output_files: for output_file_tuple in output_files_tuple: (output_file, output_file_success) = output_file_tuple if output_file_success: # If there is a list text variable (the 4th (or 3rd by 0 based index) variable), then add it to our output list if len(job_outcome) == 4: output_files_list.append([output_file, job_outcome[3]]) else: output_files_list.append([output_file]) plots_thread = PlotsThread(self.create_plots, output_files_list, self) plots_thread.start() def add_plot(self, args=dict()): self.plot_args.append(args) def finished_adding_plots(self): self.event_generate('<<CreatePlotGUI>>', when='tail') def create_plot_gui(self, event): # TODO: This should be replaced with a new window that allows the user to drag and drop the icons from one frame to another graph_names = list() for args in self.plot_args: graph_name = args['output_file'] graph_names.append(graph_name) dnd_graphs_frame = Dnd.createFrame(self, 'Drag and Drop Output Plots', graph_names, self.finish_creating_plot_gui) # This is the entry point for the def finish_creating_plot_gui(self, plot_labels): graph_count = 1 for plot_label in plot_labels: for args in self.plot_args: #print 'Looking in ' + args['plot_title'] + ' for ' + plot_label #print 'The plot label is: ' + plot_label #print 'The output file is: ' + args['output_file'] if plot_label == args['output_file']: #print 'Creating graph ' + str(graph_count) graph_count += 1 graph_window = ModelRunnerGraphGUI.GraphWindow(parent=self, title=args['window_title'], df=args['df'], plot=args['plot'], plot_title=args['plot_title'], y_label=args['y_label'], log_filename=self.log_filename) graph_window.set_grid() self.top_level_windows.append(graph_window) #print 'Creating plot GUI # Have to clear out list here instead of clear_list because clear_list() removes plot_args before this method has a chance to read # them and create the appropriate plot graph windows self.reinit_variables() # Clear all the elements in the list def clear_list(self): # Save plot args because they are need later in this run plot_args = self.plot_args self.reinit_variables() # Restore the plot args self.plot_args = plot_args self.job_list.delete(0, self.job_list.size()) self.progress_value.set(0) # Update parent to refresh widget appearance self.parent.update() def on_add(self): single_job = JobParameters(parent=self.parent, beginning_year=1950, ending_year=2100, job_id=self.last_job_id + 1, entry=self) single_job.set_grid() def on_remove(self): selection = self.job_list.curselection() for line_number in selection: line_text = self.job_list.get(line_number) job_id = int(line_text[4:line_text.index(' ', 4)]) job = self.job_params.pop(job_id) self.job_list.delete(line_number) print 'Removed Job ' + str(job['job_id']) # Fix line number for line_number in range(self.job_list.size()): line_text = self.job_list.get(line_number) job_id = int(line_text[4:line_text.index(' ', 4)]) #print 'Job ' + str(job_id) + ' is now on line ' + str(line_number) self.job_params[job_id]['line_number'] = line_number def set_grid(self): self.grid(sticky=Tkinter.N + Tkinter.S + Tkinter.W + Tkinter.E, padx=4, pady=4) self.columnconfigure(0, minsize=600) self.rowconfigure(0, minsize=300) self.job_list.grid(row=0, column=0, sticky=Tkinter.N + Tkinter.S + Tkinter.E + Tkinter.W) self.job_list_yscroll.grid(row=0, column=1, sticky=Tkinter.N + Tkinter.S + Tkinter.W) self.job_list_xscroll.grid(row=1, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N) self.new_job_frame.grid(row=2, column=0, pady=3, sticky=Tkinter.W) self.remove_job_button.grid(row=0, column=0) self.add_job_button.grid(row=0, column=1) self.progress_frame.grid(row=3, column=0, pady=3) self.progress_frame.columnconfigure(0, minsize=600) self.progress_bar.grid(row=0, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S) self.button_frame.grid(row=4, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S) self.button_frame.columnconfigure(0, minsize=300) self.button_frame.columnconfigure(1, minsize=300) self.process_button.pack(side=Tkinter.RIGHT) self.quit_button.pack(side=Tkinter.RIGHT) def start_jobs(self): # If there are no queued jobs then simply return if len(self.job_params) == 0 or len(self.job_list.get(0)) == 0: return # Deactivate the process button self.process_button.config(state = Tkinter.DISABLED) # Initialize the progress bar self.progress_value.set(0) # Update parent to refresh widget appearance self.parent.update() # Start process thread jobs_thread = JobsThread(self.job_params, self.run_job, self.on_update, self.on_resume) jobs_thread.start() self['cursor'] = 'wait' def on_update(self, status, line_number, step): if status == 'init': self.job_list.itemconfig(line_number, foreground='green') self.job_list.activate(line_number) elif status == 'success': self.job_list.itemconfig(line_number, foreground='blue') elif status == 'fail': self.job_list.itemconfig(line_number, foreground='red') self.progress_value.set(step) # Update parent to refresh widget appearance self.parent.update() def on_resume(self, job_outcomes=list()): self.progress_value.set(100) self.job_outcomes = job_outcomes self.event_generate('<<AskToClearJobs>>', when='tail') self.event_generate('<<AskToPlotGraphs>>', when='tail') self['cursor'] = 'arrow' def close_top_level_windows(self): #print 'Closing other top level windows' for top_level_window in self.top_level_windows: if top_level_window: top_level_window.withdraw() top_level_window.destroy() def notify_of_close(self, top_level_window): if top_level_window in self.top_level_windows: #print 'Removing top level window' self.top_level_windows.remove(top_level_window) def on_press(self, event): self.on_button = True self.release_pattern = "<B%d-ButtonRelease-%d>" % (event.num, event.num) self.parent.bind(self.release_pattern, self.on_release) def on_release(self, event): self.on_button = False def on_resize(self, event): self.parent.lift() if self.on_button: self.set_grid() def on_close(self): self.plot_args = list() self.withdraw() self.destroy()
class MPExportApp(object): """docstring for MPExportApp""" def __init__(self, master): super(MPExportApp, self).__init__() self.master = master self.export_type = StringVar() master.columnconfigure(1, weight=1) export_type_label = Label(master, text="Data Type: ") export_type_label.grid(row=0, column=0, sticky=E) radio_group_frame = Frame(master) radio_group_frame.grid(row=0, column=1, sticky=W) self.events_radio_button = Radiobutton(radio_group_frame, text='Events', value='events', variable=self.export_type, command=self.radio_button_changed) self.events_radio_button.select() self.events_radio_button.grid(row=0, column=0) self.people_radio_button = Radiobutton(radio_group_frame, text='People', value='people', variable=self.export_type, command=self.radio_button_changed) self.people_radio_button.grid(row=0, column=1) api_key_label = Label(master, text="API Key: ") api_key_label.grid(row=1, column=0, sticky=E) self.api_key_entry = Entry(master) self.api_key_entry.grid(row=1, column=1, columnspan=2, sticky=(E,W)) api_secret_label = Label(master, text="API Secret: ") api_secret_label.grid(row=2, column=0, sticky=E) self.api_secret_entry = Entry(master) self.api_secret_entry.grid(row=2, column=1, columnspan=2, sticky=(E, W)) self.project_token_label = Label(master, text="Project Token: ", state=DISABLED) self.project_token_label.grid(row=3, column=0, sticky=E) self.project_token_entry = Entry(master, state=DISABLED) self.project_token_entry.grid(row=3, column=1, columnspan=2, sticky=(E, W)) self.events_label = Label(master, text="Events: ") self.events_label.grid(row=4, column=0, sticky=E) self.events_entry = Entry(master) self.events_entry.insert(0, 'Event A,Event B,Event C') self.events_entry.bind('<FocusIn>', partial(self.clear_placeholder_text, self.events_entry)) self.events_entry.grid(row=4, column=1, columnspan=2, sticky=(E, W)) where_label = Label(master, text="Where: ") where_label.grid(row=5, column=0, sticky=E) self.where_entry = Entry(master) self.where_entry.grid(row=5, column=1, columnspan=2, sticky=(E, W)) self.from_date_label = Label(master, text="From Date: ") self.from_date_label.grid(row=6, column=0, sticky=E) self.from_date_entry = Entry(master) self.from_date_entry.insert(0, 'YYYY-MM-DD') self.from_date_entry.bind('<FocusIn>', partial(self.clear_placeholder_text, self.from_date_entry)) self.from_date_entry.grid(row=6, column=1, columnspan=2, sticky=(E, W)) self.to_date_label = Label(master, text="To Date: ") self.to_date_label.grid(row=7, column=0, sticky=E) self.to_date_entry = Entry(master) self.to_date_entry.insert(0, 'YYYY-MM-DD') self.to_date_entry.bind('<FocusIn>', partial(self.clear_placeholder_text, self.to_date_entry)) self.to_date_entry.grid(row=7, column=1, columnspan=2, sticky=(E, W)) export_button = Button(master, text="EXPORT", fg="green", command=self.export) export_button.grid(row=8, column=1, sticky=(E, W)) self.delete_button = Button(master, text="DELETE", fg='red', state=DISABLED, command=lambda: threading.Thread(target=self.delete_people).start()) self.delete_button.grid(row=9, column=1, sticky=(E, W)) self.progress_bar = Progressbar(master) self.progress_bar_value = IntVar() self.progress_bar.config(mode='determinate', orient='horizontal', variable=self.progress_bar_value) self.progress_bar.grid(row=10, column=0, columnspan=3, sticky=(E, W)) def clear_placeholder_text(self, entry, event): entry_text = entry.get() if entry_text == 'Event A,Event B,Event C' or entry_text == 'YYYY-MM-DD': entry.delete(0, END) def make_events_string(self, events): events = events.replace(', ', ',') events = events.split(',') events_string = '[' for x in range(0, len(events)): events_string += '"' + events[x] + '"' if x != len(events)-1: events_string += ',' else: events_string += ']' return events_string def radio_button_changed(self): if self.export_type.get() == 'people': self.project_token_label.config(state=NORMAL) self.project_token_entry.config(state=NORMAL) self.events_label.config(state=DISABLED) self.events_entry.config(state=DISABLED) self.from_date_label.config(state=DISABLED) self.from_date_entry.config(state=DISABLED) self.to_date_label.config(state=DISABLED) self.to_date_entry.config(state=DISABLED) self.delete_button.config(state=NORMAL) elif self.export_type.get() == 'events': self.project_token_label.config(state=DISABLED) self.project_token_entry.config(state=DISABLED) self.events_label.config(state=NORMAL) self.events_entry.config(state=NORMAL) self.from_date_label.config(state=NORMAL) self.from_date_entry.config(state=NORMAL) self.to_date_label.config(state=NORMAL) self.to_date_entry.config(state=NORMAL) self.delete_button.config(state=DISABLED) def export(self): if self.api_key_entry.get() == '': print 'API Key Required!' return elif self.api_secret_entry.get() == '': print 'API Secret Required!' return self.output_dir = askdirectory(title='Choose output directory', mustexist=True, parent=self.master) if not self.output_dir: return print 'Output directory is ' + self.output_dir self.progress_bar.start() if self.export_type.get() == 'people': self.export_thread = threading.Thread(target=self.export_people) elif self.export_type.get() == 'events': self.export_thread = threading.Thread(target=self.export_events) self.export_thread.start() def export_people(self): mixpanel = Mixpanel( api_key=self.api_key_entry.get(), api_secret=self.api_secret_entry.get(), endpoint=API_ENDPOINT ) '''Here is the place to define your selector to target only the users that you're after''' '''parameters = {'selector':'(properties["$email"] == "Albany") or (properties["$city"] == "Alexandria")'}''' selector = self.where_entry.get() parameters = {} if selector: parameters['selector'] = selector response = mixpanel.request(['engage'], parameters) try: result = '\nAPI ERROR! - ' + json.loads(response)['error'] + '\n' if result: print result self.progress_bar.stop() self.progress_bar_value.set(0) return except KeyError, e: pass parameters['session_id'] = json.loads(response)['session_id'] parameters['page'] = 0 global_total = json.loads(response)['total'] if global_total == 0: print 'Query returned 0 profiles!' self.progress_bar.stop() self.progress_bar_value.set(0) return print "Session id is %s \n" % parameters['session_id'] print "Here are the # of people %d" % global_total filename = self.output_dir + "/people_export_"+str(int(time.time())) jsonfile = filename + ".json" csvfile = filename + ".csv" has_results = True total = 0 with tempfile.NamedTemporaryFile(delete=False) as temp: with open(jsonfile, 'w') as j: j.write('[') while has_results: responser = json.loads(response)['results'] response_count = len(responser) total += response_count has_results = response_count == 1000 i = 0 for data in responser: dump = json.dumps(data) temp.write(dump + '\n') j.write(dump) i += 1 if i != response_count: j.write(',') print "%d / %d" % (total,global_total) parameters['page'] += 1 if has_results: j.write(',') response = mixpanel.request(['engage'], parameters) else: j.write(']') print 'JSON saved to ' + j.name j.close() mixpanel.people_json_to_csv(csvfile, temp.name) temp.close() os.remove(temp.name) self.progress_bar.stop() self.progress_bar_value.set(0)
class TkApplicationWindow(AbstractApplicationWindow): def __init__(self, app): self.root = Tk() self.root.title("Llia") self.root.config(background=factory.bg()) super(TkApplicationWindow, self).__init__(app, self.root) self.root.withdraw() if app.config()["enable-splash"]: splash = TkSplashWindow(self.root, app) self.root.deiconify() self.root.protocol("WM_DELETE_WINDOW", self.exit_app) self.llia_graph = None self._main = layout.BorderFrame(self.root) self._main.config(background=factory.bg()) self._main.pack(anchor="nw", expand=True, fill=BOTH) self._progressbar = None self._init_status_panel() self._init_menu() self._init_center_frame(self._main.center) self.root.minsize(width=665, height=375) self.group_windows = [] self.add_synth_group() self._scene_filename = "" def _init_status_panel(self): south = self._main.south south.configure(padx=4, pady=4) self._lab_status = factory.label(south, "", modal=False) b_panic = factory.panic_button(south) b_down = factory.button(south, "-") b_up = factory.button(south, "+") b_panic.grid(row=0, column=0) self._progressbar = Progressbar(south,mode="indeterminate") self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8) self._lab_status.grid(row=0,column=4, sticky='w') south.config(background=factory.bg()) b_down.configure(command=lambda: self.root.lower()) b_up.configure(command=lambda: self.root.lift()) self.update_progressbar(100, 0) def _tab_change_callback(self, event): self.llia_graph.sync() def _init_center_frame(self, master): nb = ttk.Notebook(master) nb.pack(expand=True, fill="both") frame_synths = layout.FlowGrid(nb, 6) frame_efx = layout.FlowGrid(nb, 6) frame_controllers = layout.FlowGrid(nb, 6) self.llia_graph = LliaGraph(nb, self.app) nb.add(frame_synths, text = "Synths") nb.add(frame_efx, text = "Effects") nb.add(frame_controllers, text = "Controllers") nb.add(self.llia_graph, text="Graph") nb.bind("<Button-1>", self._tab_change_callback) def display_info_callback(event): sp = event.widget.synth_spec msg = "%s: %s" % (sp["format"],sp["description"]) self.status(msg) def clear_info_callback(*_): self.status("") for st in con.SYNTH_TYPES: sp = specs[st] ttp = "Add %s Synthesizer (%s)" % (st, sp["description"]) b = factory.logo_button(frame_synths, st, ttip=ttp) b.synth_spec = sp b.bind("<Button-1>", self._show_add_synth_dialog) b.bind("<Enter>", display_info_callback) b.bind("<Leave>", clear_info_callback) frame_synths.add(b) for st in con.EFFECT_TYPES: sp = specs[st] ttp = "Add %s Effect (%s)" % (st, sp["description"]) b = factory.logo_button(frame_efx, st, ttip=ttp) b.synth_spec = sp b.bind("<Button-1>", self._show_add_efx_dialog) b.bind("<Enter>", display_info_callback) b.bind("<Leave>", clear_info_callback) frame_efx.add(b) for st in con.CONTROLLER_SYNTH_TYPES: sp = specs[st] ttp = "Add %s Effect (%s)" % (st, sp["description"]) b = factory.logo_button(frame_controllers, st, ttip=ttp) b.synth_spec = sp b.bind("<Button-1>", self._show_add_controller_dialog) b.bind("<Enter>", display_info_callback) b.bind("<Leave>", clear_info_callback) frame_controllers.add(b) @staticmethod def menu(master): m = Menu(master, tearoff=0) m.config(background=factory.bg(), foreground=factory.fg()) return m def _init_menu(self): main_menu = self.menu(self.root) self.root.config(menu=main_menu) file_menu = self.menu(main_menu) osc_menu = self.menu(main_menu) midi_menu = self.menu(main_menu) bus_menu = self.menu(main_menu) #buffer_menu = self.menu(main_menu) tune_menu = self.menu(main_menu) help_menu = self.menu(main_menu) main_menu.add_cascade(label="File", menu=file_menu) main_menu.add_cascade(label="OSC", menu=osc_menu) main_menu.add_cascade(label="MIDI", menu=midi_menu) #main_menu.add_cascade(label="Buses", menu=bus_menu) #main_menu.add_cascade(label="Buffers", menu=buffer_menu) #main_menu.add_cascade(label="Tune", menu=tune_menu) #main_menu.add_cascade(label="Help", menu=help_menu) self._init_file_menu(file_menu) self._init_osc_menu(osc_menu) self._init_midi_menu(midi_menu) self._init_bus_menu(bus_menu) #self._init_buffer_menu(buffer_menu) self._init_tune_menu(tune_menu) self._init_help_menu(help_menu) def _init_file_menu(self, fmenu): fmenu.add_command(label="Save Scene", command = self.save_scene) fmenu.add_command(label="Load Scene", command = self.load_scene) fmenu.add_separator() fmenu.add_command(label="Lliascript (Legacy)", command = self.show_history_editor) fmenu.add_separator() fmenu.add_command(label="New Synth Group", command = self._add_synth_group) fmenu.add_separator() fmenu.add_command(label="Restart", command = self._interactive_tabula_rasa) fmenu.add_command(label="Quit", command = self.exit_app) def _init_osc_menu(self, iomenu): iomenu.add_command(label="Ping", command = self.ping_global) iomenu.add_command(label="Dump", command = self.app.proxy.dump) iomenu.add_command(label="Toggle OSC Trace", command = self.toggle_osc_trace) def _init_midi_menu(self, mmenu): map_menu = self.menu(mmenu) mmenu.add_command(label = "Channel Names", command = self.show_channel_name_dialog) mmenu.add_command(label = "Controller Names", command = self.show_controller_name_dialog) mmenu.add_cascade(label = "MIDI Maps", menu = map_menu) mmenu.add_command(label = "Toggle MIDI Input Trace", command = self.toggle_midi_input_trace) mmenu.add_command(label = "Toggle MIDI Output Trace", command = self.toggle_midi_output_trace) mmenu.add_command(label = "Toggle Program Pretty Printer", command = self.toggle_program_pretty_printer) def _init_bus_menu(self, bmenu): bmenu.add_command(label="Audio", command=self.show_audiobus_dialog) bmenu.add_command(label="Control", command=self.show_controlbus_dialog) # def _init_buffer_menu(self, bmenu): # bmenu.add_command(label="View Buffers", command=self.show_bufferlist_dialog) def _init_tune_menu(self, tmenu): tmenu.add_command(label = "FIX ME: Nothing to see here") def _init_help_menu(self, hmenu): pass def exit_gui(self): try: self.root.destroy() except: pass def confirm_exit(self): return tkMessageBox.askyesno("Exit Llia", "Exit Llia?") def exit_app(self): self.app.exit_() def as_widget(self): return self.root def status(self, msg): self._lab_status.config(text=str(msg)) def warning(self, msg): msg = "WARNING: %s" % msg self._lab_status.config(text=msg) def clear_status(self): self.status("") def start_gui_loop(self): self.root.mainloop() def show_about_dialog(self): from llia.gui.tk.tk_about_dialog import TkAboutDialog dialog = TkAboutDialog(self.root, self.app) self.root.wait_window(dialog) def display_help(self, topic=None): pass def show_history_editor(self): from llia.gui.tk.tk_history import TkHistoryEditor dialog = TkHistoryEditor(self.root, self.app) self.root.wait_window(dialog) def ping_global(self): try: rs = self.app.proxy.ping() if rs: self.status("Ping OK") else: self.warning("Ping Error") except LliaPingError as err: self.warning(err.message) def toggle_osc_trace(self): LliaProxy.trace = not LliaProxy.trace if LliaProxy.trace: self.status("OSC transmission trace enabled") else: self.status("OSC transmission trace disabled") def show_channel_name_dialog(self): from llia.gui.tk.tk_channel_name_editor import TkChannelNameEditor dialog = TkChannelNameEditor(self.root, self.app) self.root.wait_window(dialog) def show_controller_name_dialog(self): from llia.gui.tk.tk_controller_name_editor import TkControllerNameEditor dialog = TkControllerNameEditor(self.root, self.app) self.root.wait_window(dialog) def toggle_midi_input_trace(self): flag = not self.app.midi_in_trace self.app.midi_in_trace = flag self.app.midi_receiver.enable_trace(flag) if flag: self.status("MIDI input trace enabled") else: self.status("MIDI output trace disabled") def toggle_midi_output_trace(self): self.status("MIDI output not available") # FIX ME def toggle_program_pretty_printer(self): self.app.pp_enabled = not self.app.pp_enabled if self.app.pp_enabled: self.status("Pretty printer enabled") else: self.status("Pretty printer disabled") def show_audiobus_dialog(self): from llia.gui.tk.tk_audiobus_editor import TkAudiobusEditor dialog = TkAudiobusEditor(self.root, self.app) self.root.wait_window(dialog) def show_controlbus_dialog(self): from llia.gui.tk.tk_controlbus_editor import TkControlbusEditor dialog = TkControlbusEditor(self.root, self.app) self.root.wait_window(dialog) # def show_bufferlist_dialog(self): # from llia.gui.tk.tk_buffer_info import TkBufferListDialog # dialog = TkBufferListDialog(self.root, self.app) # self.root.wait_window(dialog) def _show_add_synth_dialog(self, event): w = event.widget st = w.config()["text"][-1] dialog = TkAddSynthDialog(self.root, self.app, st, False) self.root.wait_window(dialog) def _show_add_efx_dialog(self, event): w = event.widget st = w.config()["text"][-1] dialog = TkAddSynthDialog(self.root, self.app, st, is_efx=True, is_controller=False) self.root.wait_window(dialog) def _show_add_controller_dialog(self, event): w = event.widget st = w.config()["text"][-1] dialog = TkAddSynthDialog(self.root, self.app, st, is_efx=False, is_controller=True) self.root.wait_window(dialog) def _add_synth_group(self): sh = self.app.ls_parser.synthhelper sh.new_group() def add_synth_group(self, name=None): gw = GroupWindow(self.app, self.root, name) # gw.transient(self.root) # If executed keeps main app window behind all other windows. self.group_windows.append(gw) self.status("Added new Synth Group Window") return gw def display_synth_editor(self, sid): try: swin = self[sid] grpid = swin.group_index grp = self.group_windows[grpid] #grp.deiconify() grp.show_synth_editor(sid) except (KeyError, IndexError): msg = "Can not find editor for %s" % sid self.warning(msg) def update_progressbar(self, count, value): self._progressbar.config(mode="determinate", maximum=count) self._progressbar.step() self.root.update_idletasks() def busy(self, flag, message=""): if message: self.status(message) self._progressbar.config(mode="indeterminate") if flag: self._progressbar.grid(row=0, column=PROGRESSBAR_COLUMN, sticky='w', padx=8) self._progressbar.start() else: self._progressbar.stop() # self._progressbar.grid_remove() self.root.update_idletasks() def save_scene(self, *_): options = {'defaultextension' : '.llia', 'filetypes' : [('Llia Scenes', '*.llia'), ('all files', '*')], 'initialfile' : self._scene_filename, 'parent' : self.root, 'title' : "Save Llia Scene"} filename = tkFileDialog.asksaveasfilename(**options) if filename: try: self.app.ls_parser.save_scene(filename) self._scene_filename = filename self.status("Scene saved as '%s'" % filename) except Exception as ex: self.warning(ex.message) else: self.status("Scene save canceld") def load_scene(self, *_): options = {'defaultextension' : '.llia', 'filetypes' : [('Llia Scenes', '*.llia'), ('all files', '*')], 'initialfile' : self._scene_filename, 'parent' : self.root, 'title' : "Load Llia Scene"} filename = tkFileDialog.askopenfilename(**options) if filename: try: self.app.ls_parser.load_scene(filename) self.status("Scene '%s' loaded" % filename) self._scene_filename = filename except Exception as ex: self.warning(ex.message) else: self.status("Load scene canceld") def tabula_rasa(self): for grp in self.group_windows: grp.tabula_rasa() self.group_windows = [] def _interactive_tabula_rasa(self, *_): # ISSUE: Check config and ask user confirmation before existing self.app.ls_parser.tabula_rasa()
class CoilSnakeFrontend: PREFS_FNAME = "prefs.yml" def __init__(self): try: with open(self.PREFS_FNAME, 'r') as f: self._prefs = yaml.load(f, Loader=yaml.CSafeLoader) except IOError: self._prefs = { 'title': 0 } def getPrefsValue(self, key): try: return self._prefs[key] except KeyError: return "" def savePrefs(self): with open(self.PREFS_FNAME, "w") as f: yaml.dump(self._prefs, f, Dumper=yaml.CSafeDumper) def toggleTitles(self): self._prefs["title"] = (~(self._prefs["title"]))|1 self.savePrefs() def aboutMenu(self): am = Toplevel(self._root) #Label(am, text="CoilSnake " + CoilSnake._VERSION, # font=("Helvetica", 16)).pack(fill=X) photo = PhotoImage(file="resources/logo.gif") photoLabel = Label(am, image=photo) photoLabel.photo = photo photoLabel.pack(fill='both', expand=1) Label(am, text= (("CoilSnake %s\n" + "Released on %s\n\n" + "Created by MrTenda\n" + "Logo art by Reg\n\n" + "With help from\n" + " Penguin, Reg, H.S, Michael1,\n" + " Mr. Accident, AnyoneEB, Goplat, Captain Bozo,\n" + " and the rest of the PK Hack community.\n" + "\n" + "Running on Python %s") % ( CoilSnake._VERSION, CoilSnake._RELEASE_DATE, python_version())), anchor="w",justify="left",bg="white",borderwidth=5, relief=GROOVE).pack( fill='both', expand=1) Button(am, text="Toggle Alternate Titles", command=self.toggleTitles).pack(fill=X) Button(am, text="Close", command=am.destroy).pack(fill=X) am.resizable(False, False) am.title("About") def setText(self, entry, str): entry.delete(0, END) entry.insert(0, str) entry.xview(END) def setEmulatorExe(self): self._prefs["Emulator"] = tkFileDialog.askopenfilename( parent=self._root, title="Select an Emulator Executable", initialfile=self.getPrefsValue("Emulator")) self.savePrefs() def setCccExe(self): self._prefs["CCC"] = tkFileDialog.askopenfilename( parent=self._root, title="Select the CCC Executable", initialfile=self.getPrefsValue("CCC")) self.savePrefs() def toggleErrorDetails(self): if self.getPrefsValue("ErrorDetails") == "1": self._prefs["ErrorDetails"] = "0" else: self._prefs["ErrorDetails"] = "1" def browseForRom(self, entry, save=False): if save: fname = tkFileDialog.asksaveasfilename( parent=self._root, title="Select an output ROM", filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')]) else: fname = tkFileDialog.askopenfilename( parent=self._root, title="Select a ROM", filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs', '*.sfc'), ('All files','*.*')]) if len(fname) > 0: self.setText(entry, fname) def browseForProject(self, entry, save=False): fname = tkFileDialog.askdirectory( parent=self._root, title="Select a Project Directory", mustexist=(not save)) self.setText(entry, fname) def runRom(self, entry): romFname = entry.get() if self.getPrefsValue("Emulator") == "": tkMessageBox.showerror(parent=self._root, title="Error", message="""Emulator executable not specified. Please specify it in the Preferences menu.""") elif romFname != "": Popen([self.getPrefsValue("Emulator"), romFname]) def resetConsole(self): self._console.delete(1.0, END) self._console.see(END) def doExport(self, romEntry, projEntry): if (romEntry.get() != "") and (projEntry.get() != ""): # Update the GUI self.resetConsole() self._exportB["state"] = DISABLED self._importB["state"] = DISABLED self._upgradeB["state"] = DISABLED # Save the fields to preferences self._prefs["export_rom"] = romEntry.get() self._prefs["export_proj"] = projEntry.get() self.savePrefs() self._progBar["value"] = 0 print "Initializing CoilSnake\n" self._cs = CoilSnake.CoilSnake() self._progBar.step(10) thread = Thread(target=self._doExportHelp, args=(romEntry.get(), projEntry.get(), time(), )) thread.start() def _doExportHelp(self, rom, proj, startTime): try: if self._cs.romToProj(rom, proj): print "Done! (Took %0.2fs)" % (time()-startTime) except Exception as inst: print "\nError:", str(inst) if self.getPrefsValue("ErrorDetails") == "1": print_exc() self._progBar["value"] = 0 self._exportB["state"] = NORMAL self._importB["state"] = NORMAL self._upgradeB["state"] = NORMAL del(self._cs) def doImport(self, projEntry, cleanRomEntry, romEntry): if self.getPrefsValue("CCC") == "": tkMessageBox.showerror(parent=self._root, title="Error", message="""CCScript Compiler executable not specified. Please specify it in the Preferences menu.""") elif ((projEntry.get() != "") and (cleanRomEntry.get() != "") and (romEntry.get() != "")): # Update the GUI self.resetConsole() self._exportB["state"] = DISABLED self._importB["state"] = DISABLED self._upgradeB["state"] = DISABLED self._importRunB["state"] = DISABLED # Save the fields to preferences self._prefs["import_proj"] = projEntry.get() self._prefs["import_baserom"] = cleanRomEntry.get() self._prefs["import_rom"] = romEntry.get() self.savePrefs() oldRom = cleanRomEntry.get() newRom = romEntry.get() projDir = projEntry.get() # Reset the progress bar self._progBar["value"] = 0 self._console.delete(1.0, END) # Run CoilSnake as usual print "Initializing CoilSnake\n" self._cs = CoilSnake.CoilSnake() self._progBar.step(10) thread = Thread(target=self._doImportHelp, args=(projDir, oldRom, newRom, time())) thread.start() def _doImportHelp(self, proj, oldRom, newRom, startTime): try: if self._cs.projToRom(proj, oldRom, newRom, self.getPrefsValue("CCC")): print "Done! (Took %0.2fs)" % (time()-startTime) except Exception as inst: print "\nError:", str(inst) if self.getPrefsValue("ErrorDetails") == "1": print_exc() self._progBar["value"] = 0 self._exportB["state"] = NORMAL self._importB["state"] = NORMAL self._upgradeB["state"] = NORMAL self._importRunB["state"] = NORMAL del(self._cs) def doUpgrade(self, romEntry, projEntry): if (romEntry.get() != "") and (projEntry.get() != ""): # Update the GUI self.resetConsole() self._exportB["state"] = DISABLED self._importB["state"] = DISABLED self._upgradeB["state"] = DISABLED # Save the fields to preferences self._prefs["upgrade_rom"] = romEntry.get() self._prefs["upgrade_proj"] = projEntry.get() self.savePrefs() self._progBar["value"] = 0 print "Initializing CoilSnake\n" self._cs = CoilSnake.CoilSnake() self._progBar.step(10) thread = Thread(target=self._doUpgradeHelp, args=(romEntry.get(), projEntry.get(), time(), )) thread.start() def _doUpgradeHelp(self, rom, proj, startTime): try: if self._cs.upgradeProject(rom, proj): print "Done! (Took %0.2fs)" % (time()-startTime) except Exception as inst: print "\nError:", str(inst) if self.getPrefsValue("ErrorDetails") == "1": print_exc() self._progBar["value"] = 0 self._exportB["state"] = NORMAL self._importB["state"] = NORMAL self._upgradeB["state"] = NORMAL del(self._cs) def expandRom(self, ex=False): r = Rom.Rom('resources/romtypes.yaml') fname = tkFileDialog.askopenfilename( parent=self._root, title="Select a ROM to expand", filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')]) if len(fname) > 0: r.load(fname) if ((not ex) and (len(r) >= 0x400000)) or (ex and (len(r) >= 0x600000)): tkMessageBox.showerror(parent=self._root, title="Error", message="This ROM is already expanded.") else: if ex: r.expand(0x600000) else: r.expand(0x400000) r.save(fname) del(r) tkMessageBox.showinfo(parent=self._root, title="Expansion Successful", message="Your ROM was expanded.") def expandRomEx(self): self.expandRom(ex=True) def addHeaderRom(self): r = Rom.Rom('resources/romtypes.yaml') fname = tkFileDialog.askopenfilename( parent=self._root, title="Select a ROM to which to add a header", filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')]) if len(fname) > 0: r.load(fname) r.addHeader() r.save(fname) del(r) tkMessageBox.showinfo(parent=self._root, title="Header Addition Successful", message="Your ROM was given a header.") def stripHeaderRom(self): r = Rom.Rom('resources/romtypes.yaml') fname = tkFileDialog.askopenfilename( parent=self._root, title="Select a ROM from which to remove a header", filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')]) if len(fname) > 0: r.load(fname) r.save(fname) del(r) tkMessageBox.showinfo(parent=self._root, title="Header Remove Successful", message="Your ROM's header was removed.") def main(self): self._root = Tk() if self.getPrefsValue("title") == 1: self._root.wm_title(getTitle() + " " + CoilSnake._VERSION) else: self._root.wm_title("CoilSnake" + " " + CoilSnake._VERSION) if self.getPrefsValue("title") == 0: self._prefs["title"] = 1 self.savePrefs() menuBar = Menu(self._root) # Preferences pulldown menu prefMenu = Menu(menuBar, tearoff=0) prefMenu.add_command(label="CCScript Compiler Executable", command=self.setCccExe) prefMenu.add_command(label="Emulator Executable", command=self.setEmulatorExe) prefMenu.add_command(label="Toggle Error Details", command=self.toggleErrorDetails) menuBar.add_cascade(label="Preferences", menu=prefMenu) # Tools pulldown menu toolsMenu = Menu(menuBar, tearoff=0) toolsMenu.add_command(label="Expand ROM to 32 MBit", command=self.expandRom) toolsMenu.add_command(label="Expand ROM to 48 MBit", command=self.expandRomEx) toolsMenu.add_command(label="Add Header to ROM", command=self.addHeaderRom) toolsMenu.add_command(label="Remove Header from ROM", command=self.stripHeaderRom) menuBar.add_cascade(label="Tools", menu=toolsMenu) # Help menu helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About", command=self.aboutMenu) menuBar.add_cascade(label="Help", menu=helpMenu) self._root.config(menu=menuBar) # Left side: Export a=Label(self._root, text="ROM -> New Project",justify=CENTER).grid( row=0, column=1, columnspan=1) # ROM file selector Label(self._root, text="Input ROM:").grid( row=1, column=0, sticky=E) inRom = Entry(self._root) inRom.grid(row=1, column=1) self.setText(inRom, self.getPrefsValue("export_rom")) def browseTmp(): self.browseForRom(inRom) def runTmp(): self.runRom(inRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=1, column=2, sticky=W) Button(self._root, text="Run", command=runTmp).grid(row=1, column=3, sticky=W) # Project dir selector Label(self._root, text="Output Directory:").grid( row=2, column=0, sticky=E) outProj = Entry(self._root) outProj.grid(row=2, column=1) self.setText(outProj, self.getPrefsValue("export_proj")) def browseTmp(): self.browseForProject(outProj, save=True) Button(self._root, text="Browse...", command=browseTmp).grid(row=2, column=2, sticky=W) # Export Button def exportTmp(): self.doExport(inRom, outProj) self._exportB = Button(self._root, text="Decompile", command=exportTmp) self._exportB.grid(row=3, column=1, columnspan=1, sticky=W+E) # Right side: Import Label(self._root, text="Project -> New ROM").grid( row=0, column=5, columnspan=1) # Base ROM file selector Label(self._root, text="Base Expanded ROM:").grid( row=1, column=4, sticky=E) baseRom = Entry(self._root) baseRom.grid(row=1, column=5) self.setText(baseRom, self.getPrefsValue("import_baserom")) def browseTmp(): self.browseForRom(baseRom) def runTmp(): self.runRom(baseRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=1, column=6) Button(self._root, text="Run", command=runTmp).grid(row=1, column=7, sticky=E+W) # Project dir selector Label(self._root, text="Project Directory:").grid( row=2, column=4, sticky=E) inProj = Entry(self._root, text=self.getPrefsValue("import_proj")) inProj.grid(row=2, column=5) self.setText(inProj, self.getPrefsValue("import_proj")) def browseTmp(): self.browseForProject(inProj, save=False) Button(self._root, text="Browse...", command=browseTmp).grid(row=2, column=6) # ROM file selector Label(self._root, text="Output ROM:").grid( row=3, column=4, sticky=E) outRom = Entry(self._root, text=self.getPrefsValue("import_rom")) outRom.grid(row=3, column=5) self.setText(outRom, self.getPrefsValue("import_rom")) def browseTmp(): self.browseForRom(outRom, save=True) def runTmp(): self.runRom(outRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=3, column=6) self._importRunB = Button(self._root, text="Run", command=runTmp) self._importRunB.grid(row=3, column=7, sticky=E+W) # Import Button def importTmp(): self.doImport(inProj, baseRom, outRom) self._importB = Button(self._root, text="Compile", command=importTmp) self._importB.grid(row=4, column=5, columnspan=1, sticky=W+E) # Upgrade a=Label(self._root, text="Upgrade Project",justify=CENTER).grid( row=5, column=1, columnspan=1) # ROM file selector Label(self._root, text="Base ROM:").grid( row=6, column=0, sticky=E) upgradeRom = Entry(self._root) upgradeRom.grid(row=6, column=1) self.setText(upgradeRom, self.getPrefsValue("upgrade_rom")) def browseTmp(): self.browseForRom(upgradeRom) def runTmp(): self.runRom(upgradeRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=6, column=2, sticky=W) Button(self._root, text="Run", command=runTmp).grid(row=6, column=3, sticky=W) # Project dir selector Label(self._root, text="Project Directory:").grid( row=7, column=0, sticky=E) upgradeProj = Entry(self._root) upgradeProj.grid(row=7, column=1) self.setText(upgradeProj, self.getPrefsValue("upgrade_proj")) def browseTmp(): self.browseForProject(upgradeProj, save=True) Button(self._root, text="Browse...", command=browseTmp).grid(row=7, column=2, sticky=W) # Upgrade Button def upgradeTmp(): self.doUpgrade(upgradeRom, upgradeProj) self._upgradeB = Button(self._root, text="Upgrade", command=upgradeTmp) self._upgradeB.grid(row=8, column=1, columnspan=1, sticky=W+E) # Progress bar self._progBar = Progressbar(self._root, orient=HORIZONTAL, mode='determinate') self._progBar.grid(row=9, column=0, columnspan=8, sticky=W+E) def updProg(dp): Progress.__updateProgress__(dp) # Note: The number of modules is hardcoded here as "19" self._progBar.step((90.0/19) * (dp/100.0)) Progress.updateProgress = updProg # Console consoleFrame = Frame(self._root) consoleFrame.grid(row=10, column=0, columnspan=8, sticky=W+E) s = Scrollbar(consoleFrame) self._console = Text(consoleFrame, width=80, height=6) s.pack(side=RIGHT, fill=Y) self._console.pack(fill=X) s.config(command=self._console.yview) self._console.config(yscrollcommand=s.set) # Stdout Redirector class StdoutRedirector: def __init__(self, textArea): self._tA = textArea def write(self,str): if str.startswith("\b\b\b\b\b\b\b\b"): self._tA.delete("end-9c", "end") self._tA.insert(END, str[8:]) else: self._tA.insert(END, str) self._tA.see(END) def flush(self): pass self._consoleStdout = StdoutRedirector(self._console) sys.stdout = self._consoleStdout sys.stderr = self._consoleStdout self._root.mainloop()
class DataSyncer: _logger = logging.getLogger('DataSyncer') def __init__(self): self.root = Tk() self.file_list = {} self.bag_num_thres = 5 self.file_size = 0 self.finish_size = 0 self.usb_model = None self._lock = threading.Lock() self.sync_proc = None self.sync_thread = None self.stop_thread = None self.status = SYNC_NOT_READY self.sync_dst_bag = '' self.sync_dst_dataset = '' self.usb_status = '' self.net_status = '' self.sync_status = '' self.cur_time = 0 # GUI interface self.frame = Frame(self.root) self.root.title('TuSimple Data Syncer') self.root.geometry('500x700') self.root.protocol("WM_DELETE_WINDOW", self.exit) self.style = Style(self.root) self.style.layout('text.Horizontal.TProgressbar', [('Horizontal.Progessbar.trough', {'children': [('Horizontal.Progressbar.pbar', {'side':'left', 'sticky':'ns'})], 'sticky': 'nswe'}), ('Horizontal.Progressbar.label', {'side':'right', 'sticky':''})]) self.font_size = tkFont.Font(family='Times New Roman', size=15) self.create_layout() self.gui_update() self.search_usb_update() self.search_net_update() DataSyncer._logger.info('GUI layout created') self.root.mainloop() def create_layout(self): # usb label usb_lbl = Label(text='usb status:', height=4, width=20, font=self.font_size) usb_lbl.grid(column=0, row=0) # usb status label self.usb_status_lbl = Label(text=self.usb_status, height=4, width=20, font=self.font_size) self.usb_status_lbl.grid(column=1, row=0) # network label net_lbl = Label(text='network status:', height=4, width=20, font=self.font_size) net_lbl.grid(column=0, row=1) # network status label self.net_status_lbl = Label(text=self.net_status, height=4, font=self.font_size) self.net_status_lbl.grid(column=1, row=1) # start date label start_lbl = Label(text='start date:', height=4, font=self.font_size) start_lbl.grid(column=0, row=2) # start date text self.start_txt = Entry(width=25, font=self.font_size) self.start_txt.grid(column=1, row=2) # end date label end_lbl = Label(text='end date:', height=4, font=self.font_size) end_lbl.grid(column=0, row=3) # end date text self.end_txt = Entry(width=25, font=self.font_size) self.end_txt.grid(column=1, row=3) # start button self.usb_button = Button(text='USB sync', height=3, command= lambda: self.start_button_click('USB'), font=self.font_size) self.usb_button.grid(column=0, row=4, sticky=N+S+E+W) # stop button self.stop_button = Button(text='stop sync', height=3, command= lambda: self.stop_button_click(), font=self.font_size) self.stop_button.grid(column=1, row=4, sticky=N+S+E+W) # start button self.net_button = Button(text='Net sync', height=3, command= lambda: self.start_button_click('Net'), font=self.font_size) self.net_button.grid(column=0, row=5, sticky=N+S+E+W) # start button self.exit_button = Button(text='exit', height=3, command=self.exit, font=self.font_size) self.exit_button.grid(column=1, row=5, sticky=N+S+E+W) # sync status label self.sync_status_lbl = Label(text=self.sync_status, width=50, height=4, font=self.font_size) self.sync_status_lbl.grid(column=0, row=6, columnspan=2) # progress bar self.progressbar = Progressbar(orient='horizontal', length=240, mode='determinate', style='text.Horizontal.TProgressbar') # time estimator self.time_est = Label(height=3, font=self.font_size) def usb_status_set(self, text): self.usb_status = text def net_status_set(self, text): self.net_status = text def sync_status_set(self, text): self.sync_status = text def usb_status_config(self, text): self.usb_status_lbl.configure(text=text) def net_status_config(self, text): self.net_status_lbl.configure(text=text) def sync_status_config(self, text): self.sync_status_lbl.configure(text=text) def prog_status_config(self, val, maximum, text): self.progressbar.configure(value=val, maximum=maximum) self.style.configure('text.Horizontal.TProgressbar', text=text) def start_date_get(self): return self.start_txt.get() def end_date_get(self): return self.end_txt.get() def set_status(self, status): with self._lock: self.status = status def get_status(self): with self._lock: return self.status def forget_progressbar(self): self.cur_time = 0 self.finish_size = 0 if len(self.progressbar.grid_info()) != 0: self.progressbar.grid_forget() if len(self.time_est.grid_info()) != 0: self.time_est.grid_forget() def search_usb_update(self): self.root.after(USB_FREQ, self.search_usb) def search_net_update(self): self.root.after(NET_FREQ, self.search_net) def gui_update(self): self.root.after(UPDATE_FREQ, self.status_update) def progressbar_update(self): self.root.after(PROG_FREQ, self.progressbar_calculator) def progressbar_calculator(self): if self.get_status() == SYNCING: self.progressbar.grid(column=0, row=12, columnspan=2) self.time_est.grid(column=0, row=13, columnspan=2) finish_size = 0 for key, folders in self.file_list.iteritems(): if 'bag' in self.file_list[key].values(): path = os.path.join(self.sync_dst_bag, key) if os.path.exists(path): try: finish_size += self.get_size(path) except OSError: DataSyncer._logger.error('Unable to get size at {}'.format(path)) for data_folder, data_type in folders.iteritems(): if data_type == 'dataset': path = os.path.join(self.sync_dst_dataset, data_folder) if os.path.exists(path): try: finish_size += self.get_size(path) except OSError: DataSyncer._logger.error('Unable to get size at {}'.format(path)) # calculate percent val = finish_size * 1. / self.file_size * 100 maximum = 100 self.prog_status_config(val, maximum, '{}/{}'.format(int(val), maximum)) # calculate speed and estimated time if self.cur_time == 0: self.cur_time = time.time() else: t_diff = time.time() - self.cur_time self.cur_time = time.time() s_diff = finish_size - self.finish_size self.finish_size = finish_size # speed in MB/s, t_diff in KB, needs to divide by 1024, time left in min sync_speed = s_diff * 1. / t_diff if t_diff != 0 else 0 time_left = int(math.ceil((self.file_size - self.finish_size) * 1. / sync_speed / 60) if sync_speed != 0 else 0) self.time_est.configure(text='Sync speed: {:.1f}MB/s, Estimate: {}min'.format(sync_speed/1024, time_left)) self.progressbar_update() def start_button_click(self, sync_type): if self.get_status() == SYNCING or (self.sync_thread != None and self.sync_thread.isAlive()): self.sync_status_set('Unable to sync: syncing in progress') DataSyncer._logger.warn('Unable to sync: syncing in progress') return self.sync_thread = threading.Thread(target=self.start_sync, args=(sync_type,)) self.sync_thread.start() def stop_button_click(self): ''' if self.stop_thread != None and self.stop_thread.isAlive(): self.sync_status_set('Unable to stop: stopping now') DataSyncer._logger.warn('Unable to sync: stopping now') return ''' if self.get_status() != SYNCING: self.sync_status_set('Unable to stop: no syncing in progress') DataSyncer._logger.warn('Unable to sync: no syncing in progress') return self.stop_thread = threading.Thread(target=self.stop_sync) self.stop_thread.start() def status_update(self): self.usb_status_config(self.usb_status) self.net_status_config(self.net_status) self.sync_status_config(self.sync_status) self.gui_update() ''' if self.sync_thread != None and self.sync_thread.isAlive() and self.get_status() in [SYNC_NOT_READY, SYNC_STOPPING]: self.sync_thread.join() DataSyncer._logger.info('sync thread joined!') if self.stop_thread != None and self.stop_thread.isAlive() and self.get_status() in [SYNC_NOT_READY]: self.stop_thread.join() DataSyncer._logger.info('stop thread joined!') ''' # check if usb is availble def search_usb(self): dev_path = os.path.join('/media', USER) dev_name = None try: devs = os.listdir(dev_path) for dev in devs: _dev = dev.lower() if DEV_PRE.lower() in _dev: dev_name = dev if dev_name: self.usb_status = dev else: self.usb_status = 'No USB found' self.usb_model = dev_name if self.get_status() != SYNCING: self.search_usb_update() except OSError: self.usb_status = '{} USB not found'.format(DEV_PRE) self.usb_model = None # search if network is available def search_net(self): try: res = os.system("ping -c 1 " + NETWORK_IP + '> /dev/null 2>&1') if res == 0: if os.path.ismount(BAG_MOUNT_POINT): self.net_status = 'Network is ready for sync' else: self.net_status = 'Mount point unfound' else: self.net_status = 'Network is unreachable' if self.get_status() != SYNCING: self.search_net_update() except OSError: print('Unable to check the network availability') # check file list def check_file_type(self, path): items = os.listdir(path) if 'top.json' in items: return 'dataset' elif 'record.json' in items or 'log' in items: return 'bag' else: return None # count how many bags one folder has def count_bag(self, folder): try: items = os.listdir(folder) except OSError: DataSyncer._logger.error('Unable to open file: {}'.format(folder)) return False bag_num = 0 for item in items: if item.endswith('.bag'): bag_num += 1 return bag_num # add to bag list def add_file_list(self, start_date, end_date): # empty the file list self.file_list = {} self.file_size = 0 # adding into file list try: dates = os.listdir(SYNC_SRC) for date in dates: if date < start_date or date > end_date: continue self.file_list[date] = {} path = os.path.join(SYNC_SRC, date) self.file_size += self.get_size(path) bag_folders = os.listdir(path) for f in bag_folders: f_path = os.path.join(SYNC_SRC, date, f) file_type = self.check_file_type(f_path) if file_type == 'dataset': ds = Dataset(f_path) _t = (ds.meta['ts_end'] - ds.meta['ts_begin']) * 1. / 1e9 / 60 if _t > self.bag_num_thres * 5: self.file_list[date][f] = 'dataset' elif file_type == 'bag': bag_num = self.count_bag(f_path) if bag_num >= self.bag_num_thres: self.file_list[date][f] = 'bag' else: DataSyncer._logger.warn('{} is not a data folder'.format(f_path)) if len(self.file_list[date]) == 0: del(self.file_list[date]) except OSError as e: DataSyncer._logger.error('Unable to open files when adding to bag list') # check user input format @staticmethod def check_date_format(date_text): try: datetime.datetime.strptime(date_text, '%Y-%m-%d') return True except ValueError: return False # check if usb condition is met for sync def check_dst_condition(self, sync_type): condition = self.usb_model if sync_type == 'USB' else self.net_status if not condition: self.sync_status_set('Unable to sync: {} is not avaible'.format(sync_type)) DataSyncer._logger.error('Unable to sync: {} is not avaible'.format(sync_type)) return False return True # check if date is met for sync def check_date_condition(self): start_date = self.start_date_get() end_date = self.end_date_get() prompt = 'Unable to sync: ' if start_date == '' or end_date == '': self.sync_status_set(prompt + 'dates null') DataSyncer._logger.error(prompt + 'dates null') return False elif not self.check_date_format(start_date) or not self.check_date_format(end_date): self.sync_status_set(prompt + 'format should be YYYY-MM-DD') DataSyncer._logger.error(prompt + 'format should be YYYY-MM-DD') return False elif start_date > end_date: self.sync_status_set(prompt + 'start date later than end date') DataSyncer._logger.error(prompt + 'start date later than end date') return False else: self.add_file_list(start_date, end_date) if len(self.file_list) == 0: self.sync_status_set(prompt + 'no bag between these dates') DataSyncer._logger.error(prompt + 'no bag between these dates') return False else: return True # check both conditions def check_sync_condition(self, sync_type): if self.check_dst_condition(sync_type) and self.check_date_condition(): self.set_status(SYNC_READY) else: self.set_status(SYNC_NOT_READY) # start syncing def start_sync(self, sync_type): # check destination self.check_sync_condition(sync_type) if self.get_status() == SYNC_NOT_READY: return self.set_status(SYNCING) # generate dist path if sync_type == 'USB': self.sync_dst_bag = self.sync_dst_dataset = os.path.join('/media', USER, self.usb_model, 'import') else: self.sync_dst_bag = os.path.join(BAG_MOUNT_POINT, 'data_collection') self.sync_dst_dataset = DATASET_MOUNT_POINT try: folders = os.listdir(self.sync_dst_bag) except OSError: self.sync_status_set('No such path: {}'.format(self.sync_dst_bag)) DataSyncer._logger.error('Unable to open file: {}'.format(self.sync_dst_bag)) return # sanity check self.sync_status_set('Sanity check...please wait') self.sanity_check() DataSyncer._logger.info('Sanity check finished') self.progressbar_update() # start to sync bag one by one for key, f_list in self.file_list.iteritems(): if key not in folders and 'bag' in f_list.values(): try: os.mkdir(os.path.join(self.sync_dst_bag, key)) except OSError: self.set_status(SYNC_NOT_READY) DataSyncer._logger.error('Unable to create {} under {}'.format(key, self.sync_dst_bag)) return for f in f_list.keys(): if self.get_status() == SYNCING: self.sync_status_set('Syncing: ' + f) cmd = ['rsync', '--progress', '-r', '--append'] cmd.append(os.path.join(SYNC_SRC, key, f)) sync_dst = os.path.join(self.sync_dst_bag, key) if f_list[f] == 'bag' else self.sync_dst_dataset cmd.append(sync_dst) self.sync_proc = subprocess.Popen(cmd) self.sync_proc.communicate() if self.sync_proc.returncode not in [0, 20]: self.sync_status_set('Syncing progress error code: {}'.format(self.sync_proc.returncode)) DataSyncer._logger.error('rsync progress error code: {}'.format(self.sync_proc.returncode)) if self.get_status() == EXIT: DataSyncer._logger.info('exiting...') return # reset status if self.get_status() == SYNCING: self.set_status(SYNC_NOT_READY) if self.sync_proc.returncode == 0: self.sync_status_set(sync_type + ' sync completed') DataSyncer._logger.info(sync_type + ' sync completed') # post deletion self.post_delete() # restart update self.search_usb_update() self.search_net_update() # forget progressbar and its related speed/time estimator self.forget_progressbar() DataSyncer._logger.info('syncing thread finished') # stop syncing def stop_sync(self): if self.sync_proc != None and self.sync_proc.poll() == None: DataSyncer._logger.info('start stopping') self.sync_proc.terminate() if self.get_status() != EXIT: self.set_status(SYNC_NOT_READY) self.sync_proc.communicate() DataSyncer._logger.info('returncode is: {}'.format(self.sync_proc.returncode)) if self.sync_proc.returncode in [0, 20]: self.sync_status_set('stop success') DataSyncer._logger.info('stop syncing thread finished') # sanity check before syncing to avoid - matching the use of rsync --append def sanity_check(self): for key, bag_folder in self.file_list.iteritems(): for f in bag_folder.keys(): try: # assumption: all files in destination must be included by those in source sync_dst = os.path.join(self.sync_dst_bag, key, f) if bag_folder[f] == 'bag' else os.path.join(self.sync_dst_dataset, f) items = os.listdir(sync_dst) for item in items: src_path = os.path.join(SYNC_SRC, key, f, item) dst_path = os.path.join(sync_dst, item) if os.path.isfile(dst_path): s_size = self.get_file_size(src_path) d_size = self.get_file_size(dst_path) else: s_size = self.get_dir_size(src_path) d_size = self.get_dir_size(dst_path) if s_size != d_size: try: os.remove(dst_path) except OSError: shutil.rmtree(dst_path) finally: DataSyncer._logger.warn('removed {}'.format(dst_path)) except OSError: DataSyncer._logger.error('Unable to do OS operation in Sanity check') # post-delete the .active bag # TO-DO: include post check def post_delete(self): for key, bag_folder in self.file_list.iteritems(): for f in bag_folder.keys(): try: if bag_folder[f] == 'bag': path = os.path.join(self.sync_dst_bag, key, f) items = os.listdir(path) for item in items: if item.endswith('.active'): path = os.path.join(path, item) os.remove(path) except OSError: DataSyncer._logger.error('Unable to do OS operation in post delete') # wait threads finish def wait_thread(self): while True: if (self.sync_thread != None and self.sync_thread.isAlive()) or (self.stop_thread != None and self.stop_thread.isAlive()): time.sleep(0.5) continue else: break # close window exit def exit(self): self.set_status(EXIT) self.stop_sync() time.sleep(0.5) self.root.destroy() sys.exit(0) # get folder size in KB in general def get_size(self, path): return int(subprocess.check_output(['du', '-s', path]).split()[0]) # calculate file's logical size def get_file_size(self, path): return int(subprocess.check_output(['ls', '-l', path]).split()[4]) # calculate folde'r logical size def get_dir_size(self, path): size = 0 for item in os.listdir(path): item_path = os.path.join(path, item) size += self.get_file_size(item_path) if os.path.isfile(item_path) else self.get_dir_size(item_path) return int(size)
class MiCall(tk.Frame): CONFIG_FILE = os.path.expanduser("~/.micall.config") def __init__(self, parent, *args, **kwargs): self.pssm = Pssm(path_to_lookup=AssetWrapper('micall/g2p/g2p_fpr.txt').path, path_to_matrix=AssetWrapper('micall/g2p/g2p.matrix').path) tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent parent.report_callback_exception = self.report_callback_exception self.rundir = None # path to MiSeq run folder containing data self.workdir = gettempdir() # default to temp directory os.chdir(self.workdir) self.line_counter = LineCounter() self.run_info = None self.target_files = [] self.button_frame = tk.Frame(self) self.button_frame.pack(side='top') self.console_frame = tk.Frame(self) self.console_frame.pack(side='top', fill='both', expand=True) try: with open(MiCall.CONFIG_FILE, 'rU') as f: self.config = json.load(f) except: self.config = {} self.nthreads = self.config.get('threads', None) if not self.nthreads: self.nthreads = int(round(cpu_count() * 0.5)) self.config['threads'] = self.nthreads self.write_config() self.button_run = tk.Button( self.button_frame, text="Run", command=self.process_files ) self.button_run.grid(row=0, column=1, sticky='W') self.progress_bar = Progressbar(self.button_frame, orient='horizontal', length=500, mode='determinate') self.progress_bar.grid(row=1, columnspan=5) scrollbar = tk.Scrollbar(self.console_frame) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.console = tk.Text(self.console_frame, bg='black', fg='white', yscrollcommand=scrollbar.set) self.console.pack(side=tk.LEFT, fill=tk.BOTH) self.console.tag_configure('ERROR', foreground="red") scrollbar.config(command=self.console.yview) # redirect stderr to Text widget #sys.stderr = Redirector(self.console) self.write('Welcome to MiCall v{}, running with {} threads.\n'.format( pipeline_version, self.nthreads)) def write(self, msg): """ Write to Text widget, scroll to bottom, and then disable editing again. :param msg: :return: """ self.console.config(state=tk.NORMAL) self.console.insert(tk.END, msg) self.console.see(tk.END) self.console.config(state=tk.DISABLED) def write_config(self): try: with open(MiCall.CONFIG_FILE, 'w') as f: json.dump(self.config, f, indent=4) except: pass # For now, we don't care if config fails def open_files(self): """ Transfer FASTQ files into working folder, uncompress. :return: """ fastq_files = [] setting_name = 'run_path' run_path = self.config.get(setting_name, '') self.rundir = tkFileDialog.askdirectory( title='Choose a folder of FASTQ files:', initialdir=run_path) if not self.rundir: return fastq_files self.config[setting_name] = self.rundir self.write_config() self.write('Selected folder %s\n' % (self.rundir,)) # check for presence of FASTQ files for root, _dirs, files in os.walk(self.rundir): for file in files: if len(fastq_re.findall(file)) > 0: fastq_files.append(os.path.join(root, file)) if fastq_files: self.write('Found %d FASTQ files.\n' % (len(fastq_files),)) else: # empty list self.write('Error, folder does not seem to contain any FASTQ(.gz) files!\n') self.rundir = None return fastq_files def callback(self, message=None, progress=None, max_progress=None): """ Report progress to the user. @param message: a string to write in the window, or None to not write @param progress: an integer value to update the progress bar @param max_progress: an integer value that represents completed progress """ if max_progress: self.progress_bar['maximum'] = max_progress if progress is not None: self.progress_bar['value'] = progress if message is not None: self.write(message + '\n') self.parent.update() def make_tree(self, path): if not os.path.isdir(path): parent = os.path.dirname(path) self.make_tree(parent) os.mkdir(path) def process_sample(self, fastq1, progress, prefixes, image_paths, error_log): fastq2 = fastq1.replace('_R1_001', '_R2_001').replace('censored1', 'censored2') if not os.path.exists(fastq2): raise IOError('ERROR: Missing R2 file for {}'.format(fastq1)) prefix = os.path.basename(fastq1).replace('_L001_R1_001.fastq', '').replace('.censored1.fastq', '') prefixes.append(prefix) output_csv = prefix + '.prelim.csv' self.write('Processing sample {} ({})\n'.format(prefix, progress)) with open(output_csv, 'wb') as handle: prelim_map(fastq1, fastq2, handle, nthreads=self.nthreads, callback=self.callback, stderr=error_log) # prepare file handles for remap stage with open(output_csv, 'rU') as prelim_csv, \ open(os.path.join(self.workdir, prefix + '.remap.csv'), 'wb') as remap_csv, \ open(os.path.join(self.workdir, prefix + '.remap_counts.csv'), 'wb') as counts_csv, \ open(os.path.join(self.workdir, prefix + '.remap_conseq.csv'), 'wb') as conseq_csv, \ open(os.path.join(self.workdir, prefix + '.unmapped1.fastq'), 'w') as unmapped1, \ open(os.path.join(self.workdir, prefix + '.unmapped2.fastq'), 'w') as unmapped2: self.write('... remapping\n') self.parent.update() self.progress_bar['value'] = 0 remap(fastq1, fastq2, prelim_csv, remap_csv, counts_csv, conseq_csv, unmapped1, unmapped2, self.workdir, nthreads=self.nthreads, callback=self.callback, stderr=error_log) # prepare file handles for conversion from SAM format to alignment with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \ open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'wb') as aligned_csv, \ open(os.path.join(self.workdir, prefix + '.insert.csv'), 'wb') as insert_csv, \ open(os.path.join(self.workdir, prefix + '.failed.csv'), 'wb') as failed_csv: self.write('... converting into alignment\n') self.parent.update() sam2aln(remap_csv, aligned_csv, insert_csv, failed_csv, nthreads=self.nthreads) with open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'rU') as aligned_csv, \ open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'wb') as nuc_csv, \ open(os.path.join(self.workdir, prefix + '.amino.csv'), 'wb') as amino_csv, \ open(os.path.join(self.workdir, prefix + '.coord_ins.csv'), 'wb') as coord_ins_csv, \ open(os.path.join(self.workdir, prefix + '.conseq.csv'), 'wb') as conseq_csv, \ open(os.path.join(self.workdir, prefix + '.failed_align.csv'), 'wb') as failed_align_csv, \ open(os.path.join(self.workdir, prefix + '.nuc_variants.csv'), 'wb') as nuc_variants_csv: self.parent.update() aln2counts(aligned_csv, nuc_csv, amino_csv, coord_ins_csv, conseq_csv, failed_align_csv, nuc_variants_csv, callback=self.callback) self.write('... generating coverage plots\n') self.parent.update() with open(os.path.join(self.workdir, prefix + '.amino.csv'), 'rU') as amino_csv: image_paths += coverage_plot(amino_csv) self.write('... performing g2p scoring on samples covering HIV-1 V3\n') self.parent.update() with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \ open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'rU') as nuc_csv, \ open(os.path.join(self.workdir, prefix + '.g2p.csv'), 'wb') as g2p_csv: sam_g2p(pssm=self.pssm, remap_csv=remap_csv, nuc_csv=nuc_csv, g2p_csv=g2p_csv) def build_run_summary(self, sample_count, error_count): summary = '{} sample'.format(sample_count) if sample_count != 1: summary += 's' if error_count > 0: summary += ' with {} error'.format(error_count) if error_count > 1: summary += 's' return summary def process_files(self): """ Perform MiCall data processing on FASTQ files in working directory. """ # look for FASTQ files fastq_files = self.open_files() if len(fastq_files) == 0: return savedir_setting_name = 'results_path' savedir = self.config.get(savedir_setting_name, '') savedir = tkFileDialog.askdirectory(title='Choose a folder to save results', initialdir=savedir) if not savedir: return self.config[savedir_setting_name] = savedir if os.path.exists(savedir) and os.listdir(savedir): self.write('Run FAILED - results folder is not empty: {}\n'.format( savedir)) return workdir_purged_setting_name = 'workdir_purged' is_workdir_purged = self.config.get(workdir_purged_setting_name) if is_workdir_purged is None: self.config[workdir_purged_setting_name] = is_workdir_purged = True self.write_config() self.workdir = os.path.join(savedir, 'working') if os.path.exists(self.workdir): shutil.rmtree(self.workdir) self.make_tree(self.workdir) os.chdir(self.workdir) # transfer FASTQ.gz files to working folder self.callback(progress=0, max_progress=len(fastq_files)) self.target_files = [] for file_index, src in enumerate(fastq_files): if src.startswith(self.workdir): # Working file from previous run. continue self.callback(progress=file_index) filename = os.path.basename(src) prefix = filename.split('.')[0] dest = os.path.join(self.workdir, filename) if '_R1_001' in dest or 'censored1' in dest: self.target_files.append(dest.replace('.gz', '')) # neither file type is present if not dest.endswith('.gz'): shutil.copy(src, dest) else: dest = os.path.join(self.workdir, prefix+'.fastq') with gzip.open(src, 'rb') as zip_src, open(dest, 'w') as fastq_dest: shutil.copyfileobj(zip_src, fastq_dest) self.callback(progress=len(fastq_files)) # remove duplicate entries self.target_files = sorted(set(self.target_files)) self.write('Transferred %d sets of FASTQ files to working directory.\n' % len(self.target_files)) image_paths = [] prefixes = [] error_count = 0 sample_count = len(self.target_files) run_summary = self.build_run_summary(sample_count, error_count) with open(os.path.join(savedir, 'micall.log'), 'w') as error_log: for sample_index, fastq1 in enumerate(self.target_files): try: progress = '{} of {}'.format(sample_index+1, run_summary) self.process_sample(fastq1, progress, prefixes, image_paths, error_log) except: msg = traceback.format_exc() self.write(msg) error_log.write(msg) error_count += 1 run_summary = self.build_run_summary(sample_count, error_count) # collate results to results folder for target_file, extension in files_to_collate: if extension is None: extension = '.' + target_file collate.collate_named_files(src_dir=self.workdir, sample_list=prefixes, extension=extension, output_path=os.path.join(savedir, target_file)) # copy coverage plots imagedir = os.path.join(savedir, 'coverage') if not os.path.exists(imagedir): os.mkdir(imagedir) for src in image_paths: dest = os.path.join(imagedir, os.path.basename(src)) shutil.move(src, dest) # clean up working files os.chdir(savedir) if is_workdir_purged: shutil.rmtree(self.workdir) self.write('Run complete: {}.\n'.format(run_summary)) def report_callback_exception(self, exc_type, exc_value, exc_traceback): message = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback)) self.write(message)
class RunningOperationsPage(BaseInputPage, object): def __init__(self, parent, controller, frame_number): BaseInputPage.__init__(self, parent, controller, frame_number) self.move_back = False self.need_subjects_file = False self.downloaded_file_path = '~/Downloads/' self.operation = Operations(self.controller) self.start = tk.Button(self, text='Start Execution', command=lambda : self.executeCommand()) self.start.grid(row=self.starting_row, column=0, sticky='W', padx=5, pady=3) self.stop = tk.Button(self, text='Stop Execution', state="disabled", command=lambda : self.terminateCommand()) self.stop.grid(row=self.starting_row, column=2, sticky='E', padx=5, pady=3) self.progressbar = Progressbar(self) self.progressbar.configure(mode='determinate', max=100) self.progressbar.grid(row=self.starting_row+1, column=0, columnspan=3, sticky='ew', padx=10, pady=10) self.controller.progressbar = self.progressbar self.output = Text(self, height=15, width=100) self.output.grid(row=self.starting_row+2, column=0, columnspan=3, sticky='ew', padx=10) self.hyperlink = HyperlinkManager(self.output) self.lf_subject_file = LabelFrame(self, text='Visual QC', padx=15, font='Helvetica 14 bold') self.lf_subject_file.grid(row=self.starting_row+3, column=0, columnspan=3, sticky='WE', padx=5, pady=5, ipadx=5, ipady=5) self.lf_subject_file.grid_rowconfigure(0, weight=1) self.lf_subject_file.grid_columnconfigure(4, weight=1) createToolTip(self.lf_subject_file, self.controller.desc.subject_file) self.lb_subject_file = Label(self.lf_subject_file, text="Select flagged subjects textfile", font='Helvetica 13 bold') self.lb_subject_file.grid(row=0, column=0, sticky="W", pady=3) self.select = tk.Button(self.lf_subject_file, text='Select flagged subjects file', command=lambda : self.chooseFile(self, controller, controller.selected_subjects, 'Selected Subjects', default_dir=self.downloaded_file_path)) self.select.grid(row=1, column=0, sticky='W', padx=5, pady=3) lb_or = Label(self.lf_subject_file, text="-OR-", font='Helvetica 13 bold') lb_or.grid(row=1, column=1, sticky="W", pady=3) self.continue_with_all_sub = tk.Button(self.lf_subject_file, text='Continue with all subjects', command=lambda : self.continueWithAllSub()) self.continue_with_all_sub.grid(row=1, column=2, sticky='W', padx=10, pady=3) self.controller.display = self.output def chooseFile(self, parent, controller, place_holder, message, default_dir=''): super(RunningOperationsPage, self).chooseFile(parent, controller, place_holder, message, default_dir=default_dir) self.executeCommand() def setFrameTitle(self): self.title.set('Press Start Execution') def onShowFrame(self, event): super(RunningOperationsPage, self).onShowFrame(event) self.resetAll() self.silentMode() def resetAll(self): self.resetUI() self.operation.resetOperations() def moveToNextPage(self): super(RunningOperationsPage, self).moveToNextPage() def resetClickCounter(self): self.move_back = False self.setRequiredInputError('') def userAgreed(self): if self.move_back: return True self.setRequiredInputError('Warning: All progress will be lost. If you wish to continue, press the button again.') self.move_back = True return False def moveToPrevPage(self): if self.userAgreed(): self.resetAll() super(RunningOperationsPage, self).moveToPrevPage() def resetUI(self): self.start.config(state="normal") self.start.config(text='Start Execution') self.btn_prev.config(state="normal") self.btn_next.config(state="disabled") self.stop.config(state="disabled") self.output.delete('1.0', END) self.title.set("Press 'Start Execution' to begin") self.progressbar.config(value=0) self.need_subjects_file = False self.disableChildren(self.lf_subject_file.winfo_children()) self.resetClickCounter() def continueWithAllSub(self): self.need_subjects_file = False self.executeCommand() def silentMode(self): if self.controller.silent: self.executeCommand() def executeCommand(self): if self.start['text'] == 'Continue Execution' and self.need_subjects_file and not self.controller.silent: selected_subjects_file_path = self.controller.selected_subjects.get() new_subjects = [] try: with open(selected_subjects_file_path, 'r') as f: new_subjects = f.readlines() new_subjects = [subj.strip() for subj in new_subjects] self.downloaded_file_path = os.path.dirname(selected_subjects_file_path) self.controller.selected_subjects.set('') self.operation.updateSubjects(new_subjects) self.setRequiredInputError('') self.need_subjects_file = False except Exception as e: self.controller.logger.error(e.message) self.controller.logger.error(traceback.format_exc()) self.setRequiredInputError('Please import correct textfile downloaded from the QC page.') return False self.disableChildren(self.lf_subject_file.winfo_children()) self.start.config(state="disabled") self.stop.config(state="normal") self.resetClickCounter() if self.start['text'] == 'Continue Execution': self.operation.incrementStage() self.title.set('Please wait') self.operation.startThreads(self) def terminateCommand(self): if self.userAgreed(): self.stop.config(state="disabled") self.operation.stopThreads() def pause(self, operation_name='', data='', need_pause=False): if need_pause and not self.controller.silent: self.start.config(state="disabled") self.start.config(text='Continue Execution') self.title.set('Please input subject file') self.btn_prev.config(state="normal") self.stop.config(state="disabled") self.resetClickCounter() self.need_subjects_file = True self.enableChildren(self.lf_subject_file.winfo_children()) if data: self.insertHyperLink(operation_name, data) def finished(self, operation_name='', data=''): self.start.config(text="Start Execution") self.start.config(state="disabled") self.btn_prev.config(state="normal") self.stop.config(state="disabled") self.title.set('Completed') self.controller.updateMessage('All operations completed. You may now close the application.') self.resetClickCounter() if data: self.insertHyperLink(operation_name, data) def insertHyperLink(self, heading, link): self.output.insert(END, '\n\n') self.output.insert(END, "QC Page for " + heading, self.hyperlink.add(partial(webbrowser.open, link))) self.output.insert(END, '\n\n') self.output.see(END) def toggleChildren(self): self.disableChildren(self.lf_subject_file.winfo_children()) def disableChildren(self, childList): for child in childList: try: self.disableChildren(child.winfo_children()) except: pass try: child.configure(state='disable') except: pass def enableChildren(self, childList): for child in childList: try: self.enableChildren(child.winfo_children()) except: pass try: child.configure(state='normal') except: pass
class Metadator_GUI(Tk): """ Main class """ def __init__(self): # basics settings Tk.__init__(self) # constructor of parent graphic class self.focus_force() # put the window on foreground self.resizable(width = False, # freeze dimensions height = False) self.iconbitmap('../data/images/metadator.ico') # icon self.title(u'Choose your maps before and after') self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) # Frames self.frmain = LabelFrame(self, text = 'General') self.frprog = LabelFrame(self, text = 'Progression') # GUI variables self.nbshp = StringVar() # number of shapefiles self.nbtab = StringVar() # number of MapInfo files #### Main frame # Labels self.labglob = Label(self.frmain, text = u' Please paste or browse the path of your maps') self.labefore = Label(self, text = u'Map before: ') self.labafter = Label(self, text = u'Map after: ') self.numfiles = Label(self, textvariable = self.nbshp) # paths to image self.pathbefore = Entry(self, width = 35) self.pathafter = Entry(self, width = 35) # browse buttons self.browsebef = Button(self, text = 'Browse', command = self.setpathbef) self.browseaft = Button(self, text = 'Browse', command = self.setpathaft) # target folder self.labtarg = Label(self, text = u'Destination folder: ') self.target = Entry(self, width = 35) self.browsetarg = Button(self, text = 'Browse', command = self.setpathtarg) # basic buttons self.validate = Button(self, text = 'Launch', relief= 'raised', command = self.bell) self.cancel = Button(self, text = 'Cancel (quit)', relief= 'groove', command = self.destroy) #### Progression frame # Progress bar self.prog = Progressbar(self, orient=HORIZONTAL, max = 50, length=200, mode='determinate') # widgets placement self.labglob.grid(row = 0, column = 0, columnspan = 3) self.labefore.grid(row = 1, column = 1, columnspan = 1) self.labafter.grid(row = 2, column = 1, columnspan = 1) self.labtarg.grid(row = 3, column = 1, columnspan = 1) self.pathbefore.grid(row = 1, column = 2, columnspan = 1) self.pathafter.grid(row = 2, column = 2, columnspan = 1) self.target.grid(row = 3, column = 2, columnspan = 1) self.browsebef.grid(row = 1, column = 3, columnspan = 1) self.browseaft.grid(row = 2, column = 3, columnspan = 1) self.browsetarg.grid(row = 3, column = 3, columnspan = 1) self.validate.grid(row = 4, column = 1, columnspan = 2) self.cancel.grid(row = 4, column = 3, columnspan = 1, sticky = "W") self.numfiles.grid(row=5, column= 2, columnspan = 2) self.prog.grid(row=6, column = 0, columnspan = 4) # frames placement self.frmain.grid(row=6) def setpathbef(self): """ ...browse and insert the path of FIRST image """ self.filename = askopenfilename(parent = self, title = 'Select the "before" image', filetypes = (("Images", "*.jpg;*.jpeg;*.png;*.tiff"), ("All files", "*.*"))) if self.filename: try: self.pathbefore.insert(0, self.filename) except: print 'no file indicated' # end of function return self.filename def setpathaft(self): """ ...browse and insert the path of SECOND image """ self.filename = askopenfilename(parent = self, title = 'Select the "after" image', filetypes = (("Images", "*.jpg;*.jpeg;*.png;*.tiff"), ("All files", "*.*"))) if self.filename: try: self.pathafter.insert(0, self.filename) except: print 'no file indicated' # end of function return self.filename def setpathtarg(self): """ ...browse and insert the path of DESTINATION FOLDER """ self.foldername = askdirectory(parent = self, title = 'Select the destination folder') if self.foldername: try: self.target.insert(0, self.foldername) except: print 'no folder indicated' # calculate number of shapefiles and MapInfo files self.nbshp.set(len(self.ligeofiles(self.foldername)[0])) self.nbtab.set(len(self.ligeofiles(self.foldername)[1])) # end of function return self.foldername def ligeofiles(self, foldertarget): u""" List shapefiles and MapInfo files (.tab, not .mid/mif) contained in the folders structure """ # Lists objects self.lishp = [] # for shapefiles self.litab = [] # for MapInfo tables # Looping in folders structure for root, dirs, files in walk(foldertarget): for i in files: # Looping on files contained if path.splitext(path.join(root, i))[1] == u'.shp' and \ path.isfile(path.join(root, i)[:-4] + u'.dbf') and \ path.isfile(path.join(root, i)[:-4] + u'.shx') and \ path.isfile(path.join(root, i)[:-4] + u'.prj'): # add complete path of shapefile self.lishp.append(path.join(root, i)) elif path.splitext(path.join(root, i))[1] == u'.tab' and \ path.isfile(path.join(root, i)[:-4] + u'.dat') and \ path.isfile(path.join(root, i)[:-4] + u'.map') and \ path.isfile(path.join(root, i)[:-4] + u'.id'): # add complete path of MapInfo file self.litab.append(path.join(root, i)) # Lists ordering and tupling self.lishp.sort() self.lishp = tuple(self.lishp) self.litab.sort() self.litab = tuple(self.litab) # End of function return self.lishp, self.litab def listing_profils(self): u""" Liste les profils existants contenus dans le répertoire dédié""" global dico_profils, new for i in glob(home + r'/data/profils/*.xml'): dico_profils[path.splitext(path.basename(i))[0]] = i if new > 0: listing_lang() load_textes(deroul_lang.get()) deroul_profils.setlist(sorted(dico_profils.keys())) fen_choix.update() # Fin de fonction return dico_profils
# -*- coding:utf-8 -*- # User: liaochenchen # Date: 2019/12/19 from Tkinter import * from ttk import Progressbar import ttk window = Tk() window.title("Welcome to LikeGeeks app") window.geometry('350x200') style = ttk.Style() style.theme_use('default') style.configure("black.Horizontal.TProgressbar", background='black') bar = Progressbar(window, length=200, style='black.Horizontal.TProgressbar') bar['value'] = 70 bar.grid(column=0, row=0) window.mainloop()
class MiCall(tk.Frame): CONFIG_FILE = os.path.expanduser("~/.micall.config") def __init__(self, parent, *args, **kwargs): self.pssm = Pssm( path_to_lookup=AssetWrapper('micall/g2p/g2p_fpr.txt').path, path_to_matrix=AssetWrapper('micall/g2p/g2p.matrix').path) tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent parent.report_callback_exception = self.report_callback_exception self.rundir = None # path to MiSeq run folder containing data self.workdir = gettempdir() # default to temp directory os.chdir(self.workdir) self.line_counter = LineCounter() self.run_info = None self.target_files = [] self.button_frame = tk.Frame(self) self.button_frame.pack(side='top') self.console_frame = tk.Frame(self) self.console_frame.pack(side='top', fill='both', expand=True) try: with open(MiCall.CONFIG_FILE, 'rU') as f: self.config = json.load(f) except: self.config = {} self.nthreads = self.config.get('threads', None) if not self.nthreads: self.nthreads = int(round(cpu_count() * 0.5)) self.config['threads'] = self.nthreads self.write_config() self.button_run = tk.Button(self.button_frame, text="Run", command=self.process_files) self.button_run.grid(row=0, column=1, sticky='W') self.progress_bar = Progressbar(self.button_frame, orient='horizontal', length=500, mode='determinate') self.progress_bar.grid(row=1, columnspan=5) scrollbar = tk.Scrollbar(self.console_frame) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.console = tk.Text(self.console_frame, bg='black', fg='white', yscrollcommand=scrollbar.set) self.console.pack(side=tk.LEFT, fill=tk.BOTH) self.console.tag_configure('ERROR', foreground="red") scrollbar.config(command=self.console.yview) # redirect stderr to Text widget #sys.stderr = Redirector(self.console) self.write('Welcome to MiCall v{}, running with {} threads.\n'.format( pipeline_version, self.nthreads)) def write(self, msg): """ Write to Text widget, scroll to bottom, and then disable editing again. :param msg: :return: """ self.console.config(state=tk.NORMAL) self.console.insert(tk.END, msg) self.console.see(tk.END) self.console.config(state=tk.DISABLED) def write_config(self): try: with open(MiCall.CONFIG_FILE, 'w') as f: json.dump(self.config, f, indent=4) except: pass # For now, we don't care if config fails def open_files(self): """ Transfer FASTQ files into working folder, uncompress. :return: """ fastq_files = [] setting_name = 'run_path' run_path = self.config.get(setting_name, '') self.rundir = tkFileDialog.askdirectory( title='Choose a folder of FASTQ files:', initialdir=run_path) if not self.rundir: return fastq_files self.config[setting_name] = self.rundir self.write_config() self.write('Selected folder %s\n' % (self.rundir, )) # check for presence of FASTQ files for root, _dirs, files in os.walk(self.rundir): for file in files: if len(fastq_re.findall(file)) > 0: fastq_files.append(os.path.join(root, file)) if fastq_files: self.write('Found %d FASTQ files.\n' % (len(fastq_files), )) else: # empty list self.write( 'Error, folder does not seem to contain any FASTQ(.gz) files!\n' ) self.rundir = None return fastq_files def callback(self, message=None, progress=None, max_progress=None): """ Report progress to the user. @param message: a string to write in the window, or None to not write @param progress: an integer value to update the progress bar @param max_progress: an integer value that represents completed progress """ if max_progress: self.progress_bar['maximum'] = max_progress if progress is not None: self.progress_bar['value'] = progress if message is not None: self.write(message + '\n') self.parent.update() def make_tree(self, path): if not os.path.isdir(path): parent = os.path.dirname(path) self.make_tree(parent) os.mkdir(path) def process_sample(self, fastq1, progress, prefixes, image_paths, error_log): fastq2 = fastq1.replace('_R1_001', '_R2_001').replace('censored1', 'censored2') if not os.path.exists(fastq2): raise IOError('ERROR: Missing R2 file for {}'.format(fastq1)) prefix = os.path.basename(fastq1).replace('_L001_R1_001.fastq', '').replace( '.censored1.fastq', '') prefixes.append(prefix) output_csv = prefix + '.prelim.csv' self.write('Processing sample {} ({})\n'.format(prefix, progress)) with open(output_csv, 'wb') as handle: prelim_map(fastq1, fastq2, handle, nthreads=self.nthreads, callback=self.callback, stderr=error_log) # prepare file handles for remap stage with open(output_csv, 'rU') as prelim_csv, \ open(os.path.join(self.workdir, prefix + '.remap.csv'), 'wb') as remap_csv, \ open(os.path.join(self.workdir, prefix + '.remap_counts.csv'), 'wb') as counts_csv, \ open(os.path.join(self.workdir, prefix + '.remap_conseq.csv'), 'wb') as conseq_csv, \ open(os.path.join(self.workdir, prefix + '.unmapped1.fastq'), 'w') as unmapped1, \ open(os.path.join(self.workdir, prefix + '.unmapped2.fastq'), 'w') as unmapped2: self.write('... remapping\n') self.parent.update() self.progress_bar['value'] = 0 remap(fastq1, fastq2, prelim_csv, remap_csv, counts_csv, conseq_csv, unmapped1, unmapped2, self.workdir, nthreads=self.nthreads, callback=self.callback, stderr=error_log) # prepare file handles for conversion from SAM format to alignment with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \ open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'wb') as aligned_csv, \ open(os.path.join(self.workdir, prefix + '.insert.csv'), 'wb') as insert_csv, \ open(os.path.join(self.workdir, prefix + '.failed.csv'), 'wb') as failed_csv: self.write('... converting into alignment\n') self.parent.update() sam2aln(remap_csv, aligned_csv, insert_csv, failed_csv, nthreads=self.nthreads) with open(os.path.join(self.workdir, prefix + '.aligned.csv'), 'rU') as aligned_csv, \ open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'wb') as nuc_csv, \ open(os.path.join(self.workdir, prefix + '.amino.csv'), 'wb') as amino_csv, \ open(os.path.join(self.workdir, prefix + '.coord_ins.csv'), 'wb') as coord_ins_csv, \ open(os.path.join(self.workdir, prefix + '.conseq.csv'), 'wb') as conseq_csv, \ open(os.path.join(self.workdir, prefix + '.failed_align.csv'), 'wb') as failed_align_csv, \ open(os.path.join(self.workdir, prefix + '.nuc_variants.csv'), 'wb') as nuc_variants_csv: self.parent.update() aln2counts(aligned_csv, nuc_csv, amino_csv, coord_ins_csv, conseq_csv, failed_align_csv, nuc_variants_csv, callback=self.callback) self.write('... generating coverage plots\n') self.parent.update() with open(os.path.join(self.workdir, prefix + '.amino.csv'), 'rU') as amino_csv: image_paths += coverage_plot(amino_csv) self.write('... performing g2p scoring on samples covering HIV-1 V3\n') self.parent.update() with open(os.path.join(self.workdir, prefix + '.remap.csv'), 'rU') as remap_csv, \ open(os.path.join(self.workdir, prefix + '.nuc.csv'), 'rU') as nuc_csv, \ open(os.path.join(self.workdir, prefix + '.g2p.csv'), 'wb') as g2p_csv: sam_g2p(pssm=self.pssm, remap_csv=remap_csv, nuc_csv=nuc_csv, g2p_csv=g2p_csv) def build_run_summary(self, sample_count, error_count): summary = '{} sample'.format(sample_count) if sample_count != 1: summary += 's' if error_count > 0: summary += ' with {} error'.format(error_count) if error_count > 1: summary += 's' return summary def process_files(self): """ Perform MiCall data processing on FASTQ files in working directory. """ # look for FASTQ files fastq_files = self.open_files() if len(fastq_files) == 0: return savedir_setting_name = 'results_path' savedir = self.config.get(savedir_setting_name, '') savedir = tkFileDialog.askdirectory( title='Choose a folder to save results', initialdir=savedir) if not savedir: return self.config[savedir_setting_name] = savedir if os.path.exists(savedir) and os.listdir(savedir): self.write('Run FAILED - results folder is not empty: {}\n'.format( savedir)) return workdir_purged_setting_name = 'workdir_purged' is_workdir_purged = self.config.get(workdir_purged_setting_name) if is_workdir_purged is None: self.config[workdir_purged_setting_name] = is_workdir_purged = True self.write_config() self.workdir = os.path.join(savedir, 'working') if os.path.exists(self.workdir): shutil.rmtree(self.workdir) self.make_tree(self.workdir) os.chdir(self.workdir) # transfer FASTQ.gz files to working folder self.callback(progress=0, max_progress=len(fastq_files)) self.target_files = [] for file_index, src in enumerate(fastq_files): if src.startswith(self.workdir): # Working file from previous run. continue self.callback(progress=file_index) filename = os.path.basename(src) prefix = filename.split('.')[0] dest = os.path.join(self.workdir, filename) if '_R1_001' in dest or 'censored1' in dest: self.target_files.append(dest.replace('.gz', '')) # neither file type is present if not dest.endswith('.gz'): shutil.copy(src, dest) else: dest = os.path.join(self.workdir, prefix + '.fastq') with gzip.open(src, 'rb') as zip_src, open(dest, 'w') as fastq_dest: shutil.copyfileobj(zip_src, fastq_dest) self.callback(progress=len(fastq_files)) # remove duplicate entries self.target_files = sorted(set(self.target_files)) self.write( 'Transferred %d sets of FASTQ files to working directory.\n' % len(self.target_files)) image_paths = [] prefixes = [] error_count = 0 sample_count = len(self.target_files) run_summary = self.build_run_summary(sample_count, error_count) with open(os.path.join(savedir, 'micall.log'), 'w') as error_log: for sample_index, fastq1 in enumerate(self.target_files): try: progress = '{} of {}'.format(sample_index + 1, run_summary) self.process_sample(fastq1, progress, prefixes, image_paths, error_log) except: msg = traceback.format_exc() self.write(msg) error_log.write(msg) error_count += 1 run_summary = self.build_run_summary( sample_count, error_count) # collate results to results folder for target_file, extension in files_to_collate: if extension is None: extension = '.' + target_file collate.collate_named_files(src_dir=self.workdir, sample_list=prefixes, extension=extension, output_path=os.path.join( savedir, target_file)) # copy coverage plots imagedir = os.path.join(savedir, 'coverage') if not os.path.exists(imagedir): os.mkdir(imagedir) for src in image_paths: dest = os.path.join(imagedir, os.path.basename(src)) shutil.move(src, dest) # clean up working files os.chdir(savedir) if is_workdir_purged: shutil.rmtree(self.workdir) self.write('Run complete: {}.\n'.format(run_summary)) def report_callback_exception(self, exc_type, exc_value, exc_traceback): message = ''.join( traceback.format_exception(exc_type, exc_value, exc_traceback)) self.write(message)
class LowerScrollingFrame(ScrollableFrame): #self.mangaFrame ==> the MangaFrame that we get our image and updates from def __init__(self,parent,*args,**kwargs): self.parent=parent ScrollableFrame.__init__(self,self.parent,*args,**kwargs) self.disableDynamicRows() #really annoying to have it on self.__body() self.mangaFrame=None self.imageNotFound=self.image=ImageTk.PhotoImage(Image.open("Image-not-found.gif")) self.image=self.imageNotFound self.redraw() def __body(self): self.BUTTONS={} self.BUTTONS["Update"]=Button(self,text="Update",command=self.updateManga) self.BUTTONS["CheckForUpdates"]=Button(self,text="Check Updates",command=self.updateManga_check) self.BUTTONS["Delete"]=Button(self,text="Delete",command=self.deleteManga) self.BUTTONS["Update"].grid(row=0,column=0,sticky=N+S+E+W) self.BUTTONS["CheckForUpdates"].grid(row=1,column=0,sticky='nsew') self.BUTTONS["Delete"].grid(row=2,column=0,sticky=N+S+E+W) self.LABELS={} self.LABELS["Status"]=Label(self,text="Status:\nUnknown") self.LABELS["ChapterCount"]=Label(self,text="Chapters:\nUnknown") self.LABELS["Updates"]=Label(self,text="Updates:\nUnknown") self.LABELS["Summary"]=LabelResizing(self,text="Summary:\n") self.LABELS["Picture"]=Label(self,image=None) self.LABELS["UpdatingStatus"]=Label(self,text="") self.LABELS["Status"].grid(row=0,column=1) self.LABELS["ChapterCount"].grid(row=1,column=1) self.LABELS["Updates"].grid(row=2,column=1) self.LABELS["Summary"].grid(row=3,column=0,sticky='nwe') self.LABELS["Picture"].grid(row=0,column=2,rowspan=5) self.LABELS["UpdatingStatus"].grid(row=5,column=0,columnspan=3) self.PROGRESSBAR=Progressbar(self) self.PROGRESSBAR.grid(row=6,column=0,columnspan=3,sticky=E+W) self.bindChidrenScrolling() self.grid_columnconfigure(0,weight=1) self.grid_columnconfigure(1,weight=2) def setManga(self,MangaFrame): #this should be a manga frame self.mangaFrame=MangaFrame self.image=self.mangaFrame.getImage() self.redraw() def redraw(self,*args): try: if self.mangaFrame.inProgress==False:self.BUTTONS["Update"].config(text="Update") else:self.BUTTONS["Update"].config(text="Cancel") self.LABELS["ChapterCount"].config(text="{} Chapters".format(self.mangaFrame.numberOfChapters())) self.LABELS["Updates"].config(text="{} Updates".format(self.mangaFrame.numberOfUpdates())) self.progressSet(self.mangaFrame.getProgress()) self.LABELS["UpdatingStatus"].config(text=self.mangaFrame.getStatus()) self.LABELS["Summary"].config(text="Summary: "+self.mangaFrame.getSummary()) except Exception as e: print e self.LABELS["Status"].config(text="Status:\nUnknown") self.LABELS["ChapterCount"].config(text="Chapters:\nUnknown") self.LABELS["Updates"].config(text="Updates:\nUnknown") self.progressReset() self.LABELS["UpdatingStatus"].config(text="") self.LABELS["Summary"].config(text="Summary:\nUnknown") self.LABELS["Picture"].config(image=self.image) def progressSet(self,value): self.PROGRESSBAR.config(value=value) def progressStep(self,value): self.PROGRESSBAR.step(value) def progressReset(self): self.PROGRESSBAR.config(value=0) def updateManga(self): if not self.mangaFrame.inProgress:self.mangaFrame.updateManga(self) else: self.mangaFrame.cancelUpdate() self.redraw() def updateManga_check(self): self.mangaFrame.updateManga_check() #look to see if there are any updates self.redraw() #change the number we have for the number of updates def deleteManga(self): rmtree("files/"+self.mangaFrame.getName()) self.parent.populateLibrary() self.mangaFrame=None self.image=self.imageNotFound self.redraw()
class CoilSnakeFrontend: PREFS_FNAME = "prefs.yml" def __init__(self): try: with open(self.PREFS_FNAME, 'r') as f: self._prefs = yaml.load(f, Loader=yaml.CSafeLoader) except IOError: self._prefs = { 'Emulator': "", 'CCC': "", 'import_proj': "", 'import_baserom': "", 'import_rom': "", 'export_proj': "", 'export_rom': "", 'title': 0, } def savePrefs(self): with open(self.PREFS_FNAME, "w") as f: yaml.dump(self._prefs, f, Dumper=yaml.CSafeDumper) def toggleTitles(self): self._prefs["title"] = (~(self._prefs["title"]))|1 self.savePrefs() def aboutMenu(self): am = Toplevel(self._root) Label(am, text="CoilSnake " + _version, font=("Helvetica", 16)).pack(fill=X) Label(am, text= "Released on " + _releaseDate + ".\n\n" + "Created by MrTenda.\n\n" + "With help from\n" + " Penguin, Mr. Accident, Goplat,\n" + " AnyoneEB, Captain Bozo,\n" + " and the rest of the PK Hack community.", anchor="w",justify="left",bg="white",borderwidth=5, relief=GROOVE).pack( fill='both', expand=1) Button(am, text="Toggle Alternate Titles", command=self.toggleTitles).pack(fill=X) Button(am, text="Close", command=am.destroy).pack(fill=X) am.resizable(False, False) am.title("About") def setText(self, entry, str): entry.delete(0, END) entry.insert(0, str) entry.xview(END) def setEmulatorExe(self): self._prefs["Emulator"] = tkFileDialog.askopenfilename( parent=self._root, title="Select an Emulator Executable", initialfile=self._prefs["Emulator"]) self.savePrefs() def setCccExe(self): self._prefs["CCC"] = tkFileDialog.askopenfilename( parent=self._root, title="Select the CCC Executable", initialfile=self._prefs["CCC"]) self.savePrefs() def browseForRom(self, entry, save=False): if save: fname = tkFileDialog.asksaveasfilename( parent=self._root, title="Select an output ROM", filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')]) else: fname = tkFileDialog.askopenfilename( parent=self._root, title="Select a ROM", filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')]) self.setText(entry, fname) def browseForProject(self, entry, save=False): fname = tkFileDialog.askdirectory( parent=self._root, title="Select a Project Directory", mustexist=(not save)) self.setText(entry, fname) def runRom(self, entry): romFname = entry.get() if self._prefs["Emulator"] == "": tkMessageBox.showerror(parent=self._root, title="Error", message="""Emulator executable not specified. Please specify it in the Preferences menu.""") elif romFname != "": Popen([self._prefs["Emulator"], romFname]) def resetConsole(self): self._console.delete(1.0, END) self._console.see(END) def doExport(self, romEntry, projEntry): if (romEntry.get() != "") and (projEntry.get() != ""): # Update the GUI self.resetConsole() self._exportB["state"] = DISABLED self._importB["state"] = DISABLED # Save the fields to preferences self._prefs["export_rom"] = romEntry.get() self._prefs["export_proj"] = projEntry.get() self.savePrefs() self._progBar["value"] = 0 print "Initializing CoilSnake\n" self._cs = CoilSnake.CoilSnake() self._progBar.step(10) thread = Thread(target=self._doExportHelp, args=(romEntry.get(), projEntry.get()+"/Project.snake", time(), )) thread.start() def _doExportHelp(self, rom, proj, startTime): try: self._cs.romToProj(rom, proj) print "Done! (Took %0.2fs)" % (time()-startTime) except Exception as inst: print "\nError! Something went wrong:" print_exc() self._progBar["value"] = 0 self._exportB["state"] = NORMAL self._importB["state"] = NORMAL del(self._cs) def doImport(self, projEntry, cleanRomEntry, romEntry): if self._prefs["CCC"] == "": tkMessageBox.showerror(parent=self._root, title="Error", message="""CCScript Compiler executable not specified. Please specify it in the Preferences menu.""") elif ((projEntry.get() != "") and (cleanRomEntry.get() != "") and (romEntry.get() != "")): # Update the GUI self.resetConsole() self._exportB["state"] = DISABLED self._importB["state"] = DISABLED self._importRunB["state"] = DISABLED # Save the fields to preferences self._prefs["import_proj"] = projEntry.get() self._prefs["import_baserom"] = cleanRomEntry.get() self._prefs["import_rom"] = romEntry.get() self.savePrefs() oldRom = cleanRomEntry.get() newRom = romEntry.get() projDir = projEntry.get() # Reset the progress bar self._progBar["value"] = 0 # Copy the clean rom to the output rom self._console.delete(1.0, END) print "Copying ROM" copyfile(oldRom, newRom) self._progBar.step(2) # Get a list of the script filenames in projDir/ccscript scriptFnames = [ projDir + "/ccscript/" + x for x in listdir(projDir + "/ccscript") if x.endswith('.ccs') ] # Compile scripts using the CCC, and put the data at $F00000 print "Calling external CCScript Compiler" process = Popen( [self._prefs["CCC"], "-n", "-o", newRom, "-s", "F00000", "--summary", projDir + "/ccscript/summary.txt"] + scriptFnames) process.wait() self._progBar.step(4) # Run CoilSnake as usual print "Initializing CoilSnake\n" self._cs = CoilSnake.CoilSnake() self._progBar.step(4) thread = Thread(target=self._doImportHelp, args=(projDir+"/Project.snake", newRom, time())) thread.start() def _doImportHelp(self, proj, rom, startTime): try: self._cs.projToRom(proj, rom, rom) print "Done! (Took %0.2fs)" % (time()-startTime) except Exception as inst: print "\nError! Something went wrong:" print_exc() self._progBar["value"] = 0 self._exportB["state"] = NORMAL self._importB["state"] = NORMAL self._importRunB["state"] = NORMAL del(self._cs) def expandRom(self, ex=False): r = Rom.Rom('romtypes.yaml') fname = tkFileDialog.askopenfilename( parent=self._root, title="Select a ROM to expand", filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')]) r.load(fname) EbRomExpander.expandRom(r, ex) r.save(fname) del(r) tkMessageBox.showinfo("Expansion Successful", "Your ROM was expanded.") def expandRomEx(self): self.expandRom(ex=True) def main(self): self._root = Tk() if self._prefs["title"] == 1: self._root.wm_title(getTitle() + " " + _version) else: self._root.wm_title("CoilSnake" + " " + _version) if self._prefs["title"] == 0: self._prefs["title"] = 1 self.savePrefs() menuBar = Menu(self._root) # Preferences pulldown menu prefMenu = Menu(menuBar, tearoff=0) prefMenu.add_command(label="CCScript Compiler Executable", command=self.setCccExe) prefMenu.add_command(label="Emulator Executable", command=self.setEmulatorExe) menuBar.add_cascade(label="Preferences", menu=prefMenu) # Tools pulldown menu toolsMenu = Menu(menuBar, tearoff=0) toolsMenu.add_command(label="Expand ROM to 32 MBit", command=self.expandRom) toolsMenu.add_command(label="Expand ROM to 48 MBit", command=self.expandRomEx) menuBar.add_cascade(label="Tools", menu=toolsMenu) # Help menu helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About", command=self.aboutMenu) menuBar.add_cascade(label="Help", menu=helpMenu) self._root.config(menu=menuBar) # Left side: Export a=Label(self._root, text="ROM -> New Project",justify=CENTER).grid( row=0, column=1, columnspan=1) # ROM file selector Label(self._root, text="Input ROM:").grid( row=1, column=0, sticky=E) inRom = Entry(self._root) inRom.grid(row=1, column=1) self.setText(inRom, self._prefs["export_rom"]) def browseTmp(): self.browseForRom(inRom) def runTmp(): self.runRom(inRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=1, column=2, sticky=W) Button(self._root, text="Run", command=runTmp).grid(row=1, column=3, sticky=W) # Project dir selector Label(self._root, text="Output Directory:").grid( row=2, column=0, sticky=E) outProj = Entry(self._root) outProj.grid(row=2, column=1) self.setText(outProj, self._prefs["export_proj"]) def browseTmp(): self.browseForProject(outProj, save=True) Button(self._root, text="Browse...", command=browseTmp).grid(row=2, column=2, sticky=W) # Export Button def exportTmp(): self.doExport(inRom, outProj) self._exportB = Button(self._root, text="Export", command=exportTmp) self._exportB.grid(row=4, column=1, columnspan=1, sticky=W+E) # Right side: Import Label(self._root, text="Project -> New ROM").grid( row=0, column=5, columnspan=1) # Base ROM file selector Label(self._root, text="Base Expanded ROM:").grid( row=1, column=4, sticky=E) baseRom = Entry(self._root) baseRom.grid(row=1, column=5) self.setText(baseRom, self._prefs["import_baserom"]) def browseTmp(): self.browseForRom(baseRom) def runTmp(): self.runRom(baseRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=1, column=6) Button(self._root, text="Run", command=runTmp).grid(row=1, column=7, sticky=W) # Project dir selector Label(self._root, text="Project Directory:").grid( row=2, column=4, sticky=E) inProj = Entry(self._root, text=self._prefs["import_proj"]) inProj.grid(row=2, column=5) self.setText(inProj, self._prefs["import_proj"]) def browseTmp(): self.browseForProject(inProj, save=False) Button(self._root, text="Browse...", command=browseTmp).grid(row=2, column=6) # ROM file selector Label(self._root, text="Output ROM:").grid( row=3, column=4, sticky=E) outRom = Entry(self._root, text=self._prefs["import_rom"]) outRom.grid(row=3, column=5) self.setText(outRom, self._prefs["import_rom"]) def browseTmp(): self.browseForRom(outRom, save=True) def runTmp(): self.runRom(outRom) Button(self._root, text="Browse...", command=browseTmp).grid(row=3, column=6) self._importRunB = Button(self._root, text="Run", command=runTmp) self._importRunB.grid(row=3, column=7, sticky=W) # Import Button def importTmp(): self.doImport(inProj, baseRom, outRom) self._importB = Button(self._root, text="Import", command=importTmp) self._importB.grid(row=4, column=5, columnspan=1, sticky=W+E) # Progress bar self._progBar = Progressbar(self._root, orient=HORIZONTAL, mode='determinate') self._progBar.grid(row=5, column=0, columnspan=8, sticky=W+E) def updProg(dp): Progress.__updateProgress__(dp) # Note: The number of modules is hardcoded here as "12" self._progBar.step((90.0/12) * (dp/100.0)) Progress.updateProgress = updProg # Console consoleFrame = Frame(self._root) consoleFrame.grid(row=6, column=0, columnspan=8, sticky=W+E) s = Scrollbar(consoleFrame) self._console = Text(consoleFrame, width=80, height=6) s.pack(side=RIGHT, fill=Y) self._console.pack(fill=X) s.config(command=self._console.yview) self._console.config(yscrollcommand=s.set) # Stdout Redirector class StdoutRedirector: def __init__(self, textArea): self._tA = textArea def write(self,str): if str.startswith("\b\b\b\b\b\b\b\b"): self._tA.delete("end-9c", "end") self._tA.insert(END, str[8:]) else: self._tA.insert(END, str) self._tA.see(END) def flush(self): pass self._consoleStdout = StdoutRedirector(self._console) sys.stdout = self._consoleStdout sys.stderr = self._consoleStdout self._root.mainloop()
class iface(): def __init__(self): root.title("MuBlas") self.lab1 = Label(root, text="Music directory") self.lab1.grid(row = 0, column = 0) self.music_entry = Entry(root,width=50,bd=1) self.music_entry.grid(row = 1, column = 0) self.m_dir_but = Button(root) self.m_dir_but["text"] = "Choose directory" self.m_dir_but.grid(row = 1, column = 1) self.m_dir_but.bind("<Button-1>", self.ask_mus_dir) self.lab3 = Label(root, text="Size in MBytes") self.lab3.grid(row = 2, column = 0) self.size_entry = Entry(root,width=5,bd=1) self.size_entry.grid(row = 2, column = 1) self.lab2 = Label(root, text="Destination directory") self.lab2.grid(row = 3, column = 0) self.destination_entry = Entry(root,width=50,bd=1) self.destination_entry.grid(row = 4, column = 0) self.dest_dir_but = Button(root) self.dest_dir_but["text"] = "Choose directory" self.dest_dir_but.grid(row = 4, column = 1) self.dest_dir_but.bind("<Button-1>", self.ask_out_dir) self.process_but = Button(root) self.process_but["text"] = "Run" self.process_but.grid(row = 6, column = 0) self.process_but.bind("<Button-1>", self.start) self.exit_but = Button(root) self.exit_but["text"] = "Exit" self.exit_but.grid(row = 6, column = 1) self.exit_but.bind("<Button-1>", self.exit_app) self.pr_bar = Progressbar(root, mode='indeterminate') self.pr_bar.grid(row = 5, column = 0, sticky = "we", columnspan = 2) #self.pr_bar.start() def ask_mus_dir(self, event): dirname = tkFileDialog.askdirectory(parent = root,initialdir="/",title='Please select a directory') self.music_entry.delete(0, END) self.music_entry.insert(0, dirname) def ask_out_dir(self, event): dirname = tkFileDialog.askdirectory(parent = root,initialdir="/",title='Please select a directory') self.destination_entry.delete(0, END) self.destination_entry.insert(0, dirname) def start(self, event): self.pr_bar.start() self.process_but["state"] = DISABLED m_dir = self.music_entry.get() d_dir = self.destination_entry.get() sz = 1024000 * int(self.size_entry.get()) mbls = MuBlas.MuBlas(m_dir, d_dir, sz) mbls.start() self.process_but["state"] = NORMAL self.pr_bar.stop() def exit_app(self, event): root.destroy() def process(self):
class GUI: def __init__(self, master): ################-GLOBAL-VARS-############################ self.version = 1.1 self.loadingMsg = "Loading......................." self.driver = "" self.tupleDates = [] self.roomTimeList = [] self.roomIndex = 0 self.outputTimeArray = [] self.userInfo = [] self.master = master self.outputEmail = "" ###############-WINDOW-SETUP-############################ self.master.title("LibCal Booker v" + str(self.version)) self.master.resizable(width=False, height=False) self.master.protocol("WM_DELETE_WINDOW", self.window_close) self.master.createcommand('exit', self.window_close) self.master.bind('<Return>', self.submit_click) ###############-LOAD-FILE-############################### # TODO: Check fields of json, if do not match, transfer over files try: with open("userInfo.json") as data_file: self.userInfo = json.load(data_file) except: print "No existing user" with open("userInfo.json", "w+") as data_file: self.userInfo = dict(version=self.version, first="Mitchell", last="Pynn", email="*****@*****.**", override=0, confirm=1, browser=0, firstLoad=True, authEmail="") json.dump(self.userInfo, data_file) ###################-DATE SELECTION-###################### # set up availDates self.availDates = [self.loadingMsg] # set up chosen date and give default value self.chosenDate = StringVar(self.master) self.chosenDate.set(self.loadingMsg) # set up dateOptionMenu self.dateOptionMenu = OptionMenu(self.master, self.chosenDate, *self.availDates, command=self.date_click) self.dateOptionMenu.grid(row=0, column=0, columnspan=1, sticky=(N, S, E, W), pady=(8, 0), padx=(5, 0)) ##################-ROOM SELECTION-###################### # set up availRooms self.availRooms = [ 'LI 1004', 'LI 1006', 'LI 1007', 'LI 1008', 'LI 1009', 'LI 1010', 'LI 4001', 'LI 4002', 'LI 4003', 'LI 4004', 'LI 4005', 'LI 4006', 'LI 4007', 'LI 4008', 'LI 4009', 'LI 4010' ] self.availTimes = [ '8:00am - 8:30am', '8:30am - 9:00am', '9:00am - 9:30am', '9:30am - 10:00am', '10:00am - 10:30am', '10:30am - 11:00am', '11:00am - 11:30am', '11:30am - 12:00pm', '12:00pm - 12:30pm', '12:30pm - 1:00pm', '1:00pm - 1:30pm', '1:30pm - 2:00pm', '2:00pm - 2:30pm', '2:30pm - 3:00pm', '3:00pm - 3:30pm', '3:30pm - 4:00pm', '4:00pm - 4:30pm', '4:30pm - 5:00pm', '5:00pm - 5:30pm', '5:30pm - 6:00pm', '6:00pm - 6:30pm', '6:30pm - 7:00pm', '7:00pm - 7:30pm', '7:30pm - 8:00pm', '8:00pm - 8:30pm', '8:30pm - 9:00pm', '9:00pm - 9:30pm', '9:30pm - 10:00pm', '10:00pm - 10:30pm', '10:30pm - 11:00pm', '11:00pm - 11:30pm', '11:30pm - 11:59pm' ] # set up chosen room and give default value self.chosenRoom = StringVar(self.master) self.chosenRoom.set(self.availRooms[0]) # set up roomOptionMenu self.roomOptionMenu = OptionMenu(self.master, self.chosenRoom, *self.availRooms, command=self.room_click) self.roomOptionMenu.grid(row=1, column=0, columnspan=1, sticky=(N, S, E, W), padx=(5, 0), pady=(5, 0)) ##################-TIME SELECTION-#################### self.timeOptionList = Listbox(self.master, selectmode=EXTENDED, height=20, exportselection=0, takefocus=0) self.timeOptionList.grid(row=2, column=0, rowspan=200, columnspan=1, sticky=(N, S, E, W), padx=(5, 0), pady=5) self.timeOptionList.insert(0, self.loadingMsg) self.timeOptionList.config(state=DISABLED) #################-BUTTONS-########################## # user info self.infoLabel = Label(self.master, text="[ U S E R I N F O ]", font=("Helvetica", 16, "bold")) self.infoLabel.grid(row=0, column=1, columnspan=2, sticky=E + W) # first Name label and input self.fnameLabel = Label(self.master, text="First: ", font=("Helvetica", 12, "bold")) self.fnameLabel.grid(row=1, column=1, sticky=W) self.fnameEntry = Entry(self.master) self.fnameEntry.grid(row=1, column=2, stick=E + W, padx=(0, 5)) self.fnameEntry.insert(0, self.userInfo["first"]) # last name label and input self.lnameLabel = Label(self.master, text="Last: ", font=("Helvetica", 12, "bold")) self.lnameLabel.grid(row=2, column=1, sticky=W) self.lnameEntry = Entry(self.master) self.lnameEntry.grid(row=2, column=2, stick=E + W, padx=(0, 5)) self.lnameEntry.insert(0, self.userInfo["last"]) # email label and entry self.emailLabel = Label(self.master, text="Email: ", font=("Helvetica", 12, "bold")) self.emailLabel.grid(row=3, column=1, sticky=W) self.emailEntry = Entry(self.master) self.emailEntry.grid(row=3, column=2, stick=E + W, padx=(0, 5)) self.emailEntry.insert(0, self.userInfo["email"]) # showBrowser checkbox self.browserVal = IntVar(self.master) self.browserVal.set(self.userInfo["browser"]) self.browser = Checkbutton(self.master, text="Show web browser", variable=self.browserVal, command=self.browser_show, onvalue=1, offvalue=0, font=("Helvetica", 12), takefocus=0) self.browser.grid(row=4, column=2, sticky=W) # override checkbox self.overrideVal = IntVar(self.master) self.overrideVal.set(self.userInfo["override"]) self.override = Checkbutton(self.master, text="Override 2hr max", variable=self.overrideVal, onvalue=1, offvalue=0, font=("Helvetica", 12), takefocus=0) self.override.grid(row=5, column=2, sticky=W) # confirm checkbox self.confirmVal = IntVar(self.master) self.confirmVal.set(self.userInfo["confirm"]) self.confirm = Checkbutton(self.master, text="Enable confirm dialog", variable=self.confirmVal, onvalue=1, offvalue=0, font=("Helvetica", 12), takefocus=0) self.confirm.grid(row=6, column=2, sticky=W) # submit button self.submit = Button(self.master, text="Submit", command=self.submit_click, takefocus=0) self.submit.grid(row=8, column=2, sticky=(N, S, E, W), padx=(0, 5), pady=(0, 5)) self.submit["state"] = "disabled" # loading bar self.loadingBar = Progressbar(self.master, orient=HORIZONTAL, length=100, mode='determinate') self.loadingBar.grid(row=9, column=2, sticky=(N, S, E, W), padx=(0, 5), pady=(0, 5)) self.loadingBar["value"] = 10 # email self.emm = Button(self.master, text="email tester", command=self.test_email_click, takefocus=0) self.emm.grid(row=10, column=2, sticky=(N, S, E, W), padx=(0, 5), pady=(0, 5)) # update skeleton GUI, then load data self.master.update() self.load_data() # make sure window on top self.master.lift() # show welcome message if first load if self.userInfo["firstLoad"]: tkMessageBox.showinfo( "Welcome", "Currently, booking multiple rooms is not permitted. You are limited to only booking one room per session. However, booking multiple time slots per room is permitted.\n\nMake sure to update the [ USER INFO ] section with your own name and email. \n\nCreated by Mitchell Pynn " ) def test_email_click(self): self.outputEmail = "*****@*****.**" def email_click(self, randVals): """ Shows basic usage of the Gmail API. Creates a Gmail API service object and outputs a list of label names of the user's Gmail account. """ credentials = self.get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('gmail', 'v1', http=http) userProfile = service.users().getProfile(userId='me').execute() # set user JSON auth email self.userInfo["authEmail"] = userProfile['emailAddress'] for idItem in randVals: print idItem try: # please newer_than:1d to: + idItem email1 = service.users().messages().list(userId='me', q='to:' + idItem).execute() output = email1['messages'] text = service.users().messages().get( userId='me', id=output[0]['id']).execute() ampFix = text['snippet'].replace('&', '&') confirmUrl = \ re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+|]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', ampFix)[ 0] + '&m=confirm' print(confirmUrl) self.driver.execute_script("window.open('" + confirmUrl + "', 'new_window')") self.driver.switch_to.window(self.driver.window_handles[1]) try: # wait until page is loaded and success element found element = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located( (By.CLASS_NAME, "final_msg"))) # close tab and return to main page self.driver.close() self.driver.switch_to.window(self.driver.window_handles[0]) except: print "Could not book room " + idItem except: print('An error occurred confirming the room: ????') def get_credentials(self): """Gets valid user credentials from storage. If nothing has been stored, or if the stored credentials are invalid, the OAuth2 flow is completed to obtain the new credentials. Returns: Credentials, the obtained credential. """ home_dir = os.path.expanduser('~') credential_dir = os.path.join(home_dir, '.credentials') if not os.path.exists(credential_dir): os.makedirs(credential_dir) credential_path = os.path.join(credential_dir, self.outputEmail + '.json') store = Storage(credential_path) credentials = store.get() if not credentials or credentials.invalid: flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) flow.user_agent = APPLICATION_NAME if flags: credentials = tools.run_flow(flow, store, flags) else: # Needed only for compatibility with Python 2.6 credentials = tools.run(flow, store) print('Storing credentials to ' + credential_path) return credentials def browser_show(self): if self.browserVal.get() == 1: # hide window/throw in corner self.driver.set_window_position(0, 0) self.driver.set_window_size(100, 600) else: # hide window/throw in corner self.driver.set_window_position(3000, 3000) self.driver.set_window_size(100, 300) def save_data(self): # update userFile when submitted with open("userInfo.json", 'r+') as data_file: self.userInfo["first"] = self.fnameEntry.get() self.userInfo["last"] = self.lnameEntry.get() self.userInfo["email"] = self.emailEntry.get() self.userInfo["confirm"] = self.confirmVal.get() self.userInfo["override"] = self.overrideVal.get() self.userInfo["browser"] = self.browserVal.get() self.userInfo["firstLoad"] = False data_file.seek(0) json.dump(self.userInfo, data_file) data_file.truncate() def window_close(self): # save data self.save_data() # destroy GUI and quit driver self.master.destroy() self.driver.quit() # clean log files if exist (maybe good to keep?) dir = os.listdir(os.getcwd()) for item in dir: if item.endswith(".log"): os.remove(os.path.join(os.getcwd(), item)) # from -> http://stackoverflow.com/a/12578715 def is_windows_64bit(self): if 'PROCESSOR_ARCHITEW6432' in os.environ: return True return os.environ['PROCESSOR_ARCHITECTURE'].endswith('64') def load_data(self): self.loadingBar["value"] = 25 self.master.update_idletasks() # connect to webdriver - Try Google Chrome, then Firefox chrome = False try: chromeOptions = webdriver.ChromeOptions() prefs = { "profile.managed_default_content_settings.images": 2, "profile.managed_default_content_settings.stylesheet": 2 } chromeOptions.add_experimental_option("prefs", prefs) if platform.system() == 'Darwin': self.driver = webdriver.Chrome( executable_path=os.getcwd() + '/bin/chrome/chromedriverDarwin', chrome_options=chromeOptions) elif platform.system() == 'Windows': self.driver = webdriver.Chrome( executable_path=os.getcwd() + '/bin/chrome/chromedriverWindows.exe', chrome_options=chromeOptions) elif platform.system() == 'Linux': self.driver = webdriver.Chrome(executable_path=os.getcwd() + '/bin/chrome/chromedriverLinux', chrome_options=chromeOptions) else: print "Fatal error - incompatible operating system" exit() chrome = True except: print "Could not load Chrome, trying Firefox." if not chrome: try: # setup firefox profile, no images, no css for speed firefox_profile = webdriver.FirefoxProfile() firefox_profile.add_extension( os.getcwd() + "/bin/ext/quickjava-2.1.2-fx.xpi") firefox_profile.set_preference( "thatoneguydotnet.QuickJava.curVersion", "2.1.2.1" ) ## Prevents loading the 'thank you for installing screen' firefox_profile.set_preference( "thatoneguydotnet.QuickJava.startupStatus.Images", 2) ## Turns images off firefox_profile.set_preference( "thatoneguydotnet.QuickJava.startupStatus.AnimatedImage", 2) ## Turns animated images off firefox_profile.set_preference( "thatoneguydotnet.QuickJava.startupStatus.CSS", 2) ## CSS firefox_profile.set_preference( "thatoneguydotnet.QuickJava.startupStatus.Flash", 2) ## Flash firefox_profile.set_preference( "thatoneguydotnet.QuickJava.startupStatus.Java", 2) ## Java firefox_profile.set_preference( "thatoneguydotnet.QuickJava.startupStatus.Silverlight", 2) ## Silverlight # load driver according to operating system, if platform.system() == 'Darwin': self.driver = webdriver.Firefox( executable_path=os.getcwd() + '/bin/gecko/geckodriverDarwin', firefox_profile=firefox_profile) elif platform.system() == 'Windows': if self.is_windows_64bit(): self.driver = webdriver.Firefox( executable_path=os.getcwd() + '/bin/gecko/geckodriverWindows64.exe', firefox_profile=firefox_profile) else: self.driver = webdriver.Firefox( executable_path=os.getcwd() + '/bin/gecko/geckodriverWindows.exe', firefox_profile=firefox_profile) elif platform.system() == 'Linux': self.driver = webdriver.Firefox( executable_path=os.getcwd() + '/bin/gecko/geckodriverLinux', firefox_profile=firefox_profile) else: print "Fatal error - incompatible operating system" exit() except: # get no firefox exception print "You must have Firefox or Google Chrome installed" exit(6) # hide window/throw in corner or show self.browser_show() self.master.lift() self.loadingBar["value"] = 50 self.master.update_idletasks() # load intial site self.driver.get("http://libcal.lakeheadu.ca/rooms_acc.php?gid=13445") assert "The Chancellor Paterson Library" in self.driver.title # scrape dates, only have to do once self.tupleDates = collections.OrderedDict() dateWheel = Select(self.driver.find_element_by_id("datei")) for date in dateWheel.options: self.tupleDates[date.text] = date.get_attribute("value") self.loadingBar["value"] = 75 self.master.update_idletasks() # remove loading option, pull dates from tuple to list # set chosen date to top entry in date list # format: {'Monday June 1st': '06-01-17'} self.availDates.remove(self.loadingMsg) for key, value in self.tupleDates.iteritems(): self.availDates.append(key) self.chosenDate.set(self.availDates[0]) # get menu, clear and add dates menu = self.dateOptionMenu["menu"] menu.delete(0, "end") for val in self.availDates: menu.add_command( label=val, command=lambda pvalue=val: self.date_click(pvalue)) # update GUI, will show current date in selection self.master.update() # initial load data self.date_click() # make sure on top self.master.lift() def date_click(self, value=""): # do nothing if same day clicked if value: if self.chosenDate.get() == value: return else: self.chosenDate.set(value) self.loadingBar["value"] = 20 self.submit["state"] = "disabled" self.master.update_idletasks() # clear timeOptionList contents, showing loading message self.timeOptionList.delete(0, END) self.timeOptionList.insert(0, self.loadingMsg) self.timeOptionList.config(state=DISABLED) if value: self.loadingBar["value"] = 40 self.master.update() # load selected date webpage self.driver.get( "http://libcal.lakeheadu.ca/rooms_acc.php?gid=13445&d=" + self.tupleDates[self.chosenDate.get()] + "&cap=0") # does this wait until page is loaded? assert "The Chancellor Paterson Library" in self.driver.title # make sure loaded? # create 2D array of [0]'s self.roomTimeList = [[0] for _ in range(16)] if value: self.loadingBar["value"] = 60 self.master.update_idletasks() self.room_click("room") def room_click(self, value=""): if value == "room": self.loadingBar["value"] = 95 else: self.loadingBar["value"] = 30 self.submit["state"] = "disabled" self.master.update_idletasks() # set roomIndex to new room self.roomIndex = self.availRooms.index(self.chosenRoom.get()) # clear timeOptionList contents, showing loading message self.timeOptionList.delete(0, END) self.timeOptionList.insert(0, self.loadingMsg) self.timeOptionList.config(state=DISABLED) if value != "room": self.loadingBar["value"] = 40 self.master.update() form = self.driver.find_element_by_id("roombookingform") if value != "room": self.loadingBar["value"] = 60 self.master.update_idletasks() rooms = form.find_elements_by_tag_name("fieldset") if value != "room": self.loadingBar["value"] = 80 self.master.update_idletasks() # don't scrape again if already loaded if self.roomTimeList[self.roomIndex] == [0]: for room in rooms: # find selected room if room.find_element_by_tag_name( "h2").text[:7] != self.chosenRoom.get(): continue # go through each room, pulling times to array times_out = [] check_boxes = room.find_elements_by_class_name("checkbox") for box in check_boxes: # output checkbox text times_out.append( self.availTimes.index( box.find_element_by_tag_name("label").text)) self.roomTimeList.insert(self.roomIndex, times_out) break # for the selected room, set time slots self.timeOptionList.config(state=NORMAL) self.timeOptionList.delete(0, END) if len(self.roomTimeList[self.roomIndex]) > 0: for timeSlot in self.roomTimeList[self.roomIndex]: self.timeOptionList.insert(END, self.availTimes[timeSlot]) else: self.timeOptionList.insert(END, "No times available") self.timeOptionList.config(state=DISABLED) # update height, update the whole list if it isnt first run self.timeOptionList.configure( height=len(self.roomTimeList[self.roomIndex])) # colorize alternating lines of the listbox for i in range(0, len(self.roomTimeList[self.roomIndex]), 2): self.timeOptionList.itemconfigure(i, background='#f0f0ff') self.loadingBar["value"] = 100 self.master.update_idletasks() # update GUI size and remove loading bar self.submit["state"] = "normal" self.master.update() def submit_click(self, value=""): if self.emailEntry.get().strip()[-13:] != "@lakeheadu.ca": tkMessageBox.showerror( "Email format error", "Please make sure to use a valid @lakeheadu.ca email address") return self.save_data() selection = self.timeOptionList.curselection() if selection == (): return if len(selection) > 4 and self.overrideVal.get() != 1: tkMessageBox.showerror("2hr Limit", "Sorry, you can only book 2hrs per day") return if self.confirmVal.get() == 1: outputTimes = "" lineBreak = '-' * (len(self.chosenDate.get()) + 2) for index in selection: pIndex = self.roomTimeList[self.roomIndex][int(index)] outputTimes += self.availTimes[pIndex] + "\n" if not tkMessageBox.askokcancel( "Please confirm the following times", self.chosenDate.get() + "\n" + lineBreak + "\n" + self.availRooms[self.roomIndex] + "\n" + outputTimes): return # if output, get times self.outputTimeArray = [] for index in selection: pIndex = self.roomTimeList[self.roomIndex][int(index)] self.outputTimeArray.append(self.availTimes[pIndex]) # book rooms self.book_times() # check if any rooms were unavailable if len(self.outputTimeArray) > 0: outputText = "The following times were unavailable to book\n----------------------------------------\n" for item in self.outputTimeArray: outputText += item + "\n" tkMessageBox.showerror("Unavailable", outputText) # clear booked room time slots, self.roomTimeList[self.roomIndex] = [0] self.room_click() def book_times(self): # refresh page try: self.driver.refresh() except: print "Could not load the browser" assert "The Chancellor Paterson Library" in self.driver.title outputText = "Successfully booked the following rooms \n" + self.chosenDate.get( ) + "\n" + '-' * (len(self.chosenDate.get()) + 2) + "\n" + self.chosenRoom.get() outputLength = 0 outputRandomId = [] self.outputEmail = self.emailEntry.get().strip( )[:-13] + "@lakeheadu.ca" while True: # get rooms form = self.driver.find_element_by_id("roombookingform") rooms = form.find_elements_by_tag_name("fieldset") for room in rooms: # find selected room if room.find_element_by_tag_name( "h2").text[:7] != self.availRooms[self.roomIndex]: continue consect = 0 selectedTimes = [] checkBoxes = room.find_elements_by_class_name("checkbox") for box in checkBoxes: # loops through times from start every time, how can I keep place of where left off? timeSlot = box.find_element_by_tag_name("label") if timeSlot.text in self.outputTimeArray: consect += 1 # adding another time will not overflow 2hrs, add it if consect <= 4: # check for consecutive, if array is blank, add time regardless # try the simplify if selectedTimes != []: for selectedIndex in selectedTimes: # check if time is in consecutive order # can I put or in between two conditions???? if (self.availTimes.index(timeSlot.text) - 1) == selectedIndex or ( self.availTimes.index( timeSlot.text) + 1) == selectedIndex: outputText += "\n" + timeSlot.text # add to selectedTimes selectedTimes.append( self.availTimes.index( timeSlot.text)) # remove timeSlot from array self.outputTimeArray.remove( timeSlot.text) # click timeSlot timeSlot.click() break else: outputText += "\n" + timeSlot.text # add to selectedTimes selectedTimes.append( self.availTimes.index(timeSlot.text)) # remove timeSlot from array self.outputTimeArray.remove(timeSlot.text) # click timeSlot timeSlot.click() # if 4 boxes are selected, break and book the selected rooms else: break # if at least one box is selected, book it, must be consecutive elif consect > 0: break break if consect > 0: # fill info of form self.driver.find_element_by_id("fname").send_keys( self.fnameEntry.get()) self.driver.find_element_by_id("lname").send_keys( self.lnameEntry.get()) # always uses random_id, override 2hrs just prevents user from booking more # then 2hrs at a time randId = self.id_generator() outputRandomId.append(randId) self.driver.find_element_by_id( "email").send_keys(self.emailEntry.get().strip()[:-13] + "+" + randId + "@lakeheadu.ca") # submit self.driver.find_element_by_id("s-lc-rm-ac-but").click() # assert it is success try: # search for success element / fail # handle failure element = WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located( (By.ID, "s-lc-rm-ac-success"))) except TimeoutException: tkMessageBox.showerror( "ERROR", "Error booking the room. Exiting...") self.driver.quit() # refresh page self.driver.refresh() # if out of times to book or cannot book times, break out if len(self.outputTimeArray) <= 0 or len( self.outputTimeArray) == outputLength: break outputLength = len(self.outputTimeArray) # print success message if len(self.outputTimeArray) <= 0: print outputRandomId tkMessageBox.showinfo("Success", outputText) # ask to confirm # if email used to book rooms does not match email authEmail ## show message that redirection is happening if tkMessageBox.askyesno( "Confirm times", "Would you like to confirm your booked times?"): # check if if self.userInfo['authEmail'] != self.outputEmail: tkMessageBox.showinfo( "Redirecting...", "Press OK and login with " + self.outputEmail + " in the browser that will open.") self.email_click(outputRandomId) # random ID generator -> http://stackoverflow.com/a/2257449 def id_generator(self, size=8, chars=string.ascii_uppercase + string.digits): return ''.join(random.choice(chars) for _ in range(size))
class Application(Frame): def run(self): appid = self.var_appid.get().strip() if len(appid) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入公众账号ID") return mch_id = self.var_mch_id.get().strip() if len(mch_id) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入商户号") return mch_key = self.var_mch_key.get().strip() if len(mch_key) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入商户密钥") return bill_date_from = self.var_bill_date_from.get().strip() if len(bill_date_from) == 0: tkMessageBox.showinfo(title=u"错误", message="请输入开始日期") return path = self.var_path.get().strip() if len(path) == 0: tkMessageBox.showinfo(title=u"错误", message="请选择输出目录") return sub_mch_id = self.txt_sub_mch_id.get(1.0, END) if len(sub_mch_id) > 0: sub_mch_ids = list(set(sub_mch_id.split())) else: sub_mch_ids = [] # save settings config.save(appid, mch_id, mch_key, sub_mch_id, path) bill_date_to = self.var_bill_date_to.get().strip() if len(bill_date_to) == 0: bill_date_to = (datetime.now() + timedelta(days=-1)).strftime("%Y%m%d") s = datetime.strptime(bill_date_from, "%Y%m%d") e = datetime.strptime(bill_date_to, "%Y%m%d") def work_proc(self, path, s, e, sub_mch_ids, event): self.btn_run.config(state='disabled') days = (e - s).days + 1 max = days * (len(sub_mch_ids) if len(sub_mch_ids) > 0 else 1) self.prg_bar.config({'maximum': max}) while s <= e: if len(sub_mch_ids) > 0: for sub_mch_id in sub_mch_ids: r = download_bill(mch_key, appid, mch_id, s, sub_mch_id) self.save_bill(r, s, mch_id, sub_mch_id) self.prg_bar.step() else: r = download_bill(mch_key, appid, mch_id, s) self.save_bill(r, s, mch_id) self.prg_bar.step() s += timedelta(days=1) self.btn_run.config(state='normal') event.set() self.running = True work_thread = threading.Thread(target=work_proc, args=(self, path, s, e, sub_mch_ids, self.event)) work_thread.start() def save_bill(self, text, bill_date, mch_id, sub_mch_id=None): bill_date = bill_date.strftime("%Y%m%d") if text.startswith('<xml>'): f = '%s_%s_%s.xml' % (bill_date, mch_id, sub_mch_id) if sub_mch_id else '%s_%s_.xml' % (bill_date, mch_id) else: f = '%s_%s_%s.csv' % (bill_date, mch_id, sub_mch_id) if sub_mch_id else '%s_%s_.csv' % (bill_date, mch_id) fullname = os.path.join(self.var_path.get().strip(), f) with open(fullname, 'wb') as csv: csv.write(text) def select_path(self): self.var_path.set(tkFileDialog.askdirectory()) def createWidgets(self, settings): row = 0 # 公众号ID self.lbl_appid = Label(self, text=u"公众帐号ID", fg='red') self.lbl_appid.grid(column=0, row=row, sticky=(E, N)) self.var_appid = StringVar(self, value=settings.get('appid')) self.txt_appid = Entry(self, textvariable=self.var_appid, width=60, font=self.font) self.txt_appid.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 商户号 self.lbl_mch_id = Label(self, text=u"商户号", fg='red') self.lbl_mch_id.grid(column=0, row=row, sticky=(E, N)) self.var_mch_id = StringVar(self, value=settings.get('mch_id')) self.txt_mch_id = Entry(self, textvariable=self.var_mch_id, width=60, font=self.font) self.txt_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 商户密钥 self.lbl_mch_key = Label(self, text=u"商户密钥", fg='red') self.lbl_mch_key.grid(column=0, row=row, sticky=(E, N)) self.var_mch_key = StringVar(self, value=settings.get('mch_key')) self.txt_mch_key = Entry(self, textvariable=self.var_mch_key, width=60, font=self.font) self.txt_mch_key.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 子商户号 self.lbl_sub_mch_id = Label(self, text=u"子商户号") self.lbl_sub_mch_id.grid(column=0, row=row, sticky=(E, N)) self.txt_sub_mch_id = Text(self, height=5, width=60, font=self.font) if settings.get('sub_mch_id'): self.txt_sub_mch_id.insert(END, settings.get('sub_mch_id')) self.txt_sub_mch_id.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 开始日期 self.lbl_bill_date_from = Label(self, text=u"开始日期", fg='red') self.lbl_bill_date_from.grid(column=0, row=row, sticky=(E, N)) self.var_bill_date_from = StringVar() self.var_bill_date_from.set((datetime.now() - timedelta(days=1)).strftime("%Y%m%d")) self.txt_bill_date_from = Entry(self, width=8, textvariable=self.var_bill_date_from, font=self.font) self.txt_bill_date_from.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 结束日期 self.lbl_bill_date_to = Label(self, text=u"结束日期") self.lbl_bill_date_to.grid(column=0, row=row, sticky=(E, N)) self.var_bill_date_to = StringVar() self.txt_bill_date_to = Entry(self, width=8, textvariable=self.var_bill_date_to, font=self.font) self.txt_bill_date_to.grid(column=1, row=row, columnspan=2, sticky=(W, N)) row += 1 # 输出目录 self.lbl_path = Label(self, text=u"输出目录", fg='red') self.lbl_path.grid(column=0, row=row, sticky=(E, N)) path = settings.get('path') self.var_path = StringVar(self, value=path if path else os.path.dirname(os.path.abspath(cur_path))) self.txt_path = Entry(self, textvariable=self.var_path, width=55, font=self.font) self.txt_path.grid(column=1, row=row, sticky=(W, N, E)) self.btn_select_path = Button(self, text=u"...", command=self.select_path) self.btn_select_path.grid(column=2, row=row, sticky=(E)) row += 1 # 进度条 self.prg_bar = Progressbar(self) self.prg_bar.grid(column=0, row=row, columnspan=3, sticky=(W, E), pady=(10, 0)) row += 1 # 执行按钮 buttonFrame = Frame(self) buttonFrame.grid(column=0, row=row, columnspan=3, pady=(15, 0), sticky=(W, E)) self.btn_run = Button(buttonFrame, width=20, text=u"下载", fg='blue', command=self.run) self.btn_run.pack() def loop(self): if self.running and self.event.is_set(): self.running = False self.event.clear() tkMessageBox.showinfo(title=u"成功", message="账单下载结束") subprocess.call('explorer "%s"' % self.var_path.get().strip().replace('/', '\\'), shell=True) self.master.after(100, self.loop) def __init__(self, master=None): Frame.__init__(self, master) self.font = tkFont.nametofont("TkDefaultFont") self.font.configure(family='MS Gothic', size=9) self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=10) self.rowconfigure(0, weight=1) self.columnconfigure (0, weight=1) settings = config.load() self.createWidgets(settings) self.event = threading.Event() self.running = False self.loop()
class QuoraAnalyticsUI(Notebook): def __init__(self): self.parent = Tkinter.Tk() Notebook.__init__(self, self.parent) #self.parent.title('Quora Analytics') self.parent.title('Quora Backup and Analytics') self.parent.wm_title('Quora Backup and Analytics') self.parent.grid_rowconfigure(0, weight=1) self.parent.grid_columnconfigure(0, weight=1) self.parent.resizable(True, True) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.crawler = QuoraCrawler(driver=QuoraCrawler.CHROME_DRIVER) self._add_frames() self.pack(fill='both', expand=True) def _add_frames(self): # Adding Answer Backup Frame f1 = Frame(self) f1.grid(column=0, row=0, sticky="NWES") for i in range(4): f1.grid_rowconfigure(i, weight=0, pad=5) f1.grid_rowconfigure(4, weight=1, pad=5) for i in range(4): f1.grid_columnconfigure(i, weight=1, pad=5) Label(f1, anchor='e', text='Answers Count : ').grid(column=0, row=0, sticky='EWNS') self.answer_count = StringVar(value=len(self.crawler.answer_list)) Label(f1, anchor='w', textvariable=self.answer_count).grid(column=1, row=0, sticky='EWNS') Label(f1, anchor='e', text='User Name : ').grid(column=2, row=0, sticky='EWNS') self.user = StringVar(value='Unknown') Label(f1, anchor='w', textvariable=self.user).grid(column=3, row=0, sticky='EWNS') tf_col = '#e6e6e6' tf = Tkinter.Frame(f1, relief=GROOVE, borderwidth='2p') tf.grid(row=1, columnspan=2, column=0, sticky='EWNS') Label(tf, text='Quora User Options', bg=tf_col, anchor='c').grid(column=0, row=0, columnspan=2, sticky='EWNS') Button(tf, text='Login', command=lambda : self.thread('login'), highlightbackground=tf_col).grid(column=0, row=1, sticky='EWNS') Button(tf, text='Logout', command=lambda : self.thread('logout'), highlightbackground=tf_col).grid(column=1, row=1, sticky='EWNS') tf.grid_rowconfigure(0, weight=1, pad=5) tf.grid_rowconfigure(1, weight=1, pad=5) tf.grid_columnconfigure(0, weight=1, pad=5) tf.grid_columnconfigure(1, weight=1, pad=5) tf = Frame(f1, relief=GROOVE, borderwidth='2p') tf.grid(row=1, columnspan=2, column=2, sticky='EWNS') Label(tf, text='Answer List Option', bg=tf_col, anchor='c').grid(column=0, columnspan=2, row=0, sticky='EWNS') Button(tf, text='Reset', command=lambda : self.thread('reset'), highlightbackground=tf_col).grid(column=0, row=1, sticky='EWNS') Button(tf, text='Update', command=lambda : self.thread('update'), highlightbackground=tf_col).grid(column=1, row=1, sticky='EWNS') tf.grid_rowconfigure(0, weight=1, pad=5) tf.grid_rowconfigure(1, weight=1, pad=5) tf.grid_columnconfigure(0, weight=1, pad=5) tf.grid_columnconfigure(1, weight=1, pad=5) # Add Progress Bar self.backup_progress = Progressbar(f1, orient="horizontal", length=100, mode="determinate") self.backup_progress.grid(row=2, columnspan=4, column=0, sticky='EWNS') # Adding Status Pane self.backup_status = StringVar(value='Ready') Label(f1, textvariable=self.backup_status, anchor='w').grid(row=3, column=0, columnspan=4, sticky='EWNS') # Adding The list of all answers tree = Treeview(f1, columns=('sno', 'date', 'question')) tree.heading('sno', text='S. No') tree.heading('date', text='Date') tree.heading('question', text='Question') tree.column("#0", width=0, stretch=False) tree.column('sno', width=40, stretch=False, anchor='center') tree.column('date', width=120, stretch=False, anchor='center') tree.column('question', stretch=True, anchor='w') tree.grid(column=0, columnspan=4, row=4, sticky='EWNS') tree.bind("<Double-1>", self.tree_item_click) self.answer_tree = tree self.populate_tree() f2 = Frame(self) self.add(f1, text='Answer Backup', underline=7) self.add(f2, text='Analytics') def tree_item_click(self, event): idx_clicked = self.answer_tree.identify_row(event.y) if idx_clicked: print "Tree Item Clicked - ", idx_clicked def show_busy_dialog(self): tkMessageBox.showerror( title='Task in Progress', message=BUSY_MSG, icon=tkMessageBox.INFO ) def thread(self, task): print "Starting a new Thread for " + task if self.backup_status.get() != 'Ready': self.show_busy_dialog() else: self.backup_status.set('Starting a new Task...') task_ids = ( ('login', self.login_crawler), ('logout', self.logout_crawler), ('update', self.update_answer_list), ('reset', self.reset_answer_list) ) for task_relation in task_ids: if task == task_relation[0]: Thread(target=task_relation[1]).start() def reset_answer_list(self): confirm = tkMessageBox.askquestion( title='Confirm Reset', message=RESET_MSG, icon='warning' ) if confirm == 'yes': self.backup_status.set('Reseting Answer List...') self.backup_progress.start(interval=500) self.crawler.reset_answer_list() self.answer_count.set(len(self.crawler.answer_list)) self.populate_tree() self.backup_status.set('Ready') self.backup_progress.stop() self.backup_progress['value'] = 0 def update_answer_list(self): try: self.backup_status.set('Checking Login Status...') self.backup_progress.start(interval=500) if not self.crawler.check_login(self.backup_progress, self.backup_status): self.backup_status.set('Logged Out !! Cannot continue') tkMessageBox.showerror( title='Login Required', message=LOGIN_REQ_MSG, icon=tkMessageBox.INFO ) else: self.backup_progress['value'] = 10 self.backup_status.set('Updating Answer List...It may take few minutes') self.crawler.update_answer_list(self.backup_progress, self.backup_status) self.answer_count.set(len(self.crawler.answer_list)) self.populate_tree() except STException: tkMessageBox.showerror( title='Operation Aborted', message=TIMEOUT_MSG, icon=tkMessageBox.ERROR ) self.backup_status.set('Ready') self.backup_progress.stop() self.backup_progress['value'] = 0 def login_crawler(self): try: self.backup_status.set('Checking Login Status...') self.backup_progress.start(interval=500) self.backup_progress['value'] = 10 if self.crawler.check_login(self.backup_progress, self.backup_status): self.backup_progress['value'] = 100 self.backup_progress.stop() tkMessageBox.showinfo( title='Login Successful', message=ALREADY_LOGIN_MSG, icon=tkMessageBox.INFO ) self.user.set(self.crawler.get_user_name()) else: # Opening Pop Up self.backup_status.set('Waiting For Credentials...') self.backup_progress['value'] = 40 self.loginpop = PasswordPopUp(self) self.loginpop.grab_set() # To lock parent window when child is shown self.parent.wait_window(self.loginpop) self.loginpop.grab_release() # Reactivate parent window email = self.loginpop.uname.strip() passw = self.loginpop.passw.strip() if len(email) > 0 and len(passw) > 0: try: self.backup_status.set('Trying to log in with ' + email + ' ...') self.backup_progress['value'] = 60 self.crawler.login(email, passw, self.backup_progress, self.backup_status) self.user.set(self.crawler.get_user_name()) except QuoraCrawler.InvalidCredentialException, e: self.backup_status.set('Login Unsuccessful') self.backup_progress['value'] = 100 self.backup_progress.stop() tkMessageBox.showerror( title='Invalid Credentials', message=e.message, icon=tkMessageBox.ERROR ) except STException: tkMessageBox.showerror( title='Operation Aborted', message=TIMEOUT_MSG, icon=tkMessageBox.ERROR ) self.backup_status.set('Ready') self.backup_progress.stop() self.backup_progress['value'] = 0 def logout_crawler(self): try: self.backup_progress.start(interval=500) self.backup_status.set('Trying to Logging Out') self.crawler.logout(self.backup_progress, self.backup_status) self.user.set('Logged Out') except STException: tkMessageBox.showerror( title='Operation Aborted', message=TIMEOUT_MSG, icon=tkMessageBox.ERROR ) self.backup_status.set('Ready') self.backup_progress.stop() self.backup_progress['value'] = 0 def populate_tree(self): for i in self.answer_tree.get_children(): self.answer_tree.delete(i) for idx, answer in enumerate(self.crawler.answer_list): self.answer_tree.insert('', 'end', idx + 1, value=((idx + 1, answer[1], answer[2]))) def destroy(self): self.crawler.quit() Notebook.destroy(self)
self.running = False def hello(): tkMessageBox.showinfo("Say Hello", "Hello World") top = Tk() top.title("Converter") L1 = Label(top, text = "Hexadecimal", width=20) L1.grid(row=0, column=0) L2 = Label(top, text = "Binary", width=20) L2.grid(row=0, column=1) L3 = Label(top, text = "Decimal", width=20) L3.grid(row=0, column=2) progressBar = Progressbar(top, orient='horizontal', mode='determinate', length=240) progressBar.grid(row=3, column = 1, columnspan = 2) B1 = Button(top, text = "Say Hello", command = hello) B1.grid(row=31, column=3) E1 = Entry(top, bd = 3) E1.grid(row=1, column=0) E2 = Entry(top, bd = 3) E2.grid(row=1, column=1) E3 = Entry(top, bd = 3) E3.grid(row=1, column=2) top.mainloop()
class Window(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Network/Port Scan") self.style = Style() self.style.configure("TFrame", background = "#000000") self.style.configure("TCheckbutton", background = "#000000") self.style.configure("TButton", background = "#000000") self.pack(fill=BOTH, expand=1) # Configure layout self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=1) self.rowconfigure(5, weight = 1) self.rowconfigure(6, weight = 1) # Title of program lbl = Label(self, text="Network/Port Scan") lbl.grid(sticky = W, pady=5, padx=5) # Text Box area = ScrolledText(self, height = 20) area.grid(row=1, column=0, columnspan=3, rowspan=4, padx=3, sticky = N+S+E+W) self.area = area # IP Address Button self.ip = BooleanVar() ip_add_button = Checkbutton(self, text="IP Address",variable=self.ip, width=10) ip_add_button.grid(row = 1, column = 3, sticky = N) ip_add_button.config(anchor = W, activebackground = "red") # Port Button self.port = BooleanVar() port_button = Checkbutton(self, text="Ports", variable=self.port, width=10) port_button.grid(row = 1, column = 3) port_button.config(anchor = W, activebackground = "orange") # Host Name Button self.host = BooleanVar() host_name_button = Checkbutton(self, text="Host Name",variable=self.host, width=10) host_name_button.grid(row = 1, column = 3, sticky = S) host_name_button.config(anchor = W, activebackground = "yellow") # Gateway Button self.gateway = BooleanVar() gateway_btn = Checkbutton(self, text="Gateway", variable=self.gateway, width=10) gateway_btn.grid(row = 2, column = 3, sticky = N) gateway_btn.config(anchor = W, activebackground = "green") # Services Button self.service = BooleanVar() service_btn = Checkbutton(self, text="Services", variable = self.service, width=10) service_btn.grid(row = 2, column = 3) service_btn.config(anchor = W, activebackground = "blue") # Starting IP label ip_label = Label(self, text = "Starting IP: ") ip_label.grid(row = 5, column = 0, pady = 1, padx = 3, sticky = W) self.ip_from = Entry(self, width = 15) self.ip_from.insert(0, start_ip) self.ip_from.grid(row = 5 , column = 0, pady = 1, padx = 3, sticky = E) # Ending IP label ip_label_two = Label(self, text = "Ending IP: ") ip_label_two.grid(row = 5, column = 1, pady = 1, padx = 5, sticky = W) self.ip_to = Entry(self, width = 15) self.ip_to.insert(0, end_ip) self.ip_to.grid(row = 5 , column = 1, pady = 1, padx = 5, sticky = E) # Starting Port Label port_label = Label(self, text = "Starting Port: ") port_label.grid(row = 5, column = 0, pady = 3, padx = 5, sticky = S+W) self.port_from = Entry(self, width = 15) self.port_from.insert(0, 0) self.port_from.grid(row = 5 , column = 0, pady = 1, padx = 5, sticky = S+E) # Ending Port Label port_label_two = Label(self, text = "Ending Port: ") port_label_two.grid(row = 5, column = 1, pady = 3, padx = 5, sticky = S+W) self.port_to = Entry(self, width = 15) self.port_to.insert(0, 1025) self.port_to.grid(row = 5 , column = 1, pady = 1, padx = 5, sticky = S+E) # Scan Me self_scan_button = Button(self, text="Scan Me", command = lambda : self.onClick(1), width = 33) self_scan_button.grid(row = 6, column = 1, sticky = N) # Scan near me Button scan_other_button = Button(self, text="Scan Near Me", width = 33, command = lambda : self.onClick(2)) scan_other_button.grid(row = 6, column = 0, pady=1, sticky = N) # Clear button clear_button = Button(self, text="Clear text", command = self.clear_text, width = 12) clear_button.grid(row = 6, column = 3, pady=1, sticky = N) # Progress Bar self.label_scanning = Progressbar(self, orient = HORIZONTAL, length = 175) self.label_scanning.grid(row = 6, column = 0, columnspan = 4, padx = 7, pady = 7, sticky = E+S+W) self.label_scanning.config(mode = "determinate") # Clear what is in the text box. def clear_text(self): self.area.delete(0.0, 'end') # empty my lists. my_ports[:] = [] ip_address_up[:] = [] target_host_name[:] = [] target_port_up[:] = [] # On click methods for scan me and scan others. def onClick(self, button_id): if button_id == 1: # Check to see if host button is marked if self.host.get() == 1: message = my_host_name() self.area.insert(0.0, message, ("warning")) self.area.tag_configure("warning", foreground = "blue") # Check to see if ports button is marked if self.port.get() == 1: # Check port entry widgets. if self.port_from: if self.port_to: # Get the user input starting_port = self.port_from.get() ending_port = self.port_to.get() message, total = scan_my_ports(int(starting_port), int(ending_port)) for i in message: new_message = "My TCP " + i + "\n" self.area.insert(0.0, new_message, ("ports")) #self.area.tag_configure("ports", foreground = "green") time = "The TCP port scan completed in: " + str(total) + "\n" self.area.insert(0.0, time, ("timing")) self.area.tag_configure("timing", foreground = "red") else: self.area.insert(0.0, "No valid ports specified.") # Check to see if IP button is marked if self.ip.get() == 1: message = my_ip() self.area.insert(0.0, message) # Check if gateway button is marked. if self.gateway.get() == 1: message = my_gateway() self.area.insert(0.0, message) # Check if service button is marked. if self.service.get() == 1: message, time = scan_my_services() for i in message: new_message = i + "\n" self.area.insert(0.0, new_message) new_time = "The local scan completed in: " + str(time) + "\n" self.area.insert(0.0. new_time, ("timing")) self.area.tag_configure("timing", foreground = "red") # If Scan other button is clicked. elif button_id == 2: # Check other IP's if self.ip.get() == 1: # Check the entry widgets. if self.ip_from: if self.ip_to: # Get the ranges from the entry widgets starting_ipv4_address = self.ip_from.get() ending_ipv4_address = self.ip_to.get() # Pass the values from the entry widgets into the function to scan nearby IP addresses. message, time = ping_ip_other(starting_ipv4_address, ending_ipv4_address) if message: for i in message: new_message = "The address: {:>15} {:>15}".format(i,"is UP\n") self.area.insert(0.0, new_message) total_time = "Range scanned: " + str(starting_ipv4_address) +" to " + str(ending_ipv4_address) + "\n" + "The IP scan completed in: " + str(time) + "\n" self.area.insert(0.0, total_time, ("timing")) self.area.tag_configure("timing", foreground = "red") else: self.area.insert(0.0, "No Ip range is specified.") # Check others Ports if self.port.get() == 1: # Check port entry widgets. if self.port_from: if self.port_to: # Get the user input starting_port = self.port_from.get() ending_port = self.port_to.get() message, time = scan_ports_other(int(starting_port), int(ending_port)) if message: for i in message: new_msg = "The " + i +"\n" self.area.insert(0.0, new_msg) else: new_msg = "Must scan nearby IP addresses first.\n" total_time = "TCP Port scan completed in: " + str(time) + "\n" self.area.insert(0.0, total_time, ("timing")) self.area.tag_configure("timing", foreground = "red") else: self.area.insert(0.0, "No Port range specified.") # Check other host names. Based on IP's scanned. if self.host.get() == 1: message, time = scan_host_other(ip_address_up) # Check that IP's of other computers were collected if message: for i in message: new_message = "Host name: "+ str(i) + "\n" self.area.insert(0.0, new_message) else: new_msg = "Must scan nearby IP addresses first. \n" self.area.insert(0.0, new_msg) total = "The host scan completed in: " + str(time) + "\n" self.area.insert(0.0, total, ("timing")) self.area.tag_configure("timing", foreground = "red") # Check gateway return the gateway of the host machine again. if self.gateway.get() == 1: message = "\n" + str(my_gateway()) self.area.insert(0.0, message) # Check what services are running on which IP and port. if self.service.get() == 1: message, time = services_other() if message: for i in message: new_message = i + "\n" self.area.insert(0.0, new_message) else: new_msg = "The IP addresses and ports must be scanned first." self.area.insert(0.0, new_msg) new_time = "The service scan completed in: " + str(time) + "\n" self.area.insert(0.0, new_time, ("timing")) self.area.tag_configure("timing", foreground = "red") else: pass
class QuoraAnalyticsUI(Notebook): def __init__(self): self.parent = Tkinter.Tk() Notebook.__init__(self, self.parent) # self.parent.title('Quora Analytics') self.parent.title("Quora Backup and Analytics") self.parent.wm_title("Quora Backup and Analytics") self.parent.grid_rowconfigure(0, weight=1) self.parent.grid_columnconfigure(0, weight=1) self.parent.resizable(True, True) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.crawler = QuoraCrawler(driver=QuoraCrawler.CHROME_DRIVER) self._add_frames() self.pack(fill="both", expand=True) def _add_frames(self): # Adding Answer Backup Frame f1 = Frame(self) f1.grid(column=0, row=0, sticky="NWES") for i in range(4): f1.grid_rowconfigure(i, weight=0, pad=5) f1.grid_rowconfigure(4, weight=1, pad=5) for i in range(4): f1.grid_columnconfigure(i, weight=1, pad=5) Label(f1, anchor="e", text="Answers Count : ").grid(column=0, row=0, sticky="EWNS") self.answer_count = StringVar(value=len(self.crawler.answer_list)) Label(f1, anchor="w", textvariable=self.answer_count).grid(column=1, row=0, sticky="EWNS") Label(f1, anchor="e", text="User Name : ").grid(column=2, row=0, sticky="EWNS") self.user = StringVar(value="Unknown") Label(f1, anchor="w", textvariable=self.user).grid(column=3, row=0, sticky="EWNS") tf_col = "#e6e6e6" tf = Tkinter.Frame(f1, relief=GROOVE, borderwidth="2p") tf.grid(row=1, columnspan=2, column=0, sticky="EWNS") Label(tf, text="Quora User Options", bg=tf_col, anchor="c").grid(column=0, row=0, columnspan=2, sticky="EWNS") Button(tf, text="Login", command=lambda: self.thread("login"), highlightbackground=tf_col).grid( column=0, row=1, sticky="EWNS" ) Button(tf, text="Logout", command=lambda: self.thread("logout"), highlightbackground=tf_col).grid( column=1, row=1, sticky="EWNS" ) tf.grid_rowconfigure(0, weight=1, pad=5) tf.grid_rowconfigure(1, weight=1, pad=5) tf.grid_columnconfigure(0, weight=1, pad=5) tf.grid_columnconfigure(1, weight=1, pad=5) tf = Frame(f1, relief=GROOVE, borderwidth="2p") tf.grid(row=1, columnspan=2, column=2, sticky="EWNS") Label(tf, text="Answer List Option", bg=tf_col, anchor="c").grid(column=0, columnspan=2, row=0, sticky="EWNS") Button(tf, text="Reset", command=lambda: self.thread("reset"), highlightbackground=tf_col).grid( column=0, row=1, sticky="EWNS" ) Button(tf, text="Update", command=lambda: self.thread("update"), highlightbackground=tf_col).grid( column=1, row=1, sticky="EWNS" ) tf.grid_rowconfigure(0, weight=1, pad=5) tf.grid_rowconfigure(1, weight=1, pad=5) tf.grid_columnconfigure(0, weight=1, pad=5) tf.grid_columnconfigure(1, weight=1, pad=5) # Add Progress Bar self.backup_progress = Progressbar(f1, orient="horizontal", length=100, mode="determinate") self.backup_progress.grid(row=2, columnspan=4, column=0, sticky="EWNS") # Adding Status Pane self.backup_status = StringVar(value="Ready") Label(f1, textvariable=self.backup_status, anchor="w").grid(row=3, column=0, columnspan=4, sticky="EWNS") # Adding The list of all answers tree = Treeview(f1, columns=("sno", "date", "question")) tree.heading("sno", text="S. No") tree.heading("date", text="Date") tree.heading("question", text="Question") tree.column("#0", width=0, stretch=False) tree.column("sno", width=40, stretch=False, anchor="center") tree.column("date", width=120, stretch=False, anchor="center") tree.column("question", stretch=True, anchor="w") tree.grid(column=0, columnspan=4, row=4, sticky="EWNS") tree.bind("<Double-1>", self.tree_item_click) self.answer_tree = tree self.populate_tree() f2 = Frame(self) self.add(f1, text="Answer Backup", underline=7) self.add(f2, text="Analytics") def tree_item_click(self, event): idx_clicked = self.answer_tree.identify_row(event.y) if idx_clicked: print "Tree Item Clicked - ", idx_clicked def show_busy_dialog(self): tkMessageBox.showerror(title="Task in Progress", message=BUSY_MSG, icon=tkMessageBox.INFO) def thread(self, task): print "Starting a new Thread for " + task if self.backup_status.get() != "Ready": self.show_busy_dialog() else: self.backup_status.set("Starting a new Task...") task_ids = ( ("login", self.login_crawler), ("logout", self.logout_crawler), ("update", self.update_answer_list), ("reset", self.reset_answer_list), ) for task_relation in task_ids: if task == task_relation[0]: Thread(target=task_relation[1]).start() def reset_answer_list(self): confirm = tkMessageBox.askquestion(title="Confirm Reset", message=RESET_MSG, icon="warning") if confirm == "yes": self.backup_status.set("Reseting Answer List...") self.backup_progress.start(interval=500) self.crawler.reset_answer_list() self.answer_count.set(len(self.crawler.answer_list)) self.populate_tree() self.backup_status.set("Ready") self.backup_progress.stop() self.backup_progress["value"] = 0 def update_answer_list(self): try: self.backup_status.set("Checking Login Status...") self.backup_progress.start(interval=500) if not self.crawler.check_login(self.backup_progress, self.backup_status): self.backup_status.set("Logged Out !! Cannot continue") tkMessageBox.showerror(title="Login Required", message=LOGIN_REQ_MSG, icon=tkMessageBox.INFO) else: self.backup_progress["value"] = 10 self.backup_status.set("Updating Answer List...It may take few minutes") self.crawler.update_answer_list(self.backup_progress, self.backup_status) self.answer_count.set(len(self.crawler.answer_list)) self.populate_tree() except STException: tkMessageBox.showerror(title="Operation Aborted", message=TIMEOUT_MSG, icon=tkMessageBox.ERROR) self.backup_status.set("Ready") self.backup_progress.stop() self.backup_progress["value"] = 0 def login_crawler(self): try: self.backup_status.set("Checking Login Status...") self.backup_progress.start(interval=500) self.backup_progress["value"] = 10 if self.crawler.check_login(self.backup_progress, self.backup_status): self.backup_progress["value"] = 100 self.backup_progress.stop() tkMessageBox.showinfo(title="Login Successful", message=ALREADY_LOGIN_MSG, icon=tkMessageBox.INFO) self.user.set(self.crawler.get_user_name()) else: # Opening Pop Up self.backup_status.set("Waiting For Credentials...") self.backup_progress["value"] = 40 self.loginpop = PasswordPopUp(self) self.loginpop.grab_set() # To lock parent window when child is shown self.parent.wait_window(self.loginpop) self.loginpop.grab_release() # Reactivate parent window email = self.loginpop.uname.strip() passw = self.loginpop.passw.strip() if len(email) > 0 and len(passw) > 0: try: self.backup_status.set("Trying to log in with " + email + " ...") self.backup_progress["value"] = 60 self.crawler.login(email, passw, self.backup_progress, self.backup_status) self.user.set(self.crawler.get_user_name()) except QuoraCrawler.InvalidCredentialException, e: self.backup_status.set("Login Unsuccessful") self.backup_progress["value"] = 100 self.backup_progress.stop() tkMessageBox.showerror(title="Invalid Credentials", message=e.message, icon=tkMessageBox.ERROR) except STException: tkMessageBox.showerror(title="Operation Aborted", message=TIMEOUT_MSG, icon=tkMessageBox.ERROR) self.backup_status.set("Ready") self.backup_progress.stop() self.backup_progress["value"] = 0 def logout_crawler(self): try: self.backup_progress.start(interval=500) self.backup_status.set("Trying to Logging Out") self.crawler.logout(self.backup_progress, self.backup_status) self.user.set("Logged Out") except STException: tkMessageBox.showerror(title="Operation Aborted", message=TIMEOUT_MSG, icon=tkMessageBox.ERROR) self.backup_status.set("Ready") self.backup_progress.stop() self.backup_progress["value"] = 0 def populate_tree(self): for i in self.answer_tree.get_children(): self.answer_tree.delete(i) for idx, answer in enumerate(self.crawler.answer_list): self.answer_tree.insert("", "end", idx + 1, value=((idx + 1, answer[1], answer[2]))) def destroy(self): self.crawler.quit() Notebook.destroy(self)
class Window(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("Network/Port Scan") self.style = Style() self.style.configure("TFrame", background="#000000") self.style.configure("TCheckbutton", background="#000000") self.style.configure("TButton", background="#000000") self.pack(fill=BOTH, expand=1) # Configure layout self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=1) self.rowconfigure(5, weight=1) self.rowconfigure(6, weight=1) # Title of program lbl = Label(self, text="Network/Port Scan") lbl.grid(sticky=W, pady=5, padx=5) # Text Box area = ScrolledText(self, height=20) area.grid(row=1, column=0, columnspan=3, rowspan=4, padx=3, sticky=N + S + E + W) self.area = area # IP Address Button self.ip = BooleanVar() ip_add_button = Checkbutton(self, text="IP Address", variable=self.ip, width=10) ip_add_button.grid(row=1, column=3, sticky=N) ip_add_button.config(anchor=W, activebackground="red") # Port Button self.port = BooleanVar() port_button = Checkbutton(self, text="Ports", variable=self.port, width=10) port_button.grid(row=1, column=3) port_button.config(anchor=W, activebackground="orange") # Host Name Button self.host = BooleanVar() host_name_button = Checkbutton(self, text="Host Name", variable=self.host, width=10) host_name_button.grid(row=1, column=3, sticky=S) host_name_button.config(anchor=W, activebackground="yellow") # Gateway Button self.gateway = BooleanVar() gateway_btn = Checkbutton(self, text="Gateway", variable=self.gateway, width=10) gateway_btn.grid(row=2, column=3, sticky=N) gateway_btn.config(anchor=W, activebackground="green") # Services Button self.service = BooleanVar() service_btn = Checkbutton(self, text="Services", variable=self.service, width=10) service_btn.grid(row=2, column=3) service_btn.config(anchor=W, activebackground="blue") # Starting IP label ip_label = Label(self, text="Starting IP: ") ip_label.grid(row=5, column=0, pady=1, padx=3, sticky=W) self.ip_from = Entry(self, width=15) self.ip_from.insert(0, start_ip) self.ip_from.grid(row=5, column=0, pady=1, padx=3, sticky=E) # Ending IP label ip_label_two = Label(self, text="Ending IP: ") ip_label_two.grid(row=5, column=1, pady=1, padx=5, sticky=W) self.ip_to = Entry(self, width=15) self.ip_to.insert(0, end_ip) self.ip_to.grid(row=5, column=1, pady=1, padx=5, sticky=E) # Starting Port Label port_label = Label(self, text="Starting Port: ") port_label.grid(row=5, column=0, pady=3, padx=5, sticky=S + W) self.port_from = Entry(self, width=15) self.port_from.insert(0, 0) self.port_from.grid(row=5, column=0, pady=1, padx=5, sticky=S + E) # Ending Port Label port_label_two = Label(self, text="Ending Port: ") port_label_two.grid(row=5, column=1, pady=3, padx=5, sticky=S + W) self.port_to = Entry(self, width=15) self.port_to.insert(0, 1025) self.port_to.grid(row=5, column=1, pady=1, padx=5, sticky=S + E) # Scan Me self_scan_button = Button(self, text="Scan Me", command=lambda: self.onClick(1), width=33) self_scan_button.grid(row=6, column=1, sticky=N) # Scan near me Button scan_other_button = Button(self, text="Scan Near Me", width=33, command=lambda: self.onClick(2)) scan_other_button.grid(row=6, column=0, pady=1, sticky=N) # Clear button clear_button = Button(self, text="Clear text", command=self.clear_text, width=12) clear_button.grid(row=6, column=3, pady=1, sticky=N) # Progress Bar self.label_scanning = Progressbar(self, orient=HORIZONTAL, length=175) self.label_scanning.grid(row=6, column=0, columnspan=4, padx=7, pady=7, sticky=E + S + W) self.label_scanning.config(mode="determinate") # Clear what is in the text box. def clear_text(self): self.area.delete(0.0, 'end') # empty my lists. my_ports[:] = [] ip_address_up[:] = [] target_host_name[:] = [] target_port_up[:] = [] # On click methods for scan me and scan others. def onClick(self, button_id): if button_id == 1: # Check to see if host button is marked if self.host.get() == 1: message = my_host_name() self.area.insert(0.0, message, ("warning")) self.area.tag_configure("warning", foreground="blue") # Check to see if ports button is marked if self.port.get() == 1: # Check port entry widgets. if self.port_from: if self.port_to: # Get the user input starting_port = self.port_from.get() ending_port = self.port_to.get() message, total = scan_my_ports(int(starting_port), int(ending_port)) for i in message: new_message = "My TCP " + i + "\n" self.area.insert(0.0, new_message, ("ports")) #self.area.tag_configure("ports", foreground = "green") time = "The TCP port scan completed in: " + str( total) + "\n" self.area.insert(0.0, time, ("timing")) self.area.tag_configure("timing", foreground="red") else: self.area.insert(0.0, "No valid ports specified.") # Check to see if IP button is marked if self.ip.get() == 1: message = my_ip() self.area.insert(0.0, message) # Check if gateway button is marked. if self.gateway.get() == 1: message = my_gateway() self.area.insert(0.0, message) # Check if service button is marked. if self.service.get() == 1: message, time = scan_my_services() for i in message: new_message = i + "\n" self.area.insert(0.0, new_message) new_time = "The local scan completed in: " + str(time) + "\n" self.area.insert(0.0.new_time, ("timing")) self.area.tag_configure("timing", foreground="red") # If Scan other button is clicked. elif button_id == 2: # Check other IP's if self.ip.get() == 1: # Check the entry widgets. if self.ip_from: if self.ip_to: # Get the ranges from the entry widgets starting_ipv4_address = self.ip_from.get() ending_ipv4_address = self.ip_to.get() # Pass the values from the entry widgets into the function to scan nearby IP addresses. message, time = ping_ip_other(starting_ipv4_address, ending_ipv4_address) if message: for i in message: new_message = "The address: {:>15} {:>15}".format( i, "is UP\n") self.area.insert(0.0, new_message) total_time = "Range scanned: " + str( starting_ipv4_address) + " to " + str( ending_ipv4_address ) + "\n" + "The IP scan completed in: " + str( time) + "\n" self.area.insert(0.0, total_time, ("timing")) self.area.tag_configure("timing", foreground="red") else: self.area.insert(0.0, "No Ip range is specified.") # Check others Ports if self.port.get() == 1: # Check port entry widgets. if self.port_from: if self.port_to: # Get the user input starting_port = self.port_from.get() ending_port = self.port_to.get() message, time = scan_ports_other( int(starting_port), int(ending_port)) if message: for i in message: new_msg = "The " + i + "\n" self.area.insert(0.0, new_msg) else: new_msg = "Must scan nearby IP addresses first.\n" total_time = "TCP Port scan completed in: " + str( time) + "\n" self.area.insert(0.0, total_time, ("timing")) self.area.tag_configure("timing", foreground="red") else: self.area.insert(0.0, "No Port range specified.") # Check other host names. Based on IP's scanned. if self.host.get() == 1: message, time = scan_host_other(ip_address_up) # Check that IP's of other computers were collected if message: for i in message: new_message = "Host name: " + str(i) + "\n" self.area.insert(0.0, new_message) else: new_msg = "Must scan nearby IP addresses first. \n" self.area.insert(0.0, new_msg) total = "The host scan completed in: " + str(time) + "\n" self.area.insert(0.0, total, ("timing")) self.area.tag_configure("timing", foreground="red") # Check gateway return the gateway of the host machine again. if self.gateway.get() == 1: message = "\n" + str(my_gateway()) self.area.insert(0.0, message) # Check what services are running on which IP and port. if self.service.get() == 1: message, time = services_other() if message: for i in message: new_message = i + "\n" self.area.insert(0.0, new_message) else: new_msg = "The IP addresses and ports must be scanned first." self.area.insert(0.0, new_msg) new_time = "The service scan completed in: " + str(time) + "\n" self.area.insert(0.0, new_time, ("timing")) self.area.tag_configure("timing", foreground="red") else: pass
class RecordFrame(MyFrame): def __init__(self, parent): MyFrame.__init__(self, parent, 'Parametrize', (100,0)) self.record_options = DataDumper.load_json_data(Constants.CONFIG_PATH)['record_options'] self.record_time.set_value(self.record_options['duration']) self.thread = None def init_ui(self): MyFrame.init_ui(self) self.columnconfigure(0, weight=2, minsize=150) self.columnconfigure(1, weight=3, minsize=100) self.file_name = TextEntry(self, 'Recorded file name') self.record_time = TextEntry(self, 'Record time') self.progress_bar = Progressbar(self, orient='horizontal', mode='determinate') self.progress_bar.grid(columnspan=2, sticky='NESW') Button(self, text='Record', command=self.threaded_record).grid(columnspan=2, sticky='NESW') def threaded_record(self): if self.thread == None or not self.thread.isAlive(): self.thread = threading.Thread(target=self.record) self.thread.start() def record(self): frequency = int(self.record_options['frequency']) record_time = int(self.record_time.get_value()) format = pyaudio.paInt16 n_channels = 2 chunk = 1024 output_filename = Constants.RAW_FILES_PATH + self.file_name.get_value() + '.wav' splitted = self.file_name.get_value().split('/') if len(splitted) > 1: splitted = splitted[:-1] acc = Constants.RAW_FILES_PATH for el in splitted: acc += el + '/' if not os.path.isdir(acc): os.mkdir(acc) audio = pyaudio.PyAudio() stream = audio.open(format=format, channels=n_channels, rate=frequency, input=True, frames_per_buffer=chunk) frames = [] progress_step = 100. / int(frequency / chunk * record_time) for i in range(0, int(frequency / chunk * record_time)): data = stream.read(chunk) frames.append(data) self.progress_bar.step(progress_step) stream.stop_stream() stream.close() audio.terminate() waveFile = wave.open(output_filename, 'wb') waveFile.setnchannels(n_channels) waveFile.setsampwidth(audio.get_sample_size(format)) waveFile.setframerate(frequency) waveFile.writeframes(b''.join(frames)) waveFile.close() tkMessageBox.showinfo('Info', 'Finished recording') self.progress_bar.step(-100)
class InterfaceGauche(LabelFrame): """Left frame of the GUI, giving the buttons and the current price and winner""" def __init__(self, tk_frame, police, **kwargs): LabelFrame.__init__(self, tk_frame, text="Tirage", font=police, **kwargs) self.waiting_time = 10 self.message = Label(self, text="Appuyez sur le bouton pour lancer le tirage", font=police) self.message.grid(column=0, row=0, columnspan=2) self.bouton_quitter = Button(self, text="Quitter", command=self.quit, font=police) self.bouton_quitter.grid(column=0, row=1, pady=10) self.bouton_cliquer = Button(self, text="Lancer!", fg="red", command=self.click, font=police) self.bouton_cliquer.grid(column=1, row=1) self.message_price = Label(self, text="Tirage pour:", font=police) self.price = Label(self, text='', bg="white", width=40, height=1, font=police) self.message_price.grid(column=0, row=3) self.price.grid(column=1, row=3, columnspan=1, padx=10, pady=10) self.message_name = Label(self, text="Le gagnant est:", font=police) self.name = Label(self, text="", bg="white", width=40, height=1, font=police) self.message_name.grid(column=0, row=4) self.name.grid(column=1, row=4, columnspan=1, pady=10) self.parent_name = self.winfo_parent() self.parent = self._nametowidget(self.parent_name) # Part waiting time self.interval = Label(self, text="Intervalle entre tirages (s)", font=police) self.interval.grid(column=0, row=6, columnspan=1, pady=10) self.v = StringVar() self.v.set(self.waiting_time) self.interval_length = Entry(self, textvariable=self.v, width=5, justify=CENTER, font=police) self.interval_length.grid(column=1, row=6, columnspan=1) self.progress_bar = Progressbar(self, length=300) self.progress_bar.grid(column=0, row=8, columnspan=2, pady=10) self.nb_players_text = Label(self, text="Nombre de joueurs", font=police) self.nb_players_text.grid(column=0, row=10, columnspan=1, pady=10) self.nb_players = Label(self, text="0", font=police) self.nb_players.grid(column=1, row=10, columnspan=1, pady=10) self.nb_prices_text = Label(self, text="Nombre de prix restants", font=police) self.nb_prices_text.grid(column=0, row=11, columnspan=1, pady=10) self.nb_prices = Label(self, text="0", font=police) self.nb_prices.grid(column=1, row=11, columnspan=1, pady=10) # police=tkFont.Font(self, size=12)#, family='Courier') # self.config(, font=police) # for i in range(5): # self.grid_rowconfigure(2, weight=1) # self.grid_rowconfigure(5, weight=1) # self.grid_rowconfigure(7, weight=1) # self.grid_rowconfigure(9, weight=1) for i in range(2): self.grid_columnconfigure(i, weight=1) def click(self): """When click is selected, the tombola starts""" try: self.waiting_time = int(self.v.get()) except ValueError: showerror("Error", "L'intervalle doit être un nombre") return self.progress_bar['maximum'] = self.waiting_time+0.01 self.interval_length.config(state=DISABLED) self.parent.draw_tombola(self.waiting_time) if not self.parent.list_prices: self.bouton_cliquer.config(state=DISABLED) self.price["text"] = "Tous les lots ont été tirés" self.name["text"] = "" self.update() def update_nb_players(self): self.nb_players["text"] = len(self.parent.list_names) self.nb_players.update() def update_nb_prices(self): self.nb_prices["text"] = len(self.parent.list_prices) self.nb_prices.update()
class TkSynthWindow(Frame): """ Provides common synth editor elements: bank editor MIDI tab Mapping tabs TkSynthWindow is customized by adding one or more TkSubEditor. """ def __init__(self, master, sproxy): """ Construct new TkSynthWindow master - The Tk container for self. In practice this is an instance of llia.gui.tk.GroupWindow sproxy - An instance of llia.Proxy. """ Frame.__init__(self, master) self.config(background=factory.bg()) self.synth = sproxy self.synth.synth_editor = self self.app = sproxy.app self.sid = sproxy.sid self.group_index = -1 factory.set_pallet(sproxy.specs["pallet"]) main = factory.paned_window(self) main.pack(expand=True, fill="both") self.bank_editor = TkBankEditor(main, self, sproxy) self.bus_and_buffer_editor = None east = factory.frame(main) self.notebook = factory.notebook(east) self.notebook.pack(anchor="nw", expand=True, fill="both") south = factory.frame(east) south.pack(after=self.notebook, anchor="w", expand=True, fill="x") self._lab_status = factory.label(south, "<status>") self._lab_extended = factory.label(south, "") b_panic = factory.panic_button(south, command=self.panic) b_lower = factory.button(south, "-", command=self.lower_window) b_lift = factory.button(south, "+", command=self.lift_window) b_panic.grid(row=0, column=0) self._lab_status.grid(row=0, column=4, sticky='ew') self._lab_extended.grid(row=0,column=5,sticky='e',padx=16) self._lab_extended.config(fg="#f1f1cd") self._progressbar = Progressbar(south,mode="indeterminate") self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8) south.config(background=factory.bg()) main.add(self.bank_editor) main.add(east) self.list_channel = None self.list_keytab = None self.var_transpose = StringVar() self.var_keyrange_low = StringVar() self.var_keyrange_high = StringVar() self.var_bendrange = StringVar() self._init_midi_tab(self.notebook) self._init_map1_tab(self.notebook) # MIDI controllers and pitchwheel self._init_map2_tab(self.notebook) # velocity, aftertouch, keynumber self._init_info_tab(self.notebook) self._child_editors = {} self.update_progressbar(100, 0) def enable(self, flag): for ed in self._child_editors.values(): ed.enable(flag) if flag: msg = "" else: msg = "Editor locked while in extended mode" self._lab_extended.config(text=msg) def panic(self): self.synth.osc_transmitter.x_all_notes_off() self.status("All notes off") def clear_status(self): self._lab_status.config(text="") def add_child_editor(self, child_name, child): # Adds child editor to list of editors without adding a notebook tab. self._child_editors[child_name] = child def _create_basic_tab(self,text): f = factory.frame(self.notebook) self.notebook.add(f, text=text) return f # icon_filename = "resources/%s/logo_32.png" % sy.specs["format"] # icon = factory.image(icon_filename) # group.notebook.add(swin, text=sy.sid, image=icon, compound="top") def _create_compund_tab(self,text,image_filename): try: icon = factory.image(image_filename) f = factory.frame(self.notebook) self.notebook.add(f,text=text,image=icon,compound="top") return f except IOError: msg = "IOError while loading image file '%s'" % image_filename print(msg) return self._create_basic_tab(text) def create_tab(self, tab_text, image_filename=""): if not image_filename: rs = self._create_basic_tab(tab_text) else: rs = self._create_compund_tab(tab_text,image_filename) return rs def remove_synth(self, *_): sid = self.synth.sid parser = self.app.ls_parser sh = parser.synthhelper sh.destroy_editor(sid) sh.remove_synth(sid, force=True) self.status("Removed synth: %s" % sid) def _init_info_tab(self, master): img = factory.image("resources/Tabs/info.png") frame = factory.frame(master) inner_frame = factory.frame(frame) master.add(frame, text="Info", image=img,compound="top") text_widget = factory.text_widget(inner_frame) text_widget.config(width=120, height=40) vsb = factory.scrollbar(inner_frame, orientation='vertical') vsb.config(command=text_widget.yview) text_widget.config(yscrollcommand=vsb.set, wrap='word',) text_widget.grid(row=0, column=0,sticky="ewns") vsb.grid(row=0, column=1, sticky='ns') inner_frame.grid(row=0, column=0, rowspan=8, columnspan=8, sticky="ewns") self._info_text_widget = text_widget def lift_window(self): mw = self.app.main_window() grp = mw.group_windows[self.group_index] grp.lift() self.status("Lift window") def lower_window(self): mw = self.app.main_window() grp = mw.group_windows[self.group_index] grp.lower() self.status("Lower window") def sync_program_tab(self): bnk = self.synth.bank() prog = bnk[None] slot = bnk.current_slot pp = self.synth.specs["pretty-printer"] if pp: txt = pp(prog, slot) else: txt = "" self._info_text_widget.delete(1.0, "end") self._info_text_widget.insert("end", txt) def _init_midi_tab(self, master): img = factory.image("resources/Tabs/midi.png") frame = factory.frame(master) master.add(frame, text = "Performance", image=img, compound="top") frame_channel = factory.frame(frame) frame_keytab = factory.frame(frame) lab_transpose = factory.label(frame, "Transpose") lab_keyrange = factory.label(frame, "Key Range") lab_bend = factory.label(frame, "Bend Range") self.list_channel = factory.listbox(frame_channel) sb_channel = factory.scrollbar(frame_channel) sb_channel.config(command=self.list_channel.yview) self.list_channel.config(yscrollcommand=sb_channel.set) self.list_keytab = factory.listbox(frame_keytab) sb_keytab = factory.scrollbar(frame_keytab) sb_keytab.config(command=self.list_keytab.yview) self.list_keytab.config(yscrollcommand=sb_keytab.set) spin_transpose = factory.int_spinbox(frame,self.var_transpose,-36,36) spin_keylow = factory.int_spinbox(frame,self.var_keyrange_low,0,127) spin_keyhigh = factory.int_spinbox(frame,self.var_keyrange_high,0,127) spin_bendrange = factory.int_spinbox(frame,self.var_bendrange, 0, 2400) factory.padding_label(frame).grid(row=0) lab_channel = factory.label(frame,"MIDI Input Channel") lab_channel.grid(row=0,column=0,columnspan=2, pady=8) frame_channel.grid(row=1, column=0, rowspan=4, columnspan=2,padx=8,pady=8) self.list_channel.pack(side="left", expand=True, fill="both") sb_channel.pack(after=self.list_channel, side="right", expand=True, fill="y") lab_ktab = factory.label(frame, "Key Table") lab_ktab.grid(row=0,column=2,columnspan=2,pady=8) frame_keytab.grid(row=1, column=2, rowspan=4, columnspan=2,padx=8,pady=8) self.list_keytab.pack(side="left", expand=True, fill="both") sb_keytab.pack(after=self.list_keytab, side="right", expand=True, fill="y") factory.padding_label(frame).grid(row=6) lab_transpose.grid(row=7, column=0, sticky="w", padx=4, pady=4) lab_keyrange.grid(row=8, column=0, sticky="w", padx=4, pady=4) lab_bend.grid(row=9, column=0, sticky="w", padx=4, pady=4) spin_transpose.grid(row=7, column=1, padx=4) spin_keylow.grid(row=8, column=1, padx=4) spin_keyhigh.grid(row=8, column=2, padx=4) spin_bendrange.grid(row=9, column=1, padx=4) def channel_callback(_): i = self.list_channel.curselection()[0] c = i+1 self.synth.midi_input_channel(c) self.status("MIDI Input Channel = %s" % c) def keytab_callback(_): i = self.list_keytab.curselection()[0] kt = self.list_keytab.get(i) self.synth.keytable(kt) self.status("Using keytable: %s" % kt) def transpose_callback(*_): try: x = int(self.var_transpose.get()) self.synth.transpose(x) self.status("Transpose = %s" % x) except ValueError: self.warning("Invalid transpose") def keyrange_callback(*_): try: a = int(self.var_keyrange_low.get()) b = int(self.var_keyrange_high.get()) a, b = min(a,b), max(a,b) self.synth.key_range((a,b)) self.status("Key range = [%3d, %3d]" % (a, b)) except ValueError: self.warning("Invalid keyrange") def bend_callback(*_): try: b = int(self.var_bendrange.get()) self.synth.bend_range(b) self.status("Bend range = %s" % b) except ValueError: self.warning("Invalid Bendrange") self.list_channel.bind("<<ListboxSelect>>", channel_callback) self.list_keytab.bind("<<ListboxSelect>>", keytab_callback) spin_transpose.config(command=transpose_callback) spin_transpose.bind("<Return>", transpose_callback) spin_keylow.config(command=keyrange_callback) spin_keylow.bind("<Return>", keyrange_callback) spin_keyhigh.config(command=keyrange_callback) spin_keyhigh.bind("<Return>", keyrange_callback) spin_bendrange.config(command=bend_callback) spin_bendrange.bind("<Return>", bend_callback) def sync_midi_tab(self): self.list_channel.delete(0, "end") for c in self.app.config().channel_assignments.formatted_list(): self.list_channel.insert("end", c) mic = self.synth.midi_input_channel()-1 self.list_channel.selection_set(mic) self.list_keytab.delete(0, "end") target, index = self.synth.keytable(), 0 for i, kt in enumerate(sorted(self.app.keytables.keys())): self.list_keytab.insert("end", kt) if target == kt: index = i self.list_keytab.selection_set(index) self.var_transpose.set(self.synth.transpose()) lo, hi = self.synth.key_range() self.var_keyrange_low.set(lo) self.var_keyrange_high.set(hi) self.var_bendrange.set(self.synth.bend_range()) # map1_tab -> MIDI controller, pitch wheel def _init_map1_tab(self, master): img = factory.image("resources/Tabs/map.png") HELP_TOPIC = "parameter-maps" frame = factory.frame(master) master.add(frame, text="Map1", image=img, compound="top") north = factory.label_frame(frame, "MIDI Controller Maps") south = factory.label_frame(frame, "Pitch Wheel Maps") north.grid(row=0, column=0, sticky="ew", padx=8, pady=8) south.grid(row=1, column=0, sticky="ew", padx=8, pady=8) def help_callback(): self.app.main_window().display_help(HELP_TOPIC) list_cc_maps = factory.listbox(north, ttip="Active MIDI controller maps") list_cc_maps.config(width=80, height=16) self.list_cc_maps = list_cc_maps sb = factory.scrollbar(north, orientation="vertical") sb.config(command=list_cc_maps.yview) list_cc_maps.config(yscrollcommand=sb.set) b_add_cc = factory.add_button(north, ttip="Add new controller map") b_delete_cc = factory.delete_button(north, ttip="Delete controller map") list_cc_maps.grid(row=0, column=0, rowspan=4, columnspan=8, sticky="ew") sb.grid(row=0, column=8, rowspan=4, sticky="ns") b_add_cc.grid(row=4, column=0, sticky="ew") b_delete_cc.grid(row=4, column=1, sticky="ew") list_pwheel_maps = factory.listbox(south, ttip="Active pitch wheel maps") list_pwheel_maps.config(width=80, height=8) self.list_pwheel_maps = list_pwheel_maps sb = factory.scrollbar(south, orientation="vertical") sb.config(command=list_pwheel_maps.yview) list_pwheel_maps.config(yscrollcommand=sb.set) b_add_pw = factory.add_button(south, ttip="Add pitchwheel map") b_delete_pw = factory.delete_button(south, ttip="Delete pitchwheel map") b_help = factory.help_button(south, command=help_callback) list_pwheel_maps.grid(row=0, column=0, rowspan=4, columnspan=8, sticky="ew") sb.grid(row=0, column=8, rowspan=4, sticky="ns") b_add_pw.grid(row=4, column=0, sticky="ew") b_delete_pw.grid(row=4, column=1, sticky="ew") b_help.grid(row=4, column=7, sticky="ew") def add_cc_callback(): dialog = add_map_dialog(self.synth, "cc", self.app) def delete_cc_callback(): dialog = delete_map_dialog(self, self.synth, "cc", self.app) def add_pw_callback(): dialog = add_map_dialog(self.synth, "PitchWheel", self.app) def delete_pw_callback(): dialog = delete_map_dialog(self, self.synth, "PitchWheel", self.app) b_add_cc.config(command=add_cc_callback) b_delete_cc.config(command=delete_cc_callback) b_add_pw.config(command=add_pw_callback) b_delete_pw.config(command=delete_pw_callback) def sync_map1_tab(self): perf = self.synth.bank()[None].performance cmaps = perf.controller_maps pwmaps = perf.pitchwheel_maps self.list_cc_maps.delete(0, "end") for ctrl, mapper in cmaps.items(): s = str(mapper) for q in s.split('\n'): self.list_cc_maps.insert("end", q) self.list_pwheel_maps.delete(0, "end") for q in str(pwmaps).split('\n'): self.list_pwheel_maps.insert("end", q) def _init_map2_tab(self, master): img = factory.image("resources/Tabs/map.png") HELP_TOPIC = "parameter-maps" HEIGHT = 8 frame = factory.frame(master) master.add(frame, text="Map2",image=img,compound="top") north = factory.label_frame(frame, "Velocity Maps") center = factory.label_frame(frame, "Aftertouch Maps") south = factory.label_frame(frame, "Keynumber Maps") north.grid(row=0, column=0, sticky="ew", padx=8, pady=8) center.grid(row=1, column=0, sticky="ew", padx=8) south.grid(row=2, column=0, sticky="ew", padx=8, pady=8) def help_callback(): self.app.main_window().display_help(HELP_TOPIC) list_vel_maps = factory.listbox(north, ttip="Active velocity maps") list_vel_maps.config(width=80, height=HEIGHT) self.list_vel_maps = list_vel_maps sb = factory.scrollbar(north, orientation="vertical") sb.config(command=list_vel_maps.yview) list_vel_maps.config(yscrollcommand=sb.set) b_add_vel = factory.add_button(north, ttip="Add velocity map") b_delete_vel = factory.delete_button(north, ttip="Delete velocity map") list_vel_maps.grid(row=0, column=0, columnspan=8, sticky="ew") sb.grid(row=0, column=8, sticky="ns") b_add_vel.grid(row=1, column=0, sticky="ew") b_delete_vel.grid(row=1, column=1, sticky="ew") list_atouch_maps = factory.listbox(center, ttip="Active after touch maps") list_atouch_maps.config(width=80, height=HEIGHT) self.list_atouch_maps = list_atouch_maps sb = factory.scrollbar(center, orientation="vertical") sb.config(command=list_atouch_maps.yview) list_atouch_maps.config(yscrollcommand=sb.set) b_add_atouch = factory.add_button(center, ttip="Add after touch map") b_delete_atouch = factory.delete_button(center, ttip="Delete after touch map") list_atouch_maps.grid(row=0, column=0, columnspan=8, sticky="ew") sb.grid(row=0, column=8, sticky="ns") b_add_atouch.grid(row=1, column=0, sticky="ew") b_delete_atouch.grid(row=1, column=1, sticky="ew") list_keynum_maps = factory.listbox(south, ttip="Active key number maps") list_keynum_maps.config(width=80, height=HEIGHT) self.list_keynum_maps = list_keynum_maps sb = factory.scrollbar(south, orientation="vertical") sb.config(command=list_keynum_maps.yview) list_keynum_maps.config(yscrollcommand=sb.set) b_add_keynum = factory.add_button(south, ttip="Add key number map") b_delete_keynum = factory.delete_button(south, ttip="Delete key number map") b_help = factory.help_button(south, command=help_callback) list_keynum_maps.grid(row=0, column=0, columnspan=8, sticky="ew") sb.grid(row=0, column=8, sticky="ns") b_add_keynum.grid(row=1, column=0, sticky="ew") b_delete_keynum.grid(row=1, column=1, sticky="ew") b_help.grid(row=1, column=7, sticky="ew") def add_map_callback(event): widget = event.widget if widget is b_add_vel: dialog = add_map_dialog(self.synth, "velocity", self.app) elif widget is b_add_atouch: dialog = add_map_dialog(self.synth, "aftertouch", self.app) elif widget is b_add_keynum: dialog = add_map_dialog(self.synth, "keynumber", self.app) else: msg = "Invalid widget - Should never see this" raise ValueError(msg) def delete_map_callback(event): widget = event.widget if widget is b_delete_vel: dialog = delete_map_dialog(self, self.synth, "velocity", self.app) elif widget is b_delete_atouch: dialog = delete_map_dialog(self, self.synth, "aftertouch", self.app) elif widget is b_delete_keynum: dialog = delete_map_dialog(self, self.synth, "keynumber", self.app) else: msg = "Invalid widget - Should never see this" raise ValueError(msg) b_add_vel.bind("<Button-1>", add_map_callback) b_add_atouch.bind("<Button-1>", add_map_callback) b_add_keynum.bind("<Button-1>", add_map_callback) b_delete_vel.bind("<Button-1>", delete_map_callback) b_delete_atouch.bind("<Button-1>", delete_map_callback) b_delete_keynum.bind("<Button-1>", delete_map_callback) def sync_map2_tab(self): perf = self.synth.bank()[None].performance vmaps = perf.velocity_maps atmaps = perf.aftertouch_maps knmaps = perf.keynumber_maps self.list_vel_maps.delete(0, 'end') self.list_atouch_maps.delete(0, 'end') self.list_keynum_maps.delete(0, 'end') for q in str(vmaps).split('\n'): self.list_vel_maps.insert('end', q) for q in str(atmaps).split('\n'): self.list_atouch_maps.insert('end', q) for q in str(knmaps).split('\n'): self.list_keynum_maps.insert('end', q) def status(self, msg): self._lab_status.config(text = msg) def warning(self, msg): msg = "WARNING: %s" % msg self._lab_status.config(text = msg) def set_value(self, param, value): for ed in self._child_editors.items(): ed.set_value(param, value) def set_aspect(self, param, value): for ed in self._child_editors.values(): ed.set_value(param, value) def sync(self, *ignore): self.sync_program_tab() self.sync_midi_tab() self.sync_map1_tab() self.sync_map2_tab() if "bank" not in ignore: self.bank_editor.sync_no_propegate() for key, ed in self._child_editors.items(): if key not in ignore: ed.sync(*ignore) def annotation_keys(self): """ See TkSubEditor annotation """ acc = [] for ed in self._child_editors.values(): acc += ed.annotation_keys() return acc def set_annotation(self, key, text): """ See TkSubEditor annotation """ for ed in self._child_editors.values(): ed.annotation(key, text) def get_annotation(self, key): """ See TkSubEditor annotation """ rs = None for ed in self._child_editors.values(): rs = ed.get_annotation(key) if rs != None: return rs return None def update_progressbar(self, count, value): """ Set progress bar to position value/count, where. count - Expected number of steps. value - Current step number. """ self._progressbar.config(mode="determinate", maximum=count) self._progressbar.step() self.update_idletasks() def busy(self, flag, message=""): """ Set progress bar to 'busy' """ if message: self.status(message) self._progressbar.config(mode="indeterminate") if flag: self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8) self._progressbar.start() else: self._progressbar.stop() self.update_idletasks()