diff --git a/python/ri_data.py b/python/ri_data.py
index afb7b3c..1bbad89 100644
--- a/python/ri_data.py
+++ b/python/ri_data.py
@@ -462,7 +462,7 @@ p - pkg, that includes this service
pass
for s in Service.list:
- if s.pkg in l:
+ if s.package in l:
if s.start == 'disable':
s.start = 'no'
else:
diff --git a/python/ri_dep.py b/python/ri_dep.py
new file mode 100644
index 0000000..b657cda
--- /dev/null
+++ b/python/ri_dep.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+import ri_data
+
+from xml.dom import minidom
+import os.path
+
+dep_xml = os.path.join(os.path.dirname(__file__), '../xml/dependency.xml')
+
+class Depending:
+ ''' Class recording depending relation '''
+ dict={}
+ def __init__(self, n):
+ self.name = n
+ self.depending = set()
+ # flag for resolve recursive
+ self.resolved = False
+ Depending.dict[n] = self
+
+ def resolve_recursive(self):
+ if self.resolved: return
+ for d in self.depending:
+ Depending.dict[d].resolve_recursive()
+ tmp=set(self.depending)
+ for d in self.depending:
+ tmp.update(Depending.dict[d].depending)
+ self.depending = tmp
+ self.resolved = True
+
+class Depended:
+ ''' Class recording depended by relation '''
+ dict={}
+ def __init__(self, n):
+ self.name = n
+ self.depended_by = set()
+ Depended.dict[n] = self
+
+def construct_depending():
+ xml_doc = minidom.parse(dep_xml)
+ xml_root = xml_doc.firstChild
+ xml_dict = {}
+ for n in xml_root.childNodes:
+ if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'package':
+ xml_dict[n.attributes['name'].value] = n
+ Depending(n.attributes['name'].value)
+
+ for d in Depending.dict.values():
+ n = xml_dict[d.name]
+ for r in n.getElementsByTagName('runtime'):
+ for dep in r.getElementsByTagName('depending'):
+ d.depending.add(dep.attributes['package'].value)
+
+def resolve_recursive_depending():
+ for d in Depending.dict.values():
+ d.resolve_recursive()
+
+def construct_depended():
+ for d in Depending.dict.values():
+ for dep in d.depending:
+ if not Depended.dict.has_key(dep):
+ Depended(dep)
+ Depended.dict[dep].depended_by.add(d.name)
+
+def get_extra_depending():
+ l = []
+ for g in ri_data.Group.dict.values():
+ if g.install != 'no':
+ l.extend([ p for p in g.mandatory ])
+ l.extend([ p[0] for p in g.optional if p[1] == 'yes' ])
+
+ set1 = set(l)
+ set2 = set(set1)
+
+ for d in set1:
+ set2.update(Depending.dict[d].depending)
+
+ res = {}
+ for d in set2.difference(set1):
+ res[d] = Depended.dict[d].depended_by.intersection(set1)
+
+ return res
+
diff --git a/python/ri_tk.py b/python/ri_tk.py
index a47e5c6..d0d2f30 100644
--- a/python/ri_tk.py
+++ b/python/ri_tk.py
@@ -210,6 +210,9 @@ class SoftwarePackageWindow():
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):
@@ -218,10 +221,16 @@ class SoftwarePackageWindow():
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):
diff --git a/python/ri_tk_cmd.py b/python/ri_tk_cmd.py
new file mode 100644
index 0000000..709f371
--- /dev/null
+++ b/python/ri_tk_cmd.py
@@ -0,0 +1,228 @@
+#!/usr/bin/python
+''' handle gui commands '''
+import ri_tk as display
+import ri_widget
+import ri_data
+import ri_dep
+
+import re
+import copy
+import sys
+
+def serial_no_init():
+ display.var_dict['serial_no.number'].set(value=ri_data.SerialNumber.value)
+
+def serial_no_quit():
+ ri_data.SerialNumber.value = display.var_dict['serial_no.number'].get()
+
+def mount_list_init():
+ ''' initialize mount list '''
+ l = []
+ for m in ri_data.MountPoint.list:
+ # get size from Partition info
+ sz = ri_data.Partition.get_size(m.device)
+ if not sz:
+ sz = ri_data.Raid.get_size(m.device)
+ print m.device, m.directory, m.filesystem, m.format, sz
+ s = m.device.ljust(10) + m.directory.ljust(10) + m.filesystem.ljust(10) + m.format.ljust(4) + sz.ljust(6)
+ l.append(s)
+ display.var_dict['mount.list'].set(value=tuple([str(i) for i in l]))
+
+def mount_list_modify(*args):
+ ''' modify an item in mount list '''
+ tw = ri_widget.TopWindow.dict['mount_list_modify']
+ tw.show()
+
+def mp_top_init():
+ ''' mount dir top window initialize '''
+ ml_win = ri_widget.Widget.dict['mount.list'].tk_widget
+ idxs = ml_win.curselection()
+ if len(idxs) == 1:
+ idx = int(idxs[0])
+ mp = ri_data.MountPoint.list[idx]
+ dev = mp.device
+ dir = mp.directory
+ fs = mp.filesystem
+ fm = mp.format
+ sz = mp.size
+ display.var_dict['mp_top_dev'].set(value=dev)
+ display.var_dict['mp_top_size'].set(value=sz)
+ display.var_dict['mp_top_dir'].set(value=dir)
+ if fm == 'yes':
+ ri_widget.Widget.dict['mp_top_format'].tk_widget.select()
+ else:
+ ri_widget.Widget.dict['mp_top_not_format'].tk_widget.select()
+
+ fs_values = eval(display.var_dict['mp_top_fs'].get())
+ for i in range(len(fs_values)):
+ if fs == fs_values[i]:
+ ri_widget.Widget.dict['mp_top_fs'].tk_widget.selection_set(i)
+
+def mp_top_ok():
+ ''' mount dir top window OK '''
+ l = []
+ for itm in eval(display.var_dict['mount.list'].get()):
+ dev = itm.split()[0]
+ dev2 = display.var_dict['mp_top_dev'].get()
+ if dev == dev2:
+ sz = display.var_dict['mp_top_size'].get()
+ dir = display.var_dict['mp_top_dir'].get()
+ fm = display.var_dict['mp_top_format'].get()
+ idxs2 = ri_widget.Widget.dict['mp_top_fs'].tk_widget.curselection()
+ if len(idxs2):
+ idx2 = int(idxs2[0])
+ fs = eval(display.var_dict['mp_top_fs'].get())[idx2]
+ else:
+ fs = ''
+
+ s2 = dev.ljust(10) + dir.ljust(10) + fs.ljust(10) + fm.ljust(4) + sz.ljust(6)
+ l.append(s2)
+ # make change in internal data structure
+ ri_data.MountPoint.change(dev2, dir, fs, fm)
+ else:
+ l.append(itm)
+
+ display.var_dict['mount.list'].set(value=tuple(l))
+ ri_widget.TopWindow.dict['mount_list_modify'].hide()
+
+def mp_top_cancel():
+ ''' mount dir top window cancel '''
+ ri_widget.TopWindow.dict['mount_list_modify'].hide()
+ pass
+
+def network_init():
+ ''' network initialize '''
+ display.var_dict['network_host_name']. set(value=ri_data.Network.hostname)
+ ri_widget.Widget.dict['network_config_%s' %(ri_data.Network.configuration and ri_data.Network.configuration or 'static')].tk_widget.invoke()
+ display.var_dict['network_domain_name']. set(value=ri_data.Network.domain)
+ display.var_dict['network_ip']. set(value=ri_data.Network.ip)
+ display.var_dict['network_subnet_mask']. set(value=ri_data.Network.mask)
+ display.var_dict['network_gateway']. set(value=ri_data.Network.gateway)
+ display.var_dict['network_primary_dns']. set(value=ri_data.Network.primary_dns)
+ display.var_dict['network_secondary_dns'].set(value=ri_data.Network.secondary_dns)
+
+def network_quit():
+ ''' network quit '''
+ ri_data.Network.hostname = display.var_dict['network_host_name'].get()
+ ri_data.Network.configuration = display.var_dict['network_config_method'].get()
+ ri_data.Network.domain = display.var_dict['network_domain_name'].get()
+ ri_data.Network.ip = display.var_dict['network_ip'].get()
+ ri_data.Network.mask = display.var_dict['network_subnet_mask'].get()
+ ri_data.Network.gateway = display.var_dict['network_gateway'].get()
+ ri_data.Network.primary_dns = display.var_dict['network_primary_dns'].get()
+ ri_data.Network.secondary_dns = display.var_dict['network_secondary_dns'].get()
+
+def ncm_dynamic():
+ ''' when radio button ncm dynamic is checked, several data entry will be set 'disable' '''
+
+ for n in ('network_domain_name','network_ip','network_subnet_mask','network_gateway','network_primary_dns','network_secondary_dns'):
+ ri_widget.Widget.dict[n].tk_widget.configure(state='disable')
+
+def ncm_static():
+ ''' when radio button ncm static is checked, several data entry will be set 'normal' '''
+ for n in ('network_domain_name','network_ip','network_subnet_mask','network_gateway','network_primary_dns','network_secondary_dns'):
+ ri_widget.Widget.dict[n].tk_widget.configure(state='normal')
+
+class GroupButton(object):
+ ''' A function class called whenever the group button is clicked '''
+ dict={}
+ def __init__(self, g):
+ self.name = g.name
+ GroupButton.dict[g.name] = self
+ display.SoftwarePackageWindow(g)
+
+ def __call__(self):
+ print self.name
+ display.SoftwarePackageWindow.dict[self.name].show()
+
+class GroupCheck(GroupButton):
+ ''' A function class called whenever the group check button is checked '''
+ def __init__(self, g, v):
+ self.variable = v
+ GroupButton.__init__(self, g)
+
+ def __call__(self):
+ v = display.var_dict[self.variable]
+ if v.get() == 'yes':
+ display.SoftwarePackageWindow.dict[self.name].show()
+
+def software_group_mandatory_construct(w):
+ ''' construct widgets based actual data
+w - Widget instance '''
+ mdt = [ m for m in ri_data.Group.dict.values() if m.install == 'mandatory' ]
+ wit = w.widgets.pop()
+ for i in mdt:
+ wi = copy.deepcopy(wit)
+ wi.attr['text'] = i.name
+ vn = "software_group_%s" %(i.name)
+ idx = mdt.index(i)
+ wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
+ wi.grid_location.dict['row'] = idx / int(w.grid_management.columns)
+ gc = GroupButton(i)
+ setattr(sys.modules['ri_cmd'], vn, gc)
+ wi.attr['command'] = vn
+ w.add_sub_widget(wi)
+
+def software_group_optional_construct(w):
+ ''' construct widgets based actual data
+w - Widget instance '''
+ opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ]
+ wit = w.widgets.pop()
+ for i in opt:
+ wi = copy.deepcopy(wit)
+ wi.attr['text'] = i.name
+ vn = "software_group_%s" %(i.name)
+ idx = opt.index(i)
+ wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
+ wi.grid_location.dict['row'] = idx / int(w.grid_management.columns)
+ gc = GroupCheck(i, vn)
+ setattr(sys.modules['ri_cmd'], vn, gc)
+ wi.attr['command'] = vn
+ wi.attr['variable'] = vn
+ wi.variables = [(vn, 'StringVar', i.install),]
+ w.add_sub_widget(wi)
+
+def software_group_optional_quit():
+ ''' software group window quit, record optional group state '''
+ opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ]
+ for i in opt:
+ print i.name
+ vn = "software_group_%s" %(i.name)
+ i.install = display.var_dict[vn].get()
+ print i.name, i.install
+
+def dependency_list_init():
+ ''' init function for list in dependency step '''
+ ri_dep.construct_depending()
+ ri_dep.resolve_recursive_depending()
+ ri_dep.construct_depended()
+ dep_dict = ri_dep.get_extra_depending()
+ l = [ k.ljust(15) + ': ' + ' '.join(dep_dict[k]) for k in dep_dict.keys()]
+ display.var_dict['dependency.list'].set(value=tuple(l))
+
+def service_construct(w):
+ ''' construct service widget based on actual data
+w - Widget instance '''
+
+ # first refresh service state
+ ri_data.Service.change_state()
+ wit = w.widgets.pop()
+ for i in ri_data.Service.list:
+ wi = copy.deepcopy(wit)
+ wi.attr['text'] = i.name
+ vn = "service_%s" %(i.name)
+ wi.attr['variable'] = vn
+ wi.variables = [(vn, 'StringVar', i.start=='yes' and 'yes' or 'no')]
+ if i.start == 'disable':
+ wi.attr['state'] = 'disable'
+ idx = ri_data.Service.list.index(i)
+ wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
+ wi.grid_location.dict['row'] = idx / int(w.grid_management.columns)
+ w.add_sub_widget(wi)
+
+def service_quit():
+ ''' record service state '''
+ for i in ri_data.Service.list:
+ if i.start != 'disable':
+ vn = "service_%s" %(i.name)
+ i.start = display.var_dict[vn].get()
diff --git a/xml/install.xml b/xml/install.xml
index 1f0bdca..6d3f0b3 100644
--- a/xml/install.xml
+++ b/xml/install.xml
@@ -23,7 +23,7 @@
-
+
@@ -85,7 +85,7 @@
-
+
办公类包括 OpenOffice.org 等办公软件。
办公类都是必选软件包,当选择安装该类后,必选包是默认安装的。
@@ -94,7 +94,7 @@
-
+
KDE是一种著名的自由图形工作环境,整个系统采用Qt程序库
KDE桌面类都是可选软件包,可以自由选择安装。
@@ -240,8 +240,8 @@
-
-
+
+
@@ -461,7 +461,7 @@
-
+
diff --git a/xml/interface_t.xml b/xml/interface_t.xml
index eca19d7..5ddc20b 100644
--- a/xml/interface_t.xml
+++ b/xml/interface_t.xml
@@ -456,6 +456,70 @@ row 4 | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -615,5 +679,7 @@ row 4 | |
+
+