Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
nvdaes committed Aug 30, 2013
0 parents commit a8706d2
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
addon/doc/*.css
addon/doc/en/
*_docHandler.py
*.html
*.ini
*.mo
*.pot
*.pyc
*.nvda-addon
.sconsign.dblite
216 changes: 216 additions & 0 deletions addon/globalPlugins/appendText/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# -*- coding: UTF-8 -*-

# Append text: a global plugin for appending text to the clipboard

# Version: 1.1
# Bug fixed: added control in gestures. Now NVDA+shift+c can be used in Excel tables
# Date: 30/01/2013
# Version: 1.0
# Date: 28/12/2012


import addonHandler
import globalPluginHandler
import api
import textInfos
import ui
import win32clipboard
import wx
import gui
import os
import languageHandler
from logHandler import log
from cStringIO import StringIO
from configobj import ConfigObj
from validate import Validator


iniFileName = os.path.join(os.path.dirname(__file__), "appendText.ini")

confspec = ConfigObj(StringIO("""#Configuration file
[separator]
bookmarkSeparator = string(default="")
"""), encoding="UTF-8", list_values=False)
confspec.newlines = "\r\n"
conf = ConfigObj(iniFileName, configspec = confspec, indent_type = "\t", encoding="UTF-8")
val = Validator()
conf.validate(val)
bookmark = conf["separator"]["bookmarkSeparator"]


addonHandler.initTranslation()

class GlobalPlugin(globalPluginHandler.GlobalPlugin):

def __init__(self):
super(globalPluginHandler.GlobalPlugin, self).__init__()
self.menu = gui.mainFrame.sysTrayIcon.menu
self.appendTextMenu = wx.Menu()
self.mainItem = self.menu.AppendSubMenu(self.appendTextMenu,
# Translators: name of a menu item.
_("&Append text"),
# Translators: tooltip for a menu item.
_("Append Text menu"))
self.clearItem = self.appendTextMenu.Append(wx.ID_ANY,
# Translators: name of a menu item.
_("D&elete appended text"),
# Translators: tooltip for a menu item.
_("Clear clipboard and delete appended text"))
gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onClearAddedText, self.clearItem)
self.settingsItem = self.appendTextMenu.Append(wx.ID_ANY,
# Translators: name of a menu item.
_("Append Text &separator..."),
# Translators: tooltip for a menu item.
_("Set the separator for appended strings"))
gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onSettings, self.settingsItem)

self.text = ""
self.baseText = ""
self.newText = ""
self.separator = "\r\n"+bookmark+"\r\n"

def terminate(self):
try:
self.menu.RemoveItem(self.mainItem)
except wx.PyDeadObjectError:
pass

def onSettings(self, evt):
# Translators: label of a dialog.
message = _("Type the text you wish to use as separator between the strings appended to clipboard")
# Translators: title of a dialog.
title = _("Append Text settings")
global bookmark
d = wx.TextEntryDialog(gui.mainFrame, message, title, defaultValue=bookmark)
gui.mainFrame.prePopup()
try:
result = d.ShowModal()
except AttributeError:
pass
gui.mainFrame.postPopup()
if result == wx.ID_OK:
bookmark = d.GetValue()
self.separator = "\r\n"+bookmark+"\r\n"
conf["separator"]["bookmarkSeparator"] = bookmark
try:
conf.validate(val, copy=True)
conf.write()
log.info("AppendText add-on configuration saved")
except Exception, e:
log.warning("Could not save AppendText add-on configuration")
log.debugWarning("", exc_info=True)
raise e

def clearClipboard(self):
try:
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
# ui.message(_("Clipboard is empty"))
except win32clipboard.error:
# Translators: message presented when cannot delete the clipboard content.
ui.message(_("Cannot clear the clipboard"))
finally:
win32clipboard.CloseClipboard()

def getSelectedText(self):
obj=api.getFocusObject()
treeInterceptor=obj.treeInterceptor
if hasattr(treeInterceptor,'TextInfo') and not treeInterceptor.passThrough:
obj=treeInterceptor
try:
info=obj.makeTextInfo(textInfos.POSITION_SELECTION)
except (RuntimeError, NotImplementedError):
info=None
if not info or info.isCollapsed:
return None
if obj == treeInterceptor:
try:
clipData = api.getClipData()
except TypeError:
clipData = None
try:
info.copyToClipboard()
selectedText = api.getClipData()
if clipData is not None:
api.copyToClip(clipData)
else:
self.clearClipboard()
return selectedText
except:
pass
return info.text

def script_review_markStartForAppend(self, gesture):
self._copyStartMarker = api.getReviewPosition().copy()
# Translators: message presented when the start marker for Append Text has been set using the review cursor.
ui.message(_("Start marked for Append Text"))
# Translators: message presented in input mode.
script_review_markStartForAppend.__doc__ = _("Marks the current position of the review cursor as the start of text to be appended.")

def script_append(self, gesture):
if self.getSelectedText() is not None:
self.newText = self.getSelectedText()
else:
if not getattr(self, "_copyStartMarker", None):
# Translators: message presented when it's not possible to append text, since no text has been selected or marked.
ui.message(_("No selection. No start marker set"))
return
pos = api.getReviewPosition().copy()
if self._copyStartMarker.obj != pos.obj:
# Translators: message presented when trying to append text, but the start marker doesn't reside in the current object.
ui.message(_("The start marker must reside within the same object"))
return
pos.move(textInfos.UNIT_CHARACTER, 1, endPoint="end")
pos.setEndPoint(self._copyStartMarker, "startToStart")
if not pos.compareEndPoints(pos, "startToEnd") < 0:
# Translators: message presented when review cursor has been used to append text and there is no text to append.
ui.message(_("No text to append"))
return
self.newText = textInfos.convertToCrlf(pos.text)
self._copyStartMarker = None
try:
clipData = api.getClipData()
except TypeError:
clipData = ""
# Translators: message presented when adding text to the clipboard and it's empty.
ui.message(_("Adding text to empty clipboard"))
try:
self.baseText = clipData+self.separator
self.text = self.baseText+self.newText
except Exception, e:
# Translators: message presented when the text to append cannot be retrieved.
ui.message(_("Can not get the text to append"))
raise e
if api.copyToClip(self.text):
# Translators: message presented when the text has been appended to the clipboard.
ui.message(_("Appended"))
else:
# Translators: message presented when the text cannot be apended to the clipboard.
ui.message(_("Cannot append text to the clipboard"))
# Translators: message presented in input mode.
script_append.__doc__ = _("Retrieves the selected string or the text from the previously set start marker up to and including the current position of the review cursor, and appends it to the clipboard.")

def onClearAddedText(self, evt):
# Translators: message presented when deleting the clipboard content.
ui.message(_("Clearing added text..."))
self.text = ""
self.baseText = ""
self.newText = ""
self.clearClipboard()
try:
api.getClipData()
except TypeError:
# Translators: message presented when the clipboard content has been deleted.
ui.message(_("Clipboard is empty"))

def script_clear(self, gesture):
self.onClearAddedText(None)
# Translators: message presented in input mode.
script_clear.__doc__ = _("Deletes the appended text and the content of the clipboard.")

__gestures = {
"kb:control+NVDA+shift+e": "append",
"kb:control+NVDA+shift+x": "clear",
"kb:control+NVDA+shift+c": "review_markStartForAppend",
}
41 changes: 41 additions & 0 deletions buildVars.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# -*- coding: UTF-8 -*-

# Build customizations
# Change this file instead of sconstruct or manifest files, whenever possible.

# Full getext (please don't change)
_ = lambda x : x

# Add-on information variables
addon_info = {
# for previously unpublished addons, please follow the community guidelines at:
# https://bitbucket.org/nvdaaddonteam/todo/src/56140dbec531e4d7591338e1dbc6192f3dd422a8/guideLines.txt
# add-on Name, internal for nvda
"addon-name" : "AppendText",
# Add-on summary, usually the user visible name of the addon.
# TRANSLATORS: Summary for this add-on to be shown on installation and add-on information.
"addon-summary" : _("Append Text"),
# Add-on description
# Translators: Long description to be shown for this add-on on add-on information from add-ons manager
"addon-description" : _("""Add-on for appending text to the clipboard."""),
# version
"addon-version" : "2.0-dev",
# Author(s)
"addon-author" : "Noelia <[email protected]>",
# URL for the add-on documentation support
"addon-url" : "http://addons.nvda-project.org"
}


import os.path

# Define the python files that are the sources of your add-on.
# You can use glob expressions here, they will be expanded.
pythonSources = [os.path.join("globalPlugins", "*.py")]

# Files that contain strings for translation. Usually your python sources
i18nSources = pythonSources + ["buildVars.py", "docHandler.py"]

# Files that will be ignored when building the nvda-addon file
# Paths are relative to the addon directory, not to the root directory of your addon sources.
excludedFiles = []
68 changes: 68 additions & 0 deletions docHandler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- coding: UTF-8 -*-

# docHandler: module for managing addons documentation
# See: http://community.nvda-project.org/ticket/2694

import os
import languageHandler
import addonHandler
import globalPluginHandler
import gui
import wx

addonHandler.initTranslation()

_addonDir = os.path.join(os.path.dirname(__file__), "..") # The root of an addon folder
_docFileName = "readme.html" # The name of an addon documentation file
_curAddon = addonHandler.Addon(_addonDir) # Addon instance
_addonSummary = _curAddon.manifest['summary']
_addonVersion = _curAddon.manifest['version']
_addonName = _curAddon.manifest['name']

def getDocFolder(addonDir=_addonDir):
langs = [languageHandler.getLanguage(), "en"]
for lang in langs:
docFolder = os.path.join(addonDir, "doc", lang)
if os.path.isdir(docFolder):
return docFolder
if "_" in lang:
tryLang = lang.split("_")[0]
docFolder = os.path.join(addonDir, "doc", tryLang)
if os.path.isdir(docFolder):
return docFolder
if tryLang == "en":
break
if lang == "en":
break
return None

def getDocPath(docFileName=_docFileName):
docPath = getDocFolder()
if docPath is not None:
docFile = os.path.join(docPath, docFileName)
if os.path.isfile(docFile):
docPath = docFile
return docPath

def openDocPath():
try:
os.startfile(getDocPath())
except WindowsError:
pass

class GlobalPlugin(globalPluginHandler.GlobalPlugin):

def __init__(self):
super(globalPluginHandler.GlobalPlugin, self).__init__()
self.help = gui.mainFrame.sysTrayIcon.helpMenu
self.helpItem = self.help.Append(wx.ID_ANY, u"{summary} {version}".format(summary=_addonSummary, version=_addonVersion), _addonName)
gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onHelp, self.helpItem)

def onHelp(self, evt):
openDocPath()

def terminate(self):
try:
self.help.RemoveItem(self.helpItem)
except wx.PyDeadObjectError:
pass
2 changes: 2 additions & 0 deletions manifest-translated.ini.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
summary = "{addon-summary}"
description = """{addon-description}"""
6 changes: 6 additions & 0 deletions manifest.ini.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name = {addon-name}
summary = "{addon-summary}"
description = """{addon-description}"""
author = "{addon-author}"
url = {addon-url}
version = {addon-version}
20 changes: 20 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Append Text #
- Authors: Noelia.
- Download: [Version 2.0-dev][1]

This add-on is used to append text to the clipboard, what can be useful when you want to join and paste strings of text from different places.
It also allows to delete the clipboard content.

## Keyboard commands ##
- NVDA+control+shift+e: Appends the selected text, or the string which has been marked with the review cursor, to the clipboard.
- NVDA+control+shift+x: Removes the clipboard content.
- NVDA+control+shift+c: Sets the start marker for Append Text using the review cursor.

## Menu commands ##
- Delete appended text: Removes the clipboard content.
- Append Text separator: Allows to set a separator which can be used to find the different strings after pasting the appended text.

## Changes for 2.0 ##
- Initial version.

[1]: http://addons.nvda-project.org/files/get.php?file=atxt
Loading

0 comments on commit a8706d2

Please sign in to comment.