Commits

Anonymous committed da08fb9

Completed adjusting the exiting tui code to match the new backend API. Fixes #7

Comments (0)

Files changed (10)

modules/support/vectorlinux/DATESET.py

         """ Return a string representing the current timezone """
         # To get the value, we must read /etc/localtime-copied-from.
         # If this excepts, then no timezone is set.
-        tz = os.readlink(self.tzlink)
-        return tz.replace('/usr/share/zoneinfo/', "")
+        if os.path.exists(self.tzlink):
+            tz = os.readlink(self.tzlink)
+            return tz.replace('/usr/share/zoneinfo/', '')
+        return 'US/Central'
+
 
     def _remove_tz_link(self):
         """ remove the symlink that sets the timezone """
-        return os.remove(self.tzlink)
+        if os.path.exists(self.tzlink):
+            return os.remove(self.tzlink)
 
     def _check_faulty_rtcports(self):
         """ Check /proc/ioports for unknown rtc ports """

modules/support/vectorlinux/FSTAB.py

     """ return a list of all partition paths"""
     partitions = []
     for dev in parted.getAllDevices():
-        if "-ROM" in dev.model:
-            continue
-        if dev.type == 1:
-            dsk = parted.Disk(dev)
-            for part in dsk.partitions:
-                # extended partitions are type 2 and have no fs
-                if part.type == 2:
-                    continue
-                partitions.append(part.path)
+        if not dev.readOnly:
+           dsk = parted.Disk(dev)
+           for part in dsk.partitions:
+               # extended partitions are type 2 and have no fs
+               if part.type != 2:
+                   partitions.append(part.path)
     return partitions
 
 def list_all_system_drives():
     """ Return a list of all device drive paths """
-    drives = []
-    for dev in parted.getAllDevices():
-        if dev.type == 1 and dev.getSize() > 0.0:
-            drives.append(dev.path)
-    return drives    
+    drives = [dev.path for dev in parted.getAllDevices() if not dev.readOnly and dev.getSize() > 0.0]
+    return drives
 
 class FstabEntry(object):
     """ Object representing an entry in /etc/fstab """

modules/support/vectorlinux/GDMHELPER.py

 
 class SettingsModel(object):
     """ Model to work with the gdm settings """
-    def __init__(self):
-        self.settingspath = "/etc/gdm/custom.conf"
-        self._tmpfile = "/tmp/gdmsettings"
+    def __init__(self, tmpfile = '/tmp/gdmsettings', settingspath = '/etc/gdm/custom.conf'):
+        self.settingspath = settingspath
+        self._tmpfile = tmpfile
         self.config = gdmconfigparser.ConfigHandler()
         self.config.read(self.settingspath)
 
     
     def _save_to_file(self):
         """ Write the changes to the file """
-        f = open(self._tmpfile, 'w')
-        self.config.write(f)
-        f.close()
-        f = open(self._tmpfile, 'r')
+        # start by saving the options on the tempfile first. This is because
+        # Our helper module ignores all comments on the file, and we want to keep those
+        # in there. They're really helpful.
+        f = open(self.settingspath, 'r')
         data = f.readlines()
         f.close()
-        exdata = []
-        f = open(self.settingspath, 'r')
-        exdata = f.readlines()
+        for key in ('AutomaticLoginEnable', 'AutomaticLogin'):
+            i = 0
+            for line in data:
+                if self._line_sets_setting(line, key):
+                    value = self.config.get('daemon', key)
+                    nline = "%s=%s\n"% (key, value)
+                    data[i] = nline
+                i += 1
+        f = open(self.settingspath, 'w')
+        f.writelines(''.join(data))
         f.close()
-        newdata = []
-        for line in exdata:
-            for _line in data:
-                if line.startswith(_line):
-                    line = _line
-            newdata.append(line.strip())
-        # remove the temp file
-        os.remove(self._tmpfile)
-        try:
-            f = open(self.settingspath, 'w')
-            f.write('\n'.join(newdata))
-            f.close()
-            log.debug("%s has been modified."% self.settingspath)
-        except:
-            msg = ("Unable to save changes to %s"% self.settingspath, " ",
-                "Check file contents and permissions.")
-            log.fatal(" ".join(msg))
-            return 1
-        return 0
+        return
+
+    def _line_sets_setting(self, line, setting):
+        """ Returns True if line sets setting"""
+        if "=" not in line:
+            return False
+        key, value = line.split('=')
+        return key.lower().strip() == setting.lower().strip()
     
-    def save_settings(self, alsetting='false', aluser=None):
+    def save_settings(self, alsetting='false', aluser=''):
         """ save the settings to the configuration (not yet written to file) """
-        if alsetting == 'false':
-            if self.config.has_option('daemon', 'AutomaticLoginEnable'):
-                self.config.remove_option('daemon', 'AutomaticLoginEnable')
-        else:
-            self.config.set('daemon', 'AutomaticLoginEnable', alsetting)
-        if aluser is None:
-            user = ''
-        else:
-            user = str(aluser).lower()
-        if aluser is not None:
-            self.config.set('daemon', 'AutomaticLogin',user)
-         # write the file
+        self.config.set('daemon', 'AutomaticLoginEnable', alsetting)
+        self.config.set('daemon', 'AutomaticLogin', aluser)
+        f = open(self._tmpfile, 'w')
+        f.writelines([alsetting,'\n', aluser])
+        f.close()
         return self._save_to_file()
+
          
-        
+        

modules/support/vectorlinux/USERADMIN.py

         return self.notify()
 
     def deleteUser(self, uname):
-        """ remove a user account """
+        """ remove a user account.
+        Arguments: uname = login name for the account to be deleted."""
         assert self.hasUser(uname), "User account does not exist"
         
         cmd = ["/usr/sbin/userdel", "-r", uname]

modules/tui/tui_autologin.py

     sys.path.append(os.getcwd())
 from modules.support.vectorlinux import LOGINMANAGERS
 from modules.support.vectorlinux import USERADMIN
-#from modules.support.vectorlinux import gdmconfigparser
 from modules.support.vectorlinux import GDMHELPER
 from modules.tuisupport import dialogs
 from modules.tuisupport import widgets
         self.set_body(urwid.LineBox(self.get_body()))
         self._autologin_enabled = self._current_state
         self._autologin_user = self._current_aluser or 'root'
+
+        # move the focus to the body of the module
+        self.set_focus('body')
     
     def save_settings(self, caller_widget=None):
         """ Make the call to save the settings """
                     buttons = [("OK", self.close_module)]
                 )
                 return self.pop_dialog(dia)
-        ret = self.settingsmodel.save_settings(
-            str(self._autologin_enabled),
-            str(self._autologin_user)
-        )
-        if ret > 0:
+
+        try:
+            self.settingsmodel.save_settings(
+                str(self._autologin_enabled),
+                str(self._autologin_user)
+                )
+        except IOError as e:
             dia = dialogs.Error(
                 parent = self.parent,
-                message = _("There was an error saving changes to gdm.") + "\n" + \
-                _("Make sure you are logged in as root and that /etc/gdm/custom.conf is ok."),
-                buttons = [("OK", self.return_to_module)]
-            )
-        else:
-            dia = dialogs.Info(
-                parent = self.parent,
-                message = _("Your settings have been successfully saved.") + "\n" + \
-                _("Your changes will take effect after the next system reboot"),
+                message = _("There was an error saving the your automatic login preferences.") + "\n" + e,
                 buttons = [("OK", self.close_module)]
+                )
+            return self.pop_dialog(dia)
+        # Display a success dialog
+        dia = dialogs.Info(
+            parent = self.parent,
+            message = _("Your settings have been successfully saved.") + "\n" + \
+            _("Your changes will take effect after the next system reboot."),
+            buttons = [("OK", self.close_module)]
             )
         return self.pop_dialog(dia)
     
             self._autologin_user = user_data
     
     def _get_users_list(self):
-        allusers = USERADMIN.UserModel().list_all()
+        allusers = USERADMIN.UserModel().listUsers()
         logins = []
         _names = []
-        for (login, uid, home) in allusers:
+        for account in allusers:
             rb = urwid.RadioButton(_names,
-                                   login,
-                                   state = self._current_aluser == login,
-                                   user_data = login)
+                                   account.login,
+                                   state = self._current_aluser == account.login,
+                                   user_data = account.login,
+                on_state_change = self.autologin_user_toggle_event)
             w = urwid.AttrWrap(rb, 'button')
             logins.append(
                 urwid.Columns([('fixed', 6, urwid.Text(" ")), w], 0))

modules/tui/tui_dateset.py

 class DateSet(dialogs.ModuleDialog):
     def __init__(self, parent):
         self.parent = parent
+        # create the models to work with the dateset module
+        self.dtmodel = DATESET.DateTime()
+        self.tzmodel = DATESET.TimeZone()
+        self.hwcmodel = DATESET.HWClock()
         msg = _("System date and time.")
         desc = _("Set the system date and time using the values below.") + "\n" + \
         _("Press +/- to navigate months, space or enter to select current date")
         self.calendar = widgets.Calendar()
         cal = urwid.LineBox(self.calendar)
         self.clock = widgets.TimePicker()
-        _widgets = [urwid.Columns([cal,('fixed', 2, widgets.blank),self.clock])]
+
+        # Create a label that explains how the timezone and hwclock work
+        tx = (
+            _("Linux uses the hardware clock setting and timezone to properly set the system time."),
+            " ",
+            _("To get the proper results, select the value that matches your hardware (BIOS) clock setting."),
+            " ",
+            _("If you are unsure about this, 'Localtime' is the common value for most PC's."),'\n'
+            )
+        warntext = urwid.Text('\n'+' '.join(tx))
+
+        # the timezone picker
+        self.tzselector = widgets.SensibleLabel(
+            markup = self.tzmodel.get_zone(),
+            actuator = self._pick_timezone
+            )
+        selector = urwid.AttrWrap(self.tzselector, 'button', 'button sel')
+        tzarea = urwid.Columns([
+            ('fixed', 20, urwid.Text("Select Timezone")) ,
+            selector
+            ])
+        # the hwclock selector
+        self.hwcselector = widgets.HChoiceBox(
+            "Hardware clock setting:",
+            ["UTC", "Localtime"]
+            )
+        self.hwcselector.set_value(self.hwcmodel.get_value())
+        lb = urwid.ListBox([warntext, self.tzselector, self.hwcselector])
+        piled_bottom = [
+            ('flow', warntext),
+            tzarea,
+            self.hwcselector
+        ]
+        bottom = urwid.Pile(piled_bottom)
+
+        top = urwid.Columns([cal, ('fixed', 2, widgets.blank), self.clock])
+
+        _widgets = [top, urwid.Divider('_'), bottom]
+
 
         dialogs.ModuleDialog.__init__(
             self,
             body = _widgets
         )
         self.set_focus('body')
+
+    def _pick_timezone(self, widget=None):
+        """ Pop a dialog to select the timezone """
+        dia = dialogs.VChoiceBox(
+            title  = _("Select your timezone"),
+            options = self.tzmodel.list_zones(),
+            parent = self.parent,
+            on_select = self._update_tz_selection)
+        # Set the initial value to the current setting. 
+        dia._selection = self.tzmodel.get_zone()
+        return self.parent.pop_module_dialog(dia, 3)
+
+    def _update_tz_selection(self, value):
+        return self.tzselector.set_value(value)
     
+    def _on_timezonepicker_enter(self, widget=None):
+        pass
+        
+
+    def _write_date_settings(self):
+        """ Write the date settings to the system based on what the user picked from the calendar widget."""
+        _year, _month, _day = self.calendar.get_date()
+        self.dtmodel.year = _year
+        self.dtmodel.month = _month
+        self.dtmodel.day = _day
+        return self.dtmodel.set_date()
+
+    def _write_time_settings(self):
+        """ Write the time settings for based on the current values of the clock widget """
+        _hr, _min, _sec = self.clock.get_time()
+        self.dtmodel.hour = _hr
+        self.dtmodel.minute = _min
+        self.dtmodel.second = _sec
+        return self.dtmodel.set_time()
+
+    def _write_timezone_setting(self):
+        tz = self.tzselector.get_value()
+        return self.tzmodel.set_zone(tz)
+
+    def _write_hwclock_setting(self):
+        setting = self.hwcselector.get_value()
+        return self.hwcmodel.set_value(setting)
+
     def save_settings(self, widget=None):
-        """ get the values from the time and date pickers and save them to the system."""
-        year, month, day = self.calendar.get_date()
-        # the DATESET module expects to add one to the month value. 
-        month = month - 1
-        # ^^ That hack is to keep things compattible with the gtk calendar.
-        code, output = DATESET.set_date((year, month, day))
-        if code > 0:
+        """ Trigger the sequence to save the changes to the system."""
+        # Save the date settings
+        try:
+            self._write_date_settings()
+        except DATESET.DateTimeError as e:
             dia = dialogs.Error(
                 parent = self.parent,
-                message = _("Error while setting the system date.") + "\n" + output.strip(),
+                message = _("Failed to set the system date.") + "\n\n%s"% e,
                 buttons = [("OK", self.return_to_module)]
-            )
+                )
             return self.pop_dialog(dia)
-        hour, minute, second = self.clock.get_time()
-        code, output = DATESET.set_time((hour, minute, second))
-        if code > 0:
+        # Save the time settings
+        try:
+            self._write_time_settings()
+        except DATESET.DateTimeError as e:
             dia = dialogs.Error(
                 parent = self.parent,
-                message = _("Error while setting the system clock.") + "\n" + output.strip(),
+                message = _("Failed to save the system time settings.") + "\n\n%s"% e,
                 buttons = [("OK", self.return_to_module)]
-            )
+                )
             return self.pop_dialog(dia)
-        
+
+        # Save the timezone settings
+        try:
+            self._write_timezone_setting()
+        except IOError as e:
+            return dialogs.Error(
+                parent = self.parent,
+                message = _("Failed to set timezone setting.") + "\n\n%s"% e,
+                buttons = [("OK", self.return_to_module)]
+                )
+            return self.pop_dialog(dia)
+    
+        # Save the hwclock settings
+        try:
+            self._write_hwclock_setting()
+        except IOError as e:
+            dia = dialogs.Error(
+                parent = self.parent,
+                message = _("Faled to save hardware clock setting.") + "\n\n%s"% e,
+                buttons = [("OK", self.return_to_module)]
+                )
+            return self.pop_dialog(dia)
+        except AssertionError as e:
+            dia = dialogs.Error(
+                parent = self.parent,
+                buttons = [("OK", self.return_to_module)],
+                message = _("Failed to save hardware clock setting.") + "\n\n%s"% e            
+                )
+            return self.pop_dialog(dia)
+
         dia = dialogs.Info(
             parent = self.parent,
-            message = _("System date and time have been successfully updated."),
+            message = ("System date and time settings have been updated."),
             buttons = [("OK", self.close_module)]
-        )
-        return self.pop_dialog(dia)        
-
+            )
+        return self.pop_dialog(dia)
+        
 
 def __vasm_test__():
     # only root can use this
 
 def __run__(parent):
     dia = DateSet(parent)
-    return parent.pop_module(dia)
+    return parent.pop_module(dia)

modules/tui/tui_password.py

                 _("New password is too short.  Select a password at least 6 characters long.")
             )
         # after all tests are passed, make the call
-        return self.do_change_password(currpass, newpass)
+        return self.do_change_password(oldpass, pass2)
     
     def report_password_error(self, error):
         """ Report a password error """
             user = os.getenv("USERNAME")
         # request the password change
         try:
-            PASSWORDS.change_password(user, oldpass, newpass):
+            PASSWORDS.change_password(user, oldpass, newpass)
         except PASSWORDS.BadPasswordException:
             dia = dialogs.Error(
                 parent = self.parent,
                 )
             return self.parent.pop_module_dialog(dia)
         except PASSWORDS.BadNewPasswordException:
-            dia = dialogs.error(
+            dia = dialogs.Error(
                 parent = self.parent,
-                message = ' '.join(
+                message = ' '.join((
                     _("The new password you entered does not meet the minimum requirements."), " ",
                     _("Passwords should be at least 6 characters long.")
-                    ),
-                buttons = [("OK", self.return_to_module)]                    
+                    )),
+                buttons = [("OK", self.return_to_module)]
                 )
             return self.parent.pop_module_dialog(dia)
         dia = dialogs.Info(

modules/tui/tui_usermanage.py

 
 class GroupsPrompt(urwid.Frame):
     """ Dialog to set the users groups """
-    def __init__(self, parent=None, login=""):
+    def __init__(self, parent=None, account=None):
         self.parent = parent
+        self.topparent = parent.parent
         self._user_groups = []
         self._buttons = [("Apply", self.do_modify_groups),
-            ("Cancel", self.parent.return_to_module_stack)]
+            ("Cancel", self.parent.return_to_module)]
         self.buttons = []
         for but, cb in self._buttons:
             self.buttons.append(
         bar = urwid.GridFlow(self.buttons, 15, 1, 1, 'center')
         title = urwid.Text(_("USER GROUP MEMBERSHIPS"), 'right')
         #self._get_user_groups()
-        self.login = login
-        self.usermodel = USERADMIN.User(login)
+        self.account = account
         _content = [
             ('flow', widgets.blank),
             self._get_user_groups(),
     
     def do_modify_groups(self, widget):
         """ Apply the changes """
-        code, output = self.usermodel.set_groups(self._user_groups)
-        if code > 0:
+        cgroups = self._user_groups
+        # store the changes to the account
+        self.account.groups = cgroups
+        try:
+            self.account.save_groups_changes()
+        except USERADMIN.AccountError as e:
             dia = dialogs.Error(
                 parent = self.parent,
-                message = _("The following error was reported while applying changes") + "\n\n" + output.strip(),
-                buttons = [("OK", self.parent.return_to_module_stack)]
+                message = _("The following error was encountered while saving changes") + ":\n\n%s"% e,
+                buttons = [("OK", self.parent.return_to_module)]
+                )
+            return self.parent.pop_dialog(dia, 3)
+        dia = dialogs.Info(
+            parent = self.parent,
+            message = _("Your changes have been successfully applied to this account."),
+            buttons = [("OK", self.parent.return_to_module)]
             )
-        else:
-            dia = dialogs.Info(
-                parent = self.parent,
-                message = _("Your changes have been successfully applied."),
-                buttons = [("OK", self.parent.return_to_module_stack)]
-            )
-        # Pop this dialog as a 3rd level widget.
-        return self.parent.pop_module_dialog(dia, 3)
+        return self.parent.pop_dialog(dia, 3)
     
     def _get_user_groups(self):
         """ Return a listbox with checkboxes for all the groups this user belongs to """
         for grp in USERADMIN.__distro_groups__:
             allgroups.append((grp, USERADMIN.__distro_groups__[grp][0]))
         # produce a list of all the groups this user is already a member of
-        memberships = self.usermodel.get_groups()
+        memberships = self.account.groups
         # Loop through all groups and check if the user is already a member.
         
         for grp, desc in allgroups:
                 message = _("Please enter a login name.  Every account needs a login name."),
                 buttons = [("OK", self._parent.return_to_module_stack)])
             return self._parent.pop_module_dialog(dia)
-        # test if the username is avialable.  This should return True if the login
-        # is available, False if it is taken
-        if not USERADMIN.test_login_availability(self.loginbox.get_edit_text()):
+        # test if the username is avialable.  This should return False if the login
+        # is available, True if it is taken
+        if self.usermodel.hasUser(self.loginbox.get_edit_text()):
             dia = dialogs.Error(
                 parent = self._parent,
                 message = _(
             groups = reg_groups
         
         # stop the screen to let the user know we are working.
-        # self._parent._mainloop.screen.stop()
-        #print _("Creating user account"),"..."
+        self.parent.set_status_text("Cearing user account")
+        #        self._parent._mainloop.screen.stop()
+        #        print _("Creating user account"),"..."
         # Pop a dialog to tell people what we're doing.
-        dia = dialogs.Info(parent = self.parent,
-                           message = _("Creating user account"),
-                           buttons = [])
-        self._parent.pop_module_dialog(dia, 2)
+        #        dia = dialogs.Info(parent = self.parent,
+        #                           message = _("Creating user account"),
+        #                           buttons = [])
+        #        self._parent.pop_module_dialog(dia, 2)
         # Now that we have the information, make the call to create the account.
-        code, out = self.usermodel.create_new_account(
-            uname = lname,        
-            realname = rname,
-            password = passw,
-            groups = groups,
-            faceicon = facepath            
-        )
-        
-        # restore the screen
-        self._parent.return_to_module_stack()
-        #self._parent._mainloop.screen.start()
-        if code > 0:
-            # there was an error. Pop a dialog.
+        account = USERADMIN.User(new=True)
+        account.login = lname
+        if rname not in ("None", "", None):
+            account.realname = rname
+        else:
+            account.realname = None
+        account.realname = rname
+        account.password = passw
+        account.groups = groups
+        account.faceicon = facepath
+        try:
+            self.usermodel.addUser(account)
+            self.parent.set_status_text("")
+        except AssertionError as e:
             dia = dialogs.Error(
                 parent = self.parent,
-                message = "%s %s"% (_("The following error occurred while creating the account"), out.strip()),
-                buttons = [("OK", self._parent.return_to_module_stack)]
+                message = _("The following error was encountered while adding the new account") + ": \n\n%s"% e,
+                buttons = [("OK", self.parent.return_to_module)]
+                )
+            self.parent.set_status_text("")
+            self.clear_form_values()
+            return self.parent.pop_dialog(dia)
+        dia = dialogs.Info(
+            parent = self.parent,
+            message = _("User account was created successfully."),
+            buttons = [("OK", self.parent.return_to_module)]
             )
-        else:
-            dia = dialogs.Info(
-                parent = self.parent,
-                message = _("User account has been successfully created."),
-                buttons = [("OK", self._parent.return_to_module_stack)]
-            )
-            # clear the form because it has already been created.
-            self.clear_form_values()
-        return self._parent.pop_module_dialog(dia)
-    
+        self.parent.set_status_text("")
+        self.clear_form_values()
+        return self.parent.pop_dialog(dia)
+            
     def clear_form_values(self):
         """ Clear the data entered into the form """
         self.privileged_account = False
         self.usermodel = USERADMIN.UserModel()
         # List the user accounts using CategoryLabel widgets.  This allows
         # to display user info when the user is selected.
-        all = self.usermodel.list_all()
-        self.usermodel.add_observable(self.refresh_user_accounts)
+        #        all = self.usermodel.list_all()
+        self.usermodel.add_observer(self.refresh_user_accounts)
         _user_labels = []
         col0 = []
         #  Add a button to create new user account.
                 return self._trigger_cancel_method()
         return super(UserWindow, self).keypress(size, key)
 
-    def refresh_user_accounts(self, data):
+    def refresh_user_accounts(self, model):
         """ Method to refresh user accounts """
         col0 = []
         # add the non-changing stuff
         col0.append(urwid.AttrWrap(self._nacct, None, 'reveal focus'))
         col0.append(widgets.blank)
         col0.append(widgets.blank)
-        for acct in data:
-            user, uid, home = acct
+        for acct in model.listUsers():
+            user = acct.login
             label = widgets.CategoryLabel(
                 user,
                 focus_method = self.display_user_details,
             label._select_method = self.switch_to_account
             widget = urwid.AttrWrap(label, None, 'reveal focus')
             col0.append(widget)
+
         self.userlisting = widgets.CategoryDisplay(col0)
         self.leftpane = urwid.ListBox(self.userlisting)
         self.columns.widget_list[0] = self.leftpane
     def display_user_details(self, widget=None):
         """ Display details about this account on the right pane """
         self.current_user = widget.label
-        account = USERADMIN.User(widget.label)
+        account = self.usermodel.getUser(self.current_user)
+        #account = USERADMIN.User(widget.label)
         btdel = urwid.AttrWrap(urwid.Button(_("Delete User"),
                                             self.confirm_delete_account),'button', 'button sel')
         btperm = urwid.AttrWrap(urwid.Button(_("User Permissions"),
                                              self.prompt_user_groups), 'button', 'button sel')
         btpass = urwid.AttrWrap(urwid.Button(_("Change User Password"),
                                              self.prompt_password_change), 'button', 'button sel')
-        #buttonbar = urwid.GridFlow([btpass, btperm, btdel], 25, 1,1, 'left')
+        if account.fullname in ("", "None", None):
+            fn = _("Not Available")
+        else:
+            fn = account.fullname
         _widgets = [
-            urwid.Text("%s : %s"% (_("Login Name"), account.get_login_name())),
-            urwid.Text("%s : %s"% (_("Real Name"),
-                                   account.get_fullname() or "Not Available")),
-            urwid.Text("%s : %s"% (_("User ID"), account.get_uid())),
-            urwid.Text("%s : %s"% (_("Home Directory"), account.get_home_dir())),
-            urwid.Text("%s : %s"% (_("Login Shell"), account.get_shell())),
+            urwid.Text("%s : %s"% (_("Login Name"), account.login)),
+            urwid.Text("%s : %s"% (_("Real Name"), fn)),
+            urwid.Text("%s : %s"% (_("User ID"), account.uid)),
+            urwid.Text("%s : %s"% (_("Home Directory"), account.homedir)),
+            urwid.Text("%s : %s"% (_("Login Shell"), account.shell)),
             widgets.blank,
             urwid.Text(_("Account Maintenance")),
-            urwid.GridFlow([btpass], 30, 1, 1, 'left'),]
+            urwid.GridFlow([btpass], 30, 1, 1, 'left')
+            ]
         if widget.label != "root":
             _widgets.append(urwid.GridFlow([btperm], 30, 1, 1, 'left'))
             _widgets.append(urwid.GridFlow([btdel], 30, 1, 1, 'left'))
     
     def do_delete_account(self, widget):
         """ Delete the account after this action has been confirmed """
-        code, output = self.usermodel.delete_user(self.current_user)
-        if code > 0:
+        try:
+            self.usermodel.deleteUser(self.current_user)
+        except AssertionError as e:
             dia = dialogs.Error(
-                message = _("The following error occurred while deleting the account") + "\n\n" + output.strip(),
+                message = _("The following error was encontered while deleting the account") + ":\n\n%s"% e,
                 parent = self.parent,
                 buttons = [("OK", self.parent.return_to_module)]
-                #buttons = [("OK", self.parent.return_to_module_stack)]
-            )
-        else:
-            dia = dialogs.Info(
-                message = _("Account has been deleted and user data has been destroyed."),
-                parent = self.parent,
-                buttons = [("OK", self.parent.return_to_module)]
-                #buttons = [("OK", self.parent.return_to_module_stack)]
+                )
+            return self.parent.pop_module_dialog(dia, 3)
+        dia = dialogs.Info(
+            parent = self.parent,
+            buttons = [("OK", self.parent.return_to_module)],
+            message = _("Account has been deleted and user data has been destroyed.")
             )
         return self.parent.pop_module_dialog(dia, 3)
     
     
     def prompt_user_groups(self, widget=None):
         """ Show a list of groups this user belongs to """
-        dia = GroupsPrompt(self.parent, self.current_user)
+        dia = GroupsPrompt(self, self.usermodel.getUser(self.current_user))
         self.parent.pop_module_dialog(dia, 2)
 
 def __vasm_test__():
 def __run__(parent):
     manager = UserWindow(parent)
     parent.pop_module(manager)
-        
+        

modules/tuisupport/dialogs.py

         
         return super(ModuleDialog, self).keypress(size, key)
     
+
+    def set_status_text(self, text):
+        """ Set the status text for this module """
+        return self.statusbar.set_text(text)
+    
     def _get_footer(self):
         """ Return a pile that can be  used for the window's footer"""
         buttons = self._get_action_area()
         """ Add a button to the action area """
         self.buttons.append((button, callback))
         self.footer = self._get_footer()
+
+class VChoiceBox(ModuleDialog):
+    def __init__(self, title="", options=[], parent=None, on_select=None):
+        self.parent = parent
+        self.on_select = on_select
+	_grp = []
+	_selectors = []
+	for item in options:
+	    rb = urwid.RadioButton(group=_grp, label=item,
+                                   on_state_change = self._radio_toggle)
+	    wrap = urwid.AttrWrap(rb, 'button', 'button sel')
+	    _selectors.append(wrap)
+	_body = _selectors
+	ModuleDialog.__init__(self,
+				      header = urwid.AttrWrap(urwid.Text(title), 'column header'),
+		desc = [widgets.blank],
+		body = _body,
+		buttons = [("OK", self.make_choice),
+                           ("Cancel", self.return_to_module)],
+		parent = parent)
+        self.set_focus('body')
+        self.choices = _selectors
+        self._selection = None
+
+    def _radio_toggle(self, radio=None, new_state = None, userdata=None):
+        if new_state:
+            self._selection = radio.get_label()
+
+    def _get_action_area(self):
+        buttons = []
+        for but, cb in self.buttons:
+            buttons.append(
+                urwid.AttrWrap(
+                    urwid.Button(but, cb), 'button', 'button sel'
+                    )
+                )
+
+        bar = urwid.GridFlow(buttons, 12, 1, 0, 'right')
+        return bar
+
+    def make_choice(self, widget=None):
+        if self.on_select:
+            self.on_select(self._selection)
+        return self.return_to_module()
+
+        

modules/tuisupport/widgets.py

         actuator:   method to be executed when this launcher is selected by pressing
                     the 'enter' key
     """
-    def __init__(self, markup, category, actuator, parent):
+    def __init__(self, markup="", category="", actuator=None, parent=None):
         self.parent = parent
         urwid.Text.__init__(self, markup)
         self.actuator = actuator
             self.keypress((10, 2), 'left')
         return key
 
+class SensibleLabel(urwid.Text):
+    def __init__(self, markup="", actuator=None, user_data=None, on_focus=None):
+	urwid.Text.__init__(self, markup)
+	self.on_focus = on_focus
+	self.actuator = actuator
+	self.user_data = user_data
+
+    def selectable(self):
+	return True
+
+    def render(self, size, focus=False):
+	if focus:
+	    if self.on_focus:
+		self.on_focus(self)
+	return super(SensibleLabel, self).render(size, focus)
+
+    def keypress(self, size, key):
+	if key in ('enter', ' '):
+	    return self.actuator()
+        return key
+
+    def set_value(self, value):
+	return self.set_text(value)
+
+    def get_value(self):
+	return self.get_text()[0]
+
 class FrameBody(urwid.Pile):
     """ Widget to be used as a frame's body widget with special key bindings
     for the tab key """
                 int(self.mnpicker.text),
                 int(self.scpicker.text))
 
+
+class HChoiceBox(urwid.Columns):
+    def __init__(self, label="", choices = []):
+	self.label = urwid.Text(label)
+	rbgroup = []
+	_widgets = [('fixed', 25, self.label)]
+	self._radios = []
+	for item in choices:
+	    rb = urwid.RadioButton(group=rbgroup, label=item, on_state_change=self.radio_toggle)
+	    self._radios.append(rb)
+	    wrap = urwid.AttrWrap(rb, 'button','button sel')
+	    _widgets.append(('fixed', 15, wrap))
+	urwid.Columns.__init__(self, _widgets)
+
+    def radio_toggle(self, radio=None, new_value=None, user_data=None):
+	if new_value:
+	    self._selection = radio.get_label()
+	    return
+
+    def get_value(self):
+	return self._selection
+
+    def set_value(self, value):
+	for item in self._radios:
+	    if item.get_label().upper() == value.upper():
+		item.toggle_state()
+		return
+
+	
+