NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

loginII.py (22956B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\loginII.py
      2 import sys
      3 import blue
      4 import carbon.common.script.util.format as fmtutil
      5 import evecamera
      6 import localization
      7 import locks
      8 import log
      9 import pytelemetry.zoning as telemetry
     10 import trinity
     11 import types
     12 import uthread
     13 import utillib
     14 from carbon.common.lib.serverInfo import GetServerInfo, GetServerIP, GetServerName, LIVE_SERVER, TEST_SERVER1, TEST_SERVER2, TEST_SERVER3
     15 from carbonui import uiconst
     16 from carbonui.control.button import Button
     17 from carbonui.control.buttonIcon import ButtonIcon
     18 from carbonui.control.layer import LayerCore
     19 from carbonui.control.singlelineedits.singleLineEditPassword import SingleLineEditPassword
     20 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
     21 from carbonui.primitives.container import Container
     22 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     23 from carbonui.primitives.layoutGrid import LayoutGrid
     24 from carbonui.primitives.sprite import Sprite
     25 from carbonui.uianimations import animations
     26 from carbonui.uicore import uicore
     27 from eve.client.script.environment import nodemanager
     28 from eve.client.script.ui.control import eveLabel
     29 from eve.client.script.ui.control.themeColored import FillThemeColored
     30 from eve.common.lib import appConst as const
     31 from eveexceptions import UserError
     32 from eveprefs import prefs, boot
     33 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     34 
     35 def GetVersion():
     36     buildno = 'Undefined'
     37     try:
     38         buildno = '%s.%s' % (boot.keyval['version'].split('=', 1)[1], boot.build)
     39     except Exception:
     40         log.LogException()
     41 
     42     return buildno
     43 
     44 
     45 try:
     46     if not GetServerInfo().isLive:
     47         if prefs.GetValue('nominidump', 0):
     48             log.general.Log('Running against a test server. Crash minidump is NOT active because of nominidump=1 in prefs.ini', log.LGNOTICE)
     49         else:
     50             log.general.Log('Running against a test server. Crash minidump is active. You can disable this with nominidump=1 in prefs.ini', log.LGNOTICE)
     51             blue.os.miniDump = True
     52 except Exception:
     53     log.LogException()
     54 
     55 class Login(LayerCore):
     56     __guid__ = 'form.LoginII'
     57     __notifyevents__ = ['OnEndChangeDevice', 'OnGraphicSettingsChanged', 'ProcessUIRefresh']
     58     isTopLevelWindow = True
     59 
     60     def OnCloseView(self):
     61         if uicore.layer.systemmenu.isopen:
     62             uthread.new(uicore.layer.systemmenu.CloseMenu)
     63         self.Reset()
     64         sm.GetService('sceneManager').SetActiveScene(None)
     65         sm.UnregisterNotify(self)
     66         del self.scene.curveSets[:]
     67         self.scene = None
     68         self.ship = None
     69         self.Flush()
     70 
     71     def ProcessUIRefresh(self):
     72         if self.isopen:
     73             if self.reloading:
     74                 self.pendingReload = 1
     75                 return
     76             currentUsername = self.usernameEditCtrl.GetValue()
     77             currentPassword = self.passwordEditCtrl.GetValue()
     78             self.reloading = 1
     79             self.Layout(False, None, currentUsername, currentPassword)
     80             self.reloading = 0
     81             if self.pendingReload:
     82                 self.pendingReload = 0
     83 
     84     def OnEndChangeDevice(self, *args):
     85         if self.isopen:
     86             if self.reloading:
     87                 self.pendingReload = 1
     88                 return
     89             currentUsername = self.usernameEditCtrl.GetValue()
     90             currentPassword = self.passwordEditCtrl.GetValue()
     91             self.reloading = 1
     92             self.Layout(1, True, currentUsername, currentPassword)
     93             self.reloading = 0
     94             if self.pendingReload:
     95                 self.pendingReload = 0
     96                 self.OnEndChangeDevice()
     97 
     98     @telemetry.ZONE_METHOD
     99     def Reset(self):
    100         self.serverStatus = {}
    101         self.serverStatusTextControl = None
    102         self.serverStatusTextFunc = None
    103         self.serverNameTextControl = None
    104         self.serverVersionTextControl = None
    105         self.mainBrowserParent = None
    106         self.mainBrowser = None
    107         self.usernameEditCtrl = None
    108         self.passwordEditCtrl = None
    109         self.connecting = False
    110         self.acceptbtns = None
    111         self.scrollText = None
    112         self.reloading = 0
    113         self.pendingReload = 0
    114         self.maintabs = None
    115         self.isShowingUpdateDialog = False
    116 
    117     @telemetry.ZONE_METHOD
    118     def OnOpenView(self, **kwargs):
    119         self.Reset()
    120         uthread.worker('login::StatusTextWorker', self.__StatusTextWorker)
    121         blue.resMan.Wait()
    122         self.serverName = utillib.GetServerName()
    123         self.serverIP = GetServerIP(self.serverName)
    124         self.serverName = GetServerName(self.serverIP)
    125         self.serverPort = utillib.GetServerPort()
    126         self.firstCheck = True
    127         self.isShowingUpdateDialog = False
    128         self.Layout()
    129         sm.ScatterEvent('OnClientReady', 'login')
    130         self.isopen = 1
    131         uthread.new(self.UpdateServerStatus)
    132 
    133     def ClickExit(self):
    134         uicore.cmd.GetCommandAndExecute('CmdQuitGame')
    135 
    136     @telemetry.ZONE_METHOD
    137     def Layout(self, reloading = 0, pushBtnArgs = None, setUsername = None, setPassword = None):
    138         if not reloading:
    139             self.sceneLoadedEvent = locks.Event('loginScene')
    140             uthread.new(self.LoadScene)
    141         self.Flush()
    142         bar_height = uicore.desktop.height / 6
    143         top_bar = Container(name='underlayContainer', parent=self, align=uiconst.TOTOP, height=bar_height)
    144         FillThemeColored(bgParent=top_bar, colorType=uiconst.COLORTYPE_UIBASE, opacity=0.5)
    145         eveLabel.EveLabelSmall(parent=top_bar, align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL, left=16, top=16, text=localization.GetByLabel('UI/Login/Version', versionNumber=GetVersion()))
    146         if trinity.mainWindow.GetWindowState().windowMode != trinity.Tr2WindowMode.WINDOWED:
    147             ButtonIcon(parent=top_bar, align=uiconst.TOPRIGHT, state=uiconst.UI_NORMAL, top=16, left=16, texturePath='res:/UI/Texture/Shared/DarkStyle/windowClose.png', hint=localization.GetByLabel('UI/Login/QuitGame'), func=self.ClickExit, args=())
    148         bottom_bar = Container(name='underlayContainer_Bottom', parent=self, align=uiconst.TOBOTTOM, height=bar_height)
    149         FillThemeColored(bgParent=bottom_bar, colorType=uiconst.COLORTYPE_UIBASE, opacity=0.5)
    150         bottomArea = Container(name='bottomArea', parent=bottom_bar, idx=0)
    151         bottomSub = Container(name='bottomSub', parent=bottomArea, align=uiconst.CENTER, idx=0, height=bottom_bar.height, width=800)
    152         Button(parent=bottom_bar, align=uiconst.TOPLEFT, top=16, left=16, label=localization.GetByLabel('UI/Login/Settings'), func=self.OpenSettings, args=())
    153         login_container = ContainerAutoSize(parent=bottom_bar, align=uiconst.CENTERTOP, top=16, width=160, alignMode=uiconst.TOTOP)
    154         is_sso_login = sm.GetService('gameui').UsingSingleSignOn()
    155         if not is_sso_login:
    156             selected_username = setUsername or settings.public.ui.Get('username', '')
    157             self.usernameEditCtrl = SingleLineEditText(name='username', parent=login_container, align=uiconst.TOTOP, maxLength=64, hintText=localization.GetByLabel('UI/Login/Username'), OnReturn=self.Connect, setvalue=selected_username)
    158             self.usernameEditCtrl.SetHistoryVisibility(0)
    159             knownUserNames = settings.public.ui.Get('usernames', [])
    160             if knownUserNames:
    161                 self.usernameEditCtrl.LoadCombo(id='usernamecombo', options=[ (name, name) for name in knownUserNames ], callback=self.OnComboChange, setvalue=selected_username, comboIsTabStop=0)
    162             self.passwordEditCtrl = SingleLineEditPassword(name='password', parent=login_container, align=uiconst.TOTOP, top=8, maxLength=64, setvalue=setPassword, hintText=localization.GetByLabel('UI/Login/Password'), OnReturn=self.Connect)
    163             if trinity.app.IsActive():
    164                 if selected_username:
    165                     uicore.registry.SetFocus(self.passwordEditCtrl)
    166                 else:
    167                     uicore.registry.SetFocus(self.usernameEditCtrl)
    168         Button(parent=login_container, align=uiconst.TOTOP, top=8 if not is_sso_login else 0, label=localization.GetByLabel('UI/Login/Connect'), func=self.Connect, btn_default=1)
    169         status_container = LayoutGrid(parent=login_container, align=uiconst.TOPLEFT, left=login_container.width + 16, columns=1, cellSpacing=(0, 4))
    170         self.serverNameTextControl = eveLabel.EveLabelSmall(parent=status_container, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, text=localization.GetByLabel('UI/Login/CheckingStatus'))
    171         self.serverStatusTextControl = eveLabel.EveLabelSmall(parent=status_container, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED)
    172         self.serverVersionTextControl = eveLabel.EveLabelSmall(parent=status_container, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED)
    173         if not self.IsChina():
    174             esrbNoticeHeight = 70
    175             esrbNoticeWidth = 200
    176             allowedSizes = [1.0, 0.9, 0.8]
    177             desktopWidth = uicore.desktop.width
    178             useHeight = int(esrbNoticeHeight * 0.7)
    179             useWidth = int(esrbNoticeWidth * 0.7)
    180             for multiplier in allowedSizes:
    181                 tempWidth = esrbNoticeWidth * multiplier
    182                 if tempWidth <= desktopWidth * 0.11:
    183                     useWidth = int(tempWidth)
    184                     useHeight = int(esrbNoticeHeight * multiplier)
    185                     break
    186 
    187             cont = Container(name='esrbParent', parent=top_bar, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL, left=16, width=useWidth, height=useHeight)
    188             sprite = Sprite(name='ESRB', parent=cont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/ESRBnotice.dds', color=(1.0, 1.0, 1.0, 1.0))
    189             sprite.rectWidth = esrbNoticeWidth
    190             sprite.rectHeight = esrbNoticeHeight
    191             animations.FadeOut(cont, duration=0.5, timeOffset=6.0)
    192 
    193     def OnGraphicSettingsChanged(self, changes):
    194         if self.isopen and 'shaderQuality' in changes and getattr(self, 'scene', None):
    195             self.CheckHeightMaps()
    196 
    197     @telemetry.ZONE_METHOD
    198     def CheckHeightMaps(self):
    199         if 'LO' in trinity.GetShaderModel():
    200             heightMapParams = nodemanager.FindNodes(self.scene, 'HeightMap', 'trinity.TriTextureParameter')
    201             for param in heightMapParams:
    202                 param.resourcePath = param.resourcePath.replace('_hi.dds', '_lo.dds')
    203 
    204         else:
    205             heightMapParams = nodemanager.FindNodes(self.scene, 'HeightMap', 'trinity.TriTextureParameter')
    206             for param in heightMapParams:
    207                 param.resourcePath = param.resourcePath.replace('_lo.dds', '_hi.dds')
    208 
    209     @telemetry.ZONE_METHOD
    210     def LoadScene(self):
    211         self.scene = trinity.Load('res:/dx9/scene/login_screen.red')
    212         blue.resMan.Wait()
    213         self.CheckHeightMaps()
    214         stations = self.scene.Find('trinity.EveStation2')
    215         for station in stations:
    216             station.PlayAnimationEx('NormalLoop', 0, 0, 0.2)
    217 
    218         sceneMan = sm.GetService('sceneManager')
    219         sceneMan.SetActiveScene(self.scene)
    220         sceneMan.SetPrimaryCamera(evecamera.CAM_LOGIN)
    221         self.sceneLoadedEvent.set()
    222         blue.pyos.synchro.Yield()
    223 
    224     def OnEsc(self):
    225         if uicore.layer.systemmenu.isopen:
    226             uthread.new(uicore.layer.systemmenu.CloseMenu)
    227         else:
    228             uthread.new(uicore.layer.systemmenu.OpenView)
    229 
    230     def OpenSettings(self):
    231         if not uicore.layer.systemmenu.isopen:
    232             uthread.new(uicore.layer.systemmenu.OpenView)
    233 
    234     def OnComboChange(self, combo, header, value, *args):
    235         self.usernameEditCtrl.SetValue(value)
    236         self.passwordEditCtrl.SetValue('')
    237         uthread.new(uicore.registry.SetFocus, self.passwordEditCtrl)
    238 
    239     @telemetry.ZONE_METHOD
    240     def __StatusTextWorker(self):
    241         while not session.userid:
    242             blue.pyos.synchro.SleepWallclock(750)
    243             try:
    244                 if getattr(self, 'serverStatusTextFunc', None) is not None:
    245                     if not getattr(self, 'connecting', 0):
    246                         self.__SetServerStatusText(refreshOnNone=True)
    247             except:
    248                 log.LogException('Exception in status text worker')
    249                 sys.exc_clear()
    250 
    251     @telemetry.ZONE_METHOD
    252     def __SetServerStatusText(self, refreshOnNone = False):
    253         if self.serverStatusTextFunc is None:
    254             self.ClearServerStatus()
    255             return
    256         statusText = apply(self.serverStatusTextFunc[0])
    257         if statusText is None:
    258             self.ClearServerStatus()
    259             if refreshOnNone:
    260                 uthread.new(self.UpdateServerStatus, False)
    261             return
    262         serverversion, serverbuild = self.serverStatusTextFunc[1:]
    263         self.SetNameText(localization.GetByLabel('UI/Login/ServerStatus/Server', serverName=self.serverName))
    264         label, parameters = statusText
    265         self.SetStatusText(localization.GetByLabel('UI/Login/ServerStatus/Status', statusText=localization.GetByLabel(label, **parameters)))
    266         if serverversion and serverbuild:
    267             if '%.2f' % serverversion != '%.2f' % boot.version or serverbuild > boot.build:
    268                 self.SetVersionText(localization.GetByLabel('UI/Login/ServerStatus/VersionIncompatible', serverVersion=serverversion, serverBuild=serverbuild))
    269         if label == '/Carbon/MachoNet/ServerStatus/OK':
    270             sm.GetService('connection').TryAutomaticLogin()
    271 
    272     def IsChina(self):
    273         return boot.region == 'optic'
    274 
    275     def GetIsAutoPatch(self, allowPatch):
    276         isAutoPatch = self.serverIP == LIVE_SERVER or self.serverIP in [TEST_SERVER1, TEST_SERVER2, TEST_SERVER3] or prefs.GetValue('forceAutopatch', 0) == 1
    277         if not allowPatch:
    278             isAutoPatch = False
    279         return isAutoPatch
    280 
    281     def IsServerPortValid(self):
    282         try:
    283             int(self.serverPort)
    284         except Exception as e:
    285             log.LogError(e)
    286             sys.exc_clear()
    287             self.SetStatusText(localization.GetByLabel('UI/Login/InvalidPortNumber', port=self.serverPort))
    288             self.serverStatusTextFunc = None
    289             return False
    290 
    291         return True
    292 
    293     def UpdateServerStatus(self, allowPatch = True):
    294         self.InternalUpdateServerStatus(allowPatch=allowPatch, bootbuild=boot.build, bootversion=boot.version)
    295 
    296     def DisplayOutOfDateMessageAndQuitGame(self, reason = None):
    297         self.isShowingUpdateDialog = True
    298         prompt_player_fsd_dialog('LoginUpdateAvailable', {'info': 'Client is out of date'})
    299         uicore.cmd.DoQuitGame()
    300 
    301     def CompareVersionsAndAct(self, bootbuild, bootversion, isAutoPatch, serverbuild, serverversion, statusMessage):
    302         if statusMessage is not None and 'Incompatible' in statusMessage[0] or '%.2f' % serverversion != '%.2f' % bootversion or serverbuild > bootbuild:
    303             if serverbuild > bootbuild and isAutoPatch:
    304                 self.DisplayOutOfDateMessageAndQuitGame('OutOfDate')
    305 
    306     def GetActualStatusMessage(self, serverbuild, serverversion, statusMessage):
    307         self.serverStatusTextFunc = None
    308         if type(statusMessage) in (types.LambdaType, types.FunctionType, types.MethodType):
    309             self.serverStatusTextFunc = (statusMessage, serverversion, serverbuild)
    310         else:
    311             self.serverStatusTextFunc = (lambda : statusMessage, serverversion, serverbuild)
    312         self.__SetServerStatusText()
    313         resolvedStatusMessage = apply(self.serverStatusTextFunc[0])
    314         messagePart = resolvedStatusMessage[0]
    315         return messagePart
    316 
    317     @telemetry.ZONE_METHOD
    318     def InternalUpdateServerStatus(self, allowPatch, bootbuild, bootversion):
    319         self.SetStatusText(localization.GetByLabel('UI/Login/CheckingStatus'))
    320         self.serverStatusTextFunc = None
    321         blue.pyos.synchro.Yield()
    322         if self.isShowingUpdateDialog:
    323             return
    324         if not self.IsServerPortValid():
    325             return
    326         serverversion = serverbuild = servercodename = None
    327         isAutoPatch = self.GetIsAutoPatch(allowPatch)
    328         try:
    329             log.LogInfo('checking status of %s' % self.serverIP)
    330             try:
    331                 if self.firstCheck:
    332                     forceQueueCheck = True
    333                     self.firstCheck = False
    334                 else:
    335                     forceQueueCheck = False
    336                 statusMessage, serverStatus = sm.GetService('machoNet').GetServerStatus('%s:%s' % (self.serverIP, self.serverPort), forceQueueCheck=forceQueueCheck)
    337             except UserError as e:
    338                 if e.msg == 'AlreadyConnecting':
    339                     sys.exc_clear()
    340                     return
    341                 raise
    342 
    343             if not self.isopen:
    344                 return
    345             self.serverStatus[self.serverIP] = (serverStatus.get('boot_version', None),
    346              serverStatus.get('boot_build', None),
    347              str(serverStatus.get('boot_codename', const.responseUnknown)),
    348              serverStatus.get('update_info', const.responseUnknown))
    349             serverversion, serverbuild, servercodename, updateinfo = self.serverStatus[self.serverIP]
    350             actualStatusMsg = self.GetActualStatusMessage(serverbuild, serverversion, statusMessage)
    351             if serverversion and serverbuild:
    352                 self.CompareVersionsAndAct(bootbuild, bootversion, isAutoPatch, serverbuild, serverversion, actualStatusMsg)
    353             elif actualStatusMsg is not None and 'IncompatibleProtocol' in actualStatusMsg:
    354                 self.DisplayOutOfDateMessageAndQuitGame('Incompatable protocol')
    355             else:
    356                 raise Exception('Invalid answer from server GetServerStatus')
    357         except Exception as e:
    358             log.LogException(e)
    359             sys.exc_clear()
    360             self.SetStatusText(localization.GetByLabel('UI/Login/UnableToConnect', IP=self.serverIP, port=self.serverPort))
    361             self.serverStatusTextFunc = None
    362 
    363     def SetNameText(self, text):
    364         if self.serverNameTextControl and not self.serverNameTextControl.destroyed:
    365             self.serverNameTextControl.text = text
    366 
    367     def SetStatusText(self, text):
    368         if self.serverStatusTextControl and not self.serverStatusTextControl.destroyed:
    369             self.serverStatusTextControl.text = text
    370 
    371     def SetVersionText(self, text):
    372         if self.serverVersionTextControl and not self.serverVersionTextControl.destroyed:
    373             self.serverVersionTextControl.text = text
    374 
    375     def ClearServerStatus(self, *args):
    376         self.SetStatusText('')
    377         self.serverStatusTextFunc = None
    378         return True
    379 
    380     def Connect(self, *args):
    381         uthread.new(self._Connect)
    382 
    383     @telemetry.ZONE_METHOD
    384     def _Connect(self):
    385         if self.connecting:
    386             return
    387         self.connecting = True
    388         giveFocus = None
    389         try:
    390             if sm.GetService('gameui').UsingSingleSignOn():
    391                 for arg in blue.pyos.GetArg()[1:]:
    392                     if arg.startswith('/ssoToken'):
    393                         try:
    394                             argName, token = arg.split('=')
    395                         except:
    396                             raise RuntimeError('Invalid format of SSO token, should be /ssoToken=<token>')
    397 
    398                 sm.GetService('gameui').DoLogin(token)
    399                 return
    400             user = self.usernameEditCtrl.GetValue()
    401             password = fmtutil.PasswordString(self.passwordEditCtrl.GetValue(raw=1))
    402             giveFocus = None
    403             if user is None or len(user) == 0:
    404                 giveFocus = 'username'
    405             if password is None or len(password) == 0:
    406                 giveFocus = 'password' if giveFocus is None else giveFocus
    407             if giveFocus is not None:
    408                 prompt_player_fsd_dialog('LoginAuthFailed')
    409                 self.CancelLogin()
    410                 self.SetFocus(giveFocus)
    411                 return
    412             log.LogInfo('server: %s selected' % self.serverIP)
    413             blue.pyos.synchro.Yield()
    414             if self.serverPort == sm.StartService('machoNet').defaultProxyPortOffset:
    415                 if self.serverIP not in self.serverStatus:
    416                     self.UpdateServerStatus()
    417                 try:
    418                     serverversion, serverbuild, servercodename, updateinfo = self.serverStatus[self.serverIP]
    419                     if serverbuild > boot.build:
    420                         if self.serverIP == LIVE_SERVER:
    421                             response = prompt_player_fsd_dialog('PatchLiveServerConnectWrongVersion', {'serverVersion': serverbuild,
    422                              'clientVersion': boot.build}, uiconst.YESNO)
    423                             if response == uiconst.ID_YES:
    424                                 self.UpdateServerStatus()
    425                         else:
    426                             prompt_player_fsd_dialog('PatchTestServerWarning', {'serverVersion': serverbuild,
    427                              'clientVersion': boot.build})
    428                         self.CancelLogin()
    429                         return
    430                 except:
    431                     log.LogInfo('No serverStatus found for server %s' % self.serverIP)
    432                     sys.exc_clear()
    433                     prompt_player_fsd_dialog('UnableToConnectToServer')
    434                     self.CancelLogin()
    435                     return
    436 
    437             sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/Login/LoggingIn'), localization.GetByLabel('UI/Login/ConnectingToCluster'), 1, 100)
    438             blue.pyos.synchro.Yield()
    439             prompt_player_fsd_dialog('OnConnecting')
    440             blue.pyos.synchro.Yield()
    441             prompt_player_fsd_dialog('OnConnecting2')
    442             blue.pyos.synchro.Yield()
    443             try:
    444                 sm.GetService('connection').Login([user,
    445                  password,
    446                  self.serverIP,
    447                  self.serverPort,
    448                  0])
    449             except Exception:
    450                 self.CancelLogin()
    451                 raise
    452 
    453             settings.public.ui.Set('username', user or '-')
    454             prefs.newbie = 0
    455             knownUserNames = settings.public.ui.Get('usernames', [])[:]
    456             if user and user not in knownUserNames:
    457                 knownUserNames.append(user)
    458                 settings.public.ui.Set('usernames', knownUserNames)
    459         except UserError as e:
    460             if e.msg.startswith('LoginAuthFailed'):
    461                 giveFocus = 'password'
    462             prompt_player_fsd_dialog(e.msg, e.dict)
    463             self.CancelLogin()
    464             self.SetFocus(giveFocus)
    465         finally:
    466             if not self.destroyed:
    467                 self.connecting = 0
    468 
    469     def CancelLogin(self):
    470         sm.GetService('loading').CleanUp()
    471 
    472     def SetFocus(self, where = None):
    473         if where is None:
    474             return
    475         if where == 'username':
    476             uicore.registry.SetFocus(self.usernameEditCtrl)
    477         elif where == 'password':
    478             self.passwordEditCtrl.SetValue('')
    479             uicore.registry.SetFocus(self.passwordEditCtrl)