Index: tools/policy/window.py
===================================================================
--- tools/policy/window.py	(revision e69367b7859e4b5f1c193d42c6ab38a5d30775dc)
+++ tools/policy/window.py	(revision 1d9b9cb90bad082c3ea603d14e89393474009ad4)
@@ -17,5 +17,12 @@
 
 class window(gtk.Window):
-
+    '''
+    The main GUI class.  It presents the various TreeViews and menus to
+    save/load/add, to add credentials, identities and actions and to change the
+    policy translation variable.  It keeps its current size and location in the
+    .abac_policy_tool.cfg file in the user's home.
+    '''
+
+    # Definition of the menus
     ui_def = '''
     <ui>
@@ -44,8 +51,13 @@
     </ui>
     '''
+    # Path to the configuration
     cfg_path = os.path.join(os.path.expanduser('~'), '.abac_policy_tool.cfg')
 
     @staticmethod
     def wrapit(widget):
+	'''
+	Put widget into a ScrolledWindow with automatic scrollbars on both
+	directions, and return the ScrolledWindow.
+	'''
 	sw = gtk.ScrolledWindow()
 	sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
@@ -54,4 +66,8 @@
 
     def report_error(self, message):
+	'''
+	Put a MessageDialog up with the given message.  This is a member method
+	so that it can be centered on the window.
+	'''
 	md = gtk.MessageDialog(self, gtk.DIALOG_MODAL, 
 		gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, 
@@ -61,4 +77,9 @@
 
     def __init__(self, policy):
+	'''
+	Initialize all the GTK hooks for menus, put the various TreeViews up
+	(connected to the policy) and read teh configuration for current
+	position.
+	'''
 	gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
 	self.policy = policy
@@ -69,9 +90,12 @@
 	self.pos = (0,0)
 	self.size = (500, 500)
+	# These are the TreeViews that will change when policy changes
 	self.pages = [ ]
+	# These are the TreeViews that change when policy translation changes
 	self.translated = [ ]
 
 	self.read_config()
 
+	# Hook up thr TreeViews
 	nb = gtk.Notebook()
 	p = action_principal_tree(policy)
@@ -105,4 +129,5 @@
 	self.translated.append(p)
 
+	# Make the Menus real
 	ui = gtk.UIManager()
 	ag = gtk.ActionGroup('action')
@@ -121,4 +146,6 @@
 	    ('Translation', None, 'Translate Credentials'),
 	    ))
+	# load and append call the same method with different user data -
+	# whether to clear current policy or not.
 	ag.add_actions((
 	    ('FileLoad', gtk.STOCK_OPEN, None, None, None, self.load),
@@ -137,4 +164,5 @@
 	ui.add_ui_from_string(window.ui_def)
 
+	# Put it all together and show it.
 	mb = ui.get_widget('ui/menubar')
 	vb = gtk.VBox()
@@ -146,8 +174,15 @@
     
     def quit(self, widget=None, data=None):
+	'''
+	Called from File->Quit in the menu.  Save location/size and exit
+	'''
 	self.save_config()
 	gtk.main_quit()
 
     def save(self, widget=None, data=None):
+	'''
+	Save the current state to a file.  Wrangle the FileChooserDialog to
+	pick the file and write to it.
+	'''
 	d = gtk.FileChooserDialog('Save file as', self, 
 		gtk.FILE_CHOOSER_ACTION_SAVE, (
@@ -161,8 +196,11 @@
 	d.set_do_overwrite_confirmation(True)
 	d.add_filter(fil)
+	# If the policy has been saved, start at that file.
 	if self.policy.filename is not None:
 	    d.set_filename(self.policy.filename)
+	# Display the chooser
 	rv = d.run()
 	d.hide()
+	# Write if the user wants to do it.
 	if rv == gtk.RESPONSE_OK:
 	    self.policy.write_zip(d.get_filename())
@@ -170,4 +208,8 @@
 
     def new(self, widget=None, data=None):
+	'''
+	Called when the user asks for a blank policy.  Put up a confirmation
+	and clear if confirmed.
+	'''
 	d = gtk.MessageDialog(self, gtk.DIALOG_MODAL, 
 		gtk.MESSAGE_ERROR, gtk.BUTTONS_OK_CANCEL, 
@@ -176,4 +218,5 @@
 	if rv == gtk.RESPONSE_OK:
 	    self.policy.clear()
+	    # After clearing, tell the TreeViews
 	    for p in self.pages:
 		p.recalc()
@@ -181,4 +224,9 @@
 
     def load(self, widget=None, data=None):
+	'''
+	Called to either load or append to the loaded policy.  data is the
+	clearit parameter to the load call.  Other than that, just put up a
+	requester and do the thing.
+	'''
 	d = gtk.FileChooserDialog('Load file', self, 
 		gtk.FILE_CHOOSER_ACTION_OPEN, (
@@ -198,4 +246,5 @@
 	if rv == gtk.RESPONSE_OK:
 	    self.policy.read_zip(d.get_filename(), data)
+	    # Tell the TreeViews to update.
 	    for p in self.pages:
 		p.recalc()
@@ -203,9 +252,15 @@
 
     def add_principal(self, widget=None, data=None):
+	'''
+	Called to add a principal with a user-supplied mnemonic name to the
+	current policy.  Do not allow duplicate mnemonic names.
+	'''
 	while True:
+	    # Ask for a name
 	    d = add_principal_dialog(self)
 	    rv = d.run()
 	    d.hide()
 	    if rv == gtk.RESPONSE_OK:
+		# Build the certificate
 		name = d.pname.get_text() 
 		if name not in self.policy.principal_names():
@@ -213,23 +268,36 @@
 			cid = Creddy.ID(name, 5 * 3600 * 24 * 365)
 		    except RuntimeError, e:
+			# Note this retries on failure
 			self.report_error('Cannot create principal: %s' % e)
 			continue
+		    # Identity to policy
 		    self.policy.add_identity(cid)
+		    # Update the trees
 		    for p in self.pages:
 			p.recalc()
+		    # clean up the dialog
 		    d.destroy()
 		    return
 		else:
+		    # Duplicate, retry
 		    d.destroy()
 		    self.report_error('Cannot overwrite name: %s' % name)
 	    else:
+		# Cancel leave this function
 		d.destroy()
 		return
 
     def add_cred(self, widget=None, data=None):
+	'''
+	Create a new credential and add it to the policy.  Most of the work is
+	parsing the data out of teh add credential dialog which may be
+	reporting a request for one of three kinds of credential.
+	'''
+	# Ask the user what they want
 	d = add_credential_dialog(self, self.policy)
 	rv = d.run()
 	d.hide()
 	if rv == gtk.RESPONSE_OK:
+	    # The name and issuer are always teh same
 	    iname = d.issuer.get_active_text()
 	    issuer = self.policy.issuers[self.policy.name_to_keyid(iname)]
@@ -237,4 +305,5 @@
 	    cred = None
 	    try: 
+		# Base credential
 		cred = Creddy.Attribute(issuer, role, 5 * 365 * 3600 * 24)
 	    except RuntimeError, e:
@@ -248,6 +317,8 @@
 
 	    mode = d.mechanism.get_active_text()
+	    # Principal is always in the results
 	    p = d.subject_principal.get_text()
 	    p = self.policy.name_to_keyid(p)
+	    # Collect the dependent components
 	    if p is None:
 		self.report_error("Missing or invalid subject principal")
@@ -266,5 +337,5 @@
 		    d.destroy()
 		    return
-
+	    # Build that sucker
 	    if mode == 'Direct assignment': cred.principal(p)
 	    elif mode == 'Direct delegation': cred.role(p, r)
@@ -272,4 +343,5 @@
 
 	    try:
+		# Actual creation
 		cred.bake()
 	    except:
@@ -277,5 +349,7 @@
 		d.destroy()
 		return
+	    # Add to policy
 	    self.policy.add_credential(cred)
+	    # Update the TreeViews
 	    for p in self.pages:
 		p.recalc()
@@ -283,4 +357,7 @@
 
     def mark_action(self, widget=None, data=None):
+	'''
+	Mark an action. Collect the user's request and propagate it.
+	'''
 	d = mark_action_dialog(self, self.policy)
 	rv = d.run()
@@ -290,4 +367,5 @@
 	    if action is not None:
 		self.policy.add_action(action)
+	    # Tell the TreeViews
 	    for p in self.pages:
 		p.recalc()
@@ -296,12 +374,26 @@
 
     def shown(self, w):
+	'''
+	Handles an event where the window appears.  Move to the saved position
+	and size.
+	'''
 	self.move(*self.pos)
 	self.resize(*self.size)
 
     def changed(self, w, e):
+	'''
+	Handles an event where the window changes (resizes or moves).  Remember
+	the size and position.
+	'''
 	self.pos = self.get_position()
 	self.size = self.get_size()
 
     def translation_change(self, ra, c, user=None):
+	'''
+	Called from any of the menu items that request a translation change.
+	They're radio buttons, so each one unsets the last.  Translate the
+	radio value into the right policy string, set the translation value and
+	update the TreeViews that depend on translation.
+	'''
 	cv = c.get_current_value()
 	if cv == 0: self.policy.translate = 'sets'
@@ -315,4 +407,8 @@
 
     def get_intpair(self, sect, opt):
+	'''
+	Utility to pull a pair of integers from a configuration file.  The size
+	and position are thsi kind of data, so this is used a couple places.
+	'''
 	if not self.cfg.has_section(sect):
 	    self.cfg.add_section(sect)
@@ -327,4 +423,7 @@
 
     def read_config(self):
+	'''
+	Get the saved size and position from the config file, if any
+	'''
 	self.cfg = ConfigParser.SafeConfigParser()
 	self.cfg.read(window.cfg_path)
@@ -335,4 +434,7 @@
 
     def save_config(self):
+	'''
+	Save the current postion to the default config file.
+	'''
 	self.cfg.set('geom', 'pos', '%d,%d' % self.pos)
 	self.cfg.set('geom', 'size', '%d,%d' % self.size)
