modified: ri_oper.py
modified: ri_tk.py
modified: ri_tk_cmd.py
modified: ri_widget.py
add network check ip and hostname update
363 lines
12 KiB
Python
363 lines
12 KiB
Python
#!/usr/bin/python
|
|
''' handle display related work upon Tkinter '''
|
|
|
|
import Tkinter
|
|
import tkMessageBox
|
|
import sys
|
|
import ri_cmd
|
|
import ri_widget
|
|
import os.path
|
|
|
|
var_dict={}
|
|
# language should be all lower case letters
|
|
language='english'
|
|
|
|
def init(base_w):
|
|
''' base_w - base widget instance '''
|
|
global root_window
|
|
root_window = Tkinter.Tk()
|
|
|
|
# grid management for root_window
|
|
root_window.columnconfigure(0, weight=1)
|
|
root_window.rowconfigure(0, weight=1)
|
|
|
|
root_window.geometry("%sx%s+0+0" %(root_window.winfo_screenwidth(),root_window.winfo_screenheight()))
|
|
root_window.title('Linx')
|
|
|
|
# bind WM_DELETE_WINDOW
|
|
root_window.protocol("WM_DELETE_WINDOW", root_window.quit)
|
|
global base_widget
|
|
base_widget = create_widget_sub(base_w, root_window)
|
|
|
|
def quit():
|
|
''' exit root window '''
|
|
root_window.quit()
|
|
|
|
def set_step_info(s):
|
|
''' set some information in base widget '''
|
|
# set step name which will be shown on base widget column 1 row 0
|
|
title = translate_text(s)
|
|
var_dict['main.step_name'].set(title)
|
|
|
|
def set_help_info(s):
|
|
''' set help information in base widget'''
|
|
help = translate_text(s)
|
|
w = ri_widget.Widget.dict['main.help'].tk_widget
|
|
w.configure(state='normal')
|
|
w.delete(1.0,Tkinter.END)
|
|
w.insert(1.0,help)
|
|
w.configure(state='disable')
|
|
|
|
def create_widget(w):
|
|
''' w - widget instance '''
|
|
|
|
create_widget_sub(w, base_widget)
|
|
|
|
# set step name
|
|
if 'name' in dir(w):
|
|
set_step_info(w.name)
|
|
set_help_info('#'+w.name+'.help')
|
|
|
|
class MyImage:
|
|
''' MyImage - a dummy class to hold Image variable '''
|
|
count = 0
|
|
|
|
def translate_text(txt):
|
|
''' multi-language support, translate t if needed '''
|
|
key = txt.lower()
|
|
if key in ri_widget.Text.dict.keys() and (txt[0] == '#' or language != 'english'):
|
|
return getattr(ri_widget.Text.dict[key], language)
|
|
else:
|
|
return txt
|
|
|
|
def modify_attributes(attr_dict):
|
|
''' modify values in attr_dict to suit Tk usage '''
|
|
for a in attr_dict.keys():
|
|
if a == 'image':
|
|
# I think there is a bug in Tkinter on Image processing
|
|
# I have to bypass it in the following way:
|
|
image_var = 'a' + str(MyImage.count)
|
|
drt = os.path.join(os.path.dirname(__file__), '../data')
|
|
setattr(MyImage, image_var, Tkinter.PhotoImage(file=os.path.join(drt, attr_dict[a])))
|
|
MyImage.count += 1
|
|
attr_dict[a] = getattr(MyImage, image_var)
|
|
elif a == 'command':
|
|
attr_dict[a] = getattr(sys.modules["ri_cmd"], attr_dict[a])
|
|
elif a == "textvariable" or a == "listvariable" or a == 'variable':
|
|
attr_dict[a] = var_dict[attr_dict[a]]
|
|
elif a == "text":
|
|
attr_dict[a] = translate_text(attr_dict[a])
|
|
|
|
def create_widget_sub(w, p_win):
|
|
'''
|
|
w - widget instance
|
|
p_win - Tk parent window '''
|
|
|
|
# name type and value
|
|
for v_n, v_t, v_v in w.variables:
|
|
if not v_n in var_dict.keys():
|
|
# if not yet in dict, create it
|
|
var_dict[v_n] = getattr(Tkinter, v_t)(value=v_v)
|
|
|
|
# change attr, if needed to suit tk
|
|
tk_attr = dict(w.attr)
|
|
modify_attributes(tk_attr)
|
|
|
|
tk_func = getattr(Tkinter, w.tp)
|
|
w_win = tk_func(p_win, tk_attr)
|
|
|
|
# save tk widget instance into w (widget instance)
|
|
setattr(w, 'tk_widget', w_win)
|
|
|
|
# display sub widgets
|
|
for sub_w in w.widgets:
|
|
create_widget_sub(sub_w, w_win)
|
|
|
|
# process action init
|
|
if 'action' in dir(w) and 'init' in w.action.dict:
|
|
getattr(sys.modules['ri_cmd'], w.action.dict['init'])()
|
|
|
|
# handle scroll bar for sub_widgets
|
|
if 'action' in dir(w):
|
|
# ing for scrolling, ed for scrolled
|
|
for ing, ed in w.action.scrolls:
|
|
ing_win = w.dict[ing].tk_widget
|
|
ed_win = w.dict[ed].tk_widget
|
|
if ing_win['orient'] == 'vertical':
|
|
ed_cmd_name = 'yscrollcommand'
|
|
ing_cmd = getattr(ed_win, 'yview')
|
|
else:
|
|
ed_cmd_name = 'xscrollcommand'
|
|
ing_cmd = getattr(ed_win, 'xview')
|
|
|
|
ing_win.configure(command=ing_cmd)
|
|
ed_win[ed_cmd_name]=ing_win.set
|
|
|
|
# grid management
|
|
if 'grid_management' in dir(w):
|
|
for cf in w.grid_management.cf_list:
|
|
cf_func = getattr(w_win, cf[0])
|
|
cf_func( cf[1], weight=cf[2])
|
|
|
|
# grid location
|
|
if 'grid_location' in dir(w):
|
|
w_win.grid(w.grid_location.dict)
|
|
|
|
# handle bindings
|
|
for bd in w.bindings:
|
|
w_win.bind(bd[0], getattr(ri_cmd, bd[1]))
|
|
|
|
|
|
return w_win
|
|
|
|
# When creating widget, I have to create each sub widget.
|
|
# while destroying a widget, only destroy one. Tk functions will
|
|
# destroy all descendant.
|
|
# so init is a little different from quit.
|
|
def process_action_quit(w):
|
|
''' process action quit '''
|
|
if 'action' in dir(w) and 'quit' in w.action.dict:
|
|
getattr(sys.modules['ri_cmd'], w.action.dict['quit'])()
|
|
|
|
if 'widgets' in dir(w):
|
|
for sub_w in w.widgets:
|
|
process_action_quit(sub_w)
|
|
|
|
def destroy_widget(w):
|
|
''' w - Widget instance '''
|
|
process_action_quit(w)
|
|
w.tk_widget.destroy()
|
|
|
|
def create_message_box(w):
|
|
''' display MessageBox
|
|
w - MessageBox instance'''
|
|
disp = getattr(tkMessageBox, w.tp)
|
|
code = disp(translate_text(w.title), translate_text(w.message))
|
|
return code
|
|
|
|
def create_top_window(w):
|
|
''' display TopWindow
|
|
w - TopWindow instance '''
|
|
tk_attr = dict(w.attr)
|
|
modify_attributes(tk_attr)
|
|
|
|
w_win = Tkinter.Toplevel(root_window, tk_attr)
|
|
|
|
for sub_w in w.widgets:
|
|
create_widget_sub(sub_w, w_win)
|
|
|
|
if 'grid_management' in dir(w):
|
|
for cf in w.grid_management.cf_list:
|
|
cf_func = getattr(w_win, cf[0])
|
|
cf_func(cf[1], weight=cf[2])
|
|
|
|
# save tk widget instance into w (TopWindow instance)
|
|
setattr(w, 'tk_widget', w_win)
|
|
|
|
# 'bind' it to root window
|
|
w_win.transient(root_window)
|
|
# grab all events into it
|
|
while True:
|
|
try:
|
|
w_win.grab_set()
|
|
except Tkinter.TclError:
|
|
pass
|
|
else:
|
|
break
|
|
|
|
w_win.wait_window()
|
|
|
|
return w_win
|
|
|
|
def destroy_top_window(w):
|
|
''' w - Toplevel instance '''
|
|
w.tk_widget.destroy()
|
|
|
|
class SoftwarePackageWindow():
|
|
''' Toplevel window for a group of software packages
|
|
class member
|
|
---------------------------
|
|
dict - class static member
|
|
|
|
instance member
|
|
---------------------------
|
|
group - data layer group instance
|
|
win - Tk widget
|
|
selection - StringVar variable for 'select_all'
|
|
opt_vars - a list to hold variables containing status for optional packages
|
|
opt_chks - a list to hold Checkbuttons for optional packages
|
|
'''
|
|
dict = {}
|
|
def __init__(self, g):
|
|
self.group = g
|
|
self.opt_vars = []
|
|
self.opt_chks = []
|
|
SoftwarePackageWindow.dict[g.name] = self
|
|
|
|
def select_all(self):
|
|
''' callback function for check button select_all '''
|
|
if self.selection.get() == 'all':
|
|
for ck in self.opt_chks:
|
|
ck.configure(state='disable')
|
|
else:
|
|
for ck in self.opt_chks:
|
|
ck.configure(state='normal')
|
|
|
|
|
|
def ok(self):
|
|
''' callback function for button OK '''
|
|
self.group.selection = self.selection.get()
|
|
for i in range(len(self.group.optional)):
|
|
# install field, yes or no
|
|
self.group.optional[i][1] = self.opt_vars[i].get()
|
|
# clear variables and check buttons
|
|
self.opt_vars = []
|
|
self.opt_chks = []
|
|
self.win.destroy()
|
|
|
|
def cancel(self):
|
|
''' callback function for button cancel '''
|
|
# clear variables and check buttons
|
|
self.opt_vars = []
|
|
self.opt_chks = []
|
|
self.win.destroy()
|
|
|
|
def show(self):
|
|
win = Tkinter.Toplevel(root_window)
|
|
self.win = win
|
|
win.geometry("%sx%s+%s+%s" %(int(root_window.winfo_screenwidth()*0.8),\
|
|
int(root_window.winfo_screenheight()*0.8),\
|
|
int(root_window.winfo_screenwidth()*0.1),\
|
|
int(root_window.winfo_screenheight()*0.1)))
|
|
win.columnconfigure(0, weight=1)
|
|
win.rowconfigure(1, weight=1)
|
|
win.rowconfigure(4, weight=1)
|
|
|
|
text_mdt = translate_text('Mandatory')
|
|
Tkinter.Label(win, text=text_mdt).grid(column=0, row=0)
|
|
cnv1 = Tkinter.Canvas(win)
|
|
hs1 = Tkinter.Scrollbar(win, orient='horizontal')
|
|
hs1.configure(command=cnv1.xview)
|
|
vs1 = Tkinter.Scrollbar(win, orient='vertical')
|
|
vs1.configure(command=cnv1.yview)
|
|
cnv1.grid(column=0, row=1, sticky='NWES')
|
|
vs1.grid(column=1, row=1, sticky='NSW')
|
|
hs1.grid(column=0, row=2, sticky='NWE')
|
|
cnv1.configure(yscrollcommand=vs1.set, xscrollcommand=hs1.set)
|
|
fr1 = Tkinter.Frame(cnv1)
|
|
cnv1.create_window((0,0), window=fr1, anchor='nw')
|
|
#column set to 5
|
|
fr1.columnconfigure(0, weight=1)
|
|
fr1.columnconfigure(1, weight=1)
|
|
fr1.columnconfigure(2, weight=1)
|
|
fr1.columnconfigure(3, weight=1)
|
|
fr1.columnconfigure(4, weight=1)
|
|
|
|
for i in range(len(self.group.mandatory)):
|
|
Tkinter.Label(fr1, text=self.group.mandatory[i]).grid(column=i%5, row=i/5, sticky='NWES')
|
|
|
|
text_opt = translate_text('Optional')
|
|
Tkinter.Label(win, text=text_opt).grid(column=0, row=3)
|
|
self.selection = Tkinter.StringVar(value=self.group.selection)
|
|
text_sal = translate_text('Select all')
|
|
chk_sa = Tkinter.Checkbutton(win, text=text_sal, command=self.select_all, variable=self.selection, onvalue='all', offvalue='manual')
|
|
chk_sa.grid(column=1, row=3)
|
|
if self.group.selection == 'all':
|
|
chk_sa.select()
|
|
else:
|
|
chk_sa.deselect()
|
|
|
|
cnv2 = Tkinter.Canvas(win)
|
|
hs2 = Tkinter.Scrollbar(win, orient='horizontal')
|
|
hs2.configure(command=cnv2.xview)
|
|
vs2 = Tkinter.Scrollbar(win, orient='vertical')
|
|
vs2.configure(command=cnv2.yview)
|
|
cnv2.grid(column=0, row=4, sticky='NWES')
|
|
vs2.grid(column=1, row=4, sticky='NSW')
|
|
hs2.grid(column=0, row=5, sticky='NWE')
|
|
cnv2.configure(yscrollcommand=vs2.set, xscrollcommand=hs2.set)
|
|
fr2 = Tkinter.Frame(cnv2)
|
|
cnv2.create_window((0,0), window=fr2, anchor='nw')
|
|
#column set to 5
|
|
fr2.columnconfigure(0, weight=1)
|
|
fr2.columnconfigure(1, weight=1)
|
|
fr2.columnconfigure(2, weight=1)
|
|
fr2.columnconfigure(3, weight=1)
|
|
fr2.columnconfigure(4, weight=1)
|
|
|
|
for i in range(len(self.group.optional)):
|
|
name, y_n = self.group.optional[i]
|
|
v = Tkinter.StringVar(value='no')
|
|
self.opt_vars.append(v)
|
|
chk = Tkinter.Checkbutton(fr2, text=name, onvalue='yes', offvalue='no', variable=self.opt_vars[i])
|
|
self.opt_chks.append(chk)
|
|
chk.grid(column=i%5, row=i/5, sticky='NWS')
|
|
if y_n == 'yes':
|
|
chk.select()
|
|
else:
|
|
chk.deselect()
|
|
|
|
if self.group.selection == 'all':
|
|
chk.configure(state='disable')
|
|
|
|
Tkinter.Button(win, text='OK', command=self.ok).grid(column=0, row=6, pady=2)
|
|
Tkinter.Button(win, text='Cancel', command=self.cancel).grid(column=1, row=6, pady=2)
|
|
|
|
# bind WM_DELETE_WINDOW
|
|
win.protocol("WM_DELETE_WINDOW", self.cancel)
|
|
|
|
win.after_idle(lambda : cnv1.configure(scrollregion=(0,0, fr1.winfo_width(), fr1.winfo_height())))
|
|
win.after_idle(lambda : cnv2.configure(scrollregion=(0,0, fr2.winfo_width(), fr2.winfo_height())))
|
|
|
|
win.transient(root_window)
|
|
# grab all events into it
|
|
while True:
|
|
try:
|
|
win.grab_set()
|
|
except Tkinter.TclError:
|
|
pass
|
|
else:
|
|
break
|
|
|
|
win.wait_window()
|