def _showAddonInfo(addon): manifest = addon.manifest # Translators: message shown in the Addon Information dialog. message = [ _("{summary} ({name})\n" "Version: {version}\n" "Author: {author}\n" "Description: {description}\n").format(**manifest) ] url = manifest.get('url') if url: # Translators: the url part of the About Add-on information message.append(_("URL: {url}").format(url=url)) minimumNVDAVersion = addonAPIVersion.formatForGUI(addon.minimumNVDAVersion) message.append( # Translators: the minimum NVDA version part of the About Add-on information _("Minimum required NVDA version: {}").format(minimumNVDAVersion)) lastTestedNVDAVersion = addonAPIVersion.formatForGUI( addon.lastTestedNVDAVersion) message.append( # Translators: the last NVDA version tested part of the About Add-on information _("Last NVDA version tested: {}").format(lastTestedNVDAVersion)) # Translators: title for the Addon Information dialog title = _("Add-on Information") gui.messageBox("\n".join(message), title, wx.OK)
def _showAddonRequiresNVDAUpdateDialog(parent, bundle): # Translators: The message displayed when installing an add-on package is prohibited, because it requires # a later version of NVDA than is currently installed. incompatibleMessage = _( "Installation of {summary} {version} has been blocked. The minimum NVDA version required for " "this add-on is {minimumNVDAVersion}, your current NVDA version is {NVDAVersion}" ).format(summary=bundle.manifest['summary'], version=bundle.manifest['version'], minimumNVDAVersion=addonAPIVersion.formatForGUI( bundle.minimumNVDAVersion), NVDAVersion=addonAPIVersion.formatForGUI(addonAPIVersion.CURRENT)) ErrorAddonInstallDialog( parent=parent, # Translators: The title of a dialog presented when an error occurs. title=_("Add-on not compatible"), message=incompatibleMessage, showAddonInfoFunction=lambda: _showAddonInfo(bundle)).ShowModal()
def _getIncompatReason(self, addon): if not addonVersionCheck.hasAddonGotRequiredSupport( addon, currentAPIVersion=self._APIVersion ): # Translators: The reason an add-on is not compatible. A more recent version of NVDA is # required for the add-on to work. The placeholder will be replaced with Year.Major.Minor (EG 2019.1). return _("An updated version of NVDA is required. NVDA version {} or later." ).format(addonAPIVersion.formatForGUI(addon.minimumNVDAVersion)) elif not addonVersionCheck.isAddonTested( addon, backwardsCompatToVersion=self._APIBackwardsCompatToVersion ): # Translators: The reason an add-on is not compatible. The addon relies on older, removed features of NVDA, # an updated add-on is required. The placeholder will be replaced with Year.Major.Minor (EG 2019.1). return _("An updated version of this add-on is required. The minimum supported API version is now {}" ).format(addonAPIVersion.formatForGUI(self._APIBackwardsCompatToVersion))
def _showAddonTooOldDialog(parent, bundle): # Translators: A message informing the user that this addon can not be installed because it is not compatible. confirmInstallMessage = _( "Installation of {summary} {version} has been blocked." " An updated version of this add-on is required," " the minimum add-on API supported by this version of NVDA is {backCompatToAPIVersion}" ).format(backCompatToAPIVersion=addonAPIVersion.formatForGUI( addonAPIVersion.BACK_COMPAT_TO), **bundle.manifest) return ErrorAddonInstallDialog( parent=parent, # Translators: The title of a dialog presented when an error occurs. title=_("Add-on not compatible"), message=confirmInstallMessage, showAddonInfoFunction=lambda: _showAddonInfo(bundle)).ShowModal()
def test_formatAsString_tupleTooLong(self): res = addonAPIVersion.formatForGUI((2019, 1, 1, 1)) self.assertEqual("unknown", res)
def test_formatAsString_none(self): res = addonAPIVersion.formatForGUI(None) self.assertEqual("unknown", res)
def test_formatAsString_zeros(self): res = addonAPIVersion.formatForGUI((0, 0, 0)) self.assertEqual("0.0", res)
def test_formatAsString_missingMinor(self): res = addonAPIVersion.formatForGUI((2019, 1, 0)) self.assertEqual("2019.1", res)
def test_formatAsString_full(self): res = addonAPIVersion.formatForGUI((2019, 1, 1)) self.assertEqual("2019.1.1", res)
def __init__(self, parent, APIVersion=addonAPIVersion.CURRENT, APIBackwardsCompatToVersion=addonAPIVersion.BACK_COMPAT_TO): if IncompatibleAddonsDialog._instance() is not None: raise RuntimeError( "Attempting to open multiple IncompatibleAddonsDialog instances" ) IncompatibleAddonsDialog._instance = weakref.ref(self) self._APIVersion = APIVersion self._APIBackwardsCompatToVersion = APIBackwardsCompatToVersion self.unknownCompatibilityAddonsList = list( addonHandler.getIncompatibleAddons( currentAPIVersion=APIVersion, backCompatToAPIVersion=APIBackwardsCompatToVersion)) if not len(self.unknownCompatibilityAddonsList) > 0: # this dialog is not designed to show an empty list. raise RuntimeError("No incompatible addons.") # Translators: The title of the Incompatible Addons Dialog wx.Dialog.__init__(self, parent, title=_("Incompatible Add-ons")) DpiScalingHelperMixin.__init__(self, self.GetHandle()) mainSizer = wx.BoxSizer(wx.VERTICAL) settingsSizer = wx.BoxSizer(wx.VERTICAL) sHelper = guiHelper.BoxSizerHelper(self, sizer=settingsSizer) maxControlWidth = 550 # Translators: The title of the Incompatible Addons Dialog introText = _( "The following add-ons are incompatible with NVDA version {}." " These add-ons can not be enabled." " Please contact the add-on author for further assistance." ).format(addonAPIVersion.formatForGUI(self._APIVersion)) AddonSelectionIntroLabel = wx.StaticText(self, label=introText) AddonSelectionIntroLabel.Wrap(self.scaleSize(maxControlWidth)) sHelper.addItem(AddonSelectionIntroLabel) # Translators: the label for the addons list in the incompatible addons dialog. entriesLabel = _("Incompatible add-ons") self.addonsList = sHelper.addLabeledControl( entriesLabel, nvdaControls.AutoWidthColumnListCtrl, style=wx.LC_REPORT | wx.LC_SINGLE_SEL, size=self.scaleSize((maxControlWidth, 350))) # Translators: The label for a column in add-ons list used to identify add-on package name (example: package is OCR). self.addonsList.InsertColumn(1, _("Package"), width=self.scaleSize(150)) # Translators: The label for a column in add-ons list used to identify add-on's running status (example: status is running). self.addonsList.InsertColumn(2, _("Version"), width=self.scaleSize(150)) # Translators: The label for a column in add-ons list used to provide some explanation about incompatibility self.addonsList.InsertColumn(3, _("Incompatible reason"), width=self.scaleSize(180)) buttonSizer = guiHelper.ButtonHelper(wx.HORIZONTAL) # Translators: The label for a button in Add-ons Manager dialog to show information about the selected add-on. self.aboutButton = buttonSizer.addButton(self, label=_("&About add-on...")) self.aboutButton.Disable() self.aboutButton.Bind(wx.EVT_BUTTON, self.onAbout) # Translators: The close button on an NVDA dialog. This button will dismiss the dialog. button = buttonSizer.addButton(self, label=_("&Close"), id=wx.ID_CLOSE) self.Bind(wx.EVT_CLOSE, self.onClose) sHelper.addDialogDismissButtons(buttonSizer) mainSizer.Add(settingsSizer, border=20, flag=wx.ALL) mainSizer.Fit(self) self.SetSizer(mainSizer) self.SetAffirmativeId(wx.ID_CLOSE) self.SetEscapeId(wx.ID_CLOSE) button.Bind(wx.EVT_BUTTON, self.onClose) self.refreshAddonsList() self.addonsList.SetFocus() self.CentreOnScreen()
def __init__( self, parent, APIVersion = addonAPIVersion.CURRENT, APIBackwardsCompatToVersion = addonAPIVersion.BACK_COMPAT_TO ): if IncompatibleAddonsDialog._instance() is not None: raise RuntimeError("Attempting to open multiple IncompatibleAddonsDialog instances") IncompatibleAddonsDialog._instance = weakref.ref(self) self._APIVersion = APIVersion self._APIBackwardsCompatToVersion = APIBackwardsCompatToVersion self.unknownCompatibilityAddonsList = list(addonHandler.getIncompatibleAddons( currentAPIVersion=APIVersion, backCompatToAPIVersion=APIBackwardsCompatToVersion )) if not len(self.unknownCompatibilityAddonsList) > 0: # this dialog is not designed to show an empty list. raise RuntimeError("No incompatible addons.") super().__init__( parent, # Translators: The title of the Incompatible Addons Dialog title=_("Incompatible Add-ons"), style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER | wx.MAXIMIZE_BOX, ) mainSizer=wx.BoxSizer(wx.VERTICAL) settingsSizer=wx.BoxSizer(wx.VERTICAL) sHelper = guiHelper.BoxSizerHelper(self, sizer=settingsSizer) maxControlWidth = 550 introText = _( # Translators: The title of the Incompatible Addons Dialog "The following add-ons are incompatible with NVDA version {}." " These add-ons can not be enabled." " Please contact the add-on author for further assistance." ).format(addonAPIVersion.formatForGUI(self._APIVersion)) AddonSelectionIntroLabel=wx.StaticText(self, label=introText) AddonSelectionIntroLabel.Wrap(self.scaleSize(maxControlWidth)) sHelper.addItem(AddonSelectionIntroLabel) # Translators: the label for the addons list in the incompatible addons dialog. entriesLabel=_("Incompatible add-ons") self.addonsList = sHelper.addLabeledControl( entriesLabel, nvdaControls.AutoWidthColumnListCtrl, style=wx.LC_REPORT|wx.LC_SINGLE_SEL, ) # Translators: The label for a column in add-ons list used to identify add-on package name (example: package is OCR). self.addonsList.InsertColumn(1, _("Package"), width=self.scaleSize(150)) # Translators: The label for a column in add-ons list used to identify add-on's running status (example: status is running). self.addonsList.InsertColumn(2, _("Version"), width=self.scaleSize(150)) # Translators: The label for a column in add-ons list used to provide some explanation about incompatibility self.addonsList.InsertColumn(3, _("Incompatible reason"), width=self.scaleSize(180)) buttonSizer = guiHelper.ButtonHelper(wx.HORIZONTAL) # Translators: The label for a button in Add-ons Manager dialog to show information about the selected add-on. self.aboutButton = buttonSizer.addButton(self, label=_("&About add-on...")) self.aboutButton.Disable() self.aboutButton.Bind(wx.EVT_BUTTON, self.onAbout) # Translators: The close button on an NVDA dialog. This button will dismiss the dialog. button = buttonSizer.addButton(self, label=_("&Close"), id=wx.ID_CLOSE) self.Bind(wx.EVT_CLOSE, self.onClose) sHelper.addDialogDismissButtons(buttonSizer, separated=True) mainSizer.Add( settingsSizer, border=guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL | wx.EXPAND, proportion=1 ) mainSizer.Fit(self) self.SetSizer(mainSizer) self.SetAffirmativeId(wx.ID_CLOSE) self.SetEscapeId(wx.ID_CLOSE) button.Bind(wx.EVT_BUTTON, self.onClose) self.refreshAddonsList() self.SetMinSize(mainSizer.GetMinSize()) # Historical initial size, result of L{self.addonsList} being (550, 350) as of PR #8006. # Setting an initial size on L{self.addonsList} by passing a L{size} argument when # creating the control would also set its minimum size and thus block the dialog from being shrunk. self.SetSize(self.scaleSize((606, 525))) self.CentreOnScreen() self.addonsList.SetFocus()