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()
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 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 VideoScanProgressScreen(GuiBaseFrame): def __init__(self, parent, controller, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) self.counting_left_frames = None def init_widgets(self): self.content_wrapper = Frame(self) self.content_wrapper.configure(background="white") self.screen_title = Header1Label( self.content_wrapper, text="Scanning video for information...\n") self.progress_bar = Progressbar(self.content_wrapper, orient=HORIZONTAL, mode="indeterminate", length=WINDOW_WIDTH / 2) self.wait_text = PLabel( self.content_wrapper, text="\nThis might take a few minutes." "\nPlease do not change the video files while this is running.\n") self.left_frames_count = PLabel(self.content_wrapper, text=LEFT_FRAMES_COUNT_PREFIX + "0") self.right_frames_count = PLabel(self.content_wrapper, text=RIGHT_FRAMES_COUNT_PREFIX + "0") self.elapsed_time_label = PLabel(self.content_wrapper) self.empty_space = PLabel(self.content_wrapper, text=" ") self.next_button = Button( self.content_wrapper, text="Next", state=DISABLED, command=lambda: self.controller.show_next_frame()) def add_widgets_to_frame(self): self.screen_title.pack() self.progress_bar.pack() self.wait_text.pack() self.left_frames_count.pack() self.right_frames_count.pack() self.elapsed_time_label.pack() self.empty_space.pack() self.next_button.pack() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): self.start_time = time.time() self.progress_bar.start() self.frame_count_thread = threading.Thread( target=self.controller.video_frame_loader.count_frames_in_videos, kwargs={"controller": self.controller}) self.frame_count_thread.start() self.master.after(50, self.check_thread) def update_frame(self, data): if LEFT_FRAMES_COUNT_PREFIX in data: self.left_frames_count.configure(text=data) if RIGHT_FRAMES_COUNT_PREFIX in data: self.right_frames_count.configure(text=data) self.elapsed_time_label.configure( text=ELAPSED_TIME_PREFIX + str(datetime.timedelta(seconds=int(time.time() - self.start_time)))) def on_hide_frame(self): self.progress_bar.stop() def check_thread(self): if self.frame_count_thread.is_alive(): self.master.after(50, self.check_thread) else: self.progress_bar.stop() self.wait_text.configure(text="\nDone!\nPress Next to continue.\n") self.next_button.configure(state=NORMAL)
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 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 Metadator(Tk): def __init__(self): u""" Main window constructor Creates 1 frame and 2 labeled subframes """ # first: the log # see: http://sametmax.com/ecrire-des-logs-en-python/ self.logger = logging.getLogger() self.logger.setLevel(logging.DEBUG) # all errors will be get log_form = logging.Formatter('%(asctime)s || %(levelname)s || %(message)s') logfile = RotatingFileHandler('Metadator_LOG.log', 'a', 5000000, 1) logfile.setLevel(logging.DEBUG) logfile.setFormatter(log_form) self.logger.addHandler(logfile) self.logger.info('\n\t ======== Metadator ========') # first messages self.logger.info('Starting the UI') # checking the path to GDAL in the path if "GDAL_DATA" not in env.keys(): try: gdal.SetConfigOption(str('GDAL_DATA'), str(path.abspath(r'data/gdal'))) except: print("Oups! Something has gone wrong...\ see: https://github.com/Guts/Metadator/issues/21") else: pass # basics settings Tk.__init__(self) # constructor of parent graphic class self.title(u'Metadator {0}'.format(MetadatorVersion)) self.style = Style() # more friendly windows style if opersys == 'win32': self.logger.info('Op. system: {0}'.format(platform.platform())) self.iconbitmap('Metadator.ico') # windows icon self.uzer = env.get(u'USERNAME') elif opersys == 'linux2': self.logger.info('Op. system: {0}'.format(platform.platform())) self.uzer = env.get(u'USER') icon = Image("photo", file=r'data/img/metadator.gif') self.call('wm', 'iconphoto', self._w, icon) self.minsize(580, 100) self.style.theme_use('clam') elif opersys == 'darwin': self.logger.info('Op. system: {0}'.format(platform.platform())) self.uzer = env.get(u'USER') else: self.logger.warning('Operating system not tested') self.logger.info('Op. system: {0}'.format(platform.platform())) self.resizable(width=False, height=False) self.focus_force() self.logger.info('GDAL version: {}'.format(gdal.__version__)) # variables self.def_rep = "" # folder to search for self.def_lang = 'FR' # language to start self.def_doc = IntVar() # to export into Word self.def_xls = IntVar() # to export into Excel 2003 self.def_xml = IntVar() # to export into ISO 19139 self.def_cat = IntVar() # to merge all output Word files self.def_odt = IntVar() # to export into OpenDocumentText self.def_dict = IntVar() # to make a dictionnary of data self.def_kass = IntVar() # to handle field name case sensitive self.def_stat = IntVar() # to active/disable stats fields self.li_pro = [] # list for profiles in language selected self.li_shp = [] # list for shapefiles path self.li_tab = [] # list for MapInfo tables path self.num_folders = 0 # number of folders explored self.today = strftime("%Y-%m-%d") # date of the day self.dico_layer = OD() # dictionary about layer properties self.dico_profil = OD() # dictionary from profile selected self.dico_fields = OD() # dictionary for fields information self.dico_rekur = OD() # dictionary of recurring attributes self.dico_err = OD() # errors list self.dico_help = OD() # dictionary of help texts li_lang = [lg for lg in listdir(r'locale')] # available languages self.blabla = OD() # texts dictionary # GUI fonts ft_tit = tkFont.Font(family="Times", size=10, weight=tkFont.BOLD) # fillfulling self.load_settings() self.load_texts(self.def_lang) self.li_profiles(self.def_lang) self.li_rekurs(self.def_lang) self.recup_help(self.def_lang) # Tabs self.nb = Notebook(self) self.tab_globals = Frame(self.nb) # tab_id = 0 self.tab_options = Frame(self.nb) # tab_id = 1 self.tab_attribs = Frame(self.nb) # tab_id = 2 self.nb.add(self.tab_globals, text=self.blabla.get('gui_tab1'), padding=3) self.nb.add(self.tab_options, text=self.blabla.get('gui_tab2'), padding=3) self.nb.add(self.tab_attribs, text=self.blabla.get('gui_tab3'), padding=3) self.logger.info('UI created') ### Tab 1: global # Frames self.FrPath = Labelframe(self.tab_globals, name='main', text=self.blabla.get('tab1_fr1')) self.FrProg = Labelframe(self.tab_globals, name='progression', text=self.blabla.get('tab1_frprog')) ## Frame 1 # target folder self.labtarg = Label(self.FrPath, text=self.blabla.get('tab1_path')) self.target = Entry(self.FrPath, width=25) self.browsetarg = Button(self.FrPath, # browse button text=self.blabla.get('tab1_browse'), command=lambda: self.setpathtarg(), takefocus=True) self.browsetarg.focus_force() # force the focus on self.profil = Label(self.FrPath, text=self.blabla.get('tab1_prof')) # profiles switcher self.ddl_profil = Combobox(self.FrPath, values=self.li_pro, width=5) self.ddl_profil.current(0) self.ddl_profil.bind("<<ComboboxSelected>>", self.select_profil) # widgets placement self.labtarg.grid(row=1, column=1, columnspan=1, sticky=N + S + W + E, padx=2, pady=8) self.target.grid(row=1, column=2, columnspan=1, sticky=N + S + W + E, padx=2, pady=8) self.browsetarg.grid(row=1, column=3, sticky=N + S + W + E, padx=2, pady=8) self.profil.grid(row=2, column=1, sticky=N + S + W + E, padx=2, pady=8) self.ddl_profil.grid(row=2, column=2, sticky=W + E + N + S, columnspan=2, padx=2, pady=8) # tooltips InfoBulle(self.target, message=self.dico_help.get(30)[1]) InfoBulle(self.browsetarg, message=self.dico_help.get(30)[1]) InfoBulle(self.ddl_profil, message=self.dico_help.get(31)[1]) ## Frame 2 # variables self.status = StringVar(self.FrProg, '') # widgets self.prog_layers = Progressbar(self.FrProg, orient="horizontal") self.prog_fields = Progressbar(self.FrProg, orient="horizontal") # widgets placement Label(self.FrProg, textvariable=self.status, foreground='DodgerBlue').pack(expand=1) self.prog_layers.pack(expand=1, fill=X) # Frames placement self.FrPath.pack(expand=1, fill='both') self.FrProg.pack(expand=1, fill='both') ### Tab 2: options # Export options caz_doc = Checkbutton(self.tab_options, text=u'HTML / Word (.doc/.docx)', variable=self.def_doc, command=lambda: self.catalog_dependance()) caz_xls = Checkbutton(self.tab_options, text=u'Excel 2003 (.xls)', variable=self.def_xls) caz_xml = Checkbutton(self.tab_options, text=u'XML (ISO 19139)', variable=self.def_xml) self.caz_cat = Checkbutton(self.tab_options, text=self.blabla.get('tab2_merge'), variable=self.def_cat) caz_odt = Checkbutton(self.tab_options, text=u'Open Document Text (.odt)', variable=self.def_odt) # widgets placement caz_doc.grid(row=1, column=0, sticky=N + S + W + E, padx=2, pady=2) self.caz_cat.grid(row=2, column=0, sticky=N + S + W + E, padx=2, pady=2) caz_xls.grid(row=1, column=1, sticky=N + S + W + E, padx=2, pady=2) caz_xml.grid(row=2, column=1, sticky=N + S + W + E, padx=2, pady=2) caz_odt.grid(row=3, column=1, sticky=N + S + W + E, padx=2, pady=2) # disabling the widgets which work only on Windows OS if opersys != 'win32': self.logger.info('Disabling Windows reserved functions.') self.def_doc.set(0) self.def_cat.set(0) caz_doc.configure(state='disabled') self.caz_cat.configure(state='disabled') else: pass # make the catalog option depending on the Word option self.catalog_dependance() # tooltips InfoBulle(caz_doc, message=self.dico_help.get(33)[1], image=self.dico_help.get(33)[2]) InfoBulle(caz_xls, message=self.dico_help.get(34)[1], image=self.dico_help.get(34)[2]) InfoBulle(caz_xml, message=self.dico_help.get(35)[1], image=self.dico_help.get(35)[2]) InfoBulle(caz_odt, message=self.dico_help.get(36)[1], image=self.dico_help.get(36)[2]) InfoBulle(self.caz_cat, message=self.dico_help.get(37)[1], image=self.dico_help.get(37)[2]) ### Tab 3: recurring attributes # Attribute selector self.lab_chps = Label(self.tab_attribs, text=self.blabla.get('tab3_sele')) self.ddl_attr = Combobox(self.tab_attribs, values=self.dico_rekur.keys()) self.ddl_attr.bind("<<ComboboxSelected>>", self.edit_rekur) self.supr = Button(self.tab_attribs, text=self.blabla.get('tab3_supp'), command=self.del_rekur) # frame self.FrRekur = Labelframe(self.tab_attribs, name='attributes', text=self.blabla.get('tab3_tit')) # attribute settings self.tab3_LBnom = Label(self.FrRekur, text=self.blabla.get('tab3_nom'), state=DISABLED) self.tab3_ENnom = Entry(self.FrRekur, state=DISABLED) self.tab3_LBdesc = Label(self.FrRekur, text=self.blabla.get('tab3_desc'), state=DISABLED) self.tab3_TXdesc = Text(self.FrRekur, height=5, width=30, wrap=WORD, state=DISABLED) self.tab3_CBcass = Checkbutton(self.FrRekur, text=self.blabla.get('tab3_cass'), variable=self.def_kass, state=DISABLED) self.tab3_CBstat = Checkbutton(self.FrRekur, text=self.blabla.get('tab3_stat'), variable=self.def_stat, state=DISABLED) # Validation button self.save = Button(self.FrRekur, text=self.blabla.get('tab3_save'), command=self.save_rekur, state='disabled') # widgets placement self.lab_chps.grid(row=1, column=1, sticky=N + S + W, padx=2, pady=2) self.ddl_attr.grid(row=1, column=2, sticky=N + S + W + E, padx=2, pady=2) self.supr.grid(row=1, column=3, sticky=N + S + W + E, padx=2, pady=2) self.tab3_LBnom.grid(row=1, column=0, columnspan=1, sticky=N + S + W, padx=2, pady=2) self.tab3_ENnom.grid(row=1, column=1, columnspan=1, sticky=N + S + W + E, padx=2, pady=2) self.tab3_LBdesc.grid(row=2, column=0, columnspan=1, sticky=N + S + W + E, padx=2, pady=2) self.tab3_TXdesc.grid(row=2, column=1, columnspan=2, sticky=N + S + W + E, padx=2, pady=2) self.tab3_CBcass.grid(row=3, column=0, columnspan=1, sticky=N + S + W + E, padx=2, pady=2) self.tab3_CBstat.grid(row=3, column=1, columnspan=1, sticky=N + S + W + E, padx=2, pady=2) self.save.grid(row=5, column=0, columnspan=4, sticky=N + S + W + E, padx=2, pady=2) # Frame placement self.FrRekur.grid(row=2, column=1, columnspan=3, sticky=N + S + W + E, padx=2, pady=2) # tooltips InfoBulle(self.lab_chps, message=self.dico_help.get(38)[1]) InfoBulle(self.ddl_attr, message=self.dico_help.get(39)[1]) InfoBulle(self.supr, message=self.dico_help.get(40)[1]) InfoBulle(self.tab3_CBcass, message=self.dico_help.get(41)[1]) InfoBulle(self.tab3_CBstat, message=self.dico_help.get(42)[1]) ## Main frame # Hola self.welcome = Label(self, text=self.blabla.get('hi') + self.uzer, font=ft_tit, foreground="red2") # Image self.icone = PhotoImage(master=self, file=r'data/img/metadator.gif') Label(self, image=self.icone).grid(row=2, column=0, padx=2, pady=2, sticky=N + S + W + E) # credits s = Style(self) s.configure('Kim.TButton', foreground='DodgerBlue', borderwidth=0, relief="flat") Button(self, text='by Julien M. (2015)', style='Kim.TButton', command=lambda: open_new('https://github.com/Guts')).grid(row=3, padx=2, pady=2, sticky=W+E) # language switcher self.ddl_lang = Combobox(self, values=li_lang, width=5) self.ddl_lang.current(li_lang.index(self.def_lang)) self.ddl_lang.bind("<<ComboboxSelected>>", self.change_lang) # Go go go button self.val = Button(self, text=self.blabla.get('tab1_go'), state='active', command=lambda: self.process()) # Cancel button self.can = Button(self, text=self.blabla.get('gui_quit'), command=self.destroy) # widgets placement self.welcome.grid(row=0, column=0, columnspan=1, sticky=N + S + W + E, padx=2, pady=2) self.ddl_lang.grid(row=1, column=0, sticky=N, padx=2, pady=0) self.can.grid(row=4, column=0, sticky=N + S + W + E, padx=2, pady=2) self.val.grid(row=4, column=1, sticky=N + S + W + E, padx=2, pady=2) # tooltips InfoBulle(self.ddl_lang, message=self.dico_help.get(32)[1]) ### Notebook placement self.nb.grid(row=0, rowspan=4, column=1, sticky=N + S + W + E) # keep updated list of profiles self.maj() def maj(self): """ update the profiles dropdown list every second """ try: self.li_profiles(self.ddl_lang.get()) self.ddl_profil['values'] = self.li_pro self.after(1000, self.maj) except WindowsError: # avoid an error occuring with browse button self.after(1000, self.maj) pass def alter_state(self, parent, new_state): """ just a function to change easily the state of all children widgets of a parent class parent=Tkinter class with children (Frame, Labelframe, Tk, etc.) new_state=Tkinter keyword for widget state (ACTIVE, NORMAL, DISABLED) """ for child in parent.winfo_children(): child.configure(state=new_state) # end of function return parent, new_state def catalog_dependance(self): """ unselect the catalog option if the word option is unselected """ if self.def_doc.get() == 0: self.def_cat.set(0) self.caz_cat.config(state='disabled') elif self.def_doc.get() == 1: self.caz_cat.config(state='normal') # end of function return def load_settings(self): u""" load settings from last execution """ confile = 'options.ini' config = ConfigParser.RawConfigParser() config.read(confile) # basics self.def_lang = config.get('basics', 'def_codelang') self.def_rep = config.get('basics', 'def_rep') # export preferences self.def_doc.set(config.get('export_preferences', 'def_word')) self.def_cat.set(config.get('export_preferences', 'def_cat')) self.def_xls.set(config.get('export_preferences', 'def_xls')) self.def_xml.set(config.get('export_preferences', 'def_xml')) self.def_dict.set(config.get('export_preferences', 'def_dict')) self.def_odt.set(config.get('export_preferences', 'def_odt')) # log self.logger.info('Last options loaded') # End of function return config, self.def_rep, self.def_lang, self.def_doc def save_settings(self): u""" save options in order to make the next execution easier """ confile = 'options.ini' config = ConfigParser.RawConfigParser() # add sections config.add_section('basics') config.add_section('export_preferences') # basics config.set('basics', 'def_codelang', self.ddl_lang.get()) config.set('basics', 'def_rep', self.target.get()) # export preferences config.set('export_preferences', 'def_word', self.def_doc.get()) config.set('export_preferences', 'def_cat', self.def_cat.get()) config.set('export_preferences', 'def_xls', self.def_xls.get()) config.set('export_preferences', 'def_xml', self.def_xml.get()) config.set('export_preferences', 'def_dict', self.def_dict.get()) config.set('export_preferences', 'def_odt', self.def_odt.get()) # Writing the configuration file with open(confile, 'wb') as configfile: config.write(configfile) # End of function return config def change_lang(self, event): u""" update the texts dictionary with the language selected """ new_lang = event.widget.get() # change to the new language selected self.load_texts(new_lang) self.li_profiles(new_lang) self.li_rekurs(new_lang) self.ddl_profil.delete(0, END) self.ddl_profil.config(values=self.li_pro) self.ddl_profil.update() self.ddl_attr.config(values=self.dico_rekur.keys()) self.recup_help(new_lang) # update widgets text # tab1 self.nb.tab(0, text=self.blabla.get('gui_tab1')) self.welcome.config(text=self.blabla.get('hi') + self.uzer) self.can.config(text=self.blabla.get('gui_quit')) self.FrPath.config(text=self.blabla.get('tab1_fr1')) self.FrProg.config(text=self.blabla.get('tab1_frprog')) self.labtarg.config(text=self.blabla.get('tab1_path')) self.browsetarg.config(text=self.blabla.get('tab1_browse')) self.val.config(text=self.blabla.get('tab1_go')) self.profil.config(text=self.blabla.get('tab1_prof')) # tab2 self.nb.tab(1, text=self.blabla.get('gui_tab2')) self.caz_cat.config(text=self.blabla.get('tab2_merge')) # tab3 self.nb.tab(2, text=self.blabla.get('gui_tab3')) self.lab_chps.config(text=self.blabla.get('tab3_sele')) self.supr.config(text=self.blabla.get('tab3_supp')) self.FrRekur.config(text=self.blabla.get('tab3_tit')) self.tab3_LBnom.config(text=self.blabla.get('tab3_nom')) self.tab3_LBdesc.config(text=self.blabla.get('tab3_desc')) self.tab3_CBcass.config(text=self.blabla.get('tab3_cass')) self.tab3_CBstat.config(text=self.blabla.get('tab3_stat')) self.save.config(text=self.blabla.get('tab3_save')) # End of function return self.blabla def load_texts(self, lang='FR'): u""" Load texts according to the selected language """ # clearing the text dictionary self.blabla.clear() # open xml cursor xml = ET.parse('locale/{0}/lang_{0}.xml'.format(lang)) # Looping and gathering texts from the xml file for elem in xml.getroot().getiterator(): self.blabla[elem.tag] = elem.text # updating the GUI self.update() # en of function return self.blabla def setpathtarg(self): """ ...browse and insert the path of target folder """ foldername = askdirectory(parent=self, initialdir=self.def_rep, mustexist=True, title=self.blabla.get('gui_cible')) # check if a folder has been choosen if foldername: try: self.target.delete(0, END) self.target.insert(0, foldername) except: info(title=self.blabla.get('nofolder'), message=self.blabla.get('nofolder')) return # count shapefiles and MapInfo files in a separated thread proc = threading.Thread(target=self.li_geofiles, args=(foldername, )) proc.daemon = True proc.start() # end of function return foldername def li_geofiles(self, foldertarget): u""" List shapefiles and MapInfo files (.tab, not .mid/mif) contained in the folders structure """ # reseting global variables self.li_shp = [] self.li_tab = [] self.browsetarg.config(state=DISABLED) # Looping in folders structure self.status.set(self.blabla.get('tab1_prog1')) self.prog_layers.start() for root, dirs, files in walk(unicode(foldertarget)): self.num_folders = self.num_folders + len(dirs) for f in files: """ looking for files with geographic data """ try: unicode(path.join(root, f)) full_path = path.join(root, f) except UnicodeDecodeError: full_path = path.join(root, f.decode('latin1')) # Looping on files contained if path.splitext(full_path.lower())[1].lower() == '.shp'\ and (path.isfile('{0}.dbf'.format(full_path[:-4])) or path.isfile('{0}.DBF'.format(full_path[:-4])))\ and (path.isfile('{0}.shx'.format(full_path[:-4])) or path.isfile('{0}.SHX'.format(full_path[:-4]))): """ listing compatible shapefiles """ # add complete path of shapefile self.li_shp.append(full_path) elif path.splitext(full_path.lower())[1] == '.tab'\ and (path.isfile(full_path[:-4] + '.dat') or path.isfile(full_path[:-4] + '.DAT'))\ and (path.isfile(full_path[:-4] + '.map') or path.isfile(full_path[:-4] + '.MAP'))\ and (path.isfile(full_path[:-4] + '.id') or path.isfile(full_path[:-4] + '.ID')): """ listing MapInfo tables """ # add complete path of MapInfo file self.li_tab.append(full_path) # stopping the progress bar self.prog_layers.stop() # Lists ordering and tupling self.li_shp.sort() self.li_shp = tuple(self.li_shp) self.li_tab.sort() self.li_tab = tuple(self.li_tab) # setting the label text and activing the buttons self.status.set(unicode(len(self.li_shp)) + u' shapefiles - ' + unicode(len(self.li_tab)) + u' tables (MapInfo) - ' + unicode(self.num_folders) + self.blabla.get('log_numfold')) self.browsetarg.config(state=ACTIVE) self.val.config(state=ACTIVE) # End of function return foldertarget, self.li_shp, self.li_tab def li_profiles(self, lang): u""" list profiles already existing """ # reseting global variable self.li_pro = [] # Looping in folders structure folder_profiles = path.join('locale/', lang + '/profiles/') self.li_pro = [lg[:-4] for lg in listdir(folder_profiles)] self.li_pro.append(self.blabla.get('tab1_new')) # End of function return folder_profiles, self.li_pro def li_rekurs(self, lang): u""" List recurring attributes that already exist in the selected language """ # clearing the text dictionary self.dico_rekur.clear() champis = path.abspath(r'locale/{0}/champignons_{0}.xml'.format(lang)) xml = ET.parse(champis) # Looping and gathering texts from the xml file for elem in xml.findall('champ'): rek_name = elem.find('intitule').text rek_desc = elem.find('description').text rek_kass = elem.find('case').text rek_stat = elem.find('stats').text self.dico_rekur[rek_name] = rek_desc, rek_kass, rek_stat self.dico_rekur[self.blabla.get('tab3_new')] = '', 0, 0 # updating the GUI self.update() # End of function return self.dico_rekur def edit_rekur(self, event): u""" preparing the form to edit a recurring attribute """ rekur = event.widget.get() # deactivate the selector self.ddl_attr.config(state=DISABLED) # activate the form self.alter_state(self.FrRekur, NORMAL) # change to the new language selected self.tab3_ENnom.insert(0, rekur) self.tab3_TXdesc.insert(1.0, self.dico_rekur.get(rekur)[0]) self.def_kass.set(self.dico_rekur.get(rekur)[1]) self.def_stat.set(self.dico_rekur.get(rekur)[2]) # End of function return self.dico_rekur def save_rekur(self): u""" save the recurring attribute edited """ # check if the attribute already exists if self.tab3_ENnom.get() in self.dico_rekur: if not askyesno(title=self.blabla.get('tab3_alert_exist1'), message=self.blabla.get('tab3_alert_exist2')): return else: pass else: pass # save self.dico_rekur[self.tab3_ENnom.get()] = self.tab3_TXdesc.get(1.0, END).rstrip(),\ self.def_kass.get(),\ self.def_stat.get() # reset the form self.tab3_ENnom.delete(0, END) self.tab3_TXdesc.delete(1.0, END) self.def_kass.set(0) self.def_stat.set(0) # deactivate the form self.alter_state(self.FrRekur, DISABLED) # updating the dropdown list self.ddl_attr.config(state=NORMAL) self.ddl_attr.delete(0, END) self.ddl_attr['values'] = self.dico_rekur.keys() # End of function return self.dico_rekur def del_rekur(self): u""" delete the selected recurring attribute """ # reactivate the selector self.ddl_attr.config(state=ACTIVE) self.dico_rekur.pop(self.ddl_attr.get()) self.ddl_attr.delete(0, END) self.ddl_attr['values'] = self.dico_rekur.keys() # reset the form self.tab3_ENnom.delete(0, END) self.tab3_TXdesc.delete(1.0, END) self.def_kass.set(0) self.def_stat.set(0) # deactivate the form self.alter_state(self.FrRekur, DISABLED) # End of function return self.dico_rekur def saveas_rekurs(self, lang): u""" save the recurring fields into the file dedicated """ rekur = ET.Element(u'champs') xml_path = r'locale/{0}/champignons_{0}.xml'.format(lang) self.dico_rekur.pop(self.blabla.get('tab3_new')) with open(xml_path, 'w') as champis: for elem in self.dico_rekur.keys(): rek = ET.SubElement(rekur, u'champ') # name of recurring attribute rek_name = ET.SubElement(rek, u'intitule') rek_name.text = elem # description of recurring attribute rek_desc = ET.SubElement(rek, u'description') rek_desc.text = self.dico_rekur.get(elem)[0] # stats option of recurring attribute rek_stats = ET.SubElement(rek, u'stats') rek_stats.text = unicode(self.dico_rekur.get(elem)[1]) # case sensitive option of recurring attribute rek_case = ET.SubElement(rek, u'case') rek_case.text = unicode(self.dico_rekur.get(elem)[2]) # creating the xml tree out_rekurs = ET.ElementTree(rekur) # saving it out_rekurs.write(xml_path, encoding='utf-8', xml_declaration='version="1.0"', method='xml') # End of function return self.dico_rekur def select_profil(self, event): """ when a profile is selected... """ profsel = event.widget.get() # if user wants to use an existing profile or create a new one if profsel == self.blabla.get('tab1_new'): self.val.config(text=self.blabla.get('tab1_crprofil')) else: self.val.config(text=self.blabla.get('tab1_go')) # end of function return self.val def recup_profil(self, lang): """ get the information from the profile selected """ # clearing the profile dictionary self.dico_profil.clear() # specific path to profile file path_profile = path.join('locale/{0}/profiles/{1}.xml'.format(lang, self.ddl_profil.get())) with open(path_profile, 'r') as profile: # open xml parser xml = ET.parse(profile) # basic informations self.dico_profil['description'] = xml.find('description').text self.dico_profil['sources'] = xml.find('sources').text self.dico_profil['url'] = xml.find('url').text self.dico_profil['url_label'] = xml.find('url_label').text self.dico_profil[u'diffusion'] = xml.find('diffusion').text # data language lang_data = xml.find(u'lang_data') self.dico_profil[u"lang_data"] = lang_data.find(u'name').text # metadata language lang_metad = xml.find(u'lang_metad') self.dico_profil[u"lang_md"] = lang_metad.find(u'name').text # diffusion constraints diff = xml.find(u'diffusion') self.dico_profil['diffusion'] = diff.find(u'name').text # update rythm rythm = xml.find(u'rythm') self.dico_profil['rythm'] = rythm.find(u'name').text # INSPIRE themes themes = xml.find('themesinspire') li_themesinspire = [theme.find('name').text for theme in themes.findall('theme')] self.dico_profil['themesinspire'] = li_themesinspire # custom keywords keywords = xml.find('keywords') li_keywords = [keyword.find('name').text for keyword in keywords.findall('keyword')] self.dico_profil['keywords'] = li_keywords # places keywords geokeywords = xml.find('geokeywords') li_geokeywords = [geokeyword.find('name').text for geokeyword in geokeywords.findall('geokeyword')] self.dico_profil['geokeywords'] = li_geokeywords # contacts contacts = xml.find(u'contacts') # point of contact cont = contacts.find(u'pointdecontact') self.dico_profil[u'cont_name'] = cont.find(u'name').text self.dico_profil[u'cont_orga'] = cont.find(u'org').text self.dico_profil[u'cont_mail'] = cont.find(u'mail').text self.dico_profil[u'cont_role'] = cont.find(u'role').text self.dico_profil[u'cont_func'] = cont.find(u'func')[0].text self.dico_profil[u'cont_street'] = cont.find(u'street').text self.dico_profil[u'cont_city'] = cont.find(u'city').text self.dico_profil[u'cont_cp'] = cont.find(u'cp').text self.dico_profil[u'cont_country'] = cont.find(u'country').text self.dico_profil[u'cont_phone'] = cont.find(u'tel').text # second contact (responsable, etc.) resp = contacts.find(u'second_contact') self.dico_profil[u'resp_name'] = resp.find(u'name').text self.dico_profil[u'resp_orga'] = resp.find(u'org').text self.dico_profil[u'resp_mail'] = resp.find(u'mail').text self.dico_profil[u'resp_role'] = resp.find(u'role').text self.dico_profil[u'resp_func'] = resp.find(u'func')[0].text self.dico_profil[u'resp_street'] = resp.find(u'street').text self.dico_profil[u'resp_city'] = resp.find(u'city').text self.dico_profil[u'resp_cp'] = resp.find(u'cp').text self.dico_profil[u'resp_country'] = resp.find(u'country').text self.dico_profil[u'resp_phone'] = resp.find(u'tel').text # End of function return self.dico_profil def recup_help(self, lang): """ get the help texts """ # specific path to xml file path_help = 'locale/%s/help_%s.xml' % (lang, lang) # reading and parsing the xml with open(path_help, 'r') as source: xml = ET.parse(source) # xml cursor for tooltip in xml.findall('tooltip'): idu = tooltip.find('id').text ref = tooltip.find('ref').text txt = tooltip.find('txt').text img = tooltip.find('image').text doc = tooltip.find('doc').text # fillfulling the INSPIRE dictionary self.dico_help[int(idu)] = ref, txt, img, doc # End of function return self.dico_help def process(self): u""" launch the different processes """ # display the main tab self.nb.select(0) # check option selected: process or create a new profile if self.ddl_profil.get() == self.blabla.get('tab1_new'): # launching the profile form self.logger.info('Creation of a new profile') tr_profile = threading.Thread(target=NewProfile, args=(self.blabla, self.ddl_lang.get(), self.dico_help, self.li_pro)) tr_profile.daemon = True tr_profile.run() # NewProfile(self.blabla, self.ddl_lang.get(), self.li_pro) self.li_profiles(self.ddl_lang.get()) # updating the dropdow list self.ddl_profil['values'] = self.li_pro return # check if the target folder has been selected if self.target.get() == "": info(title=self.blabla.get('info_blanktarget1'), message=self.blabla.get('info_blanktarget2')) return # check if a profile has been selected if self.ddl_profil.get() == "": info(title=self.blabla.get('info_blankprofile1'), message=self.blabla.get('info_blankprofile2')) return # disabling others GUI parts self.tab_globals.focus_force() self.alter_state(self.FrPath, DISABLED) # check if there are some layers into the folder structure if len(self.li_shp) + len(self.li_tab) == 0: self.logger.warning("No geofiles found in the folder structure") self.status.set(self.blabla.get('log_nodata')) return # specific variables dest = path.join(self.target.get(), 'metadator') if not path.isdir(dest): # test if folder already exists mkdir(dest, 0777) # if not, we create it # getting profile informations self.recup_profil(self.ddl_lang.get()) # saving options in a separated thread tr_options = threading.Thread(target=self.save_settings) tr_options.daemon = True tr_options.start() self.logger.info('Current options saved') # saving recurring fiels in a separated thread tr_rekurs = threading.Thread(target=self.saveas_rekurs, args=(self.ddl_lang.get(), )) tr_rekurs.daemon = True tr_rekurs.start() # configuring the progression bar self.prog_layers["maximum"] = len(self.li_shp) + len(self.li_tab) self.prog_layers["value"] # Processing the shapefiles self.logger.info('\tStart processing the files') for shp in self.li_shp: """ looping on shapefiles list """ self.logger.info('Processing: %s' % path.basename(shp)) self.status.set(path.basename(shp)) # reset recipient data self.dico_layer.clear() self.dico_fields.clear() # getting separated process threads Read_SHP(shp, self.dico_layer, self.dico_fields, 'shape', self.blabla) # checking layer error if self.dico_layer.get('error'): # increment the progress bar self.prog_layers["value"] = self.prog_layers["value"] + 1 self.update() self.logger.warning('This shape has an issue: %s' % shp) continue # getting fields statistics only if needed if self.def_doc.get() == 1 or self.def_xls.get() == 1 or self.def_odt.get() == 1: StatsFields(shp, self.dico_fields, self.dico_rekur, self.blabla) # export according to options selected if self.def_doc.get() == 1: ExportToHTML(dest, self.dico_layer, self.dico_fields, self.dico_profil, self.dico_rekur, self.blabla) html_path = path.join(dest, "{0}_MD.html".format(self.dico_layer['name'][:-4])) ExportToDocX(html_path, dest) if self.def_xls.get() == 1: ExportToXLS(dest, self.dico_layer, self.dico_fields, self.dico_profil, self.dico_rekur, self.blabla) if self.def_xml.get() == 1: ExportToXML(dest, self.dico_layer, self.dico_profil, '', self.blabla, 1, 0) if self.def_odt.get() == 1: ExportToODT(dest, self.dico_layer, self.dico_fields, self.dico_profil, self.dico_rekur, self.blabla) # increment the progress bar self.prog_layers["value"] = self.prog_layers["value"] + 1 self.update() # Processing the MapInfo tables for tab in self.li_tab: """ looping on MapInfo tables list """ self.logger.info('Processing: %s' % path.basename(tab)) self.status.set(path.basename(tab)) # reset recipient data self.dico_layer.clear() self.dico_fields.clear() # getting the informations Read_TAB(tab, self.dico_layer, self.dico_fields, 'table', self.blabla) # checking layer error if self.dico_layer.get('error'): self.logger.warning('This MapInfo table has an issue: %s' % tab) # increment the progress bar self.prog_layers["value"] = self.prog_layers["value"] +1 self.update() continue # getting fields statistics only if needed if self.def_doc.get() == 1 \ or self.def_xls.get() == 1 \ or self.def_odt.get() == 1: StatsFields(tab, self.dico_fields, self.dico_rekur, self.blabla) # export according to options selected if self.def_doc.get() == 1: ExportToHTML(dest, self.dico_layer, self.dico_fields, self.dico_profil, self.dico_rekur, self.blabla) html_path = path.join(dest, "{0}_MD.html".format(self.dico_layer['name'][:-4])) ExportToDocX(html_path, dest) if self.def_xls.get() == 1: ExportToXLS(dest, self.dico_layer, self.dico_fields, self.dico_profil, self.dico_rekur, self.blabla) if self.def_xml.get() == 1: ExportToXML(dest, self.dico_layer, self.dico_profil, '', self.blabla, 1, 0) if self.def_odt.get() == 1: ExportToODT(dest, self.dico_layer, self.dico_fields, self.dico_profil, self.dico_rekur, self.blabla) # increment the progress bar self.prog_layers["value"] = self.prog_layers["value"] + 1 self.update() # Word catalog export if self.def_doc.get() == 1 and self.def_cat.get() == 1: self.status.set(self.blabla.get('info_cat')) self.update() DocxMerger(dest, '00_Metadator_Catalog', 'metadator_') else: pass # final message # msg = self.blabla.get('info_end2') + self.blabla.get('info_end3') # info(title=self.blabla.get('info_end'), message=msg) # opening the destination folder self.open_dir_file(dest) # cleaning up logging.info('Hurray! It worked! All seem to have been fine!') self.destroy() # end of function return def open_dir_file(self, target): """ Open a file or a directory in the explorer of the operating system http://sametmax.com/ouvrir-un-fichier-avec-le-bon-programme-en-python """ # check if the file or the directory exists if not path.exists(target): raise IOError('No such file: {0}'.format(target)) # check the read permission if not access(target, R_OK): raise IOError('Cannot access file: {0}'.format(target)) # open the directory or the file according to the os if opersys == 'win32': # Windows proc = startfile(target) elif opersys.startswith('linux'): # Linux: proc = subprocess.Popen(['xdg-open', target], stdout=subprocess.PIPE, stderr=subprocess.PIPE) elif opersys == 'darwin': # Mac: proc = subprocess.Popen(['open', '--', target], stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: raise NotImplementedError( "Your `%s` isn't a supported operating system`." % opersys) # end of function return proc
class AbstractProgressScreen(GuiBaseFrame): # Backend logic thread should be making calls to controller.update_frame() to update the UI while logic runs. def __init__(self, parent, controller, backend_logic_function, **kw): GuiBaseFrame.__init__(self, parent, controller, **kw) self.backend_logic_function = backend_logic_function def init_widgets(self): self.content_wrapper = Frame(self) self.content_wrapper.configure(bg="white") self.screen_title = Header1Label(self.content_wrapper) self.empty_space_1 = PLabel(self.content_wrapper) self.progress_bar_control_var = DoubleVar() self.progress_bar = Progressbar(self.content_wrapper, orient=HORIZONTAL, mode="determinate", length=WINDOW_WIDTH / 2, variable=self.progress_bar_control_var) self.wait_text = PLabel(self.content_wrapper) self.information_display = PLabel(self.content_wrapper) self.empty_space_2 = PLabel(self.content_wrapper) self.next_button = Button(self.content_wrapper, text="Next", state=DISABLED, command=lambda: self.on_next_button()) def add_widgets_to_frame(self): self.screen_title.pack() self.empty_space_1.pack() self.progress_bar.pack() self.wait_text.pack() self.information_display.pack() self.empty_space_2.pack() self.next_button.pack() self.content_wrapper.place(relx=SCREENS_REL_X, rely=SCREEN_REL_Y_45, anchor=CENTER) def on_show_frame(self): self.wait_text.configure( text="\nThis might take a few minutes." "\nPlease do not change the video files while this is " "running.\n") self.start_time = time.time() self.backend_logic_thread = threading.Thread( target=self.backend_logic_function, kwargs={"controller": self.controller}) self.backend_logic_thread.start() self.master.after(THREAD_CHECK_ALIVE_INTERVAL_MS, self.check_thread) # Data should be a dictionary with keys "percent_done" and "message_list". def update_frame(self, data): percent_done = data[PROGRESS_SCREEN_PERCENT_DONE] message_list = data[PROGRESS_SCREEN_MESSAGE_LIST] self.progress_bar_control_var.set(percent_done) elapsed_time_seconds = int(time.time() - self.start_time) elapsed_time_message = ELAPSED_TIME_PREFIX + str( datetime.timedelta(seconds=elapsed_time_seconds)) if elapsed_time_seconds == 0: estimated_time_left_string = ESTIMATED_TIME_LEFT_PREFIX + "Calculating..." else: estimated_time_left_seconds = int( elapsed_time_seconds / percent_done * 100.0) - elapsed_time_seconds estimated_time_left_string = ESTIMATED_TIME_LEFT_PREFIX + \ str(datetime.timedelta(seconds=estimated_time_left_seconds)) message_list.append(elapsed_time_message) message_list.append(estimated_time_left_string) self.set_information_display_text(message_list) def on_hide_frame(self): self.progress_bar.stop() def set_title(self, title): self.screen_title.configure(text=title) def set_information_display_text(self, message_list): self.information_display.configure(text=("\n".join(message_list))) def check_thread(self): if self.backend_logic_thread.is_alive(): self.master.after(THREAD_CHECK_ALIVE_INTERVAL_MS, self.check_thread) else: self.progress_bar.stop() self.wait_text.configure(text="\nDone!\nPress Next to continue.\n") self.next_button.configure(state=NORMAL) def on_next_button(self): self.controller.show_next_frame()
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()