def splashscreen(): root = Tk() root.geometry("+200+200") root.overrideredirect(True) root.configure(bg = "white") back = PhotoImage(file = "splashscreen.gif") l1 = Label(root, image = back, bg = "white") scritta = Progressbar(root, orient = "horizontal", mode = "determinate", length = 240) scritta.start(30) copyright = Label(root, text = "Copyright by lokk3d", bg = "white") root.after(3000, root.destroy) l1.pack() scritta.pack(side = "left") copyright.pack( side = "right") root.mainloop()
def gdsConv(u, m): global mode global unit global globIm global im rightFrame.pack_propagate(0) if im == None: for widget in rightFrame.winfo_children(): widget.destroy() l2 = Label(rightFrame, text=' Import Image first! ', relief=RAISED, font='calibri 15 bold', fg='red').pack(padx=140) else: if u == "" or (m not in ('2', '4', '8', '16')) or (not str.isdigit(u)): for widget in rightFrame.winfo_children(): widget.destroy() label = Label(rightFrame, image=globIm) label.image = globIm label.pack(padx=60) l2 = Label(rightFrame, text=' Please select valid unit and mode! ', relief=RAISED, font='calibri 15 bold', fg='red').pack(padx=60, pady=10) else: saveLoc = tkFileDialog.asksaveasfilename() if saveLoc == None or saveLoc == "": for widget in rightFrame.winfo_children(): widget.destroy() label = Label(rightFrame, image=globIm) label.image = globIm label.pack(padx=60) l2 = Label(rightFrame, text=' Select a save location! ', relief=RAISED, font='calibri 15 bold', fg='red').pack(padx=60, pady=10) else: unit = int(u) * 1e-9 mode = int(m) for widget in rightFrame.winfo_children(): widget.destroy() # label = Label(rightFrame,image = globIm) # label.image = globIm # label.pack(padx = 60) ###gdsWriter### name = fileLoc.split('/')[-1].split('.')[0] width, height = im.size cell = core.Cell('GDSII') layout = core.Layout(name, unit) rows = np.arange(height) global imArray imArray = misc.imread(fileLoc, flatten=1) maxVal = np.max(imArray) minVal = np.min(imArray) bins = [] levels = mode for b in range(levels + 1): interval = (maxVal - minVal + 1) / float(levels) bins.append(minVal + b * interval) t = time.time() global mask mask = np.digitize(imArray, bins) ####Shows discritised image### digitized = mask * (256 / (levels)) im = Image.fromarray(digitized.astype('uint8')) width, height = im.size m = max(width, height) if m > 330: scale = 330.0 / m else: scale = 1 globIm = im.resize((int(width * scale), int(height * scale)), Image.ANTIALIAS) globIm = ImageTk.PhotoImage(globIm) label = Label(rightFrame, image=globIm) label.image = globIm label.pack(padx=int((420 - width * scale) / 2)) l2 = Label(rightFrame, text='Conversion in progress...', relief=RAISED, font='calibri 15 bold', fg='blue').pack(padx=60, pady=10) progress_var = DoubleVar(root) progress = Progressbar(rightFrame, orient=HORIZONTAL, variable=progress_var, maximum=100, length=290) progress.pack(padx=20) for row in rows: k = (float(row) / height) * 100 progress_var.set(k) time.sleep(0.001) root.update() r = mask[row] col = 0 while col < width: i = 0 pres = r[col] if r[col + i] == pres and r[col + i] > 1: while r[col + i] == pres: i = i + 1 if col + i > width - 1: break cell.add( core.Path([(col, height - row), (col + i, height - row)], pathtype=0, layer=pres - 1)) col = col + i else: col = col + 1 layout.add(cell) layout.save(saveLoc + '.gds') for widget in rightFrame.winfo_children(): widget.destroy() label = Label(rightFrame, image=globIm) label.image = globIm label.pack(padx=60) l2 = Label(rightFrame, text='Conversion completed.', relief=RAISED, font='calibri 15 bold', fg='blue').pack(padx=60, pady=10) tot = int((time.time() - t)) m = int(tot / 60) s = int(tot % 60) # message = Listbox(rightFrame,font = 'Times 12', width = 360) # message.pack(side = LEFT) # message.insert(END,'Time taken: '+str(m)+' minutes and '+str(s)+' seconds') # message.insert(END,'Image dimensions: width = '+str(width)+' height = '+str(height)) # message.insert(END,'Pixel size used: '+str(unit)) inpSize = os.path.getsize(fileLoc) outSize = os.path.getsize(saveLoc + '.gds') message = Label( rightFrame, text='Conversion time: ' + str(m) + ' minutes and ' + str(s) + ' seconds\n' + 'Image dimensions: width = ' + str(width) + ' height = ' + str(height) + '\n' + 'Pixel size used: ' + str(unit * 1e9) + ' nm\n' + 'Input file size: ' + str(inpSize / 1024) + ' KB Output GDSII file size: ' + str(outSize / 1024) + ' KB', anchor=W, justify=LEFT, font='calibri 11 bold') message.pack(side=LEFT, padx=5)
keepseqs_check = Checkbutton(optionsframe, text="Keep all sequences", variable=kpseqs, onvalue=True, offvalue=False) keeprvals_check = Checkbutton(optionsframe, text="Keep all r-values", variable=kprval, onvalue=True, offvalue=False) keepgdata_check = Checkbutton(optionsframe, text="Keep all graphed data", variable=kpgdata, onvalue=True, offvalue=False) keepseqs_check.grid(column=0, row=1, sticky=(W)) keeprvals_check.grid(column=0, row=2, sticky=(W)) keepgdata_check.grid(column=0, row=3, sticky=(W)) #------------------------------ defaults_bt = Button(mainframe, text="Last Settings", command=setdefault) defaults_bt.grid(column=3, row=1) start_bt = Button(statusframe, text="Start", width=10, command=startall) start_bt.pack(side=LEFT) progress = Progressbar(statusframe, orient=HORIZONTAL, length=450, mode='determinate') progress.pack(side=LEFT) stop_bt = Button(statusframe, text="Stop", width=10, command=stopall) stop_bt.pack(side=LEFT) diag = Text(dialogframe) scroll = Scrollbar(dialogframe) scroll.pack(side=RIGHT, fill=Y) diag.pack(side=LEFT, fill=Y) scroll.config(command=diag.yview) diag.config(yscrollcommand=scroll.set) #------------------------------ rootframe.pack(fill=BOTH) mainframe.pack() dialogframe.pack() statusframe.pack() setdefault()
class ScreenShooterGui(Tk): def __init__(self): Tk.__init__(self) self.title("WebSite ScreenShooter") self.geometry("390x420") self.mainFrame = Frame(self) self.mainFrame.pack(pady=5, padx=5) self.urlLabelFrame = Frame(self.mainFrame) self.urlLabelFrame.pack(pady=5, side=TOP, fill=X) self.urlImportLabel = Label(self.urlLabelFrame, text="web URLs:") self.urlImportLabel.pack(side=LEFT, padx=5) self.importTextFrame = Frame(self.mainFrame) self.importTextFrame.pack(pady=5, side=TOP, fill=X) self.yTextScrollbar = Scrollbar(self.importTextFrame) self.yTextScrollbar.pack(side=RIGHT, fill=Y) self.xTextScrollbar = Scrollbar(self.importTextFrame, orient=HORIZONTAL) self.xTextScrollbar.pack(side=BOTTOM, fill=X) self.importUrlsText = Text(self.importTextFrame, padx=5, pady=5, wrap=NONE, width=50, height=10, yscrollcommand=self.yTextScrollbar.set, xscrollcommand=self.xTextScrollbar.set) self.importUrlsText.pack(side=TOP, padx=5, pady=5, fill=X) self.yTextScrollbar.config(command=self.importUrlsText.yview) self.xTextScrollbar.config(command=self.importUrlsText.xview) self.outputLabelFrame = Frame(self.mainFrame) self.outputLabelFrame.pack(pady=5, side=TOP, fill=X) self.outputFileLabel = Label(self.outputLabelFrame, text="Path to the output folder:") self.outputFileLabel.pack(side=LEFT, padx=5) self.outputFieldFrame = Frame(self.mainFrame) self.outputFieldFrame.pack(pady=5, side=TOP, fill=X) self.outputFieldEntry = Entry(self.outputFieldFrame, name="outputFile", width=30) self.outputFieldEntry.pack(side=LEFT, padx=5) self.btnBrowse = Button(self.outputFieldFrame, height=1, width=6, text="Browse...", command=self.browse) self.btnBrowse.pack(side=RIGHT, padx=5) self.controlsFrame = Frame(self.mainFrame) self.controlsFrame.pack(pady=5, side=TOP, fill=X) self.btnClose = Button(self.controlsFrame, height=1, width=6, text="Close", command=self.close) self.btnClose.pack(side=LEFT, padx=5) self.btnRun = Button(self.controlsFrame, height=1, width=6, text="Run", command=self.run) self.btnRun.pack(side=RIGHT, padx=5) # *** PROGRESS BAR *** self.status = Progressbar(self.mainFrame, orient='horizontal', length=310, mode='determinate', value=0, maximum=100) self.status.pack(pady=5, padx=5, side=BOTTOM) def browse(self): outputPath = tkFileDialog.askdirectory(parent=self) self.outputFieldEntry.delete(0, last=END) self.outputFieldEntry.insert(0, outputPath) def close(self): self.destroy() def run(self): textUrls = self.importUrlsText.get('1.0', 'end') # creating a list ignoring empty values listOfUrls = [x for x in textUrls.split("\n") if x] stepAmount = 100 / len(listOfUrls) for i, url in enumerate(listOfUrls): url = url.strip() # dirty solution to find ebay items ids item_ids = re.findall(r'\/[1-4]\d{11,12}', url, re.I) if len(item_ids) > 0: output = '{root_path}/{url_base}_eBayItem-{item}.png'.format( root_path=self.outputFieldEntry.get(), url_base=url.split("/")[2], item=str(item_ids[0][1:])) else: output = '{root_path}/{url_base}.png'.format( root_path=self.outputFieldEntry.get(), url_base=url.split("/")[2]) # check if file already exists: if os.path.isfile(output): file_ver = '-({ver}).png'.format(ver=i) output = re.sub(r'\.png$', file_ver, output) screenshot(url, output) add_url_time(url, output) self.status.step(stepAmount) self.update() def mainloop(self): Tk.mainloop(self)
class Gui(threading.Thread): """ Gui class contains tkinter gui attributes and logic. When gui closed, is_running flag set to false to end bot actions when possible. Gui remains open until bot thread reaches end of run and sets driver to None. """ def __init__(self): threading.Thread.__init__(self) # Reference to bot object. Allows bi-directional # communication between gui and bot objects self.bot = None # Bot checks this variable to see status self.is_running = True self.secret_key_initialized = False # Integer value of time till next refresh of search results # Value is set after 'do_update()' completes scraping results. # Reduces by 1 every second in gui loop while gui is running. # If gui is no longer running, bot ends gui loop and thread. self.countdown = 0 self.countdown_max = 0 # Setup root self.root = Tk() self.root.geometry("+50+50") self.root.resizable(0, 0) self.root.title("Teams Praise Counter") self.root.after(100, self.change_icon) self.root.attributes('-topmost', True) self.root.protocol('WM_DELETE_WINDOW', self.confirm_quit) # Setup frame self.root.frame = Frame(self.root) self.root.frame.pack(expand=1, side="top", fill="x") self.progress_frame = Frame(self.root) self.progress_frame.pack(expand=1, side="top", fill="x") self.button_frame = Frame(self.root) self.button_frame.pack(expand=1, side="top", fill="x") # Console label self.console_label = Label(self.root.frame, text="Console: ", justify="left", anchor="w") # Console text area self.console_text_frame = Frame(self.root.frame) self.console_text_frame.pack(side="top", expand="yes", fill="x", padx=10, pady=(10, 10)) # Vertical Scroll Bar self.console_y_scroll_bar = Scrollbar(self.console_text_frame) self.console_y_scroll_bar.pack(side="right", fill="y") # Set text area to text widget self.console_text_area = Text( self.console_text_frame, width=80, height=10, yscrollcommand=self.console_y_scroll_bar.set, font=("Helvetica", 7)) self.console_text_area.pack(side="top") # Configure the scrollbars self.console_y_scroll_bar.config(command=self.console_text_area.yview) # Refresh timer progress bar self.progress_bar_style = Style(self.root) self.progress_bar_style.theme_use("default") self.progress_bar = None self.root.after(100, self.load_progress_bar) # Initialize buttons and status label - Settings, Status, Start self.settings_button = Button(self.button_frame, text="Settings", width=28, height=2, command=self.start_stop_bot) self.settings_button.pack(side="left", padx=(10, 5), pady=(10, 10), fill="x", expand=1) self.start_stop_button = Button(self.button_frame, text="Start", width=28, height=2, command=self.start_stop_bot) self.start_stop_button.pack(side="left", padx=(5, 10), pady=(10, 10), fill="x", expand=1) def load_progress_bar(self): """ Load progress bar method used with root.after. If root.after not used, gui will not load. """ self.progress_bar_style.layout("progress_bar", [ ("progress_bar.trough", { "children": [("progress_bar.pbar", { "side": "left", "sticky": "ns" }), ("progress_bar.label", { "sticky": "" })], "sticky": "nswe", }) ]) self.progress_bar = Progressbar(self.progress_frame, orient="horizontal", style="progress_bar") self.progress_bar.pack(expand=1, fill="x", side="left", padx=10, ipadx=3, ipady=3) self.progress_bar["value"] = 0 self.progress_bar_style.configure("progress_bar", background="deepskyblue", font=('Helvetica', 8), pbarrelief="flat", troughrelief="flat", troughcolor="ghostwhite") self.update_progress_label("Press Start to Launch Automation") def update_progress_bar(self, current_time, max_time): """ Update progress bar using current and max time with percentage :param current_time: integer current time till refresh in seconds :param max_time: integer max time till refresh in seconds """ try: self.update_progress_label( "{} seconds until next refresh".format(current_time)) self.progress_bar["value"] = ( (max_time - current_time) / float(max_time)) * 100 except TclError: # Invalid command name "configure" for progress_bar["value"] pass def update_progress_label(self, text): """ Wrapper used to call actual method using root.after :param text: string text used for progress label """ self.root.after(100, lambda: self.update_progress_label_after(text)) def update_progress_label_after(self, text): """ Set progress bar label text. Must be called using root.after :param text: string text used for progress label """ # Spaces added after text to center string on progress bar self.progress_bar_style.configure("progress_bar", text="{} ".format(text)) def change_icon(self): """ Change icon outside of main thread. If after is not used, application will hang when an icon change attempt is made """ self.root.iconbitmap(self.resource_path("icon.ico")) @staticmethod def resource_path(relative_path): """ When EXE generated, icon is bundled. When EXE executed, icon and other resources placed in temp folder. Function identifies whether to use current working directory or temp folder. :param relative_path: string relative path of file name :return: full path name of file including resource directory """ if hasattr(sys, '_MEIPASS'): # noinspection PyProtectedMember return os.path.join(sys._MEIPASS, relative_path) return os.path.join(os.path.abspath("."), relative_path) def start_stop_bot(self): """ Start or stop bot. Runtime error thrown if thread already started. """ try: if self.bot.is_open(): # Not in 'stop_bot()' to allow faster disabling of button self.start_stop_button["text"] = "Stopping ..." self.disable(self.start_stop_button) # After disabling button, driver is closed. After driver # closes successfully, buttons enabled and text changed. self.root.after(10, self.stop_bot) except AttributeError: # Bot object set to none exception self.start_bot() except RuntimeError: # Thread already running exception pass def start_bot(self): """ Method called by start_stop_button to start bot. It creates a new bot instance and sets circular reference in gui and bot objects. After bot has been started, button text changed to Stop. """ self.bot = Bot() self.bot.gui = self self.bot.start() self.start_stop_button["text"] = "Stop" def stop_bot(self): """ Method called by root.after to close driver and change button text from Stopping to Start. Called by root.after to allow root to update while closing. """ try: self.bot.driver.quit() self.bot = None self.enable(self.start_stop_button) self.start_stop_button["text"] = "Start" self.update_progress_label("Automation stopped") except (AttributeError, TclError): # Bot has already been closed pass def start_refresh_countdown(self): self.root.after(100, self.refresh_countdown) def refresh_countdown(self): if self.bot is None: self.update_progress_label("Automation stopped") return if self.countdown > 0: self.countdown = self.countdown - 1 self.root.after( 100, lambda: self.update_progress_bar(self.countdown, self. countdown_max)) self.root.after(1000, self.refresh_countdown) else: self.update_progress_label("Running refresh automation ...") def log(self, text, timestamp=True): """ Add text to gui console log given string parameter. :param text: string text to be added to gui console :param timestamp: boolean is timestamp added to text :return: boolean True if gui is running, otherwise return False. If required in case gui has been closed and bot attempts to add to log. """ if not self.is_running: return False # Add timestamp to beginning of text string if timestamp: text = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S") + " : " + text # Enable text area, add text, move cursor to end, disable text area self.enable(self.console_text_area) self.console_text_area.insert("insert", text) self.console_text_area.see("end") self.disable(self.console_text_area) return True @staticmethod def enable(widget): """ Enables tkinter widget. Primarily used to enable text widgets to allow writing text into widget. :param widget: tkinter widget object """ try: widget.config(state="normal") except tkinter.TclError: # Widget not found exception pass @staticmethod def disable(widget): """ Disable tkinter widget. Primarily used to disable text widgets so user is not allowed to edit text area. :param widget: tkinter widget object """ try: widget.config(state="disabled") except tkinter.TclError: # Widget not found exception pass def confirm_quit(self): """ Handle gui close logic. Sets 'is_running' variable to False. When bot sees gui is no longer running, bot begins closing thread process and driver is set to None. Root is destroyed once bot thread has ended gracefully. """ if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"): self.log("Closing application. Please wait ...") # Update required to show message in console log self.root.update() self.is_running = False try: # Wait for bot driver to close while self.bot.driver is not None: pass except AttributeError: # Bot stopped and set to None pass self.root.destroy() def run(self): """ Gui threading class start thread method. Performed when Threading.start() performed. """ self.root.mainloop()
def gdsConv2(u,m,fLoc,message): global mode global unit rightFrame.pack_propagate(0) if fLoc == None or fLoc == "": m = 'Message: Import Image first! ' message.config(text = m) message.text = m else: imArray = misc.imread(fLoc, flatten= 1) im = Image.open(fLoc) width, height = im.size m2 = max(width,height) if m2 > 330: scale = float(330)/m2 else: scale = 1 im = im.resize((int(width*scale), int(height*scale)), Image.ANTIALIAS) im = ImageTk.PhotoImage(im) if u == "" or (m not in ('2','4','8','16','32','64')) or (not str.isdigit(u)) : m = 'Message: Please select valid unit and levels! ' message.config(text = m) message.text = m else: saveLoc = tkFileDialog.asksaveasfilename() if saveLoc == None or saveLoc == "": m = 'Message: Please select a save location! ' message.config(text = m) message.text = m else: unit = int(u)*1e-9 mode = int(m) #global im for widget in rightFrame.winfo_children(): widget.destroy() label = Label(rightFrame,image = im) label.image = im label.pack(padx = 60) l2 = Label(rightFrame, text = 'Conversion in progress...',relief = RAISED, font = 'calibri 15 bold', fg = 'blue').pack(padx = 60, pady = 10) ###gdsWriter### name = fLoc.split('/')[-1].split('.')[0] cell = core.Cell('GDSII') layout = core.Layout(name,unit) rows = np.arange(height) maxVal = np.max(imArray) minVal = np.min(imArray) bins = [] levels = mode for b in range(levels+1): interval = (maxVal-minVal+1)/float(levels) bins.append(minVal+b*interval) t = time.time() progress_var = DoubleVar(root) progress=Progressbar(rightFrame,orient=HORIZONTAL,variable=progress_var, maximum = 100, length = 290) progress.pack(padx = 20) mask = np.digitize(imArray, bins) for row in rows: k = (float(row)/height)*100 progress_var.set(k) time.sleep(0.001) root.update() r = mask[row] col = 0 while col < width: i = 0 pres = r[col] if r[col + i] == pres and r[col+i] > 1 : while r[col+i] == pres: i = i+1 if col + i > width-1: break cell.add(core.Path([(col,height-row),(col+i,height-row)],pathtype = 0,layer = pres-1)) col = col + i else: col = col + 1 layout.add(cell) layout.save(saveLoc+'.gds') for widget in rightFrame.winfo_children(): widget.destroy() label = Label(rightFrame,image = im) label.image = im label.pack(padx = 60) l2 = Label(rightFrame, text = 'Conversion completed.',relief = RAISED, font = 'calibri 15 bold', fg = 'blue').pack(padx = 60, pady = 10) tot = int((time.time() - t)) m = int(tot/60) s = int(tot%60) inpSize = os.path.getsize(fLoc) outSize = os.path.getsize(saveLoc+'.gds') mess = Label(rightFrame,text = 'Conversion time: '+str(m)+' minutes and '+str(s)+' seconds\n'+'Image dimensions: width = '+str(width)+' height = '+str(height)+'\n'+'Pixel size used: '+str(unit*1e9)+' nm\n'+'Input file size: '+str(inpSize/1024)+' KB Output GDSII file size: '+str(outSize/1024)+' KB', anchor=W, justify=LEFT, font = 'calibri 11 bold') mess.pack(side = LEFT,padx = 5)
class Ui(Frame): # Implementation of Ui class which represents the main frame. def __init__(self, parent): Frame.__init__(self, parent) self.DATABASE = 'pokemon.db' self.engine = search_engine.PokemonSearchEngine() self.search_key = StringVar() self.pokemons = dict() self.pokemon_types = ['All Types'] self.COLOR_CHART = { 'Bug': 'olive drab', 'Dragon': 'tomato', 'Electric': 'gold', 'Fairy': 'HotPink1', 'Fighting': 'orange red', 'Fire': 'dark orange', 'Flying': 'deep sky blue', 'Ghost': 'dark violet', 'Grass': 'yellow green', 'Ground': 'goldenrod', 'Ice': 'cyan', 'Normal': 'gray', 'Poison': 'medium orchid', 'Psychic': 'hot pink', 'Rock': 'saddle brown', 'Steel': 'lightgrey', 'Water': 'steel blue' } self.init_ui() # UI Generator Functions def init_ui(self): frm_options = Frame(self) frm_title = Frame(frm_options, bg='red', highlightbackground="black", highlightthickness=2) frm_fetch = Frame(frm_options, bg='red', highlightbackground="black", highlightthickness=2) frm_search = Frame(frm_options, bg='red', highlightbackground="black", highlightthickness=2) frm_filter = Frame(frm_search, bg='red') frm_filter_label = Frame(frm_filter, bg='red') frm_results = Frame(frm_options, bg='red', highlightbackground="black", highlightthickness=2) frm_pokemon = Frame(frm_results, bg='red') Label(frm_title, text='POKEDEX', bg='red', fg='white', font='Calibri 20 bold')\ .pack(fill=X) Button(frm_fetch, text='Fetch Pokemon\nData', bg='yellow', command=self.btn_fetchdata_onclick).pack(side=LEFT, padx=5, pady=20) self.progress = Progressbar(frm_fetch, orient="horizontal", length=200, mode="determinate") self.progress.pack(fill=X, padx=15, pady=30, expand=True) self.lbl_progress = Label(self.progress, text='') self.lbl_progress.pack(pady=5) Label(frm_search, text='Search&Filtering', bg='red', font='Calibri 15 bold')\ .pack() Entry(frm_search, textvariable=self.search_key, width=40)\ .pack(fill=X, padx=15, pady=15) Label(frm_filter_label, text='Filter By Type', bg='red', font='Calibri 12')\ .pack(side=LEFT, padx=5) frm_filter_label.pack(side=TOP, fill=X) self.cb_filter_type = Combobox(frm_filter) self.cb_filter_type.pack(side=LEFT, fill=X, padx=5, pady=5, expand=True) Button(frm_filter, text='SEARCH', bg='yellow', command=self.btn_search_onclick).pack(side=RIGHT, fill=X, padx=10) self.lbl_result = Label(frm_results, text='Total Number Of Results', bg='red', font='Calibri 13 bold') self.lbl_result.pack() self.lb_pokemons = Listbox(frm_pokemon) self.lb_pokemons.pack(side=LEFT, padx=20, pady=10) Button(frm_pokemon, text='Get Pokemon\nData', bg='yellow', command=self.btn_getpokemon_onclick).pack(side=RIGHT, padx=10) frm_options.pack(side=LEFT, fill=BOTH, expand=True) frm_title.pack(fill=X) frm_fetch.pack(fill=X) frm_search.pack(fill=X) frm_filter.pack(fill=X) frm_results.pack(fill=X) frm_pokemon.pack(fill=X) self.pack(fill=BOTH, expand=True) def pack_pokemon_detail(self, pokemon): self.frm_detail = Frame(self, bg='red', highlightbackground="black", highlightthickness=2) Label(self.frm_detail, text=pokemon.name, bg='red', font='Calibri 18 bold').pack() Label(self.frm_detail, text=pokemon.id, bg='red', font='Calibri 13 bold').pack() cnvs_img = Canvas(self.frm_detail, bg='red') urllib.urlretrieve(pokemon.img, '1.png') cnvs_img.pack(fill=Y) Img = Image.open('1.png') Img = Img.resize((400, 250)) self.c = ImageTk.PhotoImage(Img) cnvs_img.create_image(0, 0, anchor=NW, image=self.c) for type in pokemon.type: Label(self.frm_detail, text=type, bg=self.COLOR_CHART[type], width=20, font='Calibri 10 bold').pack() Label(self.frm_detail, text='Height: ' + pokemon.height, bg='red', font='Calibri 10 bold').pack() Label(self.frm_detail, text='Weight: ' + pokemon.weight, bg='red', font='Calibri 10 bold').pack() Label(self.frm_detail, text='Category: ' + pokemon.category, bg='red', font='Calibri 10 bold').pack() Label(self.frm_detail, text='Ability: ' + pokemon.ability, bg='red', font='Calibri 10 bold').pack() Label(self.frm_detail, text='Weakness: ' + ', '.join(pokemon.weakness), bg='red', font='Calibri 10 bold').pack() self.frm_detail.pack(side=RIGHT, fill=BOTH) # GUI Element's Events def btn_fetchdata_onclick(self): try: self.read_from_db(self.DATABASE, self.pokemons) except anydbm.error: for pokemon in self.load_data('all_pokemon.txt'): self.pokemons[pokemon] = self.engine.search(pokemon) self.progress['value'] += 0.70 self.progress.update() self.create_database(self.DATABASE, self.pokemons) finally: self.lbl_progress['text'] = 'FINISHED' self.get_pokemon_types() def btn_search_onclick(self): if self.cb_filter_type.get() == 'All Types': source = self.filter_pokemon(self.search_key.get()) else: source = self.filter_pokemon_by_type(self.search_key.get().lower(), self.cb_filter_type.get()) self.lbl_result['text'] = 'Total: ' + str(len(source)) + ' Result' self.clear_and_insert_to_listbox(self.lb_pokemons, source) def btn_getpokemon_onclick(self): try: self.frm_detail.pack_forget() except: print 'All Calculated, No Problem' finally: self.pack_pokemon_detail( self.pokemons[self.lb_pokemons.get(ACTIVE)]) # Utilities def filter_pokemon_by_type(self, query_string, type): results = [] for pokemon_name, pokemon_object in self.pokemons.items(): if query_string in pokemon_name.lower( ) and type in pokemon_object.type: results.append(pokemon_name) return sorted(results) def filter_pokemon(self, query_string): results = [] for pokemon_name, pokemon_object in self.pokemons.items(): if query_string in pokemon_name: results.append(pokemon_name) return sorted(results) def get_pokemon_types(self): for pokemon, pokemon_object in self.pokemons.items(): for type in pokemon_object.type: if type not in self.pokemon_types: self.pokemon_types.append(type) self.cb_filter_type['values'] = sorted(self.pokemon_types) self.cb_filter_type.current(0) @staticmethod def clear_and_insert_to_listbox(listbox, source): listbox.delete(0, END) for item in source: listbox.insert(END, item) @staticmethod def load_data(filename): data = [] with open(filename, 'r') as file: for line in file: data.append(line.replace('\n', '')) return data @staticmethod def create_database(filename, datas): db = anydbm.open(filename, 'c') for key, value in datas.items(): db[key] = pickle.dumps(value) @staticmethod def read_from_db(filename, source): db = anydbm.open(filename, 'r') for pokemon in db: source[pokemon] = pickle.loads(db[pokemon])
class FdaAltimeterControl(tk.Toplevel): PORT_SELECTION_FRAME_HEIGHT = 80 SUB_FRAME_X_PADDING = 20 def __init__(self, parent): tk.Toplevel.__init__(self) self.parent = parent # Do not let user to close this window # is a communication with the Altimeter # is taking place. self.communicating = False self.protocol("WM_DELETE_WINDOW", self.close_asked) # Setup window content. self.initialize() def initialize(self): self.title(_(u'FlyDream Altimeter - Device Controller')) # Set fixed size. self.minsize(640, 320) self.resizable(False, False) # Altimeter local device. frame = tk.Frame(self, height=self.PORT_SELECTION_FRAME_HEIGHT) frame.pack(fill=tk.BOTH, expand=tk.YES) tk.Label(frame, text=_(u'Altimeter plugged on:')).pack(side=tk.LEFT) self.detect = tk.Button(frame, text=_(u'Refresh'), command=self.refresh_serial_ports) self.detect.pack(side=tk.RIGHT) self.port = tk.StringVar(self) self.ports = tk.OptionMenu(frame, self.port, _(u'Detecting serial ports...')) self.ports.pack(fill=tk.X, expand=tk.YES) # Update possible serial ports. self.refresh_serial_ports() # Upload altimeter flight data. frame = tk.Frame(self, padx=self.SUB_FRAME_X_PADDING) frame.pack(fill=tk.BOTH, expand=tk.YES) label = tk.Label(frame, anchor=tk.W, text=_(u'Upload')) label.pack(side=tk.TOP, fill=tk.X) # Setup bold font for titles. f = Font(font=label['font']) f['weight'] = 'bold' label['font'] = f.name Separator(frame).pack(fill=tk.X) self.progressbar = Progressbar(frame, orient='horizontal', mode='determinate') self.progressbar.pack(side=tk.BOTTOM, fill=tk.X) # Do not show progressbar # unless data is uploaded. self.hide_progressbar() self.upload_info = tk.StringVar() self.upload_info.set('/') self.info_label = tk.Label(frame, anchor=tk.NE, fg='darkgrey', textvariable=self.upload_info) self.info_label.pack(side=tk.BOTTOM, fill=tk.BOTH) self.label = tk.Label(frame, anchor=tk.W, text=_(u'Tell the altimeter to send flight ' 'data to your computer')) self.label.pack(side=tk.LEFT) self.upload = tk.Button(frame, text=_(u'Upload data'), command=self.upload) self.upload.pack(side=tk.RIGHT) # Erase altimeter flight data. frame = tk.Frame(self, padx=self.SUB_FRAME_X_PADDING) frame.pack(fill=tk.BOTH, expand=tk.YES) label = tk.Label(frame, anchor=tk.W, text=_(u'Clear')) label['font'] = f.name label.pack(side=tk.TOP, fill=tk.X) Separator(frame).pack(fill=tk.X) label = tk.Label(frame, anchor=tk.W, text=_(u'Delete all the flight data from your altimeter')) label.pack(side=tk.LEFT) self.erase = tk.Button(frame, text=_(u'Erase data'), command=self.erase) self.erase.pack(side=tk.RIGHT) # Setup altimeter sampling frequency. frame = tk.Frame(self, padx=self.SUB_FRAME_X_PADDING) frame.pack(fill=tk.BOTH, expand=tk.YES) label = tk.Label(frame, anchor=tk.W, text=_(u'Configure')) label['font'] = f.name label.pack(side=tk.TOP, fill=tk.X) Separator(frame).pack(fill=tk.X) self.frequency = tk.StringVar(self) self.frequency.set('1') self.frequencies = tk.OptionMenu(frame, self.frequency, '1', '2', '4', '8') self.frequencies.pack(side=tk.LEFT) label = tk.Label(frame, text=_(u'records per second')) label.pack(side=tk.LEFT) self.setup = tk.Button(frame, text=_(u'Set sampling frequency'), command=self.set_frequency) self.setup.pack(side=tk.RIGHT) def allow_user_interactions(self, allow=True): state = tk.NORMAL if allow else tk.DISABLED self.ports.configure(state=state) self.detect.configure(state=state) self.upload.configure(state=state) self.erase.configure(state=state) self.frequencies.configure(state=state) self.setup.configure(state=state) def close_asked(self): if not self.communicating: self.destroy() return else: showwarning(_(u'Warning'), _(u"""The application is communicating with the altimeter. Please wait until communication is finished before closing this window.""")) def hide_progressbar(self): self.progressbar.prev_pack = self.progressbar.pack_info() self.progressbar.pack_forget() self.update() # Reset progressbar for next upload. self.progressbar['value'] = 0 def show_progressbar(self): # Well, Tkinter pack does not seem to # make it easy to simply hide a widget... # # I may be missing something. prev_info_label_packinfo = self.info_label.pack_info() prev_label_packinfo = self.label.pack_info() prev_upload_packinfo = self.upload.pack_info() self.info_label.pack_forget() self.label.pack_forget() self.upload.pack_forget() self.progressbar.pack(self.progressbar.prev_pack) self.info_label.pack(prev_info_label_packinfo) self.label.pack(prev_label_packinfo) self.upload.pack(prev_upload_packinfo) self.update() def upload_progressed(self, read, total): self.progressbar['maximum'] = total self.progressbar['value'] = read info = _(u'Please wait, %d bytes read out of %d') % (read, total) self.upload_info.set(info) self.update() def default_filename(self): return time.strftime('%Y-%m-%d %H-%M-%S', time.localtime()) \ + '_flight' def upload(self): # TODO Add please wait message. # Update window state. self.show_progressbar() self.allow_user_interactions(False) self.communicating = True # Get flight data. port = self.port.get() altimeter = Altimeter(port) try: raw_data = altimeter.upload(self.upload_progressed) except FlyDreamAltimeterSerialPortError: self.show_unfound_altimeter(port) except (FlyDreamAltimeterReadError, FlyDreamAltimeterWriteError) as e: self.show_readwrite_error(port, e.message) except FlyDreamAltimeterProtocolError as e: self.show_protocol_error(port, e.message) else: # Check received data. if len(raw_data.data) == 0: showinfo(_(u'Upload Data'), _(u'Altimeter contains no data.')) else: filename = self.write_flight_data(raw_data) self.suggest_open_in_viewer(filename) finally: # Restore window state. self.communicating = False self.allow_user_interactions() self.hide_progressbar() # TODO Update altimeter information. self.upload_info.set(_(u'Done')) def write_flight_data(self, raw_data): # Let user choose a file name. # # When cancelled, None is returned. fname = asksaveasfilename( filetypes=((_(u'Flydream Altimeter Data'), '*.fda'), (_(u'All files'), '*.*')), title=_(u'Save flight data...'), initialdir='~', initialfile=self.default_filename(), defaultextension=RAW_FILE_EXTENSION) if fname: # Try to remove previous file. # # User has been warned by asksaveasfilename # if she picked an existing file name. try: os.remove(fname) except OSError as e: # errno.ENOENT is 'no such file or directory'. # # Raise if another kind of error occurred. if e.errno != errno.ENOENT: raise # This method raises an exception if file already exists. raw_data.to_file(fname) return fname def suggest_open_in_viewer(self, filename): # User may want to see latest uploaded data. if filename: reply = askokcancel(_(u'Open in viewer'), _(u'Open saved flight data in file viewer?')) if reply: self.parent.load_file(filename) def erase(self): reply = askokcancel(_(u'Erase flight data'), _(u'Really erase all flight data in your altimeter?')) if reply: self.do_erase() def do_erase(self): # TODO Make message stay while erasing is performed. showwarning(_(u'Erasing...'), _(u'Do not disconnect USB until altimeter blue LED ' 'lights again.')) # Update window state. self.allow_user_interactions(False) self.communicating = True # Reset altimeter content. port = self.port.get() altimeter = Altimeter(port) try: altimeter.clear() except FlyDreamAltimeterSerialPortError: self.show_unfound_altimeter(port) except (FlyDreamAltimeterReadError, FlyDreamAltimeterWriteError) as e: self.show_readwrite_error(port, e.message) except FlyDreamAltimeterProtocolError as e: self.show_protocol_error(port, e.message) else: # Update altimeter information. self.upload_info.set(_(u'Altimeter content erased')) finally: # Restore window state. self.communicating = False self.allow_user_interactions() def set_frequency(self): # This request is almost immediate, # so let's not bother user with yet # another message box. # Update window state. self.allow_user_interactions(False) self.communicating = True # Change altimeter sampling frequency. freq = int(self.frequency.get()) port = self.port.get() altimeter = Altimeter(port) try: altimeter.setup(freq) except FlyDreamAltimeterSerialPortError: self.show_unfound_altimeter(port) except (FlyDreamAltimeterReadError, FlyDreamAltimeterWriteError) as e: self.show_readwrite_error(port, e.message) except FlyDreamAltimeterProtocolError as e: self.show_protocol_error(port, e.message) else: # Update altimeter information. self.upload_info.set(_(u'Altimeter sampling frequency set')) finally: # Restore window state. self.communicating = False self.allow_user_interactions() def show_unfound_altimeter(self, port): showwarning(_(u'Sampling Frequency'), _(u"""Can not open port: %s Please ensure that: - your altimeter is plugged to the USB adapter. - the USB adapter is plugged to your computer. - the choosen port is correct. - the USB adapter driver is properly installed on your computer, see http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx""") % port) def show_readwrite_error(self, port, message): showwarning(_(u'Read/Write error'), _(u"""With device on: %s Internal error message: %s Please ensure that: - the choosen port is correct. - your altimeter is plugged to the USB adapter. - the USB adapter is plugged to your computer. - you did not unplugged the altimeter while it was communicating.""") % (port, message)) def show_protocol_error(self, port, message): showwarning(_(u'Protocol error'), _(u"""With device on: %s Internal error message: %s Please ensure that: - your altimeter is plugged to the USB adapter. - you did not unplugged the altimeter while it was communicating.""") % (port, message)) def refresh_serial_ports(self): # Build port list. port_list = self.detect_serial_ports() # Remove previous items in combobox. menu = self.ports['menu'] menu.delete(0, tk.END) # Add new items in combobox. self.port.set(port_list[0]) for pr in port_list: menu.add_command(label=pr, command=lambda p=pr: self.port.set(p)) def detect_serial_ports(self): # Try to detect system serial devices. port_list = [] try: # Convert to filenames. port_list = [info[0].replace('cu', 'tty') for info in list_ports.comports()] except Exception as e: showwarning(_(u'Serial Ports Detection'), _(u'Error while detecting serial ports: %s') % e.message) # Insert default port as first entry. default = Altimeter().port try: # Try to remove default one to prevent duplication. port_list.remove(default) except ValueError: pass port_list.insert(0, default) return port_list
# Create a window the_window = Tk() # Give the window a title the_window.title('Pump me up!') # Function to execute when the button is pressed def advance(): the_bar.step(step_size) # Create a button widget whose parent container is the # window the_button = Button(the_window, text='Push', command=advance) # Create a progress bar widget in the parent window (making the # maximum value displayable 101% because the bar's value # returns to zero when 100 is reached, i.e., it displays values # from 0 to 99, inclusive, by default) the_bar = Progressbar(the_window, orient=VERTICAL, maximum=101) # Call the geometry manager to "pack" the widgets onto # the window (with a blank margin around the widgets) margin_size = 5 the_button.pack(padx=margin_size, pady=margin_size) the_bar.pack(pady=margin_size) # Start the event loop to react to user inputs the_window.mainloop()
class DicoGIS(Tk): def __init__(self): u""" Main window constructor Creates 1 frame and 2 labelled subframes """ # basics settings Tk.__init__(self) # constructor of parent graphic class self.title(u'DicoGIS {0}'.format(DGversion)) self.li_raster_formats = ['ecw', 'geotiff'] # notebook self.nb = Notebook(self) self.FrProg = Labelframe(self, name='progression', text='gui_prog') self.FrOutp = Labelframe(self, name='output', text='gui_fr4') # tabs self.tab_files = Frame(self.nb) # tab_id = 0 self.tab_sgbd = Frame(self.nb) # tab_id = 1 self.tab_webservices = Frame(self.nb) # tab_id = 2 self.tab_isogeo = Frame(self.nb) # tab_id = 3 self.tab_about = Frame(self.nb) # tab_id = 4 ## TAB 1: FILES self.nb.add(self.tab_files, text='gui_files', padding=3) # frame: path folder self.FrPath = Labelframe(self.tab_files, name='files', text='gui_fr1') self.labtarg = Label(self.FrPath, text='gui_path') self.target = Entry(master=self.FrPath, width=35) self.browsetarg = Button(self.FrPath, # browse button text='gui_choix', command=lambda: self.setpathtarg(), takefocus=True) self.browsetarg.focus_force() # force the focus on # widgets placement self.labtarg.grid(row=1, column=1, columnspan=1, sticky="NSWE", padx=2, pady=2) self.target.grid(row=1, column=2, columnspan=1, sticky="NSWE", padx=2, pady=2) self.browsetarg.grid(row=1, column=3, sticky="NSWE", padx=2, pady=2) # frame: filters self.FrFilters = Labelframe(self.tab_files, name='filters', text='filters') # formats options self.opt_shp = IntVar(self.FrFilters) # able/disable shapefiles self.opt_tab = IntVar(self.FrFilters) # able/disable MapInfo tables self.opt_kml = IntVar(self.FrFilters) # able/disable KML self.opt_gml = IntVar(self.FrFilters) # able/disable GML self.opt_geoj = IntVar(self.FrFilters) # able/disable GeoJSON self.opt_gxt = IntVar(self.FrFilters) # able/disable GXT self.opt_egdb = IntVar(self.FrFilters) # able/disable Esri FileGDB self.opt_spadb = IntVar(self.FrFilters) # able/disable Spatalite DB self.opt_rast = IntVar(self.FrFilters) # able/disable rasters self.opt_cdao = IntVar(self.FrFilters) # able/disable CAO/DAO files self.opt_pdf = IntVar(self.FrFilters) # able/disable Geospatial PDF self.opt_lyr = IntVar(self.FrFilters) # able/disable Geospatial Lyr self.opt_mxd = IntVar(self.FrFilters) # able/disable Geospatial MXD self.opt_qgs = IntVar(self.FrFilters) # able/disable Geospatial QGS # format choosen: check buttons caz_shp = Checkbutton(self.FrFilters, text=u'.shp', variable=self.opt_shp) caz_tab = Checkbutton(self.FrFilters, text=u'.tab', variable=self.opt_tab) caz_kml = Checkbutton(self.FrFilters, text=u'.kml', variable=self.opt_kml) caz_gml = Checkbutton(self.FrFilters, text=u'.gml', variable=self.opt_gml) caz_geoj = Checkbutton(self.FrFilters, text=u'.geojson', variable=self.opt_geoj) caz_gxt = Checkbutton(self.FrFilters, text=u'.gxt', variable=self.opt_gxt) caz_egdb = Checkbutton(self.FrFilters, text=u'Esri FileGDB', variable=self.opt_egdb) caz_spadb = Checkbutton(self.FrFilters, text=u'Spatialite', variable=self.opt_spadb) caz_rast = Checkbutton(self.FrFilters, text=u'rasters ({0})'.format(', '.join(self.li_raster_formats)), variable=self.opt_rast) caz_cdao = Checkbutton(self.FrFilters, text=u'CAO/DAO', variable=self.opt_cdao) caz_pdf = Checkbutton(self.FrFilters, text=u'Geospatial PDF', variable=self.opt_pdf) caz_lyr = Checkbutton(self.FrFilters, text=u'.lyr', variable=self.opt_lyr) caz_mxd = Checkbutton(self.FrFilters, text=u'.mxd', variable=self.opt_mxd) caz_qgs = Checkbutton(self.FrFilters, text=u'.qgs', variable=self.opt_qgs) # widgets placement caz_shp.grid(row=1, column=0, sticky="NSWE", padx=2, pady=2) caz_tab.grid(row=1, column=1, sticky="NSWE", padx=2, pady=2) caz_kml.grid(row=1, column=2, sticky="NSWE", padx=2, pady=2) caz_gml.grid(row=1, column=3, sticky="NSWE", padx=2, pady=2) caz_geoj.grid(row=1, column=4, sticky="NSWE", padx=2, pady=2) caz_gxt.grid(row=1, column=7, sticky="NSWE", padx=2, pady=2) caz_pdf.grid(row=1, column=5, columnspan=2, sticky="NSWE", padx=2, pady=2) caz_rast.grid(row=2, column=0, columnspan=2, sticky="NSWE", padx=2, pady=2) caz_egdb.grid(row=2, column=2, columnspan=2, sticky="NSWE", padx=2, pady=2) caz_cdao.grid(row=2, column=4, columnspan=1, sticky="NSWE", padx=2, pady=2) caz_spadb.grid(row=2, column=5, columnspan=2, sticky="NSWE", padx=2, pady=2) caz_lyr.grid(row=3, column=0, columnspan=2, sticky="NSWE", padx=2, pady=2) caz_mxd.grid(row=3, column=1, columnspan=2, sticky="NSWE", padx=2, pady=2) caz_qgs.grid(row=3, column=2, columnspan=2, sticky="NSWE", padx=2, pady=2) # frames placement self.FrPath.grid(row=3, column=1, padx=2, pady=2, sticky="NSWE") self.FrFilters.grid(row=4, column=1, padx=2, pady=2, sticky="NSWE") # tab 2: database self.nb.add(self.tab_sgbd, text='gui_database', padding=3) # tab 3: webservices self.nb.add(self.tab_webservices, text='gui_webservices', padding=3) ## TAB 4: ISOGEO self.nb.add(self.tab_isogeo, text='gui_Isogeo', padding=3) ## TAB 5: ABOUT self.nb.add(self.tab_about, text='gui_about', padding=3) ## MAIN FRAME # Welcome message self.welcome = Label(self, text='hola test', foreground="red2") # Progression bar self.status = StringVar(self.FrProg, '') # widgets self.prog_layers = Progressbar(self.FrProg, orient="horizontal") Label(master=self.FrProg, textvariable=self.status, foreground='DodgerBlue').pack() # widgets placement self.prog_layers.pack(expand=1, fill='both') # Output configuration # widgets self.nameoutput = Label(self.FrOutp, text='gui_fic') self.output = Entry(self.FrOutp, width=35) # widgets placement self.nameoutput.grid(row=0, column=1, sticky="NSWE", padx=2, pady=2) self.output.grid(row=0, column=2, columnspan=2, sticky="NSWE", padx=2, pady=2) # Image self.icone = PhotoImage(file=r'../data/img/DicoGIS_logo.gif') Label(self, borderwidth=2, image=self.icone).grid(row=1, rowspan=4, column=0, padx=2, pady=2, sticky=W) # credits s = Style(self) s.configure('Kim.TButton', foreground='DodgerBlue', borderwidth=0) Button(self, text='by @GeoJulien\nGPL3 - 2015', style='Kim.TButton', command=lambda: open_new('https://github.com/Guts/DicoGIS')).grid(row=4, padx=2, pady=2, sticky="WE") # language switcher self.ddl_lang = Combobox(self, values=['fr', 'en'], width=5) # grid placement self.val = Button(self, text='gui_go', state=ACTIVE, command=lambda: self.process()) self.can = Button(self, text='gui_quit', command=lambda: self.destroy()) self.welcome.grid(row=1, column=1, columnspan=1, sticky="NS", padx=2, pady=2) self.ddl_lang.grid(row=1, column=1, sticky="NSE", padx=2, pady=2) self.nb.grid(row=2, column=1) self.FrProg.grid(row=3, column=1, sticky="NSWE", padx=2, pady=2) self.FrOutp.grid(row=4, column=1, sticky="NSWE", padx=2, pady=2) self.val.grid(row=5, column=1, columnspan=2, sticky="NSWE", padx=2, pady=2) self.can.grid(row=5, column=0, sticky="NSWE", padx=2, pady=2)
class Page(Frame): def __init__(self, parent, index=0): Frame.__init__(self, parent, height=530, relief=RAISED, borderwidth=1) self.parent = parent if index == 0: self.loadScriptPage() elif index == 1: self.scriptProcessPage() elif index == 2: self.sonifyProcessPage() elif index == 3: self.finishedPage() else: print "No Page here!" def loadScriptPage(self): # Button States self.parent.prevButton.config(state='disabled') if self.parent.scriptname != '': self.parent.nextButton.config(state='normal') explain = Label(self, text=txt.selectscript, justify=CENTER, font=root.fontH1) explain.pack(pady=50) self.loadedscript = Label(self, text=self.parent.scriptname, justify=CENTER, font=root.fontH1) self.loadedscript.pack() loadscriptBtn = Button(self, text="Load Script", command=self.getScript) loadscriptBtn.pack(pady=10) def scriptProcessPage(self): self.parent.prevButton.config(state='normal') self.parent.nextButton.config(state='normal') explain = Label(self, text="Character Selection", justify=CENTER, font=root.fontH1) explain.grid(row=0, columnspan=3, pady=20) # Instance Script self.parent.Script = ScreenPlay(normpath(self.parent.scriptpath)) actorNames = self.parent.Script.topcharacters self.actorActive = [] self.actorGender = [] for i in range(6): Label(self, text=actorNames[i], width=20).grid(row=i+1, padx=10, pady=8) participateFrame = Frame(self ,relief=RAISED, borderwidth=1) participateFrame.grid(row=i+1,column=1, padx=10, ipady=2, ipadx=5) participate = BooleanVar() self.actorActive.append(participate) self.actorActive[i].set(True) Radiobutton(participateFrame, text="ON", variable=self.actorActive[i], value=True, command=self.updateVars).pack(side=LEFT) Radiobutton(participateFrame, text="OFF", variable=self.actorActive[i], value=False, command=self.updateVars).pack(side=LEFT) genderFrame = Frame(self, relief=RAISED, borderwidth=1) genderFrame.grid(row=i+1,column=2, padx=30, ipady=2) gender = StringVar() self.actorGender.append(gender) self.actorGender[i].set('F') Label(genderFrame, text="Gender:").pack(side=LEFT, padx=10) Radiobutton(genderFrame, text="Female", variable=self.actorGender[i], value='F', command=self.updateVars).pack(side=LEFT, padx=5) Radiobutton(genderFrame, text="Male", variable=self.actorGender[i], value='M', command=self.updateVars).pack(side=LEFT, padx=5) Label(self, text="______________________", justify=CENTER, state='disabled').grid(row=8, columnspan=3, pady=10) Label(self, text="Sonification Settings", justify=CENTER, font=root.fontH1).grid(row=9, columnspan=3, pady=10) sonificationFrame = Frame(self) sonificationFrame.grid(row=10, columnspan=3) Label(sonificationFrame, text="Tone Length", width=22).grid(row=0, column=0) self.tonelen = Combobox(sonificationFrame, state='readonly', values=['1/1','1/2','1/4', '1/8']) self.tonelen.bind("<<ComboboxSelected>>", self.updateCombobox) self.tonelen.current(1) self.tonelen.grid(row=0, column=1, padx=10, pady=5) Label(sonificationFrame, text="Sonification BPM", width=22).grid(row=1, column=0) self.bpm = Combobox(sonificationFrame, state='readonly', values=[100, 120, 140, 160, 180, 200, 220, 240, 260]) self.bpm.bind("<<ComboboxSelected>>", self.updateCombobox) self.bpm.current(4) self.bpm.grid(row=1, column=1, padx=10, pady=5) Label(sonificationFrame, text="Dialogue Length per Tone", justify=LEFT).grid(row=2, column=0) self.dpt = Combobox(sonificationFrame, state='readonly', values=[1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000]) self.dpt.bind("<<ComboboxSelected>>", self.updateCombobox) self.dpt.current(4) self.dpt.grid(row=2, column=1, padx=10, pady=5) self.submitSettings() def submitSettings(self): actorSelections = [] sonifySettings = [] for i in range(6): selected = self.actorActive[i].get() gender = self.actorGender[i].get() actorSelections.append( [selected , gender ] ) sonifySettings.append(self.tonelen.get()) sonifySettings.append(self.bpm.get()) sonifySettings.append(self.dpt.get()) self.parent.actorSelections = actorSelections self.parent.sonifySettings = sonifySettings # print actorSelections # print sonifySettings def finishedPage(self): Label(self, text="Sonification Complete!", justify=CENTER, font=root.fontH1).pack(pady=200) def sonifyProcessPage(self): Label(self, text="Processing", justify=CENTER, font=root.fontH1).pack(pady=20) self.processing = Label(self, text="", justify=CENTER) self.processing.pack(pady=20) self.pbar = Progressbar(self, orient='horizontal', mode='indeterminate') self.pbar.start(10) self.pbar.pack() self.after(100, self.sonifyProcess) def sonifyProcess(self): # Create Output Directory path = dirname(normpath(self.parent.scriptpath)) self.outdir = join(path, 'output_' + str(self.parent.movietitle)) self.tempdir = join(self.outdir, 'temp') self.tempdir = join(self.tempdir, '') if not isdir(self.tempdir): makedirs(self.tempdir) notelen = self.parent.sonifySettings[0] notelen = int( notelen[-1:] ) bpm = int( self.parent.sonifySettings[1] ) cutoff = int( self.parent.sonifySettings[2] ) # Create dictionary based on settings self.parent.Script.createSceneDictionary(cutoff=cutoff) sceneAmount = len(self.parent.Script.scenedictionary) for index, character in enumerate(self.parent.Script.topcharacters): selected = self.parent.actorSelections[index][0] gender = self.parent.actorSelections[index][1] if selected: charSong = Sonification(character, gender, index) for scene in range(sceneAmount-1): if character in self.parent.Script.sceneComposition(scene): textamount = self.parent.Script.sceneComposition(scene)[character] participation = ( float(textamount) / float(cutoff) ) * 100 else: participation = None self.processing.config(text= 'Creating Audio for ' + character.title()) self.update() charSong.songBrick(participation, length=notelen) charSong.make_song(self.update, bpm=bpm, path=self.tempdir) self.mergeAudiotracks() def mergeAudiotracks(self): self.processing.config(text='Creating Multichannel Audiofile\nThis can take a while!') self.update() outfile = join(self.outdir, 'output.wav') filearray = [] for index, character in enumerate(self.parent.Script.topcharacters): filename = character.lower() + str(index) + '.wav' filearray.append( join(self.tempdir, filename) ) amix.mix_audiofiles(filearray, outfile, self.update) self.parent.nextPage() def getScript(self): scriptpath = askopenfilename(parent=self.parent, filetypes=[('Fountain Script File','.fountain')], title='Select Script') self.parent.scriptpath = scriptpath self.parent.scriptname = basename(self.parent.scriptpath) self.parent.movietitle = splitext(self.parent.scriptname)[0] self.loadedscript.config(text=self.parent.scriptname) self.parent.nextButton.config(state='normal') def updateVars(self): self.submitSettings() def updateCombobox(self, event): self.submitSettings()
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
b5 = Button(row5, width=13, text='Choose Folder', command=lambda root=root: ask_folder()) b5.pack(side=LEFT, padx=3, pady=3) ## Progress Bar progress_var = DoubleVar() cmsgvar = StringVar() cmsgvar.set('Completed 0/0') row8 = Frame(root) row8.pack(side=TOP, fill=X, padx=3, pady=3) lab6 = Label(row8, width=14, text='Progress', anchor='w') lab6.pack(side=LEFT) progressbar = Progressbar(row8, variable=progress_var, length=245, maximum=100) progressbar.pack(side=LEFT, fill=X) lab7 = Label(row8, width=14, textvariable=cmsgvar, anchor='w') lab7.pack(side=RIGHT, fill=X) ## Buttons row6 = Frame(root) row6.pack(side=TOP, fill=X, padx=7, pady=15) b9 = Button(row6, text='Generate + Email', width=15, state='disabled', command=lambda root=root: button_trigger(2)) b9.pack(side=RIGHT, padx=3, pady=3) b6 = Button(row6, text='Generate All', width=15,
class YoutubeScript: def __init__(self): self.totDownloadSize = 0 self.completedSize = 0 self.saveData = { "url": "", "title": "", "selected": [], "completed": [], "savetype": "" } def initUi(self): self.ipGui = Tk() self.ipGui.wm_title("YtD by T90") self.ipGui.wm_minsize(700, 150) self.titleFrame = Frame(self.ipGui, height=100, width=500, relief=RAISED, bg="#555") self.titleFrame.pack(fill=BOTH) titleLabel = Label(self.titleFrame, text="Youtube Downloader Script", bg="#555", fg="#fff", font=("Arial", 16)) subTitleLabel = Label(self.titleFrame, text="By T90", bg="#555", fg="#ddd") titleLabel.pack(fill=X, side=TOP, pady=3) subTitleLabel.pack(fill=X, side=BOTTOM) self.ipFrame = Frame(self.ipGui, height=200, width=500, relief=RAISED, bg="#bbb") self.ipFrame.pack(fill=BOTH, padx=3, pady=3) self.urlBox = Entry(self.ipFrame, relief=RAISED, fg="#777") self.urlBox.focus() self.urlBtn = Button(self.ipFrame, text="Download", height=2, bg="#777", fg="#eee", command=self.startDownload) self.urlBox.pack(fill=BOTH, padx=20, pady=10) self.urlBtn.pack(fill=BOTH, padx=50, pady=10) # self.urlBox.insert(0, "https://www.youtube.com/playlist?list=PLYvPGplh5--N1zwtg_5-z3kVW9U92FUc2") self.selectVidsFrame = Frame(self.ipGui, bg="#bbb") selectLabel = Label(self.selectVidsFrame, text="Select videos to be downloaded and click on Start.", bg="#bbb") self.vidsListBox = Listbox(self.selectVidsFrame, bg="#bbb", relief=RAISED, selectmode=EXTENDED, selectbackground="#888", selectforeground="#fff", borderwidth=1, highlightthickness=0, activestyle="none") self.selectVidsBtn = Button(self.selectVidsFrame, text="Start", height=2, bg="#777", fg="#eee", command=self.selectVids) selectLabel.pack(fill=X, padx=3, pady=3) self.vidsListBox.pack(fill=X, padx=10, pady=10) self.selectVidsBtn.pack(fill=X, padx=50, pady=10) self.progFrame = Frame(self.ipGui, height=200, width=500, relief=SUNKEN, bg="#bbb") self.titleInProgFrame = Frame(self.progFrame, bg="#bbb") self.status1InProgFrame = Frame(self.progFrame, bg="#bbb") self.status2InProgFrame = Frame(self.progFrame, bg="#bbb") self.progInProgFrame = Frame(self.progFrame, bg="#bbb") self.vidTitleLabel = Label(self.titleInProgFrame, text="Fetching videos, please wait...", bg="#bbb", fg="#333") self.thisVidCompletedTitle = Label(self.status1InProgFrame, text="Completed:", bg="#bbb", fg="#333", justify="right") self.thisVidCompletedText = Label(self.status1InProgFrame, text="0 MB", bg="#bbb", fg="#333", justify="left") self.thisVidSizeTitle = Label(self.status1InProgFrame, text="Size:", bg="#bbb", fg="#333", justify="right") self.thisVidSizeText = Label(self.status1InProgFrame, text="calculating", bg="#bbb", fg="#333", justify="left") self.totVidCompletedTitle = Label(self.status1InProgFrame, text="Total downloaded:", bg="#bbb", fg="#333", justify="right") self.totVidCompletedText = Label(self.status1InProgFrame, text="0 MB", bg="#bbb", fg="#333", justify="left") self.totVidSizeTitle = Label(self.status1InProgFrame, text="Total Size:", bg="#bbb", fg="#333", justify="right") self.totVidSizeText = Label(self.status1InProgFrame, text="calculating", bg="#bbb", fg="#333", justify="left") self.curSpeedTitle = Label(self.status2InProgFrame, text="Speed:", bg="#bbb", fg="#333", justify="right") self.curSpeedText = Label(self.status2InProgFrame, text="0 mbps", bg="#bbb", fg="#333", justify="left") self.vidLengthTitle = Label(self.status2InProgFrame, text="Video duration:", bg="#bbb", fg="#333", justify="right") self.vidLengthText = Label(self.status2InProgFrame, text="calculating", bg="#bbb", fg="#333", justify="left") self.etaTitle = Label(self.status2InProgFrame, text="ETA:", bg="#bbb", fg="#333", justify="right") self.etaText = Label(self.status2InProgFrame, text="calculating", bg="#bbb", fg="#333", justify="left") self.timeTakenTitle = Label(self.status2InProgFrame, text="Time Taken:", bg="#bbb", fg="#333", justify="right") self.timeTakenText = Label(self.status2InProgFrame, text="calculating", bg="#bbb", fg="#333", justify="left") self.totProgLabel = Label(self.progInProgFrame, text="Total Progress", bg="#bbb", fg="#333") s = Style() s.theme_use('alt') s.configure("grey.Horizontal.TProgressbar", foreground='#eee', background='#888') self.indiProg = Progressbar(self.progInProgFrame, style="grey.Horizontal.TProgressbar", orient='horizontal', mode='determinate', maximum=100) self.totProg = Progressbar(self.progInProgFrame, style="grey.Horizontal.TProgressbar", orient='horizontal', mode='determinate', maximum=100) self.openDownloadFolderBtn = Button(self.progInProgFrame, text="Open Download Location", height=2, bg="#777", fg="#eee", command=self.openDownloadFolder) self.titleInProgFrame.pack(fill=BOTH, expand=1) self.status1InProgFrame.pack(fill=BOTH, expand=1) self.status2InProgFrame.pack(fill=BOTH, expand=1) self.progInProgFrame.pack(fill=BOTH, expand=1) self.vidTitleLabel.pack(fill=BOTH, expand=1, padx=50, pady=10, side=TOP) self.thisVidCompletedTitle.pack(fill=BOTH, expand=1, side=LEFT) self.thisVidCompletedText.pack(fill=BOTH, expand=1, side=LEFT) self.thisVidSizeTitle.pack(fill=BOTH, expand=1, side=LEFT) self.thisVidSizeText.pack(fill=BOTH, expand=1, side=LEFT) self.totVidCompletedTitle.pack(fill=BOTH, expand=1, side=LEFT) self.totVidCompletedText.pack(fill=BOTH, expand=1, side=LEFT) self.totVidSizeTitle.pack(fill=BOTH, expand=1, side=LEFT) self.totVidSizeText.pack(fill=BOTH, expand=1, side=LEFT) self.curSpeedTitle.pack(fill=BOTH, expand=1, side=LEFT) self.curSpeedText.pack(fill=BOTH, expand=1, side=LEFT) self.vidLengthTitle.pack(fill=BOTH, expand=1, side=LEFT) self.vidLengthText.pack(fill=BOTH, expand=1, side=LEFT) self.etaTitle.pack(fill=BOTH, expand=1, side=LEFT) self.etaText.pack(fill=BOTH, expand=1, side=LEFT) self.timeTakenTitle.pack(fill=BOTH, expand=1, side=LEFT) self.timeTakenText.pack(fill=BOTH, expand=1, side=LEFT) self.indiProg.pack(fill=BOTH, expand=1, padx=50, pady=10) self.totProgLabel.pack(fill=BOTH, expand=1) self.totProg.pack(fill=BOTH, expand=1, padx=50, pady=10) self.openDownloadFolderBtn.pack(fill=BOTH, expand=1, padx=90, pady=10) def saveData(self, status="auto"): self.saveData['url'] = self.url self.saveData['title'] = self.pafy['title'] self.saveData['savetype'] = status self.saveData['selected'] = self.selectedIndexList self.saveData['completed'] = self.completedVids pickle.dump(self.saveData, "saves/saveFile_" + str(int(time.time()))) def getUrlandStart(self): try: urllib.urlretrieve("http://youtube.com/favicon.ico", "favicon.ico") self.initUi() self.ipGui.iconbitmap(r'favicon.ico') self.ipGui.mainloop() except Exception as e: print e.message root = Tk() root.withdraw() tkMessageBox.showerror("Connectivity Issues", "Connectivity issue detected. " "Please make sure that you are connected to the Internet and then restart the app.") exit(0) def startDownload(self): if not os.path.exists("downloads"): os.mkdir("downloads") self.urlBtn.config(text="Loading...") self.ipGui.update() self.url = self.urlBox.get() if "watch" in self.url and "list" in self.url: parts = self.url.split("&") for part in parts: if "list=" in part: self.url = "https://www.youtube.com/playlist?" + part break self.ipFrame.pack_forget() if "playlist" in self.url: self.selectVidsFrame.pack(fill=BOTH, padx=3, pady=3) self.vidsListBox.focus() self.pafy = pafy.get_playlist(self.url) self.ipGui.wm_title(self.pafy['title']) self.vidsObjs = [] i = 0 for vid in self.pafy['items']: self.vidsObjs.append(vid) i += 1 self.vidsListBox.insert(END, str(i) + ". " + vid['playlist_meta']['title'] + " [" + str( round(int(vid['playlist_meta']['length_seconds']) / 60, 2)) + "min]") def selectVids(self): items = self.vidsListBox.curselection() self.selectedIndexList = items if len(items) == 0: tkMessageBox.showerror("No video selected", "No videos selected.\nPlease select some videos and press start. " "Select multiple videos using Shift/Ctrl.") return self.selectedList = [] for item in items: self.selectedList.append(self.vidsObjs[item]) self.selectVidsFrame.pack_forget() self.progFrame.pack(fill=BOTH, padx=3, pady=3) self.selectVidsBtn.config(text="Fetching videos, please wait...") self.ipGui.update() self.downloadPlaylist() def downloadPlaylist(self): self.startTime = time.time() self.completedVids = [] if not os.path.exists("downloads/playlists"): os.mkdir("downloads/playlists") safePlaylistTitle = self.winStringFormat(self.pafy['title']) if not os.path.exists("downloads/playlists/" + safePlaylistTitle): os.mkdir("downloads/playlists/" + safePlaylistTitle) self.dwnldgVidNum = -1 for vid in self.selectedList: self.totDownloadSize += vid['pafy'].getbest().get_filesize() self.totProgLabel.config( text="Total Progress") for vid in self.selectedList: self.dwnldgVidNum += 1 best = vid['pafy'].getbest() index = self.vidsObjs.index(vid) safeTitle = self.winStringFormat(vid['pafy'].title + "." + best.extension) self.vidDuration = vid['pafy'].duration self.vidTitleLabel.config(text=vid['pafy'].title) best.download(quiet=True, filepath="downloads/playlists/" + safePlaylistTitle + "/" + str( index + 1) + ". " + safeTitle, callback=self.updateProg) self.totProgLabel.config( text="Completed " + str(self.dwnldgVidNum) + " of " + str(len(self.selectedList)) + " videos.") self.completedSize += best.get_filesize() self.completedVids.append(index) tkMessageBox.showinfo("Completed", "Successfully completed download.") self.openDownloadFolder() def updateProg(self, total, recvd, ratio, rate, eta): self.timeNw = time.time() timeDiff = self.timeNw - self.startTime timeTxt = "" if (timeDiff / 3600) > 1: timeTxt += str(int(timeDiff / 3600)) + " : " timeDiff %= 3600 if (timeDiff / 60) > 1: timeTxt += str(int(timeDiff / 60)) + " : " timeDiff %= 60 timeTxt += str(int(timeDiff)) self.thisVidCompletedText.config(text=str(round((recvd / 1024) / 1024, 2)) + " MB") self.thisVidSizeText.config(text=str(round(((total / 1024) / 1024), 2)) + " MB") self.totVidCompletedText.config(text=str(round((((self.completedSize + recvd) / 1024) / 1024), 2)) + " MB") self.totVidSizeText.config(text=str(round(((self.totDownloadSize / 1024) / 1024), 2)) + " MB") self.curSpeedText.config(text=str(round(rate / 1024, 2)) + " mbps") self.vidLengthText.config(text=self.vidDuration) self.etaText.config(text=str(round(eta, 1)) + " secs") self.timeTakenText.config(text=timeTxt) # statusText = "This video: " + str(round((recvd / 1024) / 1024, 2)) + " MB/" + str( # round(((total / 1024) / 1024), 2)) + " MB\tTotal: " + str( # round((((self.completedSize + recvd) / 1024) / 1024), 2)) + " MB/" + str(round(((self.totDownloadSize / 1024) / 1024), 2)) + " MB" # self.indiStat.config(text=statusText) # statusText = "Ratio: " + str(round(rate / 1024, 2)) + " mbps\t\tETA: " + str(round(eta, 1)) + " secs" # self.indiProgLabel.config(text=statusText) self.indiProg.config(value=ratio * 100) self.totProg.config(value=( (float(self.dwnldgVidNum) / len(self.selectedList)) * 100 + ((ratio * 100) / len(self.selectedList)))) self.ipGui.update() def winStringFormat(self, name): return name.replace("|", " ").replace(":", " ").replace("/", " ").replace("\\", " ").replace("$", " ").replace( "#", " ").replace("@", " ").replace(";", " ").replace("\"", " ").replace("'", " ").replace("?", " ") def openDownloadFolder(self): safePlaylistTitle = self.winStringFormat(self.pafy['title']) os.system('explorer.exe "' + os.path.dirname( os.path.abspath(__file__)) + '\\downloads\\playlists\\' + safePlaylistTitle + '"')
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 FindServer(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.selected = ""; self.controller = controller label = Label(self, text="Select server", font=TITLE_FONT, justify=CENTER, anchor=CENTER) label.pack(side="top", fill="x", pady=10) self.button1 = Button(self, text="Next",state="disabled", command=self.callback_choose) button2 = Button(self, text="Refresh", command=self.callback_refresh) button3 = Button(self, text="Back", command=self.callback_start) scrollbar = Scrollbar(self) self.mylist = Listbox(self, width=100, yscrollcommand = scrollbar.set ) self.mylist.bind("<Double-Button-1>", self.twoClick) self.button1.pack() button2.pack() button3.pack() # create list with a scroolbar scrollbar.pack( side = "right", fill="y" ) self.mylist.pack( side = "top", fill = "x", ipadx=20, ipady=20, padx=20, pady=20 ) scrollbar.config( command = self.mylist.yview ) # create a progress bar label2 = Label(self, text="Refresh progress bar", justify='center', anchor='center') label2.pack(side="top", fill="x") self.bar_lenght = 200 self.pb = Progressbar(self, length=self.bar_lenght, mode='determinate') self.pb.pack(side="top", anchor='center', ipadx=20, ipady=20, padx=10, pady=10) self.pb.config(value=0) # to select he server user must double-click on it def twoClick(self, event): widget = event.widget selection=widget.curselection() value = widget.get(selection[0]) self.selected = value self.button1.config(state="normal") # save the selected server in a global variable SELECTED_SERV = SERVER_LIST[selection[0]] set_globvar(SELECTED_SERV) # listen for broadcasts from port 8192 def listen_broadcasts(self, port, timeout): # Set the progress bar to 0 self.pb.config(value=0) step_size = ((self.bar_lenght/(MAX_NR_OF_SERVERS+1))/2) list_of_servers = [] # Initialize the listener s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.bind(('', port)) s.settimeout(LISTENING_TIMEOUT) # Listen for a number of times to get multiple servers for _ in range(MAX_NR_OF_SERVERS + 1): # Update the progress bar self.pb.step(step_size) self.pb.update_idletasks() try: message, address = s.recvfrom(8192) m_split = message.split(';') if m_split[0] == '\HELLO': server_id = (m_split[1], address) # Check if the server has not yet broadcasted itself. if server_id not in list_of_servers: list_of_servers.append(server_id) except: pass # Close the socket s.close() if not list_of_servers: # If no server found, pop a warning message. tkMessageBox.showwarning("Find Servers", "No servers found. Refresh or create a new game.") # Set the progress bar back to 0 self.pb.config(value=0) # Return the whole list of available servers return list_of_servers # service the refresh button def callback_refresh(self): global SERVER_LIST self.mylist.delete(0,END) SERVER_LIST = self.listen_broadcasts(BROADCASTING_PORT, LISTENING_TIMEOUT) for server_el in SERVER_LIST: self.mylist.insert(END,(" "+str(server_el[0])+" IP: "+str(server_el[1])+" Time: "+str(time.asctime()))) def callback_choose(self): self.mylist.delete(0,END) self.button1.config(state="disabled") self.controller.show_frame("ChooseType") def callback_start(self): self.mylist.delete(0,END) self.button1.config(state="disabled") self.controller.show_frame("StartPage")
class AudioJackGUI(object): def __init__(self, master): self.root = master self.searching = False self.can_download = True audiojack.set_useragent('AudioJack', '1.0') self.frame = ScrollableFrame(self.root) self.frame.setconfig(bg='#0D47A1', width=1280, height=720) self.frame.pack(side=TOP, fill=BOTH, expand=1) self.label = Label(self.frame.mainframe, text='AudioJack', fg='#ffffff', bg=self.frame.mainframe['background'], font=('Segoe UI', 48)) self.label.pack() self.url_entry = Entry(self.frame.mainframe, width=48, font=('Segoe UI', 20), bg='#1565C0', bd=2, highlightthickness=1, highlightcolor='#1565C0', highlightbackground='#0D47A1', fg='#ffffff', insertbackground='#ffffff', relief=FLAT, insertwidth=1) self.url_entry.pack() self.submit_button = Button(self.frame.mainframe, width=60, font=('Segoe UI', 16), text='Go!', bd=0, bg='#1E88E5', fg='#ffffff', activebackground='#2196F3', activeforeground='#ffffff', relief=SUNKEN, cursor='hand2', command=self.submit) self.submit_button.pack() self.search_progress = Progressbar(self.frame.mainframe, orient='horizontal', length=720, maximum=100 ,mode='indeterminate') self.error_info = Label(self.frame.mainframe, fg='#ff0000', bg=self.frame.mainframe['background']) # Use pack_forget on this to reset the view self.contents = Frame(self.frame.mainframe, bg=self.frame.mainframe['background']) # Contains results and custom tag options self.select_frame = Frame(self.contents, bg=self.frame.mainframe['background']) self.select_frame.pack() #Search results self.results_label = Label(self.select_frame, text='Results:', fg='#ffffff', bg=self.frame.mainframe['background']) self.results_frame = Frame(self.select_frame, bg=self.frame.mainframe['background']) self.results_label.pack() self.results_frame.pack() # Downloads self.file_label = Label(self.contents, fg='#ffffff', bg=self.frame.mainframe['background']) def submit(self): self.searching = True self.error_info.pack_forget() self.error_info.config(text='') self.contents.pack_forget() self.reset_results_frame() self.file_label.config(text='') self.results_queue = Queue.Queue() t = Thread(target=self.search) t.daemon = True t.start() self.submit_button.pack_forget() self.search_progress.pack() self.search_progress.start(10) self.root.after(100, self.handle_results) def search(self): url = self.url_entry.get() try: self.results_queue.put(audiojack.get_results(url)) except Exception as e: self.results_queue.put([]) def handle_results(self): try: results = self.results_queue.get(0) self.reset_results_frame() self.search_progress.pack_forget() self.submit_button.pack() if results == []: self.error_info.config(text='No results found.') self.error_info.pack() else: for i, entry in enumerate(results): self.get_result_box(entry).grid(row=i / 4, column=i % 4) self.contents.pack() self.select_frame.pack() except Queue.Empty: self.root.after(100, self.handle_results) def reset_results_frame(self): for result in self.results_frame.winfo_children(): result.destroy() def get_result_box(self, entry): try: text ='%s\n%s\n%s' % (entry['title'], entry['artist'], entry['album']) raw_image = Image.open(BytesIO(entry['img'].decode('base64'))) side = self.frame.mainframe.winfo_reqwidth() / 4 image_data = raw_image.resize((side, side), Image.ANTIALIAS) image = ImageTk.PhotoImage(image=image_data) frame = Frame(self.results_frame) button = Button(frame, fg='#ffffff', text=text, image=image, compound=CENTER, bg=self.frame.mainframe['background'], command=lambda: self.select(entry)) button.image = image button.pack(fill=BOTH, expand=1) return frame except Exception as e: print e print type(e) def select(self, entry): if self.can_download: self.can_download = False self.searching = False self.download_queue = Queue.Queue() t = Thread(target=lambda: self.get_select(entry)) t.daemon = True t.start() self.root.after(100, self.handle_download) def get_select(self, entry): try: self.download_queue.put(audiojack.select(entry)) except Exception: self.download_queue.put('') def handle_download(self): try: file = self.download_queue.get(0) self.can_download = True if not self.searching: label_text = 'Downloaded %s' % file self.select_frame.pack_forget() self.file_label.config(text=label_text) self.file_label.pack() self.contents.pack() except Queue.Empty: self.root.after(100, self.handle_download)
def createWidgets(self): first_row = Progressbar(self) first_row.pack(side=TOP)
class InstallationFrame(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.parent.title("FLE - KA Lite Setup - Start installation") self.loadImages() self.configureLayout() self.drawLayout() def loadImages(self): """Loads the images. The size must be the exact size of the image.""" self.kaliteleaf_photo = PhotoImage(file="images/kaliteleaf.gif", width=16, height=16) def configureLayout(self): self.top_frame = Frame(self, relief=RAISED, borderwidth=1) self.tip_label_text = StringVar() self.tip_label = Label(self.top_frame, textvariable=self.tip_label_text) self.tip_label_text.set("Install KA Lite") self.kaliteleaf_label = Label(self.top_frame, image=self.kaliteleaf_photo, width=16, height=16) self.kaliteleaf_label.image = self.kaliteleaf_photo self.info_label_text = StringVar() self.info_label_frame = Frame(self) self.info_label = Label(self.info_label_frame, textvariable=self.info_label_text) self.info_label_text.set("Ready to start...") self.progress_bar_frame = Frame(self) self.progress_bar_value = IntVar() self.progress_bar = Progressbar(self.progress_bar_frame, mode="indeterminate", variable=self.progress_bar_value, length=400) self.bottom_space_frame = Frame(self) self.install_button_frame = Frame(self) self.install_button = Button(self.install_button_frame, text="Install", command=self.startInstallation, width=15, height=2) self.quit_button = Button(self.install_button_frame, text="Quit", state=DISABLED, command=quitInstaller, width=15, height=2) def drawLayout(self): self.pack(fill=BOTH, expand=True) self.top_frame.pack(fill=X) self.tip_label.pack(fill=X, side=LEFT, padx=5, pady=5) self.kaliteleaf_label.pack(fill=X, side=RIGHT, padx=5, pady=5) self.info_label_frame.pack(fill=X) self.info_label.pack(fill=X, expand=True, padx=10, pady=10) self.progress_bar_frame.pack(fill=X) self.progress_bar.pack(fill=X, expand=True, padx=15, pady=15) self.bottom_space_frame.pack(fill=BOTH, expand=True) self.quit_button.pack(fill=X, side=RIGHT) self.install_button_frame.pack(fill=X, padx=5, pady=5) self.install_button.pack(fill=X, side=RIGHT, padx=5) def startInstallation(self): global TARGET_PATH if not TARGET_PATH: return src = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ka-lite") self.progress_bar.start(10) self.number_of_files = 0 t1 = FuncThread(self.startInstall, src, self.progress_bar, self.number_of_files, self.progress_bar_value, self.tip_label_text, self.info_label_text, self.install_button, self.quit_button) t1.start() def startInstall(self, src, progress_bar, number_of_files, progress_bar_value, tip_label_text, info_label_text, install_button, quit_button): install_button.config(state=DISABLED) tip_label_text.set("Preparing to install KA Lite...") info_label_text.set("Calculating the number of files to copy...") files = [] if os.path.isdir(src): for path, dirs, filenames, in os.walk(src): files.extend(filenames) number_of_files = len(files) progress_bar.stop() progress_bar.config(maximum=number_of_files, mode="determinate", length=400) progress_bar_value.set(0) count = 0 tip_label_text.set("Installing...") info_label_text.set(str(count)+" of "+str(number_of_files)+" copied.") list = [] for path, dirs, filenames in os.walk(src): list.append((path, dirs, filenames)) if not os.path.exists(TARGET_PATH): os.makedirs(TARGET_PATH) for t in list: for directory in t[1]: destDir = t[0].replace(src,TARGET_PATH) if not os.path.exists(os.path.join(destDir, directory)): os.makedirs(os.path.join(destDir, directory)) for sfile in t[2]: srcFile = os.path.join(t[0], sfile) destFile = os.path.join(t[0].replace(src, TARGET_PATH), sfile) shutil.copy(srcFile, destFile) count+=1 info_label_text.set(str(count)+" of "+str(number_of_files)+" copied.") progress_bar_value.set(count) quit_button.config(state=NORMAL) tip_label_text.set("Installation complete.") info_label_text.set("All files were sucessfuly copied.") return
class AudioJackGUI(object): def __init__(self, master): self.root = master self.searching = False self.can_download = True audiojack.set_useragent('AudioJack', '1.0') self.frame = ScrollableFrame(self.root) self.frame.setconfig(bg='#0D47A1', width=1280, height=720) self.frame.pack(side=TOP, fill=BOTH, expand=1) self.label = Label(self.frame.mainframe, text='AudioJack', fg='#ffffff', bg=self.frame.mainframe['background'], font=('Segoe UI', 48)) self.label.pack() self.url_entry = Entry(self.frame.mainframe, width=48, font=('Segoe UI', 20), bg='#1565C0', bd=2, highlightthickness=1, highlightcolor='#1565C0', highlightbackground='#0D47A1', fg='#ffffff', insertbackground='#ffffff', relief=FLAT, insertwidth=1) self.url_entry.pack() self.submit_button = Button(self.frame.mainframe, width=60, font=('Segoe UI', 16), text='Go!', bd=0, bg='#1E88E5', fg='#ffffff', activebackground='#2196F3', activeforeground='#ffffff', relief=SUNKEN, cursor='hand2', command=self.submit) self.submit_button.pack() self.search_progress = Progressbar(self.frame.mainframe, orient='horizontal', length=720, maximum=100, mode='indeterminate') self.error_info = Label(self.frame.mainframe, fg='#ff0000', bg=self.frame.mainframe['background']) # Use pack_forget on this to reset the view self.contents = Frame(self.frame.mainframe, bg=self.frame.mainframe['background']) # Contains results and custom tag options self.select_frame = Frame(self.contents, bg=self.frame.mainframe['background']) self.select_frame.pack() # Search results self.results_queue = Queue.Queue() self.results_label = Label(self.select_frame, text='Results:', fg='#ffffff', bg=self.frame.mainframe['background']) self.results_frame = Frame(self.select_frame, bg=self.frame.mainframe['background']) self.results_label.pack() self.results_frame.pack() # Downloads self.file_label = Label(self.contents, fg='#ffffff', bg=self.frame.mainframe['background']) def submit(self): self.searching = True self.error_info.pack_forget() self.error_info.config(text='') self.contents.pack_forget() self.reset_results_frame() self.file_label.config(text='') t = Thread(target=self.search) t.daemon = True t.start() self.submit_button.pack_forget() self.search_progress.pack() self.search_progress.start(10) self.handle_results() def search(self): url = self.url_entry.get() error = [-1] try: self.results_queue.put(audiojack.get_results(url)) except DownloadError as e: if 'not a valid url' in e.message.lower(): error.append('Invalid URL.') else: error.append('Unknown DownloadError.') self.results_queue.put(error) except NetworkError: error.append('Error when retrieving metadata.') self.results_queue.put(error) except ExtractorError: error.append('Unknown ExtractorError.') self.results_queue.put(error) def handle_results(self): try: results = self.results_queue.get(0) self.reset_results_frame() self.search_progress.pack_forget() self.submit_button.pack() if len(results) == 2 and results[0] == -1: self.error_info.config(text=results[1]) self.error_info.pack() else: for i, entry in enumerate(results): self.get_result_box(entry).grid(row=i / 4, column=i % 4) self.contents.pack() self.select_frame.pack() except Queue.Empty: self.root.after(100, self.handle_results) def reset_results_frame(self): for result in self.results_frame.winfo_children(): result.destroy() def get_result_box(self, entry): try: text = '%s\n%s\n%s' % (entry['title'], entry['artist'], entry['album']) raw_image = Image.open(BytesIO(entry['img'].decode('base64'))) side = self.frame.mainframe.winfo_reqwidth() / 4 image_data = raw_image.resize((side, side), Image.ANTIALIAS) image = ImageTk.PhotoImage(image=image_data) frame = Frame(self.results_frame) canvas = Canvas(frame, height=side, width=side, cursor='hand2', bd=0, highlightthickness=0) canvas.create_image((0, 0), image=image, anchor=NW) canvas.image = image canvas.text = None canvas.pack(fill=BOTH, expand=1) canvas.bind('<Enter>', lambda e: self.enter_results_box(canvas, text)) canvas.bind('<Leave>', lambda e: self.leave_results_box(canvas)) canvas.bind('<Button-1>', lambda e: self.select(entry)) return frame except Exception as e: print e print type(e) def enter_results_box(self, canvas, text): canvas.text = canvas.create_text( (canvas.winfo_width() / 2, canvas.winfo_height() / 2), text=text, justify=CENTER, fill='white', font=('Segoe UI', 14)) def leave_results_box(self, canvas): canvas.delete(canvas.text) def select(self, entry): if self.can_download: self.can_download = False self.searching = False self.download_queue = Queue.Queue() t = Thread(target=lambda: self.get_select(entry)) t.daemon = True t.start() self.handle_download() def get_select(self, entry): try: self.download_queue.put(audiojack.select(entry)) except Exception: self.download_queue.put('') def handle_download(self): try: file = self.download_queue.get(0) self.can_download = True if not self.searching: label_text = 'Downloaded %s' % file self.select_frame.pack_forget() self.file_label.config(text=label_text) self.file_label.pack() self.contents.pack() except Queue.Empty: self.root.after(10, self.handle_download)