Skip to content

Commit

Permalink
Merge 3484766 into 4b74c7b
Browse files Browse the repository at this point in the history
  • Loading branch information
seanbudd authored Mar 17, 2021
2 parents 4b74c7b + 3484766 commit 6a62962
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 149 deletions.
42 changes: 27 additions & 15 deletions source/core.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# -*- coding: UTF-8 -*-
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2006-2019 NV Access Limited, Aleksey Sadovoy, Christopher Toth, Joseph Lee, Peter Vágner,
# Copyright (C) 2006-2021 NV Access Limited, Aleksey Sadovoy, Christopher Toth, Joseph Lee, Peter Vágner,
# Derek Riemer, Babbage B.V., Zahari Yurukov, Łukasz Golonka
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

from typing import Optional, TYPE_CHECKING
if TYPE_CHECKING:
import wx

"""NVDA core"""

RPC_E_CALL_CANCELED = -2147418110
Expand Down Expand Up @@ -207,6 +210,27 @@ def _setInitialFocus():
except:
log.exception("Error retrieving initial focus")


def getWxLangOrNone() -> Optional['wx.LanguageInfo']:
import languageHandler
import wx
lang = languageHandler.getLanguage()
locale = wx.Locale()
wxLang = locale.FindLanguageInfo(lang)
if not wxLang and '_' in lang:
wxLang = locale.FindLanguageInfo(lang.split('_')[0])
# #8064: Wx might know the language, but may not actually contain a translation database for that language.
# If we try to initialize this language, wx will show a warning dialog.
# #9089: some languages (such as Aragonese) do not have language info, causing language getter to fail.
# In this case, wxLang is already set to None.
# Therefore treat these situations like wx not knowing the language at all.
if wxLang and not locale.IsAvailable(wxLang.Language):
wxLang = None
if not wxLang:
log.debugWarning("wx does not support language %s" % lang)
return wxLang


def main():
"""NVDA's core main loop.
This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI.
Expand Down Expand Up @@ -418,26 +442,14 @@ def handlePowerStatusChange(self):

# initialize wxpython localization support
locale = wx.Locale()
lang=languageHandler.getLanguage()
wxLang=locale.FindLanguageInfo(lang)
if not wxLang and '_' in lang:
wxLang=locale.FindLanguageInfo(lang.split('_')[0])
wxLang = getWxLangOrNone()
if hasattr(sys,'frozen'):
locale.AddCatalogLookupPathPrefix(os.path.join(globalVars.appDir, "locale"))
# #8064: Wx might know the language, but may not actually contain a translation database for that language.
# If we try to initialize this language, wx will show a warning dialog.
# #9089: some languages (such as Aragonese) do not have language info, causing language getter to fail.
# In this case, wxLang is already set to None.
# Therefore treat these situations like wx not knowing the language at all.
if wxLang and not locale.IsAvailable(wxLang.Language):
wxLang=None
if wxLang:
try:
locale.Init(wxLang.Language)
except:
log.error("Failed to initialize wx locale",exc_info=True)
else:
log.debugWarning("wx does not support language %s" % lang)

log.debug("Initializing garbageHandler")
garbageHandler.initialize()
Expand Down
26 changes: 14 additions & 12 deletions source/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,10 @@ def initialize():
if mainFrame:
raise RuntimeError("GUI already initialized")
mainFrame = MainFrame()
wxLang = core.getWxLangOrNone()
if wxLang:
# otherwise the system default will be used
mainFrame.SetLayoutDirection(wxLang.LayoutDirection)
wx.GetApp().SetTopWindow(mainFrame)
# In wxPython >= 4.1,
# wx.CallAfter no longer executes callbacks while NVDA's main thread is within apopup menu or message box.
Expand Down Expand Up @@ -725,14 +729,10 @@ def __init__(self, parent):
welcomeTextDetail = wx.StaticText(self, wx.ID_ANY, self.WELCOME_MESSAGE_DETAIL)
mainSizer.Add(welcomeTextDetail,border=20,flag=wx.EXPAND|wx.LEFT|wx.RIGHT)

optionsSizer = wx.StaticBoxSizer(
wx.StaticBox(
self,
# Translators: The label for a group box containing the NVDA welcome dialog options.
label=_("Options")
),
wx.VERTICAL
)
# Translators: The label for a group box containing the NVDA welcome dialog options.
optionsLabel = _("Options")
optionsSizer = wx.StaticBoxSizer(wx.VERTICAL, self, label=optionsLabel)
optionsBox = optionsSizer.GetStaticBox()
sHelper = guiHelper.BoxSizerHelper(self, sizer=optionsSizer)
# Translators: The label of a combobox in the Welcome dialog.
kbdLabelText = _("&Keyboard layout:")
Expand All @@ -747,17 +747,18 @@ def __init__(self, parent):
log.error("Could not set Keyboard layout list to current layout",exc_info=True)
# Translators: The label of a checkbox in the Welcome dialog.
capsAsNVDAModifierText = _("&Use CapsLock as an NVDA modifier key")
self.capsAsNVDAModifierCheckBox = sHelper.addItem(wx.CheckBox(self, label=capsAsNVDAModifierText))
self.capsAsNVDAModifierCheckBox = sHelper.addItem(wx.CheckBox(optionsBox, label=capsAsNVDAModifierText))
self.capsAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"])
# Translators: The label of a checkbox in the Welcome dialog.
startAfterLogonText = _("St&art NVDA after I sign in")
self.startAfterLogonCheckBox = sHelper.addItem(wx.CheckBox(self, label=startAfterLogonText))
self.startAfterLogonCheckBox = sHelper.addItem(wx.CheckBox(optionsBox, label=startAfterLogonText))
self.startAfterLogonCheckBox.Value = config.getStartAfterLogon()
if globalVars.appArgs.secure or config.isAppX or not config.isInstalledCopy():
self.startAfterLogonCheckBox.Disable()
# Translators: The label of a checkbox in the Welcome dialog.
showWelcomeDialogAtStartupText = _("&Show this dialog when NVDA starts")
self.showWelcomeDialogAtStartupCheckBox = sHelper.addItem(wx.CheckBox(self, label=showWelcomeDialogAtStartupText))
_showWelcomeDialogAtStartupCheckBox = wx.CheckBox(optionsBox, label=showWelcomeDialogAtStartupText)
self.showWelcomeDialogAtStartupCheckBox = sHelper.addItem(_showWelcomeDialogAtStartupCheckBox)
self.showWelcomeDialogAtStartupCheckBox.SetValue(config.conf["general"]["showWelcomeDialogAtStartup"])
mainSizer.Add(optionsSizer, border=guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
mainSizer.Add(self.CreateButtonSizer(wx.OK), border=guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL|wx.ALIGN_RIGHT)
Expand Down Expand Up @@ -810,7 +811,8 @@ def __init__(self, parent):

# Translators: The label of the license text which will be shown when NVDA installation program starts.
groupLabel = _("License Agreement")
sizer = sHelper.addItem(wx.StaticBoxSizer(wx.StaticBox(self, label=groupLabel), wx.VERTICAL))
sizer = wx.StaticBoxSizer(wx.VERTICAL, self, label=groupLabel)
sHelper.addItem(sizer)
licenseTextCtrl = wx.TextCtrl(self, size=(500, 400), style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH)
licenseTextCtrl.Value = codecs.open(getDocFilePath("copying.txt", False), "r", encoding="UTF-8").read()
sizer.Add(licenseTextCtrl)
Expand Down
17 changes: 10 additions & 7 deletions source/gui/configProfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,24 @@ def __init__(self, parent):

mainSizer = wx.BoxSizer(wx.VERTICAL)
sHelper = guiHelper.BoxSizerHelper(self,orientation=wx.VERTICAL)
profilesListGroupSizer = wx.StaticBoxSizer(wx.StaticBox(self), wx.HORIZONTAL)
profilesListGroupSizer = wx.StaticBoxSizer(wx.HORIZONTAL, self)
profilesListBox = profilesListGroupSizer.GetStaticBox()
profilesListGroupContents = wx.BoxSizer(wx.HORIZONTAL)

#contains the profile list and activation button in vertical arrangement.
changeProfilesSizer = wx.BoxSizer(wx.VERTICAL)
item = self.profileList = wx.ListBox(self,
choices=[self.getProfileDisplay(name, includeStates=True) for name in self.profileNames])
item = self.profileList = wx.ListBox(
profilesListBox,
choices=[self.getProfileDisplay(name, includeStates=True) for name in self.profileNames]
)
self.bindHelpEvent("ProfilesBasicManagement", self.profileList)
item.Bind(wx.EVT_LISTBOX, self.onProfileListChoice)
item.Selection = self.profileNames.index(config.conf.profiles[-1].name)
changeProfilesSizer.Add(item, proportion=1.0)

changeProfilesSizer.AddSpacer(guiHelper.SPACE_BETWEEN_BUTTONS_VERTICAL)

self.changeStateButton = wx.Button(self)
self.changeStateButton = wx.Button(profilesListBox)
self.bindHelpEvent("ConfigProfileManual", self.changeStateButton)
self.changeStateButton.Bind(wx.EVT_BUTTON, self.onChangeState)
self.AffirmativeId = self.changeStateButton.Id
Expand All @@ -68,17 +71,17 @@ def __init__(self, parent):

buttonHelper = guiHelper.ButtonHelper(wx.VERTICAL)
# Translators: The label of a button to create a new configuration profile.
newButton = buttonHelper.addButton(self, label=_("&New"))
newButton = buttonHelper.addButton(profilesListBox, label=_("&New"))
self.bindHelpEvent("ProfilesCreating", newButton)
newButton.Bind(wx.EVT_BUTTON, self.onNew)

# Translators: The label of a button to rename a configuration profile.
self.renameButton = buttonHelper.addButton(self, label=_("&Rename"))
self.renameButton = buttonHelper.addButton(profilesListBox, label=_("&Rename"))
self.bindHelpEvent("ProfilesBasicManagement", self.renameButton)
self.renameButton.Bind(wx.EVT_BUTTON, self.onRename)

# Translators: The label of a button to delete a configuration profile.
self.deleteButton = buttonHelper.addButton(self, label=_("&Delete"))
self.deleteButton = buttonHelper.addButton(profilesListBox, label=_("&Delete"))
self.bindHelpEvent("ProfilesBasicManagement", self.deleteButton)
self.deleteButton.Bind(wx.EVT_BUTTON, self.onDelete)

Expand Down
13 changes: 9 additions & 4 deletions source/gui/guiHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,10 @@ def addLabeledControl(self, labelText, wxCtrlClass, **kwargs):
Relies on guiHelper.LabeledControlHelper and thus guiHelper.associateElements, and therefore inherits any
limitations from there.
"""
labeledControl = LabeledControlHelper(self._parent, labelText, wxCtrlClass, **kwargs)
parent = self._parent
if isinstance(self.sizer, wx.StaticBoxSizer):
parent = self.sizer.GetStaticBox()
labeledControl = LabeledControlHelper(parent, labelText, wxCtrlClass, **kwargs)
if(isinstance(labeledControl.control, (wx.ListCtrl,wx.ListBox,wx.TreeCtrl))):
self.addItem(labeledControl.sizer, flag=wx.EXPAND, proportion=1)
else:
Expand All @@ -345,6 +348,9 @@ def addDialogDismissButtons(self, buttons, separated=False):
Should be set to L{False} for message or single input dialogs, L{True} otherwise.
@type separated: L{bool}
"""
parent = self._parent
if isinstance(self.sizer, wx.StaticBoxSizer):
parent = self.sizer.GetStaticBox()
if self.sizer.GetOrientation() != wx.VERTICAL:
raise NotImplementedError(
"Adding dialog dismiss buttons to a horizontal BoxSizerHelper is not implemented."
Expand All @@ -354,16 +360,15 @@ def addDialogDismissButtons(self, buttons, separated=False):
elif isinstance(buttons, (wx.Sizer, wx.Button)):
toAdd = buttons
elif isinstance(buttons, int):
toAdd = self._parent.CreateButtonSizer(buttons)
toAdd = parent.CreateButtonSizer(buttons)
else:
raise NotImplementedError("Unknown type: {}".format(buttons))
if separated:
self.addItem(wx.StaticLine(self._parent), flag=wx.EXPAND)
self.addItem(wx.StaticLine(parent), flag=wx.EXPAND)
self.addItem(toAdd, flag=wx.ALIGN_RIGHT)
self.dialogDismissButtonsAdded = True
return buttons

class SIPABCMeta(wx.siplib.wrappertype, ABCMeta):
"""Meta class to be used for wx subclasses with abstract methods."""
pass

45 changes: 24 additions & 21 deletions source/gui/installerGui.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,15 @@ def __init__(self, parent, isUpdate):
self.bindHelpEvent("InstallWithIncompatibleAddons", self.confirmationCheckbox)
self.confirmationCheckbox.SetFocus()

optionsSizer = guiHelper.BoxSizerHelper(self, sizer=sHelper.addItem(wx.StaticBoxSizer(
wx.StaticBox(
self,
# Translators: The label for a group box containing the NVDA installation dialog options.
label=_("Options")
),
wx.VERTICAL
)))
# Translators: The label for a group box containing the NVDA installation dialog options.
optionsLabel = _("Options")
optionsHelper = sHelper.addItem(wx.StaticBoxSizer(wx.VERTICAL, self, label=optionsLabel))
optionsSizer = guiHelper.BoxSizerHelper(self, sizer=optionsHelper)
optionsBox = optionsSizer.GetStaticBox()

# Translators: The label of a checkbox option in the Install NVDA dialog.
startOnLogonText = _("Use NVDA during sign-in")
self.startOnLogonCheckbox = optionsSizer.addItem(wx.CheckBox(self, label=startOnLogonText))
self.startOnLogonCheckbox = optionsSizer.addItem(wx.CheckBox(optionsBox, label=startOnLogonText))
self.bindHelpEvent("StartAtWindowsLogon", self.startOnLogonCheckbox)
if globalVars.appArgs.enableStartOnLogon is not None:
self.startOnLogonCheckbox.Value = globalVars.appArgs.enableStartOnLogon
Expand All @@ -197,19 +194,22 @@ def __init__(self, parent, isUpdate):
if self.isUpdate and shortcutIsPrevInstalled:
# Translators: The label of a checkbox option in the Install NVDA dialog.
keepShortCutText = _("&Keep existing desktop shortcut")
self.createDesktopShortcutCheckbox = optionsSizer.addItem(wx.CheckBox(self, label=keepShortCutText))
keepShortCutBox = wx.CheckBox(optionsBox, label=keepShortCutText)
self.createDesktopShortcutCheckbox = optionsSizer.addItem(keepShortCutBox)
else:
# Translators: The label of the option to create a desktop shortcut in the Install NVDA dialog.
# If the shortcut key has been changed for this locale,
# this change must also be reflected here.
createShortcutText = _("Create &desktop icon and shortcut key (control+alt+n)")
self.createDesktopShortcutCheckbox = optionsSizer.addItem(wx.CheckBox(self, label=createShortcutText))
createShortcutBox = wx.CheckBox(optionsBox, label=createShortcutText)
self.createDesktopShortcutCheckbox = optionsSizer.addItem(createShortcutBox)
self.bindHelpEvent("CreateDesktopShortcut", self.createDesktopShortcutCheckbox)
self.createDesktopShortcutCheckbox.Value = shortcutIsPrevInstalled if self.isUpdate else True

# Translators: The label of a checkbox option in the Install NVDA dialog.
createPortableText = _("Copy &portable configuration to current user account")
self.copyPortableConfigCheckbox = optionsSizer.addItem(wx.CheckBox(self, label=createPortableText))
createPortableBox = wx.CheckBox(optionsBox, label=createPortableText)
self.copyPortableConfigCheckbox = optionsSizer.addItem(createPortableBox)
self.bindHelpEvent("CopyPortableConfigurationToCurrentUserAccount", self.copyPortableConfigCheckbox)
self.copyPortableConfigCheckbox.Value = bool(globalVars.appArgs.copyPortableConfig)
if globalVars.appArgs.copyPortableConfig is None:
Expand All @@ -220,12 +220,12 @@ def __init__(self, parent, isUpdate):
bHelper = sHelper.addDialogDismissButtons(guiHelper.ButtonHelper(wx.HORIZONTAL))
if shouldAskAboutAddons:
# Translators: The label of a button to launch the add-on compatibility review dialog.
reviewAddonButton = bHelper.addButton(self, label=_("&Review add-ons..."))
reviewAddonButton = bHelper.addButton(optionsBox, label=_("&Review add-ons..."))
self.bindHelpEvent("InstallWithIncompatibleAddons", reviewAddonButton)
reviewAddonButton.Bind(wx.EVT_BUTTON, self.onReviewAddons)

# Translators: The label of a button to continue with the operation.
continueButton = bHelper.addButton(self, label=_("&Continue"), id=wx.ID_OK)
continueButton = bHelper.addButton(optionsBox, label=_("&Continue"), id=wx.ID_OK)
continueButton.SetDefault()
continueButton.Bind(wx.EVT_BUTTON, self.onInstall)
if shouldAskAboutAddons:
Expand All @@ -235,7 +235,7 @@ def __init__(self, parent, isUpdate):
)
continueButton.Enable(False)

bHelper.addButton(self, id=wx.ID_CANCEL)
bHelper.addButton(optionsBox, id=wx.ID_CANCEL)
# If we bind this using button.Bind, it fails to trigger when the dialog is closed.
self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL)

Expand Down Expand Up @@ -349,35 +349,38 @@ def __init__(self, parent):
# Translators: The label of a grouping containing controls to select the destination directory
# in the Create Portable NVDA dialog.
directoryGroupText = _("Portable &directory:")
groupHelper = sHelper.addItem(gui.guiHelper.BoxSizerHelper(self, sizer=wx.StaticBoxSizer(wx.StaticBox(self, label=directoryGroupText), wx.VERTICAL)))
groupSizer = wx.StaticBoxSizer(wx.VERTICAL, self, label=directoryGroupText)
groupHelper = sHelper.addItem(gui.guiHelper.BoxSizerHelper(self, sizer=groupSizer))
groupBox = groupSizer.GetStaticBox()
# Translators: The label of a button to browse for a directory.
browseText = _("Browse...")
# Translators: The title of the dialog presented when browsing for the
# destination directory when creating a portable copy of NVDA.
dirDialogTitle = _("Select portable directory")
directoryEntryControl = groupHelper.addItem(gui.guiHelper.PathSelectionHelper(self, browseText, dirDialogTitle))
directoryPathHelper = gui.guiHelper.PathSelectionHelper(groupBox, browseText, dirDialogTitle)
directoryEntryControl = groupHelper.addItem(directoryPathHelper)
self.portableDirectoryEdit = directoryEntryControl.pathControl
if globalVars.appArgs.portablePath:
self.portableDirectoryEdit.Value = globalVars.appArgs.portablePath

# Translators: The label of a checkbox option in the Create Portable NVDA dialog.
copyConfText = _("Copy current &user configuration")
self.copyUserConfigCheckbox = sHelper.addItem(wx.CheckBox(self, label=copyConfText))
self.copyUserConfigCheckbox = sHelper.addItem(wx.CheckBox(groupBox, label=copyConfText))
self.copyUserConfigCheckbox.Value = False
if globalVars.appArgs.launcher:
self.copyUserConfigCheckbox.Disable()
# Translators: The label of a checkbox option in the Create Portable NVDA dialog.
startAfterCreateText = _("&Start the new portable copy after creation")
self.startAfterCreateCheckbox = sHelper.addItem(wx.CheckBox(self, label=startAfterCreateText))
self.startAfterCreateCheckbox = sHelper.addItem(wx.CheckBox(groupBox, label=startAfterCreateText))
self.startAfterCreateCheckbox.Value = False

bHelper = sHelper.addDialogDismissButtons(gui.guiHelper.ButtonHelper(wx.HORIZONTAL), separated=True)

continueButton = bHelper.addButton(self, label=_("&Continue"), id=wx.ID_OK)
continueButton = bHelper.addButton(groupBox, label=_("&Continue"), id=wx.ID_OK)
continueButton.SetDefault()
continueButton.Bind(wx.EVT_BUTTON, self.onCreatePortable)

bHelper.addButton(self, id=wx.ID_CANCEL)
bHelper.addButton(groupBox, id=wx.ID_CANCEL)
# If we bind this using button.Bind, it fails to trigger when the dialog is closed.
self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL)

Expand Down
Loading

0 comments on commit 6a62962

Please sign in to comment.