class Credits(tkSimpleDialog.Dialog): def body(self, master): self.image = Tk.PhotoImage(file=GIFFILE) self.icon = Tk.Label(master, image=self.image) self.icon.pack(side=Tk.TOP) label = Tk.Label(master, text=crnotice1) label.pack(side=Tk.TOP) font = "Helvetica " + TITLEFONTSIZE label = Tk.Label(master, font=font, text="Credits", justify=Tk.CENTER, foreground='blue') label.pack(side=Tk.TOP) font = "Helvetica " + AXISFONTSIZE self.infoText = ScrolledText(master, relief=Tk.FLAT, padx=3, pady=3, background='white', foreground="blue", wrap='word', width=70, height=12, font=font, tabs=("4c")) self.infoText.pack(expand=0, fill=Tk.X, side=Tk.BOTTOM) self.infoText.delete('0.0', Tk.END) self.infoText.insert('0.0', getCredits()) self.infoText.configure(state=Tk.DISABLED)
class TraceFrame(Frame): def __init__(self, *args, **kwargs): Frame.__init__(self, *args, **kwargs) self.t = ScrolledText(self, wrap="word") self.t.configure(background="light cyan") self.t.configure(height = 10) self.t.tag_config("in", foreground="forest green") self.t.tag_config("err", foreground="orange red") self.t.tag_config("time", foreground="sea green") self.t.tag_config("curr", foreground="black") self.t.tag_config("out", foreground="firebrick") self.t.pack(side="top", fill="both", expand=True) def add_To_Trace(self, st, tag): ''' :param st: txte a afficher :param tag: type de texte a afficher :return: ''' self.t.insert(INSERT, st, tag) self.t.see(END) def clear_Trace(self): ''' Efface la zone de texte :return: ''' self.t.delete('1.0', 'end')
class PopupScrolledText(PopupWindow): """ Scrolled text output window with 'Save As...' """ def __init__(self, title="", kind="", iconfile=None, var=None): PopupWindow.__init__(self, title=title, kind=kind, iconfile=iconfile) if var: self._var = var else: self._var = BooleanVar() self._var.trace_variable("w", self._visibility_control) self._text = ScrolledText(self) self._text.pack() self._text.config(font=FONT) self._make_menu() self._visibility_control() def on_close(self, *args): self._var.set(False) def _visibility_control(self, *args): if self._var.get(): self.deiconify() else: self.withdraw() def _make_menu(self): topmenu = Menu(self) self.config(menu=topmenu) file = Menu(topmenu, tearoff=0) file.add_command(label="Save as...", command=self.on_save_as) file.add_command(label="Hide", command=self.on_close) topmenu.add_cascade(label="File", menu=file) edit = Menu(topmenu, tearoff=0) edit.add_command(label="Clear text", command=self.on_clear) topmenu.add_cascade(label="Edit", menu=edit) def on_save_as(self): filename = asksaveasfilename() if filename: alltext = self.gettext() f = open(filename, "w") f.write(alltext) f.close() def on_clear(self): self._text.delete("0.0", END) self._text.update() def gettext(self): return self._text.get("1.0", END + "-1c") def hide(self): self._var.set(False) def show(self): self._var.set(True)
class App(object): def __init__(self): self.window = tk.Tk() self.window.attributes("-fullscreen",True) self.window.minsize(width=320, height=240) self.window.maxsize(width=320, height=240) self.buttonFrame = tk.Frame(self.window) self.printButton=tk.Button(self.buttonFrame, text='PRINT!', height=2, command=self.printTxt) self.printButton.pack(side=tk.LEFT, fill=tk.X, padx=5, pady=5) self.loadButton=tk.Button(self.buttonFrame, text='LOAD', height=2, command=self.load) self.loadButton.pack(side=tk.LEFT, fill=tk.X, padx=5, pady=5, expand=1) self.exitButton=tk.Button(self.buttonFrame, text='EXIT', height=2, command=self.exitWin) self.exitButton.pack(side=tk.LEFT, fill=tk.X, padx=5, pady=5, expand=1) self.buttonFrame.pack(side=tk.TOP) self.filename = '/home/pi/Desktop/fly.txt' self.txt = ScrolledText(self.window) self.txt.vbar.config(width=18) self.txt.pack(expand=True, fill=tk.BOTH) self.loadFile() self.poll() def poll(self): if(float(self.txt.vbar.get()[1])==1): self.txt.see(1.0) #goto top else: self.txt.yview(tk.SCROLL,1,tk.UNITS) self.window.after(1000, self.poll) def load(self): self.filename = askopenfilename(initialdir="/home/pi/Desktop", title="SELECT TXT", filetypes=(("txt files","*.txt"),("all files","*.*")) ) self.loadFile() def loadFile(self): self.txt.delete(1.0,tk.END) fly = open(self.filename,'r') self.txt.insert(1.0, fly.read()) fly.close() def printTxt(self): call(["lp", self.filename]) tkMessageBox.showinfo("PRINT", "it's printing!") def exitWin(self): result = tkMessageBox.askquestion("EXIT?!", "zomg, u sure?", icon='warning') if result == 'yes': self.window.quit()
class MemorablePwdsApp(pp2e_laj.gui.tools.guimixin.GuiMixin, pp2e_laj.gui.tools.guimaker.GuiMakerWindowMenu): """(Tkinter) User interface for memorable passwords application.""" def clear(self): """Clear all the candidate passwords.""" self._candidates = [] self.refreshCandidates() def generate(self): """Generates a set of candidate passwords.""" for i in range(0, 8): self._candidates.append(self._generator.next()) self.refreshCandidates() def help(self): pp2e_laj.gui.tools.guimaker.GuiMakerWindowMenu.help(self) def makeWidgets(self): middle = Frame(self) middle.pack(expand=YES, fill=BOTH) Label(middle, text='Candidate Passwords').grid(row=0, column=0, sticky=NSEW) self.candidatesView = ScrolledText(middle, height=15, width=45) self.candidatesView.config(font=('courier', 10, 'normal')) self.candidatesView.grid(row=1, column=0, sticky=NSEW) Label(middle, text='Try It!').grid(row=0, column=1, sticky=NSEW) self.scratchPadView = ScrolledText(middle, height=15, width=45) self.scratchPadView.config(font=('courier', 10, 'normal')) self.scratchPadView.grid(row=1, column=1, sticky=NSEW) def refreshCandidates(self): self.candidatesView.delete('1.0', END) for word in self._candidates: self.candidatesView.insert(END, word + '\n') def start(self): """Initialize the menu bar and tool bar of the application.""" self._candidates = [] self._generator = mem_pwds.MemorablePwds.MemorablePwds() self.menuBar = [ ('File', 0, [('New', 0, self.clear), ('Exit', 0, sys.exit)]), ('Edit', 0, [('Generate', 0, self.generate)]), ] self.toolBar = [ ('Generate', self.generate, {'side': LEFT}), ('Clear', self.clear, {'side': LEFT}), ]
class GuiShuffler(shuffle.Shuffler): def __init__(self): shuffle.Shuffler.__init__(self, 20, 10, 2) self.frmMain = Tk() self.blockStr = StringVar() self.blockSizeStr = StringVar() self.groupStr = StringVar() self.results = ScrolledText(self.frmMain) self.blockStr.set(str(self.blocks)) self.blockSizeStr.set(str(self.blockSize)) self.groupStr.set(str(self.groups)) Label(self.frmMain, text="Blocks").grid(row=0, sticky=E) blockEntry = Entry(self.frmMain, textvariable=self.blockStr) blockEntry.grid(column=1, row=0) Label(self.frmMain, text="Block Size").grid(row=1, sticky=E) blockSizeEntry = Entry(self.frmMain, textvariable=self.blockSizeStr) blockSizeEntry.grid(column=1, row=1) Label(self.frmMain, text="Groups").grid(row=2, sticky=E) groupEntry = Entry(self.frmMain, textvariable=self.groupStr) groupEntry.grid(column=1, row=2) self.results.grid(columnspan=2, row=3, sticky=W+E) genBtn = Button(self.frmMain, text="Generate", command=self.generate, anchor=SE) genBtn.grid(columnspan=2, row=4, sticky=S) def generate(self): try: self.blocks = int(self.blockStr.get()) self.blockSize = int(self.blockSizeStr.get()) self.groups = int(self.groupStr.get()) except ValueError: tkMessageBox.showwarning("Not a Number", "All values must be numbers.\n") return if not self.is_valid_group_size(): tkMessageBox.showwarning("Group Size", "Block Size must be evenly divisible by groups to get an even grouping.\n") else: self.results.delete(1.0, END) # clear previous entries self.print_results(self.results) def print_results(self, results): for i in range(self.blocks): results.insert(END, ' '.join([str(i) for i in self.shuffle()])) results.insert(END, "\n") def run(self): self.frmMain.mainloop()
class Run_UI: def __init__(self,root): #creating the title and window dimensions root.iconbitmap('Images\img.ico') root.title("Never Miss Class") root.maxsize(width=450,height=300) root.minsize(width=450,height=300) centre_screen(root,225,150) #creating a canvas to place widgets on self.main_canvas = Canvas(root,width = 450, height =300,highlightthickness=0) self.main_canvas.pack() self.text_field = ScrolledText(self.main_canvas,width=52,height=18) #You have to set the state to normal to make changes to it. Disabling it makes it uneditable self.text_field.configure(state='normal') #deleting anything previously in the text field self.text_field.delete(1.0,END) #putting stuff in the text field. Works just like appending onto a list. self.text_field.insert(END, "The program is now running in the background. \n") #open the current day's database file today = datetime.datetime.now().weekday() weekdays = {0:"Monday",1:"Tuesday",2:"Wednesday",3:"Thursday",4:"Friday"} f = open(weekdays[today]+".txt", "r") classes = [] for line in f: classes.append(line.strip("\n").split("|")) f.close() # sort the 2d list by class times, and sort the class names and URLs # in the same way so the times and names stay together insert_sort(classes[1], classes[0], classes[2]) # set up default names for any classes the user has not named for i in range(len(classes[2])): if classes[2][i] == "": classes[2][i] = "Class " + str(i) # print out the sorted schedule self.text_field.insert(END, "Here is "+weekdays[today]+"'s schedule: \n") self.text_field.insert(END, ("{0:25}{1:>10}").format("Class Name", "Class Time \n")) self.text_field.insert(END, "-" * 35 + "\n") # iterate through the list of URLs for i in range(len(classes[0])): # for every non-empty url, print the associated name and date of the class if classes[0][i] != "": self.text_field.insert(END, ("{0:25}{1:>10}").format(classes[2][i], classes[1][i] + "\n")) # disable the text field after writing to it self.text_field.configure(state='disabled') self.text_field.place(x=5,y=5)
class Updates(): """ обновление программы """ def __init__(self,app): self.app=app self.win=Frame(self.app.win) self.check_b=Button(self.win,text='Проверить доступные обновления',style='mini2.TButton',image=self.app.app.app.img['check'],compound='left',command=self.update_list) self.check_b.grid(row=0,column=0,padx=5,pady=5,sticky=N) self.txt=ScrolledText(self.win,width=85,height=10,font=('normal',10)) self.txt.grid(row=1,column=0,sticky=N,padx=30) self.down_but=Button(self.win,text='Загрузить обновления',image=self.app.app.app.img['download'],compound='left',style='mini2.TButton',state='disable',command=self.download_updates) self.down_but.grid(row=2,column=0,pady=5) def update_list(self): """ загружаем список доступных обновлений """ serv=self.app.app.app.sets.sync_server try:last=int(self.app.app.app.sets.last_update) except:last=0 self.check_b['state']='disable' self.txt.delete(0.0,END) self.txt.insert(END,'Выполняется проверка обновлений...\n') self.win.update() data={} data['data']=str(last) try: resp=urllib.urlopen(serv+'/updates',urllib.urlencode(data)).read() resp=eval(resp) except Exception,x: self.txt.insert(END,'Не удалось подключиться к серверу обновлений :(') self.win.update() self.check_b['state']='normal' return if len(resp)==0: self.txt.insert(END,'Новых обновлений не найдено!') self.win.update() self.check_b['state']='normal' return self.txt.delete(0.0,END) for x in resp: self.txt.insert(END,'Обновление от %s.\n%s\n\n'%(int2date(x[0]),x[1].encode('utf-8'))) self.resp=resp self.down_but['state']='normal'
class aAbout(tkSimpleDialog.Dialog): """ The application's about box """ def __init__(self, master=None): tkSimpleDialog.Dialog.__init__(self, master) def buttonbox(self): # Stolen from tkSimpleDialog.py # add standard button box. override if you don't want the # standard buttons box = Tk.Frame(self) w = Tk.Button(box, text="OK", width=10) w.pack(side=Tk.RIGHT, padx=5, pady=5) self.bind("<Return>", self.ok) box.pack(side=Tk.BOTTOM, fill=X) def body(self, master): self.resizable(0, 0) self.catIconImage = Tk.PhotoImage(file=GIFFILE) # statt file= self.catIcon = Tk.Label(master, image=self.catIconImage) self.catIcon.pack(side=Tk.TOP) label = Tk.Label(master, text=crnotice1) label.pack(side=Tk.TOP) font = "Helvetica " + TITLEFONTSIZE label = Tk.Label(master, font=font, text=crnotice2, justify=Tk.CENTER) label.pack(side=Tk.TOP) color = 'green' font = "Helvetica " + AXISFONTSIZE self.infoText = ScrolledText( master, relief=Tk.FLAT, padx=3, pady=3, background=color, #foreground="black", wrap='word', width=60, height=12, font=font) self.infoText.pack(expand=0, fill=X, side=Tk.BOTTOM) self.infoText.delete('0.0', Tk.END) self.infoText.insert('0.0', getLicense()) self.infoText.configure(state=Tk.DISABLED) self.title("STARS - About") def ok(self): print 'ok'
class aAbout(tkSimpleDialog.Dialog): """ The application's about box """ def __init__(self, master=None): tkSimpleDialog.Dialog.__init__(self, master) def buttonbox(self): # Stolen from tkSimpleDialog.py # add standard button box. override if you don't want the # standard buttons box = Tk.Frame(self) w = Tk.Button(box, text="OK", width=10) w.pack(side=Tk.RIGHT, padx=5, pady=5) self.bind("<Return>", self.ok) box.pack(side=Tk.BOTTOM,fill=X) def body(self, master): self.resizable(0,0) self.catIconImage = Tk.PhotoImage(file=GIFFILE) # statt file= self.catIcon = Tk.Label(master, image=self.catIconImage) self.catIcon.pack(side=Tk.TOP) label = Tk.Label(master, text=crnotice1) label.pack(side=Tk.TOP) font = "Helvetica "+TITLEFONTSIZE label = Tk.Label(master, font=font, text=crnotice2, justify=Tk.CENTER) label.pack(side=Tk.TOP) color = 'green' font = "Helvetica "+AXISFONTSIZE self.infoText = ScrolledText(master, relief=Tk.FLAT, padx=3, pady=3, background=color, #foreground="black", wrap='word', width=60, height=12, font=font) self.infoText.pack(expand=0, fill=X, side=Tk.BOTTOM) self.infoText.delete('0.0', Tk.END) self.infoText.insert('0.0', getLicense()) self.infoText.configure(state=Tk.DISABLED) self.title("STARS - About") def ok(self): print 'ok'
class Licensing( Frame ): BUTTON_TEXT = "Copy to clipboard" def __init__( self, master ): Frame.__init__( self, master ) COMPOSITOR.register_view( self ) self._setup_view() self.on_model_updated( COMPOSITOR.OTHER_UPDATED ) def _setup_view( self ): self.rowconfigure( 0, weight = 1 ) self.columnconfigure( 0, weight = 1 ) self.license_box = ScrolledText( self, state = DISABLED ) self.license_box.grid( row = 0, column = 0, sticky = W + E + N + S, padx = 5, pady = 5 ) self.clipboard_button = Button( self, text = self.BUTTON_TEXT, command = self._on_copy_pressed ) self.clipboard_button.grid( row = 1, column = 0, sticky = N + E ) def _on_copy_pressed( self ): self.license_box.clipboard_clear() self.license_box.clipboard_append( self.license_box.get( '0.0', END ) ) self.clipboard_button.configure( text = "Copied!", state = DISABLED ) self.after( 2500, lambda: self.clipboard_button.configure( text = self.BUTTON_TEXT, state = NORMAL ) ) def on_model_updated( self, reason ): if reason not in [COMPOSITOR.OTHER_UPDATED, COMPOSITOR.SELECTED_TYPE_CHANGED, COMPOSITOR.LAYER_ADDED, COMPOSITOR.LAYER_REMOVED, COMPOSITOR.SHEET_SELECTED, COMPOSITOR.LAYER_ORDER_CHANGED]: return # The compositor changed state, so make sure we're up to date, too. self.license_box.configure( state = NORMAL ) # clear the existing text self.license_box.delete( 1.0, END ) sheets = COMPOSITOR.get_selected_sheets().values() license_text = LICENSING.get_formatted_licensing( sheets ) self.license_box.insert( END, license_text ) self.license_box.configure( state = DISABLED ) def destroy( self ): COMPOSITOR.deregister_view( self ) Frame.destroy( self )
class StringViewer(Frame): def __init__(self, parent, get_func, title=None): Frame.__init__(self,parent) self.text = ScrolledText(parent) self.text.pack(fill=BOTH,expand="yes") self.prev = get_func() self.text.insert(END,self.prev) self.after(1000, self.poll) self.get_func=get_func parent.wm_title(title) def poll(self): str = self.get_func() if not str == self.prev: self.text.delete("1.0", END) self.text.insert(END, self.get_func()) self.text.see(END) self.after(1000,self.poll)
class StringViewer(Frame): def __init__(self, parent, get_func, title=None): Frame.__init__(self, parent) self.text = ScrolledText(parent) self.text.pack(fill=BOTH, expand="yes") self.prev = get_func() self.text.insert(END, self.prev) self.after(1000, self.poll) self.get_func = get_func parent.wm_title(title) def poll(self): str = self.get_func() if not str == self.prev: self.text.delete("1.0", END) self.text.insert(END, self.get_func()) self.text.see(END) self.after(1000, self.poll)
class Credits(tkSimpleDialog.Dialog): def body(self, master): self.image = Tk.PhotoImage(file=GIFFILE) self.icon = Tk.Label(master, image=self.image) self.icon.pack(side=Tk.TOP) label = Tk.Label(master, text= crnotice1) label.pack(side=Tk.TOP) font = "Helvetica "+TITLEFONTSIZE label = Tk.Label(master, font=font,text= "Credits", justify=Tk.CENTER, foreground='blue') label.pack(side=Tk.TOP) font = "Helvetica "+AXISFONTSIZE self.infoText = ScrolledText(master, relief=Tk.FLAT, padx=3, pady=3, background='white', foreground="blue", wrap='word', width=70, height=12, font=font, tabs=("4c")) self.infoText.pack(expand=0, fill=Tk.X, side=Tk.BOTTOM) self.infoText.delete('0.0', Tk.END) self.infoText.insert('0.0', getCredits()) self.infoText.configure(state=Tk.DISABLED)
class Application(tk.Frame): def __init__(self, master=None): tk.Frame.__init__(self, master) self.pack() self.createWidgets() def __del__(self): pass def createWidgets(self): self.contentDest = tk.StringVar() self.contentDest.set(u'随意写个用户名') self.entryDest = tk.Entry(self, width=60) self.entryDest["textvariable"] = self.contentDest self.entryDest.grid(row=0) self.entryDest.focus() self.entryDest.bind('<Return>', lambda event: self.start()) self.buttonStart = tk.Button(self, text='生成序列号', width=25) self.buttonStart['command'] = self.start self.buttonStart['fg'] = 'black' self.buttonStart.grid(row=1) self.text = ScrolledText(self, font=('Courier New', 13), fg='green', bg='black', width=50) self.text.grid(row=2, columnspan=1) def start(self): self.running = True self.td = threading.Thread(target=self.gen_key) self.td.setDaemon(True) self.td.start() def get_md5(self, src_txt): m = hashlib.md5() try: src_txt = src_txt.encode("utf-8") except: pass m.update(src_txt) return m.hexdigest() def gen_key(self): try: self.text.delete(0.0, "end") name = self.contentDest.get() self.text.insert("end", u"注册名:【%s】\n" % name) salt = str(randint(10000, 30000)) self.text.insert("end", u"盐 值:【%s】\n" % salt) salted_text = u"ax5{}b52w{}vb3".format(name, salt) self.text.insert("end", u"盐混淆:【%s】\n" % salted_text) hashed_text = self.get_md5(salted_text) self.text.insert("end", u"哈希值:【%s】\n" % hashed_text) result_key = u"{}{}{}".format(hashed_text[:4], salt, hashed_text[4:]) self.text.insert("end", u"序列号:【%s】\n" % result_key) self.text.insert("end", (u"^-^成功生成^-^\n" u"请复制注册名和序列号进行软件激活:" u"菜单栏->HELP->Register->输入激活")) except Exception as e: self.text.insert("end", u'生成失败,请填写英文名重新生成')
class TkTCPWatch(Tkinter.Frame): '''The tcpwatch top-level window. ''' def __init__(self, master): Tkinter.Frame.__init__(self, master) self.createWidgets() # connections maps ids to TkConnectionObservers. self.connections = {} self.showingid = '' self.queue = Queue() self.processQueue() def createWidgets(self): listframe = Tkinter.Frame(self) listframe.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) scrollbar = Tkinter.Scrollbar(listframe, orient=Tkinter.VERTICAL) self.connectlist = Tkinter.Listbox(listframe, yscrollcommand=scrollbar.set, exportselection=0) scrollbar.config(command=self.connectlist.yview) scrollbar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y) self.connectlist.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) self.connectlist.bind('<Button-1>', self.mouseListSelect) self.textbox = ScrolledText(self, background="#ffffff") self.textbox.tag_config("message", foreground="#000000") self.textbox.tag_config("client", foreground="#007700") self.textbox.tag_config("clientesc", foreground="#007700", background="#dddddd") self.textbox.tag_config("server", foreground="#770000") self.textbox.tag_config("serveresc", foreground="#770000", background="#dddddd") self.textbox.insert(Tkinter.END, startup_text, "message") self.textbox.pack(side='right', fill=Tkinter.BOTH, expand=1) self.pack(fill=Tkinter.BOTH, expand=1) def addConnection(self, id, conn): self.connections[id] = conn connectlist = self.connectlist connectlist.insert(Tkinter.END, id) def updateConnection(self, id, output): if id == self.showingid: textbox = self.textbox for data, style in output: textbox.insert(Tkinter.END, data, style) def mouseListSelect(self, event=None): connectlist = self.connectlist idx = connectlist.nearest(event.y) sel = connectlist.get(idx) connections = self.connections if connections.has_key(sel): self.showingid = '' output = connections[sel].getOutput() self.textbox.delete(1.0, Tkinter.END) for data, style in output: self.textbox.insert(Tkinter.END, data, style) self.showingid = sel def processQueue(self): try: if not self.queue.empty(): # Process messages for up to 1/4 second from time import time limit = time() + 0.25 while time() < limit: try: f, args = self.queue.get_nowait() except Empty: break f(*args) finally: self.master.after(50, self.processQueue)
class Window(ttk.Frame): def __init__(self, parent): self.tab_delim = "\n=====++++++=====\n" self.tabs = [] self.dirty = False ttk.Frame.__init__(self, parent) self.parent = parent self.parent.title("Very Secret Things") self.style = ttk.Style() self.style.theme_use("default") self.pack(fill=tk.BOTH, expand=1) self.nb = ttk.Notebook(self) self.nb.pack(fill=tk.BOTH, expand=1) self.saveButton = ttk.Button(self, text="Close", command=self.save) self.saveButton.pack(side=tk.RIGHT, padx=5, pady=5) # I don't feel like making a rekey dialog atm #~ rekeyButton = ttk.Button(self, text="Re-Key", command=self.rekey) #~ rekeyButton.pack(side=tk.RIGHT, padx=5, pady=5) addButton = ttk.Button(self, text="Add Tab", command=self.add_tab) addButton.pack(side=tk.LEFT, padx=5, pady=5) delButton = ttk.Button(self, text="Delete Tab", command=self.rem_tab) delButton.pack(side=tk.LEFT, padx=5, pady=5) #add search tab f = ttk.Frame(self.nb) self.search = ttk.Entry(f) self.search.focus() self.search.pack(fill=tk.BOTH) self.search.bind("<KeyRelease>", self.search_key_press) self.search_result = ScrolledText(f, relief=tk.RAISED, wrap=tk.WORD, state=tk.DISABLED) self.search_result.pack(fill=tk.BOTH, expand=1) self.nb.add(f, text='search') #add other tabs for text in self.parent.secret.split(self.tab_delim): self.add_tab(text, dirty=False) self.nb.select(self.nb.tabs()[0]) #select search tab def search_key_press(self, key): '''if search key is found displays that line and all lines below it until an empty line is reached.''' search = self.search.get() found = [] state = None for line in self.parent.secret.splitlines(): if state is None: if search in line.lower(): state = line else: if line.strip() == "": found.append(state) state = None else: state += "\n" + line if state is not None: found.append(state) self.search_result.config(state=tk.NORMAL) self.search_result.delete("0.0", tk.END) self.search_result.insert(tk.INSERT, "\n\n".join(found)) self.search_result.config(state=tk.DISABLED) def save(self): if self.dirty: #file changed self.update(dirty=False) save(self.parent.secret, self.parent.key, self.parent.geometry()) self.quit() def rem_tab(self): tabid = self.nb.select() if self.nb.index(tabid) > 0: #index minus 1 to account for search tab del self.tabs[self.nb.index(tabid) - 1] self.nb.forget(tabid) self.update() def add_tab(self, text='new', dirty=True): f = ttk.Frame(self.nb) # see http://stackoverflow.com/questions/13832720/how-to-attach-a-scrollbar-to-a-text-widget t = ScrolledText(f, relief=tk.RAISED, wrap=tk.WORD) t.insert(tk.INSERT, text) t.pack(fill=tk.BOTH, expand=1) t.bind("<KeyRelease>", self.update) self.nb.add(f) self.tabs.append(t) self.nb.select(self.nb.tabs()[-1]) self.update(dirty=dirty) def update(self, key=None, dirty=True): if dirty and not self.dirty: self.dirty = True self.saveButton.config(text="Save&Close") data = [tab.get('0.0', tk.END).rstrip() for tab in self.tabs] self.parent.secret = self.tab_delim.join(data) #update tab title tabid = self.nb.select() name = data[self.nb.index(tabid) - 1].rstrip().split('\n', 1)[0].strip() self.nb.tab(tabid, text=name or "empty")
class TkTCPWatch (Tkinter.Frame): '''The tcpwatch top-level window. ''' def __init__(self, master): Tkinter.Frame.__init__(self, master) self.createWidgets() # connections maps ids to TkConnectionObservers. self.connections = {} self.showingid = '' self.queue = Queue() self.processQueue() def createWidgets(self): listframe = Tkinter.Frame(self) listframe.pack(side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) scrollbar = Tkinter.Scrollbar(listframe, orient=Tkinter.VERTICAL) self.connectlist = Tkinter.Listbox( listframe, yscrollcommand=scrollbar.set, exportselection=0) scrollbar.config(command=self.connectlist.yview) scrollbar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y) self.connectlist.pack( side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1) self.connectlist.bind('<Button-1>', self.mouseListSelect) self.textbox = ScrolledText(self, background="#ffffff") self.textbox.tag_config("message", foreground="#000000") self.textbox.tag_config("client", foreground="#007700") self.textbox.tag_config( "clientesc", foreground="#007700", background="#dddddd") self.textbox.tag_config("server", foreground="#770000") self.textbox.tag_config( "serveresc", foreground="#770000", background="#dddddd") self.textbox.insert(Tkinter.END, startup_text, "message") self.textbox.pack(side='right', fill=Tkinter.BOTH, expand=1) self.pack(fill=Tkinter.BOTH, expand=1) def addConnection(self, id, conn): self.connections[id] = conn connectlist = self.connectlist connectlist.insert(Tkinter.END, id) def updateConnection(self, id, output): if id == self.showingid: textbox = self.textbox for data, style in output: textbox.insert(Tkinter.END, data, style) def mouseListSelect(self, event=None): connectlist = self.connectlist idx = connectlist.nearest(event.y) sel = connectlist.get(idx) connections = self.connections if connections.has_key(sel): self.showingid = '' output = connections[sel].getOutput() self.textbox.delete(1.0, Tkinter.END) for data, style in output: self.textbox.insert(Tkinter.END, data, style) self.showingid = sel def processQueue(self): try: if not self.queue.empty(): # Process messages for up to 1/4 second from time import time limit = time() + 0.25 while time() < limit: try: f, args = self.queue.get_nowait() except Empty: break f(*args) finally: self.master.after(50, self.processQueue)
class app(): def __init__(self): self.root = Tk() self.root.title("WebScan") self.root.resizable(False, False) self.rr = IntVar() #self.root.geometry("1000x800") self.creat_weaget() ##varible to paues the scan## self.aa = IntVar() self.aa = False self.tt = StringVar self.va = StringVar ###left frame### self.left = Frame(self.root) self.left.grid(row=0, column=0, sticky=W) self.creat_left_weget() ###right frame## self.right = Frame(self.root) self.right.grid(row=0, column=1, sticky=E) self.creat_right_weget() ##progressbar text## self.style = ttk.Style(self.root) self.style.layout('text.Horizontal.TProgressbar', [('Horizontal.Progressbar.trough', { 'children': [('Horizontal.Progressbar.pbar', { 'side': 'left', 'sticky': 'ns' })], 'sticky': 'nswe' }), ('Horizontal.Progressbar.label', { 'sticky': '' })]) self.style.configure('text.Horizontal.TProgressbar', text='') def creat_weaget(self): ##top menu## self.menu_bar = Menu(self.root) self.root.config(menu=self.menu_bar) file_menu = Menu(self.menu_bar, tearoff=0) file_menu.add_command(label="About", command=self.he) self.menu_bar.add_cascade(label="Help", menu=file_menu) conf_menu = Menu(self.menu_bar, tearoff=0) conf_menu.add_command(label="User Agent Spoofing", command=self.con) self.menu_bar.add_cascade(label="Setting", menu=conf_menu) pass def creat_left_weget(self): ###label## label = Label(self.left, text="Entre the target Address") label.grid(row=0, column=0, pady=10, sticky=N) ##entry## self.entry = Entry(self.left) self.entry.grid(row=1, column=0, padx=10, pady=5, sticky=W + E) self.entry.focus() ##radio box## self.r = IntVar() ba_1 = Radiobutton(self.left, variable=self.r, value=1, text="Scan ") ba_1.grid(row=2, column=0, sticky=W) tt.create_ToolTip(ba_1, 'Only Scant the target Site') ba_2 = Radiobutton(self.left, variable=self.r, value=2, text="Spider") ba_2.grid(row=2, column=0, sticky=E) tt.create_ToolTip(ba_2, 'Spider the target site') ##submit batton## self.submit = Button(self.left, text="Start Scan", command=self.th) self.submit.grid(row=3, column=0, padx=10, pady=5, sticky=W) ##paus button## self.stop = Button(self.left, text="Pause Scan", command=self.st) self.stop.grid(row=4, column=0, padx=10, pady=5, sticky=W + E) self.stop.config(state='disabled') ##exit button## self.exit = Button(self.left, text="Exit", command=self.exe) self.exit.grid(row=3, column=0, padx=10, pady=5, sticky=E) ##progress bar## self.progre = ttk.Progressbar(self.left, style='text.Horizontal.TProgressbar', length=200, mode='determinate') self.progre.grid(row=5, column=0, padx=10) self.progre["maximum"] = 100 self.progre["value"] = 0 ##scrollbar## self.scroll = Scrollbar(self.left) self.scroll.grid(row=6, column=0, rowspan=5, sticky=N + E + S) xscrollbar = Scrollbar(self.left, orient=HORIZONTAL) xscrollbar.grid(row=13, column=0, sticky=E + W) ###listbox## self.list = Listbox(self.left, width=10, height=20, yscrollcommand=self.scroll.set, xscrollcommand=xscrollbar.set) self.list.grid(row=6, column=0, sticky=W + E + N + S, columnspan=1, rowspan=5, pady=5, padx=10) xscrollbar.config(command=self.list.xview) pass def creat_right_weget(self): ##textpt## self.script = Button(self.right, text="Scrip", command=self.script) self.script.grid(row=1, column=1, pady=5, sticky=W + E) tt.create_ToolTip(self.script, 'Search for scripts in Seleted Site') self.script.config(state='disabled') ##comments## self.comments = Button(self.right, text="Comments", command=self.comment) self.comments.grid(row=1, column=2, pady=5, sticky=W + E) self.comments.config(state='disabled') tt.create_ToolTip(self.comments, 'Search for Comments in Seleted Site') ##Vulnerabilites## self.vul = Button(self.right, text="Vulnerabilites", command=self.vul_2) self.vul.grid(row=1, column=3, pady=5, sticky=W + E) self.vul.config(state='disabled') tt.create_ToolTip(self.vul, 'Scan passively for Vulnerabilites in Seleted Site') ##response header## self.response = Button(self.right, text="Response", command=self.head_2) self.response.grid(row=1, column=4, pady=5, sticky=W + E) self.response.config(state='disabled') tt.create_ToolTip(self.response, 'Print Response header for Seleted Site') ##request header## self.request = Button(self.right, text="Request", command=self.req_2) self.request.grid(row=1, column=5, pady=5, sticky=W + E) self.request.config(state='disabled') tt.create_ToolTip(self.request, 'Print Request header for textpts in Seleted Site') ##scrolltest## xscrollbar = Scrollbar(self.right, orient=HORIZONTAL) xscrollbar.grid(row=3, column=1, columnspan=6, sticky=E + W) self.text = ScrolledText(self.right, height=30, state='disabled', wrap=NONE, xscrollcommand=xscrollbar.set) self.text.grid(row=2, column=1, columnspan=6, padx=10, pady=5, sticky=W + E) xscrollbar.config(command=self.text.xview) pass def st(self): if self.aa == False: self.aa = True self.stop.config(text="resume scan") elif self.aa == True: self.aa = False self.stop.config(text="pause scan") def th(self): if self.entry.get(): if self.r.get(): print self.r.get() self.t1 = threading.Thread(target=self.rev, args=[]) self.t1.setDaemon(True) self.t1.start() #self.t2 = threading.Thread(target=self.status, args=[]) #self.t2.start() else: messagebox.showerror("Error", "First Select the Attack Mode") else: messagebox.showerror("Error", "First Entre the target site") ##callback function for exit button## def exe(self): self.root.destroy() ##callback function for help menu## def he(self): help = mes.message() self.text.config(state='normal') #help="This is python based tool which crowl the target web site and print scripts and comments present at the target web page. " self.text.insert(END, help) self.text.config(state='disabled') ##call back function for seting menu bar## def con(self): self.top = Toplevel() self.top.title("User Agents") self.top.geometry("200x150") self.top.resizable(False, False) ba_1 = Radiobutton(self.top, variable=self.rr, value=1, text="Chrome on Windows 8.1") ba_1.grid(row=0, column=0, sticky=W) tt.create_ToolTip( ba_1, 'User-Agent : Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36' ) ba_2 = Radiobutton(self.top, variable=self.rr, value=2, text="Safari on iOS") ba_2.grid(row=1, column=0, sticky=W) tt.create_ToolTip( ba_2, 'User-Agent : Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4' ) ba_3 = Radiobutton(self.top, variable=self.rr, value=3, text="IE6 on Windows XP") ba_3.grid(row=2, column=0, sticky=W) tt.create_ToolTip( ba_3, 'User-Agent : Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)' ) ba_4 = Radiobutton(self.top, variable=self.rr, value=4, text="Googlebot") ba_4.grid(row=3, column=0, sticky=W) tt.create_ToolTip( ba_4, 'User-Agent : Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' ) bb = Button(self.top, text="Exit", command=self.top.destroy) bb.grid(row=4, column=0) ##callback function for submitt button## def _mess(self): messagebox.showerror("Error", "First Select the target from listbox") ##print the textpts## def comment(self): click_item = self.list.curselection() self.text.config(state='normal') if click_item: self.text.delete(1.0, END) t = self.list.get(click_item) tt = str(comm[t]) self.text.insert(END, tt) else: self._mess() self.text.config(state='disabled') def script(self): click_item = self.list.curselection() self.text.config(state='normal') if click_item: self.text.delete(1.0, END) t = self.list.get(click_item) self.tt = (sc[t]) self.text.insert(END, self.tt) else: self._mess() self.text.config(state='disabled') ##print the request headers## def req_2(self): click_item = self.list.curselection() self.text.config(state='normal') if click_item: self.text.delete(1.0, END) self.text.insert(END, "GET\t") self.text.insert(END, self.list.get(click_item)) t = self.list.get(click_item) tt = req[t] for ta in tt: pa = ta + "\t\t" + ":" + tt[ta] + "\n" self.text.insert(END, pa, 'rehead') else: self._mess() self.text.config(state='disabled') self.text.tag_config('rehead', foreground='red') ##print the response## def head_2(self): click_item = self.list.curselection() self.text.config(state='normal') if click_item: self.text.delete(1.0, END) statue = str(resp[self.list.get(click_item)]) + "\n" self.text.insert(END, statue, 'statue') t = self.list.get(click_item) tt = head[t] for ta in tt: pa = ta + "\t\t" + ":" + tt[ta] + "\n" self.text.insert(END, pa, 'head') self.text.insert(END, "\n") la = res[self.list.get(click_item)] #print la self.text.insert(END, la, 'body') else: self._mess() self.text.tag_config('statue', foreground='blue') self.text.tag_config('head', foreground='red') self.text.tag_config('body', foreground='green') self.text.config(state='disabled') ##scan for vulnerabilites## def vul_2(self): click_item = self.list.curselection() self.text.config(state='normal') if click_item: self.text.delete(1.0, END) t = self.list.get(click_item) tt = head[t] try: xssprotect = tt['X-XSS-Protection'] if xssprotect != '1; mode=block': self.text.insert( END, '\nX-XSS-Protection not set properly, XSS may be possible:' ) except: self.text.insert( END, '\nX-XSS-Protection not set, XSS may be possible') try: contenttype = tt['X-Content-Type-Options'] if contenttype != 'nosniff': self.text.insert( END, '\nX-Content-Type-Options not set properly:') except: self.text.insert(END, '\nX-Content-Type-Options not set') try: hsts = tt['Strict-Transport-Security'] except: self.text.insert( END, '\nHSTS header not set, MITM attacks may be possible') try: csp = tt['Content-Security-Policy'] self.text.insert(END, '\nContent-Security-Policy set:') except: self.text.insert(END, '\nContent-Security-Policy missing') try: click = tt['x-frame-options'] except: self.text.insert( END, "\nX-Frame-Options Header is not set, Clickjacking may be possible\n" ) self.text.insert(END, "\nCookie Information\n", 'title') self.text.tag_config('title', foreground='blue') for cookie in sop[t].cookies: name = str(cookie.name) self.text.insert(END, 'Name :', 'nam') self.text.insert(END, name + '\n', 'value') self.text.insert(END, 'Value :', 'nam') self.text.insert(END, cookie.value + '\n', 'value') if not cookie.secure: cookie.secure = "False" self.text.insert(END, 'Secure :', 'nam') self.text.insert(END, cookie.secure + '\n', 'value') if 'httponly' in cookie._rest.keys(): cookie.httponly = 'True' else: cookie.httponly = 'False' self.text.insert(END, 'HTTPOnly :', 'nam') self.text.insert(END, cookie.httponly + '\n', 'value') if cookie.domain_initial_dot: cookie.domain_initial_dot = 'True' self.text.insert(END, 'Cookie Scope to parent domain :', 'nam') self.text.insert(END, str(cookie.domain_initial_dot) + '\n', 'value') self.text.insert(END, "-------------------------------\n", 'new') self.text.tag_config('nam', foreground='red') self.text.tag_config('value', foreground='green') self.text.tag_config('new', foreground='orange') else: self._mess() self.text.config(state='disabled') def rev(self): self.text.config(state='normal') self.text.delete(1.0, END) self.text.config(state='disabled') self.menu_bar.entryconfig("Help", state='disabled') self.menu_bar.entryconfig("Setting", state='disabled') self.script.config(state='normal') self.comments.config(state='normal') self.request.config(state='normal') self.response.config(state='normal') self.vul.config(state='normal') self.stop.config(state='normal') self.submit.config(state='disabled') self.entry.config(state='disabled') if self.rr.get() == 1: headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36' } elif self.rr.get() == 2: headers = { 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4' } elif self.rr.get() == 3: headers = { 'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)' } elif self.rr.get() == 4: headers = { 'User-Agent': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' } else: headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36' } print "user agent" + str(self.rr.get()) content = self.entry.get() if (content[:4] == "http") or (content[:5] == "https"): L.put(content) else: content = "https://" + content L.put(content) print self.entry.get() while (L.qsize()): ##start progress bar## self.progre.start() self.style.configure("text.Horizontal.TProgressbar", text="Scan is running") ##pause the scan## print self.aa while (self.aa): self.progre.stop() self.style.configure("text.Horizontal.TProgressbar", text="Scan Paused") #print("scan stop") trurl = L.get() ##check target is previsely scaned or not## if trurl in duplic: continue else: duplic.add(str(trurl)) ## check target address is correct or not## try: response = requests.get(trurl, headers=headers) except: self.text.delete(1.0, END) self.progre.stop() #self.text.insert(END,"Please Entre Valid Address") messagebox.showerror("Error", "Please Entre Valid Address") break ##insert the scaned links in the list box## self.list.insert(END, trurl) resp[trurl] = response head[trurl] = response.headers # storing response the headers req[trurl] = response.request.headers #storing request headers com = " " sc[trurl] = com ##finding the scripts## soup = BeautifulSoup(response.content, "lxml") for line in soup.find_all('script'): for r in line.text.split(">"): #print r+"\n" sc[trurl] += (r) + "\n" ##finding the comments## aa = re.compile("\n") a = aa.sub(" ", response.text) comments = re.findall(r'[^>]<!--(.*?)-->', a) sop[trurl] = response if comments: com = " " comm[trurl] = com for c in comments: comm[trurl] += "\n" + com + str(c) else: comm[trurl] = "Comments not avaliable" #tt=str(sc[click_item] #print soup.prettify() res[trurl] = soup.prettify() #response.text #storing response if (self.r.get() == 2): for line in soup.find_all('a'): newline = line.get('href') print newline try: if newline[:4] == "http" or newline[:5] == "https": #count up to four digits if trurl in newline: L.put(newline) #print L.qsize() elif newline[:1] == "/": combine = trurl + newline L.put(combine) #print L.qsize() #print combine elif newline[:1] != "/": combine = trurl + "/" + newline L.put(combine) except: print "Error" elif (self.r.get() == 1): L.empty() self.progre.stop() self.style.configure("text.Horizontal.TProgressbar", text="Scan is completed") self.progre['value'] = 200 self.submit.config(state='normal') self.entry.config(state='normal') self.entry.delete(0, 'end') self.stop.config(state='disabled') self.menu_bar.entryconfig("Help", state='normal') self.menu_bar.entryconfig("Setting", state='normal')
class myPanel(tkinter.Tk): def __init__(self): tkinter.Tk.__init__(self, 'lsx') try: self.ss = self.clipboard_get() except: self.ss = '' self.cnt = 0 self.slices = paragraph(self.ss, qrlen) self.string = None if not os.path.exists('config.ini'): x = - 100 + 0.2 * self.winfo_screenwidth() # 100: 补偿初始Tk界面为200x200 y = - 100 + 0.7 * self.winfo_screenheight() xy = '+%d+%d'%(x,y) with open('config.ini','w') as f: f.write(xy) with open('config.ini','r') as f: xy = f.read() self.geometry(xy) self.minsize(450,206) self.qrc = tkinter.Label(self) self.ent = ScrolledText(self, width=1, height=15) self.ent.insert(1.0, self.ss) self.ent.mark_set('insert','0.0') # 程序首次运行时不使用see函数,否则会有未知原因半行内容沉没在Text窗体上面一点点 self.ent.focus() text = self.slices[self.cnt] basic = (len(self.slices),len(self.ss)) info = 'Page: %s, Length: %s'%basic if zh_cn: info = '共%s页, %s字'%basic self.withdraw() # withdraw/deiconify 阻止页面闪烁 self.update_idletasks() self.ent.pack(padx=2, pady=2, fill='both', expand=True, side='right') # RIGHT为了在Label隐藏再显示后所在位置一致 self.qrc.pack() self.setQrcode(text, info) self.deiconify() self.qrc.bind('<Button-2>',self.onExit) self.qrc.bind('<Button-1>',self.fliping) self.qrc.bind('<Button-3>',self.fliping) self.qrc.bind('<Double-Button-1>',self.setting) self.qrc.bind('<Double-ButtonRelease-3>',self.openFile) # 没有Release会在窗口打开之后的鼠标抬起时唤起右键菜单 self.ent.bind('<Escape>',self.onExit) self.ent.bind('<F1>',self.openFile) self.ent.bind('<F2>',self.fliping) self.ent.bind('<F3>',self.fliping) self.ent.bind('<F4>',self.setting) self.ent.bind('<KeyRelease>',self.refresh) self.ent.bind('<ButtonRelease-1>',self.selected) self.bind('<Destroy>',lambda evt:self.onExit(evt,close=True)) def setQrcode(self, string, info): if self.string != string: self.string = string if string == '': self.qrc.forget() else: global img img = qrmake(string) self.qrc.config(image=img) self.qrc.pack() log(string, info) self.title('Text Helper v1.06 (%s)'%info) if zh_cn: self.title('文本助手v1.06 (%s)'%info) def refresh(self, evt): if evt.keysym in ['Control_L', 'Return', 'BackSpace']: ss2 = self.ent.get('0.0', 'end')[:-1] if self.ss != ss2: self.ss = ss2 self.cnt = 0 self.slices = paragraph(self.ss, qrlen) text = self.slices[self.cnt] basic = (len(self.slices),len(self.ss)) info = 'Page: %s, Length: %s'%basic if zh_cn: info = '共%s页, %s字'%basic self.setQrcode(text, info) def fliping(self, evt): if evt.num == 1 or evt.keysym == 'F3': self.cnt = min(self.cnt+1,len(self.slices)-1) else: self.cnt = max(self.cnt-1,0) cur1 = getIndex(''.join(self.slices[:self.cnt])) cur2 = getIndex(''.join(self.slices[:self.cnt+1])) self.setCursor(cur1, cur2) text = self.slices[self.cnt] basic = (self.cnt+1,len(self.slices),len(text),len(self.ss)) info = 'Page: %s/%s, Sel: %s/%s'%basic if zh_cn: info = '第%s/%s页, 共%s/%s字'%basic self.setQrcode(text, info) def selected(self, evt): if self.ent.tag_ranges('sel'): text = self.ent.selection_get() info = 'Sel: %s/%s'%(len(text),len(self.ss)) if zh_cn: info = '选中%s/%s字'%(len(text),len(self.ss)) self.setQrcode(text, info) def setCursor(self, cur1, cur2): self.ent.mark_set('insert', cur1) self.ent.tag_remove('sel','0.0','end') self.ent.tag_add('sel',cur1,cur2) self.ent.see(cur1) def setting(self, evt): max_page = len(self.slices) num = tkinter.simpledialog.askinteger('Goto','Go to page (1-%s):'%max_page, initialvalue=self.cnt+1) self.ent.focus() if num: self.cnt = max(1,min(max_page,num)) - 1 text = self.slices[self.cnt] basic = (self.cnt+1,len(self.slices),len(text),len(self.ss)) info = 'Page: %s/%s, Sel: %s/%s'%basic if zh_cn: info = '第%s/%s页, 共%s/%s字'%basic self.setQrcode(text, info) def openFile(self, evt): path = tkinter.filedialog.askopenfilename() if path != '': filename = os.path.basename(path) with open(path,'rb') as f: s = f.read() try: try: res = s.decode() except: try: res = s.decode('gbk') except: raise except: s = base64.urlsafe_b64encode(filename.encode()+b'\n'+s).decode() total = int((len(s)-1)/(qrlen-10)+1) res = '' for i in range(total): res += '%04d%04d.%s,'%(total, i+1, s[(qrlen-10)*i:(qrlen-10)*(i+1)]) self.ss = res self.cnt = 0 self.slices = paragraph(self.ss, qrlen) self.ent.delete(1.0, 'end') self.ent.insert(1.0, res) text = self.slices[self.cnt] basic = (len(self.slices),len(self.ss)) info = 'Page: %s, Length: %s'%basic if zh_cn: info = '共%s页, %s字'%basic self.setQrcode(text, info) def onExit(self, evt, close=False): xy = '+%d+%d'%(self.winfo_x(),self.winfo_y()) with open('config.ini','w') as f: f.write(xy) if not close: self.destroy()
class App(object): def __init__(self): self.root = tki.Tk() self.root.geometry("300x200") # does xpath var exist? def isValidXml(xml, xpathString): r = xml.xpath(xpathString) if( len(r) > 0): return True return False try: with open ("config.xml","r") as myfile: data=myfile.read() rxml = etree.fromstring(data) # url base required! isValidXml(rxml, "//root/urlBase") if( isValidXml(rxml, "//root/urlBase") == False): print "url not set in config file. Exiting..." sys.exit(2) self.url = rxml.xpath("//root/urlBase")[0].text except: print "unable to load config. Exiting..." sys.exit(1) # id search bar bbar = tki.Frame(self.root) bbar.pack(fill=tki.X) l1 = tki.Label(bbar,text=u"ID:") l1.pack(side="left") self.mridVar = tki.StringVar() self.mrid = tki.Entry(bbar,textvariable=self.mridVar) self.mrid.pack(side="left",expand=1,fill=tki.BOTH) # load default mrid if set in file if( isValidXml(rxml, "//root/defaultMrid") ): mridDefault = rxml.xpath("//root/defaultMrid")[0].text self.mridVar.set(mridDefault) # create a Text widget with a Scrollbar attached self.txt = ScrolledText(self.root, undo=True, width=1,height=1) self.txt['font'] = ('courrier', '8') #self.txt['font'] = ('consolas', '12') self.txt.pack(fill="both",expand=1) # get and exit buttons bbar = tki.Frame(self.root) bbar.pack(fill="x") b1 = tki.Button(bbar,text=u"Get Order",command=self.getOrder) b1.pack(side="left",fill="x",expand=1) b2 = tki.Button(bbar,text=u"Exit",command=self.exitButtonClicked) b2.pack(side="left",expand=1,fill="x") # exit program def exitButtonClicked(self): exit(0) # get maint order def getOrder(self): self.txt.insert(tki.INSERT,"Sending...") self.send = subprocess.Popen(["java","-jar", "getServiceOrder.jar", self.url + "ServiceOrdersGet", self.mridVar.get()], stdout=subprocess.PIPE) flags = fcntl(self.send.stdout, F_GETFL) fcntl(self.send.stdout, F_SETFL, flags | O_NONBLOCK) def callback(): try: data = read(self.send.stdout.fileno(), 20) dataOut = data self.txt.delete('1.0',tki.END) while True: if data == '': print dataOut print "calling outputresult" outputResult(dataOut) print "done output" break data = read(self.send.stdout.fileno(), 1024) dataOut += data except OSError: self.txt.insert(tki.END,'.') self.root.after(1000, callback) self.root.after(1000,callback) def outputValue(label, string, xml): searchString = './/*[local-name() = \'' + string + '\']'; r = xml.xpath(searchString) if len(r) > 0: self.txt.insert(tki.END,label + r[0].text + "\n") def xmlExists(string, xml): searchString = './/*[local-name() = \'' + string + '\']'; r = xml.xpath(searchString) if len(r) > 0 : return True; return False; # output address info def outputAddress(doc): addresses = doc.xpath('.//*[local-name() = \'mainAddress\']') for addr in addresses: self.txt.insert(tki.END,"\nAddress:\n") outputValue(" General:", "addressGeneral", addr) outputValue(" Zipcode:", "code", addr) outputValue(" Town:", "name", addr) outputValue(" State:", "stateOrProvince", addr) # output the attachments def outputAttachments(doc): attachments = doc.xpath('.//*[local-name() = \'Attachments\']') for attachment in attachments: self.txt.insert(tki.END,"\nAttachment:\n") outputValue("URL: ", "Url", attachment) outputValue("Description: ", "Description", attachment) outputValue("Comment: ", "Comment", attachment) # print results to text def outputResult(xmlString): try: print xmlString print "about to output ..." doc = etree.fromstring(xmlString) orders = doc.xpath('//*[local-name() = \'ServiceOrder\']') for order in orders: print "in order in orders" outputValue("MRID: ", "mRID", order) outputValue("Kind: ", "kind", order) outputValue("Last Mod: ", "lastModifiedDateTime", order) outputValue("requested: ", "requestedDateTime", order) outputValue("Status: ", "statusKind", order) outputValue("Created: ", "createdDateTime", order) outputValue("Reason: ", "reason", order) outputValue("Severity: ", "severity", order) outputValue("Type: ", "type", order) self.txt.insert(tki.END,"\nInternal Loc:\n") outputValue(" Name: ", "BuildingName", order) outputValue(" Number: ", "BuildingNumber", order) outputValue(" Floor: ", "Floor", order) outputValue(" Room: ", "RoomNumber", order) outputAddress(order) outputAttachments(order) self.txt.insert(tki.END,"\n\n") except Exception, e: print "output error: " + str(e) self.txt.insert(tki.END,"Operation Failed:\n\n" + xmlString)
class App: # Constructor def __init__(self,master): # Create the Menu for the GUI menu = Menu(root) root.config(menu=menu) filemenu = Menu(menu) # File Menu with Load location and exit options menu.add_cascade(label="File", menu=filemenu) filemenu.add_command(label="Load location",command=self.save_location) filemenu.add_separator() filemenu.add_command(label="Exit", command=master.quit) # Help menu with 'about' option helpmenu = Menu(menu) menu.add_cascade(label="Help", menu=helpmenu) helpmenu.add_command(label="About...", command=self.about) # We create three frames. Top, main, bottom frames. Some prefer grid manager. self.top_frame = Frame(master,bg='#A9A7A6') self.top_frame.pack(side=TOP) # Main frame frame = Frame(master,bg='#B9B7B6') frame.pack(fill='y', expand=True) # Bottom frame self.bottom_frame = Frame(master,bg='#D5E3ED') self.bottom_frame.pack(side=BOTTOM) # Help text to be displayed always help_label = Label(self.top_frame, text="*** If country is US, enter state abbreviation eg. CA, MA, OH.\nElse enter country name: eg. India, UK, Australia\n\n") help_label.pack(side=LEFT) # Label and text box for entering State/country state_label = Label(frame,text="STATE / COUNTRY") state_label.pack(side=LEFT) self.state = Entry(frame) self.state.pack(side=LEFT) # Label and text box for entering City city_label = Label(frame,text="CITY") city_label.pack(side=LEFT) self.city = Entry(frame) self.city.pack(side=LEFT) # Create Radiobuttons. Another choice would be to use list box. R1 = Radiobutton(root, text="Geo Lookup", variable=var, value=1,command=self.show_options) R1.pack( anchor = W ) R3 = Radiobutton(root, text="Trip Planner",variable=var, value=3, command=self.show_options) R3.pack( anchor = W ) R4 = Radiobutton(root, text="Alerts", variable=var, value=4, command=self.show_label) R4.pack( anchor = W ) R5 = Radiobutton(root, text="Astronomy", variable=var, value=5,command=self.show_options) R5.pack( anchor = W ) R6 = Radiobutton(root, text="Forecast", variable=var, value=6,command=self.show_options) R6.pack( anchor = W ) R7 = Radiobutton(root, text="10 Day Forecast", variable=var, value=7,command=self.show_options) R7.pack( anchor = W ) R8 = Radiobutton(root, text="Yesterday weather", variable=var, value=8,command=self.show_options) R8.pack( anchor = W ) R2 = Radiobutton(root, text="Almanac", variable=var, value=2,command=self.show_options) R2.pack( anchor = W ) R9 = Radiobutton(root, text="Historical weather", variable=var, value=9, command=self.show_options) R9.pack( anchor = W ) # Create three buttons self.submit = Button(self.bottom_frame,text="Submit",command=self.find_weather) self.submit.pack(side=LEFT) self.save = Button(self.bottom_frame,text="Save Location(s)",command=self.save_location) self.save.pack(side=LEFT) self.quit = Button(self.bottom_frame,text="Quit",command=self.quit_program) self.quit.pack(side=LEFT) # Label and text box for displaying output self.output_label = Label(self.bottom_frame,text="\n\n\nWeather output:") self.output_label.pack(side=LEFT) self.output = ScrolledText(self.bottom_frame,bg='#D66B54') # ScrolledText looks better. Can use Text as well. self.output['font'] = ('monaco','12') def show_label(self): # Clear any other old labels self.clear_labels_and_text() if var.get() == 4: # Alerts # Display label related to alerts self.alert_label = Label(self.bottom_frame,text="**** This feature is only for United States ****") self.alert_label.pack(side=TOP) return def save_location(self): # RFE tkMessageBox.showinfo("Note", "This feature has not been implemented yet") return def quit_program(self): exit(0) return def about(self): # Just a note tkMessageBox.showinfo("About Weather lookup app", "This application is for demonstration purposes only. Not intended for commercial use.") return def clear_labels_and_text(self): dummy=0 # dummy variable basically for NO OP # We have different try-except blocks for different labels. # The reason is - at any point of time only one or none of the labels / text fields # would be displayed. Hence having one try-except will create problems. try: # Clear the history date label and text box. self.history_date_label.pack_forget() self.history_date.pack_forget() except AttributeError: dummy=1 # Do nothing basically try: # Clear the labels and text boxes associated with the trip planner self.from_date.pack_forget() self.from_date_label.pack_forget() self.to_date.pack_forget() self.to_date_label.pack_forget() except AttributeError: dummy=1 try: # Clear the alert label for alters self.alert_label.pack_forget() except AttributeError: dummy=1 try: # Clear the note label associated with the historical weather self.note_label.pack_forget() except AttributeError: dummy=1 # Delete any output displayed in the textbox self.output.delete(1.0,END) return def show_options(self): dummy = 0 if var.get() == 3: # Trip Planner # Clear any other labels or input forms self.clear_labels_and_text() # Display options for trip planner self.from_date_label = Label(self.bottom_frame,text="Departure (MMDD):") self.from_date_label.pack(side=LEFT) self.from_date = Entry(self.bottom_frame) self.from_date.pack(side=LEFT) self.to_date_label = Label(self.bottom_frame,text="Return (MMDD):") self.to_date_label.pack(side=LEFT) self.to_date = Entry(self.bottom_frame) self.to_date.pack(side=LEFT) elif var.get() == 9: # HIstorical Weather # Clear any other labels or input forms self.clear_labels_and_text() self.note_label = Label(self.bottom_frame,text="NOTE: Year should be greater than 2000") self.note_label.pack(side=TOP) # Display options for HIstorical Weather self.history_date_label = Label(self.bottom_frame,text="Historical date (yyyymmdd):") self.history_date_label.pack(side=RIGHT) self.history_date = Entry(self.bottom_frame) self.history_date.pack(side=RIGHT) else: # Clear any other labels or input forms self.clear_labels_and_text() return def find_weather(self): # Clear any other labels or input forms self.clear_labels_and_text() # If state or city is empty show error message if not self.state.get() or not self.city.get(): tkMessageBox.showerror("Error","Please enter both Country/State and City") return # Convert state / country to uppercase and replaces spaces with %20 for url construction state = self.state.get() if ' ' in state: state = re.sub(' ','%20',state) state = state.strip().upper() # Replace spaces in city with %20 for url construction city = self.city.get() if ' ' in city: city = re.sub(' ','%20',city) city = city.strip().lower() # Base URL with API key base_url = 'http://api.wunderground.com/api/' + your_api_key + '/' # Assign url_suffix for each option if var.get() == 1: url_suffix = 'geolookup/conditions/q/' + state + '/' + city + '.json' elif var.get() == 2: url_suffix = 'almanac/q/' + state + '/' + city + '.json' elif var.get() == 3: from_date = self.from_date.get() to_date = self.to_date.get() url_suffix = 'planner_' + from_date + to_date + '/q/' + state + '/' + city + '.json' elif var.get() == 4: url_suffix = 'alerts/q/' + state + '/' + city + '.json' elif var.get() == 5: url_suffix = 'astronomy/q/' + state + '/' + city + '.json' elif var.get() == 6: url_suffix = 'forecast/q/' + state + '/' + city + '.json' elif var.get() == 7: url_suffix = 'forecast10day/q/' + state + '/' + city + '.json' elif var.get() == 8: url_suffix = 'yesterday/q/' + state + '/' + city + '.json' elif var.get() == 9: history_date = self.history_date.get() url_suffix = 'history_' + history_date + '/q/' + state + '/' + city + '.json' try: # Send request and get parsed data url = base_url + url_suffix f = urllib2.urlopen(url) json_string = f.read() parsed_json = json.loads(json_string) except UnboundLocalError: # Throw message if none of radiobuttons are selected. tkMessageBox.showerror("Invalid Input","Select one of the options") return self.output.delete(1.0,END) if var.get() == 1: # Geo Lookup # Parse and send output try: location = parsed_json['location']['city'] temp_f = parsed_json['current_observation']['temp_f'] if '%20' in state: state = re.sub('%20',' ',state) self.output.text = "Temp for city - " + location + ", " + state + " in F is "+ str(temp_f) except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 2: # Almanac # Parse and send output try: normal_high = parsed_json['almanac']['temp_high']['normal']['F'] record_high = parsed_json['almanac']['temp_high']['record']['F'] record_high_year = parsed_json['almanac']['temp_high']['recordyear'] normal_low = parsed_json['almanac']['temp_low']['normal']['F'] record_low = parsed_json['almanac']['temp_low']['record']['F'] record_low_year = parsed_json['almanac']['temp_low']['recordyear'] self.output.text = ("NORMAL LOW ---> " + normal_low + " (F)\n" + "RECORD LOW ---> " + record_low + " (F)\n" + "RECORD LOW YEAR : " + record_low_year + "\n" + "NORMAL HIGH ---> " + normal_high + " (F)\n" + "RECORD HIGH ---> " + record_high + " (F)\n" + "RECORD HIGH YEAR : " + record_high_year) + "\n" except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 3: # Trip Planner # Parse and send output try: trip_title = parsed_json['trip']['title'] start_date = parsed_json['trip']['period_of_record']['date_start']['date']['pretty'] end_date = parsed_json['trip']['period_of_record']['date_end']['date']['pretty'] self.output.text = (trip_title + "\n\nPLANNER DATE --> \nFROM: " + start_date + "\nTO: " + end_date) high_temp1 = parsed_json['trip']['temp_high']['min']['F'] high_temp2 = parsed_json['trip']['temp_high']['max']['F'] self.output.text = self.output.text + ("\nMax temperature will be in the range ---> " + high_temp1 + " to " + high_temp2 + "(F)\n") low_temp1 = parsed_json['trip']['temp_low']['min']['F'] low_temp2 = parsed_json['trip']['temp_low']['max']['F'] self.output.text = self.output.text + ("\nMin temperature will be in the range ---> " + low_temp1 + " to " + low_temp2 + "(F)\n") chance_of_rain = parsed_json['trip']['chance_of']['chanceofrainday']['percentage'] self.output.text = self.output.text + ("\nChance of rain is " + chance_of_rain + " %\n") chance_of_hightemp = parsed_json['trip']['chance_of']['tempoverninety']['percentage'] hot_day_name = parsed_json['trip']['chance_of']['tempoverninety']['name'] hot_day_description = parsed_json['trip']['chance_of']['tempoverninety']['description'] self.output.text = self.output.text + ("\nChance of " + hot_day_name + "day (" + hot_day_description +") is " + chance_of_hightemp + " %\n") chance_of_humidity = parsed_json['trip']['chance_of']['chanceofhumidday']['percentage'] self.output.text = self.output.text + ("\nHumidity ---> " + chance_of_humidity + " %\n") except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 4: # Alerts # Parse and send output try: alert_description = parsed_json['alerts'][0]['description'] alert_expires = parsed_json['alerts'][0]['expires'] message = parsed_json['alerts'][0]['message'] self.output.text = ("Alert ---> " + alert_description + "\nAlert expires ---> " + alert_expires + "\n" + message) except KeyError: self.output.text = "ERROR: please check your input!" except IndexError: tkMessageBox.showerror("Error", "Alerts feature applicable only to states in US.") self.output.text = "ERROR: state not within the US." finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 5: # Astronomy # Parse and send output try: self.output.text = ("Current time ---> " + parsed_json['moon_phase']['current_time']['hour'] + ":" + parsed_json['moon_phase']['current_time']['minute'] + "\nSunrise ---> " + parsed_json['moon_phase']['sunrise']['hour'] + ":" + parsed_json['moon_phase']['sunrise']['minute'] + "\nSunset ---> " + parsed_json['moon_phase']['sunset']['hour'] + ":" + parsed_json['moon_phase']['sunset']['minute']) except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 6: # Forecast # Parse and send output self.output.text = "\n" try: for i in range(0,8): if i == 0: date_and_time = parsed_json['forecast']['txt_forecast']['forecastday'][i]['title'] + " " + parsed_json['forecast']['txt_forecast']['date'] else: date_and_time = parsed_json['forecast']['txt_forecast']['forecastday'][i]['title'] self.output.text = self.output.text + (date_and_time + " is " + parsed_json['forecast']['txt_forecast']['forecastday'][i]['fcttext'] + "\n\n") except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 7: # 10DayForcast # Parse and send output self.output.text = "\n" try: for i in range(0,10): date_and_time = parsed_json['forecast']['simpleforecast']['forecastday'][i]['date']['pretty'] high_temp = parsed_json['forecast']['simpleforecast']['forecastday'][i]['high']['fahrenheit'] low_temp = parsed_json['forecast']['simpleforecast']['forecastday'][i]['low']['fahrenheit'] conditions = parsed_json['forecast']['simpleforecast']['forecastday'][i]['conditions'] snow_allday_inches = parsed_json['forecast']['simpleforecast']['forecastday'][i]['snow_allday']['in'] snow_allday_cms = parsed_json['forecast']['simpleforecast']['forecastday'][i]['snow_allday']['cm'] max_wind = parsed_json['forecast']['simpleforecast']['forecastday'][i]['maxwind']['mph'] avg_wind = parsed_json['forecast']['simpleforecast']['forecastday'][i]['avewind']['mph'] self.output.text = self.output.text + ("\t\t** Day " + str(i) + " ---> " + date_and_time + " **\n" +"\t\t---------------------------------------------------\n" + "\t\tHIGH TEMP - " + high_temp + "\t\t LOW TEMP - " + low_temp + "\n" + "\t\tConditions - " + conditions + "\n") if int(snow_allday_cms) != 0: self.output.text = self.output.text + ("\t\tSnow in centimeters - " + snow_allday_cms + "\n") if int(snow_allday_inches) != 0: self.output.text = self.output.text + ("\t\tSnow in inches - " + snow_allday_inches + "\n") self.output.text = self.output.text + ("\t\tMAX WIND - " + str(max_wind) + "\t\t AVERAGE WIND - " + str(avg_wind) + "\n\n") except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 8: # Yesterday weather # Parse and send output try: self.output.text = ("Date ---> " + parsed_json['history']['date']['pretty'] + "\nTemperature ---> " + parsed_json['history']['observations'][0]['tempi'] + " F" + "\nTemperature ---> " + parsed_json['history']['observations'][0]['tempm'] + " C") except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0,self.output.text) self.output.pack(side=BOTTOM) elif var.get() == 9: # Historical Weather # Parse and send output try: self.output.text = ("Date ---> " + parsed_json['history']['date']['pretty'] + "\nTemperature ---> " + parsed_json['history']['observations'][0]['tempi'] + " F\n" + "Temperature ---> " + parsed_json['history']['observations'][0]['tempm'] + " C\n") rain = parsed_json['history']['observations'][0]['rain'] snow = parsed_json['history']['observations'][0]['snow'] if int(rain) != 0: self.output.text = self.output.text + ("Rain ---> " + rain + "\n") if int(snow) != 0: self.output.text = self.output.text + ("Snow ---> " + snow + "\n") except KeyError: self.output.text = "ERROR: please check your input!" finally: self.output.insert(1.0, self.output.text) self.output.pack(side=BOTTOM)
class ExportApp(Frame): """GUI version of the Phoshare tool.""" def __init__(self, master=None): """Initialize the app, setting up the UI.""" Frame.__init__(self, master, padding=10) top = self.winfo_toplevel() menu_bar = Menu(top) top["menu"] = menu_bar apple = Menu(menu_bar, name='apple') menu_bar.add_cascade(label='Phoshare', menu=apple) apple.add_command(label="About Phoshare", command=self.__aboutHandler) sub_menu = Menu(menu_bar, name='help') menu_bar.add_cascade(label="Help", menu=sub_menu) sub_menu.add_command(label="Phoshare Help", command=self.help_buttons) self.thread_queue = Queue.Queue(maxsize=100) self.active_library = None top.columnconfigure(0, weight=1) top.rowconfigure(0, weight=1) self.grid(sticky=N+S+E+W) self.valid_library = False self.exiftool = False self.iphoto_library = StringVar() self.iphoto_library_status = StringVar() self.browse_library_button = None self.export_folder = StringVar() self.library_status = None self.dryrun_button = None self.export_button = None self.text = None self.events = StringVar() self.albums = StringVar() self.smarts = StringVar() self.foldertemplate = StringVar() self.nametemplate = StringVar() self.captiontemplate = StringVar() self.update_var = IntVar() self.delete_var = IntVar() self.originals_var = IntVar() self.link_var = IntVar() self.folder_hints_var = IntVar() self.faces_box = None self.faces_var = IntVar() self.face_keywords_box = None self.face_keywords_var = IntVar() self.face_albums_var = IntVar() self.face_albums_text = StringVar() self.iptc_box = None self.iptc_all_box = None self.iptc_var = IntVar() self.iptc_all_var = IntVar() self.gps_box = None self.gps_var = IntVar() self.verbose_var = IntVar() self.info_icon = PhotoImage(file="info-b16.gif") self.create_widgets() # Set up logging so it gets redirected to the text area in the app. self.logging_handler = logging.StreamHandler(self) self.logging_handler.setLevel(logging.WARN) _logger.addHandler(self.logging_handler) def __aboutHandler(self): HelpDialog(self, """%s %s Copyright 2010 Google Inc. http://code.google.com/p/phoshare""" % (phoshare_version.PHOSHARE_VERSION, phoshare_version.PHOSHARE_BUILD), title="About Phoshare") def init(self): """Initializes processing by launching background thread checker and initial iPhoto library check.""" self.thread_checker() if exiftool.check_exif_tool(sys.stdout): self.exiftool = True self.faces_box.configure(state=NORMAL) self.face_keywords_box.configure(state=NORMAL) self.iptc_box.configure(state=NORMAL) self.iptc_all_box.configure(state=NORMAL) self.gps_box.configure(state=NORMAL) options = self.Options() options.load() self.init_from_options(options) self.check_iphoto_library() def init_from_options(self, options): """Populates the UI from options.""" self.iphoto_library.set(options.iphoto) self.export_folder.set(options.export) self.albums.set(su.fsdec(options.albums)) self.events.set(su.fsdec(options.events)) self.smarts.set(su.fsdec(options.smarts)) self.foldertemplate.set(su.unicode_string(options.foldertemplate)) self.nametemplate.set(su.unicode_string(options.nametemplate)) self.captiontemplate.set(su.unicode_string(options.captiontemplate)) self.update_var.set(_int_from_bool(options.update)) self.delete_var.set(_int_from_bool(options.delete)) self.originals_var.set(_int_from_bool(options.originals)) self.link_var.set(_int_from_bool(options.link)) self.folder_hints_var.set(_int_from_bool(options.folderhints)) self.faces_var.set(_int_from_bool(options.faces) and self.exiftool) self.face_keywords_var.set(_int_from_bool(options.face_keywords) and self.exiftool) self.face_albums_var.set(_int_from_bool(options.facealbums)) self.face_albums_text.set(options.facealbum_prefix) if options.iptc and self.exiftool: self.iptc_var.set(1) if options.iptc == 2: self.iptc_all_var.set(1) self.gps_var.set(_int_from_bool(options.gps) and self.exiftool) def _add_section(self, container, text, help_command): """Adds a new UI section with a bold label and an info button. Args: container: UI element that will contain this new item row: row number in grid. Uses two rows. text: label frame text. help_command: command to run when the info button is pressed. Returns: tuple of new section and content frames. """ section_frame = Frame(container) section_frame.columnconfigure(0, weight=1) label = Label(section_frame, text=text) label.config(font=_BOLD_FONT) label.grid(row=0, column=0, sticky=W, pady=5) Button(section_frame, image=self.info_icon, command=help_command).grid(row=0, column=1, sticky=E) content_frame = Frame(section_frame) content_frame.grid(row= 1, column=0, columnspan=2, sticky=N+S+E+W, pady=5) return (section_frame, content_frame) def _create_button_bar(self, container, row): """Creates the button bar with the Dry Run and Export buttons. Args: row: row number in grid. Returns: next row number in grid. """ button_bar = Frame(container) button_bar.grid(row=row, column=0, sticky=E+W, padx=10) button_bar.columnconfigure(0, weight=1) verbose_box = Checkbutton(button_bar, text="Show debug output", var=self.verbose_var) verbose_box.grid(row=0, column=0, sticky=E) self.dryrun_button = Button(button_bar, text="Dry Run", command=self.do_dryrun, state=DISABLED) self.dryrun_button.grid(row=0, column=1, sticky=E, pady=5) self.export_button = Button(button_bar, text="Export", command=self.do_export, state=DISABLED) self.export_button.grid(row=0, column=2, pady=5) return row + 1 def _create_library_tab(self, library_tab): library_tab.columnconfigure(0, weight=1) row = 0 f = Frame(library_tab) f.grid(row=row, columnspan=2, stick=E+W, padx=5, pady=5) row += 1 f.columnconfigure(1, weight=1) Label(f, text="iPhoto Library:").grid(sticky=E) iphoto_library_entry = Entry(f, textvariable=self.iphoto_library) iphoto_library_entry.grid(row=0, column=1, sticky=E+W) self.browse_library_button = Button(f, text="Browse...", command=self.browse_library) self.browse_library_button.grid(row=0, column=2) self.library_status = Label(f, textvariable=self.iphoto_library_status) self.library_status.grid(row=1, column=1, sticky=W) (cf, lf) = self._add_section(library_tab, "Events, Albums and Smart Albums", self.help_events) cf.grid(row=row, columnspan=2, stick=E+W) row += 1 lf.columnconfigure(1, weight=1) Label(lf, text="Events:").grid(sticky=E) events_entry = Entry(lf, textvariable=self.events) events_entry.grid(row=0, column=1, sticky=EW) Label(lf, text="Albums:").grid(sticky=E) albums_entry = Entry(lf, textvariable=self.albums) albums_entry.grid(row=1, column=1, sticky=EW) Label(lf, text="Smart Albums:").grid(sticky=E) smarts_entry = Entry(lf, textvariable=self.smarts) smarts_entry.grid(row=2, column=1, columnspan=3, sticky=EW) def _create_files_tab(self, files_tab): files_tab.columnconfigure(0, weight=1) # Export folder and options row = 0 (cf, lf) = self._add_section(files_tab, "Export Folder and Options", self.help_export) cf.grid(row=row, columnspan=2, stick=E+W) row += 1 lf.columnconfigure(1, weight=1) label = Label(lf, text="Export Folder:") label.grid(sticky=E) export_folder_entry = Entry(lf, textvariable=self.export_folder) export_folder_entry.grid(row=0, column=1, columnspan=2, sticky=E+W) Button(lf, text="Browse...", command=self.browse_export).grid(row=0, column=3) update_box = Checkbutton(lf, text="Overwrite changed pictures", var=self.update_var) update_box.grid(row=1, column=1, sticky=W) originals_box = Checkbutton(lf, text="Export originals", var=self.originals_var) originals_box.grid(row=2, column=1, sticky=W) hint_box = Checkbutton(lf, text="Use folder hints", var=self.folder_hints_var) hint_box.grid(row=3, column=1, sticky=W) delete_box = Checkbutton(lf, text="Delete obsolete pictures", var=self.delete_var) delete_box.grid(row=4, column=1, sticky=W) link_box = Checkbutton(lf, text="Use file links", var=self.link_var) link_box.grid(row=5, column=1, sticky=W) # Templates ---------------------------------------- (cf, lf) = self._add_section(files_tab, "Name Templates", self.help_templates) cf.grid(row=row, columnspan=2, stick=E+W) row += 1 lf.columnconfigure(1, weight=1) Label(lf, text="Folder names:").grid(sticky=E) foldertemplate_entry = Entry(lf, textvariable=self.foldertemplate) foldertemplate_entry.grid(row=0, column=1, sticky=EW) Label(lf, text="File names:").grid(sticky=E) nametemplate_entry = Entry(lf, textvariable=self.nametemplate) nametemplate_entry.grid(row=1, column=1, sticky=EW) Label(lf, text="Captions:").grid(sticky=E) captiontemplate_entry = Entry(lf, textvariable=self.captiontemplate) captiontemplate_entry.grid(row=2, column=1, sticky=EW) def _create_metadata_tab(self, metadata_tab): metadata_tab.columnconfigure(0, weight=1) row = 0 # Metadata -------------------------------------------- (cf, lf) = self._add_section(metadata_tab, "Metadata", self.help_metadata) cf.grid(row=row, columnspan=2, stick=E+W) row += 1 self.iptc_box = Checkbutton(lf, text=("Export metadata (descriptions, " "keywords, ratings, dates)"), var=self.iptc_var, state=DISABLED, command=self.change_iptc_box) self.iptc_box.grid(row=0, column=0, columnspan=2, sticky=W) self.iptc_all_box = Checkbutton(lf, text="Check previously exported images", var=self.iptc_all_var, command=self.change_metadata_box, state=DISABLED) self.iptc_all_box.grid(row=1, column=0, sticky=W) self.gps_box = Checkbutton(lf, text="Export GPS data", var=self.gps_var, command=self.change_metadata_box, state=DISABLED) self.gps_box.grid(row=2, column=0, sticky=W) # Faces --------------------------------------------------- (cf, lf) = self._add_section(metadata_tab, "Faces", self.help_faces) cf.grid(row=row, columnspan=2, stick=E+W) row += 1 lf.columnconfigure(2, weight=1) self.faces_box = Checkbutton(lf, text="Copy faces into metadata", var=self.faces_var, state=DISABLED, command=self.change_metadata_box) self.faces_box.grid(row=0, column=0, sticky=W) self.face_keywords_box = Checkbutton( lf, text="Copy face names into keywords", var=self.face_keywords_var, command=self.change_metadata_box, state=DISABLED) self.face_keywords_box.grid(row=1, column=0, sticky=W) checkbutton = Checkbutton(lf, text="Export faces into folders", var=self.face_albums_var) checkbutton.grid(row=2, column=0, sticky=W) label = Label(lf, text="Faces folder prefix:") label.grid(row=2, column=1, sticky=E) entry = Entry(lf, textvariable=self.face_albums_text) entry.grid(row=2, column=2, sticky=E+W) def create_widgets(self): """Builds the UI.""" self.columnconfigure(0, weight=1) n = Notebook(self) n.grid(row=0, sticky=E+W+N+S) library_tab = Frame(n) n.add(library_tab, text='Library') self._create_library_tab(library_tab) files_tab = Frame(n) n.add(files_tab, text='Files') self._create_files_tab(files_tab) metadata_tab = Frame(n) n.add(metadata_tab, text='Metadata') self._create_metadata_tab(metadata_tab) self._create_button_bar(self, 1) self.text = ScrolledText(self, borderwidth=4, relief=RIDGE, padx=4, pady=4) self.text.grid(row=2, column=0, sticky=E+W+N+S) self.rowconfigure(2, weight=1) def change_iptc_box(self): """Clears some options that depend on the metadata export option.""" mode = self.iptc_var.get() if not mode: self.faces_var.set(0) self.face_keywords_var.set(0) self.iptc_all_var.set(0) self.gps_var.set(0) def change_metadata_box(self): """Sets connected options if an option that needs meta data is changed. """ mode = (self.faces_var.get() or self.face_keywords_var.get() or self.iptc_all_var.get() or self.gps_var.get()) if mode: self.iptc_var.set(1) def help_events(self): HelpDialog(self, """Events, Albums and Smart Albums Selects which events, albums, or smart albums to export. Each field is a regular expression, and at least one must be filled in. Matches are done against the beginning of the event or album name. An entry in Events of Family will export all events that start with "Family", including "Family 2008" and "Family 2009". "|" separates alternate patterns, so Family|Travel will export all events that start with either "Family" or "Travel". "." matches any character, and therefore, . will export all events. To export all events with "2008" in the name, use .*2008 For more details on regular expressions, see http://en.wikipedia.org/wiki/Regular_expression""") def help_templates(self): HelpDialog(self, """Folder, file, and image caption templates. Templates are strings with place holders for values. The place holders have the format "{name}". Everything else in the template will be copied. Examples: {title} {yyyy}/{mm}/{dd} {title} - generates "2010/12/31 My Birthday" if the date of the pictures is Dec 31, 2010, and the title is "My Birthday". {yyyy} Event: {event} - generates "2010 Event: Birthday" for an event with any date in 2010 and the name "Birthday". Available place holders for folder names: {name} - name of the album or event. {hint} - folder hint (taken from line event or album description starting with @). {yyyy} - year of album or event date. {mm} - month of album or event date. {dd} - date of album or event date. Available place holders for file names: {album} - name of album (or in the case of an event, the name of the event). {index} - number of image in album, starting at 1. {index0} - number of image in album, padded with 0s, so that all numbers have the same length. {event} - name of the event. In the case of an album, the name of the event to which the image belongs. {event_index} - number of image in the event, starting at 1. If the case of an album, this number will be based on the event to which the image belongs. {event_index0} - same as {event_index}, but padded with leading 0s so that all values have the same length. {title} - image title. {yyyy} - year of image. {mm} - month of image (01 - 12). {dd} - day of image (01 - 31). If you are using {album}/{index}/{index0} place holders, the image will be named based on whatever album or event it is contained. That means an image in two albums will be exported with different names, even so the files are identical. If you want to use the same name for each image, regardless of which album it is in, use {event}, {event_index}, and {event_index0} instead. Available place holders for captions: {title} - image title. {description} - image description. {title_description} - concatenated image title and description, separated by a : if both are set. {yyyy} - year of image. {mm} - month of image (01 - 12). {dd} - day of image (01 - 31). """) def help_buttons(self): HelpDialog(self, """Export modes. Click on "Dry Run" to see what Phoshare would do without actually modifying any files. Click on "Export" to export your files using the current settings. All your settings will be saved when you click either Dry Run and Export, and re-loaded if you restart Phoshare. Check "Show debug output" to generate additional output message that can assist in debugging Phoshare problems. """) def help_export(self): HelpDialog(self, """Export Settings Export Folder: path to the folder for exporting images. Overwrite changed pictures: If set, pictures that already exist in the export folder will be overriden if an different version exist in iPhoto. Any edits made to previously exported images in the export folder will be lost! Use Dry Run to see which files would be overwritten. Export originals: If set, and an image has been modified in iPhoto, both the original and the edited version will be exported. The original will be stored in a sub-folder called "Originals". Use folder hints: By default, each exported event or album will become a folder in the export folder. With folder hints, a sub-folder name can be given in the event or album description by adding a line starting with a @ character. Example: Family Vacation @Vacation would export all images in that event into a sub-folder called "Vacation". Delete obsolete pictures: If set, any image, movie file or folder in the export folder that does not exist in the iPhoto library will be deleted. Use Dry Run to see which files would be deleted. Use file links: Don't copy images during export, but make a link to the files in the iPhoto library instead. This option is only available if the export folder is on the same drive as the iPhoto library. This option will save a lot of disk space because it avoids making copies of all your images and videos. Using this option causes the metadata of the images IN YOUR IPHOTO LIBRARY to be modified. While phoshare should not cause any problems to your images, it is best to use this option only if you have a backup of your iPhoto library, and you know how to restore your library from the backup. For more details on link mode, see https://sites.google.com/site/phosharedoc/Home#TOC-link-mode""") def help_faces(self): HelpDialog(self, """Faces options. Copy faces into metadata: faces tags and face regions will be copied into the image metadata using the Microsoft Photo Region Schema: http://msdn.microsoft.com/en-us/library/ee719905(VS.85).aspx Copy faces names into keywords: If set, face names will be merged into image keywords. Requires "Export metadata" checked. Export faces into folders: If checked, folders will be created for each face tag, each containing all the images tagged with that person. Faces folder prefix: If set, the string will be used as a prefix for the face export folders if "Exported faces into folders" is checked. This can be just a value like "Face: ", or a sub-folder name like "Faces/" if it ends with a "/" Metadata options will be disabled if exiftool is not available. """) def help_metadata(self): HelpDialog(self, """Metadata options. Export metadata: sets the description, keywords, rating and date metadata in the exported images to match the iPhoto settings. Check previously exported images: If not checked, metadata will only be set for new or updated images. If checked, metadata will be checked in all images, including ones that were previously exported. This is much slower. Export GPS data: export the GPS coordinates into the image metadata. Metadata options will be disabled if exiftool is not available.""") def check_iphoto_library(self): self.valid_library = False self.enable_buttons() self.iphoto_library_status.set("Checking library location...") self.launch_export("library") def set_library_status(self, good, message): if good: self.valid_library = True self.enable_buttons() self.iphoto_library_status.set(message) def write_progress(self, text): self.text.insert(END, text) self.text.see(END) def enable_buttons(self): if self.valid_library: self.dryrun_button.config(state=NORMAL) self.export_button.config(state=NORMAL) else: self.dryrun_button.config(state=DISABLED) self.export_button.config(state=DISABLED) self.browse_library_button.config(state=NORMAL) def browse_library(self): path = tkFileDialog.askopenfilename(title="Locate iPhoto Library") self.iphoto_library.set(path) self.check_iphoto_library() def browse_export(self): path = tkFileDialog.askdirectory(title="Locate Export Folder") self.export_folder.set(path) def do_export(self): if self.active_library: self.stop_thread() return if not self.can_export(): return self.export_button.config(text="Stop Export") self.dryrun_button.config(state=DISABLED) self.run_export(False) def do_dryrun(self): if self.active_library: self.stop_thread() return if not self.can_export(): return self.dryrun_button.config(text="Stop Dry Run") self.export_button.config(state=DISABLED) self.run_export(True) def stop_thread(self): if self.active_library: self.active_library.abort() def export_done(self): self.active_library = None self.dryrun_button.config(text="Dry Run") self.export_button.config(text="Export") self.enable_buttons() class Options(object): """Simple helper to create an object compatible with the OptionParser output in Phoshare.py.""" def __init__(self): self.iphoto = '~/Pictures/iPhoto Library' self.export = '~/Pictures/Album' self.albums = '' self.events = '.' self.smarts = '' self.ignore = [] self.delete = False self.update = False self.link = False self.dryrun = False self.folderhints = False self.captiontemplate = u'{description}' self.foldertemplate = u'{name}' self.nametemplate = u'{title}' self.aperture = False # TODO self.size = '' # TODO self.picasa = False # TODO self.movies = True # TODO self.originals = False self.iptc = 0 self.gps = False self.faces = False self.facealbums = False self.facealbum_prefix = '' self.face_keywords = False self.verbose = False def load(self): """Attempts to load saved options. Returns True if saved options were available.""" if not os.path.exists(_CONFIG_PATH): return False config = ConfigParser.SafeConfigParser() config.read(_CONFIG_PATH) s = 'Export1' if config.has_option(s, 'iphoto'): self.iphoto = config.get(s, 'iphoto') if config.has_option(s, 'export'): self.export = config.get(s, 'export') if config.has_option(s, 'albums'): self.albums = config.get(s, 'albums') if config.has_option(s, 'events'): self.events = config.get(s, 'events') if config.has_option(s, 'smarts'): self.smarts = config.get(s, 'smarts') if config.has_option(s, 'foldertemplate'): self.foldertemplate = config.get(s, 'foldertemplate') if config.has_option(s, 'nametemplate'): self.nametemplate = config.get(s, 'nametemplate') if config.has_option(s, 'captiontemplate'): self.captiontemplate = config.get(s, 'captiontemplate') if config.has_option(s, 'delete'): self.delete = config.getboolean(s, 'delete') if config.has_option(s, 'update'): self.update = config.getboolean(s, 'update') if config.has_option(s, 'link'): self.link = config.getboolean(s, 'link') if config.has_option(s, 'folderhints'): self.folderhints = config.getboolean(s, 'folderhints') if config.has_option(s, 'captiontemplate'): self.nametemplate = unicode(config.get(s, 'captiontemplate')) if config.has_option(s, 'nametemplate'): self.nametemplate = unicode(config.get(s, 'nametemplate')) if config.has_option(s, 'size'): self.size = config.get(s, 'size') if config.has_option(s, 'picasa'): self.picasa = config.getboolean(s, 'picasa') if config.has_option(s, 'movies'): self.movies = config.getboolean(s, 'movies') if config.has_option(s, 'originals'): self.originals = config.getboolean(s, 'originals') if config.has_option(s, 'iptc'): self.iptc = config.getint(s, 'iptc') if config.has_option(s, 'gps'): self.gps = config.getboolean(s, 'gps') if config.has_option(s, 'faces'): self.faces = config.getboolean(s, 'faces') if config.has_option(s, 'facealbums'): self.facealbums = config.getboolean(s, 'facealbums') if config.has_option(s, 'facealbum_prefix'): self.facealbum_prefix = config.get(s, 'facealbum_prefix') if config.has_option(s, 'face_keywords'): self.face_keywords = config.getboolean(s, 'face_keywords') return True def save(self): """Saves the current options into a file.""" config = ConfigParser.RawConfigParser() s = 'Export1' config.add_section(s) config.set(s, 'iphoto', self.iphoto) config.set(s, 'export', self.export) config.set(s, 'albums', su.fsenc(self.albums)) config.set(s, 'events', su.fsenc(self.events)) config.set(s, 'smarts', su.fsenc(self.smarts)) config.set(s, 'foldertemplate', su.fsenc(self.foldertemplate)) config.set(s, 'nametemplate', su.fsenc(self.nametemplate)) config.set(s, 'captiontemplate', su.fsenc(self.captiontemplate)) config.set(s, 'delete', self.delete) config.set(s, 'update', self.update) config.set(s, 'link', self.link) config.set(s, 'dryrun', self.dryrun) config.set(s, 'folderhints', self.folderhints) config.set(s, 'captiontemplate', self.captiontemplate) config.set(s, 'nametemplate', self.nametemplate) config.set(s, 'size', self.size) config.set(s, 'picasa', self.picasa) config.set(s, 'movies', self.movies) config.set(s, 'originals', self.originals) config.set(s, 'iptc', self.iptc) config.set(s, 'gps', self.gps) config.set(s, 'faces', self.faces) config.set(s, 'facealbums', self.facealbums) config.set(s, 'facealbum_prefix', self.facealbum_prefix) config.set(s, 'face_keywords', self.face_keywords) config_folder = os.path.split(_CONFIG_PATH)[0] if not os.path.exists(config_folder): os.makedirs(config_folder) configfile = open(_CONFIG_PATH, 'wb') config.write(configfile) configfile.close() def can_export(self): if (not self.albums.get() and not self.events.get() and not self.smarts.get()): tkMessageBox.showerror( "Export Error", ("Need to specify at least one event, album, or smart album " "for exporting.")) return False return True def run_export(self, dry_run): mode = "export" if dry_run: mode = "dry_run" self.launch_export(mode) def launch_export(self, mode): """Launch an export operation in a new thread, to not block the UI. Args: mode - name of operation to run, "library", "dry_run", or "export". """ self.text.delete('1.0', END) self.browse_library_button.config(state=DISABLED) export_thread = threading.Thread(target=self.export_thread, args=(mode,)) export_thread.start() def export_thread(self, mode): """Run an export operation in a thread, to not block the UI. Args: mode - name of operation to run, "library", "dry_run", or "export". """ try: # First, load the iPhoto library. library_path = su.expand_home_folder(self.iphoto_library.get()) album_xml_file = iphotodata.get_album_xmlfile(library_path) data = iphotodata.get_iphoto_data(album_xml_file) msg = "Version %s library with %d images" % ( data.applicationVersion, len(data.images)) self.write(msg + '\n') if mode == "library": # If we just need to check the library, we are done here. self.thread_queue.put(("done", (True, mode, msg))) return # Do the actual export. export_folder = su.expand_home_folder(self.export_folder.get()) args = ['Phoshare.py', '--export', '"' + export_folder + '"'] options = self.Options() options.iphoto = self.iphoto_library.get() args.extend(['--iphoto', '"' + options.iphoto + '"']) options.export = self.export_folder.get() options.dryrun = mode == "dry_run" options.albums = self.albums.get() if options.albums: args.extend(['--albums', '"' + options.albums + '"']) options.events = self.events.get() if options.events: args.extend(['--events', '"' + options.events + '"']) options.smarts = self.smarts.get() if options.smarts: args.extend(['--smarts', '"' + options.smarts + '"']) options.foldertemplate = unicode(self.foldertemplate.get()) if options.foldertemplate: args.extend(['--foldertemplate', '"' + options.foldertemplate + '"']) options.nametemplate = unicode(self.nametemplate.get()) if options.nametemplate: args.extend(['--nametemplate', '"' + options.nametemplate + '"']) options.captiontemplate = unicode(self.captiontemplate.get()) if options.captiontemplate: args.extend(['--captiontemplate', '"' + options.captiontemplate + '"']) options.ignore = [] # TODO options.update = self.update_var.get() == 1 if options.update: args.append('--update') options.delete = self.delete_var.get() == 1 if options.delete: args.append('--delete') options.originals = self.originals_var.get() == 1 if options.originals: args.append('--originals') options.link = self.link_var.get() == 1 if options.link: args.append('--link') options.folderhints = self.folder_hints_var.get() == 1 if options.folderhints: args.append('--folderhints') options.faces = self.faces_var.get() == 1 if options.faces: args.append('--faces') options.face_keywords = self.face_keywords_var.get() == 1 if options.face_keywords: args.append('--face_keywords') if self.iptc_all_var.get() == 1: options.iptc = 2 args.append('--iptcall') elif self.iptc_var.get() == 1: options.iptc = 1 args.append('--iptc') else: options.iptc = 0 options.gps = self.gps_var.get() if options.gps: args.append('--gps') options.facealbums = self.face_albums_var.get() == 1 if options.facealbums: args.append('--facealbums') options.facealbum_prefix = self.face_albums_text.get() if options.facealbum_prefix: args.append('--facealbum_prefix') exclude = None # TODO options.save() print " ".join(args) self.logging_handler.setLevel(logging.DEBUG if self.verbose_var.get() else logging.INFO) self.active_library = phoshare_main.ExportLibrary(export_folder) phoshare_main.export_iphoto(self.active_library, data, exclude, options) self.thread_queue.put(("done", (True, mode, ''))) except Exception, e: # IGNORE:W0703 self.thread_queue.put(("done", (False, mode, str(e) + '\n\n' + traceback.format_exc())))
class LogHandler(object): ''' Logging and warnings ''' def __init__(self, app): self.app = app self.enabled = True # enabling or disabling logging # get package loggers self.loggers = [] self.pkgName = __name__.split('.')[0] for name in logging.Logger.manager.loggerDict.keys(): if self.pkgName in name: self.loggers.append(logging.getLogger(name)) self.font = tkFont.Font(family='Courier New', size=12) # make text for normal logs self.logFrame = tk.Frame(self.app.root) self.logScroll = ScrolledText(self.app.root, bd=0, highlightthickness=0, font=self.font, bg=COL_PRIM, fg=COL_HL, width=80) self.logScroll.pack(side=tk.RIGHT, fill=tk.Y) # make warning panel self.alert = tk.Label(self.app.graphEditor.bg, cursor='X_cursor', font=self.font, bg=COL_HL, fg=COL_BG) self.alert.bind('<Button-1>', lambda _: self.resetWarning()) self.alert.pack(side=tk.TOP) self.alert.pack_forget() # initially not visible self.enableLog(False) # initially, disable normal logs def enableLog(self, enable): ''' Enables/Disables logging and shows/hides the log scroll ''' self.enabled = enable if enable: # slow, but comprehensive logging self.logScroll.pack(side=tk.RIGHT, fill=tk.Y) self.setLogLevel(logging.DEBUG) else: # only alerts can occur now self.clear() self.logScroll.pack_forget() self.setLogLevel(logging.WARNING) def setLogLevel(self, level): ''' Sets all package related loggers to a new level. This results in better performance, but other log handlers won't see messages below level too of course. ''' for logger in self.loggers: logger.setLevel(level) def warn(self, warning): ''' Shows a warning ''' # append linefeed to current text curText = self.alert.cget('text') if curText and not curText.endswith('\n'): curText += '\n' # add warning to current text and show self.alert.config(text=curText + warning) self.alert.pack() def resetWarning(self): ''' Resets the warnings in the alert panel ''' self.alert.config(text='') self.alert.pack_forget() def write(self, msg): ''' This method is called from the logging module for each message ''' if any(lvl in msg for lvl in ('WARNING', 'ERROR', 'CRITICAL')): # user needs attention self.warn(msg) if self.enabled: # normal logging self.logScroll.insert(tk.END, msg) def flush(self): ''' This method might be called from the logging module ''' pass def tail(self): ''' Scrolls down to the last messages ''' if self.enabled: self.logScroll.see(tk.END) # super useful but super slow def clear(self): self.logScroll.delete(1.0, tk.END)
class InputFile: def __init__(self, drawing): self.drawing = drawing self.toplevel = Toplevel() self.dirty = False self.filename = drawing.name + ".inp" self.toplevel.title(self.filename) self.inputText = ScrolledText(self.toplevel) self.inputText.pack() self.popup = Menu(self.toplevel, tearoff=0) self.popup.add_command(label="Dismiss", command=self.nothing) self.popup.add_command(label="Abort", command=self.abort) self.popup.add_command(label="Accept", command=self.accept) self.popup.add_command(label="Feedback", command=self.feedback) self.popup.add_command(label="Other File", command=self.changeFile) self.popup.add_command(label="Run", command=self.run) self.popup.add_command(label="Debug", command=self.debug) def popupMenu(event): self.popup.post(event.x_root, event.y_root) self.toplevel.bind('<Button-3>', popupMenu) Widget.bind(self.inputText, '<Any-KeyPress>', self.setDirty) self.refreshSource() def nothing(self): pass def abort(self): self.refreshSource() self.setClean() print "aborted" def accept(self): inptext = self.getSource() handle = open(self.filename, "w") handle.write(inptext) self.setClean() def run(self): self.accept() self.drawing.doRun() def debug(self): self.drawing.doDebug() def changeFile(self): self.filename = tkFileDialog.asksaveasfilename( initialdir=os.getcwd(), parent=self.toplevel, title="Select Input file", filetypes=[("Input files", ".inp")], defaultextension='.inp') self.filename = os.path.basename(self.filename) self.refreshSource() self.drawing.setInpFile(os.path.splitext(self.filename)[0]) def refreshSource(self): inptext = "" if os.path.exists(self.filename): inptext = open(self.filename).read() self.setSource(inptext) self.toplevel.title(self.filename) def setSource(self, txt): self.inputText.delete('1.0', END) self.inputText.insert(END, txt) def getSource(self): return self.inputText.get("1.0", END) def feedback(self): resFile = "res" + os.sep + os.path.splitext( os.path.basename(self.filename))[0] + ".res" if os.path.exists(resFile): resText = open(resFile).read() self.setSource(resText) self.setDirty() def setClean(self): if self.dirty: self.dirty = False self.toplevel.title(self.filename) def setDirty(self, event=None): if event and (event.keysym in [ 'Shift_L', 'Shift_R', 'Alt_L', 'Alt_R', 'Win_L', 'Win_R' ]): return if not self.dirty: self.dirty = True self.toplevel.title(self.filename + "*")
class LogReader(object): def __init__(self, root, **kwargs): self.root = root self.filenameLog = kwargs.get('filenameLog', None) self.ClearDisplay = kwargs.get('ClearDisplay', False) ''' By default don't display Filenames and directory ''' mainstyle = ttk.Style() # mainstyle.theme_use(mainstyle.theme_names()[0]) mainstyle.configure('My.TFrame', background='gray50', foreground='gray97', font="Monospace 12") Btnstyle = ttk.Style() Btnstyle.configure('My.TButton', background='gray50', foreground='gray97', font="Monospace 12") root.title("Log reader v0.1") Chkstyle = ttk.Style() Chkstyle.configure('My.TCheckbutton', background='gray50', foreground='gray97', font="Monospace 12") Chkstyle = ttk.Style() Chkstyle.configure('My.TLabel', background='gray50', foreground='gray97', font="Monospace 12") root.title("Libretto v0.1") self.initParam() #====================================================================== # Main Frame #====================================================================== self.f0 = ttk.Frame(self.root, style='My.TFrame') self.f0.pack(expand=True, fill='both') LabelUP = ttk.Label( self.f0, text="Please select the log file then click on read", style='My.TLabel') LabelUP.pack(side="top") self.fDisp = ttk.Frame(self.f0, style='My.TFrame') self.fDisp.pack(expand=True, fill='both', side="right") self.fParam = ttk.Frame(self.f0, style='My.TFrame') self.fParam.pack(side="left") #====================================================================== # Frame fDisp #====================================================================== # Display stdout self.customFont = tkFont.Font( family="Helvetica", size=12) self.text_area = ScrolledText( self.fDisp, font=self.customFont, undo=True, background='gray20', foreground="gray92") self.text_area.pack(expand=True, fill='both') self.text_area.configure(state='normal') self.text_area.yview(END) self.text_area.after(0) self.text_area.tag_configure("comment", font="Helvetica 12", foreground="gray60") self.text_area.tag_configure("subsubTitle", font="Helvetica 12 bold") self.text_area.tag_configure("subTitle", font="Helvetica 14 bold") self.text_area.tag_configure("Title", font="Helvetica 16 bold") self.text_area.tag_configure("warn", font="Helvetica 12 bold", foreground="red") self.text_area.tag_configure("File", font="Helvetica 10", foreground="DarkSlateGray1") self.text_area.tag_configure("FileOther", font="Helvetica 10", foreground="plum") self.text_area.tag_configure("Directory", font="Helvetica 10", foreground="goldenrod1") self.text_area.tag_configure("validate", font="Helvetica 12 bold", foreground="OliveDrab1") self.text_area.tag_configure("param", font="Helvetica 12", foreground="wheat") # stdout redirection sys.stdout = StdoutRedirector(self.text_area) #====================================================================== # Parameters #====================================================================== # File Selection button SelectLogFileBtn = ttk.Button( self.fParam, text="Select the log file", style='My.TButton') SelectLogFileBtn.grid(row=0, column=0) SelectLogFileBtn.configure(command=lambda: self.set_LogFile()) Label = ttk.Label(self.fParam, text="", style='My.TLabel') Label.grid(row=1, column=0) # Refresh button SelectLogFileBtn = ttk.Button( self.fParam, text="Refresh", style='My.TButton') SelectLogFileBtn.grid(row=2, column=0) SelectLogFileBtn.configure(command=lambda: self.RefreshLog()) Label = ttk.Label(self.fParam, text="", style='My.TLabel') Label.grid(row=9, column=0) # Display Files button ChkBtnDispFilenames = ttk.Checkbutton( self.fParam, text="Display the filenames", style='My.TCheckbutton') ChkBtnDispFilenames.grid(row=10, column=0) ChkBtnDispFilenames.configure(variable=self.Entry_DispFilenames, command=lambda: self.set_DispFilenames()) # Display Comments button ChkBtnDispCom = ttk.Checkbutton( self.fParam, text="Display the comments", style='My.TCheckbutton') ChkBtnDispCom.grid(row=11, column=0) ChkBtnDispCom.configure(variable=self.Entry_DispComment, command=lambda: self.set_DispComment()) # Display Directories button ChkBtnDispDir = ttk.Checkbutton( self.fParam, text="Display the directories", style='My.TCheckbutton') ChkBtnDispDir.grid(row=12, column=0) ChkBtnDispDir.configure(variable=self.Entry_DispDir, command=lambda: self.set_DispDir()) # Display Warnings button ChkBtnDispWarn = ttk.Checkbutton( self.fParam, text="Display the warnings", style='My.TCheckbutton') ChkBtnDispWarn.grid(row=13, column=0) ChkBtnDispWarn.configure(variable=self.Entry_DispWarn, command=lambda: self.set_DispWarn()) # Display Warnings button ChkBtnDispParam = ttk.Checkbutton( self.fParam, text="Display the parameters", style='My.TCheckbutton') ChkBtnDispParam.grid(row=14, column=0) ChkBtnDispParam.configure(variable=self.Entry_DispParam, command=lambda: self.set_DispParam()) self.RefreshLog() if self.ClearDisplay: self.UpdateAllDisp() def printExample(self): return ["=========================================", "= Welcome in the Log Reader ", "=========================================", "", "=== This is a big title ! ===", " ~ A little bit different of this sub-Title", " * And guess what, now a sub-sub-Title ! ", " # right now I am commenting my example", " p_Dodo is a parameter", " BlablablaAudyIsTheBestBlablabla...", " X_something is a most of the time the filename of " + " an MRI image or created", " Z_something is the filename of a file which is not an " + "mri image (it can be some stats or a matrix)", " D_anotherthing is a directory", " > Well this task seems to be a success", " !! But this is a message you should read"] def initParam(self): self.logExtension = ("*.txt", "*.log") self.LogMessage = None self.listHideBal = [] global DefaultFileNameMRIImage global DefaultFileNameMRIMasks global DefaultFileNameOther global DefaultFileNameMatrix global DefaultDirectory global DefaultName global DefaultWarning global DefaultTitle global DefaultSubTitle global DefaultSubSubTitle global DefaultComment global DefaultValidate global DefaultParameter self.DefaultFileNameMRIImage = DefaultFileNameMRIImage self.DefaultFileNameMRIMasks = DefaultFileNameMRIMasks self.DefaultFileNameOther = DefaultFileNameOther self.DefaultFileNameMatrix = DefaultFileNameMatrix self.DefaultDirectory = DefaultDirectory self.DefaultName = DefaultName self.DefaultWarning = DefaultWarning self.DefaultTitle = DefaultTitle self.DefaultSubTitle = DefaultSubTitle self.DefaultSubSubTitle = DefaultSubSubTitle self.DefaultComment = DefaultComment self.DefaultValidate = DefaultValidate self.DefaultParameter = DefaultParameter self.DispWarn = True self.Entry_DispWarn = IntVar(value=1) self.DispParam = True self.Entry_DispParam = IntVar(value=1) if self.ClearDisplay: self.DispFilenames = False self.Entry_DispFilenames = IntVar(value=0) self.DispComment = False self.Entry_DispComment = IntVar(value=0) self.DispDir = False self.Entry_DispDir = IntVar(value=0) else: self.DispFilenames = True self.Entry_DispFilenames = IntVar(value=1) self.DispComment = True self.Entry_DispComment = IntVar(value=1) self.DispDir = True self.Entry_DispDir = IntVar(value=1) def DispOrHide(self, DispSomething, listHideBal): if DispSomething: # update the balise to hide list listHideBal = [e for e in self.listHideBal if e not in listHideBal] else: listHideBal = listHideBal + self.listHideBal self.listHideBal = listHideBal self.resetDisp() self.watchLog(bal=self.listHideBal) def set_DispFilenames(self): self.DispFilenames = self.Entry_DispFilenames.get() listbal0 = [self.DefaultFileNameMRIImage, self.DefaultFileNameMatrix, self.DefaultFileNameMRIMasks, self.DefaultFileNameOther] self.DispOrHide(self.DispFilenames, listbal0) def set_DispDir(self): self.DispDir = self.Entry_DispDir.get() listbal0 = [self.DefaultDirectory] self.DispOrHide(self.DispDir, listbal0) def set_DispComment(self): self.DispComment = self.Entry_DispComment.get() listbal0 = [self.DefaultComment] self.DispOrHide(self.DispComment, listbal0) def set_DispWarn(self): self.DispWarn = self.Entry_DispWarn.get() listbal0 = [self.DefaultWarning] self.DispOrHide(self.DispWarn, listbal0) def set_DispParam(self): self.DispParam = self.Entry_DispParam.get() listbal0 = [self.DefaultParameter] self.DispOrHide(self.DispParam, listbal0) def UpdateAllDisp(self): self.set_DispComment() self.set_DispDir() self.set_DispFilenames() def set_LogFile(self): self.filenameLog = self.OpenFile( self.OriginalDirectory, self.logExtension) self.RefreshLog() def filterLog(self, str0, bal): ''' delete the lines which contain a specific balise ''' if type(bal) != list: if type(bal) != str: if not bal: return str0 else: bal = [bal] try: str1 = DeleteTabulation(str0) except: str1 = str0 for e in bal: if str1[0:len(e)] == e: return None return str0 def loadLog(self): ''' load a log ''' if self.filenameLog: with open(self.filenameLog) as f: self.LogMessage = f.read().splitlines() else: self.LogMessage = self.printExample() def watchLog(self, bal=None): ''' display the log ''' for line in self.LogMessage: l = self.filterLog(line, bal) if l: print l def resetDisp(self): ''' ''' self.text_area.delete('1.0', END) def RefreshLog(self): self.loadLog() self.resetDisp() self.watchLog(bal=self.listHideBal) def OpenFile(self, initialdir0="", filetype='*.*'): if filetype != '*.*': filetypes0 = (("Files", filetype), ("All Files", "*.*")) name = askopenfilename(initialdir=initialdir0, filetypes=filetypes0, title="Choose a file.") else: name = askopenfilename(initialdir=initialdir0, title="Choose a file.") return name def close(self): print "close" exit()
class TextBox: def __init__(self): self.WIDTH = 600 self.HEIGHT = 800 self.FONT = "helvetica" self.FONT_SIZE = 12 # colours specified as RGB fractions self.bg_input = [1, 1, 1] self.fg_input = [0, 0, 0] self.bg_article = [0, 0, 0] self.fg_min_article = [0.5, 0.5, 0.5] self.fg_max_article = [0.9, 0.9, 0.9] self.fg_solution_article = [1, 1, 1] #[0.3, 0.5, 1.0] #[1, 0.7, 0.4] invert = False if invert: self.bg_input = [1. - v for v in self.bg_input] self.fg_input = [1. - v for v in self.fg_input] self.bg_article = [1. - v for v in self.bg_article] self.fg_min_article = [1. - v for v in self.fg_min_article] self.fg_max_article = [1. - v for v in self.fg_max_article] self.text = "" # what is shown in the box self.allText = "" # the text for the entire article self.sentences = [] # list of sentences in article # dictionary mapping from size to k-hot encoding indicating # which sentences are in the summary self.solutions = [] # (not used) how much weight is put on each sentence self.weights = [] self.only_summary = True self.summary_size = 1 self.summary_coherence = 0.0 self.summary_independence = 0.8 self.summarizer = Summarizer(parent=self) self.root = Tk() self.draw(init=True) #self.root.mainloop() def draw(self, init=False): if init: # show main article body self.tk_article = ScrolledText(self.root) # let user paste and enter text self.tk_user_input = ScrolledText(self.root) self.tk_summary_size_scale = Scale(self.root) self.tk_summary_size_scale_label = Label(self.root, text="Length") self.tk_summary_coherence_scale = Scale(self.root) self.tk_summary_coherence_scale_label = Label(self.root, text="Coherence") self.tk_summary_independence_scale = Scale(self.root) self.tk_summary_independence_scale_label = Label( self.root, text="Independence") self.tk_toggle_view = Button(self.root, text="more", command=self.handleToggleView) self.tk_recalculate = Button(self.root, text="Update", command=self.handleRecalculate) self.root.geometry("%dx%d" % (self.WIDTH, self.HEIGHT)) self.root.title("QuickReader V4") self.tk_article.configure(width=25, height=6, bd=0, highlightthickness=0, wrap="word", font=self.FONT) self.tk_user_input.configure(width=25, height=3, bd=0, highlightthickness=0, wrap="word", font=self.FONT) self.tk_summary_size_scale.configure( bd=0, from_=0, to=20, orient=HORIZONTAL, sliderrelief=FLAT, command=lambda event: self.handleSlider( self.tk_summary_size_scale.get())) ###### self.tk_summary_coherence_scale.configure( bd=0, from_=0, to=1, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.05, command=lambda event: self.handleCoherenceSlider( self.tk_summary_coherence_scale.get())) self.tk_summary_coherence_scale.set(self.summary_coherence) ###### self.tk_summary_independence_scale.configure( bd=0, from_=0, to=1.5, orient=HORIZONTAL, sliderrelief=FLAT, resolution=0.05, command=lambda event: self.handleIndependenceSlider( self.tk_summary_independence_scale.get())) self.tk_summary_independence_scale.set(self.summary_independence) # set colours self.root.configure(background="black") self.tk_summary_size_scale.configure(troughcolor="#444444", fg="black", background="white", activebackground="#bbbbbb") self.tk_summary_coherence_scale.configure( troughcolor="#444444", fg="black", background="white", activebackground="#bbbbbb") self.tk_summary_independence_scale.configure( troughcolor="#444444", fg="black", background="white", activebackground="#bbbbbb") self.tk_article.configure(bg=toHex(self.bg_article), fg="white", insertbackground="blue") self.tk_article.vbar.configure(bg="white", width=10, troughcolor="black") self.tk_user_input.configure(bg=toHex(self.bg_input), fg=toHex(self.fg_input), insertbackground="blue") self.tk_user_input.vbar.configure(bg="white", width=10, troughcolor="black") self.tk_user_input.focus() self.tk_user_input.bind("<KeyRelease-Return>", (lambda event: self.handleUserInput( self.tk_user_input.get("0.0", END)))) self.root.bind("<Configure>", self.resize) def setText(self, text, redraw=False): self.text = text if redraw: self.updateArticleInfo() def setSentences(self, sentences, redraw=False): self.sentences = sentences if redraw: self.updateArticleInfo() def setSolutions(self, solutions, redraw=False): self.solutions = solutions if redraw: self.updateArticleInfo() def setWeights(self, weights, redraw=False): self.weights = weights if redraw: self.updateArticleInfo() def handleToggleView(self): print("View toggle!") self.only_summary = not self.only_summary if self.only_summary: self.tk_toggle_view.configure(text="more") else: self.tk_toggle_view.configure(text="less") self.updateSummary() def handleRecalculate(self): print("Update!") self.handleUserInput(self.allText) def handleSlider(self, value): print("Slider:", value) self.summary_size = value self.updateSummary() def handleCoherenceSlider(self, value): print("Coherence Slider:", value) self.summary_coherence = value #self.updateSummary() def handleIndependenceSlider(self, value): print("Independence Slider:", value) self.summary_independence = value #self.updateSummary() def updateSummary(self): l = self.summary_size if self.only_summary and l != 0: self.setText('\n\n'.join([ self.sentences[i] for i in range(len(self.sentences)) if self.solutions[l][i] == 1 ])) else: self.setText(self.allText, redraw=False) self.updateArticleInfo() self.setWeights([0. for _ in self.sentences], redraw=True) self.tk_article.yview_moveto(0) #vbar.set(0, 0) #configure(jump=0) def handleUserInput(self, inStr): self.tk_user_input.delete("0.0", END) if inStr.strip() == "": return text = inStr text = ''.join([ch for ch in text if ord(ch) < 128]) self.setText(text, redraw=False) self.setSolutions([], redraw=False) self.setWeights([], redraw=True) text, sentences, solutions = self.summarizer.summarize( text, coherence_weight=self.summary_coherence, independence_weight=self.summary_independence, size_weight=1., beam_width=3, hard_size_limit=None) self.allText = text self.sentences = sentences self.solutions = solutions self.solutions[0] = [1. for _ in sentences] # get max length for summary max_len = max(solutions.keys()) set_len = min(max_len, 3) self.tk_summary_size_scale.configure(from_=0, to=max_len) self.tk_summary_size_scale.set(set_len) self.summary_size = set_len # text: all the text in one long string # sentences: the text split up into a list of sentences # solution: dictionary mapping summary size to a one-hot vector over the sentences, indicating # which sentences are included in the summarization # the text should be the same, but update it anyways since it needs to contain the # exact same stuff as the sentences self.updateSummary() #self.updateArticleInfo() def resize(self, event=[]): LINEH = 20.0 pixelX = self.root.winfo_width() pixelY = self.root.winfo_height() bf = 5 # buffer size in pixels # update find_icon, wiki_icon, and graph_icon # set toggle and recalculate button toggleW = 50 toggleH = 35 * 1 self.tk_toggle_view.place(x=pixelX - toggleW, y=0, width=toggleW, height=toggleH) updateW = 50 updateH = 35 * 2 self.tk_recalculate.place(x=pixelX - updateW, y=toggleH, width=updateW, height=updateH) buttonH = toggleH + updateH labelW = 90 # set position of size scale scaleW = pixelX - updateW - labelW scaleH = 35 self.tk_summary_size_scale.place(x=labelW, y=0, width=scaleW, height=scaleH) self.tk_summary_size_scale_label.place(x=0, y=0, width=labelW, height=scaleH) # set position of coherence scale coherenceW = pixelX - updateW - labelW coherenceH = 35 self.tk_summary_coherence_scale.place(x=labelW, y=scaleH, width=scaleW, height=scaleH) self.tk_summary_coherence_scale_label.place(x=0, y=scaleH, width=labelW, height=coherenceH) # set position of independence scale independenceW = pixelX - updateW - labelW independenceH = 35 self.tk_summary_independence_scale.place(x=labelW, y=scaleH + coherenceH, width=scaleW, height=scaleH) self.tk_summary_independence_scale_label.place(x=0, y=scaleH + coherenceH, width=labelW, height=independenceH) # update user input inputW = pixelX inputH = int(3.0 * LINEH) self.tk_user_input.place(x=0, y=pixelY - inputH, width=inputW, height=inputH) # update article articleW = pixelX articleH = pixelY - inputH - scaleH - coherenceH - independenceH self.tk_article.place(x=0, y=scaleH + coherenceH + independenceH, width=articleW, height=articleH) def updateArticleInfo(self): self.articleClear() self.articleCat(self.text) if self.weights != []: self.articleColour() self.root.update() def articleClear(self): self.tk_article.delete("1.0", END) self.tk_article.update() self.root.update() return def articleCat(self, inStr): self.tk_article.insert(END, inStr) self.tk_article.yview(END) def articleColour(self): ''' solution = self.solutions[self.summary_size] allText = self.text #self.tk_article.get('1.0', 'end-1c') # make sure weights are normalised maxW = max(self.weights) minW = min(self.weights) weights = self.weights if maxW != minW: weights = [(v-minW)/(maxW-minW) for v in self.weights] for i in range(len(self.sentences)): if self.only_summary and solution[i] != 1.: continue s = self.sentences[i] if len(s.strip()) == 0: continue tagNameA = ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(10)]) L_Size = 12 # if solution[i] == 1 else 10 L_Colour = blend(self.fg_min_article, self.fg_max_article, weights[i]) L_Colour = self.fg_solution_article if solution[i] == 1 else L_Colour countVar = StringVar(self.root) pos = self.tk_article.search(s, "1.0", stopindex="end", count=countVar) self.tk_article.tag_add(tagNameA, pos, "{} + {}c".format(pos, countVar.get())) bolding = "normal" #"bold" if self.solution[i] == 1 else "normal" # font = (self.FONT, L_Size, bolding) self.tk_article.tag_config(tagNameA, foreground=toHex(L_Colour), font=font)#self.FONT+' %s'%(L_Size)) self.root.update() ''' solution = self.solutions[self.summary_size] allText = self.text #self.tk_article.get('1.0', 'end-1c') #print("=========") for i in range(len(self.sentences)): if self.only_summary and solution[i] != 1.: continue s = self.sentences[i] #if len(s.strip()) == 0: # continue #print("- ", s) tagNameA = ''.join([ random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(10) ]) L_Size = self.FONT_SIZE # if solution[i] == 1 else 10 L_Colour = self.fg_solution_article if solution[ i] == 1 else self.fg_min_article #print("\t", L_Colour) countVar = StringVar(self.root) pos = self.tk_article.search(s, "1.0", stopindex="end", count=countVar) self.tk_article.tag_add(tagNameA, pos, "{} + {}c".format(pos, countVar.get())) bolding = "normal" #"bold" if self.solution[i] == 1 else "normal" # font = (self.FONT, L_Size, bolding) self.tk_article.tag_config(tagNameA, foreground=toHex(L_Colour), font=font) #self.FONT+' %s'%(L_Size)) self.root.update()
class GrammarGUI: def __init__(self, grammar, text, title='Input Grammar'): self.root = None try: self._root = Tkinter.Tk() self._root.title(title) level1 = Tkinter.Frame(self._root) level1.pack(side='top', fill='none') Tkinter.Frame(self._root).pack(side='top', fill='none') level2 = Tkinter.Frame(self._root) level2.pack(side='top', fill='x') buttons = Tkinter.Frame(self._root) buttons.pack(side='top', fill='none') self.sentence = Tkinter.StringVar() Tkinter.Label(level2, text="Sentence:").pack(side='left') Tkinter.Entry(level2, background='white', foreground='black', width=60, textvariable=self.sentence).pack( side='left') lexiconFrame = Tkinter.Frame(level1) Tkinter.Label(lexiconFrame, text="Lexicon:").pack(side='top', fill='x') Tkinter.Label(lexiconFrame, text=" ex. 'dog N':").pack( side='top', fill='x') self.lexicon = ScrolledText(lexiconFrame, background='white', foreground='black', width=30) self.lexicon.pack(side='top') grammarFrame = Tkinter.Frame(level1) Tkinter.Label(grammarFrame, text="Grammar:").pack(side='top', fill='x') Tkinter.Label(grammarFrame, text=" ex. 'S -> NP VP':").pack(side='top',fill='x') self.grammarRules = ScrolledText(grammarFrame, background='white', foreground='black', width=30) self.grammarRules.pack(side='top') lexiconFrame.pack(side='left') grammarFrame.pack(side='left') Tkinter.Button(buttons, text='Clear', background='#a0c0c0', foreground='black', command=self.clear).pack(side='left') Tkinter.Button(buttons, text='Parse', background='#a0c0c0', foreground='black', command=self.parse).pack(side='left') self.init_menubar() # Enter mainloop. Tkinter.mainloop() except: print 'Error creating Tree View' self.destroy() raise def init_menubar(self): menubar = Tkinter.Menu(self._root) filemenu = Tkinter.Menu(menubar, tearoff=0) filemenu.add_command(label='Save Rules', underline=0, command=self.save, accelerator='Ctrl-s') self._root.bind('<Control-s>', self.save) filemenu.add_command(label='Load Rules', underline=0, command=self.load, accelerator='Ctrl-o') self._root.bind('<Control-o>', self.load) filemenu.add_command(label='Clear Rules', underline=0, command=self.clear, accelerator='Ctrl-r') self._root.bind('<Control-r>', self.clear) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') self._root.bind('<Control-q>', self.destroy) menubar.add_cascade(label='File', underline=0, menu=filemenu) self._root.config(menu=menubar) def getRules(self, makegrammar=True): """ Takes the currently typed in rules and turns them from text into a list of either string rules or Earley CFGs """ text = self.grammarRules.get(1.0, Tkinter.END) rules = [] for item in text.split("\n"): moreitems = item.split(",") for furtheritem in moreitems: furtheritem = furtheritem.strip() if not furtheritem: continue tokens = furtheritem.split() if not (len(tokens)>=3 and tokens[1] == "->"): print "Invalid rule: %s"%furtheritem else: if makegrammar: rules.append(Rule(cfg.Nonterminal(tokens[0]), *map(lambda x: cfg.Nonterminal(x), tokens[2:]))) else: rules.append(furtheritem.strip()) return rules def getLexicon(self, makegrammar=True): """ Takes the currently typed in lexicon and turns them from text into a list of either string lexical definitions or Earley CFGs """ text = self.lexicon.get(1.0, Tkinter.END) lex = [] for item in text.split("\n"): moreitems = item.split(",") for furtheritem in moreitems: furtheritem = furtheritem.strip() if not furtheritem: continue tokens = furtheritem.split() if not len(tokens)>=2: print "Invalid lexical mapping: %s"%furtheritem else: if makegrammar: word = tokens[0] for pos in tokens[1:]: lex.append(Rule(cfg.Nonterminal(pos), word)) else: lex.append(furtheritem.strip()) return lex def parse(self, *args): """ Calls the FullChartViewer with the given grammar and lexicon to parse the given sentence """ grammar = EarleyCFG(cfg.Nonterminal('S'), self.getRules(), self.getLexicon()) sent = self.sentence.get().strip() tok_sent = WSTokenizer().tokenize(sent) print "Starting chart parsing viewer" FullChartViewer(grammar, tok_sent, 'Parsing "%s"'%sent) def save(self, *args): "Save a rule/lexicon set to a text file" from tkFileDialog import asksaveasfilename ftypes = [('Text file', '.txt'), ('All files', '*')] filename = asksaveasfilename(filetypes=ftypes, defaultextension='.txt') if not filename: return f = open(filename, 'w') f.write('---- Rules -----\n%s\n' % '\n'.join(self.getRules(False))) f.write('---- Lexicon -----\n%s\n' % '\n'.join(self.getLexicon(False))) f.close() def load(self, *args): "Load rule/lexicon set from a text file" from tkFileDialog import askopenfilename ftypes = [('Text file', '.txt'), ('All files', '*')] filename = askopenfilename(filetypes=ftypes, defaultextension='.txt') if not filename: return f = open(filename, 'r') lines = f.readlines() f.close() rules = [] lexicon = [] state = 'rules' for line in lines: line = line.strip() if not line: continue elif line.startswith("-"): if line.find("Rules")>0: state = 'rules' else: state = 'lexicon' else: toks = line.split() if state == 'rules' and len(toks)>=3 and toks[1]=='->': rules.append(line) elif state == 'lexicon' and len(toks)>=2: lexicon.append(line) self.clear() self.grammarRules.insert(1.0, '\n'.join(rules)) self.lexicon.insert(1.0, '\n'.join(lexicon)) def clear(self, *args): "Clears the grammar and lexical and sentence inputs" self.grammarRules.delete(1.0, Tkinter.END) self.lexicon.delete(1.0, Tkinter.END) self.sentence.set('') def destroy(self, *args): if self._root is None: return self._root.destroy() self._root = None print self.sentence.get()
class ClustererGui(ttk.Frame): """GUI to open/save xml/text-files and visualize clustering.""" def __init__(self, master=None): """Init GUI - get auto-split-sentences-option and standard test-file-folder from config-file.""" ttk.Frame.__init__(self, master) self.grid(sticky=tk.N + tk.S + tk.E + tk.W) self.createWidgets() self.filepath = None self.xml_filepath = None self.filename = None self.article_id = None self.extraction = None self.author_no = None self.correct = None self.result = None self.colors = [] config = ConfigParser.ConfigParser() config.read("config.cfg") params = dict(config.items("params")) article_dir = params['test_file_dir'] self.auto_split_sentences = bool(int(params['auto_split_sentences'])) self.show_knee_point = bool(int(params['show_knee_point'])) self.show_knee_point = False # currently not supported in GUI-mode self.last_dir = article_dir def createWidgets(self): """Organize GUI.""" top = self.winfo_toplevel() top.rowconfigure(0, weight=1) top.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.rowconfigure(1, weight=0) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=0) left_frame = ttk.Frame(self, relief="raised", borderwidth=1) left_frame.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W) left_frame.rowconfigure(0, weight=0) left_frame.rowconfigure(1, weight=1) left_frame.columnconfigure(0, weight=1) buttons_topleft = ttk.Frame(left_frame) buttons_topleft.grid(row=0, column=0) self.choose_file_btn = ttk.Button(buttons_topleft, text='choose file...', command=self.choose_file) self.choose_file_btn.grid(row=0, column=0) self.save_file_btn = ttk.Button(buttons_topleft, text='save file...', command=self.save_file) self.save_file_btn.grid(row=0, column=1) self.extract_feat_btn = ttk.Button( buttons_topleft, text='process', command=self.start_featureextr_thread) self.extract_feat_btn.grid(row=0, column=2) right_frame = ttk.Frame(self) right_frame.grid(row=0, column=1, sticky=tk.N + tk.S + tk.E + tk.W) right_frame.rowconfigure(0, weight=1) right_frame.rowconfigure(1, weight=1) self.distr_entry = ScrolledText(right_frame, width=30, height=30) self.distr_entry.grid(row=0, column=0, columnspan=2, sticky=tk.N) self.test_entry = ScrolledText(right_frame, width=30) self.test_entry.grid(row=1, column=0, columnspan=2, sticky=tk.N) self.scrolledText = ScrolledText(left_frame, undo=True, wrap=tk.WORD) self.scrolledText['font'] = ('Helvetica', '12') self.scrolledText.tag_configure('lines', background="#dddddd", foreground="black", font=('Helvetica', 9)) self.scrolledText.tag_configure('blanks', background="#ffffff", foreground="black", font=('Helvetica', 9)) self.scrolledText.grid(row=1, column=0, sticky=tk.N + tk.S + tk.E + tk.W) status_bar = ttk.Frame(self) status_bar.grid(row=1, column=0, columnspan=2, sticky=tk.W) status_bar.columnconfigure(0, weight=1, minsize=100) status_bar.columnconfigure(1, weight=1) self.status = tk.StringVar() self.status.set("ready") self.status_label = ttk.Label(status_bar, textvariable=self.status) self.status_label.grid(row=0, column=1, padx=10) self.progressbar = ttk.Progressbar(status_bar, mode='indeterminate', length=200) self.progressbar.grid(row=0, column=0, padx=3) def choose_file(self): """Choose text or xml file dialog.""" self.filepath = askopenfilename(initialdir=self.last_dir, filetypes=(("text and xml files", ("*.txt", "*.xml")), )) if self.filepath: ext = os.path.splitext(self.filepath)[1] if ext == ".xml": '''save raw-text of xml-file to a new file and print it''' self.xml_filepath = self.filepath self.filepath = self.create_text_fromXML() base = os.path.split(self.filepath)[0] self.article_id = os.path.split(base)[1] self.filename = os.path.split(self.filepath)[1] self.scrolledText.delete(1.0, tk.END) self.print_raw_text() self.scrolledText.edit_reset() def create_text_fromXML(self): """Create text-file out of given xml-file.""" new_filepath = os.path.splitext(self.filepath)[0] + ".txt" with codecs.open(self.filepath, 'r', 'UTF-8') as xml_file: xml_tree = etree.parse(xml_file) with codecs.open(new_filepath, 'w', 'UTF-8') as newFile: first_entry = True for entry in xml_tree.getroot(): if entry.text is not None: if not first_entry: newFile.write("\n\n") else: first_entry = False newFile.write(entry.text) return new_filepath def save_file(self): """Save text-file-dialog.""" text = self.scrolledText.get("0.0", tk.END) if self.filepath is None: name = asksaveasfilename(initialdir=self.last_dir, defaultextension=".txt") if name: self.filepath = name else: return try: with codecs.open(self.filepath, 'w', 'UTF-8') as newFile: newFile.write(text.strip()) self.scrolledText.edit_reset() base = os.path.split(self.filepath)[0] self.article_id = os.path.split(base)[1] self.filename = os.path.split(self.filepath)[1] return True except Exception: # as e: raise def start_featureextr_thread(self): """Start thread for feature extraction.""" self.distr_entry.delete(1.0, tk.END) self.status.set("processing...") if self.filepath is None or self.article_id is None: tkMessageBox.showwarning("Save File", "Save file for feature extraction.") return try: self.scrolledText.edit_undo() self.scrolledText.edit_redo() tkMessageBox.showwarning("File changed", "File was changed, please save.") return except tk.TclError: self.extraction = clusterer.Clusterer(self.article_id, self.filepath, self.xml_filepath, self.auto_split_sentences, self.show_knee_point) self.ftr_extr_thread = threading.Thread( target=self.extract_features) self.ftr_extr_thread.daemon = True self.progressbar.start() self.ftr_extr_thread.start() self.after(1000, self.check_feat_thread) def check_feat_thread(self): """Check if feature extraction thread is still working - if not: visualize cluster-results.""" if self.ftr_extr_thread.is_alive(): self.after(1000, self.check_feat_thread) else: self.status.set("ready") # generate author-colormap self.colors = [None] * len(set(self.clusters)) for k in set(self.clusters): temp_color = plt.cm.spectral( np.float(k) / (np.max(self.clusters) + 1)) if k == 0: temp_color = plt.cm.spectral(0.05) self.colors[k] = self.convert_to_hex(temp_color) self.configure_colors() self.progressbar.stop() self.print_author_distr() self.print_text() if self.correct is not None and self.author_no is not None: self.test_entry.delete(1.0, tk.END) s = "authors found: {}".format(len(set(self.clusters))) s += "\n believe-score: {:.4f}".format(self.believe_score) s += "\n\n true number of authors: {}".format(self.author_no) s += "\n precision: {:.4f}".format(self.scores[0]) s += "\n recall: {:.4f}".format(self.scores[1]) s += "\n f1-score: {:.4f}".format(self.scores[2]) s += "\n adjusted-rand-index: {:.4f}".format(self.scores[3]) self.test_entry.insert(tk.INSERT, s) else: self.test_entry.delete(1.0, tk.END) s = "authors found: {}".format(len(set(self.clusters))) s += "\n believe-score: {:.4f}".format(self.believe_score) self.test_entry.insert(tk.INSERT, s) def extract_features(self): """Start feature extraction.""" self.clusters, self.result, self.author_no, self.believe_score, self.scores = self.extraction.calc_cluster( ) if self.result is not None: c = Counter(self.result) self.correct = c[True] / sum(c.values()) * 100 def print_text(self): """Print raw text with specified author-colors.""" self.scrolledText.delete(1.0, tk.END) f = open(self.filepath) line_number = 0 actual_line_number = 0 for line in f: actual_line_number += 1 if line.strip(): s = str(line_number) + ' ' + str( self.clusters[line_number]) + ' ' + line s = line line_cluster = str(line_number) + ' ' + str( self.clusters[line_number]) + ' ' line_cluster = ('{:^' + str(14 - len(line_cluster)) + '}').format(line_cluster) self.scrolledText.insert(tk.INSERT, line_cluster, 'lines') try: self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number])) # if self.result[line_number]: # # correct assignment - print text foreground in white # self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number])) # else: # # false assignment - print text foreground in black # self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number]*10**2)) except IndexError: self.scrolledText.insert(tk.INSERT, s) except TypeError: self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number])) line_number += 1 else: s = line self.scrolledText.insert(tk.INSERT, s, 'blanks') f.close() def print_raw_text(self): """Print raw text.""" f = open(self.filepath) for line in f: self.scrolledText.insert(tk.INSERT, line) f.close() def get_distribution(self, l=None): """Return Counter with author distribution in percent.""" if l is None: l = self.clusters counter = Counter(l) sum_counter = sum(counter.values()) for key in counter.iterkeys(): counter[key] = counter[key] / sum_counter * 100 return counter def print_author_distr(self): """Print author distribution with specified author-colors.""" self.distr_entry.delete(1.0, tk.END) distr = self.get_distribution(self.clusters) for index, count in distr.most_common(): author_i = "author " + str(index) + "{:>20}%\n".format( locale.format(u'%.2f', count)) self.distr_entry.insert(tk.INSERT, author_i, str(index)) def convert_to_hex(self, col): """Convert inter-tuple to hex-coded string.""" red = int(col[0] * 255) green = int(col[1] * 255) blue = int(col[2] * 255) return '#{r:02x}{g:02x}{b:02x}'.format(r=red, g=green, b=blue) def configure_colors(self): """Configure author-specific colors for author-distribution and cluster-results.""" for i, c in enumerate(self.colors): self.scrolledText.tag_configure(str(i), background=c, foreground="white") self.distr_entry.tag_configure(str(i), background=c, foreground="white")
class App: def __init__(self, master): class IORedirector(object): def __init__(self, stext): self.stext = stext class StdoutRedirector(IORedirector): def write(self, str): self.stext.insert(END, str) self.skip_apnx = BooleanVar() self.is_azw = BooleanVar() self.is_log = BooleanVar() self.nac = IntVar() self.is_overwrite_pdoc_thumbs = BooleanVar() self.is_overwrite_amzn_thumbs = BooleanVar() self.is_overwrite_apnx = BooleanVar() self.kindlepath = StringVar() self.status = StringVar() self.days = StringVar() self.frame = Frame(master, borderwidth=5) self.frame.pack(side=TOP, anchor=W) self.chk_button = Button(self.frame, text="Choose Kindle", command=self.askdirectory, width=15) self.chk_button.pack(side=LEFT) self.kindle_label = Label(self.frame, textvariable=self.kindlepath) self.kindle_label.pack(side=LEFT) self.frame2 = Frame(master, borderwidth=5) self.frame2.pack(side=TOP, pady=5) self.frame3 = Frame( self.frame2, ) self.frame3.pack(side=TOP, anchor=W) self.days_entry = Entry( self.frame3, width=4, textvariable=self.days, state=DISABLED ) self.days_entry.pack(side=RIGHT, anchor=NW) self.days_checkbox = Checkbutton( self.frame3, text="Process only younger files than days provided: ", variable=self.nac, command=self.naccheck ) self.days_checkbox.deselect() self.days_checkbox.pack(side=TOP, anchor=NW) self.log_checkbox = Checkbutton( self.frame2, text="Write less informations in Message Window?", variable=self.is_log ) self.log_checkbox.deselect() self.log_checkbox.pack(side=TOP, anchor=NW) self.apnx_checkbox = Checkbutton( self.frame2, text="Skip generating book page numbers " "(APNX files)?", variable=self.skip_apnx ) self.apnx_checkbox.deselect() self.apnx_checkbox.pack(side=TOP, anchor=NW) self.labelframe = LabelFrame( self.frame2, text=" For special needs. Use with caution! ", padx=5, pady=5 ) self.labelframe.pack(fill="both", expand="yes", pady=10) self.over_pdoc_thumbs_checkbox = Checkbutton( self.labelframe, text="Overwrite existing personal documents (PDOC) covers?", variable=self.is_overwrite_pdoc_thumbs ) self.over_pdoc_thumbs_checkbox.deselect() self.over_pdoc_thumbs_checkbox.pack(side=TOP, anchor=NW) self.over_amzn_thumbs_checkbox = Checkbutton( self.labelframe, text="Overwrite existing amzn book (EBOK) and book sample (EBSP) " "covers?", variable=self.is_overwrite_amzn_thumbs ) self.over_amzn_thumbs_checkbox.deselect() self.over_amzn_thumbs_checkbox.pack(side=TOP, anchor=NW) self.over_apnx_checkbox = Checkbutton( self.labelframe, text="Overwrite existing book page numbers (APNX files)?", variable=self.is_overwrite_apnx ) self.over_apnx_checkbox.deselect() self.over_apnx_checkbox.pack(side=TOP, anchor=NW) self.azw_checkbox = Checkbutton( self.labelframe, text="Extract covers from AZW files?", variable=self.is_azw ) self.azw_checkbox.deselect() self.azw_checkbox.pack(side=TOP, anchor=NW) self.frame3 = Frame(master, borderwidth=5) self.frame3.pack(side=TOP, anchor=W) self.run_button = Button(self.frame3, text="Start", command=self.run, width=15) self.run_button.pack(side=LEFT) self.status_label = Label(self.frame3, textvariable=self.status) self.status_label.pack(side=LEFT, pady=5) self.frame4 = Frame(master, borderwidth=5) self.frame4.pack(side=TOP) self.msg1 = 'Message Window: \n' self.stext = ScrolledText(self.frame4, bd=1, wrap=WORD, height=25, width=100, relief=RIDGE) if sys.platform == 'win32': self.stext.config(font=('Courier', 9, 'normal')) self.stext.pack() self.stext.insert(END, self.msg1) sys.stdout = StdoutRedirector(self.stext) def naccheck(self): if self.nac.get() == 0: self.days_entry.delete(0, END) self.days_entry.configure(state='disabled') else: self.days_entry.configure(state='normal') def run(self): self.docs = os.path.join(self.kindlepath.get(), 'documents') self.stext.delete(1.0, END) self.status.set('Start processing your books...') tkMessageBox.showwarning( 'Starting...', 'Process is starting. Click OK button and wait for ' + 'finish confirmation...', icon='question', parent=root ) self.frame.update_idletasks() if self.days.get() == '': ec = extract_cover_thumbs( self.is_log.get(), self.is_overwrite_pdoc_thumbs.get(), self.is_overwrite_amzn_thumbs.get(), self.is_overwrite_apnx.get(), self.skip_apnx.get(), self.kindlepath.get(), self.docs, self.is_azw, None ) else: ec = extract_cover_thumbs( self.is_log.get(), self.is_overwrite_pdoc_thumbs.get(), self.is_overwrite_amzn_thumbs.get(), self.is_overwrite_apnx.get(), self.skip_apnx.get(), self.kindlepath.get(), self.docs, self.is_azw, self.days.get() ) if ec == 0: self.status.set('Process finished.') tkMessageBox.showwarning( 'Finished...', 'Process finished. Check Message Window for details...', icon='info', parent=root ) elif ec == 1: self.status.set('Process finished with PROBLEMS!') tkMessageBox.showwarning( 'Finished...', 'Process finished with PROBLEMS! ' + 'Check Message Window for details...', icon='warning', parent=root ) def askdirectory(self): if sys.platform == 'win32': a = tkFileDialog.askdirectory(initialdir="c:/") else: a = tkFileDialog.askdirectory(initialdir="/") self.kindlepath.set(str(a.encode(sys.getfilesystemencoding())))
class Tkui(base.BaseUI): """ This is a ui class which handles the complete Tk user interface. """ def __init__(self): """ Initializes.""" base.BaseUI.__init__(self) # internal ui queue self._event_queue = Queue.Queue() # map of session -> (bold, foreground, background) self._currcolors = {} # ses -> string self._unfinishedcolor = {} self._viewhistory = 0 self._do_i_echo = 1 # holds a map of window names -> window references self._windows = {} # instantiate all the widgets self._tk = Tk() self._tk.geometry("800x600") self.settitle() if os.name == "posix": fnt = tkFont.Font(family="Courier", size=12) else: fnt = tkFont.Font(family="Fixedsys", size=12) self._entry = CommandEntry( self._tk, self, fg="white", bg="black", insertbackground="yellow", font=fnt, insertwidth="2" ) self._entry.pack(side="bottom", fill="both") self._topframe = Frame(self._tk) self._topframe.pack(side="top", fill="both", expand=1) self._txt = ScrolledText(self._topframe, fg="white", bg="black", font=fnt, height=20) self._txt.pack(side="bottom", fill="both", expand=1) self._txt.bind("<KeyPress>", self._ignoreThis) self._txtbuffer = ScrolledText(self._topframe, fg="white", bg="black", font=fnt, height=20) self._txtbuffer.bind("<KeyPress-Escape>", self.escape) self._txtbuffer.bind("<KeyPress>", self._ignoreThis) self._entry.focus_set() self._initColorTags() self.dequeue() exported.hook_register("config_change_hook", self.configChangeHandler) exported.hook_register("to_user_hook", self.write) # FIXME - fix this explanation. this is just terrible. tc = config.BoolConfig( "saveinputhighlight", 0, 1, "Allows you to change the behavior of the command entry. When " "saveinputhighlight is off, we discard whatever is on the entry " "line. When it is on, we will retain the contents allowing you " "to press the enter key to do whatever you typed again.", ) exported.add_config("saveinputhighlight", tc) self._quit = 0 def runui(self): global HELP_TEXT exported.add_help("tkui", HELP_TEXT) exported.write_message('For tk help type "#help tkui".') exported.add_command("colorcheck", colorcheck_cmd) # run the tk mainloop here self._tk.mainloop() def wantMainThread(self): # The tkui needs the main thread of execution so we return # a 1 here. return 1 def quit(self): if not self._quit: self._quit = 1 self._topframe.quit() def dequeue(self): qsize = self._event_queue.qsize() if qsize > 10: qsize = 10 for i in range(qsize): ev = self._event_queue.get_nowait() ev.execute(self) self._tk.after(25, self.dequeue) def settitle(self, title=""): """ Sets the title bar to the Lyntin title plus the given string. @param title: the title to set @type title: string """ if title: title = constants.LYNTINTITLE + title else: title = constants.LYNTINTITLE self._event_queue.put(_TitleEvent(self._tk, title)) def removeWindow(self, windowname): """ This removes a NamedWindow from our list of NamedWindows. @param windowname: the name of the window to write to @type windowname: string """ if self._windows.has_key(windowname): del self._windows[windowname] def writeWindow(self, windowname, message): """ This writes to the window named "windowname". If the window does not exist, we spin one off. It handles ansi text and messages just like writing to the main window. @param windowname: the name of the window to write to @type windowname: string @param message: the message to write to the window @type message: string or Message instance """ self._event_queue.put(_WriteWindowEvent(windowname, message)) def writeWindow_internal(self, windowname, message): if not self._windows.has_key(windowname): self._windows[windowname] = NamedWindow(windowname, self, self._tk) self._windows[windowname].write(message) def _ignoreThis(self, tkevent): """ This catches keypresses from the history buffer.""" # kludge so that ctrl-c doesn't get caught allowing windows # users to copy the buffer.... if tkevent.keycode == 17 or tkevent.keycode == 67: return self._entry.focus() if tkevent.char: # we do this little song and dance so as to pass events # we don't want to deal with to the entry widget essentially # by creating a new event and tossing it in the event list. # it only sort of works--but it's the best code we've got # so far. args = ("event", "generate", self._entry, "<KeyPress>") args = args + ("-rootx", tkevent.x_root) args = args + ("-rooty", tkevent.y_root) args = args + ("-keycode", tkevent.keycode) args = args + ("-keysym", tkevent.keysym) self._tk.tk.call(args) return "break" def pageUp(self): """ Handles prior (Page-Up) events.""" if self._viewhistory == 0: self._txtbuffer.pack(side="top", fill="both", expand=1) self._viewhistory = 1 self._txtbuffer.delete("1.0", "end") lotofstuff = self._txt.get("1.0", "end") self._txtbuffer.insert("end", lotofstuff) for t in self._txt.tag_names(): taux = None tst = 0 for e in self._txt.tag_ranges(t): if tst == 0: taux = e tst = 1 else: tst = 0 self._txtbuffer.tag_add(t, str(taux), str(e)) self._txtbuffer.yview("moveto", "1") if os.name != "posix": self._txtbuffer.yview("scroll", "20", "units") self._tk.update_idletasks() self._txt.yview("moveto", "1.0") if os.name != "posix": self._txt.yview("scroll", "220", "units") else: # yscroll up stuff self._txtbuffer.yview("scroll", "-15", "units") def pageDown(self): """ Handles next (Page-Down) events.""" if self._viewhistory == 1: # yscroll down stuff self._txtbuffer.yview("scroll", "15", "units") def escape(self, tkevent): """ Handles escape (Escape) events.""" if self._viewhistory == 1: self._txtbuffer.forget() self._viewhistory = 0 else: self._entry.clearInput() def configChangeHandler(self, args): """ This handles config changes including mudecho. """ name = args["name"] newvalue = args["newvalue"] if name == "mudecho": if newvalue == 1: # echo on self._do_i_echo = 1 self._entry.configure(show="") else: # echo off self._do_i_echo = 0 self._entry.configure(show="*") def _yadjust(self): """Handles y scrolling after text insertion.""" self._txt.yview("moveto", "1") # if os.name != 'posix': self._txt.yview("scroll", "20", "units") def _clipText(self): """ Scrolls the text buffer up so that the new text written at the bottom of the text buffer can be seen. """ temp = self._txt.index("end") ind = temp.find(".") temp = temp[:ind] if temp.isdigit() and int(temp) > 800: self._txt.delete("1.0", "100.end") def write(self, args): """ This writes text to the text buffer for viewing by the user. This is overridden from the 'base.BaseUI'. """ self._event_queue.put(_OutputEvent(args)) def write_internal(self, args): mess = args["message"] if type(mess) == types.StringType: mess = message.Message(mess, message.LTDATA) line = mess.data ses = mess.session if line == "" or self.showTextForSession(ses) == 0: return color, leftover = buffer_write(mess, self._txt, self._currcolors, self._unfinishedcolor) if mess.type == message.MUDDATA: self._unfinishedcolor[ses] = leftover self._currcolors[ses] = color self._clipText() self._yadjust() def convertColor(self, name): """ Tk has this really weird color palatte. So I switched to using color names in most cases and rgb values in cases where I couldn't find a good color name. This method allows me to specify either an rgb or a color name and it converts the color names to rgb. @param name: either an rgb value or a name @type name: string @returns: the rgb color value @rtype: string """ if name.startswith("#"): return name rgb = self._tk._getints(self._tk.tk.call("winfo", "rgb", self._txt, name)) rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256) print name, "converted to: ", rgb return rgb def _initColorTags(self): """ Sets up Tk tags for the text widget (fg/bg/u).""" for ck in fg_color_codes.keys(): color = self.convertColor(fg_color_codes[ck]) self._txt.tag_config(ck, foreground=color) self._txtbuffer.tag_config(ck, foreground=color) for ck in bg_color_codes.keys(): self._txt.tag_config(ck, background=bg_color_codes[ck]) self._txtbuffer.tag_config(ck, background=bg_color_codes[ck]) self._txt.tag_config("u", underline=1) self._txtbuffer.tag_config("u", underline=1) def colorCheck(self): """ Goes through and displays all the combinations of fg and bg with the text string involved. Purely for debugging purposes. """ fgkeys = ["30", "31", "32", "33", "34", "35", "36", "37"] bgkeys = ["40", "41", "42", "43", "44", "45", "46", "47"] self._txt.insert("end", "color check:\n") for bg in bgkeys: for fg in fgkeys: self._txt.insert("end", str(fg), (fg, bg)) self._txt.insert("end", str("b" + fg), ("b" + fg, bg)) self._txt.insert("end", "\n") for fg in fgkeys: self._txt.insert("end", str(fg), (fg, "b" + bg)) self._txt.insert("end", str("b" + fg), ("b" + fg, "b" + bg)) self._txt.insert("end", "\n") self._txt.insert("end", "\n") self._txt.insert("end", "\n")
class TermWindow(Frame): ## # constructor method def __init__(self, master = None, **cnf): apply(Frame.__init__, (self, master), cnf) self.__create_widgets__() self.rxThread = None self.rxWaitEvent = threading.Event() self.rxWaitPattern = "" self.localEcho = False self.logFile = None self.textQueue = Queue.Queue() self.update_thread_safe() def update_thread_safe(self): try: while 1: element = self.textQueue.get_nowait() if element is not None: msg,tag = element self.__display__(msg,tag) self.st_trm.update_idletasks() except Queue.Empty: pass self.st_trm.after(100, self.update_thread_safe) ## # worker function for threaded reading from the input of # the assigned device # def __thrd_reader__(self): self.waitbuf = "" while 1: try: x = self.device.read() if len(x): cmd = self.cmdVar.get() if len(cmd): self.cmdVar.set("") self.write(x) if self.rxWaitEvent.isSet(): self.waitbuf += x if self.waitbuf.find(self.rxWaitPattern) > -1: self.rxWaitEvent.clear() while not self.rxWaitEvent.isSet(): pass self.rxWaitEvent.clear() except: traceback.print_exc() time.sleep(1) else: # this infinitesimal sleep keeps the GUI update alive time.sleep(.01) def waitfor(self, pattern, maxwait=10): self.waitbuf = "" self.rxWaitPattern = pattern self.rxWaitEvent.set() self.maxwait = 10 while self.rxWaitEvent.isSet() and self.maxwait > 0: time.sleep(1) self.maxwait -= 1 if self.maxwait == 0: self.message("PatternNotFound") self.rxWaitEvent.set() ## # def __create_widgets__(self): dfl_font = 'Courier 10' # the title frame of the terminal self.f_title = Frame(self) self.f_title.pack(fill=BOTH) self.f_title.configure(FRAMEBORDER) self.shVar = StringVar() # show/hide button self.b_sh = Button(self.f_title, textvariable=self.shVar, font=dfl_font) self.b_sh.pack(side=RIGHT) self.b_sh['command'] = self.show_hide_cont # clear screen button self.b_cls = Button(self.f_title, text="CLS", font=dfl_font, underline=0) self.b_cls.pack(side=RIGHT) self.b_cls['command'] = self.clear_screen # echo on/off button self.al_echo = Label(self.f_title, text = "ECHO", relief = RAISED, font = dfl_font, padx='3m', pady='1m', underline=0) self.al_echo.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.al_echo.bind("<Button-1>", self.__echo_handler__) # log on/off button self.al_log = Label(self.f_title, text = "LOG", relief = RAISED, font = dfl_font, padx='3m', pady='1m', underline=0) self.al_log.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.al_log.bind("<Button-1>", self.__log_handler__) # device connect button self.al_connect = Label(self.f_title, text = "CONNECT", relief = RAISED, font = dfl_font, padx='3m', pady='1m', underline=1) self.al_connect.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.al_connect.bind("<Button-1>", self.__connect_handler__) self.mb_macros = Menubutton(self.f_title, text = "Macros", relief=RAISED) self.mb_macros.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.mb_macros.menu = Menu(self.mb_macros, tearoff = 0) self.mb_macros["menu"] = self.mb_macros.menu # title of terminal window self.tVar = StringVar() self.l_title = Label(self.f_title, text="foo", font=dfl_font) self.l_title['textvariable'] = self.tVar self.l_title.pack(side=LEFT, expand=1, fill=X) self.l_title['width'] = 42 self.update_title("------ XXX ------") # frame for scrolled text window # (this frame handle needs to be kept fo show_hide_cont()) self.f_cont = Frame(self) # IO data scrolled text window self.st_trm = ScrolledText(self.f_cont, height=10, state=DISABLED, wrap=NONE) self.st_trm.pack(expand=1,fill=BOTH) self.st_trm['font'] = dfl_font self.st_trm.tag_config('E', foreground="blue") self.st_trm.tag_config('M', foreground="magenta") tframe = Frame(self.f_cont) tframe.pack(expand = 0, fill = X) self.cmdVar = StringVar() self.ent_trm = Entry(tframe, textvariable=self.cmdVar, font=dfl_font) self.ent_trm.pack(side=LEFT, expand =1, fill = X) self.ent_trm.bind("<Control-l>", self.__log_handler__) self.ent_trm.bind("<Control-e>", self.__echo_handler__) self.ent_trm.bind("<Control-o>", self.__connect_handler__) self.ent_trm.bind("<Control-c>", self.clear_screen) self.ent_trm.bind("<Control-x>", self.show_hide_cont) self.ent_trm.bind("<Control-m>", lambda *args: self.do_macro("M")) self.ent_trm.bind("<KeyPress>", self.__input_handler__) self.gui_elements = [ self.b_sh, self.b_cls, self.al_echo, self.al_log, self.al_connect, self.mb_macros, self.l_title, self.st_trm, self.ent_trm] self.show_cont() def add_macro(self, id, title, text = None, function = None, params = None): if text: cmd = lambda *args: self.do_macro(text) if function: user_func = eval(function) params = eval(str(params)) cmd = lambda *args: user_func(DEVICES, **params) mb = self.mb_macros.menu.add_command(label = title, command = cmd) def _configure_(self,**args): for e in self.gui_elements: e.configure(args) def __input_handler__(self, *args): for i in args: if self.localEcho: self.display(i.char, "E") if len(i.char): if i.char == "\r": self.device.write("\r\n") self.cmdVar.set("") else: self.device.write(i.char) def __echo_handler__(self, *args): if self.localEcho: self.localEcho = False self.al_echo['relief'] = RAISED self.message("Local Echo OFF") else: self.localEcho = True self.al_echo['relief'] = SUNKEN self.message("Local Echo ON") def __log_handler__(self, *args): try: do_open = self.logFile.closed logname = self.logFile.name except: do_open = True logname = "" if do_open: if self.device.logname: logname = self.device.logname self.message("logfile from config file %s " % logname) else: fd = FileDialog(self) logname = fd.go(logname) try: if self.device.logmode not in "wa": self.device.logmode = "a" print "force _a_ppend" self.logFile = open(logname, self.device.logmode) self.al_log['relief'] = SUNKEN self.message("Logging ON: %s" % self.logFile.name) except: self.message("Error open logfile: %s" % logname) else: self.message("Logging OFF: %s" % self.logFile.name) self.logFile.flush() self.logFile.close() self.al_log['relief'] = RAISED def __connect_handler__(self, *args): if self.device.isConnected: self.device.disconnect() self.al_connect['relief'] = RAISED self.message("Disconnected") else: try: self.device.connect() self.al_connect['relief'] = SUNKEN self.message("Connected") self.al_connect['fg'] = "black" except: self.device.isConnected = False self.message( str(sys.exc_info()[1]) ) self.al_connect['fg'] = "red" def clear_screen(self, *args): self.st_trm['state'] = NORMAL self.st_trm.delete("0.0",END) self.st_trm['state'] = DISABLED def set_device(self,device): self.device = device self.rxThread = threading.Thread(target = self.__thrd_reader__) # if a thread is not a daemon, the program needs to join all self.rxThread.setDaemon(1) print "**",self.device, self.device.name self.rxThread.setName("GUI_RX_%s" % self.device.name) self.rxThread.start() self.update_title(self.device) # if self.device.echo: self.localEcho = 0 self.__echo_handler__() if self.device.log: self.__log_handler__() if self.device.auto_connect: self.__connect_handler__() def update_title(self, title): self.tVar.set(title) def show_cont(self): self.shVar.set("X") self.f_cont.pack(expand=1,fill=BOTH) def hide_cont(self): self.shVar.set("+") self.f_cont.pack_forget() def show_hide_cont(self, *args): if self.shVar.get() == "X": self.hide_cont() else: self.show_cont() def do_macro(self, *args): if self.localEcho: self.display(args[0] + "\n", "E") self.device.write(args[0]+ "\n") def write(self, data): self.textQueue.put((data, None)) def message(self, text, tag='M'): msg = "[%s:%s:%s]\n" % (time.asctime(),self.device.name, text) if self.st_trm.index(AtInsert()).find(".0") < 1: msg = "\n" + msg self.textQueue.put((msg, tag)) def display(self, text, tag = None): self.textQueue.put((text, tag)) def __display__(self, msg, tag = None): self.st_trm['state'] = NORMAL here = self.st_trm.index(AtInsert()) for d in re.split("([\r\v\t\n])", msg): if len(d): if d != '\r': self.st_trm.insert(END, d) if tag: self.st_trm.tag_add(tag, here, AtInsert()) self.st_trm.see(END) self.st_trm['state'] = DISABLED try: self.logFile.write(msg) self.logFile.flush() except: pass
class Crawler_plusplus(): def __init__(self): self.rt = tk.Tk() #创建窗口 self.rt.title('Automatically download pictures') #窗口标题 self.menu = tk.Menu(self.rt) #在根窗口里创建一个菜单 self.rt.config(menu=self.menu) #把新创建菜单定为根窗口的菜单 self.aboutmenu = tk.Menu(self.menu) #在根窗口菜单里创建一个菜单 self.picturemenu = tk.Menu(self.menu) #在根窗口菜单里创建一个菜单 self.aboutmenu.add_command(label='help', command=self.help) #菜单里的菜单增加“help”命令 self.menu.add_cascade(label='About', menu=self.aboutmenu) #把菜单里的菜单命名为about self.menu.add_cascade(label='Picture Proecessing', menu=self.picturemenu) self.picturemenu.add_command(label='Start Proecessing', command=self.Picture_Processing) self.menu.add_command(label='refresh', command=self.refresh) self.menu.add_command(label='Exit', command=self.close) self.frame1 = tk.Frame(self.rt, height=260, width=520) #左边模块,负责爬取百度图片 self.middle = tk.Frame(self.rt, height=260, width=120) #右边模块,用来提示错误信息 self.lframe1 = tk.LabelFrame(self.frame1, height=60, width=520, text='Save path') self.lframe2 = tk.LabelFrame(self.frame1, height=200, width=520, text='Download') self.b1 = tk.Button(self.lframe1, text='Choose', width=8, height=1, command=self.get_directory1) self.b2 = tk.Button(self.lframe1, text='Confirm', width=10, height=1, command=self.confirm_e) self.b3 = tk.Button(self.lframe1, text='Cancel', width=10, height=1, command=self.deconfirm_e, state='disabled') self.a1 = tk.Button(self.lframe2, text='Get the picture', width=10, height=1, command=self.start_cr, state='disabled') self.e1 = tk.Entry(self.lframe1, takefocus=True) self.e2 = tk.Entry(self.lframe2, state='disabled') self.alo = tk.Label(self.rt, text='Note:') #中间模块的内容 self.ala = tk.Label(self.rt, text='', foreground='red') #中间模块的错误提示,内容现在是空的 self.l1 = tk.Label(self.lframe2, text='Key words:', relief='flat') self.l2 = tk.Label(self.lframe2, text='Download progress:', relief='groove') self.s = ScrolledText(self.lframe2, height=8, width=40, state='disabled', wrap='char', borderwidth=0) self.frame1.grid(column=0, row=0, rowspan=2, columnspan=1) self.lframe1.grid(row=0, column=1) self.b1.place(x=45, y=15, anchor='center') self.e1.place(x=280, y=15, anchor='e') self.b2.place(x=400, y=15, anchor='e') self.b3.place(x=480, y=15, anchor='e') self.lframe2.grid(row=1, column=1) self.l1.place(x=130, y=15, anchor='e') self.e2.place(x=280, y=15, anchor='e') self.a1.place(x=400, y=15, anchor='e') self.l2.place(x=15, y=45, anchor='w') self.s.place(x=15, y=115, anchor='w') self.middle.grid(column=1, row=0) self.ala.place(x=580, y=140, anchor='center') self.alo.place(x=580, y=120, anchor='center') #图形处理界面 def Picture_Processing(self): top = tk.Toplevel() top.title('Picture Processing') top.geometry('520x260') self.frame2 = tk.Frame(top, height=260, width=520) #框架 用来批量处理图片 self.lframe3 = tk.LabelFrame(self.frame2, height=140, width=520, text='图片预处理') self.lframe4 = tk.LabelFrame(self.frame2, height=60, width=520, text='保存图片集') self.lframe5 = tk.LabelFrame(self.frame2, height=60, width=520, text='预处理图片路径选择') self.b4 = tk.Button(self.lframe5, text='选择图片目录', width=12, height=1, command=self.get_directory5) self.b5 = tk.Button(self.lframe5, text='确定该目录', width=10, height=1, command=self.confirm_e1) self.b6 = tk.Button(self.lframe5, text='取消确定', width=10, height=1, command=self.deconfirm_e1, state='disabled') self.a2 = tk.Button(self.lframe3, text='图片处理启动', width=10, height=1, command=self.start_pi, state='disabled') self.ad = tk.Button(self.lframe4, text='选择保存文件夹', width=14, height=1, command=self.get_directory4, state='disabled') self.a3 = tk.Button(self.lframe4, text='确定该目录', width=10, height=0, command=self.confirm_e2, state='disabled') self.a4 = tk.Button(self.lframe4, text='取消确定', width=10, height=0, command=self.deconfirm_e2, state='disabled') self.a5 = tk.Button(self.lframe3, text='默认设置', width=10, height=1, command=self.reset, state='disabled') self.e3 = tk.Entry(self.lframe5, takefocus=True) self.e4 = tk.Entry(self.lframe4, takefocus=True, state='disabled') self.alb = tk.Label(self.lframe5, text='', foreground='red') self.l3 = tk.Label(self.lframe3, text='处理进度:', relief='groove') self.xlen = tk.IntVar() self.xlen.set(128) self.ylen = tk.IntVar() self.ylen.set(128) self.xl = tk.Entry(self.lframe3, state='readonly', width=4, textvariable=self.xlen, invcmd=self.alarm) self.yl = tk.Entry(self.lframe3, state='readonly', width=4, textvariable=self.ylen, invcmd=self.alarm) self.xv = tk.Label(self.lframe3, text='输出图宽:') self.yv = tk.Label(self.lframe3, text='输出图高:') self.note1 = tk.Label(self.lframe3, text='建议输出\n128*128') self.s1 = ScrolledText(self.lframe3, height=6, width=40, state='disabled', borderwidth=0) self.color = tk.IntVar() self.color.set(0) self.rb1 = tk.Radiobutton(self.lframe3, text='灰色', variable=self.color, value=0, state='disabled') self.rb2 = tk.Radiobutton(self.lframe3, text='彩色', variable=self.color, value=1, state='disabled') self.cls = tk.Label(self.lframe3, text='输出图片颜色') self.type = tk.Label(self.lframe3, text='输出图片格式') self.type.place(x=75, y=5, anchor='w') self.ty = tk.IntVar() self.ty.set(0) self.rb3 = tk.Radiobutton(self.lframe3, text='jpg', variable=self.ty, value=0, state='disabled') self.rb4 = tk.Radiobutton(self.lframe3, text='png', variable=self.ty, value=1, state='disabled') self.rb5 = tk.Radiobutton(self.lframe3, text='jpeg', variable=self.ty, value=2, state='disabled') self.rb3.place(x=150, y=5, anchor='w') self.rb4.place(x=200, y=5, anchor='w') self.rb5.place(x=250, y=5, anchor='w') self.a3.place(x=400, y=45, anchor='e') self.a4.place(x=480, y=45, anchor='e') self.frame2.grid(column=2, row=0, rowspan=3, columnspan=1) self.lframe5.grid(column=0, row=0) self.b4.place(x=80, y=15, anchor='center') self.e3.place(x=280, y=15, anchor='e') self.b5.place(x=400, y=15, anchor='e') self.b6.place(x=480, y=15, anchor='e') self.alb.place(x=550, y=15, anchor='e') self.lframe4.grid(column=0, row=1) self.ad.place(x=80, y=15, anchor='center') self.e4.place(x=280, y=15, anchor='e') self.a3.place(x=400, y=15, anchor='e') self.a4.place(x=480, y=15, anchor='e') self.lframe3.grid(column=0, row=2) self.l3.place(x=15, y=15, anchor='w') self.s1.place(x=15, y=70, anchor='w') self.xv.place(x=330, y=30, anchor='w') self.xl.place(x=390, y=30, anchor='w') self.yv.place(x=330, y=60, anchor='w') self.yl.place(x=390, y=60, anchor='w') self.note1.place(x=420, y=45, anchor='w') self.rb1.place(x=380, y=5, anchor='w') self.rb2.place(x=440, y=5, anchor='w') self.cls.place(x=305, y=5, anchor='w') self.a2.place(x=480, y=90, anchor='e') self.a5.place(x=400, y=90, anchor='e') #打开readme.txt文件查看帮助 def help(self): os.system('notepad.exe readme.txt') #程序功能无法使用时刷新,重新启动该脚本 def refresh(self): self.quit() os.system('python root.py') #运行程序,打开窗口 def run(self): self.rt.mainloop() #爬图前确认图片关键字是否存在 def start_cr(self): word = self.e2.get() if word != '': st = askyesno(title='确认开始', message='确定开始下载图片?这会有一段时间的卡顿,中途不要退出页面') if st: self.start_in() #图片关键字存在,开始爬图 else: self.s.config(state='normal') self.s.delete(1.0, 'end') self.s.insert('end', '请先输入图片关键字(如:周杰伦)') self.s.config(state='disabled') def close(self): cl = askyesno(title='确认关闭', message='确定要关闭吗?') if cl: self.quit() def quit(self): self.rt.destroy() def confirm_e(self): path = self.e1.get() if path == '': self.ala.config(text='请先选择图片保存目录!') elif os.path.exists(path) is False: self.ala.config(text='该路径不存在!') else: self.ala.config(text='') self.e1.config(state='disabled') self.e2.config(state='normal') self.b1.config(state='disabled') self.b2.config(state='disabled') self.b3.config(state='normal') self.a1.config(state='normal') def confirm_e1(self): path = self.e3.get() if path == '': self.ala.config(text='请先选择图片目录!') elif os.path.exists(path) is False: self.ala.config(text='该路径不存在!') else: self.ala.config(text='') self.b4.config(state='disabled') self.b5.config(state='disabled') self.e3.config(state='disabled') self.e4.config(state='normal') self.b6.config(state='normal') self.ad.config(state='normal') self.a3.config(state='normal') def confirm_e2(self): path = self.e4.get() if path == '': self.ala.config(text='请先选择图片保存目录!') elif os.path.exists(path) is False: self.ala.config(text='该路径不存在!') else: self.ala.config(text='') self.b6.config(state='disabled') self.ad.config(state='disabled') self.e4.config(state='disabled') self.a3.config(state='disabled') self.a4.config(state='normal') self.rb1.config(state='normal') self.rb2.config(state='normal') self.rb3.config(state='normal') self.rb4.config(state='normal') self.rb5.config(state='normal') self.xl.config(state='normal') self.yl.config(state='normal') self.a2.config(state='normal') self.a5.config(state='normal') def deconfirm_e(self): self.e1.config(state='normal') self.e2.config(state='disabled') self.b1.config(state='normal') self.b2.config(state='normal') self.b3.config(state='disabled') self.a1.config(state='disabled') self.a3.config(state='disabled') self.s.config(state='disabled') def deconfirm_e1(self): self.b4.config(state='normal') self.b5.config(state='normal') self.e3.config(state='normal') self.e4.config(state='disabled') self.b6.config(state='disabled') self.ad.config(state='disabled') self.a3.config(state='disabled') def deconfirm_e2(self): self.b6.config(state='normal') self.ad.config(state='normal') self.e4.config(state='normal') self.a3.config(state='normal') self.a4.config(state='disabled') self.b6.config(state='normal') self.ad.config(state='normal') self.e4.config(state='normal') self.a3.config(state='normal') self.a4.config(state='disabled') self.rb1.config(state='disabled') self.rb2.config(state='disabled') self.rb3.config(state='disabled') self.rb4.config(state='disabled') self.rb5.config(state='disabled') self.xl.config(state='disabled') self.yl.config(state='disabled') self.a2.config(state='disabled') self.a5.config(state='disabled') def reset(self): self.xlen.set(128) self.ylen.set(128) self.color.set(0) self.ty.set(0) self.a2.config(state='normal') #开始收集'存储地址'和'图片关键字'并开始爬图 def start_in(self): word = self.e2.get() self.a1.config(state='disabled') self.e2.config(state='disabled') self.s.config(state='normal') self.b1.config(state='disabled') self.b2.config(state='disabled') self.b3.config(state='disabled') path = self.e1.get() self.s.delete(1.0, 'end') ins = word.encode('utf-8') self.s.insert('end', '正在百度搜索:' + ins) self.get_images(word, path) #这是爬图的主程序 #格式错误反馈 def alarm(self): self.ala.config(text='输入格式有误!') #self.a.delete(0,'end') #读取网页url def readurl(self, url): page = urllib.urlopen(url) htm = page.read() return htm #下载网络图片 #imgurl:单张网络图片的url地址 #path:图片存储路径 #x:图片编号,同时也是图片名 #lastname:网络图片的后缀名 def downloadimg(self, imgurl, path, x, lastname): error_time = 0 while True: time.sleep(1) try: try: urllib.urlretrieve(imgurl, path + '/%s' % x + lastname) # 从地址上下载单张图片到指定存储位置上 #self.s.insert('insert', '\n第%s张图片下载成功' % x) except socket.timeout: # 防止超时卡死,重新下载 self.s.insert('insert', '\nReloading...') count = 1 # 卡死计数 while count <= 2: # 重新下载图片两次 try: urllib.urlretrieve(imgurl, path + '/%s' % x + lastname) time.sleep(0.001) self.s.insert('insert', '\n第%s张图片下载成功' % x) break except socket.timeout: err_info = 'Reloading for %d time' % count if count == 1 else 'Reloading for %d times' % count self.s.insert('insert', '\n' + err_info) count = count + 1 if count > 2: # 卡死次数过多 # 删除错误文件 os.remove(path + '/%s' % x + lastname) imgname = path + '/%s' % x + lastname size = os.path.getsize(imgname) / float(1024) # 获取图片大小 # size单位为kb if size < 20: # 删除小于20kb的图片 os.remove(path + '/%s' % x + lastname) self.s.insert('insert', '\n第%s张图片大小太小,跳过' % x) except: error_time += 1 if error_time == 100: print('your network is little bad') time.sleep(60) if error_time == 101: print('your network is broken') break continue break #获取图片地址列表 #jpgre:jpg图片地址的正则表达式形式 #pngre和jpegre同上 #htm:网页源代码 def get_imglist(self, jpgre, pngre, jpegre, htm): jpglist = re.findall(jpgre, htm) #在htm里寻找所有jpg图片的源代码,并做成一个列表 pnglist = re.findall(pngre, htm) jpeglist = re.findall(jpegre, htm) piclist = [jpglist, pnglist, jpeglist] return piclist #piclist是一个三元列表,每一个元素也是一个列表 #获得文件夹目录 def get_directory1(self): savepath = askdirectory() self.e1.delete(0, 'end') self.e1.insert('insert', savepath) def get_directory5(self): savepath = askdirectory() self.e3.delete(0, 'end') self.e3.insert('insert', savepath) def get_directory4(self): savepath = askdirectory() self.e4.delete(0, 'end') self.e4.insert('insert', savepath) #爬取图片主程序 #word:图片关键字 #path:图片存储路径 def get_images(self, word, path): var1 = word.encode('utf-8') #get()函数得到的字符串不是utf-8编码,需要转到utf-8 search = urllib.quote(var1) #用urllib的网页格式转码utf-8格式的图片关键字 pn = 0 # pn = 20*(页数+1) err_num = 0 #错误计数,连续十个网址下载出现错误时就终止爬图 x = 1 #图片编号 jpg = 'objURL":"(.+?.jpg)",' #百度图片的URL地址的正则表达式 jpgre = re.compile(jpg) #编译正则表达式,用于寻找网页源代码里的图片地址 jpeg = 'objURL":"(.+?.jpeg)",' jpegre = re.compile(jpeg) png = 'objURL":"(.+?.png)",' pngre = re.compile(png) self.s.insert('insert', '\n--------开始爬图--------') while True: url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + search + '&pn=' + str( pn) + '&gsm=3c&ct=&ic=0&lm=-1&width=0&height=0' try: self.s.insert('insert', '\n正在读取源代码...') htm = self.readurl(url) #从网页地址里读取网页源代码 piclist = self.get_imglist(jpgre, pngre, jpegre, htm) #在网页文件里寻找编译后的URL地址,并返回一个列表 namelist = ['.jpg', '.png', '.jpeg'] #后缀名列表,百度图片的后缀名一般只有三种:jpg,png,jpeg n = 0 m = 0 self.s.insert('insert', '\n--------------') self.s.insert('insert', '\n源代码读取完毕') self.s.insert('insert', '\n--------------') for list in piclist: #注意:piclist是一个三元列表,每一个元素也是一个列表 lastname = namelist[n] n = n + 1 for imgurl in list: #list存储着许多图片的URL地址,每个imgurl是单张图片的url地址 dlth = threading.Thread( target=self.downloadimg, args=( imgurl, path, x, lastname, )) #把下载单张图片交给子进程去完成,提供进程需要执行的目标函数和函数参数 dlth.setDaemon(True) #dlth这三行缺一不可 dlth.start() #开始执行进程 self.s.insert('insert', '\n第%s张图片下载成功' % x) x = x + 1 #开始下载下一张图片 err_num = 0 #一张网页的下载顺利完成,错误代码归零 except: self.s.insert('insert', '\n...结束本页内容下载 继续') #跳过该页面下载下一页 pn = pn + 20 #pn = 20*(页数+1) err_num = err_num + 1 if pn > 1960: #图片关键字只会存100页的图片,所以pn>1960时不可能查到图 self.s.insert('insert', '\n...图片全部下载完毕') break elif err_num > 10: self.s.insert('insert', '\n...搜索不到更多图片,下载完毕') break elif x >= 1024: self.s.insert('insert', '\n...图片下载已达到上限') break self.s.insert('insert', '\n--------加载下一页--------') #以下为图片预处理部分 def start_pi(self): st = askyesno(title='确认开始', message='确定开始批处理图片?这会有一段时间的卡顿,但是可以去存储的文件夹拿到处理好的图') if st: reload(sys) sys.setdefaultencoding('utf8') self.start_pic() def start_pic(self): xLen = self.xl.get() yLen = self.yl.get() if xLen.isdigit() is True and yLen.isdigit() is True: self.ala.config(text='') self.a2.config(state='disabled') self.s1.config(state='normal') self.s1.insert('end', '\nxLen:' + str(xLen)) self.s1.insert('end', '\nyLen:' + str(yLen)) picpath = self.e3.get() savepath = self.e4.get() self.s1.insert('end', '\npicpath:' + picpath) self.s1.insert('end', '\nsavepath:' + savepath) pictypelist = ['LA', 'RGB'] pictype = pictypelist[self.color.get()] self.s1.insert('end', '\npictype:' + pictype) lastnamelist = ['.jpg', '.png', '.jpeg'] lastname = lastnamelist[self.ty.get()] self.s1.insert('end', '\nlastname:' + lastname) self.pre_main(picpath, savepath, pictype, xLen, yLen, lastname) else: self.ala.config(text='长宽输入格式有误!') def getNameList(self, picpath): if os.path.exists(picpath) is False: self.ala.config(text='该路径不存在!') else: self.ala.config(text='') files = os.listdir(picpath) return files def picdeal(self, name, picpath, savepath, pictype, xLen, yLen, lastname): try: names = name.split('.')[0] img = Image.open(picpath + '/' + name).convert(pictype).resize( (int(xLen), int(yLen))) img.save(savepath + '/%s' % names + lastname) except socket.timeout: count = 1 while count <= 2: try: img.save(savepath + '/%s' % names + lastname) self.s1.insert('end', '\n重新保存图片%s' % name + '1次') except socket.timeout: img.save(savepath + '/%s' % names + lastname) self.s1.insert('end', '\n重新保存图片%s' % name + '%d次' % (count + 1)) count = count + 1 if count >= 2: os.remove(savepath + '/%s' % names + lastname) except: names = name.split('.')[0] os.remove(savepath + '/%s' % names + lastname) def pre_main(self, picpath, savepath, pictype, xLen, yLen, lastname): nameList = self.getNameList(picpath) self.s1.insert('end', '\n共有%d张图片需要处理' % len(nameList)) for name in nameList: self.s1.insert('end', '\n正在处理图片:' + name) prth = threading.Thread(target=self.picdeal, args=( name, picpath, savepath, pictype, xLen, yLen, lastname, )) prth.setDaemon(True) prth.start()
class SourceEditor: def __init__(self,central,name,bodyTopNode,specTopNode): self.dirty = False self.central = central self.name = name self.toplevel = Toplevel() self.toplevel.title(name) self.pw = Pmw.PanedWidget(self.toplevel, orient='vertical') specpane = self.pw.add("spec") bodypane = self.pw.add("body") self.specText = ScrolledText(specpane,font=("monaco",10),height=5,background=Colors.background) self.specText.pack(expand=YES,fill=BOTH) self.bodyText = ScrolledText(bodypane,font=("monaco",10),height=15,background=Colors.background) self.bodyText.pack(expand=YES,fill=BOTH) self.nodeMap = {bodyTopNode: self.bodyText, specTopNode: self.specText} self.textMap = {self.bodyText: bodyTopNode, self.specText: specTopNode} Widget.bind(self.bodyText,'<Any-KeyPress>',self.setDirty) Widget.bind(self.specText,'<Any-KeyPress>',self.setDirty) self.popup = Menu(self.toplevel,tearoff=0) self.popup.add_command(label="Dismiss", command=self.nothing) self.popup.add_command(label="Diagram", command=self.goDiagram) self.popup.add_command(label="Abort", command=self.abort) self.popup.add_command(label="Accept", command=self.accept) self.popup.add_command(label="Recolor", command=self.recolor) def popupMenu(event): self.popup.post(event.x_root,event.y_root) self.toplevel.bind('<Button-3>', popupMenu) self.pw.pack(expand=YES,fill=BOTH) self.toplevel.protocol("WM_DELETE_WINDOW",self.central.doQuit) self.refresh() def nothing(self): pass def setClean(self): if self.dirty: self.dirty = False self.toplevel.title(self.name) self.central.unlockGraphics(self.name) def setDirty(self,event): if event.keysym in ['Shift_L', 'Shift_R', 'Alt_L', 'Alt_R', 'Win_L', 'Win_R']: return if not self.dirty: self.dirty = True self.toplevel.title(self.name+"*") self.central.lockGraphics(self.name) def abort(self): if self.dirty: self.setClean() self.setSource() def getSource(self): return (self.specText.get("1.0",END), self.bodyText.get("1.0",END)) def accept(self): if self.dirty: self.bodyText.config(cursor="watch") self.specText.config(cursor="watch") self.bodyText.update() # so that the cursor will show self.specText.update() self.central.update(self.name, self.specText.get("1.0",END), self.bodyText.get("1.0",END),saveOutput=False) self.central.setChanged(self.name) self.setClean() self.bodyText.config(cursor="xterm") self.specText.config(cursor="xterm") def recolor(self): stext,btext = self.getSource() self.colorize(self.specText,stext) self.colorize(self.bodyText,btext) def show(self, specTopNode, bodyTopNode): self.nodeMap = {bodyTopNode: self.bodyText, specTopNode: self.specText} self.textMap = {self.bodyText: bodyTopNode, self.specText: specTopNode} self.setSource() def setSource(self): oldScroll,dummy = self.specText.yview() self.specText.delete('1.0',END) stext = self.textMap[self.specText].regen(forDisplay=True) self.specText.insert(END,stext) self.colorize(self.specText,stext) self.specText.yview("moveto", oldScroll) oldScroll,dummy = self.bodyText.yview() self.bodyText.delete('1.0',END) btext = self.textMap[self.bodyText].regen(forDisplay=True) self.bodyText.insert(END,btext) self.colorize(self.bodyText,btext) self.bodyText.yview("moveto", oldScroll) def colorize(self,textWidget,progText): def colorizeSub(color,wordList): textWidget.tag_remove(color,'1.0',END) textWidget.tag_configure(color,foreground=color) keywords = re.compile(r'\b(' + string.join(wordList,"|") + r')\b') iter = keywords.finditer(progText) for match in iter: start, stop = match.span() textWidget.tag_add(color,"1.0+%dc" % start, "1.0+%dc" % stop) textWidget.tag_remove('hilite','1.0',END) colorizeSub(Colors.keyword, Lexis.keywords) colorizeSub(Colors.reserved, Lexis.reservedWords) def refresh(self): self.setSource() def goDiagram(self): self.central.showDiagram(self.name) def showSource(self,node): self.makeTop() topNode = node.getTopNode() self.text = self.nodeMap[topNode] self.text.tag_remove('hilite','1.0',END) start, end = node.lineRange() startIdx = '%d.0' % int(start) endIdx = '%d.0' % (int(end)+1) self.text.tag_configure('hilite',background=Colors.locatecolor,foreground='black') self.text.see(startIdx) self.text.tag_add('hilite',startIdx,endIdx) def coolSource(self): self.text.tag_configure('hilite',background='white',foreground=Colors.locatecooledcolor) def makeTop(self): TkWorkaround.raiseWindow(self.toplevel) def rescueResource(self): return repr(self.toplevel.geometry()) def setGeom(self,geom): self.toplevel.geometry(geom) def showError(self, unitType, lineNo): text = {'m': self.bodyText, 'i': self.specText}[unitType] startIdx = '%s.0' % int(lineNo) endIdx = '%s.0' % (int(lineNo)+1) text.tag_remove('hilite','1.0',END) text.tag_configure('hilite',background=Colors.locatecolor,foreground='black') text.see(startIdx) text.tag_add('hilite',startIdx,endIdx) self.makeTop()
class facades_main(Tkinter.Tk): def __init__(self, parent): Tkinter.Tk.__init__(self, parent) self.parent = parent self.initialize() self.clock_tick() def update_val_from_entry(self): global G_RUN_STATUS global G_SHUTDOWN_DELAY global G_WAKEUP_AFTER global G_LOOP_NUMBER global G_LONGRUN_ACTION G_SHUTDOWN_DELAY = int(self.entry_second.get(), base=10) G_WAKEUP_AFTER = int(self.entry_wakeafter.get(), base=10) G_LOOP_NUMBER = int(self.entry_loop.get(), base=10) G_LONGRUN_ACTION = self.var_action.get() def reset_rtcdata(self): efiapi = WinApiEfiVariables() rtcdata = efiapi.read(UEFI_VAR_NAME, UEFI_VAR_GUID) data = RtcWakeData(*struct.unpack_from(RTC_WAKE_DATA_FORMAT, rtcdata)) #just reset to not wake up data2 = data._replace(Alarm_Wake=3,Alarm_Week=0, \ RtcWakeTime_Hour= 0, \ RtcWakeTime_Minute= 0, \ RtcWakeTime_Second= 0 ) rtcdata = data2.packstring() efiapi.write(UEFI_VAR_NAME, UEFI_VAR_GUID, rtcdata) def func_shutdown(self): global G_CURRENT_LOOPNUM G_CURRENT_LOOPNUM += 1 self.confighandle.set_config('run_status', 'True') self.confighandle.set_config('current_loop', str(G_CURRENT_LOOPNUM)) self.confighandle.update_file() if (G_LONGRUN_ACTION == 4): print "reboot" Hour = int(time.strftime("%H"), 10) Minute = int(time.strftime("%M"), 10) Second = int(time.strftime("%S"), 10) self.logger.info("reboot time: %d:%d:%d" %(Hour, Minute, Second)) os.system('shutdown /r /f /t 0') while(1): pass efiapi = WinApiEfiVariables() rtcdata = efiapi.read(UEFI_VAR_NAME, UEFI_VAR_GUID) data = RtcWakeData(*struct.unpack_from(RTC_WAKE_DATA_FORMAT, rtcdata)) (Hour, Minute, Second) = self.CalAlarmTimer() data2 = data._replace(Alarm_Wake=1,Alarm_Week=0, \ RtcWakeTime_Hour= Hour, \ RtcWakeTime_Minute= Minute, \ RtcWakeTime_Second= Second ) rtcdata = data2.packstring() efiapi.write(UEFI_VAR_NAME, UEFI_VAR_GUID, rtcdata) if (G_LONGRUN_ACTION == 3): print "shutdown" os.system('shutdown /s /f /t 0') if (G_LONGRUN_ACTION == 2): print "suspend" os.system('rundll32.exe PowrProf.dll,SetSuspendState') if (G_LONGRUN_ACTION == 1): print "sleep" os.system('rundll32.exe powrprof.dll,SetSuspendState 0,1,0') def CalAlarmTimer(self): Hour = int(time.strftime("%H"), 10) Minute = int(time.strftime("%M"), 10) Second = int(time.strftime("%S"), 10) print "current time:", Hour, Minute, Second print "wake after:", G_WAKEUP_AFTER self.logger.info("current time: %d:%d:%d" %(Hour, Minute, Second)) # total_secs = Hour*3600 + Minute*60 + Second total_secs += G_WAKEUP_AFTER total_secs += G_SHUTDOWN_DELAY # Hour = total_secs / 3600 Minute = (total_secs % 3600) / 60 Second = (total_secs % 3600) % 60 if Hour >= 24: Hour = 0 print "wake time: %d:%d:%d" %(Hour, Minute, Second) self.logger.info("wake time: %d:%d:%d" %(Hour, Minute, Second)) return (Hour,Minute,Second) def clock_tick(self): now = time.strftime("%H:%M:%S") self.label_ticker.configure(text=now) self.label_ticker.after(200, self.clock_tick) def clock_timeout(self): count = self.entry_second.get() #print count count = int(count, 10) print count if (G_RUN_STATUS): if (count > 0): self.count_second.set(count - 1) self._job = self.entry_second.after(1000, self.clock_timeout) if (count == 0): print "function to action!" self.func_shutdown() def initialize(self): global G_RUN_STATUS global G_SHUTDOWN_DELAY global G_WAKEUP_AFTER global G_LOOP_NUMBER global G_CURRENT_LOOPNUM global G_LONGRUN_ACTION self.geometry("400x450+300+100") self.minsize(350,250) self.grid() self._job = None self.confighandle = lrConfigParser(configfn) self.count_second = Tkinter.IntVar() self.str_action = Tkinter.StringVar() self.var_action = Tkinter.IntVar() self.loop_number = Tkinter.IntVar() self.current_loop = Tkinter.IntVar() self.wake_after = Tkinter.IntVar() self.str_start = Tkinter.StringVar() self.var_action.set(G_LONGRUN_ACTION ) self.count_second.set(G_SHUTDOWN_DELAY) self.loop_number.set(G_LOOP_NUMBER) self.current_loop.set(G_CURRENT_LOOPNUM) self.wake_after.set(G_WAKEUP_AFTER) if (G_LONGRUN_ACTION == 4): self.str_action.set("reboot ") if (G_LONGRUN_ACTION == 3): self.str_action.set("Shutdown") self.log_queue = Queue.Queue() self.label_blank = Tkinter.Label(self, text='') self.label_ticker = Tkinter.Label(self, text="test",anchor='e',font=('times', 20, 'bold'), bg='green') self.entry_second = Tkinter.Entry(self, text=self.count_second, font=('times', 20, 'bold'),width=5) self.label_str1 = Tkinter.Label(self, text='seconds to',font=('times', 20, 'bold')) self.label_str2 = Tkinter.Label(self, text='Loop',font=('times', 20, 'bold')) self.label_str3 = Tkinter.Label(self, text='seconds to',font=('times', 20, 'bold')) self.label_str4 = Tkinter.Label(self, text='wakeup', font=('times', 20, 'bold')) self.entry_wakeafter = Tkinter.Entry(self, text=self.wake_after, font=('times', 20, 'bold'),width=5) self.label_str_action = Tkinter.Label(self, textvariable=self.str_action, font=('times', 20, 'bold')) self.radiobtn_s3 = Tkinter.Radiobutton(self, text='S3',variable=self.var_action, value=1, command=self.radiobtn_callback, state='disabled') self.radiobtn_s4 = Tkinter.Radiobutton(self, text='S4',variable=self.var_action, value=2, command=self.radiobtn_callback, state='disabled') self.radiobtn_s5 = Tkinter.Radiobutton(self, text='S5',variable=self.var_action, value=3, command=self.radiobtn_callback) self.radiobtn_reboot = Tkinter.Radiobutton(self, text='reboot',variable=self.var_action, value=4, command=self.radiobtn_callback) self.entry_loop = Tkinter.Entry(self, text=self.loop_number, font=('times', 20, 'bold'),width=5) self.btn_start = Tkinter.Button(self, text="Start",bg="green",font=('times', 20, 'bold'), command=self.btn_start_callback) self.btn_edit = Tkinter.Button(self, text="Edit", font=('times', 20, 'bold'), state="disabled", command=self.btn_edit_callback) self.label_current_loop = Tkinter.Label(self, textvariable=self.current_loop, font=('times', 20, 'bold')) self.btn_clrlog = Tkinter.Button(self, text="Clear Log",font=('times', 15, 'bold'), command=self.btn_clearlog_callback) self.log_widget = ScrolledText(self, width = 50, heigh = 15) self.label_blank.grid(row=0,column=0,ipadx=20) self.label_ticker.grid(row=0,column=2,sticky='w') self.entry_second.grid(row=1,column=0) self.label_str1.grid(row=1,column=1,sticky='w') self.label_str_action.grid(row=1,column=2,sticky='w') self.entry_loop.grid(row=2,column=0) self.label_str2.grid(row=2, column=1,sticky='w') self.radiobtn_s3.grid(row=2,column=2,sticky='w') self.radiobtn_s4.grid(row=2,column=2,sticky='w', padx=40) self.radiobtn_s5.grid(row=2,column=2,sticky='w', padx=80) self.radiobtn_reboot.grid(row=2,column=2,sticky='w',padx=120) self.entry_wakeafter.grid(row=3, column=0) self.label_str3.grid(row=3, column=1) self.label_str4.grid(row=3, column=2,sticky='w') self.label_blank.grid(row=4,column=0) self.btn_start.grid(row=5, column=0) self.btn_edit.grid(row=5, column=1) self.btn_clrlog.grid(row=5,column=2,sticky='w') self.label_current_loop.grid(row=5, column=2,sticky='w',padx=120) self.log_widget.grid(row=6, column=0, columnspan=3, sticky='w') #init log queue self.logger = logging.getLogger(logfn) self.logger.setLevel(logging.INFO) logformat = logging.Formatter(LOG_FORMAT) hl = QueueLogger(queue=self.log_queue) hl.setFormatter(logformat) self.logger.addHandler(hl) self.start_logwidget() if G_CURRENT_LOOPNUM <= G_LOOP_NUMBER: if G_RUN_STATUS: print "auto run loop %d" %(G_CURRENT_LOOPNUM) self.logger.info("\ncurrent loop: %d" %(G_CURRENT_LOOPNUM)) self.btn_start_callback() else: print "loop pass!" self.current_loop.set(G_CURRENT_LOOPNUM-1) if G_RUN_STATUS: print "reset run status here" G_RUN_STATUS = False G_CURRENT_LOOPNUM -= 1 self.current_loop.set(str(G_CURRENT_LOOPNUM)) self.confighandle.set_config('current_loop', str(G_CURRENT_LOOPNUM)) self.confighandle.update_file() self.reset_rtcdata() def radiobtn_callback(self): global G_LONGRUN_ACTION seltmp = self.var_action.get() G_LONGRUN_ACTION = seltmp if (seltmp == 4): self.str_action.set("reboot") if (seltmp == 3): self.str_action.set("Shutdown") if (seltmp == 2): self.str_action.set("Suspend ") if (seltmp == 1): self.str_action.set("Sleep ") def btn_clearlog_callback(self): global G_CURRENT_LOOPNUM self.log_widget.config(state='normal') self.log_widget.delete(0.0, Tkinter.END) self.log_widget.config(state='disabled') if os.path.isfile(logfn): with open(logfn, 'w'): pass #reset current loop to zero if G_CURRENT_LOOPNUM != 0: G_CURRENT_LOOPNUM = 0 self.confighandle.set_config('current_loop', str(G_CURRENT_LOOPNUM)) self.confighandle.update_file() self.current_loop.set(G_CURRENT_LOOPNUM) def btn_start_callback(self): global G_RUN_STATUS global G_EDITABLE if G_EDITABLE: G_EDITABLE = False print "set get from entry" self.update_val_from_entry() self.confighandle.set_config('shutdown_delay', str(G_SHUTDOWN_DELAY)) self.confighandle.set_config('loop_number', str(G_LOOP_NUMBER)) self.confighandle.set_config('wake_after', str(G_WAKEUP_AFTER)) self.confighandle.set_config('longrun_action', str(G_LONGRUN_ACTION)) self.confighandle.update_file() self.btn_start.config(text='Stop ', bg = "red", command=self.btn_stop_callback) self.entry_second.config(state='disabled') self.entry_loop.config(state='disabled') self.btn_edit.config(state='disabled') self.entry_wakeafter.config(state='disabled') G_EDITABLE = False if not G_RUN_STATUS: G_RUN_STATUS = True self.clock_timeout() def btn_stop_callback(self): global G_RUN_STATUS G_RUN_STATUS = False self.btn_start.config(text="Start", bg = "green", command=self.btn_start_callback) self.btn_edit.config(state='normal') self.confighandle.set_config('run_status', str(G_RUN_STATUS)) self.confighandle.update_file() self.reset_rtcdata() def btn_edit_callback(self): global G_EDITABLE print "edit callback, to enable change variables" self.btn_edit.config(text="Apply", command=self.btn_apply_callback) self.entry_second.config(state='normal') self.entry_loop.config(state='normal') self.entry_wakeafter.config(state='normal') G_EDITABLE = True def btn_apply_callback(self): global G_EDITABLE print "apply callback, save changes to cfg file after edit" self.btn_edit.config(text="Edit", command=self.btn_edit_callback) self.entry_second.config(state='disabled') self.entry_loop.config(state='disabled') self.entry_wakeafter.config(state='disabled') G_EDITABLE = False self.update_val_from_entry() ##update into cfg file self.confighandle.set_config('shutdown_delay', str(G_SHUTDOWN_DELAY)) self.confighandle.set_config('loop_number', str(G_LOOP_NUMBER)) self.confighandle.set_config('wake_after', str(G_WAKEUP_AFTER)) self.confighandle.set_config('longrun_action', str(G_LONGRUN_ACTION)) self.confighandle.update_file() def start_logwidget(self): if os.path.isfile(logfn): self.log_widget.config(state='normal') print "read log file into log widget" with open(logfn) as fin: for line in fin: self.log_widget.insert(Tkinter.END, line) self.log_widget.see(Tkinter.END) self.log_widget.update_idletasks() self.log_widget.config(state='disabled') self.update_logwidget(self.log_widget, self.log_queue) def update_logwidget(self, widget, queue): widget.config(state='normal') while not queue.empty(): line = queue.get() widget.insert(Tkinter.END, line) widget.see(Tkinter.END) widget.update_idletasks() widget.config(state='disabled') self.logger_alarm = widget.after(10, self.update_logwidget, widget, queue)
class LogFrame: def __init__(self, root, options, main_logger): self.root = root self.options = options self.main_logger = main_logger self.frame = tk.Frame(self.root) self.frame.columnconfigure(0, weight=1) # first row doesn't expoands self.frame.rowconfigure(0, weight=0) # let the second row grow self.frame.rowconfigure(1, weight=1) self.log_commands_frame = tk.LabelFrame(self.frame, text="Controls", padx=5, pady=5) self.log_commands_frame.grid(row=0, column=0, sticky=tk.NSEW, padx=4, pady=5) self.log_messages_frame = tk.Frame(self.frame) self.log_messages_frame.grid(row=1, column=0, sticky=tk.NSEW) # let the SIP trace growing self.log_messages_frame.columnconfigure(0, weight=1) self.log_messages_frame.rowconfigure(0, weight=1) self.log_messages = ScrolledText(self.log_messages_frame) self.log_messages.grid(row=0, column=0, sticky=tk.NSEW) # Log Messages frame row = 0 self.log_messages_clear_button = tk.Button( self.log_commands_frame, text="Clear", command=self.clear_log_messages) self.log_messages_clear_button.grid(row=row, column=0, sticky=tk.N) self.log_messages_pause_button = tk.Button( self.log_commands_frame, text="Pause", command=self.pause_log_messages) self.log_messages_pause_button.grid(row=row, column=1, sticky=tk.N) row = row + 1 def get_frame(self): return self.frame def clear_log_messages(self): self.log_messages.config(state='normal') self.log_messages.delete(0.0, tk.END) self.log_messages.config(state='disabled') def pause_log_messages(self): if self.log_messages_alarm is not None: self.log_messages.after_cancel(self.log_messages_alarm) self.log_messages_pause_button.configure( text="Resume", command=self.start_log_messages) self.log_messages_alarm = None def start_log_messages(self): self.update_log_messages_widget() self.log_messages_pause_button.configure( text="Pause", command=self.pause_log_messages) def update_log_messages_widget(self): self.update_widget(self.log_messages, self.log_queue) self.log_messages_alarm = self.log_messages.after( 20, self.update_log_messages_widget) def update_widget(self, widget, queue): widget.config(state='normal') while not queue.empty(): line = queue.get() widget.insert(tk.END, line) widget.see(tk.END) # Scroll to the bottom widget.update_idletasks() widget.config(state='disabled')
class my_form(Frame): """Form""" def __init__(self, master=None): """Elemente der Form kreieren""" Frame.__init__(self, master) self.pack() #self.createWidgets() self.text_label = Label(self, height=1, width=80, anchor=NW, text="Play-Out-Logging Nr: ") self.text_label.pack() self.text_label_1 = Label(self, height=1, width=80, text="Titel aktuell") self.text_label_1.pack() self.textBox = ScrolledText(self, height=5, width=80) self.textBox.pack() self.textBox.insert(END, "In the Beginning...\n") self.text_label_2 = Label(self, height=1, width=80, text="Rueckmeldung von Webserver") self.text_label_2.pack() self.textBox1 = ScrolledText(self, height=10, width=80) self.textBox1.pack() self.textBox1.insert(END, "...and the End\n") # registering callback self.listenID = self.after(500, self.lets_rock) def display_logging(self, log_meldung_1, log_meldung_2): """display messages in form, loading periodically """ if log_meldung_1 is not None: self.text_label.config(text="Play-Out-Logging Nr: " + str(ac.app_counter) + " / Interval von " + str(int(db.ac_config_1[2])) + " Sekunden") self.textBox.delete('1.0', '3.end') self.textBox.insert(END, log_meldung_1 + "\n") if log_meldung_2 is not None: self.text_label.config(text="Play-Out-Logging Nr: " + str(ac.app_counter) + " / Interval von " + str(int(db.ac_config_1[2])) + " Sekunden") self.textBox1.delete('1.0', '8.end') self.textBox1.insert(END, log_meldung_2 + "\n") self.listenID = self.after( int(db.ac_config_1[2]) * 1000, self.lets_rock) return def lets_rock(self): """man funktion""" lib_cm.message_write_to_console(ac, u"lets rock") ac.app_counter += 1 log_data = None time_now = datetime.datetime.now() time_back = datetime.datetime.now() + datetime.timedelta(hours=- 1) c_time = time_back.strftime("%Y-%m-%d %H") lib_cm.message_write_to_console(ac, c_time) # time for reloading mpd # skipping mpd-check if time_now.hour == 4: if time_now.minute == 40: if time_now.second >= 5 and time_now.second <= 30: log_meldung_1 = "Logging waehrend MPD-Neustart ausgesetzt" db.write_log_to_db_a(ac, log_meldung_1, "p", "write_also_to_console") self.display_logging(log_meldung_1, "") return # 1. load sources # 2. assign sources transmittime source_id = check_source(self, c_time, time_now) if source_id is None: return # 3. Pruefen ob Quelle Aussenuebertragung, VP oder Studios # Bei Aussenuebertragung stehen keine Logfiles zur Verfuegung, # Sendung muesste in db zu finden sein if source_id == "05": log_changed_ext = logging_source_ext(self, source_id, time_now) if log_changed_ext is None: return if source_id == "01" or source_id == "02": # Daten aus Logfiles holen bzw. aus db lib_cm.message_write_to_console(ac, u"Sendung aus Studio") log_changed = check_mairlist_log(self, source_id, time_now, log_data) if log_changed is None: return if source_id == "03": # else source_id == "05": # Daten aus Logfiles holen bzw. aus db lib_cm.message_write_to_console(ac, u"Sendung via Playout oder Internetstream") # Daten aus mAirlist_Logdatei holen # if mairlist if db.ac_config_1[9] == "mairlist": log_changed = check_mairlist_log(self, source_id, time_now, log_data) if log_changed is None: return if db.ac_config_1[9] == "mpd": log_changed = check_mpd_log(self, time_now, log_data) if log_changed is None: return if ac.log_author is None: ac.log_start = (str(time_now.date()) + " " + str(time_now.time())[0:8]) ac.log_author = db.ac_config_1[3] if ac.log_title is None: ac.log_title = db.ac_config_1[4] # Bezeichnung der Quelle holen log_source_desc = db.read_tbl_row_with_cond(ac, db, "SG_HF_SOURCE", "SG_HF_SOURCE_ID, SG_HF_SOURCE_DESC", "SG_HF_SOURCE_ID ='" + source_id + "'") if log_source_desc is None: log_meldung_1 = ("Keine Bezeichnung Sendequelle gefunden," " nichts uebertragen..") db.write_log_to_db_a(ac, log_meldung_1, "p", "write_also_to_console") self.display_logging(log_meldung_1, "") return # 5. Logging in db db.write_log_to_db(ac, log_source_desc[1].strip() + ": " + ac.log_author + " - " + ac.log_title, "a") log_meldung_1 = (log_source_desc[1] + ": \n" + ac.log_author + " - " + ac.log_title) # 6. Upload auf Webserver web = upload_data_prepare() if web is not None: self.display_logging(log_meldung_1, web) else: ac.log_start = (str(time_now.date()) + " " + str(time_now.time())[0:8]) ac.log_author = db.ac_config_1[3] ac.log_title = db.ac_config_1[4] log_meldung_1 = ac.app_errorslist[4] + " \n" self.display_logging(log_meldung_1, None) return
class LoggingUI(TimedFrame): u'''ロギング用UI''' def __init__(self, *args, **kwargs): TimedFrame.__init__(self, *args, **kwargs) self.pack() self.init() self.startTimer() def init(self): if not config.normalize.points: self._label = tk.Label(self, text = u'まだ正規化が済んでいません。\n正規化を行ってください。') self._label.pack() return if not config.template.images or len(config.template.images) < 10 or not all(config.template.images): self._label = tk.Label(self, text = u'まだ学習が済んでいません。\n学習を行ってください。') self._label.pack() return # テンプレートの読み込み self.loadTemplates() # カメラの準備 self._camera = cv.CaptureFromCAM(config.camera.id) # 左側UI frame1 = tk.Frame(self) frame1.pack(side = tk.LEFT, expand = True, fill = tk.BOTH) # カメラ画像表示用Canvasなどの準備 self._cvmat = None self._image = tk.PhotoImage(width = config.canvas.width, height = config.canvas.height) self._canvas = tk.Canvas(frame1, width = config.canvas.width, height = config.canvas.height) self._canvas.create_image(config.canvas.width / 2, config.canvas.height / 2, image = self._image, tags = 'image') self._canvas.pack(expand = True, fill = tk.BOTH) # ボタン self._main_button = tk.Button(frame1) self._main_button.pack(side = tk.LEFT) self.logStop() self._reset_button = tk.Button(frame1, text = u'リセット', command = self.reset) self._reset_button.pack(side = tk.RIGHT) # 生データ表示領域 self._textarea = ScrolledText(self, width = 6, height = 18) self._textarea.pack(side = tk.LEFT, expand = True) # 右側UI frame2 = tk.Frame(self) frame2.pack(side = tk.LEFT, expand = True, fill = tk.BOTH) # ログデータ表示領域 self._graph = tk.Canvas(frame2, width = config.canvas.width, height = config.canvas.height, bg = 'white') self._graph.pack(expand = True, fill = tk.BOTH) self._bar_graph = BarGraph(A(width = config.canvas.width, height = config.canvas.height), config.logging.graph_max_count) # ボタン self._out_button = tk.Button(frame2, text = u'生データをコピー', command = self.datacopy) self._out_button.pack(side = tk.LEFT) self._gchart_button = tk.Button(frame2, text = u'Google Chart URLをコピー', command = self.gchart) self._gchart_button.pack(side = tk.RIGHT) # 画像をフィルタするための変数 self._clip_rect, self._perspective_points = Points2Rect(config.normalize.points) # ロギング開始、停止のフラグ self._take_log = False # ログ self._log = [] # カメラ画像の更新を1秒間隔にする self.addTiming(self.showImage, 1) def setValue(self, value): if value is None: value = 0 self._bar_graph.setValue(value) self._graph.delete('bar') for bar in self._bar_graph.getAllBars(): self._graph.create_rectangle( bar.p1.x, bar.p1.y, bar.p2.x, bar.p2.y, fill = 'green', stipple = 'gray25', tags = 'bar' ) def loadTemplates(self): u'''テンプレート画像の読み込み''' self._templates = [] for i, cvimageinfo in enumerate(config.template.images): cvmat = cv.CreateMatHeader(cvimageinfo.rows, cvimageinfo.cols, cvimageinfo.type) cv.SetData(cvmat, cvimageinfo.data) self._templates.append(A( image = cv.GetImage(cvmat), number = i, result = None, )) def showImage(self): u'''カメラ画像の表示''' captured = cv.QueryFrame(self._camera) self._cvmat = self.filter(captured) self._image = CvMat2TkImage(self._cvmat) self._canvas.itemconfigure('image', image = self._image) if self._take_log: self.logging() def logging(self): u'''ログを取る''' target = self._cvmat digits_sieve = DigitsSieve() for template in self._templates: if not template.result: # マッチング結果保存用領域の準備 template.result = cv.CreateImage( (target.width - template.image.width + 1, target.height - template.image.height + 1), cv.IPL_DEPTH_32F, 1, ) cv.MatchTemplate(target, template.image, template.result, config.logging.match_method) # 数値の読み取り minVal, maxVal, minLoc, maxLoc = cv.MinMaxLoc(template.result) while maxVal > config.logging.match_threshold: # 検出された数値情報の保持 digits_sieve.push(A( number = template.number, x = maxLoc[0], y = maxLoc[1], width = template.image.width, height = template.image.height, score = maxVal, )) # 現在の位置周辺のスコアをクリアし、次にスコアの高い位置を取得する SetReal2DAround(template.result, maxLoc, config.logging.match_exclusion_size, 0.0) minVal, maxVal, minLoc, maxLoc = cv.MinMaxLoc(template.result) value = digits_sieve.getValue() if value is not None: self._log.append(value) self.setValue(value) self._textarea.insert(tk.END, '%d\n' % value) self._textarea.see(tk.END) def logStart(self): u'''ロギングを開始する''' self._main_button.configure(text = u'ストップ', command = self.logStop) self._take_log = True def logStop(self): u'''ロギングを停止する''' self._main_button.configure(text = u'スタート', command = self.logStart) self._take_log = False def reset(self): u'''リセット''' self._bar_graph.init() self.setValue(0) self._log = [] self._textarea.delete('1.0', tk.END) def datacopy(self): u'''生データをクリップボードにコピーする''' text = self._textarea.get('1.0', tk.END) self.clipboard_clear() self.clipboard_append(text) def gchart(self): u'''Google Chart API用のURLをクリップボードにコピーする''' if self._log \ and len(self._log) > 0 \ and max(self._log) > 0: unit = float(4095) / max(self._log) url = gExtendedUrl( map(lambda x: unit * x, self._log), cht = 'bvs', # 棒グラフ chxt = 'y', # y軸の目盛り表示 chxr = '0,0,%d' % max(self._log), # y軸の最小最大値 chg = '0,10,3,2', # 補助線 chbh = '%d,1' % (480 / len(self._log) - 1), # 棒グラフの棒の幅 ) self.clipboard_clear() self.clipboard_append(url) def filter(self, cvmat): u'''画像をフィルタする''' # サイズ調整 thumbnail = cv.CreateMat(config.canvas.height, config.canvas.width, cv.CV_8UC3) cv.Resize(cvmat, thumbnail) return NormalizeImage(thumbnail, self._clip_rect, self._perspective_points)
class Globby_Text_Editor(tk.Frame): def __init__(self, parent_widget, settings): # some initial values # TODO this Values are obsolete since Project_Settings covers them # --> self.settings.projects_path self.hash_opened_filename = None self.opened_filename = None self.settings = settings self.edit_button_list=[ {'text':'new page', 'cmd':self.on_new_page, 'keytxt':'CTRL+n','hotkey':'<Control-n>'}, {'text':'del page', 'cmd':self.on_del_page, 'keytxt':'CTRL+n','hotkey':'<DELETE>'} , {'text':'save', 'cmd':self.on_save, 'keytxt':'CTRL+s','hotkey':'<Control-s>'}, {'text':'undo', 'cmd':self.on_undo, 'keytxt':'CTRL+z','hotkey':'<Control-z>'}, {'text':'redo', 'cmd':self.on_redo, 'keytxt':'CTRL+y','hotkey':'<Control-y>'}] self.syntax_button_list=[ {'text':'**bold**', 'cmd':self.on_tag_insert, 'open_tag':'**', 'close_tag':'**','keytxt':'CTRL+b','hotkey':'<Control-b>'}, {'text':'//italic//', 'cmd':self.on_tag_insert, 'open_tag':'//', 'close_tag':'//', 'keytxt':'CTRL+i','hotkey':'<Control-i>'}, {'text':'__underline__', 'cmd':self.on_tag_insert, 'open_tag':'__', 'close_tag':'__', 'keytxt':'CTRL+u','hotkey':'<Control-u>'}, {'text':'[Link]', 'cmd':self.on_tag_insert, 'open_tag':'[', 'close_tag':']', 'keytxt':'CTRL+l','hotkey':'<Control-l>'}, {'text':'¸¸sub¸¸', 'cmd':self.on_tag_insert, 'open_tag':'¸¸', 'close_tag':'¸¸', 'keytxt':'CTRL+d','hotkey':'<Control-d>'}, {'text':'^^upper^^', 'cmd':self.on_tag_insert, 'open_tag':'^^', 'close_tag':'^^', 'keytxt':'CTRL+q','hotkey':'<Control-q>'}, {'text':'-~smaller~-', 'cmd':self.on_tag_insert, 'open_tag':'-~', 'close_tag':'~-', 'keytxt':'CTRL+w','hotkey':'<Control-w>'}, {'text':'+~bigger~+', 'cmd':self.on_tag_insert, 'open_tag':'+~', 'close_tag':'~+', 'keytxt':'CTRL+e','hotkey':'<Control-e>'}, {'text':'~~strike_thru~~', 'cmd':self.on_tag_insert, 'open_tag':'~~', 'close_tag':'~~', 'keytxt':'CTRL+t','hotkey':'<Control-t>'} ] # build Widgets tk.Frame.__init__(self, parent_widget) self.pack(fill=tk.BOTH, expand=tk.YES) #self.baseframe = tk.Frame(parent_widget) #self.baseframe.pack(fill=tk.BOTH, expand=tk.YES) self.editor() self.button_frame() # start tracking text changes inside the editfield thread.start_new_thread(self.on_txt_changes, ('',)) def editor(self): """ combine some Widgets to an enhanced editor (incl. Scrollbar) --> self.text the text widget itself --> self.opened_file_label Label on top of the editfield to show the name of the current opened File It can be used to show textchanges """ # build widgets self.txtfrm = tk.Frame(self) self.txtfrm.pack(fill=tk.BOTH, side=tk.LEFT, expand=tk.YES) self.opened_file_label = tk.Label(self.txtfrm, text="No File chosen") self.opened_file_label.pack(fill=tk.X) self.text = ScrolledText(self.txtfrm, bg="white", undo=1, maxundo=30, wrap=tk.WORD) self.text.pack(fill=tk.BOTH, expand=tk.YES, side=tk.LEFT) self.text.insert(1.0, u"Please open a File to edit") # build first(reference -- new name??) hash for comparison on changes self.hash_opened_filename = hash(self.text.get(1.0,tk.END)) # Set focus on textwidget and move cursor to the upper left self.text.focus_set() self.text.mark_set(tk.INSERT, '0.0') # goto line self.text.see(tk.INSERT) # scroll to line def label_button_row(self, parent_widget=None, btnlst=None, start_count=0): """Build a 2 column table with a label beside each button in a row. Bind a keyboard sequence to the button command. Display this keyboard sequence on the label. todo: - think about a parameter for the widget to bind the Hotkeys - rename to: labled_button_row, draw_labled_button_row Parameter: --> parent_widget: Parent widget to place the table --> btnlst: Type: List of dicts representing a button Example: {'text':'**bold**', # displayed on the Button (string) 'cmd':self.on_tag_insert, # command 'open_tag':'**', # chars representing the beginning # of a tag for inserting (string) 'close_tag':'**', # chars representing the end # of a tag for inserting (string) 'keytxt':'CTRL+b', # displayed on the Label (string) 'hotkey':'<Control-b>'} # keyboard sequence (string) Note: The existence of 'open_tag' and 'close_tag' in btnlst decides which command is bound to the Button. If they aren't there 'cmd' must be a function without parameters!!! otherwise 'cmd' needs following parameters: otag = btn['open_tag'] ctag = btn['close_tag'] event = None # Placeholder for a keysequence --> start_count: Type: int Description: The table is relized with tkinter grid layout manager. start_count is used if there is already a grid (with a Label beside a button). start_count can add the automatic genrated buttons under the existing. In Globby_Editor it is used to put a label_button_row under a Tkinter menubutton(file choose, headlines). """ i = start_count for btn in btnlst: try: otag = btn['open_tag'] ctag = btn['close_tag'] event = None doit = lambda e=event, o=otag, c=ctag:self.on_tag_insert(e,o,c) tk.Button(parent_widget, text=btn['text'], command=doit, relief=tk.RIDGE ).grid(column=0, row=i, sticky=tk.W+tk.E) self.text.bind(btn['hotkey'],doit) except KeyError: tk.Button(parent_widget, text=btn['text'], command=btn['cmd'], relief=tk.RIDGE ).grid(column=0, row=i, sticky=tk.W+tk.E) tk.Label(parent_widget, text=btn['keytxt'], relief=tk.FLAT ).grid(column=1, row=i, sticky=tk.W) i +=1 def button_frame(self): """draws a frame to hold a edit- and syntax-buttons under each other """ self.btnfrm = tk.Frame(self) self.btnfrm.pack(fill=tk.BOTH, side=tk.LEFT) self.edit_buttons() self.syntax_buttons() def edit_buttons(self): """draws a frame with buttons for editing (save, undo, redo, open) """ # genrate a labelframe self.efrm = tk.LabelFrame(self.btnfrm, text="Edit Buttons") self.efrm.pack(fill=tk.BOTH, padx=5, pady=5) # generate a button with a pulldown menue to open a file to edit self.file_open_mbtn = tk.Menubutton(self.efrm, text='Open File') # generate the pulldown menue self.file_open_menu = tk.Menu(self.file_open_mbtn, postcommand=self.gen_file2edit_menu) # bind the pulldown menue to the menubutton self.file_open_mbtn.config(menu=self.file_open_menu, relief=tk.RIDGE) self.file_open_mbtn.grid(column=0,row=0, sticky=tk.W+tk.E) # label beside the Button to display the associated keyboard shortcut self.file_open_lbl = tk.Label(self.efrm, text='CTRL+o', relief=tk.FLAT) self.file_open_lbl.grid(column=1, row=0, sticky=tk.W+tk.E) # generate buttons as described in self.edit_button_list self.label_button_row(self.efrm, self.edit_button_list, 2) # bind keyboard shortcut to the menue self.text.bind('<Control-o>', lambda e: self.file_open_menu.tk_popup(e.x_root, e.y_root)) def gen_file2edit_menu(self): """generates a (new) menu bound to the file chooser button so every time when a project is created or deleted gen_choose_project_menu should be called """ # delete all existing menue entrys self.file_open_menu.delete(0,tk.END) proj_path = os.path.join(self.settings.projects_path, self.settings.current_project ) print "proj_path", proj_path for this_file in os.listdir(proj_path): splitted = os.path.splitext(this_file) if splitted[1] == ".txt" and splitted[0] != "menue": #print "this_file",this_file open_file = os.path.join(proj_path, this_file) do_it = lambda bla = open_file:self.on_open(bla) self.file_open_menu.add_command(label=splitted, command=do_it) def syntax_buttons(self): """draws a frame with buttons for insert (wiki)markup idea: new parameter for on_tag_insert() jump_in_between=True/False so a pulldown list for different levels of headlines arn't necessary """ # genrate a labelframe self.sfrm = tk.LabelFrame(self.btnfrm, text="Syntax Buttons") self.sfrm.pack(fill=tk.BOTH, padx=5, pady=5) # generate a button with a pulldown menue für headline Syntax self.headln_menubtn = tk.Menubutton(self.sfrm, text='= Headlines =') # generate the pulldown menue self.headln_menu = tk.Menu(self.headln_menubtn) # bind the pulldown menue to the menubutton self.headln_menubtn.config(menu=self.headln_menu, relief=tk.RIDGE) # generate menue entrys i=1 for entry in ('h1','h2','h3','h4','h5','h6'): otag = '\n\n'+'='*i+' ' ctag = ' '+'='*i+'\n\n' doit = lambda event=None, o=otag, c=ctag:self.on_tag_insert(event,o,c) self.headln_menu.add_command(label=entry, command=doit) i+=1 self.headln_menubtn.grid(column=0,row=0, sticky=tk.W+tk.E) # label beside the Button to display the associated keyboard shortcut self.headln_lbl = tk.Label(self.sfrm, text='CTRL+h', relief=tk.FLAT) self.headln_lbl.grid(column=1, row=0, sticky=tk.W+tk.E) # generate buttons as described in self.edit_button_list self.label_button_row(self.sfrm, self.syntax_button_list, 1) # bind keyboard shortcut to the menue self.text.bind('<Control-h>', lambda e: self.headln_menu.tk_popup(e.x_root, e.y_root)) def on_txt_changes(self, dummy_value=tk.NONE): """ tracks text changes inside the editfield by comparing hash values new name: visualize_txt_changes??? """ while True: new_hash = hash(self.text.get(1.0, tk.END)) if new_hash != self.hash_opened_filename: #print "changes" self.opened_file_label.configure(fg="red") else: #print "no changes" self.opened_file_label.configure(fg="black") sleep(0.2) def on_open(self, file_to_open=None): """- opens a *.txt file from project folder - generates a reference hash. - Brings the cursor to the upper left and show this position in the textfield Parameter: --> file_to_open: complete path for file to open idea: - rename file_to_open to openfile or file_to_open """ self.opened_file_to_open = file_to_open self.opened_file_label.configure(text=file_to_open) self.text.delete(1.0, tk.END) self.opened_filename = os.path.basename(file_to_open) # write file content into the editfield editfile = codecs.open(file_to_open,'r', 'utf-8') self.text.insert(1.0, editfile.read()) editfile.close() # generate reference hash for a comparison to track text changes self.hash_opened_filename = hash(self.text.get(1.0,tk.END)) self.text.edit_reset() # clear tk's undo/redo stacks self.text.focus_set() # focus to textfield self.text.mark_set(tk.INSERT, '0.0') # place cursor to upper left self.text.see(tk.INSERT) # and display this line def on_save(self): """ Safes the current edited file""" if self.opened_filename: print "on_safe_" print " self.opened_filename",self.opened_filename self.hash_opened_filename = hash(self.text.get(1.0,tk.END)) path_to_safe_file = os.path.join(self.settings.projects_path, self.settings.current_project, self.opened_filename) safefile = codecs.open(path_to_safe_file,'w', 'utf-8') safefile.write(self.text.get(1.0,tk.END)) safefile.close() self.text.edit_reset() #clear tk's undo/redo stacks else: showinfo('Globby Text Editor','No File to save \n\n' 'You need to choose a File before editing') def on_undo(self): try: # tk8.4 keeps undo/redo stacks self.text.edit_undo( ) # exception if stacks empty except tk.TclError: showinfo('Globby Text Editor', 'Nothing to undo') def on_redo(self): print "redo" try: # tk8.4 keeps undo/redo stacks self.text.edit_redo() # exception if stacks empty except tk.TclError: showinfo('Globby Text Editor', 'Nothing to redo') def on_new_page(self): """ Ask the user to name the new File, create a blank File and load it into the Editorwidget TODO: check if file with the new filename allready exists check if Filename contains Specialchars """ print "on_new_page" nfile_name = tkSimpleDialog.askstring("New File Name", "Fill in a new File Name") proj_path = os.path.join(self.settings.projects_path, self.settings.current_project) nfile_name = os.path.join(proj_path, nfile_name.strip()+'.txt') nfile = codecs.open(nfile_name, 'w', 'utf-8') current_project = self.settings.current_project infostring1 = u'# Diese Datei wurde automatisch mit ' infostring2 = u'dem Projekt "%s" erstellt' % current_project nfile.write(infostring1+infostring2 ) nfile.close() self.on_open(nfile_name) def on_del_page(self): """""" print "del page" # self.settings.current_project del_file = os.path.join(self.settings.projects_path, self.settings.current_project, self.opened_filename) del_page = askyesno("Do you really want to delete ", del_file) if del_page: #self.set_project(self.new_project_name) print "%s geloescht" % del_file os.remove(del_file) def on_tag_insert(self, event=None, open_tag=None, close_tag=None): """ inserts a (wiki)tag to the current cursor position. If there is no text marked in the editfield, open_tag and close_tag are inserted to the current cursor position behind each other and the cursor jumps in between. Otherwise the marked string is enclosed by open_tag and close_tag and inserted to the current cursor position. Here the new cursor position is right behind the complete inserted string with tags. At this moment this behavior is quite buggy :-( idea: - new parameter for on_tag_insert() jump_in_between=True/False so a pulldown list for different levels of headlines arn't necessary - rename to: on_insert_tag?? on_tag_insert Parameter: --> event # keyboard shortcut --> open_tag # string --> close_tag # string """ #print 'event',event #print 'open_tag',open_tag #print 'close_tag',close_tag ## when no String is selected: if not self.text.tag_ranges(tk.SEL): print "no String is selected" insert_point = self.text.index('insert') insertline = insert_point.split('.')[0] addit = 1 if event != None: print "event not None" addit = 2 insertrow = str(int(insert_point.split('.')[1])+len(open_tag)+addit) new_insert_point = insertline+'.'+ insertrow self.text.insert(insert_point, open_tag+''+close_tag) # place cursor to insert_point self.text.mark_set(tk.INSERT, new_insert_point) # display this position on the editfield self.text.see(tk.INSERT) ## when a String is selected: else: #print "im else" marked_text = self.text.get(self.text.index(tk.SEL_FIRST), self.text.index(tk.SEL_LAST)) replace_index = self.text.index(tk.SEL_FIRST) print "replace_index in selected", replace_index self.text.delete(self.text.index(tk.SEL_FIRST), self.text.index(tk.SEL_LAST)) self.text.insert(replace_index, open_tag+marked_text+close_tag)
class NamedWindow: """ This creates a window for the Tkui which you can then write to programmatically. This allows modules to spin off new named windows and write to them. """ def __init__(self, windowname, master, partk): """ Initializes the window @param windowname: the name of the new window @type windowname: string @param master: the main tk window @type master: toplevel """ self._parent = master self._tk = Toplevel(partk) self._windowname = windowname # map of session -> (bold, foreground, background) self._currcolors = {} # ses -> string self._unfinishedcolor = {} self._do_i_echo = 1 self._tk.geometry("500x300") self._tk.title("Lyntin -- " + self._windowname) self._tk.protocol("WM_DELETE_WINDOW", self.close) if os.name == "posix": fontname = "Courier" else: fontname = "Fixedsys" fnt = tkFont.Font(family=fontname, size=12) self._txt = ScrolledText(self._tk, fg="white", bg="black", font=fnt, height=20) self._txt.pack(side=TOP, fill=BOTH, expand=1) # handles improper keypresses self._txt.bind("<KeyPress>", self._ignoreThis) # initialize color tags self._initColorTags() def convertColor(self, name): """ Tk has this really weird color palatte. So I switched to using color names in most cases and rgb values in cases where I couldn't find a good color name. This method allows me to specify either an rgb or a color name and it converts the color names to rgb. @param name: either an rgb value or a name @type name: string @returns: the rgb color value @rtype: string """ if name[0] == "#": return name rgb = self._tk._getints( self._tk.tk.call('winfo', 'rgb', self._txt, name)) rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256) print name, "converted to: ", rgb return rgb def _initColorTags(self): """ Sets up Tk tags for the text widget (fg/bg).""" for ck in fg_color_codes.keys(): color = self.convertColor(fg_color_codes[ck]) self._txt.tag_config(ck, foreground=color) for ck in bg_color_codes.keys(): self._txt.tag_config(ck, background=bg_color_codes[ck]) self._txt.tag_config("u", underline=1) def _ignoreThis(self, tkevent): """ This catches keypresses to this window. """ return "break" def close(self): """ Closes and destroys references to this window. """ self._parent.removeWindow(self._windowname) self._tk.destroy() def _yadjust(self): """Handles y scrolling after text insertion.""" self._txt.yview('moveto', '1') # if os.name != 'posix': self._txt.yview('scroll', '20', 'units') def _clipText(self): """ Scrolls the text buffer up so that the new text written at the bottom of the text buffer can be seen. """ temp = self._txt.index("end") ind = temp.find(".") temp = temp[:ind] if (temp.isdigit() and int(temp) > 800): self._txt.delete("1.0", "100.end") def write(self, msg): """ This writes text to the text buffer for viewing by the user. This is overridden from the 'base.BaseUI'. """ if type(msg) == types.TupleType: msg = msg[0] if type(msg) == types.StringType: msg = message.Message(msg, message.LTDATA) line = msg.data ses = msg.session if line == '': return color, leftover = buffer_write(msg, self._txt, self._currcolors, self._unfinishedcolor) if msg.type == message.MUDDATA: self._unfinishedcolor[ses] = leftover self._currcolors[ses] = color self._clipText() self._yadjust()
class ClustererGui(ttk.Frame): """GUI to open/save xml/text-files and visualize clustering.""" def __init__(self, master=None): """Init GUI - get auto-split-sentences-option and standard test-file-folder from config-file.""" ttk.Frame.__init__(self, master) self.grid(sticky=tk.N+tk.S+tk.E+tk.W) self.createWidgets() self.filepath = None self.xml_filepath = None self.filename = None self.article_id = None self.extraction = None self.author_no = None self.correct = None self.result = None self.colors = [] config = ConfigParser.ConfigParser() config.read("config.cfg") params = dict(config.items("params")) article_dir = params['test_file_dir'] self.auto_split_sentences = bool(int(params['auto_split_sentences'])) self.show_knee_point = bool(int(params['show_knee_point'])) self.show_knee_point = False # currently not supported in GUI-mode self.last_dir = article_dir def createWidgets(self): """Organize GUI.""" top=self.winfo_toplevel() top.rowconfigure(0, weight=1) top.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.rowconfigure(1, weight=0) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=0) left_frame = ttk.Frame(self, relief="raised", borderwidth=1) left_frame.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W) left_frame.rowconfigure(0, weight=0) left_frame.rowconfigure(1, weight=1) left_frame.columnconfigure(0, weight=1) buttons_topleft = ttk.Frame(left_frame) buttons_topleft.grid(row=0, column=0) self.choose_file_btn = ttk.Button(buttons_topleft, text='choose file...', command=self.choose_file) self.choose_file_btn.grid(row=0, column=0) self.save_file_btn = ttk.Button(buttons_topleft, text='save file...', command=self.save_file) self.save_file_btn.grid(row=0, column=1) self.extract_feat_btn = ttk.Button(buttons_topleft, text='process', command=self.start_featureextr_thread) self.extract_feat_btn.grid(row=0, column=2) right_frame = ttk.Frame(self) right_frame.grid(row=0, column=1, sticky=tk.N+tk.S+tk.E+tk.W) right_frame.rowconfigure(0, weight=1) right_frame.rowconfigure(1, weight=1) self.distr_entry = ScrolledText(right_frame, width=30, height=30) self.distr_entry.grid(row=0, column=0, columnspan=2, sticky=tk.N) self.test_entry = ScrolledText(right_frame, width=30) self.test_entry.grid(row=1, column=0, columnspan=2, sticky=tk.N) self.scrolledText = ScrolledText(left_frame, undo=True, wrap=tk.WORD) self.scrolledText['font'] = ('Helvetica', '12') self.scrolledText.tag_configure('lines', background="#dddddd", foreground="black", font=('Helvetica', 9)) self.scrolledText.tag_configure('blanks', background="#ffffff", foreground="black", font=('Helvetica', 9)) self.scrolledText.grid(row=1, column=0, sticky=tk.N+tk.S+tk.E+tk.W) status_bar = ttk.Frame(self) status_bar.grid(row=1, column=0, columnspan=2, sticky=tk.W) status_bar.columnconfigure(0, weight=1, minsize=100) status_bar.columnconfigure(1, weight=1) self.status = tk.StringVar() self.status.set("ready") self.status_label = ttk.Label(status_bar, textvariable=self.status) self.status_label.grid(row=0, column=1, padx=10) self.progressbar = ttk.Progressbar(status_bar, mode='indeterminate', length=200) self.progressbar.grid(row=0, column=0, padx=3) def choose_file(self): """Choose text or xml file dialog.""" self.filepath = askopenfilename(initialdir=self.last_dir, filetypes=(("text and xml files", ("*.txt","*.xml")),)) if self.filepath: ext = os.path.splitext(self.filepath)[1] if ext == ".xml": '''save raw-text of xml-file to a new file and print it''' self.xml_filepath = self.filepath self.filepath = self.create_text_fromXML() base = os.path.split(self.filepath)[0] self.article_id = os.path.split(base)[1] self.filename = os.path.split(self.filepath)[1] self.scrolledText.delete(1.0, tk.END) self.print_raw_text() self.scrolledText.edit_reset() def create_text_fromXML(self): """Create text-file out of given xml-file.""" new_filepath = os.path.splitext(self.filepath)[0] + ".txt" with codecs.open(self.filepath, 'r', 'UTF-8') as xml_file: xml_tree = etree.parse(xml_file) with codecs.open(new_filepath, 'w', 'UTF-8') as newFile: first_entry = True for entry in xml_tree.getroot(): if entry.text is not None: if not first_entry: newFile.write("\n\n") else: first_entry = False newFile.write(entry.text) return new_filepath def save_file(self): """Save text-file-dialog.""" text = self.scrolledText.get("0.0", tk.END) if self.filepath is None: name = asksaveasfilename(initialdir=self.last_dir, defaultextension=".txt") if name: self.filepath = name else: return try: with codecs.open(self.filepath, 'w', 'UTF-8') as newFile: newFile.write(text.strip()) self.scrolledText.edit_reset() base = os.path.split(self.filepath)[0] self.article_id = os.path.split(base)[1] self.filename = os.path.split(self.filepath)[1] return True except Exception:# as e: raise def start_featureextr_thread(self): """Start thread for feature extraction.""" self.distr_entry.delete(1.0, tk.END) self.status.set("processing...") if self.filepath is None or self.article_id is None: tkMessageBox.showwarning( "Save File", "Save file for feature extraction.") return try: self.scrolledText.edit_undo() self.scrolledText.edit_redo() tkMessageBox.showwarning( "File changed", "File was changed, please save.") return except tk.TclError: self.extraction = clusterer.Clusterer(self.article_id, self.filepath, self.xml_filepath, self.auto_split_sentences, self.show_knee_point) self.ftr_extr_thread = threading.Thread(target=self.extract_features) self.ftr_extr_thread.daemon = True self.progressbar.start() self.ftr_extr_thread.start() self.after(1000, self.check_feat_thread) def check_feat_thread(self): """Check if feature extraction thread is still working - if not: visualize cluster-results.""" if self.ftr_extr_thread.is_alive(): self.after(1000, self.check_feat_thread) else: self.status.set("ready") # generate author-colormap self.colors = [None]*len(set(self.clusters)) for k in set(self.clusters): temp_color = plt.cm.spectral(np.float(k) / (np.max(self.clusters) + 1)) if k == 0: temp_color = plt.cm.spectral(0.05) self.colors[k] = self.convert_to_hex(temp_color) self.configure_colors() self.progressbar.stop() self.print_author_distr() self.print_text() if self.correct is not None and self.author_no is not None: self.test_entry.delete(1.0, tk.END) s = "authors found: {}".format(len(set(self.clusters))) s += "\n believe-score: {:.4f}".format(self.believe_score) s += "\n\n true number of authors: {}".format(self.author_no) s += "\n precision: {:.4f}".format(self.scores[0]) s += "\n recall: {:.4f}".format(self.scores[1]) s += "\n f1-score: {:.4f}".format(self.scores[2]) s += "\n adjusted-rand-index: {:.4f}".format(self.scores[3]) self.test_entry.insert(tk.INSERT, s) else: self.test_entry.delete(1.0, tk.END) s = "authors found: {}".format(len(set(self.clusters))) s += "\n believe-score: {:.4f}".format(self.believe_score) self.test_entry.insert(tk.INSERT, s) def extract_features(self): """Start feature extraction.""" self.clusters, self.result, self.author_no, self.believe_score, self.scores = self.extraction.calc_cluster() if self.result is not None: c = Counter(self.result) self.correct = c[True] / sum(c.values()) * 100 def print_text(self): """Print raw text with specified author-colors.""" self.scrolledText.delete(1.0, tk.END) f = open(self.filepath) line_number = 0 actual_line_number = 0 for line in f: actual_line_number += 1 if line.strip(): s = str(line_number) + ' '+str(self.clusters[line_number]) + ' '+line s = line line_cluster = str(line_number) + ' '+str(self.clusters[line_number])+ ' ' line_cluster = ('{:^'+str(14-len(line_cluster))+'}').format(line_cluster) self.scrolledText.insert(tk.INSERT, line_cluster, 'lines') try: self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number])) # if self.result[line_number]: # # correct assignment - print text foreground in white # self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number])) # else: # # false assignment - print text foreground in black # self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number]*10**2)) except IndexError: self.scrolledText.insert(tk.INSERT, s) except TypeError: self.scrolledText.insert(tk.INSERT, s, str(self.clusters[line_number])) line_number += 1 else: s = line self.scrolledText.insert(tk.INSERT, s, 'blanks') f.close() def print_raw_text(self): """Print raw text.""" f = open(self.filepath) for line in f: self.scrolledText.insert(tk.INSERT, line) f.close() def get_distribution(self, l=None): """Return Counter with author distribution in percent.""" if l is None: l = self.clusters counter = Counter(l) sum_counter = sum(counter.values()) for key in counter.iterkeys(): counter[key] = counter[key] / sum_counter * 100 return counter def print_author_distr(self): """Print author distribution with specified author-colors.""" self.distr_entry.delete(1.0, tk.END) distr = self.get_distribution(self.clusters) for index, count in distr.most_common(): author_i = "author "+str(index)+"{:>20}%\n".format(locale.format(u'%.2f',count)) self.distr_entry.insert(tk.INSERT, author_i, str(index)) def convert_to_hex(self, col): """Convert inter-tuple to hex-coded string.""" red = int(col[0]*255) green = int(col[1]*255) blue = int(col[2]*255) return '#{r:02x}{g:02x}{b:02x}'.format(r=red,g=green,b=blue) def configure_colors(self): """Configure author-specific colors for author-distribution and cluster-results.""" for i,c in enumerate(self.colors): self.scrolledText.tag_configure(str(i), background=c, foreground="white") self.distr_entry.tag_configure(str(i), background=c, foreground="white")
class DesDesk(): def __init__(self): window = Tk() window.title("des加密与解密") window.geometry('700x500+300+150') # window['background'] = 'MintCream' # window['background'] = 'Moccasin' # window['background'] = 'Honeydew' # img_gif = PhotoImage(file='timg.gif') # image = Image.open(r'timg.gif') # background_image = ImageTk.PhotoImage(image) # background_image = ImageTk.PhotoImage(image) # window['background'] = background_image # window['background'] = img_gif window['background'] = "LightCyan" # window.iconbitmap("des.jpeg") # frame1 = Frame(window) # frame1.pack() window_x = 120 font = "Times" font_color = "LightCoral" # font_color = "Wheat" input_label = Label(window, text="明文") input_label.config(bg=font_color) input_label.config(font=font) input_label_y = 10 input_label.place(x=window_x, y=input_label_y) self.input_text = ScrolledText(window, height=8, width=60) self.input_text.tag_config('a', foreground='red') self.input_text.place(x=window_x, y=input_label_y + 30) key_label = Label(window, text="密码") key_label.config(font=font) key_label.config(bg=font_color) self.key = StringVar() key_entry = Entry(window, textvariable=self.key) key_entry['show'] = "*" key_label_y = 190 key_label.place(x=window_x, y=key_label_y) key_entry.place(x=window_x + 40, y=key_label_y) button_color = "CornflowerBlue" btn_font_color = "Ivory" encode = Button(window, text="加密", command=self.encode_text) encode.config(font=font) encode.config(bg=button_color) encode.config(fg=btn_font_color) #decode_img = PhotoImage(file="decode.png") decode = Button(window, text="解密", command=self.decode_text) decode.config(font=font) decode.config(bg=button_color) decode.config(fg=btn_font_color) encode.place(x=window_x + 300, y=key_label_y) decode.place(x=window_x + 380, y=key_label_y) out_label = Label(window, text="密文") out_label.config(font=font) out_label.config(bg=font_color) out_label_y = 240 out_label.place(x=window_x, y=out_label_y) self.out_text = ScrolledText(window, height=8, width=60) self.out_text.place(x=window_x, y=out_label_y + 30) #label = Label(window, text="解密").place(x=20,y=30) # text_area.grid(row=1, column=1) # text_entry.grid(row=1, column=2) # key_label.grid(row=2, column=1) # key_entry.grid(row=2, column=2) # encode.grid(row=2, column=1) # import and export button import_btn = Button(window, text="导入", command=self.ask_open_file) export_btn = Button(window, text="导出", command=self.ask_save_file) import_btn.place(x=window_x + 300, y=out_label_y + 160) export_btn.place(x=window_x + 380, y=out_label_y + 160) import_btn.config(font=font) import_btn.config(bg=button_color) import_btn.config(fg=btn_font_color) export_btn.config(font=font) export_btn.config(bg=button_color) export_btn.config(fg=btn_font_color) window.mainloop() def ask_open_file(self): try: file_path = tkFileDialog.askopenfilename() with open(file_path, "r") as file: contents = file.read() # print(contents) contents = eval(contents) text_not_null = False if contents.has_key('text'): self.input_text.insert(END, contents['text']) text_not_null = True if contents.has_key("key"): self.key.set(contents['key']) text_not_null = True if contents.has_key("encode"): self.out_text.insert(END, contents['encode']) text_not_null = True if text_not_null: showinfo("提示", "导入成功!") else: showinfo("提示", "文件为空!") except Exception as e: return # 将明文、密码和密文以字典方式保存 def ask_save_file(self): try: file_path = tkFileDialog.asksaveasfilename() contents = dict( text=self.input_text.get("1.0", END).strip(), key=self.key.get().strip(), encode=self.out_text.get("1.0", END).strip(), ) contents = str(contents) print(contents) with open(file_path, "w") as file: file.write(contents) showinfo("提示", "导出成功!") except Exception as e: return def encode_text(self): text = self.input_text.get("1.0", END).strip() key = self.key.get().strip() if text == "" or text == None: print("请输入明文!") showinfo("提示", "请输入明文!") return if key == "" or key == None: print("请输入密码!") showinfo("提示", "请输入密码!") return if not check_key(key): showinfo("提示", "密码中必须含有数字、字母和特殊字符!") self.key.set("") return print("text:%s;key:%s" % (text, key)) encoded_text = des.code(text, key) print("encode_text is %s" % encoded_text) # clean out_put area self.out_text.delete("1.0", END) # insert into out_put text self.out_text.insert(END, encoded_text) def decode_text(self): text = self.out_text.get("0.0", END).strip() key = self.key.get().strip() if text == "" or text == None: print("请输入密文!") showinfo("提示", "请输入密文!") return if key == "" or text == None: print("请输入密码!") showinfo("提示", "请输入密码!") return print("text:%s;key:%s" % (text, key)) try: decoded_text = des_1.decode(text, key) print("decoded_text is %s" % decoded_text) except Exception as e: showerror("", "解密过程出错请重试!") self.out_text.delete("1.0", END) self.key.set("") return self.input_text.delete("1.0", END) self.input_text.insert(END, decoded_text)
class Tkui(base.BaseUI): """ This is a ui class which handles the complete Tk user interface. """ def __init__(self): """ Initializes.""" base.BaseUI.__init__(self) # internal ui queue self._event_queue = Queue.Queue() # map of session -> (bold, foreground, background) self._currcolors = {} # ses -> string self._unfinishedcolor = {} self._viewhistory = 0 self._do_i_echo = 1 # holds a map of window names -> window references self._windows = {} # instantiate all the widgets self._tk = Tk() self._tk.geometry("800x600") self.settitle() if os.name == 'posix': fnt = tkFont.Font(family="Courier", size=12) else: fnt = tkFont.Font(family="Fixedsys", size=12) self._entry = CommandEntry(self._tk, self, fg='white', bg='black', insertbackground='yellow', font=fnt, insertwidth='2') self._entry.pack(side='bottom', fill='both') self._topframe = Frame(self._tk) self._topframe.pack(side='top', fill='both', expand=1) self._txt = ScrolledText(self._topframe, fg='white', bg='black', font=fnt, height=20) self._txt.pack(side='bottom', fill='both', expand=1) self._txt.bind("<KeyPress>", self._ignoreThis) self._txtbuffer = ScrolledText(self._topframe, fg='white', bg='black', font=fnt, height=20) self._txtbuffer.bind("<KeyPress-Escape>", self.escape) self._txtbuffer.bind("<KeyPress>", self._ignoreThis) self._entry.focus_set() self._initColorTags() self.dequeue() exported.hook_register("config_change_hook", self.configChangeHandler) exported.hook_register("to_user_hook", self.write) # FIXME - fix this explanation. this is just terrible. tc = config.BoolConfig( "saveinputhighlight", 0, 1, "Allows you to change the behavior of the command entry. When " "saveinputhighlight is off, we discard whatever is on the entry " "line. When it is on, we will retain the contents allowing you " "to press the enter key to do whatever you typed again.") exported.add_config("saveinputhighlight", tc) self._quit = 0 def runui(self): global HELP_TEXT exported.add_help("tkui", HELP_TEXT) exported.write_message("For tk help type \"#help tkui\".") exported.add_command("colorcheck", colorcheck_cmd) # run the tk mainloop here self._tk.mainloop() def wantMainThread(self): # The tkui needs the main thread of execution so we return # a 1 here. return 1 def quit(self): if not self._quit: self._quit = 1 self._topframe.quit() def dequeue(self): qsize = self._event_queue.qsize() if qsize > 10: qsize = 10 for i in range(qsize): ev = self._event_queue.get_nowait() ev.execute(self) self._tk.after(25, self.dequeue) def settitle(self, title=""): """ Sets the title bar to the Lyntin title plus the given string. @param title: the title to set @type title: string """ if title: title = constants.LYNTINTITLE + title else: title = constants.LYNTINTITLE self._event_queue.put(_TitleEvent(self._tk, title)) def removeWindow(self, windowname): """ This removes a NamedWindow from our list of NamedWindows. @param windowname: the name of the window to write to @type windowname: string """ if self._windows.has_key(windowname): del self._windows[windowname] def writeWindow(self, windowname, message): """ This writes to the window named "windowname". If the window does not exist, we spin one off. It handles ansi text and messages just like writing to the main window. @param windowname: the name of the window to write to @type windowname: string @param message: the message to write to the window @type message: string or Message instance """ self._event_queue.put(_WriteWindowEvent(windowname, message)) def writeWindow_internal(self, windowname, message): if not self._windows.has_key(windowname): self._windows[windowname] = NamedWindow(windowname, self, self._tk) self._windows[windowname].write(message) def _ignoreThis(self, tkevent): """ This catches keypresses from the history buffer.""" # kludge so that ctrl-c doesn't get caught allowing windows # users to copy the buffer.... if tkevent.keycode == 17 or tkevent.keycode == 67: return self._entry.focus() if tkevent.char: # we do this little song and dance so as to pass events # we don't want to deal with to the entry widget essentially # by creating a new event and tossing it in the event list. # it only sort of works--but it's the best code we've got # so far. args = ('event', 'generate', self._entry, "<KeyPress>") args = args + ('-rootx', tkevent.x_root) args = args + ('-rooty', tkevent.y_root) args = args + ('-keycode', tkevent.keycode) args = args + ('-keysym', tkevent.keysym) self._tk.tk.call(args) return "break" def pageUp(self): """ Handles prior (Page-Up) events.""" if self._viewhistory == 0: self._txtbuffer.pack(side='top', fill='both', expand=1) self._viewhistory = 1 self._txtbuffer.delete("1.0", "end") lotofstuff = self._txt.get('1.0', 'end') self._txtbuffer.insert('end', lotofstuff) for t in self._txt.tag_names(): taux = None tst = 0 for e in self._txt.tag_ranges(t): if tst == 0: taux = e tst = 1 else: tst = 0 self._txtbuffer.tag_add(t, str(taux), str(e)) self._txtbuffer.yview('moveto', '1') if os.name != 'posix': self._txtbuffer.yview('scroll', '20', 'units') self._tk.update_idletasks() self._txt.yview('moveto', '1.0') if os.name != 'posix': self._txt.yview('scroll', '220', 'units') else: # yscroll up stuff self._txtbuffer.yview('scroll', '-15', 'units') def pageDown(self): """ Handles next (Page-Down) events.""" if self._viewhistory == 1: # yscroll down stuff self._txtbuffer.yview('scroll', '15', 'units') def escape(self, tkevent): """ Handles escape (Escape) events.""" if self._viewhistory == 1: self._txtbuffer.forget() self._viewhistory = 0 else: self._entry.clearInput() def configChangeHandler(self, args): """ This handles config changes including mudecho. """ name = args["name"] newvalue = args["newvalue"] if name == "mudecho": if newvalue == 1: # echo on self._do_i_echo = 1 self._entry.configure(show='') else: # echo off self._do_i_echo = 0 self._entry.configure(show='*') def _yadjust(self): """Handles y scrolling after text insertion.""" self._txt.yview('moveto', '1') # if os.name != 'posix': self._txt.yview('scroll', '20', 'units') def _clipText(self): """ Scrolls the text buffer up so that the new text written at the bottom of the text buffer can be seen. """ temp = self._txt.index("end") ind = temp.find(".") temp = temp[:ind] if (temp.isdigit() and int(temp) > 800): self._txt.delete("1.0", "100.end") def write(self, args): """ This writes text to the text buffer for viewing by the user. This is overridden from the 'base.BaseUI'. """ self._event_queue.put(_OutputEvent(args)) def write_internal(self, args): mess = args["message"] if type(mess) == types.StringType: mess = message.Message(mess, message.LTDATA) line = mess.data ses = mess.session if line == '' or self.showTextForSession(ses) == 0: return color, leftover = buffer_write(mess, self._txt, self._currcolors, self._unfinishedcolor) if mess.type == message.MUDDATA: self._unfinishedcolor[ses] = leftover self._currcolors[ses] = color self._clipText() self._yadjust() def convertColor(self, name): """ Tk has this really weird color palatte. So I switched to using color names in most cases and rgb values in cases where I couldn't find a good color name. This method allows me to specify either an rgb or a color name and it converts the color names to rgb. @param name: either an rgb value or a name @type name: string @returns: the rgb color value @rtype: string """ if name.startswith("#"): return name rgb = self._tk._getints( self._tk.tk.call('winfo', 'rgb', self._txt, name)) rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256) print name, "converted to: ", rgb return rgb def _initColorTags(self): """ Sets up Tk tags for the text widget (fg/bg/u).""" for ck in fg_color_codes.keys(): color = self.convertColor(fg_color_codes[ck]) self._txt.tag_config(ck, foreground=color) self._txtbuffer.tag_config(ck, foreground=color) for ck in bg_color_codes.keys(): self._txt.tag_config(ck, background=bg_color_codes[ck]) self._txtbuffer.tag_config(ck, background=bg_color_codes[ck]) self._txt.tag_config("u", underline=1) self._txtbuffer.tag_config("u", underline=1) def colorCheck(self): """ Goes through and displays all the combinations of fg and bg with the text string involved. Purely for debugging purposes. """ fgkeys = ['30', '31', '32', '33', '34', '35', '36', '37'] bgkeys = ['40', '41', '42', '43', '44', '45', '46', '47'] self._txt.insert('end', 'color check:\n') for bg in bgkeys: for fg in fgkeys: self._txt.insert('end', str(fg), (fg, bg)) self._txt.insert('end', str("b" + fg), ("b" + fg, bg)) self._txt.insert('end', '\n') for fg in fgkeys: self._txt.insert('end', str(fg), (fg, "b" + bg)) self._txt.insert('end', str("b" + fg), ("b" + fg, "b" + bg)) self._txt.insert('end', '\n') self._txt.insert('end', '\n') self._txt.insert('end', '\n')
class dial_gui(Frame): doireg = re.compile('^[0-9]{2}\.[0-9]{4}/.+$') def __init__(self, master=None): Frame.__init__(self, master) self.pack(expand=YES, fill=BOTH) log = login_win() self.login = log.login self.passwd = log.passwd self.createWidgets() self.importer = DialImporter(log.login,log.passwd) def createWidgets(self): self.inframe = Frame(self) self.intext = Label(self.inframe,text="Fetch DOIs for:") self.ininput = Entry(self.inframe) self.ininput.bind('<Return>', (lambda event: self.fetch_dois())) self.inbutton = Button(self.inframe,text="get DOIs",command=self.fetch_dois) self.qb = Button(self, text='Quit', command=self.quit) self.en = ScrolledText(self) self.en.insert(INSERT,'Enter DOI here, one line per DOI') self.rb = Button(self,text="Process",command=self.readentries) self.qb.pack(side=BOTTOM, fill=X, padx=10, pady=10) self.rb.pack(side=BOTTOM, fill=X, padx=10, pady=10) self.inframe.pack(side=TOP,fill=X,padx=10, pady=10) self.intext.pack(side=LEFT) self.ininput.pack(side=LEFT, padx=10) self.inbutton.pack(side=RIGHT) self.en.pack(side=TOP, fill=BOTH, padx=10, pady=10) self.ininput.focus() def fetch_dois(self): author = self.ininput.get().strip() dois = "\n".join(self.importer.get_author_dois(author)) self.en.delete('1.0', END) self.en.insert("1.0",dois) self.rb.focus() def readentries(self): self.content = self.en.get("1.0",END).strip().split("\n") badmatches = [doi for doi in self.content if not self.doireg.match(doi)] okmatches = [doi for doi in self.content if self.doireg.match(doi)] if len(badmatches): showwarning('','The following DOIs are malformed and will not be processed: \n'+'\n'.join(badmatches)) fails = {} for doi in okmatches: print "Getting info about", doi error = self.importer.get_info(doi) if error: fails[doi] = error else: print "Inserting into DIAL", doi try: error = self.importer.push_to_dial() except Exception as push_err: error = repr(push_err) if error : fails[doi] = error if len(fails): failmsg = '\n'.join([ key+", error: "+value for key, value in fails.items()]) showwarning('','The following DOIs import failed :\n\n'+failmsg) else: showinfo('','Importation of all {} DOIs ended successfully'.format(len(okmatches))) self.importer.cleanup_files()
class App(tk.Frame): def __init__(self, master=None, frets=17, strings=6): tk.Frame.__init__(self, master) self.pack(fill=tk.BOTH,expand=True) self.master.title('FB Dots') self.frets = frets + 1 self.strings = strings tframe = tk.Frame(self) tframe.pack(expand=False, anchor=tk.W) for i in range(self.frets): tk.Label(tframe, text=str(i)).grid(row=0, column=i) self.dots = [] for i in range(self.strings): dots = [] for j in range(self.frets): x = DotEntry(tframe, width=3) x.grid(row=(i + 1), column=j, sticky=(tk.E+tk.W)) dots.append(x) self.dots.append(dots) bframe = tk.Frame(self) bframe.pack(expand=False, anchor=tk.W) tk.Button(bframe, text='Load', command=self.load).grid(row=0, column=0, sticky=(tk.E+tk.W)) tk.Button(bframe, text='Save', command=self.save).grid(row=0, column=1, sticky=(tk.E+tk.W)) tk.Button(bframe, text='Clear', command=self.clear).grid(row=0, column=2, sticky=(tk.E+tk.W)) tk.Label(bframe, text=' Ring Character: ').grid(row=0, column=3, sticky=(tk.E+tk.W)) self.ring_character = tk.StringVar() self.ring_character.set('.') tk.Entry(bframe, textvariable=self.ring_character, width=2).grid(row=0, column=4, sticky=(tk.E+tk.W)) tk.Button(bframe, text='Down', command=self.move_down).grid(row=0, column=5, sticky=(tk.E+tk.W)) tk.Button(bframe, text='Up', command=self.move_up).grid(row=0, column=6, sticky=(tk.E+tk.W)) self.io = ScrolledText(self) self.io.pack(fill=tk.BOTH, expand=True, anchor=tk.N) def load(self): rc = self.ring_character.get() v = self.io.get(1.0, tk.END) val = unrepr(v) for d in val: s,f,t,r = d s = s - 1 out = t if r: out += rc if not out: out += ' ' self.dots[s][f].set(out) def save(self): rc = self.ring_character.get() val = [] for i in range(self.strings): for j in range(self.frets): v = self.dots[i][j].get() if len(v) == 0: continue if rc in v: r = 1 else: r = 0 v = ''.join([x for x in v if x not in [rc, ' ']]) val.append(((i + 1), j, v, r)) self.io.delete(1.0, tk.END) self.io.insert(tk.END, str(val)) def clear(self): for s in self.dots: for f in s: f.set('') def move(self, offset): self.save() self.clear() v = self.io.get(1.0, tk.END) val = unrepr(v) new_val = [] for d in val: s,f,t,r = d f += offset if 0 <= f < self.frets: new_val.append((s,f,t,r)) else: print f self.io.delete(1.0, tk.END) self.io.insert(tk.END, str(new_val)) self.load() def move_up(self): self.move(1) def move_down(self): self.move(-1)
class ClientGUI(object): def __init__(self, windowTitle="Client GUI"): # create new instance of TK self.base_gui = pygui.Tk() # store the windowTitle in an object attribute self.base_window_title = windowTitle # Connection Details self.connection_host = '' self.connection_name = '' self.connection_port = 0 # Client Object self.client = None # [Connection GUI Initialization] ::start self.connection_gui_bootstrapped = False self.connection_config_frame = pygui.Frame(self.base_gui) self.host_to_use_field = pygui.Entry(self.connection_config_frame) self.port_to_use_field = pygui.Entry(self.connection_config_frame) self.name_field = pygui.Entry(self.connection_config_frame) self.connect_server_btn = pygui.Button(self.connection_config_frame, text="Connect", command=self.connect_to_server) # [Connection GUI Initialization] ::end # [Main GUI Initialization] ::start self.main_gui_bootstrapped = False self.chat_room_frame = pygui.Frame(self.base_gui) self.activity_log_area = ScrolledText(self.chat_room_frame, height=10, width=50) self.message_field = pygui.Entry(self.chat_room_frame) self.submit_msg_btn = pygui.Button(self.chat_room_frame, text="Send", command=self.send_msg) self.exit_chat_btn = pygui.Button(self.chat_room_frame, text="Leave Chat Room", command=lambda: self.switch_context('connection')) # [Connection GUI Initialization] ::end def bootstrap(self): if self.client is None: print "Client Object must be specified. Call the set_client() method and set the ClientGUI Object." sys.exit(1) self.connection_gui() # set window title self.base_gui.wm_title(self.base_window_title) # handle close button self.base_gui.protocol("WM_DELETE_WINDOW", self.destroy_gui) # Start the GUI self.base_gui.mainloop() def connection_gui(self): # [Config Section] :start # assemble the UI and the frame if the attribute does not exist if self.connection_gui_bootstrapped is False: # Add field for host/hostname to use pygui.Label(self.connection_config_frame, text="Host").grid(row=0, column=0) self.host_to_use_field.grid(row=0, column=1) # Add field for port to use pygui.Label(self.connection_config_frame, text="Port").grid(row=1, column=0) self.port_to_use_field.grid(row=1, column=1) # Add field for chat username/alias pygui.Label(self.connection_config_frame, text="Name").grid(row=2, column=0) self.name_field.grid(row=2, column=1) self.connect_server_btn.grid(row=3, column=1) self.connection_gui_bootstrapped = True self.connection_config_frame.pack(side=pygui.TOP, padx=10, pady=10) # [Config Section] :end def main_gui(self): # [Chat Room] ::start # assemble the UI and the frame if the attribute does not exist if self.main_gui_bootstrapped is False: self.activity_log_area.grid(row=0) self.activity_log_area.edit_modified(0) self.activity_log_area.config(highlightbackground="black") self.activity_log_area.bind('<<Modified>>', self.scroll_to_end) self.message_field.grid(row=1, column=0) self.message_field.config(width=30) self.message_field.bind("<Return>", self.send_msg) self.submit_msg_btn.grid(row=1, column=1) self.exit_chat_btn.grid(row=2) self.main_gui_bootstrapped = True # empty the chat logs self.activity_log_area.delete("1.0", pygui.END) # show the frame for chat room self.chat_room_frame.pack(side=pygui.TOP, padx=10, pady=10) # [Chat Room] ::end def destroy_gui(self): # disconnect from the server self.client.disconnect() # destroy the window self.base_gui.destroy() def switch_context(self, context): if context == 'main': # hide the connection frame/GUI from the window if hasattr(self, 'connection_config_frame'): self.connection_config_frame.pack_forget() self.main_gui() title = "%s connected on %s:%s - %s" % (strip_uid(self.connection_name), self.connection_host, str(self.connection_port), self.base_window_title) # change the window title to show the connection details self.base_gui.wm_title(title) else: # disconnect from the server self.client.disconnect() # hide the chat room frame/GUI from the window if hasattr(self, 'chat_room_frame'): self.chat_room_frame.pack_forget() self.connection_gui() # set window title self.base_gui.wm_title(self.base_window_title) def scroll_to_end(self, *_): # scroll to the end of text area self.activity_log_area.see(pygui.END) self.activity_log_area.edit_modified(0) def connect_to_server(self): hostval = self.host_to_use_field.get() portval = self.port_to_use_field.get() nameval = self.name_field.get() if hostval != '' and portval != '' and nameval != '': self.connection_host = str(hostval) self.connection_name = str(nameval) # check if the host supplied is a valid ip address if not is_ipv4(self.connection_host): msgBox.showinfo("Client GUI", "Invalid IP Address") return # check if the input for port number is a valid integer try: self.connection_port = int(portval) except ValueError: msgBox.showinfo("Client GUI", "Invalid Port Number") return # initiate client-server connection if self.client.connect(self.connection_host, self.connection_port, self.connection_name) is True: # swap UI components/widgets self.switch_context('main') # log any broadcast message and disconnect on lost connection self.client.start_communications(self.log, lambda: self.switch_context('connection')) else: msgBox.showinfo("Client GUI", "Cant connect to server. Please try again later.") else: msgBox.showinfo("Client GUI", "Please enter the host, and port to connect to as well as your chat name") def set_client(self, client): self.client = client def send_msg(self, *_): message = self.message_field.get() # only send messages which are not empty if message: # show the message on your side self.log('[' + strip_uid(self.connection_name) + '] ' + message) # send the message to the other side self.client.send_msg(str(message)) # delete the message self.message_field.delete(0, pygui.END) def log(self, message): self.activity_log_area.insert(pygui.END, message + "\n")
class Application(Frame): def __init__(self, master): Frame.__init__(self, master) self.grid() self.create_widgets() def create_widgets(self): self.label_0 = Label(self, text = "Enter differential equation:") self.label_0.grid(row = 0, column = 0, sticky =W) self.label_1 = Label(self, text = "y' = ") self.label_1.grid(row = 1, column = 0, sticky =W) self.input_1 = Entry(self) self.input_1.grid(row = 1, column = 1, sticky = W) self.label_2 = Label(self, text = "y") self.label_2.grid(row = 1, column = 2, sticky =W) self.label_2 = Label(self, text = "Enter initial condition:") self.label_2.grid(row = 2, column = 0, sticky =W) self.label_3 = Label(self, text = "y(") self.label_3.grid(row = 3, column = 0, sticky =W) self.input_2 = Entry(self) self.input_2.grid(row = 3, column = 1, sticky = W) self.label_4 = Label(self, text = ") = ") self.label_4.grid(row = 3, column = 2, sticky =W) self.input_3 = Entry(self) self.input_3.grid(row = 3, column = 3, sticky = W) self.label_5 = Label(self, text = "Approximate: y(") self.label_5.grid(row = 4, column = 0, sticky =W) self.input_4 = Entry(self) self.input_4.grid(row = 4, column = 1, sticky = W) self.label_6 = Label(self, text = ")") self.label_6.grid(row = 4, column = 2, sticky =W) self.label_7 = Label(self, text = "Step size: ") self.label_7.grid(row = 5, column = 0, sticky =W) self.input_5 = Entry(self) self.input_5.grid(row = 5, column = 1, sticky = W) self.button = Button(self) self.button["text"] = "Get Solution" self.button["command"] = self.calculate self.button.grid(row = 6, column = 0, sticky = W) self.textbox = ScrolledText(self, wrap = WORD, width = 30, height = 10) self.textbox.grid(row = 7, column = 0, columnspan = 2, sticky = W) self.label_8 = Label(self, text = "Give me a sample calculation:") self.label_8.grid(row = 8, column = 0, sticky =W) self.button = Button(self) self.button["text"] = "Sample" self.button["command"] = self.sample self.button.grid(row = 8, column = 1, sticky = W) def calculate(self): """Increase the click count and display the new total""" df = float(self.input_1.get()) h_accum = float(self.input_2.get()) init = float(self.input_3.get()) end = float(self.input_4.get()) h = float(self.input_5.get()) results = get_result (df, init, h, end, h_accum) self.textbox.delete(0.0, END) self.textbox.insert(0.0, results) def sample(self): self.input_1.delete(0, 'end') self.input_2.delete(0, 'end') self.input_3.delete(0, 'end') self.input_4.delete(0, 'end') self.input_5.delete(0, 'end') self.input_1.insert(0, -5) self.input_2.insert(0, 0) self.input_3.insert(0, 1) self.input_4.insert(0, 4) self.input_5.insert(0, 0.25)
class SigBridgeUI(Tk): server = None server_thread = None def __init__(self): Tk.__init__(self) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) # 2 rows: firts with settings, second with registrar data self.main_frame = Frame(self) # Commands row doesn't expands self.main_frame.rowconfigure(0, weight=0) # Logs row will grow self.main_frame.rowconfigure(1, weight=1) # Main frame can enlarge self.main_frame.columnconfigure(0, weight=1) self.main_frame.columnconfigure(1, weight=1) self.main_frame.grid(row=0, column=0) # Run/Stop button self.server_button = Button(self.main_frame, text="Connect", command=self.start_server) self.server_button.grid(row=0, column=0) # Clear button self.clear_button = Button(self.main_frame, text="Clear Log", command=self.clear_log) self.clear_button.grid(row=0, column=1) # Logs Widget self.log_widget = ScrolledText(self.main_frame) self.log_widget.grid(row=1, column=0, columnspan=2) # made not editable self.log_widget.config(state='disabled') # Queue where the logging handler will write self.log_queue = Queue.Queue() # Setup the logger self.uilogger = logging.getLogger('SigBridgeUI') self.uilogger.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') # Use the QueueLogger as Handler hl = QueueLogger(queue=self.log_queue) hl.setFormatter(formatter) self.uilogger.addHandler(hl) # self.log_widget.update_idletasks() self.set_geometry() # Setup the update_widget callback reading logs from the queue self.start_log() def clear_log(self): self.log_widget.config(state='normal') self.log_widget.delete(0.0, END) self.log_widget.config(state='disabled') def start_log(self): self.uilogger.info("SigBridge Started.") self.update_widget() # self.control_log_button.configure(text="Pause Log", command=self.stop_log) def update_widget(self): self.log_widget.config(state='normal') # Read from the Queue and add to the log widger while not self.log_queue.empty(): line = self.log_queue.get() tag = "error" if " ERROR " in line else 'info' self.log_widget.insert(END, line, tag) self.log_widget.see(END) # Scroll to the bottom self.log_widget.update_idletasks() self.log_widget.tag_config('error', foreground="red") self.log_widget.config(state='disabled') self.log_widget.after(10, self.update_widget) def set_geometry(self): # set position in window w = 600 # width for the Tk h = 300 # height for the Tk # get screen width and height ws = self.winfo_screenwidth() # width of the screen hs = self.winfo_screenheight() # height of the screen # calculate x and y coordinates for the Tk window x = (ws/2) - (w/2) y = (hs/2) - (h/2) # set the dimensions of the screen # and where it is placed self.geometry('%dx%d+%d+%d' % (w, h, x, y)) def start_server(self): try: self.server = SigServer(('0.0.0.0', 25), None, self.uilogger) self.server_thread = threading.Thread(name='server', target=self.server.run) self.server_thread.daemon = True self.server_thread.start() self.server_button.configure(text="Disconnect", command=self.stop_server) except Exception as err: self.uilogger("Cannot start the server: %s" % err.message) # self.label_variable.set(self.entry_variable.get()+"(Started Signal Server)") # self.entry.focus_set() # self.entry.selection_range(0, END) def stop_server(self): self.server.shutdown() self.server_button.configure(text="Connect", command=self.start_server) self.server = None
class BackupUI(Frame): def __init__(self, parent=None, **options): Frame.__init__(self, parent, padx=10, pady=10) self.dataQueue = queue.Queue() self.thread = None self.outputPath = StringVar() self.userVar = IntVar() self.photoVar = IntVar() self.photoVar.set(1) self.top = Frame(self) self.top.pack(side=TOP, expand=YES, fill=X) self.top.config(bd=2) self.createForm() self.createButtons() self.createText() def createButtons(self): frm = Frame(self.top) frm.pack(side=RIGHT, expand=YES, anchor=NE) self.btnStart = Button(frm, text='开始备份', command=self.start) self.btnStart.pack(side=TOP) self.btnStop = Button(frm, text='停止备份', command=self.stop) self.btnStop.pack(side=TOP) self.btnStop.config(state=DISABLED) frm = Frame(self.top) frm.pack(side=RIGHT, expand=YES, anchor=NE) self.userCheck = Checkbutton(frm, text='备份好友资料', variable=self.userVar) self.userCheck.config(command=self.callback) self.userCheck.pack(side=TOP) self.photoCheck = Checkbutton( frm, text='备份相册照片', variable=self.photoVar) self.photoCheck.config(command=self.callback) self.photoCheck.pack(side=TOP) frm = Frame(self, pady=5, padx=5) frm.pack(side=TOP, anchor=W) self.btnSelect = Button(frm, text='选择保存路径', command=self.selectPath) self.btnSelect.pack(side=LEFT) self.savePath = Entry(frm, width=45, textvariable=self.outputPath) self.savePath.pack(side=LEFT) self.savePath.insert(END, os.path.abspath(os.path.join('.', 'output'))) def createForm(self): self.login = Frame(self.top) # self.login.config(padx=4, pady=4) self.login.pack(side=LEFT, anchor=W) fields = const.LOGIN_FIELDS self.inputs = [] for i in range(len(fields)): lbl = Label(self.login, text=fields[i]) lbl.grid(row=i, column=0) var = StringVar() self.inputs.append(var) ent = Entry(self.login, textvariable=var) ent.grid(row=i, column=1) self.login.rowconfigure(i, weight=1) self.login.columnconfigure(0, weight=1) self.login.columnconfigure(1, weight=1) def createText(self): winfont = ('simhei', 10, 'normal') font = ('Helvetica', 12, 'normal') self.content = Frame(self, pady=5) self.content.pack(side=LEFT, expand=YES, fill=BOTH) self.text = ScrolledText(self.content) self.text.pack(side=TOP, expand=YES, fill=BOTH) self.text.config(bg='light gray', fg='black') self.text.config(padx=10, pady=10, font=winfont if isWin32 else font) self.text.insert(END, const.USER_GUIDE) self.text.config(state=DISABLED) def selectPath(self): path = askdirectory(initialdir='.') if path: self.savePath.delete(0, END) self.savePath.insert(END, path) def callback(self): #print('callback', self.userVar.get(), self.photoVar.get()) pass def write(self, message): if message and message.strip(): # timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.dataQueue.put(timestamp+" - "+message+'\n') def updateText(self, message): self.text.config(state=NORMAL) self.text.insert(END, str(message)) self.text.config(state=DISABLED) self.text.see(END) self.text.update() def updateUI(self): try: message = self.dataQueue.get(block=False) if message: self.updateText(message) except queue.Empty: pass running = self.thread and self.thread.is_alive() self.btnStart.config(state=DISABLED if running else NORMAL) self.btnStop.config(state=NORMAL if running else DISABLED) self.after(100, self.updateUI) def stop(self): if getattr(self, 'thread'): self.thread.stop() def start(self): keys = ['username', 'password', 'target'] values = map(lambda x: x.get(), self.inputs) if not any(values): showerror(const.NO_INPUT_TITLE, const.NO_INPUT_MESSAGE) return options = dict(zip(keys, values)) options['output'] = self.savePath.get() options['include_user'] = self.userVar.get() options['include_photo'] = self.photoVar.get() print('启动参数:', options) self.text.config(state=NORMAL) self.text.delete('0.0', END) self.text.config(state=DISABLED) self.updateUI() self.thread = BackupThread(self, self.dataQueue, **options) self.thread.start()
class MainApp(Tk): """ Main page """ def __init__(self): Tk.__init__(self) self.find_b = PhotoImage(file="Image/Find_button.gif") self.logo = PhotoImage(file='Image/logo_app.gif') self.find_b2 = PhotoImage(file='Image/find_b2.gif') self.date = date() self.var = IntVar() def window(self): """Display Main window""" self.header = Frame(self, width=450, height=65, bg='#1E90FF') self.logo_name = Label(self.header, image=self.logo, bg='#1E90FF') self.datetime = Label(self, text=self.date) self.title_name = Label(self, text="Title", font=('Arial', 12,)) self.title_box = Entry(self, width = 58, bg='white', relief=FLAT, font=('AngsanaUPC', 15)) self.note_text = Label(self, text="Your Note", font=('Arial', 12,)) self.note_box = ScrolledText(self, font=('AngsanaUPC', 14), width=65, relief=FLAT, bg='white', height=9) self.check = Checkbutton(self, text='Favorite', bg='#FEFF92', variable=self.var, activebackground='#FEFF92', width=55, justify='left') self.add_note = Button(self, width=45, text="Add Note", bg='green', relief=FLAT, font=('Arial', 11, 'bold') , command=self.create_note, fg='white', activebackground='#13AA02', activeforeground='white') self.find_note = Button(self.header, image=self.find_b, relief=FLAT, bg='gray', font=('Arial', 13, 'bold') , command=self.find_notes, width=68, height=59, activebackground='#1E90FF') self.all = Button(self, width=31, height=2, fg='white', text="Note Storage", bg='#009cff', relief=FLAT, activeforeground='white', font=('Arial', 16, 'bold'), command=self.note_storage, activebackground='#0069C6') self.last = Frame(self, bg='#1E90FF', width=450, height=25) self.fac = Label(self.last, fg='white', bg='#1E90FF', text="Faculty of Information Technology, KMITL") self.header.place(x=0, y=0) self.logo_name.place(x=15, y=5) self.datetime.place(x=325, y=75) self.title_name.place(x=20, y=80) self.title_box.place(x=20, y=110) self.note_text.place(x=20, y=150) self.note_box.place(x=20, y=185) self.check.place(x=20, y=423) self.add_note.place(x=20, y=457) self.find_note.place(x=376, y=0) self.all.place(x=20, y=500) self.last.place(x=0, y=575) self.fac.place(x=110, y=3) self.bind("<Button-1>", self.flat) self.find_note.bind("<Button-1>", self.find_press) self.find_note.bind("<ButtonRelease-1>", self.find_release) def note_storage(self): """Create Note Storage page""" note_store = NoteStorage() note_store.geometry('450x600+450+90') note_store.title('Note Storage') note_store.resizable(width=False, height=False) note_store.all_note() def create_note(self): """Create new note page""" title_name = self.title_box.get() note_text = self.note_box.get('1.0', END) favorite = self.var.get() count = 0 for i in get_data(): if title_name == i: break else: count += 1 if title_name != '' and note_text != '' and len(title_name) <= 30: if count != len(get_data()): ask = tkMessageBox.askquestion\ ("Replace note", "Are you want to replace?", icon="warning") if ask == 'yes': self.title_box.delete(0, END) self.note_box.delete('1.0', END) note_page = NoteCreate() note_page.geometry('350x500+500+150') note_page.title('New note' + ' ' + ':' + ' ' + title_name) note_page.resizable(width=False, height=False) note_page.note_page(title_name, note_text, favorite) else: self.title_box.delete(0, END) self.note_box.delete('1.0', END) note_page = NoteCreate() note_page.geometry('350x500+500+150') note_page.title('New note' + ' ' + ':' + ' ' + title_name) note_page.resizable(width=False, height=False) note_page.note_page(title_name, note_text, favorite) elif len(title_name) > 30: error = tkMessageBox.showerror('Error', 'Your title is too long!') else: error = tkMessageBox.showerror('Error', 'Please input your note!') def find_notes(self): """Create find note page""" find = Findpage() find.geometry('400x500+475+145') find.resizable(width=False, height=False) find.title('Find your note') def flat(self, event): """Event widget flat""" event.widget.config(relief=FLAT) def find_press(self, event): """Event button press""" self.find_note.config(image=self.find_b2) def find_release(self, event): """Event button release""" self.find_note.config(image=self.find_b)
class TermWindow(Frame): EOL = None ## # constructor method def __init__(self, master=None, **cnf): apply(Frame.__init__, (self, master), cnf) self.__create_widgets__() self.rxWaitPattern = "" self.localEcho = False self.logFile = None self.inQueue = Queue.Queue() self.outQueue = Queue.Queue() self.update_thread_safe() def update_thread_safe(self): while not self.inQueue.empty(): element = self.inQueue.get_nowait() if element is not None: msg, tag = element self.__display__(msg, tag) self.st_trm.update_idletasks() self.st_trm.after(100, self.update_thread_safe) ## # def __create_widgets__(self): dfl_font = 'Courier 10' # the title frame of the terminal self.f_title = Frame(self) self.f_title.pack(fill=BOTH) self.f_title.configure(FRAMEBORDER) self.shVar = StringVar() # show/hide button self.b_sh = Button(self.f_title, textvariable=self.shVar, font=dfl_font) self.b_sh.pack(side=RIGHT) self.b_sh['command'] = self.show_hide_cont # clear screen button self.b_cls = Button(self.f_title, text="CLS", font=dfl_font, underline=0) self.b_cls.pack(side=RIGHT) self.b_cls['command'] = self.clear_screen # echo on/off button self.al_echo = Label(self.f_title, text="ECHO", relief=RAISED, font=dfl_font, padx='3m', pady='1m', underline=0) self.al_echo.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.al_echo.bind("<Button-1>", self.__echo_handler__) # log on/off button self.al_log = Label(self.f_title, text="LOG", relief=RAISED, font=dfl_font, padx='3m', pady='1m', underline=0) self.al_log.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.al_log.bind("<Button-1>", self.__log_handler__) # device connect button self.al_connect = Label(self.f_title, text="CONNECT", relief=RAISED, font=dfl_font, padx='3m', pady='1m', underline=1) self.al_connect.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.al_connect.bind("<Button-1>", self.__connect_handler__) self.mb_macros = Menubutton(self.f_title, text="Macros", relief=RAISED) self.mb_macros.pack(side=RIGHT, padx=1, pady=1, fill=BOTH) self.mb_macros.menu = Menu(self.mb_macros, tearoff=0) self.mb_macros["menu"] = self.mb_macros.menu # title of terminal window self.tVar = StringVar() self.l_title = Label(self.f_title, text="foo", font=dfl_font) self.l_title['textvariable'] = self.tVar self.l_title.pack(side=LEFT, expand=1, fill=X) self.l_title['width'] = 42 self.update_title("------ XXX ------") # frame for scrolled text window # (this frame handle needs to be kept fo show_hide_cont()) self.f_cont = Frame(self) # IO data scrolled text window self.st_trm = ScrolledText(self.f_cont, height=10, state=DISABLED, wrap=NONE) self.st_trm.pack(expand=1, fill=BOTH) self.st_trm['font'] = dfl_font self.st_trm.tag_config('E', foreground="blue") self.st_trm.tag_config('M', foreground="magenta") tframe = Frame(self.f_cont) tframe.pack(expand=0, fill=X) self.cmdVar = StringVar() self.ent_trm = Entry(tframe, textvariable=self.cmdVar, font=dfl_font) self.ent_trm.pack(side=LEFT, expand=1, fill=X) self.ent_trm.bind("<Control-l>", self.__log_handler__) self.ent_trm.bind("<Control-e>", self.__echo_handler__) self.ent_trm.bind("<Control-o>", self.__connect_handler__) self.ent_trm.bind("<Control-c>", self.clear_screen) self.ent_trm.bind("<Control-x>", self.show_hide_cont) self.ent_trm.bind("<Control-m>", lambda *args: self.do_macro("M")) self.ent_trm.bind("<KeyPress>", self.__input_handler__) self.gui_elements = [ self.b_sh, self.b_cls, self.al_echo, self.al_log, self.al_connect, self.mb_macros, self.l_title, self.st_trm, self.ent_trm ] self.show_cont() def add_macro(self, id, title, text=None, function=None, params=None): if text: cmd = lambda *args: self.do_macro(text) if function: user_func = eval(function) if params: params = eval(str(params)) else: params = {} cmd = lambda *args: user_func(self, DEVICES, **params) mb = self.mb_macros.menu.add_command(label=title, command=cmd) def _configure_(self, **args): for e in self.gui_elements: e.configure(args) def __input_handler__(self, *args): for i in args: self.terminal_device_write(i.char) def terminal_device_write(self, *args): for i in args: if self.localEcho: self.display(i, "E") if len(i): if i == "\r" or i == "\n": self.device.write(self.EOL) self.display(self.EOL, "E") self.cmdVar.set("") else: self.device.write(i) self.st_trm.update_idletasks() def __echo_handler__(self, *args): if self.localEcho: self.localEcho = False self.al_echo['relief'] = RAISED self.message("Local Echo OFF") else: self.localEcho = True self.al_echo['relief'] = SUNKEN self.message("Local Echo ON") def __log_handler__(self, *args): try: do_open = self.logFile.closed logname = self.logFile.name except: do_open = True logname = "" if do_open: if self.device.logname: logname = self.device.logname self.message("logfile from config file %s " % logname) else: fd = FileDialog(self) logname = fd.go(logname) try: if self.device.logmode not in "wa": self.device.logmode = "a" _print(3, "force _a_ppend") self.logFile = open(logname, self.device.logmode) self.al_log['relief'] = SUNKEN self.message("Logging ON: %s" % self.logFile.name) except: self.message("Error open logfile: %s" % logname) else: self.message("Logging OFF: %s" % self.logFile.name) self.logFile.flush() self.logFile.close() self.al_log['relief'] = RAISED def __connect_handler__(self, *args): if self.device.isConnected: self.device.disconnect() self.al_connect['relief'] = RAISED self.message("Disconnected") else: try: self.device.connect() self.al_connect['relief'] = SUNKEN self.message("Connected") self.al_connect['fg'] = "black" except: self.device.isConnected = False self.message(str(sys.exc_info()[1])) self.al_connect['fg'] = "red" def clear_screen(self, *args): self.st_trm['state'] = NORMAL self.st_trm.delete("0.0", END) self.st_trm['state'] = DISABLED def set_device(self, device): self.device = device self.device.configure(TxQueue=self.outQueue, RxQueue=self.inQueue) self.update_title(self.device) if self.device.log: self.__log_handler__() if self.device.auto_connect: self.__connect_handler__() def update_title(self, title): self.tVar.set(title) def show_cont(self): self.shVar.set("X") self.f_cont.pack(expand=1, fill=BOTH) def hide_cont(self): self.shVar.set("+") self.f_cont.pack_forget() def show_hide_cont(self, *args): if self.shVar.get() == "X": self.hide_cont() else: self.show_cont() def do_macro(self, *args): if self.localEcho: self.display(args[0] + "\n", "E") self.device.write(args[0] + "\n") def write(self, data): self.outQueue.put((data, None)) def message(self, text, tag='M'): msg = "[%s:%s:%s]\n" % (time.asctime(), self.device.name, text) if self.st_trm.index(AtInsert()).find(".0") < 1: msg = "\n" + msg self.inQueue.put((msg, tag)) def display(self, text, tag=None): self.inQueue.put((text, tag)) def __display__(self, msg, tag=None): self.st_trm['state'] = NORMAL here = self.st_trm.index(AtInsert()) for d in re.split("([\r\v\t\n])", msg): if len(d): if d != '\r': self.st_trm.insert(END, d) if tag: self.st_trm.tag_add(tag, here, AtInsert()) self.st_trm.see(END) self.st_trm['state'] = DISABLED try: self.logFile.write(msg) self.logFile.flush() except: pass
class File_search: # Constructor def __init__(self, master): # To run debug on, change variable to True self.debug = False filename_cache = 'cache.txt' # We create three frames. Top, main, bottom frames. Some prefer grid manager. self.top_frame = Frame(master, bg='#f4d142') self.top_frame.pack(side=TOP) # Main frame frame = Frame(master, bg='#ddd6d4') frame.pack(fill='y', expand=True) # Bottom frame self.bottom_frame = Frame(master, bg='#bcecf2') self.bottom_frame.pack(side=BOTTOM) if os.path.isfile(filename_cache): self.Log("File exists") # Read contents of file and append contents to listbox fh = open(filename_cache, 'r') self.file_list = fh.readlines() fh.close() self.file_list_box_label = Label(frame, text="Recently searched files", bg='#ddd6d4') self.file_list_box_label.pack(side=TOP) self.file_list_box = Listbox(frame, selectmode=SINGLE, bg='#ddd6d4') self.file_list_box.pack(side=TOP) for item in self.file_list: self.file_list_box.insert(END, item) else: self.Log("File does not exists") # Labels and entry's for accepting input file_label = Label(self.top_frame, text="Filename", bg='#f4d142') file_label.pack(side=LEFT) self.file_name = Entry(self.top_frame, bg='#f4d142') self.file_name.pack(side=LEFT) dir_label = Label(self.top_frame, text="Directory (where file might be) **", bg='#f4d142') dir_label.pack(side=LEFT, pady=50) self.dir_name = Entry(self.top_frame, bg='#f4d142') self.dir_name.pack(side=LEFT) note_label = Label( frame, text= "** If this is empty then the current working directory is taken", bg='#ddd6d4') note_label.pack(side=BOTTOM) # Create search button self.search = Button(frame, text="Search", command=self.search_file, bg='#ddd6d4') self.search.pack(side=LEFT, padx=10) # Create cache button self.cache = Button(frame, text="Cache filename", command=self.write_filename_for_caching, bg='#ddd6d4') self.cache.pack(side=LEFT, padx=10) # Create clear button self.clear = Button(frame, text="Clear Fields", command=self.clear_text, bg='#ddd6d4') self.clear.pack(side=LEFT, padx=10) # Label and text box for displaying output self.output_label = Label(self.bottom_frame, text="Search output:", bg='#bcecf2') self.output_label.pack(side=TOP) self.output = ScrolledText( self.bottom_frame, bg='#D66B54') # ScrolledText looks better. Can use Text as well. self.output['font'] = ('monaco', '12') def check_dir_access(self, cwd): """ Function to check access to file """ if os.path.exists(cwd): return True else: return False def clear_text(self, time_labels=0): """ Function to clear text and labels after search is clicked """ dummy = 0 if time_labels == 0: self.output.delete(1.0, END) self.file_name.delete(0, END) self.dir_name.delete(0, END) if time_labels == 1: try: self.time_label.pack_forget() self.time_taken_label.pack_forget() except AttributeError: dummy = 1 return def write_filename_for_caching(self): """ Write filename (that returns success for search) to file """ try: if self.success == True: self.output.delete(1.0, END) filename_cache = 'cache.txt' # created in current working directory filename_to_write = self.file_name.get() filename_to_write = filename_to_write.strip() fh = open(filename_cache, 'a') fh.write(filename_to_write + "\n") fh.close() self.output.text = "Cache updated successfully!" self.output.insert(1.0, self.output.text) if filename_to_write not in self.file_list: self.file_list_box.insert(END, filename_to_write) else: self.output.text = "File already in cache!" self.output.insert(END, self.output.text) except AttributeError: # If button is clicked with empty filename or before searching, throw error tkMessageBox.showinfo( 'Note', 'File name has to be searched before caching') return def search_file(self): # Clear time labels if search if performed more than once self.clear_text(time_labels=1) # Start timer start_time = time.time() # Delete any existing output self.output.delete(1.0, END) # Empty array paths = [] # Get input from ENTRY boxes dir_name = self.dir_name.get() dir_name = dir_name.strip() if dir_name is '': cwd = '.' else: cwd = dir_name bool = self.check_dir_access(cwd) if bool == False: tkMessageBox.showerror( "Error", "Directory doesn't exist. Please check spelling.") search_file = self.file_name.get() search_file = search_file.strip() # Validate empty inputs if search_file == '' and self.file_list_box.curselection() == []: tkMessageBox.showerror( 'Select one...', 'Enter filename or choose one file from listbox') if search_file == '': if self.file_list_box.curselection() != []: self.file_name.insert( 0, self.file_list_box.get(self.file_list_box.curselection())) search_file = self.file_name.get() search_file = search_file.strip() # Validate wildcard if '*' not in search_file: # No wildcard for root, dirs, files in os.walk(cwd): for filename in files: if filename.lower() == search_file.lower(): paths.append(os.path.abspath(root) + '/' + filename) else: # Wildcard match for root, dirs, files in os.walk(cwd): for filename in files: if fnmatch.fnmatch(filename.lower(), search_file.lower()): paths.append(os.path.abspath(root) + '/' + filename) # If found update output with paths if len(paths) > 0: self.Log(str(len(paths)) + " file(s) found ") self.output.text = str( len(paths)) + " files found with name " + search_file + "\n\n" for path in paths: self.success = True self.Log("File found at ---> " + str(path) + "\n") self.output.text += str(path) + "\n" # Else -> error else: self.output.text = "Error: File not found." self.Log("File not found") # Display time taken done_time = time.time() time_taken = done_time - start_time time_taken = math.ceil(time_taken) self.time_taken_label = Label(self.bottom_frame, text=str(time_taken) + " second(s)", bg='#bcecf2') self.time_taken_label.pack(side=BOTTOM) self.time_label = Label(self.bottom_frame, text="Time taken: ", bg='#bcecf2') self.time_label.pack(side=BOTTOM) # Insert output text in ScrolledText self.output.insert(1.0, self.output.text) self.output.pack(side=BOTTOM) return def Log(self, msg): """ Function to print debug messages """ if self.debug == True: print msg return
class Room(Toplevel): __client_sock = None __user_name = None __room_name = None __main_frame = None __top_frame = None __exit_room = False def __init__(self, client, room_name, main_frame, top_frame): Toplevel.__init__(self) self['background'] = 'grey' self.protocol('WM_DELETE_WINDOW', self.close_room) self.__user_name = main_frame.get_user_name() self.title("Room Name:" + room_name) self.__room_name = room_name self.configure_GUI() self.__client_sock = client self.__top_frame = top_frame self.__main_frame = main_frame self.__main_frame.add_new_room(self.__room_name, self) self.withdraw() self.mainloop() def show_room(self): self.__top_frame.withdraw() self.deiconify() def close_room(self): self.withdraw() def configure_GUI(self): # main window bg_color = '#208090' self['bg'] = bg_color self.geometry("400x500+520+500") self.resizable(width=True, height=True) self.frm_top = Frame(self, width=380, height=250) self.frm_mid = Frame(self, width=380, height=150) self.frm_btm = Frame(self, width=380, height=30) self.frm_btm['bg'] = bg_color self.label_msg_list = Label(self, justify=LEFT, text=u"""消息列表""") self.label_user_name = Label(self, justify=LEFT, text=self.__user_name) self.text_msg_List = ScrolledText(self.frm_top, borderwidth=1, highlightthickness=0, relief='flat', bg='#fffff0') self.text_msg_List.tag_config('userColor', foreground='red') self.text_msg_List.place(x=0, y=0, width=380, height=250) self.text_client_msg = ScrolledText(self.frm_mid) self.text_client_msg.grid(row=0, column=0) self.button_send_msg = Button(self.frm_btm, text='发送消息', command=self.__send_msg_btn_cmd) self.button_send_msg.place(x=0, y=0, width=100, height=30) self.button_exit_room = Button(self.frm_btm, text='退出房间', command=self.__exit_room_btn_cmd) self.button_exit_room.place(x=280, y=0, width=100, height=30) self.label_msg_list.grid(row=0, column=0, padx=2, pady=2, sticky=W) self.frm_top.grid(row=1, column=0, padx=2, pady=2) self.label_user_name.grid(row=2, column=0, padx=2, pady=2, sticky=W) self.frm_mid.grid( row=3, column=0, padx=2, pady=2, ) self.frm_btm.grid( row=4, column=0, padx=2, pady=2, ) self.frm_top.grid_propagate(0) self.frm_mid.grid_propagate(0) self.frm_btm.grid_propagate(0) def destroy_room(self): self.destroy() def query_room_user_name(self): msg = {'roomName': self.__room_name} data = package_sys_msg("SysRoomUserNameRequest", msg) self.__client_sock.append_to_msg_sending_queue(data) def __exit_room_btn_cmd(self): self.__exit_room = True msg = {'roomName': self.__room_name} data = package_sys_msg("SysExitRoomRequest", msg) self.__client_sock.append_to_msg_sending_queue(data) def __send_msg_btn_cmd(self): if self.__exit_room: return usr_msg = self.text_client_msg.get('0.0', END) self.display_new_msg(self.__user_name, usr_msg, 'userColor') self.text_client_msg.delete('0.0', END) data = package_room_chat_msg(self.__user_name, self.__room_name, usr_msg) self.__client_sock.append_to_msg_sending_queue(data) def display_new_msg(self, user_name, msg, config=''): self.text_msg_List['state'] = 'normal' msg_time = time.strftime(" %Y-%m-%d %H:%M:%S", time.localtime()) + '\n' self.text_msg_List.insert(END, user_name + ': ' + msg_time + msg + '\n', config) self.text_msg_List['state'] = 'disabled'
class NamedWindow: """ This creates a window for the Tkui which you can then write to programmatically. This allows modules to spin off new named windows and write to them. """ def __init__(self, windowname, master, partk): """ Initializes the window @param windowname: the name of the new window @type windowname: string @param master: the main tk window @type master: toplevel """ self._parent = master self._tk = Toplevel(partk) self._windowname = windowname # map of session -> (bold, foreground, background) self._currcolors = {} # ses -> string self._unfinishedcolor = {} self._do_i_echo = 1 self._tk.geometry("500x300") self._tk.title("Lyntin -- " + self._windowname) self._tk.protocol("WM_DELETE_WINDOW", self.close) if os.name == "posix": fontname = "Courier" else: fontname = "Fixedsys" fnt = tkFont.Font(family=fontname, size=12) self._txt = ScrolledText(self._tk, fg="white", bg="black", font=fnt, height=20) self._txt.pack(side=TOP, fill=BOTH, expand=1) # handles improper keypresses self._txt.bind("<KeyPress>", self._ignoreThis) # initialize color tags self._initColorTags() def convertColor(self, name): """ Tk has this really weird color palatte. So I switched to using color names in most cases and rgb values in cases where I couldn't find a good color name. This method allows me to specify either an rgb or a color name and it converts the color names to rgb. @param name: either an rgb value or a name @type name: string @returns: the rgb color value @rtype: string """ if name[0] == "#": return name rgb = self._tk._getints(self._tk.tk.call("winfo", "rgb", self._txt, name)) rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256) print name, "converted to: ", rgb return rgb def _initColorTags(self): """ Sets up Tk tags for the text widget (fg/bg).""" for ck in fg_color_codes.keys(): color = self.convertColor(fg_color_codes[ck]) self._txt.tag_config(ck, foreground=color) for ck in bg_color_codes.keys(): self._txt.tag_config(ck, background=bg_color_codes[ck]) self._txt.tag_config("u", underline=1) def _ignoreThis(self, tkevent): """ This catches keypresses to this window. """ return "break" def close(self): """ Closes and destroys references to this window. """ self._parent.removeWindow(self._windowname) self._tk.destroy() def _yadjust(self): """Handles y scrolling after text insertion.""" self._txt.yview("moveto", "1") # if os.name != 'posix': self._txt.yview("scroll", "20", "units") def _clipText(self): """ Scrolls the text buffer up so that the new text written at the bottom of the text buffer can be seen. """ temp = self._txt.index("end") ind = temp.find(".") temp = temp[:ind] if temp.isdigit() and int(temp) > 800: self._txt.delete("1.0", "100.end") def write(self, msg): """ This writes text to the text buffer for viewing by the user. This is overridden from the 'base.BaseUI'. """ if type(msg) == types.TupleType: msg = msg[0] if type(msg) == types.StringType: msg = message.Message(msg, message.LTDATA) line = msg.data ses = msg.session if line == "": return color, leftover = buffer_write(msg, self._txt, self._currcolors, self._unfinishedcolor) if msg.type == message.MUDDATA: self._unfinishedcolor[ses] = leftover self._currcolors[ses] = color self._clipText() self._yadjust()
#adding text area to the main window Label(root, text="Send serial command to arduino device").grid(row=0, column=0, columnspan=3, padx=8, sticky=W ) Label(root, text="Baud rate").grid(row=1, column=0, padx=8, sticky=W) baud_rate=StringVar() baud_rate.set("9600") Label(root, textvariable=baud_rate).grid(row=1, column=1, padx=1, sticky=W ) serial_out_data=StringVar() send_data = ttk.Entry(root, width=23, textvariable=serial_out_data) send_data.grid(row=1, column=2, columnspan=5, padx=8, sticky=W) send_button=Button(text="Send", command=send_serial) send_button.grid(row=1, column=5, padx=8) Label(root, text="").grid(row=2) txt_a = ScrolledText(root, width=60, height=13) txt_a.grid(row=3, column=0, columnspan=6) txt_a.delete(INSERT) #txt=Message(root, textvariable=serial_out_data, width=100).grid(row=3, column=0, columnspan=6) Label(root, text=" ").grid(row=4) Label(root, text="VOLTAGE MONITOR").grid(row=5, column=0,columnspan=3, padx=8, sticky=W+S+E+N) Label(root, text="Battery ").grid(row=6, column=0, padx=8, sticky=W) Label(root, text="Solar cell").grid(row=6, column=1, padx=8, sticky=W) Label(root, text="Charging ").grid(row=6, column=2, padx=8, sticky=W) Label(root, text=" ").grid(row=6, column=3, padx=8, sticky=W) Label(root, text=" ").grid(row=6, column=4, padx=8, sticky=W) Label(root, text=" ").grid(row=6, column=5, padx=8, sticky=W) # set the voltages to 0.0V for battery, solar and charging #battery #pwm slider pwm_var=StringVar()
class GUI_hcheck: # do everything! def __init__(self): self.top = Tk() self.top.title('Health Check Tool') self.top.geometry('1400x800') #------- Label,Entry defination ----------# self.l1 = Label(self.top, text="IP:").grid(row=1, column=1, sticky="w") self.e1 = Entry(self.top) self.e1.grid(row=1, column=2,sticky="ew") self.l2 = Label(self.top, text="User:"******"w") self.e2 = Entry(self.top) self.e2.grid(row=2, column=2,sticky="ew") self.l3 = Label(self.top, text="Passwd:").grid(row=3, column=1, sticky="w") self.e3 = Entry(self.top) self.e3['show'] = '*' self.e3.grid(row=3, column=2,sticky="ew") self.l4 = Label(self.top, text="Command pool:").grid(row=4, column=1, sticky="e") self.l5 = Label(self.top, text="To be run command:").grid(row=4, column=5, sticky="e") self.e4 = Entry(self.top, width=30) self.e4.grid(row=16, column=0, columnspan=3, sticky="ew") #------- Checkbutton defination ----------# self.cb1State = IntVar() self.cb1 = Checkbutton(self.top, variable=self.cb1State, text = "Always Yes", command=self.callCheckbutton) self.cb1.grid(row=21, column=16) #------- Listbox defination ----------# self.cmdfm = Frame(self.top) self.cmdsb = Scrollbar(self.cmdfm) self.cmdsb_x = Scrollbar(self.cmdfm,orient = HORIZONTAL) self.cmdsb.pack(side=RIGHT, fill=Y) self.cmdsb_x.pack(side=BOTTOM, fill=X) self.cmdls = Listbox(self.cmdfm, selectmode=EXTENDED, height=25, width=40, xscrollcommand=self.cmdsb_x.set, yscrollcommand=self.cmdsb.set) self.cmdsb.config(command=self.cmdls.yview) self.cmdsb_x.config(command=self.cmdls.xview) self.cmdls.pack(side=LEFT, fill=BOTH) self.cmdfm.grid(row=5, rowspan=10, column=0,columnspan=4,sticky="ew") self.db_file = os.path.join(os.getcwd(),'%s' % constants.DB_NAME) flist = utility.load_file(self.db_file) if flist != None: log.debug ("db file found, start load command") for element in flist: element = element.strip('\n') if element == '' or element.startswith('#'): continue self.cmdls.insert(END, element) else: log.debug ("db file doesn't existed, initail cmd") for element in constants.CMD_LIST_COMM: self.cmdls.insert(END, element) self.dirfm = Frame(self.top) self.dirsb = Scrollbar(self.dirfm) self.dirsb_x = Scrollbar(self.dirfm,orient = HORIZONTAL) self.dirsb.pack(side=RIGHT, fill=Y) self.dirsb_x.pack(side=BOTTOM, fill=X) self.dirs = Listbox(self.dirfm, selectmode=EXTENDED, height=25, width=40, xscrollcommand=self.dirsb_x.set,yscrollcommand=self.dirsb.set) self.dirsb.config(command=self.dirs.yview) self.dirsb_x.config(command=self.dirs.xview) self.dirs.pack(side=LEFT, fill=BOTH) self.dirfm.grid(row=5, rowspan=10, column=5,columnspan=4,sticky="ew") #------- Buttion defination ----------# # add command button self.b1 = Button(self.top,text=">>",width=6,borderwidth=3,relief=RAISED, command=self.move_cmd) self.b1.grid(row=7, column=4) # del command button self.b2 = Button(self.top,text="<<",width=6,borderwidth=3,relief=RAISED, command=self.del_cmd) self.b2.grid(row=8, column=4) # move up command button self.b3 = Button(self.top,text="up",width=6,borderwidth=3,relief=RAISED, command=self.up_cmd) self.b3.grid(row=7, column=10) # move down command button self.b4 = Button(self.top,text="down",width=6,borderwidth=3,relief=RAISED, command=self.down_cmd) self.b4.grid(row=8, column=10) # start command button self.b5 = Button(self.top,text="Start",bg='red',width=10,borderwidth=3,relief=RAISED, command=self.start_process) self.b5.grid(row=2, column=11) # yes button self.b6 = Button(self.top,text="Yes",width=6,borderwidth=3,relief=RAISED, command=self.set_confirm_yes) self.b6.grid(row=21, column=13) # No button self.b7 = Button(self.top,text="No",width=6,borderwidth=3,relief=RAISED, command=self.set_confirm_no) self.b7.grid(row=21, column=14) # Skip button self.b8 = Button(self.top,text="Skip",width=6,borderwidth=3,relief=RAISED, command=self.set_confirm_skip) self.b8.grid(row=21, column=15) # Add button self.b9 = Button(self.top,text="add cmd",width=10,borderwidth=3,relief=RAISED, command=self.add_command) self.b9.grid(row=15, column=1) # Del button self.b10 = Button(self.top,text="del cmd",width=10,borderwidth=3,relief=RAISED, command=self.del_command) self.b10.grid(row=15, column=2) # Manual button self.manual = False self.b11 = Button(self.top,text="Manual model",width=10,borderwidth=3,relief=RAISED, command=self.manual_mode) self.b11.grid(row=2, column=12) #------- ScrolledText defination ----------# self.sfm = Frame(self.top) self.console = ScrolledText(self.sfm,height=45, width=86,bg='black',fg='green',insertbackground='green') self.console['font'] = ('lucida console','10') self.console.bind("<Return>", self.process_input) self.console.pack() self.sfm.grid(row=4, rowspan=15, column=11,columnspan=10,sticky="ew") self.redir = redirect(self.console) sys.stdout = self.redir sys.stderr = self.redir self.fconsole = logging.StreamHandler(sys.stdout) self.fconsole.setLevel(logging.INFO) logging.getLogger('').addHandler(self.fconsole) #------- Menu defination ----------# self.menubar = Menu() # file menu self.fmenu = Menu() #self.fmenu.add_command(label = 'New',command=self.new_win) self.fmenu.add_command(label = 'Import cmd',command=self.load_cmd) self.fmenu.add_command(label = 'Export cmd',command=self.export_cmd) self.menubar.add_cascade(label = 'File', menu = self.fmenu) # edit menu self.emenu = Menu() self.cmenu = Menu() self.cvar = StringVar() for item in ['white/black', 'black/white', 'green/black']: self.cmenu.add_radiobutton(label = item, variable=self.cvar, value=item, command=self.sel_color_style) self.emenu.add_cascade(label = 'console style', menu = self.cmenu) self.emenu.add_command(label = 'reset cmd pool',command=self.reset_cmd_pool) self.menubar.add_cascade(label = 'Edit', menu = self.emenu) self.top['menu'] = self.menubar def new_win(self): #GUI_hcheck() pass def sel_color_style(self): log.debug ("select console color style: %s " % self.cvar.get()) color = self.cvar.get() if color == 'white/black': self.console.config(bg='black',fg='white',insertbackground='white') elif color == 'black/white': self.console.config(bg='white',fg='black',insertbackground='black') elif color == 'green/black': self.console.config(bg='black',fg='green',insertbackground='green') def move_cmd(self): if self.cmdls.curselection() != (): for i in self.cmdls.curselection(): if utility.elemet_exists(self.dirs.get(0,END), self.cmdls.get(i)) == None: self.dirs.insert(END,self.cmdls.get(i)) log.debug ("move command %s" % self.cmdls.get(i)) else: tkMessageBox.showwarning('Message', 'Please select at lease one item') def load_cmd(self): file = tkFileDialog.askopenfilename() flist = utility.load_file(file) if flist != None: self.dirs.delete(0,END) for element in flist: element = element.strip('\n') if element == '' or element.startswith('#'): continue if utility.elemet_exists(self.dirs.get(0,END), element) == None: self.dirs.insert(END, element) else: tkMessageBox.showerror('Message', 'import failed') def export_cmd(self): file = tkFileDialog.askopenfilename() if utility.export_file(self.dirs.get(0,END), file) == True: tkMessageBox.showinfo('Message', 'export finish') else: tkMessageBox.showerror('Message', 'export failed') def del_cmd(self): if self.dirs.curselection() != (): for i in self.dirs.curselection(): self.dirs.delete(i) else: tkMessageBox.showwarning('Message', 'Please select at lease one item') def up_cmd(self): select = self.dirs.curselection() if (len(select)) >= 2: tkMessageBox.showwarning('Message', 'Only one select is supported') return log.debug ("move up select pos: %s" % str(select)) if select != () and select != (0,): element = self.dirs.get(select) self.dirs.delete(select) self.dirs.insert((select[0] - 1), element) self.dirs.select_set(select[0] - 1) def down_cmd(self): select = self.dirs.curselection() if (len(select)) >= 2: tkMessageBox.showwarning('Message', 'Only one select is supported') return log.debug ("move down select pos: %s" % str(select)) if select != () and select != (END,): element = self.dirs.get(select) self.dirs.delete(select) self.dirs.insert((select[0] + 1), element) self.dirs.select_set(select[0] + 1) def start_process(self): log.debug ("current thread total numbers: %d" % threading.activeCount()) response = tkMessageBox.askokcancel('Message', 'Will start healthcheck, please click OK to continue, or cancel') if response == False: return th = threading.Thread(target=self.start_cmd) th.setDaemon(True) th.start() def start_cmd(self): self.manual = False cmd = list(self.dirs.get(0,END)) if len(cmd) == 0: log.info ("To be run cmd numbers none, quit...") return log.debug ("fetch cmd list from GUI: %s" % cmd) (ip, port) = utility.getipinfo(self.e1.get()) log.debug ("get ip infor-> ip: %s, port:%s" % (ip,port)) if ip == False: log.error ("Given ip infor is wrong! The right ip address: xxx.xxx.xxx.xxx or IP:port ") return self.b5.config(state=DISABLED) self.b11.config(state=DISABLED) self.console.delete('1.0',END) try: self.wf = Workflow(cmd, ip, self.e2.get(), self.e3.get(), port) self.wf.start() except: pass self.b5.config(state=NORMAL) self.b11.config(state=NORMAL) def manual_mode(self): cmd = [] (ip, port) = utility.getipinfo(self.e1.get()) log.debug ("get ip infor-> ip: %s, port:%s" % (ip,port)) if ip == False: log.error ("Given ip infor is wrong! The right ip address: xxx.xxx.xxx.xxx or IP:port ") return self.wf_manual = Workflow(cmd, ip, self.e2.get(), self.e3.get(), port) if self.wf_manual.setup_ssh(self.wf_manual.hostip) == False: log.error ("\nssh setup error! please check ip/user/passwd and network is okay") del self.wf_manual return self.console.delete('1.0',END) self.console.insert(END, "Switch to manual mode...\n\ Please input command directly after \">>> \"\n\n") self.prompt = ">>> " self.insert_prompt() self.manual = True self.b5.config(state=DISABLED) self.b11.config(state=DISABLED) def set_confirm_yes(self): try: self.wf.set_confirm('Yes') except AttributeError: log.debug("wf doesn't existed") def set_confirm_no(self): try: self.wf.set_confirm('No') except AttributeError: log.debug("wf doesn't existed") def set_confirm_skip(self): try: self.wf.set_confirm('Skip') except AttributeError: log.debug("wf doesn't existed") def callCheckbutton(self): try: if self.cb1State.get() == 1: self.wf.set_automatic(5) else: self.wf.set_automatic(None) except AttributeError: log.debug("wf doesn't existed") self.cb1.deselect() tkMessageBox.showwarning('Message', 'please press start button first') def saveinfo(self): pass def add_command(self): item = self.e4.get() if item != '': if utility.elemet_exists(self.cmdls.get(0,END), item) == None: self.cmdls.insert(END,item) self.cmdls.see(END) log.debug ("add new command %s" % item) self.save_command() else: tkMessageBox.showwarning('Message', 'entry can not empty') def del_command(self): if self.cmdls.curselection() != (): for i in self.cmdls.curselection(): self.cmdls.delete(i) self.save_command() else: tkMessageBox.showwarning('Message', 'Please select at lease one item') def save_command(self): if utility.export_file(self.cmdls.get(0,END), self.db_file) != True: log.error ("save command pool failed") def reset_cmd_pool(self): log.debug ("start to reset command pool list") self.cmdls.delete(0,END) for element in constants.CMD_LIST_COMM: self.cmdls.insert(END, element) self.save_command() def insert_prompt(self): c = self.console.get("end-2c") if c != "\n": self.console.insert("end", "\n") self.console.insert("end", self.prompt, ("prompt",)) #self.text.insert("end", self.prompt) # this mark lets us find the end of the prompt, and thus # the beggining of the user input self.console.mark_set("end-of-prompt", "end-1c") self.console.mark_gravity("end-of-prompt", "left") def process_input(self,event): index = self.console.index("end-1c linestart") line = self.console.get(index,'end-1c') log.debug ("last line: %s" % line) if self.manual == True: self.console.insert("end", "\n") command = self.console.get("end-of-prompt", "end-1c") command = command.strip() if command != '': if command == 'bye' or command == 'exit': log.info ("quit from manual mode...") self.wf_manual.ssh.close() self.manual = False self.b5.config(state=NORMAL) self.b11.config(state=NORMAL) return elif command == 'help': log.info ("This is used for run command on target server by ssh, for example: >>> df -h, >>> svcs -xv") elif self.wf_manual.remote_cmd(command) == 1: log.error ("command %s execute failed" % command) self.insert_prompt() self.console.see("end") # this prevents the class binding from firing, since we # inserted the newline in this method return "break" else: if line == 'Yes' or line == 'y' or line == 'yes': self.set_confirm_yes() elif line == 'No' or line == 'n' or line == 'no': self.set_confirm_no() elif line == 'Skip' or line == 's' or line == 'skip': self.set_confirm_skip() else: pass
class LogFrame: def __init__(self, root, options, main_logger): self.root = root self.options = options self.main_logger = main_logger self.frame = tk.Frame(self.root) self.frame.columnconfigure(0, weight=1) # first row doesn't expoands self.frame.rowconfigure(0, weight=0) # let the second row grow self.frame.rowconfigure(1, weight=1) self.log_commands_frame = tk.LabelFrame(self.frame, text="Controls", padx=5, pady=5) self.log_commands_frame.grid(row=0, column=0, sticky=tk.NSEW, padx=4, pady=5) self.log_messages_frame = tk.Frame(self.frame) self.log_messages_frame.grid(row=1, column=0, sticky=tk.NSEW) # let the SIP trace growing self.log_messages_frame.columnconfigure(0, weight=1) self.log_messages_frame.rowconfigure(0, weight=1) self.log_messages = ScrolledText(self.log_messages_frame) self.log_messages.grid(row=0, column=0, sticky=tk.NSEW) # Log Messages frame row = 0 self.log_messages_clear_button = tk.Button(self.log_commands_frame, text="Clear", command=self.clear_log_messages) self.log_messages_clear_button.grid(row=row, column=0, sticky=tk.N) self.log_messages_pause_button = tk.Button(self.log_commands_frame, text="Pause", command=self.pause_log_messages) self.log_messages_pause_button.grid(row=row, column=1, sticky=tk.N) row = row + 1 def get_frame(self): return self.frame def clear_log_messages(self): self.log_messages.config(state='normal') self.log_messages.delete(0.0, tk.END) self.log_messages.config(state='disabled') def pause_log_messages(self): if self.log_messages_alarm is not None: self.log_messages.after_cancel(self.log_messages_alarm) self.log_messages_pause_button.configure(text="Resume", command=self.start_log_messages) self.log_messages_alarm = None def start_log_messages(self): self.update_log_messages_widget() self.log_messages_pause_button.configure(text="Pause", command=self.pause_log_messages) def update_log_messages_widget(self): self.update_widget(self.log_messages, self.log_queue) self.log_messages_alarm = self.log_messages.after(20, self.update_log_messages_widget) def update_widget(self, widget, queue): widget.config(state='normal') while not queue.empty(): line = queue.get() widget.insert(tk.END, line) widget.see(tk.END) # Scroll to the bottom widget.update_idletasks() widget.config(state='disabled')