Beispiel #1
0
 def processUpdate():
     url = addonInfos["url"]
     if url.endswith('/'): url = url[0:-1]
     url = "%s.nvda-addon?%s" % (url, urlencode(paramsDL()))
     fp = os.path.join(globalVars.appArgs.configPath,
                       "%s.nvda-addon" % sectionName)
     try:
         dl = URLopener()
         dl.retrieve(url, fp)
         try:
             curAddons = []
             for addon in addonHandler.getAvailableAddons():
                 curAddons.append(addon)
             bundle = addonHandler.AddonBundle(fp)
             prevAddon = None
             bundleName = bundle.manifest['name']
             for addon in curAddons:
                 if not addon.isPendingRemove and bundleName == addon.manifest[
                         'name']:
                     prevAddon = addon
                     break
             if prevAddon: prevAddon.requestRemove()
             addonHandler.installAddonBundle(bundle)
             core.restart()
         except BaseException as e:
             log.error(e)
             os.startfile(fp)
     except BaseException as e:
         log.error(e)
         return wx.CallAfter(errorUpdateDialog)
 def getBundle():
     try:
         bundle = addonHandler.AddonBundle(self.destPath.decode("mbcs"))
     except AttributeError:
         bundle = addonHandler.AddonBundle(self.destPath)
     except:
         log.error("Error opening addon bundle from %s" % self.destPath,
                   exc_info=True)
         # Translators: The message displayed when an error occurs when trying to update an add-on package due to package problems.
         gui.messageBox(
             _("Cannot update {name} - missing file or invalid file format"
               ).format(name=self.addonName),
             makeAddonWindowTitle(NVDAString("Error")),
             wx.OK | wx.ICON_ERROR)
         return None
     return bundle
Beispiel #3
0
 def processUpdate():
     url = configBE._addonURL + "latest?" + urlencode(paramsDL())
     fp = os.path.join(globalVars.appArgs.configPath,
                       "brailleExtender.nvda-addon")
     try:
         dl = URLopener()
         dl.retrieve(url, fp)
         try:
             curAddons = []
             for addon in addonHandler.getAvailableAddons():
                 curAddons.append(addon)
             bundle = addonHandler.AddonBundle(fp)
             prevAddon = None
             bundleName = bundle.manifest['name']
             for addon in curAddons:
                 if not addon.isPendingRemove and bundleName == addon.manifest[
                         'name']:
                     prevAddon = addon
                     break
             if prevAddon: prevAddon.requestRemove()
             addonHandler.installAddonBundle(bundle)
             core.restart()
         except BaseException as e:
             log.error(e)
             os.startfile(fp)
     except BaseException as e:
         log.error(e)
         ui.message(
             _("Unable to save or download update file. Opening your browser"
               ))
         os.startfile(url)
     return
Beispiel #4
0
	def installAddon(self, addonPath, closeAfter=False):
		try:
			try:
				bundle=addonHandler.AddonBundle(addonPath)
			except:
				log.error("Error opening addon bundle from %s"%addonPath,exc_info=True)
				# Translators: The message displayed when an error occurs when opening an add-on package for adding. 
				gui.messageBox(_("Failed to open add-on package file at %s - missing file or invalid file format")%addonPath,
					# Translators: The title of a dialog presented when an error occurs.
					_("Error"),
					wx.OK | wx.ICON_ERROR)
				return
			# Translators: A message asking the user if they really wish to install an addon.
			if gui.messageBox(_("Are you sure you want to install this add-on? Only install add-ons from trusted sources.\nAddon: {summary} {version}\nAuthor: {author}").format(**bundle.manifest),
				# Translators: Title for message asking if the user really wishes to install an Addon.
				_("Add-on Installation"),
				wx.YES|wx.NO|wx.ICON_WARNING)!=wx.YES:
				return
			bundleName=bundle.manifest['name']
			prevAddon=None
			for addon in self.curAddons:
				if not addon.isPendingRemove and bundleName==addon.manifest['name']:
					prevAddon=addon
					break
			if prevAddon:
				# Translators: A message asking if the user wishes to update a previously installed add-on with this one.
				if gui.messageBox(_("A version of this add-on is already installed. Would you like to update it?"),
				# Translators: A title for the dialog  asking if the user wishes to update a previously installed add-on with this one.
				_("Add-on Installation"),
				wx.YES|wx.NO|wx.ICON_WARNING)!=wx.YES:
					return
				prevAddon.requestRemove()
			progressDialog = gui.IndeterminateProgressDialog(gui.mainFrame,
			# Translators: The title of the dialog presented while an Addon is being installed.
			_("Installing Add-on"),
			# Translators: The message displayed while an addon is being installed.
			_("Please wait while the add-on is being installed."))
			try:
				gui.ExecAndPump(addonHandler.installAddonBundle,bundle)
			except:
				log.error("Error installing  addon bundle from %s"%addonPath,exc_info=True)
				self.refreshAddonsList()
				progressDialog.done()
				del progressDialog
				# Translators: The message displayed when an error occurs when installing an add-on package.
				gui.messageBox(_("Failed to install add-on  from %s")%addonPath,
					# Translators: The title of a dialog presented when an error occurs.
					_("Error"),
					wx.OK | wx.ICON_ERROR)
				return
			else:
				self.refreshAddonsList(activeIndex=-1)
				progressDialog.done()
				del progressDialog
		finally:
			if closeAfter:
				# #4460: If we do this immediately, wx seems to drop the WM_QUIT sent if the user chooses to restart.
				# This seems to have something to do with the wx.ProgressDialog.
				# The CallLater seems to work around this.
				wx.CallLater(1, self.Close)
Beispiel #5
0
def getAddon():
    import tempfile, os
    addon = opener(updateInfo["downloadUrl"])
    content = addon.read()
    addon.close()
    if updateInfo["size"] != len(content):
        gui.messageBox(_("Data load error"),
                       _("Error"),
                       style=wx.OK | wx.ICON_ERROR)
        return
    fd, path = tempfile.mkstemp(".nvda-addon", "tcmd_addon_update-")
    with open(path, "wb") as file:
        file.write(content)
    import core
    bundle = addonHandler.AddonBundle(path)
    try:
        if not addonHandler.addonVersionCheck.isAddonCompatible(bundle):
            gui.messageBox(_(
                "This version of NVDA is incompatible. To install the add-on, NVDA version {year}.{major} or higher is required. Please update NVDA or download an older version of the add-on here: \n{link}"
            ).format(
                year=bundle.minimumNVDAVersion[0],
                major=bundle.minimumNVDAVersion[1],
                link=
                "https://github.com/jawhien/extendedTotalCmd/releases/tag/2.5"
            ),
                           _("Error"),
                           style=wx.OK | wx.ICON_ERROR)
            os.close(fd)
            os.unlink(path)
            return
    except:
        pass
    gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
    for addon in addonHandler.getAvailableAddons():
        if not addon.isPendingRemove and manifest["name"].lower(
        ) == addon.manifest["name"].lower():
            addon.requestRemove()
            break
    os.close(fd)
    os.unlink(path)
    if gui.messageBox(_(
            "Changes were made to add-ons. You must restart NVDA for these changes to take effect. Would you like to restart now?"
    ),
                      _("Restart NVDA"),
                      style=wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES:
        core.restart()
Beispiel #6
0
 def processUpdate(expectedSHA256Sum):
     url = addonInfos["url"]
     if url.endswith('/'):
         url = url[0:-1]
     url = "%s.nvda-addon?%s" % (url, urlencode(paramsDL()))
     fp = os.path.join(globalVars.appArgs.configPath,
                       "%s.nvda-addon" % sectionName)
     try:
         with urllib.request.urlopen(url) as res:
             with open(fp, "wb") as out:
                 out.write(res.read())
         actualSHA256Sum = SHA256Sum(fp)
         if expectedSHA256Sum != actualSHA256Sum:
             log.info("Invalid hash for %s. Actual: %s, expected: %s" %
                      (fp, actualSHA256Sum, expectedSHA256Sum))
             msg = _(
                 "Hashes do not match! Actual value is '{actualHash}'. Expected is '{expectedHash}'."
             ).format(actualHash=actualSHA256Sum,
                      expectedHash=expectedSHA256Sum)
             wx.CallAfter(errorUpdateDialog, msg)
             return
         curAddons = []
         for addon in addonHandler.getAvailableAddons():
             curAddons.append(addon)
         bundle = addonHandler.AddonBundle(fp)
         prevAddon = None
         bundleName = bundle.manifest['name']
         for addon in curAddons:
             if not addon.isPendingRemove and bundleName == addon.manifest[
                     "name"]:
                 prevAddon = addon
                 break
         if prevAddon:
             prevAddon.requestRemove()
         addonHandler.installAddonBundle(bundle)
         core.restart()
     except BaseException as e:
         log.error(e)
         return wx.CallAfter(errorUpdateDialog, e)
Beispiel #7
0
 def onTimer(self):
     if self.inTimer is True or self.hasBeenUpdated is True:
         return
     self.inTimer = True
     try:
         evt = self.updater.queue.get_nowait()
     except queue.Empty:
         evt = None
     if evt is not None:
         filepath = evt.get("download", None)
         if filepath is not None:
             import addonHandler
             for prev in addonHandler.getAvailableAddons():
                 if prev.name == updater.ADDON_NAME:
                     prev.requestRemove()
             bundle = addonHandler.AddonBundle(filepath)
             addonHandler.installAddonBundle(bundle)
             logHandler.log.info(
                 "Installed version %s, restart NVDA to make the changes permanent"
                 % (evt["version"]))
             self.hasBeenUpdated = True
     self.inTimer = False
     wx.CallLater(1000, self.onTimer)
Beispiel #8
0
 def download():
     global urlName, urlN, directory, bundle
     p = urllib.request.Request(urlRepos)
     r = urllib.request.urlopen(p).read()
     githubApi = json.loads(r.decode('utf-8'))
     urlName = githubApi[0]['assets'][0]['browser_download_url']
     urlN = str(urlName.split("/")[-1:]).replace("[", "").replace(
         "\'", "").replace("]", "")
     directory = os.path.join(globalVars.appArgs.configPath, "updates")
     if os.path.exists(directory) == False:
         os.mkdir(directory)
     file = os.path.join(directory, urlN)
     req = urllib.request.Request(urlName,
                                  headers={'User-Agent': 'Mozilla/5.0'})
     response = urllib.request.urlopen(req)
     fileContents = response.read()
     response.close()
     f = open(file, "wb")
     f.write(fileContents)
     f.close()
     bundle = addonHandler.AddonBundle(file)
     if bundle.manifest["name"] == ourAddon.manifest['name']:
         AddonFlow.checkCompatibility()
     AddonFlow.doNothing()
Beispiel #9
0
def installAddon(parentWindow, addonPath):
    """ Installs the addon at path. Any error messages / warnings are presented to the user via a GUI message box.
	If attempting to install an addon that is pending removal, it will no longer be pending removal.
	:return True on success or False on failure.
	"""
    try:
        bundle = addonHandler.AddonBundle(addonPath)
    except:
        log.error("Error opening addon bundle from %s" % addonPath,
                  exc_info=True)
        gui.messageBox(
            # Translators: The message displayed when an error occurs when opening an add-on package for adding.
            _("Failed to open add-on package file at %s - missing file or invalid file format"
              ) % addonPath,
            # Translators: The title of a dialog presented when an error occurs.
            _("Error"),
            wx.OK | wx.ICON_ERROR)
        return False  # Exit early, can't install an invalid bundle

    if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
        _showAddonRequiresNVDAUpdateDialog(parentWindow, bundle)
        return False  # Exit early, addon does not have required support
    elif not addonVersionCheck.isAddonTested(bundle):
        _showAddonTooOldDialog(parentWindow, bundle)
        return False  # Exit early, addon is not up to date with the latest API version.
    elif wx.YES != _showConfirmAddonInstallDialog(parentWindow, bundle):
        return False  # Exit early, User changed their mind about installation.

    prevAddon = None
    for addon in addonHandler.getAvailableAddons():
        if not addon.isPendingRemove and bundle.name == addon.manifest['name']:
            prevAddon = addon
            break
    if prevAddon:
        summary = bundle.manifest["summary"]
        curVersion = prevAddon.manifest["version"]
        newVersion = bundle.manifest["version"]

        # Translators: A title for the dialog asking if the user wishes to update a previously installed
        # add-on with this one.
        messageBoxTitle = _("Add-on Installation")

        # Translators: A message asking if the user wishes to update an add-on with the same version
        # currently installed according to the version number.
        overwriteExistingAddonInstallationMessage = _(
            "You are about to install version {newVersion} of {summary}, which appears to be already installed. "
            "Would you still like to update?").format(summary=summary,
                                                      newVersion=newVersion)

        # Translators: A message asking if the user wishes to update a previously installed add-on with this one.
        updateAddonInstallationMessage = _(
            "A version of this add-on is already installed. "
            "Would you like to update {summary} version {curVersion} to version {newVersion}?"
        ).format(summary=summary, curVersion=curVersion, newVersion=newVersion)

        if gui.messageBox(
                overwriteExistingAddonInstallationMessage if curVersion
                == newVersion else updateAddonInstallationMessage,
                messageBoxTitle, wx.YES | wx.NO | wx.ICON_WARNING) != wx.YES:
            return False
        prevAddon.requestRemove()

    from contextlib import contextmanager

    @contextmanager
    def doneAndDestroy(window):
        try:
            yield window
        except:
            # pass on any exceptions
            raise
        finally:
            # but ensure that done and Destroy are called.
            window.done()
            window.Destroy()

    #  use a progress dialog so users know that something is happening.
    progressDialog = gui.IndeterminateProgressDialog(
        parentWindow,
        # Translators: The title of the dialog presented while an Addon is being installed.
        _("Installing Add-on"),
        # Translators: The message displayed while an addon is being installed.
        _("Please wait while the add-on is being installed."))

    try:
        # Use context manager to ensure that `done` and `Destroy` are called on the progress dialog afterwards
        with doneAndDestroy(progressDialog):
            gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
            return True
    except:
        log.error("Error installing  addon bundle from %s" % addonPath,
                  exc_info=True)
        gui.messageBox(
            # Translators: The message displayed when an error occurs when installing an add-on package.
            _("Failed to install add-on from %s") % addonPath,
            # Translators: The title of a dialog presented when an error occurs.
            _("Error"),
            wx.OK | wx.ICON_ERROR)
    return False
Beispiel #10
0
 def _downloadSuccess(self):
     self._stopped()
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath.decode("mbcs"))
         except AttributeError:
             bundle = addonHandler.AddonBundle(self.destPath)
         except:
             log.error("Error opening addon bundle from %s" % self.destPath,
                       exc_info=True)
             # Translators: The message displayed when an error occurs when trying to update an add-on package due to package problems.
             gui.messageBox(
                 _("Cannot update {name} - missing file or invalid file format"
                   ).format(name=self.addonName), translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # Check compatibility with NVDA and/or Windows release.
         import versionInfo
         minimumNVDAVersion = bundle.manifest.get("minimumNVDAVersion",
                                                  None)
         if minimumNVDAVersion is None:
             minimumNVDAVersion = [
                 versionInfo.version_year, versionInfo.version_major
             ]
         lastTestedNVDAVersion = bundle.manifest.get(
             "lastTestedNVDAVersion", None)
         if lastTestedNVDAVersion is None:
             lastTestedNVDAVersion = [
                 versionInfo.version_year, versionInfo.version_major
             ]
         # For NVDA version, only version_year.version_major will be checked.
         minimumYear, minimumMajor = minimumNVDAVersion[:2]
         lastTestedYear, lastTestedMajor = lastTestedNVDAVersion[:2]
         if not ((minimumYear, minimumMajor) <=
                 (versionInfo.version_year, versionInfo.version_major) <=
                 (lastTestedYear, lastTestedMajor)):
             # Translators: The message displayed when trying to update an add-on that is not going to be compatible with the current version of NVDA.
             gui.messageBox(
                 _("{name} add-on is not compatible with this version of NVDA. Minimum NVDA version: {minYear}.{minMajor}, last tested: {testedYear}.{testedMajor}."
                   ).format(name=self.addonName,
                            minYear=minimumYear,
                            minMajor=minimumMajor,
                            testedYear=lastTestedYear,
                            testedMajor=lastTestedMajor),
                 translate("Error"), wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # Some add-ons require a specific Windows release or later.
         import winVersion
         minimumWindowsVersion = bundle.manifest.get(
             "minimumWindowsVersion", None)
         if minimumWindowsVersion is None:
             minimumWindowsVersion = winVersion.winVersion[:3]
         else:
             minimumWindowsVersion = [
                 int(data) for data in minimumWindowsVersion.split(".")
             ]
         minimumWinMajor, minimumWinMinor, minimumWinBuild = minimumWindowsVersion
         winMajor, winMinor, winBuild = winVersion.winVersion[:3]
         if (winMajor, winMinor, winBuild) < (
                 minimumWinMajor, minimumWinMinor, minimumWinBuild):
             # Translators: The message displayed when the add-on requires a newer version of Windows.
             gui.messageBox(
                 _("{name} add-on is not compatible with this version of Windows."
                   ).format(name=self.addonName), translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         bundleName = bundle.manifest['name']
         isDisabled = False
         # Optimization (future): it is better to remove would-be add-ons all at once instead of doing it each time a bundle is opened.
         for addon in addonHandler.getAvailableAddons():
             # Check for disabled state first.
             if bundleName == addon.manifest['name']:
                 if addon.isDisabled:
                     isDisabled = True
                 if not addon.isPendingRemove:
                     addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating {name}").format(name=self.addonName),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error("Error installing  addon bundle from %s" %
                       self.destPath,
                       exc_info=True)
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             # Translators: The message displayed when an error occurs when installing an add-on package.
             gui.messageBox(
                 _("Failed to update {name} add-on").format(
                     name=self.addonName), translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         else:
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             _updatedAddons.append(bundleName)
             if isDisabled:
                 for addon in addonHandler.getAvailableAddons():
                     if bundleName == addon.manifest[
                             'name'] and addon.isPendingInstall:
                         addon.enable(False)
                         break
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
     self.continueUpdatingAddons()
Beispiel #11
0
def installAddon(storeClient, addon, closeAfter=False, silent=False):
    if silent == False:
        ui.message(_("Downloading %s") % (addon.name))
    data = storeClient.getAddonFile(addon.id, addon.versionId)

    if data is None:
        if silent == False:
            ui.message(_("Unable to download the add-on."))
        return False
    tmp = os.path.join(config.getUserDefaultConfigPath(),
                       "storeDownloadedAddon.nvda-addon")
    logHandler.log.info(u"Saving to %s" % (tmp))
    f = file(tmp, "wb")
    f.write(data)
    f.close()
    path = tmp
    if path is None:
        if silent == False:
            ui.message(_("Unable to download %s") % (addon.name))
        return False
    if silent == False:
        ui.message(_("Installing"))
    try:
        bundle = addonHandler.AddonBundle(path)
    except:
        logHandler.log.error("Error opening addon bundle from %s" % path,
                             exc_info=True)
        # Translators: The message displayed when an error occurs when opening an add-on package for adding.
        if silent == False:
            gui.messageBox(
                _("Failed to open add-on package file at %s - missing file or invalid file format"
                  ) % path,
                # Translators: The title of a dialog presented when an error occurs.
                _("Error"),
                wx.OK | wx.ICON_ERROR)
        return False
    bundleName = bundle.manifest['name']
    prevAddon = None
    for addon in addonHandler.getAvailableAddons():
        if not addon.isPendingRemove and bundleName == addon.manifest['name']:
            prevAddon = addon
            break
    if prevAddon:
        prevAddon.requestRemove()
    if silent is False:
        progressDialog = gui.IndeterminateProgressDialog(
            gui.mainFrame,
            # Translators: The title of the dialog presented while an Addon is being installed.
            _("Installing Add-on"),
            # Translators: The message displayed while an addon is being installed.
            _("Please wait while the add-on is being installed."))
        try:
            gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
        except:
            logHandler.log.error("Error installing  addon bundle from %s" %
                                 addonPath,
                                 exc_info=True)
            progressDialog.done()
            del progressDialog
            # Translators: The message displayed when an error occurs when installing an add-on package.
            gui.messageBox(
                _("Failed to install add-on from %s") % (addon.name),
                # Translators: The title of a dialog presented when an error occurs.
                _("Error"),
                wx.OK | wx.ICON_ERROR)
            return False
        progressDialog.done()
        del progressDialog
    else:
        try:
            addonHandler.installAddonBundle(bundle)
        except:
            return False
    if closeAfter:
        wx.CallLater(1, core.restart)
    return True
Beispiel #12
0
 def _downloadSuccess(self):
     self._stopped()
     # Emulate add-on update (don't prompt to install).
     from gui import addonGui
     closeAfter = addonGui.AddonsDialog._instance is None
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath.decode("mbcs"))
         except:
             log.error("Error opening addon bundle from %s" % self.destPath,
                       exc_info=True)
             # Translators: The message displayed when an error occurs when opening an add-on package for adding.
             gui.messageBox(
                 _("Failed to open add-on package file at %s - missing file or invalid file format"
                   ) % self.destPath,
                 # Translators: The title of a dialog presented when an error occurs.
                 _("Error"),
                 wx.OK | wx.ICON_ERROR)
             return
         bundleName = bundle.manifest['name']
         for addon in addonHandler.getAvailableAddons():
             if not addon.isPendingRemove and bundleName == addon.manifest[
                     'name']:
                 addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating Add-on"),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error("Error installing  addon bundle from %s" %
                       self.destPath,
                       exc_info=True)
             if not closeAfter:
                 addonGui.AddonsDialog(gui.mainFrame).refreshAddonsList()
             progressDialog.done()
             del progressDialog
             # Translators: The message displayed when an error occurs when installing an add-on package.
             gui.messageBox(
                 _("Failed to update add-on  from %s") % self.destPath,
                 # Translators: The title of a dialog presented when an error occurs.
                 _("Error"),
                 wx.OK | wx.ICON_ERROR)
             return
         else:
             if not closeAfter:
                 addonGui.AddonsDialog(
                     gui.mainFrame).refreshAddonsList(activeIndex=-1)
             progressDialog.done()
             del progressDialog
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
         if closeAfter:
             wx.CallLater(1, addonGui.AddonsDialog(gui.mainFrame).Close)
Beispiel #13
0
 def _downloadSuccess(self):
     self._stopped()
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath)
         except:
             log.error(f"Error opening addon bundle from {self.destPath}",
                       exc_info=True)
             gui.messageBox(
                 # Translators: The message displayed when an error occurs
                 # when trying to update an add-on package due to package problems.
                 _("Cannot update {name} - missing file or invalid file format"
                   ).format(name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # NVDA itself will check add-on compatibility range.
         # As such, the below fragment was borrowed from NVDA Core (credit: NV Access).
         from addonHandler import addonVersionCheck
         from gui import addonGui
         if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
             addonGui._showAddonRequiresNVDAUpdateDialog(
                 gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         elif not addonVersionCheck.isAddonTested(bundle):
             addonGui._showAddonTooOldDialog(gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         bundleName = bundle.manifest['name']
         isDisabled = False
         # Optimization (future): it is better to remove would-be add-ons all at once
         # instead of doing it each time a bundle is opened.
         for addon in addonHandler.getAvailableAddons():
             # Check for disabled state first.
             if bundleName == addon.manifest['name']:
                 if addon.isDisabled:
                     isDisabled = True
                 if not addon.isPendingRemove:
                     addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating {name}").format(name=self.addonName),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error(
                 f"Error installing  addon bundle from {self.destPath}",
                 exc_info=True)
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             gui.messageBox(
                 # Translators: The message displayed when an error occurs when installing an add-on package.
                 _("Failed to update {name} add-on").format(
                     name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         else:
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             _updatedAddons.append(bundleName)
             if isDisabled:
                 for addon in addonHandler.getAvailableAddons():
                     if bundleName == addon.manifest[
                             'name'] and addon.isPendingInstall:
                         addon.enable(False)
                         break
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
     self.continueUpdatingAddons()
Beispiel #14
0
    def installAddon(self, addonPath, closeAfter=False):
        try:
            try:
                bundle = addonHandler.AddonBundle(addonPath)
            except:
                log.error("Error opening addon bundle from %s" % addonPath,
                          exc_info=True)
                gui.messageBox(
                    # Translators: The message displayed when an error occurs when opening an add-on package for adding.
                    _("Failed to open add-on package file at %s - missing file or invalid file format"
                      ) % addonPath,
                    # Translators: The title of a dialog presented when an error occurs.
                    _("Error"),
                    wx.OK | wx.ICON_ERROR)
                return

            if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
                self._showAddonRequiresNVDAUpdateDialog(bundle)
                return

            if not addonVersionCheck.isAddonTested(bundle):
                if wx.YES != self._showAddonUntestedDialog(bundle):
                    return
                AddonCompatibilityState.setAddonCompatibility(
                    addon=bundle,
                    compatibilityStateValue=compatValues.
                    MANUALLY_SET_COMPATIBLE)
            elif wx.YES != self._showConfirmAddonInstallDialog(bundle):
                return

            prevAddon = None
            for addon in self.curAddons:
                if not addon.isPendingRemove and bundle.name == addon.manifest[
                        'name']:
                    prevAddon = addon
                    break
            if prevAddon:
                summary = bundle.manifest["summary"]
                curVersion = prevAddon.manifest["version"]
                newVersion = bundle.manifest["version"]
                if gui.messageBox(
                        # Translators: A message asking if the user wishes to update an add-on with the same version currently installed according to the version number.
                        _("You are about to install version {newVersion} of {summary}, which appears to be already installed. Would you still like to update?"
                          ).format(summary=summary, newVersion=newVersion)
                        if curVersion == newVersion else
                        # Translators: A message asking if the user wishes to update a previously installed add-on with this one.
                        _("A version of this add-on is already installed. Would you like to update {summary} version {curVersion} to version {newVersion}?"
                          ).format(summary=summary,
                                   curVersion=curVersion,
                                   newVersion=newVersion),
                        # Translators: A title for the dialog  asking if the user wishes to update a previously installed add-on with this one.
                        _("Add-on Installation"),
                        wx.YES | wx.NO | wx.ICON_WARNING) != wx.YES:
                    return
                prevAddon.requestRemove()
            progressDialog = gui.IndeterminateProgressDialog(
                gui.mainFrame,
                # Translators: The title of the dialog presented while an Addon is being installed.
                _("Installing Add-on"),
                # Translators: The message displayed while an addon is being installed.
                _("Please wait while the add-on is being installed."))
            try:
                gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
            except:
                log.error("Error installing  addon bundle from %s" % addonPath,
                          exc_info=True)
                self.refreshAddonsList()
                progressDialog.done()
                del progressDialog
                # Translators: The message displayed when an error occurs when installing an add-on package.
                gui.messageBox(
                    _("Failed to install add-on  from %s") % addonPath,
                    # Translators: The title of a dialog presented when an error occurs.
                    _("Error"),
                    wx.OK | wx.ICON_ERROR)
                return
            else:
                self.refreshAddonsList(activeIndex=-1)
                progressDialog.done()
                del progressDialog
        finally:
            if closeAfter:
                # #4460: If we do this immediately, wx seems to drop the WM_QUIT sent if the user chooses to restart.
                # This seems to have something to do with the wx.ProgressDialog.
                # The CallLater seems to work around this.
                wx.CallLater(1, self.Close)
Beispiel #15
0
 def _downloadSuccess(self):
     self._stopped()
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath)
         except:
             log.error(f"Error opening addon bundle from {self.destPath}",
                       exc_info=True)
             gui.messageBox(
                 # Translators: The message displayed when an error occurs
                 # when trying to update an add-on package due to package problems.
                 _("Cannot update {name} - missing file or invalid file format"
                   ).format(name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # Check compatibility with NVDA and/or Windows release.
         # NVDA itself will check add-on compatibility range.
         # As such, the below fragment was borrowed from NVDA Core (credit: NV Access).
         from addonHandler import addonVersionCheck
         from gui import addonGui
         # Check compatibility with NVDA and/or Windows release.
         if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
             addonGui._showAddonRequiresNVDAUpdateDialog(
                 gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         elif not addonVersionCheck.isAddonTested(bundle):
             addonGui._showAddonTooOldDialog(gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         # Some add-ons require a specific Windows release or later.
         # Prepare for winVersion.getWinVer function.
         import winVersion
         minimumWindowsVersion = bundle.manifest.get(
             "minimumWindowsVersion", None)
         if hasattr(winVersion, "getWinVer"):
             if minimumWindowsVersion is None:
                 minimumWindowsVersion = winVersion.getWinVer()
             else:
                 minimumWindowsVersion = winVersion.WinVersion.fromVersionText(
                     minimumWindowsVersion)
             winVersionUnsupported = winVersion.getWinVer(
             ) < minimumWindowsVersion
         else:
             if minimumWindowsVersion is None:
                 minimumWindowsVersion = winVersion.winVersion[:3]
             else:
                 minimumWindowsVersion = [
                     int(data) for data in minimumWindowsVersion.split(".")
                 ]
             minimumWinMajor, minimumWinMinor, minimumWinBuild = minimumWindowsVersion
             winMajor, winMinor, winBuild = winVersion.winVersion[:3]
             winVersionUnsupported = (winMajor, winMinor, winBuild) < (
                 minimumWinMajor, minimumWinMinor, minimumWinBuild)
         if winVersionUnsupported:
             gui.messageBox(
                 # Translators: The message displayed when the add-on requires a newer version of Windows.
                 _("{name} add-on is not compatible with this version of Windows."
                   ).format(name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         bundleName = bundle.manifest['name']
         isDisabled = False
         # Optimization (future): it is better to remove would-be add-ons all at once
         # instead of doing it each time a bundle is opened.
         for addon in addonHandler.getAvailableAddons():
             # Check for disabled state first.
             if bundleName == addon.manifest['name']:
                 if addon.isDisabled:
                     isDisabled = True
                 if not addon.isPendingRemove:
                     addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating {name}").format(name=self.addonName),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error(
                 f"Error installing  addon bundle from {self.destPath}",
                 exc_info=True)
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             gui.messageBox(
                 # Translators: The message displayed when an error occurs when installing an add-on package.
                 _("Failed to update {name} add-on").format(
                     name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         else:
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             _updatedAddons.append(bundleName)
             if isDisabled:
                 for addon in addonHandler.getAvailableAddons():
                     if bundleName == addon.manifest[
                             'name'] and addon.isPendingInstall:
                         addon.enable(False)
                         break
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
     self.continueUpdatingAddons()