commit/placeMarkers: norrumar: Start implementation of skipTranslation procedure to get texts translated in NVDA, based on Alberto Buffolino implementation.

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Fri, 04 Nov 2016 06:30:43 -0000

1 new commit in placeMarkers:

https://bitbucket.org/nvdaaddonteam/placemarkers/commits/27a049b67ac8/
Changeset:   27a049b67ac8
Branch:      7.0
User:        norrumar
Date:        2016-11-04 06:30:24+00:00
Summary:     Start implementation of skipTranslation procedure to get texts 
translated in NVDA, based on Alberto Buffolino implementation.

Affected #:  3 files

diff --git a/addon/globalPlugins/placeMarkers.py 
b/addon/globalPlugins/placeMarkers.py
deleted file mode 100755
index c3b5da2..0000000
--- a/addon/globalPlugins/placeMarkers.py
+++ /dev/null
@@ -1,759 +0,0 @@
-# -*- coding: UTF-8 -*-
-# placeMarkers: Plugin to manage place markers based on positions or strings 
in specific documents
-#Copyright (C) 2012-2016 Noelia Ruiz Martínez
-# Released under GPL 2
-
-# Gestures sent to applications when add-on features are not applicable
-# Date: 1/09/2015
-# Changed key commands
-# Date: 27/02/2015
-# Removed Open documentation option from add-on menu, as suggested by Bernd 
Dorer
-# Date: 16/02/2015
-# Added case sensitive search
-# Date: 2/02/2015
-# Removed fragment identifiers in bookmark filenames
-# Date: 24/06/2014
-# Support for enhanced skim reading in version 2014.1.
-# Date: 13/03/2014
-# Support for skim reading.
-# Date: 28/10/2013
-# Assigned script categories for input gestures
-# Date: 12/10/2013
-# PlaceMarkers
-# Used decode("mbcs") instead of unicode in _basePath variable
-# Date: 21/09/2013
-# Added searched strings history
-# Date: 01/07/2013
-# Limited length of file names
-# Date: 04/05/2013
-# Added support for cyrillic characters
-# Date: 1/05/2013
-# Create placeMarkers folders if don't exist
-# Date: 25/04/2013
-# Added a different keystroke to delete bookmarks
-# Date: 16/04/2013
-# Version: 2.0: Added accValue in file names to use EPUBReader
-# Date: 31/03/2013
-# Version: 1.1
-# Date: 03/08/2012
-
-import addonHandler
-import globalPluginHandler
-import api
-import re
-import os
-import shutil
-import config
-import globalVars
-import languageHandler
-import textInfos
-import controlTypes
-import gui
-from gui import guiHelper
-import wx
-import ui
-import speech
-import cPickle
-import codecs
-import sayAllHandler
-from scriptHandler import willSayAllResume
-from cursorManager import CursorManager
-from logHandler import log
-
-addonHandler.initTranslation()
-
-_addonDir = os.path.join(os.path.dirname(__file__), "..") # The root of an 
addon folder
-_curAddon = addonHandler.Addon(_addonDir) # Addon instance
-_addonSummary = _curAddon.manifest['summary']
-_basePath = os.path.join(os.path.dirname(__file__), 
"placeMarkers").decode("mbcs")
-_searchFolder = os.path.join(_basePath, "search")
-_bookmarksFolder = os.path.join(_basePath, "bookmarks")
-_configPath = globalVars.appArgs.configPath
-
-def createSearchFolder():
-       if os.path.isdir(_searchFolder):
-               return
-       try:
-               os.makedirs(_searchFolder)
-       except Exception as e:
-               log.debugWarning("Error creating search folder", exc_info=True)
-               raise e
-
-def createBookmarksFolder():
-       if os.path.isdir(_bookmarksFolder):
-               return
-       try:
-               os.makedirs(_bookmarksFolder)
-       except Exception as e:
-               log.debugWarning("Error creating bookmarks folder", 
exc_info=True)
-               raise e
-
-createSearchFolder()
-createBookmarksFolder()
-
-def doFindText(text, reverse=False, caseSensitive=False):
-       if not text:
-               return
-       obj=api.getFocusObject()
-       treeInterceptor=obj.treeInterceptor
-       if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
-               obj=treeInterceptor
-               CursorManager._lastFindText=text
-               CursorManager._lastCaseSensitivity=caseSensitive
-       elif obj.role != controlTypes.ROLE_EDITABLETEXT:
-               return
-       try:
-               info=obj.makeTextInfo(textInfos.POSITION_CARET)
-       except (NotImplementedError, RuntimeError):
-               info=obj.makeTextInfo(textInfos.POSITION_FIRST)
-       try:
-               res=info.find(text,reverse=reverse, caseSensitive=caseSensitive)
-       except WindowsError:
-               wx.CallAfter(gui.messageBox,
-       # Translators: label of error dialog, translated in NVDA core.
-               _('text "%s" not found')%text,
-               # Translators: title of error dialog, translated in NVDA core.
-               _("Find Error"),
-               wx.OK|wx.ICON_ERROR)
-       except:
-               if api.copyToClip(text):
-                       # Translators: message presented when a string of text 
has been copied to the clipboard.
-                       ui.message(_("%s copied to clipboard") % text)
-               return
-       if res:
-               if hasattr(obj,'selection'):
-                       obj.selection=info
-               else:
-                       info.updateCaret()
-               speech.cancelSpeech()
-               info.move(textInfos.UNIT_LINE,1,endPoint="end")
-               speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
-       else:
-               wx.CallAfter(gui.messageBox,
-               # Translators: label of error dialog, translated in NVDA core.
-               _('text "%s" not found')%text,
-               # Translators: title of error dialog, translated in NVDA core.
-               _("Find Error"),
-               wx.OK|wx.ICON_ERROR)
-
-def doFindTextUp(text, caseSensitive=False):
-       doFindText(text, reverse=True, caseSensitive=caseSensitive)
-
-def standarFileName(fileName):
-       fileName.encode("mbcs")
-       notAllowed = re.compile("\?|:|\*|\t|<|>|\"|\/|\\||") # Invalid 
characters
-       allowed = re.sub(notAllowed, "", unicode(fileName))
-       return allowed
-
-def getFile(folder, ext=""):
-       obj=api.getForegroundObject()
-       file = obj.name
-       obj = api.getFocusObject()
-       try:
-               obj = obj.treeInterceptor.rootNVDAObject
-               childID = obj.IAccessibleChildID
-               iAObj = obj.IAccessibleObject
-               accValue = iAObj.accValue(childID)
-               nameToAdd = " - %s" % 
accValue.split("/")[-1].split("\\")[-1].split("#")[0]
-       except:
-               nameToAdd = ""
-       file = file.rsplit(" - ", 1)[0]
-       file = file.split("\\")[-1]
-       file += nameToAdd
-       file = standarFileName(file)
-       folderPath = os.path.join(_basePath, folder)
-       maxLenFileName = 232-len(folderPath)
-       if maxLenFileName <= 0:
-               return ""
-       file = file[:maxLenFileName]
-       file = file+ext
-       path = os.path.join(folderPath, file)
-       return path
-
-def getFileSearch():
-       return getFile("search", ".txt")
-
-def getSavedTexts():
-       searchFile = getFileSearch()
-       try:
-               with codecs.open(searchFile, "r", "utf-8") as f:
-                       savedStrings = f.read().split("\n")
-       except:
-               savedStrings = []
-       return savedStrings
-
-def getLastSpecificFindText():
-       try:
-               return getSavedTexts()[0]
-       except:
-               return ""
-
-class SpecificSearchDialog(wx.Dialog):
-
-       def __init__(self, parent):
-               # Translators: The title of the Specific Search dialog.
-               super(SpecificSearchDialog, self).__init__(parent, 
title=_("Specific search"))
-               self.searchFile = getFileSearch()
-               self.savedTexts = getSavedTexts()
-               mainSizer = wx.BoxSizer(wx.VERTICAL)
-               sHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
-               # Translators: The label of a combo box in the Specific Search 
dialog.
-               savedTextsLabel = _("&Saved texts")
-               self.savedTextsComboBox = 
sHelper.addLabeledControl(savedTextsLabel, wx.Choice, choices=self.savedTexts)
-               self.savedTextsComboBox.Bind(wx.EVT_CHOICE, 
self.onSavedTextsChange)
-               # Translators: A label for a chekbox in the Specific search 
dialog.
-               self.removeCheckBox = sHelper.addItem(wx.CheckBox(self, 
label=_("&Remove from history")))
-               self.removeCheckBox.Disable()
-               # Translators: The label of an edit box in the Specific Search 
dialog.
-               searchTextLabel = _("&Text to search:")
-               searchLabeledCtrl = gui.guiHelper.LabeledControlHelper(self, 
searchTextLabel, wx.TextCtrl)
-               self.searchTextEdit = searchLabeledCtrl.control
-               self.searchTextEdit.Value = getLastSpecificFindText()
-               self.searchTextEdit.Bind(wx.EVT_TEXT, 
self.onSearchEditTextChange)
-               # Translators: A label for a chekbox in the Specific search 
dialog.
-               self.addCheckBox = sHelper.addItem(wx.CheckBox(self, 
label=_("&Add to history")))
-                               # Translators: Label for a set of radio buttons 
in the Specific search dialog.
-               searchActionsLabel = _("Action on s&earch")
-               searchChoices = (
-                       # Translators: An action in the Search group of the 
Specific search dialog.
-                       _("Search &next"),
-                       # Translators: An action in the Search group of the 
Specific search dialog.
-                       _("Search &previous"),
-                       # Translators: An action in the Search group of the 
Specific search dialog.
-                       _("&Don't search"),
-               )
-               
self.searchRadioBox=sHelper.addItem(wx.RadioBox(self,label=searchActionsLabel, 
choices=searchChoices))
-               self.searchRadioBox.Bind(wx.EVT_RADIOBOX, self.onSearchRadioBox)
-               # Translators: A label for a chekbox in the Specific search 
dialog.
-               self.caseSensitiveCheckBox = sHelper.addItem(wx.CheckBox(self, 
label=_("&Case-sensitive search")))
-               
sHelper.addDialogDismissButtons(self.CreateButtonSizer(wx.OK|wx.CANCEL))
-               self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
-               mainSizer.Add(sHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
-               self.Sizer = mainSizer
-               mainSizer.Fit(self)
-               self.searchTextEdit.SetFocus()
-               if not self.searchTextEdit.Value:
-                       self.addCheckBox.Disable()
-                       self.searchRadioBox.Disable()
-                       self.caseSensitiveCheckBox.Disable()
-               self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
-
-       def onSearchEditTextChange(self, evt):
-               if self.searchTextEdit.Value:
-                       self.addCheckBox.Enable()
-                       self.searchRadioBox.Enable()
-                       self.caseSensitiveCheckBox.Enable()
-               else:
-                       self.addCheckBox.Disable()
-                       self.searchRadioBox.Disable()
-                       self.caseSensitiveCheckBox.Disable()
-
-       def onSavedTextsChange(self, evt):
-               self.searchTextEdit.Value = 
self.savedTextsComboBox.GetStringSelection()
-               self.removeCheckBox.Enable()
-
-       def onSearchRadioBox(self, evt):
-               if self.searchRadioBox.Selection == 2: # Don't search
-                       self.caseSensitiveCheckBox.Disable()
-
-       def onOk(self, evt):
-               self.Destroy()
-               if self.addCheckBox.Value or self.searchRadioBox.Selection < 2: 
# Add or search
-                       text = self.searchTextEdit.Value
-               actionToPerform = self.searchRadioBox.Selection
-               if actionToPerform < 2: # Search
-                       caseSensitive = self.caseSensitiveCheckBox.Value
-                       if actionToPerform == 0:
-                               wx.CallLater(100, doFindText, text, 
caseSensitive=caseSensitive)
-                       else:
-                               wx.CallLater(100, doFindTextUp, text, 
caseSensitive=caseSensitive)
-               if self.addCheckBox.Value or self.removeCheckBox.Value:
-                       savedStrings = self.savedTexts
-                       if self.removeCheckBox.Value:
-                               del 
savedStrings[self.savedTextsComboBox.Selection]
-                       if self.addCheckBox.Value and not "\n" in text and not 
text in savedStrings:
-                               savedStrings.insert(0, text)
-                       if len(savedStrings) == 0:
-                               os.remove(self.searchFile)
-                               return
-                       try:
-                               with codecs.open(self.searchFile, "w", "utf-8") 
as f:
-                                       f.write("\n".join(savedStrings))
-                       except Exception as e:
-                               log.debugWarning("Error saving strings of text 
for specific search", exc_info=True)
-                               raise e
-
-def doCopy(copyDirectory):
-       try:
-               shutil.rmtree(copyDirectory, ignore_errors=True)
-               shutil.copytree(_basePath, copyDirectory)
-       except Exception as e:
-               wx.CallAfter(gui.messageBox,
-               # Translators: label of error dialog shown when cannot copy 
placeMarkers folder.
-               _("Folder not copied"),
-               # Translators: title of error dialog shown when cannot copy 
placeMarkers folder.
-               _("Copy Error"),
-               wx.OK|wx.ICON_ERROR)
-               raise e
-
-def doRestore(restoreDirectory):
-       try:
-               shutil.rmtree(_basePath, ignore_errors=True)
-               shutil.copytree(restoreDirectory, _basePath)
-       except Exception as e:
-               wx.CallAfter(gui.messageBox,
-               # Translators: label of error dialog shown when cannot copy 
placeMarkers folder.
-               _("Folder not copied"),
-               # Translators: title of error dialog shown when cannot copy 
placeMarkers folder.
-               _("Copy Error"),
-               wx.OK|wx.ICON_ERROR)
-               raise e
-
-class CopyDialog(wx.Dialog):
-
-       def __init__(self, parent):
-               # Translators: The title of the Copy dialog.
-               super(CopyDialog, self).__init__(parent, title=_("Copy place 
markers"))
-
-               mainSizer = wx.BoxSizer(wx.VERTICAL)
-               sHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
-
-               # Translators: An informational message displayed in the Copy 
dialog.
-               dialogCaption=_("""Select a folder to save a backup of your 
current place markers.\n
-               They will be copied from %s.""" % _basePath)
-               sHelper.addItem(wx.StaticText(self, label=dialogCaption))
-
-               # Translators: The label of a grouping containing controls to 
select the destination directory in the Copy dialog.
-               directoryGroupText = _("directory for backup:")
-               groupHelper = 
sHelper.addItem(gui.guiHelper.BoxSizerHelper(self, 
sizer=wx.StaticBoxSizer(wx.StaticBox(self, label=directoryGroupText), 
wx.VERTICAL)))
-               # 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 copying place markers.
-               dirDialogTitle = _("Select directory to copy")
-               directoryEntryControl = 
groupHelper.addItem(gui.guiHelper.PathSelectionHelper(self, browseText, 
dirDialogTitle))
-               self.copyDirectoryEdit = directoryEntryControl.pathControl
-               self.copyDirectoryEdit.Value = os.path.join(_configPath, 
"placeMarkersBackup")
-               bHelper = 
sHelper.addDialogDismissButtons(gui.guiHelper.ButtonHelper(wx.HORIZONTAL))
-               continueButton = bHelper.addButton(self, label=_("&Continue"), 
id=wx.ID_OK)
-               continueButton.SetDefault()
-               continueButton.Bind(wx.EVT_BUTTON, self.onCopy)
-               bHelper.addButton(self, id=wx.ID_CANCEL)
-               mainSizer.Add(sHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
-               self.Sizer = mainSizer
-               mainSizer.Fit(self)
-               self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
-
-       def onCopy(self, evt):
-               if not self.copyDirectoryEdit.Value:
-                       # Translators: The message displayed when the user has 
not specified a destination directory in the Copy dialog.
-                       gui.messageBox(_("Please specify a directory."),
-                               _("Error"),
-                               wx.OK | wx.ICON_ERROR)
-                       return
-               drv=os.path.splitdrive(self.copyDirectoryEdit.Value)[0]
-               if drv and not os.path.isdir(drv):
-                       # Translators: The message displayed when the user 
specifies an invalid destination drive, translated in NVDA core.
-                       gui.messageBox(_("Invalid drive %s")%drv,
-                               _("Error"),
-                               wx.OK | wx.ICON_ERROR)
-                       return
-               self.Hide()
-               doCopy(self.copyDirectoryEdit.Value)
-               self.Destroy()
-
-       def onCancel(self, evt):
-               self.Destroy()
-
-class PathSelectionWithoutNewDir(gui.guiHelper.PathSelectionHelper):
-
-       def __init__(self, parent, buttonText, browseForDirectoryTitle):
-               super(PathSelectionWithoutNewDir, self).__init__(parent, 
buttonText, browseForDirectoryTitle)
-
-       def onBrowseForDirectory(self, evt):
-               startPath = self.getDefaultBrowseForDirectoryPath()
-               with wx.DirDialog(self._parent, self._browseForDirectoryTitle, 
defaultPath=startPath, style=wx.DD_DIR_MUST_EXIST | wx.DD_DEFAULT_STYLE) as d:
-                       if d.ShowModal() == wx.ID_OK:
-                               self._textCtrl.Value = d.Path
-
-class RestoreDialog(wx.Dialog):
-
-       def __init__(self, parent):
-               # Translators: The title of the Restore dialog.
-               super(RestoreDialog, self).__init__(parent, title=_("Restore 
place markers"))
-
-               mainSizer = wx.BoxSizer(wx.VERTICAL)
-               sHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
-
-               # Translators: An informational message displayed in the 
Restore dialog.
-               dialogCaption=_("""Select a folder to restore a backup of your 
previous copied place markers.\n
-               They will be copied to %s.""" % _basePath)
-               sHelper.addItem(wx.StaticText(self, label=dialogCaption))
-
-               # Translators: The label of a grouping containing controls to 
select the destination directory in the Restore dialog.
-               directoryGroupText = _("directory containing backup:")
-               groupHelper = 
sHelper.addItem(gui.guiHelper.BoxSizerHelper(self, 
sizer=wx.StaticBoxSizer(wx.StaticBox(self, label=directoryGroupText), 
wx.VERTICAL)))
-               # 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 restoring place markers.
-               dirDialogTitle = _("Select directory to restore")
-               directoryEntryControl = 
groupHelper.addItem(PathSelectionWithoutNewDir(self, browseText, 
dirDialogTitle))
-               self.restoreDirectoryEdit = directoryEntryControl.pathControl
-               backupDirectory = os.path.join(_configPath, 
"placeMarkersBackup")
-               if os.path.isdir(backupDirectory):
-                       self.restoreDirectoryEdit.Value = backupDirectory
-               bHelper = 
sHelper.addDialogDismissButtons(gui.guiHelper.ButtonHelper(wx.HORIZONTAL))
-               continueButton = bHelper.addButton(self, label=_("&Continue"), 
id=wx.ID_OK)
-               continueButton.SetDefault()
-               continueButton.Bind(wx.EVT_BUTTON, self.onRestore)
-               bHelper.addButton(self, id=wx.ID_CANCEL)
-               mainSizer.Add(sHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
-               self.Sizer = mainSizer
-               mainSizer.Fit(self)
-               self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
-
-       def onRestore(self, evt):
-               if not self.restoreDirectoryEdit.Value:
-                       # Translators: The message displayed when the user has 
not specified a destination directory in the Restore dialog.
-                       gui.messageBox(_("Please specify a directory."),
-                               _("Error"),
-                               wx.OK | wx.ICON_ERROR)
-                       return
-               drv=os.path.splitdrive(self.restoreDirectoryEdit.Value)[0]
-               if drv and not os.path.isdir(drv):
-                       # Translators: The message displayed when the user 
specifies an invalid destination drive, translated in NVDA core.
-                       gui.messageBox(_("Invalid drive %s")%drv,
-                               _("Error"),
-                               wx.OK | wx.ICON_ERROR)
-                       return
-               self.Hide()
-               doRestore(self.restoreDirectoryEdit.Value)
-               self.Destroy()
-
-       def onCancel(self, evt):
-               self.Destroy()
-
-class GlobalPlugin(globalPluginHandler.GlobalPlugin):
-
-       scriptCategory = unicode(_addonSummary)
-
-       def __init__(self):
-               super(globalPluginHandler.GlobalPlugin, self).__init__()
-               self.menu = gui.mainFrame.sysTrayIcon.preferencesMenu
-               #self.menu = gui.mainFrame.sysTrayIcon.menu
-               self.BSMenu = wx.Menu()
-               self.mainItem = self.menu.AppendSubMenu(self.BSMenu,
-               # Translators: the name of addon submenu.
-               _("P&lace markers"),
-               # Translators: the tooltip text for addon submenu.
-               _("Bookmarks and Search menu"))
-               self.searchItem = self.BSMenu.Append(wx.ID_ANY,
-               # Translators: the name for an item of addon submenu.
-               _("&Specific search folder"),
-               # Translators: the tooltip text for an item of addon submenu.
-               _("Opens the specific search folder"))
-               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, 
self.onSpecificSearch, self.searchItem)
-               self.bookmarksItem = self.BSMenu.Append(wx.ID_ANY,
-               # Translators: the name for an item of addon submenu.
-               _("&Bookmarks folder"),
-               # Translators: the tooltip text for an item of addon submenu.
-               _("Opens the bookmarks folder"))
-               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onBookmarks, 
self.bookmarksItem)
-               self.copyItem = self.BSMenu.Append(wx.ID_ANY,
-               # Translators: the name for an item of addon submenu.
-               _("&Copy placeMarkers folder..."),
-               # Translators: the tooltip text for an item of addon submenu.
-               _("Backup of place markers"))
-               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onCopy, 
self.copyItem)
-               self.restoreItem = self.BSMenu.Append(wx.ID_ANY,
-               # Translators: the name for an item of addon submenu.
-               _("R&estore place markers..."),
-               # Translators: the tooltip text for an item of addon submenu.
-               _("Restore previously saved place markers"))
-               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onRestore, 
self.restoreItem)
-               self._pickle = ""
-               self._states = []
-
-       def terminate(self):
-               try:
-                       self.menu.RemoveItem(self.mainItem)
-               except wx.PyDeadObjectError:
-                       pass
-
-       def onSpecificSearch(self, evt):
-               try:
-                       os.startfile(_searchFolder)
-               except WindowsError:
-                       pass
-
-       def script_openSpecificSearchFolder(self, gesture):
-               wx.CallAfter(self.onSpecificSearch, None)
-       script_openSpecificSearchFolder.__doc__ = _("Opens the specific search 
folder.")
-
-       def onBookmarks(self, evt):
-               try:
-                       os.startfile(_bookmarksFolder)
-               except WindowsError:
-                       pass
-
-       def script_openBookmarksFolder(self, gesture):
-               wx.CallAfter(self.onBookmarks, None)
-       script_openBookmarksFolder.__doc__ = _("Opens the bookmarks folder.")
-
-       def onCopy(self, evt):
-               gui.mainFrame.prePopup()
-               d = CopyDialog(gui.mainFrame)
-               d.Show()
-               gui.mainFrame.postPopup()
-
-       def script_activateCopyDialog(self, gesture):
-               wx.CallAfter(self.onCopy, None)
-       script_activateCopyDialog.__doc__ = _("Activates the Copy dialog of 
%s." % _addonSummary)
-
-       def onRestore(self, evt):
-               gui.mainFrame.prePopup()
-               d = RestoreDialog(gui.mainFrame)
-               d.Show()
-               gui.mainFrame.postPopup()
-
-       def script_activateRestoreDialog(self, gesture):
-               wx.CallAfter(self.onRestore, None)
-       script_activateRestoreDialog.__doc__ = _("Activates the Restore dialog 
of %s." % _addonSummary)
-
-       def popupSpecificSearchDialog(self):
-               if gui.isInMessageBox:
-                       return
-               gui.mainFrame.prePopup()
-               d = SpecificSearchDialog(gui.mainFrame)
-               d.Show()
-               gui.mainFrame.postPopup()
-
-       def script_specificFind(self,gesture):
-               obj=api.getFocusObject()
-               if not controlTypes.STATE_MULTILINE in obj.states:
-                       treeInterceptor=obj.treeInterceptor
-                       if not (hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough):
-                               gesture.send()
-                               return
-               wx.CallAfter(self.popupSpecificSearchDialog)
-       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
-       script_specificFind.__doc__ = _("finds a text string from the current 
cursor position for a specific document.")
-
-       def getStates(self):
-               self.getPickle()
-               fileName = self._pickle
-               try:
-                       self._states = cPickle.load(file(fileName, "r"))
-               except IOError:
-                       self._states = []
-
-       def getPickle(self):
-               self._pickle = getFile("bookmarks", ".pickle")
-
-       def script_saveBookmark(self, gesture):
-               obj = api.getFocusObject()
-               treeInterceptor=obj.treeInterceptor
-               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
-                       obj=treeInterceptor
-               else:
-                       gesture.send()
-                       return
-               self.getStates()
-               fileName = self._pickle
-               start = obj.makeTextInfo(textInfos.POSITION_ALL)
-               try:
-                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
-               except (NotImplementedError, RuntimeError):
-                       ui.message(
-                       # Translators: message presented when a bookmark cannot 
be saved.
-                       _("Bookmark cannot be saved"))
-                       return
-               start.setEndPoint(end, "endToStart")
-               count = len(start.text)
-               if count in self._states:
-                       ui.message(
-                       # Translators: message presented when the current 
position was previously saved as a bookmark.
-                       _("This position was already saved"))
-                       return
-               self._states.append(count)
-               self._states.sort()
-               try:
-                       cPickle.dump(self._states, file(fileName, "wb"))
-                       ui.message(
-                       # Translators: message presented when a position is 
saved as a bookmark.
-                       _("Saved position at character %d") %count)
-               except Exception as e:
-                       log.debugWarning("Error saving bookmark", exc_info=True)
-                       ui.message(
-                       # Translators: message presented when a bookmark cannot 
be saved.
-                       _("Cannot save bookmark"))
-                       raise e
-       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
-       script_saveBookmark.__doc__ = _("Saves the current position as a 
bookmark.")
-
-       def script_deleteBookmark(self, gesture):
-               obj = api.getFocusObject()
-               treeInterceptor=obj.treeInterceptor
-               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
-                       obj=treeInterceptor
-               else:
-                       gesture.send()
-                       return
-               self.getStates()
-               if len(self._states) == 0:
-                       ui.message(
-                       # Translators: message presented when the current 
document doesn't contain bookmarks.
-                       _("No bookmarks"))
-                       return
-               fileName = self._pickle
-               start = obj.makeTextInfo(textInfos.POSITION_ALL)
-               try:
-                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
-               except (NotImplementedError, RuntimeError):
-                       ui.message(_("Bookmark cannot be deleted"))
-                       return
-               start.setEndPoint(end, "endToStart")
-               count = len(start.text)
-               if count not in self._states:
-                       ui.message(
-                       # Translators: message presented when the current 
document has bookmarks, but none is selected.
-                       _("No bookmark selected"))
-                       return
-               self._states.remove(count)
-               if len(self._states) > 0:
-                       self._states.sort()
-                       try:
-                               cPickle.dump(self._states, file(fileName, "wb"))
-                               ui.message(
-                               # Translators: message presented when a 
bookmark is deleted.
-                               _("Bookmark deleted"))
-                               return
-                       except:
-                               pass
-               else:
-                       try:
-                               os.remove(fileName)
-                               ui.message(_
-                               # Translators: message presented when the 
current document doesn't contain bookmarks.
-                               ("No bookmarks"))
-                               return
-                       except WindowsError:
-                               pass
-               log.debugWarning("Error saving bookmarks", exc_info=True)
-               ui.message(
-               # Translators: message presented when cannot delete a bookmark.
-               _("Cannot delete bookmark"))
-       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
-       script_deleteBookmark.__doc__ = _("Deletes the current bookmark.")
-
-       def script_selectNextBookmark(self, gesture):
-               obj = api.getFocusObject()
-               treeInterceptor=obj.treeInterceptor
-               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
-                       obj=treeInterceptor
-               else:
-                       gesture.send()
-                       return
-               self.getStates()
-               if len(self._states) == 0:
-                       ui.message(
-                       # Translators: message presented when trying to select 
a bookmark, but none is found.
-                       _("No bookmarks found"))
-                       return
-               start = obj.makeTextInfo(textInfos.POSITION_ALL)
-               try:
-                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
-               except (NotImplementedError, RuntimeError):
-                       ui.message(
-                       # Translators: message presented when cannot find any 
bookmark.
-                       _("Cannot find any bookmark"))
-                       return
-               start.setEndPoint(end, "endToStart")
-               count = len(start.text)
-               for bookmark in self._states:
-                       if bookmark > count:
-                               end.move(textInfos.UNIT_CHARACTER, 
bookmark-count)
-                               obj.selection = end
-                               if not willSayAllResume(gesture):
-                                       
end.move(textInfos.UNIT_LINE,1,endPoint="end")
-                                       
speech.speakTextInfo(end,reason=controlTypes.REASON_CARET)
-                                       ui.message(
-                                       # Translators: message presented when a 
bookmark is selected.
-                                       _("Position: character %d") % bookmark)
-                               return
-               ui.message(
-               # Translators: message presented when the next bookmark is not 
found.
-               _("Next bookmark not found"))
-       script_selectNextBookmark.resumeSayAllMode=sayAllHandler.CURSOR_CARET
-       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
-       script_selectNextBookmark.__doc__ = _("Moves to the next bookmark.")
-
-       def script_selectPreviousBookmark(self, gesture):
-               obj = api.getFocusObject()
-               treeInterceptor=obj.treeInterceptor
-               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
-                       obj=treeInterceptor
-               else:
-                       gesture.send()
-                       return
-               self.getStates()
-               if len(self._states) == 0:
-                       ui.message(
-                       # Translators: message presented when trying to select 
a bookmark, but none is found.
-                       _("No bookmarks found"))
-                       return
-               start = obj.makeTextInfo(textInfos.POSITION_ALL)
-               try:
-                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
-               except (NotImplementedError, RuntimeError):
-               # Translators: message presented when cannot find any bookmark.
-                       ui.message(_("Cannot find any bookmark"))
-                       return
-               start.setEndPoint(end, "endToStart")
-               count = len(start.text)
-               bookmarkList = self._states
-               bookmarkList.reverse()
-               for bookmark in bookmarkList:
-                       if bookmark < count:
-                               end.move(textInfos.UNIT_CHARACTER, 
bookmark-count)
-                               obj.selection = end
-                               if not willSayAllResume(gesture):
-                                       
end.move(textInfos.UNIT_LINE,1,endPoint="end")
-                                       
speech.speakTextInfo(end,reason=controlTypes.REASON_CARET)
-                                       ui.message(
-                                       # Translators: message presented when a 
bookmark is selected.
-                                       _("Position: character %d") % bookmark)
-                               return
-               ui.message(
-               # Translators: message presented when the previous bookmark is 
not found.
-               _("Previous bookmark not found"))
-       
script_selectPreviousBookmark.resumeSayAllMode=sayAllHandler.CURSOR_CARET
-       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
-       script_selectPreviousBookmark.__doc__ = _("Moves to the previous 
bookmark.")
-
-       def script_copyCurrentBookmarksFile(self, gesture):
-               obj=api.getFocusObject()
-               if not controlTypes.STATE_MULTILINE in obj.states:
-                       treeInterceptor=obj.treeInterceptor
-                       if not (hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough) and controlTypes.STATE_MULTILINE not in obj.states:
-                               gesture.send()
-                               return
-               fileName = getFile("bookmarks")
-               if not api.copyToClip(os.path.basename(fileName)):
-                       ui.message(
-                       # Translators: message presented when cannot copy the 
file name corresponding to place markers.
-                       _("Cannot copy file name for place markers"))
-                       return
-               ui.message(
-               # Translators: message presented when file name for place 
markers is copied to clipboard.
-               _("Place markers file name copied to clipboard"))
-                       # Translators: message presented in input mode, when a 
keystroke of an addon script is pressed.
-       script_copyCurrentBookmarksFile.__doc__ = _("Copies the name of the 
current file for place markers to the clipboard.")
-
-       __gestures = {
-               "kb:control+shift+NVDA+f": "specificFind",
-               "kb:control+shift+NVDA+k": "saveBookmark",
-               "kb:control+shift+NVDA+delete": "deleteBookmark",
-               "kb:NVDA+k": "selectNextBookmark",
-               "kb:shift+NVDA+k": "selectPreviousBookmark",
-               "kb:control+shift+k": "copyCurrentBookmarksFile",
-       }

diff --git a/addon/globalPlugins/placeMarkers/__init__.py 
b/addon/globalPlugins/placeMarkers/__init__.py
new file mode 100644
index 0000000..5737beb
--- /dev/null
+++ b/addon/globalPlugins/placeMarkers/__init__.py
@@ -0,0 +1,761 @@
+# -*- coding: UTF-8 -*-
+# placeMarkers: Plugin to manage place markers based on positions or strings 
in specific documents
+#Copyright (C) 2012-2016 Noelia Ruiz Martínez
+# Released under GPL 2
+
+# Gestures sent to applications when add-on features are not applicable
+# Date: 1/09/2015
+# Changed key commands
+# Date: 27/02/2015
+# Removed Open documentation option from add-on menu, as suggested by Bernd 
Dorer
+# Date: 16/02/2015
+# Added case sensitive search
+# Date: 2/02/2015
+# Removed fragment identifiers in bookmark filenames
+# Date: 24/06/2014
+# Support for enhanced skim reading in version 2014.1.
+# Date: 13/03/2014
+# Support for skim reading.
+# Date: 28/10/2013
+# Assigned script categories for input gestures
+# Date: 12/10/2013
+# PlaceMarkers
+# Used decode("mbcs") instead of unicode in _basePath variable
+# Date: 21/09/2013
+# Added searched strings history
+# Date: 01/07/2013
+# Limited length of file names
+# Date: 04/05/2013
+# Added support for cyrillic characters
+# Date: 1/05/2013
+# Create placeMarkers folders if don't exist
+# Date: 25/04/2013
+# Added a different keystroke to delete bookmarks
+# Date: 16/04/2013
+# Version: 2.0: Added accValue in file names to use EPUBReader
+# Date: 31/03/2013
+# Version: 1.1
+# Date: 03/08/2012
+
+import addonHandler
+import globalPluginHandler
+import api
+import re
+import os
+import shutil
+import config
+import globalVars
+import languageHandler
+import textInfos
+import controlTypes
+import gui
+from gui import guiHelper
+import wx
+import ui
+import speech
+import cPickle
+import codecs
+import sayAllHandler
+from scriptHandler import willSayAllResume
+from cursorManager import CursorManager
+from logHandler import log
+from skipTranslation import translate
+
+addonHandler.initTranslation()
+
+_addonDir = os.path.join(os.path.dirname(__file__), "..", "..") # The root of 
an addon folder
+_curAddon = addonHandler.Addon(_addonDir) # Addon instance
+_addonSummary = _curAddon.manifest['summary']
+_basePath = os.path.join(os.path.dirname(__file__), 
"savedPlaceMarkers").decode("mbcs")
+_searchFolder = os.path.join(_basePath, "search")
+_bookmarksFolder = os.path.join(_basePath, "bookmarks")
+_configPath = globalVars.appArgs.configPath
+
+def createSearchFolder():
+       if os.path.isdir(_searchFolder):
+               return
+       try:
+               os.makedirs(_searchFolder)
+       except Exception as e:
+               log.debugWarning("Error creating search folder", exc_info=True)
+               raise e
+
+def createBookmarksFolder():
+       if os.path.isdir(_bookmarksFolder):
+               return
+       try:
+               os.makedirs(_bookmarksFolder)
+       except Exception as e:
+               log.debugWarning("Error creating bookmarks folder", 
exc_info=True)
+               raise e
+
+createSearchFolder()
+createBookmarksFolder()
+
+def doFindText(text, reverse=False, caseSensitive=False):
+       if not text:
+               return
+       obj=api.getFocusObject()
+       treeInterceptor=obj.treeInterceptor
+       if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
+               obj=treeInterceptor
+               CursorManager._lastFindText=text
+               CursorManager._lastCaseSensitivity=caseSensitive
+       elif obj.role != controlTypes.ROLE_EDITABLETEXT:
+               return
+       try:
+               info=obj.makeTextInfo(textInfos.POSITION_CARET)
+       except (NotImplementedError, RuntimeError):
+               info=obj.makeTextInfo(textInfos.POSITION_FIRST)
+       try:
+               res=info.find(text,reverse=reverse, caseSensitive=caseSensitive)
+       except WindowsError:
+               wx.CallAfter(gui.messageBox,
+       # Translators: label of error dialog, translated in NVDA core.
+               _('text "%s" not found')%text,
+               # Translators: title of error dialog, translated in NVDA core.
+               _("Find Error"),
+               wx.OK|wx.ICON_ERROR)
+       except:
+               if api.copyToClip(text):
+                       # Translators: message presented when a string of text 
has been copied to the clipboard.
+                       ui.message(_("%s copied to clipboard") % text)
+               return
+       if res:
+               if hasattr(obj,'selection'):
+                       obj.selection=info
+               else:
+                       info.updateCaret()
+               speech.cancelSpeech()
+               info.move(textInfos.UNIT_LINE,1,endPoint="end")
+               speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
+       else:
+               wx.CallAfter(gui.messageBox,
+               # Translators: label of error dialog, translated in NVDA core.
+               _('text "%s" not found')%text,
+               # Translators: title of error dialog, translated in NVDA core.
+               _("Find Error"),
+               wx.OK|wx.ICON_ERROR)
+
+def doFindTextUp(text, caseSensitive=False):
+       doFindText(text, reverse=True, caseSensitive=caseSensitive)
+
+def standarFileName(fileName):
+       fileName.encode("mbcs")
+       notAllowed = re.compile("\?|:|\*|\t|<|>|\"|\/|\\||") # Invalid 
characters
+       allowed = re.sub(notAllowed, "", unicode(fileName))
+       return allowed
+
+def getFile(folder, ext=""):
+       obj=api.getForegroundObject()
+       file = obj.name
+       obj = api.getFocusObject()
+       try:
+               obj = obj.treeInterceptor.rootNVDAObject
+               childID = obj.IAccessibleChildID
+               iAObj = obj.IAccessibleObject
+               accValue = iAObj.accValue(childID)
+               nameToAdd = " - %s" % 
accValue.split("/")[-1].split("\\")[-1].split("#")[0]
+       except:
+               nameToAdd = ""
+       file = file.rsplit(" - ", 1)[0]
+       file = file.split("\\")[-1]
+       file += nameToAdd
+       file = standarFileName(file)
+       folderPath = os.path.join(_basePath, folder)
+       maxLenFileName = 232-len(folderPath)
+       if maxLenFileName <= 0:
+               return ""
+       file = file[:maxLenFileName]
+       file = file+ext
+       path = os.path.join(folderPath, file)
+       return path
+
+def getFileSearch():
+       return getFile("search", ".txt")
+
+def getSavedTexts():
+       searchFile = getFileSearch()
+       try:
+               with codecs.open(searchFile, "r", "utf-8") as f:
+                       savedStrings = f.read().split("\n")
+       except:
+               savedStrings = []
+       return savedStrings
+
+def getLastSpecificFindText():
+       try:
+               return getSavedTexts()[0]
+       except:
+               return ""
+
+class SpecificSearchDialog(wx.Dialog):
+
+       def __init__(self, parent):
+               # Translators: The title of the Specific Search dialog.
+               super(SpecificSearchDialog, self).__init__(parent, 
title=_("Specific search"))
+               self.searchFile = getFileSearch()
+               self.savedTexts = getSavedTexts()
+               mainSizer = wx.BoxSizer(wx.VERTICAL)
+               sHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+               # Translators: The label of a combo box in the Specific Search 
dialog.
+               savedTextsLabel = _("&Saved texts")
+               self.savedTextsComboBox = 
sHelper.addLabeledControl(savedTextsLabel, wx.Choice, choices=self.savedTexts)
+               self.savedTextsComboBox.Bind(wx.EVT_CHOICE, 
self.onSavedTextsChange)
+               # Translators: A label for a chekbox in the Specific search 
dialog.
+               self.removeCheckBox = sHelper.addItem(wx.CheckBox(self, 
label=_("&Remove from history")))
+               self.removeCheckBox.Disable()
+               # Translators: The label of an edit box in the Specific Search 
dialog.
+               searchTextLabel = _("&Text to search:")
+               searchLabeledCtrl = gui.guiHelper.LabeledControlHelper(self, 
searchTextLabel, wx.TextCtrl)
+               self.searchTextEdit = searchLabeledCtrl.control
+               self.searchTextEdit.Value = getLastSpecificFindText()
+               self.searchTextEdit.Bind(wx.EVT_TEXT, 
self.onSearchEditTextChange)
+               # Translators: A label for a chekbox in the Specific search 
dialog.
+               self.addCheckBox = sHelper.addItem(wx.CheckBox(self, 
label=_("&Add to history")))
+                               # Translators: Label for a set of radio buttons 
in the Specific search dialog.
+               searchActionsLabel = _("Action on s&earch")
+               searchChoices = (
+                       # Translators: An action in the Search group of the 
Specific search dialog.
+                       _("Search &next"),
+                       # Translators: An action in the Search group of the 
Specific search dialog.
+                       _("Search &previous"),
+                       # Translators: An action in the Search group of the 
Specific search dialog.
+                       _("&Don't search"),
+               )
+               
self.searchRadioBox=sHelper.addItem(wx.RadioBox(self,label=searchActionsLabel, 
choices=searchChoices))
+               self.searchRadioBox.Bind(wx.EVT_RADIOBOX, self.onSearchRadioBox)
+               # Translators: A label for a chekbox in the Specific search 
dialog.
+               self.caseSensitiveCheckBox = sHelper.addItem(wx.CheckBox(self, 
label=_("&Case-sensitive search")))
+               
sHelper.addDialogDismissButtons(self.CreateButtonSizer(wx.OK|wx.CANCEL))
+               self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK)
+               mainSizer.Add(sHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               self.Sizer = mainSizer
+               mainSizer.Fit(self)
+               self.searchTextEdit.SetFocus()
+               if not self.searchTextEdit.Value:
+                       self.addCheckBox.Disable()
+                       self.searchRadioBox.Disable()
+                       self.caseSensitiveCheckBox.Disable()
+               self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+
+       def onSearchEditTextChange(self, evt):
+               if self.searchTextEdit.Value:
+                       self.addCheckBox.Enable()
+                       self.searchRadioBox.Enable()
+                       self.caseSensitiveCheckBox.Enable()
+               else:
+                       self.addCheckBox.Disable()
+                       self.searchRadioBox.Disable()
+                       self.caseSensitiveCheckBox.Disable()
+
+       def onSavedTextsChange(self, evt):
+               self.searchTextEdit.Value = 
self.savedTextsComboBox.GetStringSelection()
+               self.removeCheckBox.Enable()
+
+       def onSearchRadioBox(self, evt):
+               if self.searchRadioBox.Selection == 2: # Don't search
+                       self.caseSensitiveCheckBox.Disable()
+
+       def onOk(self, evt):
+               self.Destroy()
+               if self.addCheckBox.Value or self.searchRadioBox.Selection < 2: 
# Add or search
+                       text = self.searchTextEdit.Value
+               actionToPerform = self.searchRadioBox.Selection
+               if actionToPerform < 2: # Search
+                       caseSensitive = self.caseSensitiveCheckBox.Value
+                       if actionToPerform == 0:
+                               wx.CallLater(100, doFindText, text, 
caseSensitive=caseSensitive)
+                       else:
+                               wx.CallLater(100, doFindTextUp, text, 
caseSensitive=caseSensitive)
+               if self.addCheckBox.Value or self.removeCheckBox.Value:
+                       savedStrings = self.savedTexts
+                       if self.removeCheckBox.Value:
+                               del 
savedStrings[self.savedTextsComboBox.Selection]
+                       if self.addCheckBox.Value and not "\n" in text and not 
text in savedStrings:
+                               savedStrings.insert(0, text)
+                       if len(savedStrings) == 0:
+                               os.remove(self.searchFile)
+                               return
+                       try:
+                               with codecs.open(self.searchFile, "w", "utf-8") 
as f:
+                                       f.write("\n".join(savedStrings))
+                       except Exception as e:
+                               log.debugWarning("Error saving strings of text 
for specific search", exc_info=True)
+                               raise e
+
+def doCopy(copyDirectory):
+       try:
+               shutil.rmtree(copyDirectory, ignore_errors=True)
+               shutil.copytree(_basePath, copyDirectory)
+       except Exception as e:
+               wx.CallAfter(gui.messageBox,
+               # Translators: label of error dialog shown when cannot copy 
placeMarkers folder.
+               _("Folder not copied"),
+               # Translators: title of error dialog shown when cannot copy 
placeMarkers folder.
+               _("Copy Error"),
+               wx.OK|wx.ICON_ERROR)
+               raise e
+
+def doRestore(restoreDirectory):
+       try:
+               shutil.rmtree(_basePath, ignore_errors=True)
+               shutil.copytree(restoreDirectory, _basePath)
+       except Exception as e:
+               wx.CallAfter(gui.messageBox,
+               # Translators: label of error dialog shown when cannot copy 
placeMarkers folder.
+               _("Folder not copied"),
+               # Translators: title of error dialog shown when cannot copy 
placeMarkers folder.
+               _("Copy Error"),
+               wx.OK|wx.ICON_ERROR)
+               raise e
+
+class CopyDialog(wx.Dialog):
+
+       def __init__(self, parent):
+               # Translators: The title of the Copy dialog.
+               super(CopyDialog, self).__init__(parent, title=_("Copy place 
markers"))
+
+               mainSizer = wx.BoxSizer(wx.VERTICAL)
+               sHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+
+               # Translators: An informational message displayed in the Copy 
dialog.
+               dialogCaption=_("""Select a folder to save a backup of your 
current place markers.\n
+               They will be copied from %s.""" % _basePath)
+               sHelper.addItem(wx.StaticText(self, label=dialogCaption))
+
+               # Translators: The label of a grouping containing controls to 
select the destination directory in the Copy dialog.
+               directoryGroupText = _("directory for backup:")
+               groupHelper = 
sHelper.addItem(gui.guiHelper.BoxSizerHelper(self, 
sizer=wx.StaticBoxSizer(wx.StaticBox(self, label=directoryGroupText), 
wx.VERTICAL)))
+               # 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 copying place markers.
+               dirDialogTitle = _("Select directory to copy")
+               directoryEntryControl = 
groupHelper.addItem(gui.guiHelper.PathSelectionHelper(self, browseText, 
dirDialogTitle))
+               self.copyDirectoryEdit = directoryEntryControl.pathControl
+               self.copyDirectoryEdit.Value = os.path.join(_configPath, 
"placeMarkersBackup")
+               bHelper = 
sHelper.addDialogDismissButtons(gui.guiHelper.ButtonHelper(wx.HORIZONTAL))
+               continueButton = bHelper.addButton(self, 
label=translate("&Continue"), id=wx.ID_OK)
+               continueButton.SetDefault()
+               continueButton.Bind(wx.EVT_BUTTON, self.onCopy)
+               bHelper.addButton(self, id=wx.ID_CANCEL)
+               mainSizer.Add(sHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               self.Sizer = mainSizer
+               mainSizer.Fit(self)
+               self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+
+       def onCopy(self, evt):
+               if not self.copyDirectoryEdit.Value:
+                       # Translators: The message displayed when the user has 
not specified a destination directory in the Copy dialog.
+                       gui.messageBox(_("Please specify a directory."),
+                               _("Error"),
+                               wx.OK | wx.ICON_ERROR)
+                       return
+               drv=os.path.splitdrive(self.copyDirectoryEdit.Value)[0]
+               if drv and not os.path.isdir(drv):
+                       # Translators: The message displayed when the user 
specifies an invalid destination drive, translated in NVDA core.
+                       gui.messageBox(_("Invalid drive %s")%drv,
+                               _("Error"),
+                               wx.OK | wx.ICON_ERROR)
+                       return
+               self.Hide()
+               doCopy(self.copyDirectoryEdit.Value)
+               self.Destroy()
+
+       def onCancel(self, evt):
+               self.Destroy()
+
+class PathSelectionWithoutNewDir(gui.guiHelper.PathSelectionHelper):
+
+       def __init__(self, parent, buttonText, browseForDirectoryTitle):
+               super(PathSelectionWithoutNewDir, self).__init__(parent, 
buttonText, browseForDirectoryTitle)
+
+       def onBrowseForDirectory(self, evt):
+               startPath = self.getDefaultBrowseForDirectoryPath()
+               with wx.DirDialog(self._parent, self._browseForDirectoryTitle, 
defaultPath=startPath, style=wx.DD_DIR_MUST_EXIST | wx.DD_DEFAULT_STYLE) as d:
+                       if d.ShowModal() == wx.ID_OK:
+                               self._textCtrl.Value = d.Path
+
+class RestoreDialog(wx.Dialog):
+
+       def __init__(self, parent):
+               # Translators: The title of the Restore dialog.
+               super(RestoreDialog, self).__init__(parent, title=_("Restore 
place markers"))
+
+               mainSizer = wx.BoxSizer(wx.VERTICAL)
+               sHelper = gui.guiHelper.BoxSizerHelper(self, 
orientation=wx.VERTICAL)
+
+               # Translators: An informational message displayed in the 
Restore dialog.
+               dialogCaption=_("""Select a folder to restore a backup of your 
previous copied place markers.\n
+               They will be copied to %s.""" % _basePath)
+               sHelper.addItem(wx.StaticText(self, label=dialogCaption))
+
+               # Translators: The label of a grouping containing controls to 
select the destination directory in the Restore dialog.
+               directoryGroupText = _("directory containing backup:")
+               groupHelper = 
sHelper.addItem(gui.guiHelper.BoxSizerHelper(self, 
sizer=wx.StaticBoxSizer(wx.StaticBox(self, label=directoryGroupText), 
wx.VERTICAL)))
+               # 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 restoring place markers.
+               dirDialogTitle = _("Select directory to restore")
+               directoryEntryControl = 
groupHelper.addItem(PathSelectionWithoutNewDir(self, browseText, 
dirDialogTitle))
+               self.restoreDirectoryEdit = directoryEntryControl.pathControl
+               backupDirectory = os.path.join(_configPath, 
"placeMarkersBackup")
+               if os.path.isdir(backupDirectory):
+                       self.restoreDirectoryEdit.Value = backupDirectory
+               bHelper = 
sHelper.addDialogDismissButtons(gui.guiHelper.ButtonHelper(wx.HORIZONTAL))
+               continueButton = bHelper.addButton(self, label=_("&Continue"), 
id=wx.ID_OK)
+               continueButton.SetDefault()
+               continueButton.Bind(wx.EVT_BUTTON, self.onRestore)
+               bHelper.addButton(self, id=wx.ID_CANCEL)
+               mainSizer.Add(sHelper.sizer, 
border=gui.guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
+               self.Sizer = mainSizer
+               mainSizer.Fit(self)
+               self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
+
+       def onRestore(self, evt):
+               if not self.restoreDirectoryEdit.Value:
+                       # Translators: The message displayed when the user has 
not specified a destination directory in the Restore dialog.
+                       gui.messageBox(_("Please specify a directory."),
+                               _("Error"),
+                               wx.OK | wx.ICON_ERROR)
+                       return
+               drv=os.path.splitdrive(self.restoreDirectoryEdit.Value)[0]
+               if drv and not os.path.isdir(drv):
+                       # Translators: The message displayed when the user 
specifies an invalid destination drive, translated in NVDA core.
+                       gui.messageBox(_("Invalid drive %s")%drv,
+                               _("Error"),
+                               wx.OK | wx.ICON_ERROR)
+                       return
+               self.Hide()
+               doRestore(self.restoreDirectoryEdit.Value)
+               self.Destroy()
+
+       def onCancel(self, evt):
+               self.Destroy()
+
+class GlobalPlugin(globalPluginHandler.GlobalPlugin):
+
+       scriptCategory = unicode(_addonSummary)
+
+       def __init__(self):
+               super(globalPluginHandler.GlobalPlugin, self).__init__()
+               self.menu = gui.mainFrame.sysTrayIcon.preferencesMenu
+               #self.menu = gui.mainFrame.sysTrayIcon.menu
+               self.BSMenu = wx.Menu()
+               self.mainItem = self.menu.AppendSubMenu(self.BSMenu,
+               # Translators: the name of addon submenu.
+               _("P&lace markers"),
+               # Translators: the tooltip text for addon submenu.
+               _("Bookmarks and Search menu"))
+               self.searchItem = self.BSMenu.Append(wx.ID_ANY,
+               # Translators: the name for an item of addon submenu.
+               _("&Specific search folder"),
+               # Translators: the tooltip text for an item of addon submenu.
+               _("Opens the specific search folder"))
+               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, 
self.onSpecificSearch, self.searchItem)
+               self.bookmarksItem = self.BSMenu.Append(wx.ID_ANY,
+               # Translators: the name for an item of addon submenu.
+               _("&Bookmarks folder"),
+               # Translators: the tooltip text for an item of addon submenu.
+               _("Opens the bookmarks folder"))
+               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onBookmarks, 
self.bookmarksItem)
+               self.copyItem = self.BSMenu.Append(wx.ID_ANY,
+               # Translators: the name for an item of addon submenu.
+               _("&Copy placeMarkers folder..."),
+               # Translators: the tooltip text for an item of addon submenu.
+               _("Backup of place markers"))
+               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onCopy, 
self.copyItem)
+               self.restoreItem = self.BSMenu.Append(wx.ID_ANY,
+               # Translators: the name for an item of addon submenu.
+               _("R&estore place markers..."),
+               # Translators: the tooltip text for an item of addon submenu.
+               _("Restore previously saved place markers"))
+               gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onRestore, 
self.restoreItem)
+               self._pickle = ""
+               self._states = []
+
+       def terminate(self):
+               try:
+                       self.menu.RemoveItem(self.mainItem)
+               except wx.PyDeadObjectError:
+                       pass
+
+       def onSpecificSearch(self, evt):
+               try:
+                       os.startfile(_searchFolder)
+               except WindowsError:
+                       pass
+
+       def script_openSpecificSearchFolder(self, gesture):
+               wx.CallAfter(self.onSpecificSearch, None)
+       script_openSpecificSearchFolder.__doc__ = _("Opens the specific search 
folder.")
+
+       def onBookmarks(self, evt):
+               try:
+                       os.startfile(_bookmarksFolder)
+               except WindowsError:
+                       pass
+
+       def script_openBookmarksFolder(self, gesture):
+               wx.CallAfter(self.onBookmarks, None)
+       script_openBookmarksFolder.__doc__ = _("Opens the bookmarks folder.")
+
+       def onCopy(self, evt):
+               gui.mainFrame.prePopup()
+               d = CopyDialog(gui.mainFrame)
+               d.Show()
+               gui.mainFrame.postPopup()
+
+       def script_activateCopyDialog(self, gesture):
+               wx.CallAfter(self.onCopy, None)
+       script_activateCopyDialog.__doc__ = _("Activates the Copy dialog of 
%s." % _addonSummary)
+
+       def onRestore(self, evt):
+               gui.mainFrame.prePopup()
+               d = RestoreDialog(gui.mainFrame)
+               d.Show()
+               gui.mainFrame.postPopup()
+
+       def script_activateRestoreDialog(self, gesture):
+               wx.CallAfter(self.onRestore, None)
+       script_activateRestoreDialog.__doc__ = _("Activates the Restore dialog 
of %s." % _addonSummary)
+
+       def popupSpecificSearchDialog(self):
+               if gui.isInMessageBox:
+                       return
+               gui.mainFrame.prePopup()
+               d = SpecificSearchDialog(gui.mainFrame)
+               d.Show()
+               gui.mainFrame.postPopup()
+
+       def script_specificFind(self,gesture):
+               obj=api.getFocusObject()
+               if not controlTypes.STATE_MULTILINE in obj.states:
+                       treeInterceptor=obj.treeInterceptor
+                       if not (hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough):
+                               gesture.send()
+                               return
+               wx.CallAfter(self.popupSpecificSearchDialog)
+       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
+       script_specificFind.__doc__ = _("finds a text string from the current 
cursor position for a specific document.")
+
+       def getStates(self):
+               self.getPickle()
+               fileName = self._pickle
+               try:
+                       self._states = cPickle.load(file(fileName, "r"))
+               except IOError:
+                       self._states = []
+
+       def getPickle(self):
+               self._pickle = getFile("bookmarks", ".pickle")
+
+       def script_saveBookmark(self, gesture):
+               obj = api.getFocusObject()
+               treeInterceptor=obj.treeInterceptor
+               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
+                       obj=treeInterceptor
+               else:
+                       gesture.send()
+                       return
+               self.getStates()
+               fileName = self._pickle
+               start = obj.makeTextInfo(textInfos.POSITION_ALL)
+               try:
+                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
+               except (NotImplementedError, RuntimeError):
+                       ui.message(
+                       # Translators: message presented when a bookmark cannot 
be saved.
+                       _("Bookmark cannot be saved"))
+                       return
+               start.setEndPoint(end, "endToStart")
+               count = len(start.text)
+               if count in self._states:
+                       ui.message(
+                       # Translators: message presented when the current 
position was previously saved as a bookmark.
+                       _("This position was already saved"))
+                       return
+               self._states.append(count)
+               self._states.sort()
+               try:
+                       cPickle.dump(self._states, file(fileName, "wb"))
+                       ui.message(
+                       # Translators: message presented when a position is 
saved as a bookmark.
+                       _("Saved position at character %d") %count)
+               except Exception as e:
+                       log.debugWarning("Error saving bookmark", exc_info=True)
+                       ui.message(
+                       # Translators: message presented when a bookmark cannot 
be saved.
+                       _("Cannot save bookmark"))
+                       raise e
+       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
+       script_saveBookmark.__doc__ = _("Saves the current position as a 
bookmark.")
+
+       def script_deleteBookmark(self, gesture):
+               obj = api.getFocusObject()
+               treeInterceptor=obj.treeInterceptor
+               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
+                       obj=treeInterceptor
+               else:
+                       gesture.send()
+                       return
+               self.getStates()
+               if len(self._states) == 0:
+                       ui.message(
+                       # Translators: message presented when the current 
document doesn't contain bookmarks.
+                       _("No bookmarks"))
+                       return
+               fileName = self._pickle
+               start = obj.makeTextInfo(textInfos.POSITION_ALL)
+               try:
+                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
+               except (NotImplementedError, RuntimeError):
+                       ui.message(_("Bookmark cannot be deleted"))
+                       return
+               start.setEndPoint(end, "endToStart")
+               count = len(start.text)
+               if count not in self._states:
+                       ui.message(
+                       # Translators: message presented when the current 
document has bookmarks, but none is selected.
+                       _("No bookmark selected"))
+                       return
+               self._states.remove(count)
+               if len(self._states) > 0:
+                       self._states.sort()
+                       try:
+                               cPickle.dump(self._states, file(fileName, "wb"))
+                               ui.message(
+                               # Translators: message presented when a 
bookmark is deleted.
+                               _("Bookmark deleted"))
+                               return
+                       except:
+                               pass
+               else:
+                       try:
+                               os.remove(fileName)
+                               ui.message(_
+                               # Translators: message presented when the 
current document doesn't contain bookmarks.
+                               ("No bookmarks"))
+                               return
+                       except WindowsError:
+                               pass
+               log.debugWarning("Error saving bookmarks", exc_info=True)
+               ui.message(
+               # Translators: message presented when cannot delete a bookmark.
+               _("Cannot delete bookmark"))
+       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
+       script_deleteBookmark.__doc__ = _("Deletes the current bookmark.")
+
+       def script_selectNextBookmark(self, gesture):
+               obj = api.getFocusObject()
+               treeInterceptor=obj.treeInterceptor
+               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
+                       obj=treeInterceptor
+               else:
+                       gesture.send()
+                       return
+               self.getStates()
+               if len(self._states) == 0:
+                       ui.message(
+                       # Translators: message presented when trying to select 
a bookmark, but none is found.
+                       _("No bookmarks found"))
+                       return
+               start = obj.makeTextInfo(textInfos.POSITION_ALL)
+               try:
+                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
+               except (NotImplementedError, RuntimeError):
+                       ui.message(
+                       # Translators: message presented when cannot find any 
bookmark.
+                       _("Cannot find any bookmark"))
+                       return
+               start.setEndPoint(end, "endToStart")
+               count = len(start.text)
+               for bookmark in self._states:
+                       if bookmark > count:
+                               end.move(textInfos.UNIT_CHARACTER, 
bookmark-count)
+                               obj.selection = end
+                               if not willSayAllResume(gesture):
+                                       
end.move(textInfos.UNIT_LINE,1,endPoint="end")
+                                       
speech.speakTextInfo(end,reason=controlTypes.REASON_CARET)
+                                       ui.message(
+                                       # Translators: message presented when a 
bookmark is selected.
+                                       _("Position: character %d") % bookmark)
+                               return
+               ui.message(
+               # Translators: message presented when the next bookmark is not 
found.
+               _("Next bookmark not found"))
+       script_selectNextBookmark.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
+       script_selectNextBookmark.__doc__ = _("Moves to the next bookmark.")
+
+       def script_selectPreviousBookmark(self, gesture):
+               obj = api.getFocusObject()
+               treeInterceptor=obj.treeInterceptor
+               if hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough:
+                       obj=treeInterceptor
+               else:
+                       gesture.send()
+                       return
+               self.getStates()
+               if len(self._states) == 0:
+                       ui.message(
+                       # Translators: message presented when trying to select 
a bookmark, but none is found.
+                       _("No bookmarks found"))
+                       return
+               start = obj.makeTextInfo(textInfos.POSITION_ALL)
+               try:
+                       end = obj.makeTextInfo(textInfos.POSITION_CARET)
+               except (NotImplementedError, RuntimeError):
+               # Translators: message presented when cannot find any bookmark.
+                       ui.message(_("Cannot find any bookmark"))
+                       return
+               start.setEndPoint(end, "endToStart")
+               count = len(start.text)
+               bookmarkList = self._states
+               bookmarkList.reverse()
+               for bookmark in bookmarkList:
+                       if bookmark < count:
+                               end.move(textInfos.UNIT_CHARACTER, 
bookmark-count)
+                               obj.selection = end
+                               if not willSayAllResume(gesture):
+                                       
end.move(textInfos.UNIT_LINE,1,endPoint="end")
+                                       
speech.speakTextInfo(end,reason=controlTypes.REASON_CARET)
+                                       ui.message(
+                                       # Translators: message presented when a 
bookmark is selected.
+                                       _("Position: character %d") % bookmark)
+                               return
+               ui.message(
+               # Translators: message presented when the previous bookmark is 
not found.
+               _("Previous bookmark not found"))
+       
script_selectPreviousBookmark.resumeSayAllMode=sayAllHandler.CURSOR_CARET
+       # Translators: message presented in input mode, when a keystroke of an 
addon script is pressed.
+       script_selectPreviousBookmark.__doc__ = _("Moves to the previous 
bookmark.")
+
+       def script_copyCurrentBookmarksFile(self, gesture):
+               obj=api.getFocusObject()
+               if not controlTypes.STATE_MULTILINE in obj.states:
+                       treeInterceptor=obj.treeInterceptor
+                       if not (hasattr(treeInterceptor,'TextInfo') and not 
treeInterceptor.passThrough) and controlTypes.STATE_MULTILINE not in obj.states:
+                               gesture.send()
+                               return
+               fileName = getFile("bookmarks")
+               if not api.copyToClip(os.path.basename(fileName)):
+                       ui.message(
+                       # Translators: message presented when cannot copy the 
file name corresponding to place markers.
+                       _("Cannot copy file name for place markers"))
+                       return
+               ui.message(
+               # Translators: message presented when file name for place 
markers is copied to clipboard.
+               _("Place markers file name copied to clipboard"))
+                       # Translators: message presented in input mode, when a 
keystroke of an addon script is pressed.
+       script_copyCurrentBookmarksFile.__doc__ = _("Copies the name of the 
current file for place markers to the clipboard.")
+
+       __gestures = {
+               "kb:control+shift+NVDA+f": "specificFind",
+               "kb:control+shift+NVDA+k": "saveBookmark",
+               "kb:control+shift+NVDA+delete": "deleteBookmark",
+               "kb:NVDA+k": "selectNextBookmark",
+               "kb:shift+NVDA+k": "selectPreviousBookmark",
+               "kb:control+shift+k": "copyCurrentBookmarksFile",
+       }
+

diff --git a/addon/globalPlugins/placeMarkers/skipTranslation.py 
b/addon/globalPlugins/placeMarkers/skipTranslation.py
new file mode 100644
index 0000000..ea074a6
--- /dev/null
+++ b/addon/globalPlugins/placeMarkers/skipTranslation.py
@@ -0,0 +1,9 @@
+# -*- coding: UTF-8 -*-
+# skipTranslation: Module to get translated texts from NVDA
+# Based on implementation made by Alberto Buffolino
+# https://github.com/nvaccess/nvda/issues/4652
+#Copyright (C) 2016 Noelia Ruiz Martínez
+# Released under GPL 2
+
+def translate(text):
+       return _(text)

Repository URL: https://bitbucket.org/nvdaaddonteam/placemarkers/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.

Other related posts:

  • » commit/placeMarkers: norrumar: Start implementation of skipTranslation procedure to get texts translated in NVDA, based on Alberto Buffolino implementation. - commits-noreply