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 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 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