class InfoList: def __init__(self, baseFrame, selectEvent, dataFormat, initialInfo=[], width=30, height=5): self.infoData = initialInfo self.dataFormat = dataFormat self.infoList = Listbox( baseFrame, width=width, height=height, listvariable=StringVar(value=[ele[0] for ele in self.infoData])) self.infoList.bind('<<ListboxSelect>>', selectEvent) self.infoList.grid(row=0, column=0) self.scrollbar = Scrollbar(baseFrame, orient=VERTICAL, command=self.infoList.yview) self.scrollbar.grid(row=0, column=1, sticky=(N, S)) self.infoList['yscrollcommand'] = self.scrollbar.set self.updateInfo(self.infoData) def updateInfo(self, infoData=[]): self.infoList.delete(0, len(self.infoData) - 1) self.infoData = infoData for iinfo, info in enumerate(self.infoData): info[0] = iinfo self.infoList.insert(iinfo, self.dataFormat(info)) for i in range(0, len(self.infoData), 2): self.infoList.itemconfigure(i, background='#f0f0ff') def report(self): idxs = self.infoList.curselection() if len(idxs) == 1: return self.infoData[idxs[0]] return []
class Ms: def __init__(self): self.win = Tk() self.win.title('Account Statement') self.win.geometry("500x250") self.win.config(bg="purple") self.win.iconbitmap('atm.ico') self.win.resizable(0, 0) # declare frame and scrollbar self.my_frame = Frame(self.win, bg="violet") self.my_scrollbar = Scrollbar(self.my_frame, orient=VERTICAL) # declraing Listbox self.list_box = Listbox(self.my_frame, width=100, yscrollcommand=self.my_scrollbar.set, bg="black", fg="white") #config scroll bar self.my_scrollbar.config(command=self.list_box.yview) self.my_scrollbar.pack(side=RIGHT, fill=Y) self.my_frame.pack(pady=15) self.list_box.pack(pady=15) def get_mini(self, user): # adding items in Listbox with open(f"{user}.txt") as file: mylist = file.readlines() for item in mylist: self.list_box.insert(END, item) self.list_box.itemconfigure(END, selectbackground="violet", selectforeground="black", activestyle=None) file.close()
def second_window(root, info): def next_step(): idxs = lbox.curselection() for blogger in idxs: name = bloggers()[blogger] if name not in info['bloggers']: info['bloggers'].append(name) if 'Blogs' in info['platforms']: blog_posts(root, info) else: third_window(root, info) def cantfind(info=info): idxs = lbox.curselection() for blogger in idxs: name = bloggers()[blogger] if name not in info['bloggers']: info['bloggers'].append(name) add_blogger(info=info) def active_next(*args): send.state(['!disabled', 'active']) def back(): idxs = lbox.curselection() for blogger in idxs: name = bloggers()[blogger] if name not in info['bloggers']: info['bloggers'].append(name) first_window(root, info=info) c = ttk.Frame(root, padding=(5, 0, 0, 0)) c.grid(column=0, row=0, sticky=(N, W, E, S)) background_image = tkinter.PhotoImage(file='%s/Desktop/natappy/images/moon.gif' % home) background_label = tkinter.Label(c, image=background_image) background_label.image = background_image background_label.place(x=0, y=0, relwidth=1, relheight=1) root.grid_columnconfigure(0, weight=3) root.grid_rowconfigure(0, weight=3) lbox = Listbox(c, selectmode=MULTIPLE) lbox.grid(column=0, row=1, rowspan=11, columnspan=7, sticky=( N, W, S), padx=(10, 10), pady=(1, 1), ipadx=75) yscroll = ttk.Scrollbar(command=lbox.yview, orient=VERTICAL) yscroll.grid(row=0, column=0, padx=(0, 10), sticky=(N, W, S)) lbox.configure(yscrollcommand=yscroll.set) for blogger in bloggers(): lbox.insert(END, blogger) lbox.bind("<<ListboxSelect>>") lbox.yview_scroll(40, 'units') cantfind = ttk.Button(c, text='Add new bloggers', command=cantfind) cantfind.grid(column=4, row=1, padx=(10, 0), sticky=(N, S, E, W), pady=(20, 10)) send = ttk.Button(c, text='Next', command=next_step, default='active', state='disabled') send.grid(column=6, row=11, sticky=E, pady=20, padx=(2, 20)) close = ttk.Button(c, text='Back', command=back, default='active') close.grid(column=5, row=11, sticky=S + E, pady=20, padx=2) lbox.bind('<<ListboxSelect>>', active_next) if info['bloggers']: for blogger in info['bloggers']: i = bloggers().index(blogger) lbox.selection_set(i) active_next() for i in range(len(bloggers()), 2): lbox.itemconfigure(i, background='#f0f0ff') c.grid_columnconfigure(0, weight=1) c.grid_rowconfigure(5, weight=1) root.title('2/5 Select bloggers') root.geometry('680x550+300+40')
class DMselector(ttk.Frame): """Listbox for DM Creation, Selection, and Sorting.""" def __init__(self, master, conflict): """Initialize DM selection/creation Widget.""" ttk.Frame.__init__(self, master) self.conflict = conflict self.dms = conflict.decisionMakers # variables self.listVariable = StringVar( value=tuple(['Double Click to Add Item'])) self.selIdx = None self.selectedDM = None # widgets self.label = ttk.Label(self, text="Decision Makers") self.dmListDisp = Listbox(self, listvariable=self.listVariable) self.scrollY = ttk.Scrollbar(self, orient=VERTICAL, command=self.dmListDisp.yview) self.upBtn = ttk.Button(self, width=10, text='Up', command=self.upCmd) self.downBtn = ttk.Button(self, width=10, text='Down', command=self.downCmd) self.delBtn = ttk.Button(self, width=10, text='Delete', command=self.delCmd) # configuration self.dmListDisp.configure(yscrollcommand=self.scrollY.set) self.columnconfigure(0, weight=1) self.rowconfigure(1, weight=1) self.label.grid(column=0, row=0, columnspan=5, sticky=NSEW) self.dmListDisp.grid(column=0, row=1, columnspan=5, sticky=NSEW) self.scrollY.grid(column=5, row=1, sticky=NSEW) self.upBtn.grid(column=2, row=2, sticky=NSEW) self.downBtn.grid(column=3, row=2, sticky=NSEW) self.delBtn.grid(column=4, row=2, sticky=NSEW) self.dmListDisp.bind('<<ListboxSelect>>', self.selChgCmd) self.dmListDisp.bind('<Double-1>', self.editCmd) self.dmListDisp.bind('<Delete>', self.delCmd) self.dmListDisp.bind('<Return>', self.editCmd) def refresh(self, event=None): """Refresh widget contents.""" self.updateList() for idx in range(len(self.dms)): self.dmListDisp.itemconfigure(idx, foreground='black') self.dmListDisp.itemconfigure(len(self.dms), foreground='#A0A0A0') def updateList(self, event=None): """Update the value in the displayed listVariable.""" self.listVariable.set( tuple(self.dms.names() + ['Double Click to Add Item'])) def moveEntry(self, idx, idx2): """Move an item from idx to idx2.""" self.dms.insert(idx2, self.dms.pop(idx)) self.updateList() self.dmListDisp.selection_clear(idx) self.dmListDisp.selection_set(idx2) self.selChgCmd() self.event_generate("<<dmOptChg>>") def upCmd(self, event=None): """Move the selected element up one space in the list.""" idx = self.selIdx # check that there is an entry selected, and it isn't the first entry. if idx not in [-1, 0, len(self.dms)]: self.moveEntry(idx, idx - 1) def downCmd(self, event=None): """Move the selected element down one space in the list.""" idx = self.selIdx # check that there is an entry selected, and it isn't the last entry if idx not in [-1, len(self.dms) - 1, len(self.dms)]: self.moveEntry(idx, idx + 1) def delCmd(self, *args): """Delete the selected element from the list.""" idx = self.selIdx if idx != len(self.dms): # check that a valid entry is selected del self.dms[idx] self.refresh() self.event_generate("<<dmOptChg>>") def selChgCmd(self, *args): """Called when the selection changes.""" self.selIdx = int(self.dmListDisp.curselection()[0]) if self.selIdx != len(self.conflict.decisionMakers): self.selectedDM = self.conflict.decisionMakers[self.selIdx] else: self.selectedDM = None self.event_generate('<<DMselected>>') def editCmd(self, *args): """Called when a list entry is selected for editing.""" self.event_generate('<<EditDM>>') def reselect(self, event=None): """Return selection focus to a dm after an action is completed.""" if self.selIdx is not None: self.dmListDisp.selection_set(self.selIdx) self.dmListDisp.event_generate('<<ListboxSelect>>')
class StreamFrame(Frame): def __init__(self, master): super(StreamFrame, self).__init__(master) self.root = master # check if user has saved the training sentiment analyzers pol_checkfile = os.path.exists('files/sa_polarity.pickle') subj_checkfile = os.path.exists('files/sa_subjectivity.pickle') if not (pol_checkfile and subj_checkfile): # if we cant find the SA files # These frames will hold the widgets nofiles_frm = Frame( self ) # this for the the warning message and the back and exit buttons nofiles_frm.grid(row=3, column=0, pady=5) exit_frm = Frame(self) # exit frame, contains back and exit button exit_frm.grid(row=4, column=0, pady=5) message = "SA files not found." read_write.log_message("[WARN] (frames.StreamFrame) : " + message) message += "\nClick Start Training first to train the NLTK classifiers." Label(nofiles_frm, text=message).grid(row=0, column=0, padx=10, pady=5) self.mng_stream_btn = Button( nofiles_frm, text="Start Stream") # ignore this, if there are no tweets # Build the widgets for nofiles_frm self.back_btn = Button(exit_frm, text="Back") self.back_btn.grid(row=1, column=1, ipadx=5, ipady=3, pady=15) self.exit_btn = Button(exit_frm, text="Exit", command=self.safe_exit) self.exit_btn.grid(row=1, column=3, ipadx=5, ipady=3, padx=15, pady=10) else: # These frames will hold the widgets label_frm = Frame(self) # this for the label and entry label_frm.grid(row=0, column=2, padx=10, pady=10, ipady=20, ipadx=20) # Frame for keywords self.keywords_frm = Frame( self ) # this will be hidden until user wants to see previous keywords self.keywords_frm.grid(row=0, column=3, rowspan=3, pady=15) # Build the widgets for label_frm Label(label_frm, text="Keyword:").grid(row=0, column=0, padx=20) self.keyword_entry = Entry(label_frm, width=30) self.keyword_entry.grid(row=0, column=1, columnspan=3) # Build the widgets for button_frm self.mng_stream_btn = Button( label_frm, text="Start Stream") # this will change from start to stop self.mng_stream_btn.grid(row=1, column=1, ipadx=5, ipady=3, pady=20) self.pause_stream_btn = Button( label_frm, text="Pause Stream") # if user starts stream, show this button self.pause_stream_btn.grid(row=1, column=3, ipadx=5, ipady=3, padx=10, pady=20) self.pause_stream_btn.grid_remove() # Build the widgets for keywords_frm self.manage_keywords_btn = Button( self.keywords_frm, command=self.show_keywords, text=">>>") # this will change into "<<<" when user clicks it self.manage_keywords_btn.grid(row=0, column=0, ipadx=5, ipady=3, padx=10) # Build the widgets for exit_frm self.back_btn = Button(label_frm, text="Back") self.back_btn.grid(row=2, column=1, ipadx=5, ipady=3, pady=15) self.exit_btn = Button(label_frm, text="Exit", command=self.safe_exit) self.exit_btn.grid(row=2, column=3, ipadx=5, ipady=3, padx=15, pady=10) # this method creates a new list box and populates it with the data from keywords.json def show_keywords(self): # first re-configure the button to show the desired text and change the command into hiding method self.manage_keywords_btn.config(text="<<<", command=self.hide_keywords) self.previous_keywords = read_write.read_keywords( ) # get any previous keywords # if there are keywords and the list is not empty if len(self.previous_keywords) > 0: # build the list box self.keyword_lb = Listbox(self.keywords_frm, height=10) self.keyword_lb.grid(column=1, row=0, pady=10, padx=5, sticky=(N, S, E, W)) # add a binding method self.keyword_lb.bind('<Double-1>', self.select_keyword) # and add the OK button. This happens here, because we don'w want a button without a list box self.select_keyword_btn = Button(self.keywords_frm, text="OK", command=self.select_keyword) self.select_keyword_btn.grid(row=3, column=1, ipady=3, ipadx=5, pady=10) # adding the keywords to the list box counter = 0 for keyword in self.previous_keywords: self.keyword_lb.insert(counter, keyword) counter += 1 # Colorize alternating lines of the listbox for i in range(0, len(self.previous_keywords), 2): self.keyword_lb.itemconfigure(i, background='#f0f0ff') # this method changes the button again and it is called to hide the list box def hide_keywords(self): self.manage_keywords_btn.config(text=">>>", command=self.show_keywords) try: # this may result to an error, because we can call hide_keywords before we initialize # the list box. This happening if no keywords are present in keywords.json self.keyword_lb.destroy() self.select_keyword_btn.destroy() except AttributeError: pass def select_keyword(self, *args): idxs = self.keyword_lb.curselection() if len(idxs) == 1: idx = int(idxs[0]) name = self.previous_keywords[idx] self.keyword_entry.delete(0, "end") self.keyword_entry.insert(0, name) def safe_exit(self): x = messagebox.askyesno(title="Exit", message="Are you sure you want to exit?", icon="question") if x: stream_util.stream_controller.stop() read_write.log_message("[INFO]" + stream_util.LOG_NAME + "Exiting...") self.root.destroy()
class LintGui: """Build and control a window to interact with pylint""" def __init__(self, root=None): """init""" self.root = root or Tk() self.root.title("Pylint") # reporter self.reporter = None # message queue for output from reporter self.msg_queue = queue.Queue() self.msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) # gui objects self.lbMessages = None self.showhistory = None self.results = None self.btnRun = None self.information_box = None self.convention_box = None self.refactor_box = None self.warning_box = None self.error_box = None self.fatal_box = None self.txtModule = None self.status = None self.msg_type_dict = None self.init_gui() def init_gui(self): """init helper""" # setting up frames top_frame = Frame(self.root) mid_frame = Frame(self.root) radio_frame = Frame(self.root) res_frame = Frame(self.root) msg_frame = Frame(self.root) check_frame = Frame(self.root) history_frame = Frame(self.root) btn_frame = Frame(self.root) rating_frame = Frame(self.root) top_frame.pack(side=TOP, fill=X) mid_frame.pack(side=TOP, fill=X) history_frame.pack(side=TOP, fill=BOTH, expand=True) radio_frame.pack(side=TOP, fill=BOTH, expand=True) rating_frame.pack(side=TOP, fill=BOTH, expand=True) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=BOTH, expand=True) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Message ListBox rightscrollbar = Scrollbar(msg_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.lbMessages = Listbox( msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white" ) self.lbMessages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lbMessages.yview) bottomscrollbar.config(command=self.lbMessages.xview) # History ListBoxes rightscrollbar2 = Scrollbar(history_frame) rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) self.showhistory = Listbox( history_frame, yscrollcommand=rightscrollbar2.set, xscrollcommand=bottomscrollbar2.set, bg="white" ) self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) self.showhistory.bind("<Double-Button-1>", self.select_recent_file) self.set_history_window() # status bar self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) self.status.pack(side=BOTTOM, fill=X) # labels self.lblRatingLabel = Label(rating_frame, text="Rating:") self.lblRatingLabel.pack(side=LEFT) self.lblRating = Label(rating_frame, textvariable=self.rating) self.lblRating.pack(side=LEFT) Label(mid_frame, text="Recently Used:").pack(side=LEFT) Label(top_frame, text="Module or package").pack(side=LEFT) # file textbox self.txtModule = Entry(top_frame, background="white") self.txtModule.bind("<Return>", self.run_lint) self.txtModule.pack(side=LEFT, expand=True, fill=X) # results box rightscrollbar = Scrollbar(res_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.results = Listbox( res_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white", font="Courier" ) self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) # buttons Button(top_frame, text="Open", command=self.file_open).pack(side=LEFT) Button(top_frame, text="Open Package", command=(lambda: self.file_open(package=True))).pack(side=LEFT) self.btnRun = Button(top_frame, text="Run", command=self.run_lint) self.btnRun.pack(side=LEFT) Button(btn_frame, text="Quit", command=self.quit).pack(side=BOTTOM) # radio buttons self.information_box = IntVar() self.convention_box = IntVar() self.refactor_box = IntVar() self.warning_box = IntVar() self.error_box = IntVar() self.fatal_box = IntVar() i = Checkbutton( check_frame, text="Information", fg=COLORS["(I)"], variable=self.information_box, command=self.refresh_msg_window, ) c = Checkbutton( check_frame, text="Convention", fg=COLORS["(C)"], variable=self.convention_box, command=self.refresh_msg_window, ) r = Checkbutton( check_frame, text="Refactor", fg=COLORS["(R)"], variable=self.refactor_box, command=self.refresh_msg_window ) w = Checkbutton( check_frame, text="Warning", fg=COLORS["(W)"], variable=self.warning_box, command=self.refresh_msg_window ) e = Checkbutton( check_frame, text="Error", fg=COLORS["(E)"], variable=self.error_box, command=self.refresh_msg_window ) f = Checkbutton( check_frame, text="Fatal", fg=COLORS["(F)"], variable=self.fatal_box, command=self.refresh_msg_window ) i.select() c.select() r.select() w.select() e.select() f.select() i.pack(side=LEFT) c.pack(side=LEFT) r.pack(side=LEFT) w.pack(side=LEFT) e.pack(side=LEFT) f.pack(side=LEFT) # check boxes self.box = StringVar() # XXX should be generated report = Radiobutton( radio_frame, text="Report", variable=self.box, value="Report", command=self.refresh_results_window ) rawMet = Radiobutton( radio_frame, text="Raw metrics", variable=self.box, value="Raw metrics", command=self.refresh_results_window ) dup = Radiobutton( radio_frame, text="Duplication", variable=self.box, value="Duplication", command=self.refresh_results_window ) ext = Radiobutton( radio_frame, text="External dependencies", variable=self.box, value="External dependencies", command=self.refresh_results_window, ) stat = Radiobutton( radio_frame, text="Statistics by type", variable=self.box, value="Statistics by type", command=self.refresh_results_window, ) msgCat = Radiobutton( radio_frame, text="Messages by category", variable=self.box, value="Messages by category", command=self.refresh_results_window, ) msg = Radiobutton( radio_frame, text="Messages", variable=self.box, value="Messages", command=self.refresh_results_window ) report.select() report.grid(column=0, row=0, sticky=W) rawMet.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=E) stat.grid(column=0, row=1, sticky=W) msgCat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, columnspan=2, sticky=W) # dictionary for check boxes and associated error term self.msg_type_dict = { "I": lambda: self.information_box.get() == 1, "C": lambda: self.convention_box.get() == 1, "R": lambda: self.refactor_box.get() == 1, "E": lambda: self.error_box.get() == 1, "W": lambda: self.warning_box.get() == 1, "F": lambda: self.fatal_box.get() == 1, } self.txtModule.focus_set() def select_recent_file(self, event): """adds the selected file in the history listbox to the Module box""" if not self.showhistory.size(): return selected = self.showhistory.curselection() item = self.showhistory.get(selected) # update module self.txtModule.delete(0, END) self.txtModule.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" # clear the window self.lbMessages.delete(0, END) for msg in self.msgs: if self.msg_type_dict.get(msg[0])(): msg_str = self.convert_to_string(msg) self.lbMessages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], "black") self.lbMessages.itemconfigure(END, fg=fg_color) def refresh_results_window(self): """refresh the results window with current output""" # clear the window self.results.delete(0, END) try: for res in self.tabs[self.box.get()]: self.results.insert(END, res) except: pass def convert_to_string(self, msg): """make a string representation of a message""" if msg[2] != "": return "(" + msg[0] + ") " + msg[1] + "." + msg[2] + " [" + msg[3] + "]: " + msg[4] else: return "(" + msg[0] + ") " + msg[1] + " [" + msg[3] + "]: " + msg[4] def process_incoming(self): """process the incoming messages from running pylint""" while self.msg_queue.qsize(): try: msg = self.msg_queue.get(0) if msg == "DONE": self.report_stream.output_contents() return False # adding message to list of msgs self.msgs.append(msg) # displaying msg if message type is selected in check box if self.msg_type_dict.get(msg[0])(): msg_str = self.convert_to_string(msg) self.lbMessages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], "black") self.lbMessages.itemconfigure(END, fg=fg_color) except queue.Empty: pass return True def periodic_call(self): """determine when to unlock the run button""" if self.process_incoming(): self.root.after(100, self.periodic_call) else: # enabling button so it can be run again self.btnRun.config(state=NORMAL) def mainloop(self): """launch the mainloop of the application""" self.root.mainloop() def quit(self, _=None): """quit the application""" self.root.quit() def halt(self): """program halt placeholder""" return def file_open(self, package=False, _=None): """launch a file browser""" if not package: filename = askopenfilename( parent=self.root, filetypes=[("pythonfiles", "*.py"), ("allfiles", "*")], title="Select Module" ) else: filename = askdirectory(title="Select A Folder", mustexist=1) if filename == (): return self.txtModule.delete(0, END) self.txtModule.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txtModule.get() if not filename: filename = os.getcwd() if filename + "\n" in self.filenames: index = self.filenames.index(filename + "\n") self.filenames.pop(index) # ensure only 10 most recent are stored if len(self.filenames) == 10: self.filenames.pop() self.filenames.insert(0, filename + "\n") def set_history_window(self): """update the history window with info from the history file""" # clear the window self.showhistory.delete(0, END) # keep the last 10 most recent files try: view_history = open(HOME + HISTORY, "r") for hist in view_history.readlines(): if not hist in self.filenames: self.filenames.append(hist) self.showhistory.insert(END, hist.split("\n")[0]) view_history.close() except IOError: # do nothing since history file will be created later return def run_lint(self, _=None): """launches pylint""" self.update_filenames() self.root.configure(cursor="watch") self.reporter = GUIReporter(self, output=self.report_stream) module = self.txtModule.get() if not module: module = os.getcwd() # cleaning up msgs and windows self.msgs = [] self.lbMessages.delete(0, END) self.tabs = {} self.results.delete(0, END) self.btnRun.config(state=DISABLED) # setting up a worker thread to run pylint worker = Thread(target=lint_thread, args=(module, self.reporter, self)) self.periodic_call() worker.start() # Overwrite the .pylint-gui-history file with all the new recently added files # in order from filenames but only save last 10 files write_history = open(HOME + HISTORY, "w") write_history.writelines(self.filenames) write_history.close() self.set_history_window() self.root.configure(cursor="")
class LintGui: """Build and control a window to interact with pylint""" def __init__(self, root=None): """init""" self.root = root or Tk() self.root.title('Pylint') #reporter self.reporter = None #message queue for output from reporter self.msg_queue = queue.Queue() self.msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) #gui objects self.lbMessages = None self.showhistory = None self.results = None self.btnRun = None self.information_box = None self.convention_box = None self.refactor_box = None self.warning_box = None self.error_box = None self.fatal_box = None self.txtModule = None self.status = None self.msg_type_dict = None self.init_gui() def init_gui(self): """init helper""" #setting up frames top_frame = Frame(self.root) mid_frame = Frame(self.root) radio_frame = Frame(self.root) res_frame = Frame(self.root) msg_frame = Frame(self.root) check_frame = Frame(self.root) history_frame = Frame(self.root) btn_frame = Frame(self.root) rating_frame = Frame(self.root) top_frame.pack(side=TOP, fill=X) mid_frame.pack(side=TOP, fill=X) history_frame.pack(side=TOP, fill=BOTH, expand=True) radio_frame.pack(side=TOP, fill=BOTH, expand=True) rating_frame.pack(side=TOP, fill=BOTH, expand=True) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=BOTH, expand=True) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) #Message ListBox rightscrollbar = Scrollbar(msg_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.lbMessages = Listbox(msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lbMessages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lbMessages.yview) bottomscrollbar.config(command=self.lbMessages.xview) #History ListBoxes rightscrollbar2 = Scrollbar(history_frame) rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) self.showhistory = Listbox(history_frame, yscrollcommand=rightscrollbar2.set, xscrollcommand=bottomscrollbar2.set, bg="white") self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) self.showhistory.bind('<Double-Button-1>', self.select_recent_file) self.set_history_window() #status bar self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) self.status.pack(side=BOTTOM, fill=X) #labels self.lblRatingLabel = Label(rating_frame, text='Rating:') self.lblRatingLabel.pack(side=LEFT) self.lblRating = Label(rating_frame, textvariable=self.rating) self.lblRating.pack(side=LEFT) Label(mid_frame, text='Recently Used:').pack(side=LEFT) Label(top_frame, text='Module or package').pack(side=LEFT) #file textbox self.txtModule = Entry(top_frame, background='white') self.txtModule.bind('<Return>', self.run_lint) self.txtModule.pack(side=LEFT, expand=True, fill=X) #results box rightscrollbar = Scrollbar(res_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.results = Listbox(res_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white", font="Courier") self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) #buttons Button(top_frame, text='Open', command=self.file_open).pack(side=LEFT) Button(top_frame, text='Open Package', command=(lambda: self.file_open(package=True))).pack(side=LEFT) self.btnRun = Button(top_frame, text='Run', command=self.run_lint) self.btnRun.pack(side=LEFT) Button(btn_frame, text='Quit', command=self.quit).pack(side=BOTTOM) #radio buttons self.information_box = IntVar() self.convention_box = IntVar() self.refactor_box = IntVar() self.warning_box = IntVar() self.error_box = IntVar() self.fatal_box = IntVar() i = Checkbutton(check_frame, text="Information", fg=COLORS['(I)'], variable=self.information_box, command=self.refresh_msg_window) c = Checkbutton(check_frame, text="Convention", fg=COLORS['(C)'], variable=self.convention_box, command=self.refresh_msg_window) r = Checkbutton(check_frame, text="Refactor", fg=COLORS['(R)'], variable=self.refactor_box, command=self.refresh_msg_window) w = Checkbutton(check_frame, text="Warning", fg=COLORS['(W)'], variable=self.warning_box, command=self.refresh_msg_window) e = Checkbutton(check_frame, text="Error", fg=COLORS['(E)'], variable=self.error_box, command=self.refresh_msg_window) f = Checkbutton(check_frame, text="Fatal", fg=COLORS['(F)'], variable=self.fatal_box, command=self.refresh_msg_window) i.select() c.select() r.select() w.select() e.select() f.select() i.pack(side=LEFT) c.pack(side=LEFT) r.pack(side=LEFT) w.pack(side=LEFT) e.pack(side=LEFT) f.pack(side=LEFT) #check boxes self.box = StringVar() # XXX should be generated report = Radiobutton(radio_frame, text="Report", variable=self.box, value="Report", command=self.refresh_results_window) rawMet = Radiobutton(radio_frame, text="Raw metrics", variable=self.box, value="Raw metrics", command=self.refresh_results_window) dup = Radiobutton(radio_frame, text="Duplication", variable=self.box, value="Duplication", command=self.refresh_results_window) ext = Radiobutton(radio_frame, text="External dependencies", variable=self.box, value="External dependencies", command=self.refresh_results_window) stat = Radiobutton(radio_frame, text="Statistics by type", variable=self.box, value="Statistics by type", command=self.refresh_results_window) msgCat = Radiobutton(radio_frame, text="Messages by category", variable=self.box, value="Messages by category", command=self.refresh_results_window) msg = Radiobutton(radio_frame, text="Messages", variable=self.box, value="Messages", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) rawMet.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=E) stat.grid(column=0, row=1, sticky=W) msgCat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, columnspan=2, sticky=W) #dictionary for check boxes and associated error term self.msg_type_dict = { 'I': lambda: self.information_box.get() == 1, 'C': lambda: self.convention_box.get() == 1, 'R': lambda: self.refactor_box.get() == 1, 'E': lambda: self.error_box.get() == 1, 'W': lambda: self.warning_box.get() == 1, 'F': lambda: self.fatal_box.get() == 1 } self.txtModule.focus_set() def select_recent_file(self, event): """adds the selected file in the history listbox to the Module box""" if not self.showhistory.size(): return selected = self.showhistory.curselection() item = self.showhistory.get(selected) #update module self.txtModule.delete(0, END) self.txtModule.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" #clear the window self.lbMessages.delete(0, END) for msg in self.msgs: if (self.msg_type_dict.get(msg[0])()): msg_str = self.convert_to_string(msg) self.lbMessages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lbMessages.itemconfigure(END, fg=fg_color) def refresh_results_window(self): """refresh the results window with current output""" #clear the window self.results.delete(0, END) try: for res in self.tabs[self.box.get()]: self.results.insert(END, res) except: pass def convert_to_string(self, msg): """make a string representation of a message""" if (msg[2] != ""): return "(" + msg[0] + ") " + msg[1] + "." + msg[2] + " [" + msg[ 3] + "]: " + msg[4] else: return "(" + msg[0] + ") " + msg[1] + " [" + msg[3] + "]: " + msg[4] def process_incoming(self): """process the incoming messages from running pylint""" while self.msg_queue.qsize(): try: msg = self.msg_queue.get(0) if msg == "DONE": self.report_stream.output_contents() return False #adding message to list of msgs self.msgs.append(msg) #displaying msg if message type is selected in check box if (self.msg_type_dict.get(msg[0])()): msg_str = self.convert_to_string(msg) self.lbMessages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lbMessages.itemconfigure(END, fg=fg_color) except queue.Empty: pass return True def periodic_call(self): """determine when to unlock the run button""" if self.process_incoming(): self.root.after(100, self.periodic_call) else: #enabling button so it can be run again self.btnRun.config(state=NORMAL) def mainloop(self): """launch the mainloop of the application""" self.root.mainloop() def quit(self, _=None): """quit the application""" self.root.quit() def halt(self): """program halt placeholder""" return def file_open(self, package=False, _=None): """launch a file browser""" if not package: filename = askopenfilename(parent=self.root, filetypes=[('pythonfiles', '*.py'), ('allfiles', '*')], title='Select Module') else: filename = askdirectory(title="Select A Folder", mustexist=1) if filename == (): return self.txtModule.delete(0, END) self.txtModule.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txtModule.get() if not filename: filename = os.getcwd() if filename + '\n' in self.filenames: index = self.filenames.index(filename + '\n') self.filenames.pop(index) #ensure only 10 most recent are stored if len(self.filenames) == 10: self.filenames.pop() self.filenames.insert(0, filename + '\n') def set_history_window(self): """update the history window with info from the history file""" #clear the window self.showhistory.delete(0, END) # keep the last 10 most recent files try: view_history = open(HOME + HISTORY, 'r') for hist in view_history.readlines(): if not hist in self.filenames: self.filenames.append(hist) self.showhistory.insert(END, hist.split('\n')[0]) view_history.close() except IOError: # do nothing since history file will be created later return def run_lint(self, _=None): """launches pylint""" self.update_filenames() self.root.configure(cursor='watch') self.reporter = GUIReporter(self, output=self.report_stream) module = self.txtModule.get() if not module: module = os.getcwd() #cleaning up msgs and windows self.msgs = [] self.lbMessages.delete(0, END) self.tabs = {} self.results.delete(0, END) self.btnRun.config(state=DISABLED) #setting up a worker thread to run pylint worker = Thread(target=lint_thread, args=( module, self.reporter, self, )) self.periodic_call() worker.start() # Overwrite the .pylint-gui-history file with all the new recently added files # in order from filenames but only save last 10 files write_history = open(HOME + HISTORY, 'w') write_history.writelines(self.filenames) write_history.close() self.set_history_window() self.root.configure(cursor='')
class Window(Frame): # Inicialización def __init__(self, master): # Parametros para mi clase Frame Frame.__init__(self, master) # Referenciamos self.master = master # GUI Here self.init_window() def init_window(self): # Titulo de la ventana self.master.title("QA Tools") # Instanciamos un menu menu = Menu(self.master) # Referenciamos al widget self.master.config(menu=menu) # Agreamos submenus file = Menu(menu, tearoff=0) # Agregamos submenu Open file.add_command(label="Open", command=self.openFile) # Agregamos submenu exit file.add_command(label="Exit", command=self.client_exit) # menu File menu.add_cascade(label="File", menu=file) # Scrollbar self.scrollbar = Scrollbar(self.master, orient=VERTICAL) self.scrollbar.pack(side=RIGHT, fill=Y) # Lista self.lista = Listbox(self.master, font=("Helvetica", 8), borderwidth=0, activestyle=NONE, yscrollcommand=self.scrollbar.set) self.lista.pack(fill=BOTH, expand=1) self.scrollbar.config(command=self.lista.yview) # Funcion para cerrar la app def client_exit(self): self.master.destroy() # Funcion para abrir un doc def openFile(self): self.lista.delete(0, END) # obtenemos el archivo filepath = fdialog.askopenfilename(initialdir="C:/Users/%s" % user, filetypes=( ("SQL File", "*.sql"), ("All Files", "*.*")), title="Selección de Archivo") switchCommentOn = 'N' flagBlockBD = 'N' flagBlockES = '' countBlock = 0 countLine = 0 countObject = 0 listBlockMerge = [listBlockHeader,listBlockBody,listBlockFoot,listStatements] dicBlock = {} dicReport = {} # dicParameters = {} dicBlockDescriptions = {} # listObjects = [] listConstants = [use, if_, exists, from_, sysobjects, objectid_, and_, type_, drop, procedure, create, grant, execute] conjConstants = set(listConstants) # listParameters = ['@'] # listBlock = [] conjBlockBD = set(listBlockBD) conjBlockHeader = set(listBlockHeader) conjBlockBody = set(listBlockBody) conjBlockFoot = set(listBlockFoot) # listBlockParameters = [] listBlockDescriptions = [] try: # con el nombre del archivo with open(filepath) as fp: # obtenemos la primera linea line = fp.readline() # mientras exista una linea while line: # damos formato estandar a la linea reemplazando )([].' por un espacio line = line.lower().replace(')', ' ').replace('(', ' ').replace('[', ' ').replace( ']', ' ').replace('.', ' ').replace("'", ' ').replace("\n", ' ').replace("\t", ' ') strippedLine = line.strip() if strippedLine == "": line = fp.readline() countLine += 1 continue if flagBlockBD == 'N' and countBlock >= 1: break if strippedLine == go: observation = '' conjBlock = set(dicBlock.keys()) if conjBlockBD.issubset(conjBlock): flagBlockBD = 'S' print(conjBlock) elif conjBlockHeader.issubset(conjBlock): flagBlockES = 'H' countObject = 2 print(conjBlock) elif conjBlockBody.issubset(conjBlock): flagBlockES = 'B' countObject = 1 print(conjBlock) elif conjBlockFoot.issubset(conjBlock): flagBlockES = 'F' countObject = 1 print(conjBlock) else: observation = "Bloque incompleto " if flagBlockBD == 'N': observation += "(Bloque BD) " if flagBlockES == '' and flagBlockBD == 'S' and countBlock >= 1: observation += "(Bloque Estandar) " conjBlock = conjBlock - conjConstants if len(conjBlock) == 1: if observation == "": self.lista.insert(END, ' '.join(map(str, conjBlock))) self.lista.itemconfigure(END, fg="#00aa00") else: self.lista.insert(END, observation) self.lista.itemconfigure(END, fg="#ff0000") elif len(conjBlock) == 0: self.lista.insert(END, observation) self.lista.itemconfigure(END, fg="#ff0000") else: observation = "Bloque con dos o más objetos " + flagBlockES self.lista.insert(END, observation) self.lista.itemconfigure(END, fg="#ff0000") dicBlock.clear() #dicBlockDescriptions.clear() #print(dicReport) countBlock += 1 else: if flagBlockBD == 'N': dicBlock = processLine(line,listBlockBD,dicBlock) line = fp.readline() countLine += 1 continue indexLineComent = line.find(lineComment, beg) if indexLineComent >= 0: line = fp.readline() countLine += 1 continue indexBlockComentOpen = line.find(blockCommentOpen, beg) if indexBlockComentOpen >= 0 or switchCommentOn == 'S': indexBlockComentClose = line.find(blockCommentClose, beg) if indexBlockComentClose >= 0: switchCommentOn = 'N' else: #dicBlockDescriptions = processLine(line,listDescriptions,dicBlockDescriptions) switchCommentOn = 'S' else: for target in listBlockMerge: dicBlock = processLine(line,target,dicBlock) # siguiente linea line = fp.readline() countLine += 1 except OSError as e: if e.errno == errno.ENOENT: messagebox.showwarning("Warning", "File not found / File not selected")
class Widgets: def __init__(self, root): self.setup = Setup(self) json_data = Json() self.update = Update(self, self.setup) self.db = LocalSqlite3() self.tracks = Tracks() self.top_menu = TopMenu(self, root) self.preset_setups = json_data.preset_setups self.game_modes = json_data.game_modes self.weatherTypes = json_data.weather self.cars = ('All Cars', '') self.raceSettings = json_data.cars #self.game_versions = json_data.game_versions self.c = Frame(root, padding=(5, 5, 12, 0)) self.c.grid(column=0, row=0, sticky=(N, W, E, S)) root.grid_columnconfigure(0, weight=1) root.grid_rowconfigure(0, weight=1) self.bg = "#33393b" # backgroundcolor self.fg = "white" # forgroundcolor self.status_message = StringVar() self.tracks_sorted = StringVar(value=self.tracks.track_sorted_list) self.sliderFrame = LabelFrame( self.c, text="Setup", labelanchor='nw', padding=5) self.track_box = Listbox( self.c, listvariable=self.tracks_sorted, height=len(self.tracks.track_sorted_list), bg=self.bg, fg=self.fg, highlightcolor="black", selectbackground="darkred", selectforeground="white") self.track_box.selection_clear(1, last=None) # self.game_version_box = self.create_combobox(list(self.game_versions)) self.race_box = self.create_combobox(list(self.raceSettings)) self.cars_box = self.create_combobox(self.cars) self.weather_box = self.create_combobox(list(self.weatherTypes)) self.game_mode_box = self.create_combobox(list(self.game_modes)) self.preset_box = self.create_combobox(list(self.preset_setups.values())) """ self.sort_tracks_box = self.create_checkbox( 'Order Tracks', self.sort_tracks, lambda: self.toggle_track_list(self.sort_tracks.get())) self.auto_use_changes_box = self.create_checkbox( 'Auto Use Changes', self.auto_use_changes, lambda: self.update_auto_use(self.auto_use_changes.get())) self.auto_save_changes_box = self.create_checkbox( 'Auto Save Changes', self.auto_save_changes, lambda: self.update_auto_save(self.auto_save_changes.get())) self.auto_use_track_box = self.create_checkbox( 'Auto Use track', self.auto_use_track, lambda: self.update_auto_use_track(self.auto_use_track.get())) """ # self.upload_button = self.create_button("Upload", self.upload) # self.community_button = self.create_button("Community", community.Community) # self.import_setups = self.create_button("import previous setups", self.update.populate_db_from_setups_dir) self.useButton = self.create_button("Use", self.use_cmd) # self.useSaveButton = self.create_button("Save & Use", self.use_save_cmd) # self.saveButton = self.create_button("Save", self.save_cmd) # self.saveAsButton = self.create_button("Save As", self.save_as_cmd) # self.openButton = self.create_button("Open", self.open_cmd) # self.tipBtn = self.create_button("Tip Scruffe", # lambda: self.open_url("https://paypal.me/valar")) self.status_bar = Label( self.c, textvariable=self.status_message, anchor=W) scales = MakeScale(self.sliderFrame) self.front_wing_Scale = scales.make("Front wing") self.rear_wing_Scale = scales.make("Rear wing") self.on_throttle_Scale = scales.make("On throttle", from_=50, to=100) self.off_throttle_Scale = scales.make("Off throttle", from_=50, to=100) self.front_camber_Scale = scales.make("Front camber", step=0.1, offset=-3.5) self.rear_camber_Scale = scales.make("Rear camber", step=0.1, offset=-2) self.front_toe_Scale = scales.make("Front toe", step=0.01, offset=0.05, res=2) self.rear_toe_Scale = scales.make("Rear toe", step=0.03, offset=0.20, res=2) # there is an offset self.front_suspension_Scale = scales.make("Front suspension") self.rear_suspension_Scale = scales.make("Rear suspension") self.front_antiroll_bar_Scale = scales.make("Front antiroll bar") self.rear_antiroll_bar_Scale = scales.make("Rear antiroll bar") self.front_suspension_height_Scale = scales.make("Front suspension height") self.rear_suspension_height_Scale = scales.make("Rear suspension height") self.brake_pressure_Scale = scales.make("Brake pressure", from_=50, to=100) self.brake_bias_Scale = scales.make("Brake bias", from_=70, to=50) self.front_right_tyre_pressure_Scale = scales.make("Front right tyre pressure", step=.4, offset=21) # , 0.4) self.front_left_tyre_pressure_Scale = scales.make("Front left tyre pressure", step=.4, offset=21) self.rear_right_tyre_pressure_Scale = scales.make("Rear right tyre pressure", step=.4, offset=19.5) self.rear_left_tyre_pressure_Scale = scales.make("Rear left tyre pressure", step=.4, offset=19.5) self.ballast_Scale = scales.make("Ballast") self.ramp_differential_Scale = scales.make("Ramp differential", from_=50, to=70) self.fuel_load_Scale = scales.make("Fuel load", from_=5, to=110) self.grid() self.enable_free_widgets() @property def boxes(self): return [self.track_box, self.race_box, self.cars_box, self.weather_box, self.game_mode_box, self.preset_box] """@property def check_boxes(self): return [self.sort_tracks_box, self.auto_use_changes_box, self.auto_save_changes_box, self.auto_use_track_box, # self.import_setups ]""" @property def league_id(self): return self.race_box.get() @property def team_id(self): """returns the ingame f1game team_id""" team_ids = [ # https://forums.codemasters.com/topic/50942-f1-2020-udp-specification/ "Mercedes", "Ferrari", "Red Bull", "Williams", "Racing Point", "Renault", "AlphaTauri", "Haas", "McLaren", "Alfa Romeo", "McLaren 1988", "McLaren 1991", "Williams 1992", "Ferrari 1995", "Williams 1996", "McLaren 1998", "Ferrari 2002", "Ferrari 2004", "Renault 2006", "Ferrari 2007", "McLaren 2008", "Red Bull 2010", "Ferrari 1976", "ART Grand Prix", "Campos Vexatec Racing", "Carlin", "Charouz Racing System", "Dams", "Uni-Virtuosi Racing", # changed russiantime "MP Motorsport", "Pertamina", # "McLaren 1990", "Trident", "BWT HWA Racelab", "McLaren 1976", "Lotus 1972", "Ferrari 1979", "McLaren 1982", "Williams 2003", "Brawn 2009", "Lotus 1978", "F1 Generic car", "Art GP ’19", "Campos ’19", "Carlin ’19", "Sauber Junior Charouz ’19", "Dams '19", "Uni-Virtuosi ‘19", "MP Motorsport ‘19", "Prema ’19", "Trident ’19", "Arden ’19", "Benetton 1994", "Benetton 1995", "Ferrari 2000", "Jordan 1991", "All Cars", "My Team"] # 255 """ f2 does not comply with udp specification some examples: 69 =multiplayer 76= mpmotersport 77 perta 78 trident 79 bwt 80 hitech 81 jordan91 82 benet """ team = self.cars_box.get() if team == "All Cars": return 41 # multiplayer car return team_ids.index(team) @property def game_mode_id(self): return self.game_modes[self.game_mode_box.get()] @property def weather_id(self): if self.weather_box.get() == "Wet": return 0 return 1 @property def sliders(self): """list of sliders""" return [ self.front_wing_Scale, self.rear_wing_Scale, self.on_throttle_Scale, self.off_throttle_Scale, self.front_camber_Scale, self.rear_camber_Scale, self.front_toe_Scale, self.rear_toe_Scale, self.front_suspension_Scale, self.rear_suspension_Scale, self.front_suspension_height_Scale, self.rear_suspension_height_Scale, self.front_antiroll_bar_Scale, self.rear_antiroll_bar_Scale, self.brake_pressure_Scale, self.brake_bias_Scale, self.front_right_tyre_pressure_Scale, self.front_left_tyre_pressure_Scale, self.rear_right_tyre_pressure_Scale, self.rear_left_tyre_pressure_Scale, self.ballast_Scale, self.fuel_load_Scale, self.ramp_differential_Scale] @sliders.setter def sliders(self, unpacked_setup): print(' - - - - - - - - setting sliders - - - - - - - - ') print(unpacked_setup) database_setup = unpacked_setup[0] if database_setup is True: i = 8 for slider in self.sliders: if slider.offset != 1: value = unpacked_setup[i] p = round(value - slider.offset, slider.res) product = round(p / slider.step, slider.res) + 1 slider.set(product) else: slider.set(unpacked_setup[i]) i += 1 print('loaded : ', unpacked_setup[1:8]) print('sliders values : ', unpacked_setup[8:]) else: # .bin file create_slider = SliderCounter(unpacked_setup) for slider in self.sliders: create_slider.set_slider_value(slider) print(" - - - - - - - - - - - - - - - - ") def create_combobox(self, _values): return Combobox( self.c, justify="center", values=_values, state="readonly") def create_checkbox(self, text, variable, command=None): return Checkbutton( self.c, text=text, variable=variable, command=command) def create_checkbutton(self, txt, var, cmd): return Checkbutton( self.c, text=txt, variable=var, command=lambda: cmd) def create_button(self, text, command=None): return Button( self.c, text=text, command=command) def grid(self): self.sliderFrame.grid( row=0, rowspan=15, column=2, columnspan=5) box_grid = GridWidgets() for box in self.boxes: box_grid.grid_box(box) check_box_grid = GridWidgets(startrow=8, padx=10) """for check_box in self.check_boxes: check_box_grid.grid_box(check_box)""" buttons = GridWidgets(startrow=check_box_grid.row, increment_horizontal=True) buttons.grid_box(self.useButton, columnspan=2) # buttons.grid_box(self.saveButton) # buttons.grid_box(self.saveAsButton) # buttons.grid_box(self.openButton) # buttons.grid_box(self.tipBtn, columnspan=2) # buttons.grid_box(self.community_button) # buttons.grid_box(self.upload_button) status = GridWidgets(startrow=(buttons.row + 16)) status.grid_box(self.status_bar, columnspan=7) self.c.grid_columnconfigure(0, weight=1) self.c.grid_rowconfigure(11, weight=1) def use_cmd(self): print(" - - - - - - - - using - - - - - - - - ") self.setup.use_setup() self.status_message.set("Using current setup") print(" - - - - - - - - - - - - - - - - ") def open_cmd(self): print(" - - - - - - - - opening file - - - - - - - - ") try: path = self.setup.open_setup() self.status_message.set(" Opened (" + str(path) + ")") except FileNotFoundError: self.status_message.set(" Can't find file)") print(" - - - - - - - - - - - - - - - - ") def use_save_cmd(self): self.setup.use_setup() self.save_cmd() def save_cmd(self): print(" - - - - - - - - saving - - - - - - - - ") car_setup = self.create_car_setup_from_widgets() print("car setup info: ", car_setup.info) print("car setup values: ", car_setup.values) self.setup.save_setup(car_setup) self.status_message.set("Saved") print(" - - - - - - - - - - - - - - - - ") def save_as_cmd(self): print(" - - - - - - - - save as - - - - - - - - ") try: path = self.setup.save_as_setup() self.status_message.set("Saved: " + path) except FileNotFoundError: self.status_message.set("File not found") def upload(self): print(" - - - - - - - - uploading - - - - - - - - ") car_setup = self.create_car_setup_from_widgets() print(car_setup.info) # commands.Commands().upload(car_setup) def toggle_track_list_order(self, sort_bool): print(" - - - - - - - - sorting track list - - - - - - - - ") """sort track list based on calendar or Alphabet""" # save new value to config file Config().sort_tracks = sort_bool # update track list self.tracks.toggle_track_sort(sort_bool) self.track_box.delete(0, END) self.track_box.insert(END, *self.tracks.track_sorted_list) # redo background color self.tracks_background_color() # show the previous selected track Events(self).box_event() def tracks_background_color(self): for i in range(0, len(self.tracks.track_sorted_list), 2): self.track_box.itemconfigure(i, background='#576366', fg=self.fg) def set_starting_values(self): print(" - - - - - - - - set starting values - - - - - - - - ") race = Config().race self.track_box.selection_set(0) self.race_box.set(race) self.cars_box['values'] = self.raceSettings[race] self.cars_box.set(Config().cars) self.weather_box.set(Config().weather) self.game_mode_box.set(Config().game_mode) self.preset_box.set("Load Preset") self.status_message.set('') self.top_menu.set_starting_values() self.toggle_race_sliders(race) Events(self).show_track_selection() def toggle_race_sliders(self, race): print(" - - - - - - - - toggle race sliders - - - - - - - - ") on_throttle = 'enabled' off_throttle = 'enabled' brake_pressure = 'enabled' fuel_load = 'enabled' ballast = 'enabled' ramp_differential = 'enabled' if race == 'F1 2021' or race == 'F1 2020' or race == 'classic': ramp_differential = 'disabled' if race == 'F1 2021' or race == 'F1 2020': ballast = 'disabled' elif race == 'F2 2021' or race == 'F2 2020' or race == 'F2 2019': on_throttle = 'disabled' off_throttle = 'disabled' brake_pressure = 'disabled' fuel_load = 'disabled' self.on_throttle_Scale.config(state=on_throttle) self.off_throttle_Scale.config(state=off_throttle) self.brake_pressure_Scale.config(state=brake_pressure) self.fuel_load_Scale.config(state=fuel_load) self.ballast_Scale.config(state=ballast) self.ramp_differential_Scale.config(state=ramp_differential) def create_car_setup_from_widgets(self): print("... creating car setup from widgets") current_track = Config().current_track league_id = league_sql.LeagueSql().get_id_from_name(self.league_id) track_id = TrackSql().get_track_id_by_country(current_track) print("self.config.current_track", current_track) print("track id", track_id) team_id = self.db.teams.get_team_id(self.cars_box.get(), league_id) car_setup = CarSetup( league_id=league_id, save_name=" save name test", team_id=team_id, track_id=track_id, game_mode_id=self.game_mode_id, weather_id=self.weather_id, front_wing=self.front_wing_Scale.get(), rear_wing=self.rear_wing_Scale.get(), on_throttle=self.on_throttle_Scale.get(), off_throttle=self.off_throttle_Scale.get(), front_camber=self.front_camber_Scale.get(), rear_camber=self.rear_camber_Scale.get(), front_toe=self.front_toe_Scale.get(), rear_toe=self.rear_toe_Scale.get(), front_suspension=self.front_suspension_Scale.get(), rear_suspension=self.rear_suspension_Scale.get(), front_suspension_height=self.front_suspension_height_Scale.get(), rear_suspension_height=self.rear_suspension_height_Scale.get(), front_antiroll_bar=self.front_antiroll_bar_Scale.get(), rear_antiroll_bar=self.rear_antiroll_bar_Scale.get(), brake_pressure=self.brake_pressure_Scale.get(), brake_bias=self.brake_bias_Scale.get(), front_right_tyre_pressure=self.front_right_tyre_pressure_Scale.get(), front_left_tyre_pressure=self.front_left_tyre_pressure_Scale.get(), rear_right_tyre_pressure=self.rear_right_tyre_pressure_Scale.get(), rear_left_tyre_pressure=self.rear_left_tyre_pressure_Scale.get(), ballast=self.ballast_Scale.get(), fuel_load=self.fuel_load_Scale.get(), ramp_differential=self.ramp_differential_Scale.get() ) return car_setup @staticmethod def open_url(url): open_new(url) def enable_free_widgets(self): self.race_box.configure(state="readonly") self.preset_box.configure(state='readonly') def premium(self): """enables premium content"""
class CopyToMoveTo: """ Minimalist file manager intended to be used independently or alongside Windows Explorer """ def __init__(self, root): """ Setup window geometry, init settings, define widgets + layout """ self.master = root self.master.title("CopyTo-MoveTo") self.master.iconbitmap(f"{dirname(__file__)}/icon.ico") if system() != "Windows": self.master.withdraw() messagebox.showwarning( "Incompatible platform", "CopyTo-MoveTo currently supports Windows platforms only.") raise SystemExit #Settings: self.settings_show_hidden = BooleanVar() self.settings_include_files = BooleanVar(value=True) self.settings_ask_overwrite = BooleanVar() self.settings_ask_overwrite.trace("w", self.settings_exclusives) self.settings_rename_dupes = BooleanVar(value=True) self.settings_rename_dupes.trace("w", self.settings_exclusives) self.settings_multiselect = BooleanVar(value=True) self.settings_select_dirs = BooleanVar(value=True) self.settings_select_dirs.trace("w", self.settings_mutuals) self.settings_select_files = BooleanVar(value=True) self.settings_select_files.trace("w", self.settings_mutuals) self.settings_geometry = None self.appdata_dir = getenv("APPDATA") + "/CopyTo-MoveTo" self.appdata_path = self.appdata_dir + "/settings.json" self.settings = self.init_settings() if self.settings: self.settings_geometry = self.settings["geometry"] self.settings_show_hidden.set(self.settings["show_hidden"]) self.settings_include_files.set(self.settings["include_files"]) self.settings_ask_overwrite.set(self.settings["ask_overwrite"]) self.settings_rename_dupes.set(self.settings["rename_dupes"]) self.settings_multiselect.set(self.settings["multiselect"]) self.settings_select_dirs.set(self.settings["select_dirs"]) self.settings_select_files.set(self.settings["select_files"]) self.dialog_showing = BooleanVar() self.help_showing = BooleanVar() self.about_showing = BooleanVar() self.master.protocol("WM_DELETE_WINDOW", self.master_close) self.master.bind("<Control-w>", self.master_close) #Geometry: self.master.minsize(width=450, height=200) if self.settings_geometry: self.master.geometry(self.settings_geometry) self.master.update() else: self.master.geometry("600x400") self.master.update_idletasks() (width_offset, height_offset) = Ufd.get_offset(self.master) self.master.geometry(f"+{width_offset}+{height_offset}") self.master.update_idletasks() # Menu: self.main_menu = Menu(self.master) self.master.config(menu=self.main_menu) self.file_menu = Menu(self.main_menu, tearoff=0) self.settings_menu = Menu(self.main_menu, tearoff=0) self.main_menu.add_cascade(label="File", menu=self.file_menu) self.main_menu.add_cascade(label="Settings", menu=self.settings_menu) self.file_menu.add_command(label="Open Source(s)", accelerator="Ctrl+O", command=lambda: self.show_ufd(source=True)) self.master.bind("<Control-o>", lambda event: self.show_ufd(source=True)) self.file_menu.add_command(label="Open Destination(s)", accelerator="Ctrl+K+O", command=lambda: self.show_ufd(source=False)) self.master.bind("<Control-k>o", lambda event: self.show_ufd(source=False)) self.file_menu.add_separator() self.file_menu.add_command(label="Help / Commands", command=self.show_help) self.file_menu.add_command(label="About", command=self.show_about) #Settings menu: self.settings_menu.add_checkbutton(label="Show Hidden Files & Folders", variable=self.settings_show_hidden, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton( label="Include Files in Tree", variable=self.settings_include_files, onvalue=True, offvalue=False) self.settings_menu.add_separator() self.settings_menu.add_checkbutton( label="Ask Overwrite", variable=self.settings_ask_overwrite, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton(label="Rename Duplicates", variable=self.settings_rename_dupes, onvalue=True, offvalue=False) self.settings_menu.add_separator() self.settings_menu.add_checkbutton(label="Multiselect", variable=self.settings_multiselect, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton(label="Select Folders", variable=self.settings_select_dirs, onvalue=True, offvalue=False) self.settings_menu.add_checkbutton(label="Select Files", variable=self.settings_select_files, onvalue=True, offvalue=False) self.main_menu.add_separator() #Menu commands: self.main_menu.add_command(label="Swap Selected", command=self.swap_selected) self.master.bind("<Control-s>", lambda event: self.swap_selected()) self.main_menu.add_command(label="Clear Selected", command=self.clear_selected) self.master.bind("<Control-x>", lambda event: self.clear_selected()) self.main_menu.add_command(label="Clear All", command=self.clear_all) self.master.bind("<Control-Shift-X>", lambda event: self.clear_all()) self.main_menu.add_separator() self.main_menu.add_command(label="COPY", command=lambda: self._submit(copy=True)) self.master.bind("<Control-Shift-Return>", lambda event: self._submit(copy=True)) self.main_menu.add_command(label="MOVE", command=lambda: self._submit(copy=False)) self.master.bind("<Control-Return>", lambda event: self._submit(copy=False)) # Body: self.paneview = PanedWindow(self.master, sashwidth=7, bg="#cccccc", bd=0, orient="vertical") self.top_pane = PanedWindow(self.paneview) self.bottom_pane = PanedWindow(self.paneview) self.paneview.add(self.top_pane) self.paneview.add(self.bottom_pane) self.label_source = Label(self.top_pane, text="Source(s):") self.label_dest = Label(self.bottom_pane, text="Destination(s):") self.y_scrollbar_source = Scrollbar(self.top_pane, orient="vertical") self.x_scrollbar_source = Scrollbar(self.top_pane, orient="horizontal") self.y_scrollbar_dest = Scrollbar(self.bottom_pane, orient="vertical") self.x_scrollbar_dest = Scrollbar(self.bottom_pane, orient="horizontal") self.list_box_source = Listbox( self.top_pane, selectmode="extended", yscrollcommand=self.y_scrollbar_source.set, xscrollcommand=self.x_scrollbar_source.set) self.list_box_dest = Listbox(self.bottom_pane, selectmode="extended", yscrollcommand=self.y_scrollbar_dest.set, xscrollcommand=self.x_scrollbar_dest.set) self.x_scrollbar_source.config(command=self.list_box_source.xview) self.y_scrollbar_source.config(command=self.list_box_source.yview) self.x_scrollbar_dest.config(command=self.list_box_dest.xview) self.y_scrollbar_dest.config(command=self.list_box_dest.yview) # Layout: self.master.rowconfigure(0, weight=1) self.master.columnconfigure(0, weight=1) self.top_pane.rowconfigure(1, weight=1) self.top_pane.columnconfigure(0, weight=1) self.bottom_pane.rowconfigure(1, weight=1) self.bottom_pane.columnconfigure(0, weight=1) self.paneview.paneconfigure(self.top_pane, minsize=100) self.paneview.paneconfigure(self.bottom_pane, minsize=100) self.paneview.grid(row=0, column=0, sticky="nsew") self.label_source.grid(row=0, column=0, sticky="w") self.list_box_source.grid(row=1, column=0, sticky="nsew") self.y_scrollbar_source.grid(row=1, column=1, sticky="ns") self.x_scrollbar_source.grid(row=2, column=0, sticky="ew") self.label_dest.grid(row=0, column=0, sticky="w", columnspan=2) self.list_box_dest.grid(row=1, column=0, sticky="nsew") self.y_scrollbar_dest.grid(row=1, column=1, sticky="ns") self.x_scrollbar_dest.grid(row=2, column=0, sticky="ew") def __str__(self): """Return own address""" return f"CopyTo-MoveTo @ {hex(id(self))}" def init_settings(self): """Called on startup, loads, parses, and returns json settings.""" if exists(self.appdata_path): with open(self.appdata_path, "r") as settings_file: settings_json = settings_file.read() settings = loads(settings_json) return settings else: return None def settings_exclusives(self, *args): """ Callback assigned to settings that are mutually exclusive, to prevent logical/runtime errors or unexpected behavior. """ if args[0] == "PY_VAR2": if self.settings_ask_overwrite.get() == 1: self.settings_rename_dupes.set(0) return elif args[0] == "PY_VAR3": if self.settings_rename_dupes.get() == 1: self.settings_ask_overwrite.set(0) return def settings_mutuals(self, *args): """ Prevent select folders & select files from being disabled concurrently If both are unselected, reselect the one we didn't just deselect on. """ if self.settings_select_dirs.get() == 0 \ and self.settings_select_files.get() == 0: if args[0] == "PY_VAR5": self.settings_select_files.set(1) elif args[0] == "PY_VAR6": self.settings_select_dirs.set(1) def master_close(self, event=None): """ Similar to utils.toplevel_close(). writes settings to the disk as json. """ settings = { "geometry": self.master.geometry(), "show_hidden": self.settings_show_hidden.get(), "include_files": self.settings_include_files.get(), "ask_overwrite": self.settings_ask_overwrite.get(), "rename_dupes": self.settings_rename_dupes.get(), "multiselect": self.settings_multiselect.get(), "select_dirs": self.settings_select_dirs.get(), "select_files": self.settings_select_files.get(), } settings_json = dumps(settings) if not exists(self.appdata_dir): mkdir(self.appdata_dir) with open(self.appdata_path, "w+") as settings_file: settings_file.write(settings_json) if self.dialog_showing.get() == 1: self.ufd.cancel() self.master.destroy() def toplevel_close(self, dialog, boolean): """ This callback flips the value for a given toplevel_showing boolean to false, before disposing of the toplevel. """ boolean.set(0) dialog.destroy() def swap_selected(self): """Swap list entries between source & destination""" source_selection = list(self.list_box_source.curselection()) dest_selection = list(self.list_box_dest.curselection()) for i in reversed(source_selection): item = self.list_box_source.get(i) self.list_box_source.delete(i) self.list_box_dest.insert("0", item) for i in reversed(dest_selection): item = self.list_box_dest.get(i) self.list_box_dest.delete(i) self.list_box_source.insert("0", item) def clear_selected(self): """Removes selected (highlighted) item(s) from a given listbox""" source_selection = list(self.list_box_source.curselection()) dest_selection = list(self.list_box_dest.curselection()) if source_selection: for i in reversed(source_selection): self.list_box_source.delete(i) self.list_box_source.selection_set(source_selection[0]) if dest_selection: for i in reversed(dest_selection): self.list_box_dest.delete(i) self.list_box_dest.selection_set(dest_selection[0]) def clear_all(self): """Clears both listboxes in the main UI, resetting the form.""" self.list_box_source.delete(0, "end") self.list_box_dest.delete(0, "end") def handled(fn): """Filesystem operations are wrapped here for error handling""" @wraps(fn) def inner(self, *args, **kwargs): try: fn(self, *args, **kwargs) return True except (PermissionError, FileNotFoundError) as err: self.skipped_err.append(f"{err.args[1]}:\n" + (" => ".join(args))) return False return inner @handled def _copy(self, path, destination): """Wrapper for shutil.copy2() || shutil.copytree()""" if isfile(path): copy2(path, destination) else: copytree(path, destination) @handled def _move(self, path, destination): """Wrapper for shutil.move()""" move(path, destination) @handled def _delete(self, path): """Wrapper for os.remove() || shutil.rmtree()""" if isfile(path): remove(path) elif isdir(path): rmtree(path) def disabled_ui(fn): """Menubar is disabled during operations""" @wraps(fn) def inner(self, *args, **kwargs): self.main_menu.entryconfig("File", state="disabled") self.main_menu.entryconfig("Settings", state="disabled") self.main_menu.entryconfig("Clear Selected", state="disabled") self.main_menu.entryconfig("Clear All", state="disabled") self.main_menu.entryconfig("COPY", state="disabled") self.main_menu.entryconfig("MOVE", state="disabled") fn(self, *args, **kwargs) self.main_menu.entryconfig("File", state="normal") self.main_menu.entryconfig("Settings", state="normal") self.main_menu.entryconfig("Clear Selected", state="normal") self.main_menu.entryconfig("Clear All", state="normal") self.main_menu.entryconfig("COPY", state="normal") self.main_menu.entryconfig("MOVE", state="normal") return inner def _submit(self, copy): """Thread/wrapper for submit() so we don't block the UI during operations""" self.thread = Thread(target=self.submit, args=(copy, ), daemon=True) self.thread.start() @disabled_ui def submit(self, copy): """ Move or copy each item in the origin list to the path in the destination list. Supports no more than one destination directory where copy == False. Ask Overwrite and Rename Dupes will alter the way we handle existing data standing in the way. By default, duplicates are renamed with an index. A messagebox can complain to the user if shutil raises a PermissionError, and the operation is skipped. """ if (self.list_box_dest.size() > 1) and not copy: messagebox.showwarning( "Invalid Operation", "Move operation only supports a single destination directory.") return sources = self.list_box_source.get(0, "end") destinations = self.list_box_dest.get(0, "end") self.skipped_err = [] for j, destination in enumerate(destinations): if isfile(destination): self.skipped_err.append(f"Invalid destination: {destination}") continue for i, source in enumerate(sources): self.progress(i, j) (_, filename) = split(source) future_destination = join(destination + sep, filename) if exists(future_destination): if not self.settings_ask_overwrite.get() \ and not self.settings_rename_dupes.get(): if not self._delete(future_destination): continue if self.settings_ask_overwrite.get(): if self.ask_overwrite(future_destination): if not self._delete(future_destination): continue else: continue if self.settings_rename_dupes.get(): future_destination = self.name_dupe(future_destination) if copy: if not self._copy(source, future_destination): continue else: if not self._move(source, future_destination): continue self.list_box_source.delete(0, "end") self.list_box_dest.delete(0, "end") if self.skipped_err: messagebox.showerror(title="Error(s)", message="\n\n".join(self.skipped_err)) @staticmethod def name_dupe(path): """ Renames the file or directory until it doesn't exist in the destination with that name anymore, by appending the filename with an index wrapped in parenthesis. (Windows platforms) file.txt => file (1).txt => file (2).txt """ if system() != "Windows": raise OSError("For use with Windows filesystems.") path_ = path (root, filename) = split(path_) if isdir(path_): title = filename ext = None else: (title, ext) = splitext(filename) filecount = 0 while exists(path_): filecount += 1 new_title = title + " (" + str(filecount) + ")" if ext: new_title = new_title + ext path_ = join(root, new_title) return path_ def ask_overwrite(self, future_destination): """Messagebox result returned as truth value""" return messagebox.askyesno( title="Path Conflict", message=f"Overwrite:\n\n{future_destination}?\n\n" \ f"YES - Overwrite\nNO - Skip" ) def progress(self, i, j): """ Visualize operands in GUI during operations i = current source operand index j = current destination operand index """ for y, _ in enumerate(self.list_box_source.get(0, "end")): if y != i: self.list_box_source.itemconfigure(y, bg="#FFFFFF", fg="#000000") else: self.list_box_source.itemconfigure(y, bg="#cccccc", fg="#000000") for x, _ in enumerate(self.list_box_dest.get(0, "end")): if x != j: self.list_box_dest.itemconfigure(x, bg="#FFFFFF", fg="#000000") else: self.list_box_dest.itemconfigure(x, bg="#cccccc", fg="#000000") self.master.update() #Toplevels: def show_about(self): """ Displays a static dialog that doesn't allow additional instances of itself to be created while showing. """ if self.about_showing.get() == 0: self.about_showing.set(1) try: with open(f"{dirname(__file__)}/about.txt", "r") as aboutfile: about_info = aboutfile.read() except FileNotFoundError: messagebox.showerror("Error", "File not found") self.about_showing.set(0) return else: self.about = Toplevel() self.about.title("About") self.about.iconbitmap(f"{dirname(__file__)}/icon.ico") self.about.geometry("600x400") self.about.resizable(0, 0) self.about.update_idletasks() (width_offset, height_offset) = Ufd.get_offset(self.about) self.about.geometry(f"+{width_offset-75}+{height_offset-75}") self.about.update_idletasks() self.about_message = Label( self.about, text=about_info, justify="left", wraplength=(self.about.winfo_width() - 25)) self.about_message.grid(sticky="nsew") self.about.protocol( "WM_DELETE_WINDOW", lambda: self.toplevel_close( self.about, self.about_showing)) def show_help(self): """ Displays a scrollable dialog that doesn't allow additional instances of itself to be created while showing. """ if self.help_showing.get() == 0: self.help_showing.set(1) try: with open(f"{dirname(__file__)}/help.txt", "r") as helpfile: help_info = helpfile.read() except FileNotFoundError: messagebox.showerror("Error", "File not found") self.help_showing.set(0) return else: self.help_window = Toplevel() self.help_window.title("Help") self.help_window.iconbitmap(f"{dirname(__file__)}/icon.ico") self.help_window.geometry("500x300") self.help_window.update_idletasks() (width_offset, height_offset) = Ufd.get_offset(self.help_window) self.help_window.geometry( f"+{width_offset+75}+{height_offset-75}") self.help_window.update_idletasks() self.message_y_scrollbar = Scrollbar(self.help_window, orient="vertical") self.help_text = Text( self.help_window, wrap="word", yscrollcommand=self.message_y_scrollbar.set) self.help_window.rowconfigure(0, weight=1) self.help_window.columnconfigure(0, weight=1) self.help_text.grid(row=0, column=0, sticky="nsew") self.message_y_scrollbar.grid(row=0, column=1, sticky="nse") self.message_y_scrollbar.config(command=self.help_text.yview) self.help_text.insert("end", help_info) self.help_text.config(state="disabled") self.help_window.protocol( "WM_DELETE_WINDOW", lambda: self.toplevel_close( self.help_window, self.help_showing)) def show_ufd(self, source=True): """ Display Ufd w/ appropriate kwargs => Populate GUI w/ result""" if self.dialog_showing.get() == 0: self.dialog_showing.set(1) self.ufd = Ufd(title="Add Items", show_hidden=self.settings_show_hidden.get(), include_files=self.settings_include_files.get(), multiselect=self.settings_multiselect.get(), select_dirs=self.settings_select_dirs.get(), select_files=self.settings_select_files.get(), unix_delimiter=False, stdout=False) for result in self.ufd(): if source: self.list_box_source.insert("end", result) else: self.list_box_dest.insert("end", result) self.dialog_showing.set(0)
class Player(Frame): def __init__(self,master): super().__init__(master) self.master =master mixer.init() self.pack() if os.path.exists("tracks.pickle"): with open ("tracks.pickle", "rb") as f: self.playlist =pickle.load(f) else: self.playlist =[] # player state flags self.track_index =0 self.track_paused =True self.track_played =False self.model_frame() self.track_widget() self.tracklist_widget() self.controls_widget() # frames def model_frame(self): self.track =LabelFrame(self, relief =GROOVE ) self.track.configure( width =410, height =300 ) self.track.grid(row=0, column=0,pady=10,padx=10) self.tracklist =LabelFrame(self, relief =GROOVE ) self.tracklist.configure( width =190, height =420 ) self.tracklist.grid(row=0, column=1,rowspan=3,pady=10,padx=10) self.controls =LabelFrame(self, font =("times new roman",15,"bold"), bg ="white", fg ="white", bd =0, relief =GROOVE ) self.controls.configure( width =410, height =100 ) self.controls.grid(row=1, column=0,pady=10,padx=10) # widgets def track_widget(self): self.canvas =Label(self.track,font =("times new roman",15,"bold"),bg="white", fg ="dodgerblue") self.canvas['text'] ="Hit tracks"; self.canvas.configure(width =33, height =1) self.canvas.grid(row =0,column =0) self.canvas =Label(self.track,image=track_ico) self.canvas.configure(width =300, height =240) self.canvas.grid(row =1,column =0) self.playing_tune =Label(self.track,font =("Calibri",13),bg="white", fg ="dodgerblue") self.playing_tune['text'] ="Musiflix MP3 Player"; self.playing_tune.configure(width =44, height =1) self.playing_tune.grid(row =2,column =0) def tracklist_widget(self): self.listtitle =Label(self.tracklist,font =("times new roman",15,"bold"),bg="white", fg ="dodgerblue") self.listtitle['text'] =f"Playlist: {len(self.playlist)} " self.listtitle.configure(width =10, height =1) self.listtitle.grid(row =0,column =0) self.scrollbar =Scrollbar(self.tracklist,orient =VERTICAL) self.scrollbar.grid(row=0, column=1,rowspan =10, sticky="NS") self.list =Listbox(self.tracklist, selectmode =SINGLE, yscrollcommand =self.scrollbar.set, selectbackground ="sky blue") self.track_listing() self.list.config(height =22) self.list.bind('<Double-1>', self.play_track) self.scrollbar.config(command =self.list.yview) self.list.grid(row=2, column=0, rowspan =5) def track_listing(self): for index, track in enumerate(self.playlist): self.list.insert(index,os.path.basename(track)) def controls_widget(self): self.tracklister =Button(self.controls, font =("times new roman",15,"bold"), bg="white", fg ="dodgerblue", padx =10,pady =5, command =self.select_track ) self.tracklister['text'] ="Load tracks" self.tracklister.grid(row =0,column =0,padx=10,pady =5) self.prevbutton =Button(self.controls,image =prev_icon, command =self.prev_track) self.prevbutton.grid(row =0,column =1,pady =5) self.pausebutton =Button(self.controls,image =pauseicon, command =self.pause_track) self.pausebutton.grid(row =0,column =2,pady =5) self.nextbutton =Button(self.controls,image =next_icon, command =self.next_track) self.nextbutton.grid(row =0,column =3,pady =5) self.volume =DoubleVar() self.slider =Scale(self.controls, from_ =0, to =10, orient =HORIZONTAL) self.slider['variable'] =self.volume self.slider['command'] =self.change_volume self.slider.set(3) mixer.music.set_volume(0.3) self.slider.grid(row =0, column=4,padx=10,pady =5) def change_volume(self, event =None): self.v =self.volume.get() mixer.music.set_volume(self.v/10) def select_track(self): self.tunes =[] directory =filedialog.askdirectory() for rooot, dirs, files in os.walk(directory): for file in files: if os.path.splitext(file)[1] =='.mp3': path =(rooot + '/' + file).replace('\\','/') self.tunes.append(path) with open("tracks.pickle", "wb") as f: pickle.dump(self.tunes, f) self.playlist =self.tunes self.listtitle['text'] =f"Playlist: {len(self.playlist)}" self.list.delete(0, END) self.track_listing() def play_track(self, event =None): try: if event is not None: self.track_index =self.list.curselection()[0] for i in range(len(self.playlist)): self.list.itemconfigure(i,bg="white",fg="black") mixer.music.load(self.playlist[self.track_index]) self.track_paused =False self.track_played =True self.pausebutton['image'] =playicon self.playing_tune.anchor('w') self.playing_tune['text'] =os.path.basename(self.playlist[self.track_index]) self.list.activate(self.track_index) self.list.itemconfigure(self.track_index,bg="teal", fg="white") mixer.music.play() except Exception as e: pass def pause_track(self): if not self.track_paused: try: self.track_paused =True self.pausebutton['image'] =pauseicon mixer.music.pause() except Exception as e: pass else: try: if not self.track_played: self.play_track() self.track_paused =False self.pausebutton['image'] =playicon mixer.music.unpause() except Exception as e: pass def next_track(self): if self.track_index > len(self.playlist) -1: self.track_index =0 self.track_index +=1 self.play_track() def prev_track(self): if self.track_index < 0: self.track_index =len(self.playlist) -1 self.track_index -=1 self.play_track()