commit/RapidSettings: ABuffEr: Various bug fixes, updated readme and template

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Tue, 17 Mar 2015 14:01:26 -0000

1 new commit in RapidSettings:

https://bitbucket.org/nvdaaddonteam/rapidsettings/commits/d3638bea60da/
Changeset:   d3638bea60da
Branch:      master
User:        ABuffEr
Date:        2015-03-17 14:01:05+00:00
Summary:     Various bug fixes, updated readme and template

Affected #:  10 files

diff --git a/addon/globalPlugins/rapidSettings/__init__.py 
b/addon/globalPlugins/rapidSettings/__init__.py
index 2ae647e..516bfdd 100644
--- a/addon/globalPlugins/rapidSettings/__init__.py
+++ b/addon/globalPlugins/rapidSettings/__init__.py
@@ -11,7 +11,7 @@ from msg import message as msg
 import queueHandler
 import ui
 from tones import beep
-from logHandler import log
+#from logHandler import log
 import addonHandler
 addonHandler.initTranslation()
 
@@ -21,7 +21,7 @@ _addonSummary = _curAddon.manifest['summary']
 _scriptCategory = unicode(_addonSummary)
 
 # the global variables to store current settings dialog instance
-# and a application focused object before script_showSettingsTree execution
+# and an application focused object before script_showSettingsTree execution
 ins = curAppObj = None
 
 class SettingsTree(wx.TreeCtrl):
@@ -97,7 +97,7 @@ class SettingsTree(wx.TreeCtrl):
                # list of all wx controls in the dialog
                children = ins.GetChildren()
                # loop to prepare names for tree items, based on combobox, 
editbox, checkbox and slider
-               for n in range(0,len(children)):
+               for n in xrange(0,len(children)):
                        child = children[n]
                        name = None
                        if child.IsEnabled():
@@ -107,13 +107,13 @@ class SettingsTree(wx.TreeCtrl):
                                                # the colon presence is very 
inconsistent
                                                sep = ' ' if 
child.GetName().endswith(':') else ': '
                                                # concatenate name, separator 
and current value of combobox
-                                               name = 
sep.join([msg(child.GetName()), msg(child.GetLabel())])
+                                               name = 
sep.join([msg(child.GetName()), msg(child.GetStringSelection())])
                                        else:
                                                # ...but some other has 
"choice" as name, so we take the staticText label, the previous control
                                                sep = ' ' if 
children[n-1].GetLabel().endswith(':') else ': '
-                                               name = 
sep.join([msg(children[n-1].GetLabel()), msg(child.GetLabel())])
+                                               name = 
sep.join([msg(children[n-1].GetLabel()), msg(child.GetStringSelection())])
                                elif child.ClassName == u'wxTextCtrl':
-                                       name = ': 
'.join([msg(children[n-1].GetLabel()), child.GetLabel()])
+                                       name = ': 
'.join([msg(children[n-1].GetLabel()), child.GetValue()])
                                elif child.ClassName == u'wxCheckBox':
                                        name = ': 
'.join([msg(child.GetLabel()), msg("on" if child.GetValue() else "off")])
                                elif child.ClassName == u'wxSlider':
@@ -325,8 +325,16 @@ class SettingsTreeDialog(SettingsDialog):
                self.originalTriggersValue = self.modifiedTriggersValue = 
config.conf.profileTriggersEnabled
                # hide controls associated with tree items
                self.disableItems()
+               # bind onEscape on all items, to avoid problems pressing escape
+               for item in self.GetChildren():
+                       item.Bind(wx.EVT_KEY_UP, self.onEscape)
+               # remember ok and cancel button
+#              self.Bind(wx.EVT_KEY_UP, self.onEscape, id=wx.ID_OK)
+#              self.Bind(wx.EVT_KEY_UP, self.onEscape, id=wx.ID_CANCEL)
                # trace modified settings
                self.changedItems = []
+               # useful to fix problem closing context menu in onCancel
+               self.contextMenu = None
 
        def listProfiles(self):
                """Build the list for profiles combo"""
@@ -376,33 +384,33 @@ class SettingsTreeDialog(SettingsDialog):
 
        def viewPopupMenu(self, event):
                """Create context menu, calling preparePopupMenu, and view it"""
-               popupMenu = self.preparePopupMenu()
-               self.PopupMenu(popupMenu)
+               self.contextMenu = self.preparePopupMenu()
+               self.PopupMenu(self.contextMenu)
 
        def preparePopupMenu(self):
                """Prepare context menu items according to current profile"""
                popupMenu = wx.Menu()
                toggleManualProfileMI = popupMenu.Append(wx.NewId(), 
msg("Manual activate"))
-               self.Bind(wx.EVT_MENU, self.toggleManualProfile, 
toggleManualProfileMI)
+               popupMenu.Bind(wx.EVT_MENU, self.toggleManualProfile, 
toggleManualProfileMI)
                newProfileMI = popupMenu.Append(wx.NewId(), msg("&New", 
amp=True))
-               self.Bind(wx.EVT_MENU, self.newProfile, newProfileMI)
+               popupMenu.Bind(wx.EVT_MENU, self.newProfile, newProfileMI)
                renameProfileMI = popupMenu.Append(wx.NewId(), msg("&Rename", 
amp=True))
-               self.Bind(wx.EVT_MENU, self.renameProfile, renameProfileMI)
+               popupMenu.Bind(wx.EVT_MENU, self.renameProfile, renameProfileMI)
                deleteProfileMI = popupMenu.Append(wx.NewId(), msg("&Delete", 
amp=True))
-               self.Bind(wx.EVT_MENU, self.deleteProfile, deleteProfileMI)
+               popupMenu.Bind(wx.EVT_MENU, self.deleteProfile, deleteProfileMI)
                toggleTriggersMI = popupMenu.AppendCheckItem(wx.NewId(), 
msg("Temporarily d&isable all triggers", amp=True))
                toggleTriggersMI.Check(not self.modifiedTriggersValue)
-               self.Bind(wx.EVT_MENU, self.toggleTriggers, toggleTriggersMI)
-               # FIXME: escape should close menu, but close dialog
-               # Translators: a label of menu item to close menu itself
-               closeMenuMI = popupMenu.Append(wx.NewId(), _("&Close menu"))
-               self.Bind(wx.EVT_MENU, self.closePopupMenu, closeMenuMI)
-               curProfile = self.profileCombo.GetLabel()
+               popupMenu.Bind(wx.EVT_MENU, self.toggleTriggers, 
toggleTriggersMI)
+               curProfile = self.profileCombo.GetStringSelection()
                if curProfile == msg("(normal configuration)"):
+                       toggleManualProfileMI.Enable(False)
                        renameProfileMI.Enable(False)
                        deleteProfileMI.Enable(False)
                else:
-                       (cName, cStates) = curProfile.rsplit(' (', 1)
+                       try:
+                               cName, cStates = curProfile.rsplit(' (', 1)
+                       except:
+                               cName = curProfile.rsplit(' (', 1)
                        # if yes, it is manual or triggered
                        if self.originalProfile != msg("(normal 
configuration)"):
                                (oName, oStates) = 
self.originalProfile.rsplit(' (', 1)
@@ -412,7 +420,7 @@ class SettingsTreeDialog(SettingsDialog):
                        # or it is normal configuration, and currently selected 
profile was already
                        # candidate to be manually activated, so now it can be 
only deactivated
                        elif cName == self.keepProfile:
-                                       
toggleManualProfileMI.SetText(msg("Manual deactivate"))
+                               toggleManualProfileMI.SetText(msg("Manual 
deactivate"))
                return popupMenu
 
        def postInit(self):
@@ -475,6 +483,11 @@ class SettingsTreeDialog(SettingsDialog):
                self.slider.Bind(wx.EVT_COMMAND_SCROLL, lambda event, 
item=slider: self.onItemChange(event, item))
                self.slider.Enable()
 
+       def onEscape(self, event):
+               if event.GetKeyCode() == wx.WXK_ESCAPE:
+                       self.onCancel(event)
+#                      event.StopPropagation()
+
        def onInputSearch(self, event):
                """Process input in search field, call search method on the 
tree"""
                input = self.search.GetValue()
@@ -500,7 +513,7 @@ class SettingsTreeDialog(SettingsDialog):
                        # useful for language and variant comboboxes in voice 
section
                        item.GetEventHandler().ProcessEvent(event)
                        # request a update to relative tree item
-                       self.tree.updateLabel(self.combo.GetLabel())
+                       self.tree.updateLabel(self.combo.GetStringSelection())
                elif item.ClassName == u'wxTextCtrl':
                        if self.edit.GetValue() == self.editOriginalValue:
                                self.changedItems.remove(item)
@@ -607,7 +620,7 @@ class SettingsTreeDialog(SettingsDialog):
        def toggleManualProfile(self, event):
                """Indicate which profile must be kept manually active after 
dialog closing"""
                toggleManualProfileMI = 
event.GetEventObject().FindItemById(event.GetId())
-               name = self.profileCombo.GetLabel().rsplit(' (', 1)[0]
+               name = self.profileCombo.GetStringSelection().rsplit(' (', 1)[0]
                if toggleManualProfileMI.GetText() == msg("Manual activate"):
                        self.keepProfile = name
                else:
@@ -618,11 +631,11 @@ class SettingsTreeDialog(SettingsDialog):
                """Show new profile creation dialog"""
                # collapse and request to eventually save changes
                self.tree.CollapseAll()
+               self.onOk(wx.EVT_BUTTON)
                profDlg = self.getProfileDialog()
                NewProfileDialog(profDlg).Show()
                # "destroy" ProfilesDialog instance, for coherence reasons
                ProfilesDialog._instance = None
-               self.onOk(wx.EVT_BUTTON)
 
        def renameProfile(self, event):
                """Show profile renaming dialog"""
@@ -646,10 +659,12 @@ class SettingsTreeDialog(SettingsDialog):
                profDlg.onDelete(wx.EVT_BUTTON)
                # "destroy" ProfilesDialog instance, for coherence reasons
                ProfilesDialog._instance = None
-               # update dialog title and profileCombo
+               # update dialog title, tree and profileCombo
+               self.tree.find = ''
+               self.tree.initSections(self.tree.prepareClassList())
+               self.updateProfileCombo()
                self.title = self.prepareTitle()
                self.SetTitle(self.title)
-               self.updateProfileCombo()
 
        def toggleTriggers(self, event):
                """Indicate if triggers must be kept activated or deactivated 
after dialog closing"""
@@ -673,11 +688,6 @@ class SettingsTreeDialog(SettingsDialog):
                # Temporary solution part 2: close dialog
                self.onOk(wx.EVT_BUTTON)
 
-       def closePopupMenu(self, event):
-               """Close context menu"""
-               # see FIXME comment in preparePopupMenu
-               event.GetEventObject().Destroy()
-
        def onOk(self, event):
                """Call onOk(event) on phantom dialog instance, if this exists, 
and the same on superclass, plus many various actions"""
                if ins is not None and "wxPyDeadObject" not in 
str(ins.__class__):
@@ -687,7 +697,12 @@ class SettingsTreeDialog(SettingsDialog):
                        # disable an eventual profile manually activated (to 
modify)
                        config.conf.manualActivateProfile(None)
                else:
-                       (name, states) = self.originalProfile.rsplit(' (', 1)
+                       try:
+                               (name, states) = self.originalProfile.rsplit(' 
(', 1)
+                       # changing NVDA language and pressing return, we have 
only name (normal configuration), so:
+                       except:
+                               name = self.originalProfile.rsplit(' (', 1)
+                               states = []
                        # if initial profile is manual, otherwise
                        if msg("manual") in states:
                                try:
@@ -719,6 +734,10 @@ class SettingsTreeDialog(SettingsDialog):
 
        def onCancel(self, event):
                """Call onCancel(event) on phantom dialog instance, if this 
exists, and the same on superclass"""
+               if self.contextMenu != None and "wxPyDeadObject" not in 
str(self.contextMenu.__class__):
+                       self.contextMenu.Destroy()
+                       self.profileCombo.SetFocus()
+                       return
                if ins is not None and "wxPyDeadObject" not in 
str(ins.__class__):
                        ins.onCancel(event)
                # if triggers is originally enabled
@@ -741,7 +760,7 @@ class SettingsTreeDialog(SettingsDialog):
                                # simply manually deactivate an eventual 
profile manually activated (to modify it)
                                config.conf.manualActivateProfile(None)
                # if initial is normal configuration and is not currently 
selected profile in profileCombo
-               elif self.originalProfile != self.profileCombo.GetLabel():
+               elif self.originalProfile != 
self.profileCombo.GetStringSelection():
                        # disable an eventual profile manually activated (to 
modify)
                        config.conf.manualActivateProfile(None)
                super(SettingsTreeDialog, self).onCancel(event)

diff --git a/addon/locale/it/LC_MESSAGES/nvda.po 
b/addon/locale/it/LC_MESSAGES/nvda.po
index 66eaa42..3471a9a 100644
--- a/addon/locale/it/LC_MESSAGES/nvda.po
+++ b/addon/locale/it/LC_MESSAGES/nvda.po
@@ -7,15 +7,15 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 'rapidSettings' '2.0dev'\n"
 "Report-Msgid-Bugs-To: 'nvda-translations@xxxxxxxxxxxxx'\n"
-"POT-Creation-Date: 2014-03-15 14:47+0100\n"
-"PO-Revision-Date: 2014-03-15 14:49+0100\n"
+"POT-Creation-Date: 2015-03-17 14:55+0100\n"
+"PO-Revision-Date: 2015-03-17 14:56+0100\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: Alberto Buffolino <a.buffolino@xxxxxxxxx>\n"
 "Language: it\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.6.4\n"
+"X-Generator: Poedit 1.6.5\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Poedit-Basepath: .\n"
 
@@ -41,20 +41,14 @@ msgstr ""
 "La finestra di dialogo profili di configurazione è aperta. Prima chiudila, "
 "per favore."
 
-#. FIXME: escape should close menu, but close dialog
-#. Translators: a label of menu item to close menu itself
-#: addon\globalPlugins\rapidSettings\__init__.py:398
-msgid "&Close menu"
-msgstr "&Chiudi menu"
-
 #. Translators: the message for save changes
-#: addon\globalPlugins\rapidSettings\__init__.py:758
+#: addon\globalPlugins\rapidSettings\__init__.py:777
 #, python-brace-format
 msgid "Do you want to save changes for {section} section?"
 msgstr "Vuoi salvare i cambiamenti per la sezione {section}?"
 
 #. Translators: the description for the settings tree script.
-#: addon\globalPlugins\rapidSettings\__init__.py:784
+#: addon\globalPlugins\rapidSettings\__init__.py:803
 msgid ""
 "Presents a tree of all settings sections, which you can expand to modify all "
 "NVDA options"
@@ -76,3 +70,6 @@ msgid ""
 msgstr ""
 "Permette di accedere a tutte le impostazioni in una singola finestra, e "
 "ricercare fra di esse."
+
+#~ msgid "&Close menu"
+#~ msgstr "&Chiudi menu"

diff --git a/buildVars.py b/buildVars.py
index 19eb7c5..77ff8d7 100644
--- a/buildVars.py
+++ b/buildVars.py
@@ -11,19 +11,21 @@ addon_info = {
        # for previously unpublished addons, please follow the community 
guidelines at:
        # https://bitbucket.org/nvdaaddonteam/todo/raw/master/guideLines.txt
        # add-on Name, internal for nvda
-       "addon-name" : "rapidSettings",
+       "addon_name" : "rapidSettings",
        # 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" : _("Rapid Settings"),
+       "addon_summary" : _("Rapid Settings"),
        # Add-on description
        # Translators: Long description to be shown for this add-on on add-on 
information from add-ons manager
-       "addon-description" : _("""Lets you to access to all settings in a 
single window, and search among them."""),
+       "addon_description" : _("""Lets you to access to all settings in a 
single window, and search among them."""),
        # version
-       "addon-version" : "2.0dev",
+       "addon_version" : "2.0dev",
        # Author(s)
-       "addon-author" : u"Alberto Buffolino <a.buffolino@xxxxxxxxx>",
+       "addon_author" : u"Alberto Buffolino <a.buffolino@xxxxxxxxx>",
        # URL for the add-on documentation support
-       "addon-url" : None
+       "addon_url" : None,
+       # Documentation file name
+       "addon_docFileName" : "readme.html",
 }
 
 
@@ -34,7 +36,7 @@ import os.path
 pythonSources = [os.path.join("addon", "globalPlugins", "rapidSettings", 
"*.py")]
 
 # Files that contain strings for translation. Usually your python sources
-i18nSources = pythonSources + ["buildVars.py", "docHandler.py"]
+i18nSources = pythonSources + ["buildVars.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.

diff --git a/docHandler.py b/docHandler.py
deleted file mode 100644
index b514fe4..0000000
--- a/docHandler.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- 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__), "..").decode("mbcs") # 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

diff --git a/manifest-translated.ini.tpl b/manifest-translated.ini.tpl
index 4750635..c06aa84 100644
--- a/manifest-translated.ini.tpl
+++ b/manifest-translated.ini.tpl
@@ -1,2 +1,2 @@
-summary = "{addon-summary}"
-description = """{addon-description}"""
+summary = "{addon_summary}"
+description = """{addon_description}"""

diff --git a/manifest.ini.tpl b/manifest.ini.tpl
index 8093a3f..7de43bf 100644
--- a/manifest.ini.tpl
+++ b/manifest.ini.tpl
@@ -1,6 +1,7 @@
-name = {addon-name}
-summary = "{addon-summary}"
-description = """{addon-description}"""
-author = "{addon-author}"
-url = {addon-url}
-version = {addon-version}
+name = {addon_name}
+summary = "{addon_summary}"
+description = """{addon_description}"""
+author = "{addon_author}"
+url = {addon_url}
+version = {addon_version}
+docFileName = {addon_docFileName}

diff --git a/readme.md b/readme.md
index 96577b7..e4a69f5 100644
--- a/readme.md
+++ b/readme.md
@@ -25,6 +25,7 @@ You can also search in all settings, using the specific field 
before the tree; t
 ## Changes for 2.0 ##
 
 * Profile management implementation.
+* Various bug fixes.
 
 ## Changes for 1.0 ##
 
@@ -33,11 +34,8 @@ You can also search in all settings, using the specific 
field before the tree; t
 ### Bugs or problems still present ###
 
 * Braille remains on a blank line when search field it cleaned automatically.
-* If you press escape on a combobox, editbox, radio button or slider, the 
event is not processed by main dialog, generating errors.
-* If you press escape on context menu, dialog is closed (not context menu).
 * It's not possible to use return on a tree item to simulate click on ok 
button (see code for details).
 * Enable or disable triggers from context menu requires to close dialog for 
coherence reasons (see code for details).
 * When you select a Braille display that requires port selection, the port 
combobox is not shown immediately.
-* If you get an error in Braille display selection (display not found), after 
pressing ok the original dialog appears.
 
 [1]: http://addons.nvda-project.org/files/get.php?file=rs-dev
\ No newline at end of file

diff --git a/sconstruct b/sconstruct
index 1d54d6e..b77cfe6 100644
--- a/sconstruct
+++ b/sconstruct
@@ -1,5 +1,5 @@
 # NVDA add-on template  SCONSTRUCT file
-#Copyright (C) 2012 Rui Batista <ruiandrebatista@xxxxxxxxx>
+#Copyright (C) 2012, 2014 Rui Batista <ruiandrebatista@xxxxxxxxx>
 #This file is covered by the GNU General Public License.
 #See the file COPYING.txt for more details.
 
@@ -8,7 +8,6 @@ import gettext
 import os
 import os.path
 import zipfile
-import configobj
 
 import buildVars
 
@@ -16,7 +15,7 @@ import buildVars
 def md2html(source, dest):
        import markdown
        lang = os.path.basename(os.path.dirname(source)).replace('_', '-')
-       title="{addonSummary} 
{addonVersion}".format(addonSummary=buildVars.addon_info["addon-summary"], 
addonVersion=buildVars.addon_info["addon-version"])
+       title="{addonSummary} 
{addonVersion}".format(addonSummary=buildVars.addon_info["addon_summary"], 
addonVersion=buildVars.addon_info["addon_version"])
        headerDic = {
                "[[!meta title=\"": "# ",
                "\"]]": " #",
@@ -52,10 +51,11 @@ def mdTool(env):
        )
        env['BUILDERS']['markdown']=mdBuilder
 
-env = Environment(ENV=os.environ, tools=[mdTool])
 
+env = Environment(ENV=os.environ, tools=['gettexttool', mdTool])
+env.Append(**buildVars.addon_info)
 
-addonFile = 
env.File("{addon-name}-{addon-version}.nvda-addon".format(**buildVars.addon_info))
+addonFile = env.File("${addon_name}-${addon_version}.nvda-addon")
 
 def addonGenerator(target, source, env, for_signature):
        action = env.Action(lambda target, source, env : 
createAddonBundleFromPath(source[0].abspath, target[0].abspath) and None,
@@ -79,31 +79,7 @@ env['BUILDERS']['NVDAAddon'] = 
Builder(generator=addonGenerator)
 env['BUILDERS']['NVDAManifest'] = Builder(generator=manifestGenerator)
 env['BUILDERS']['NVDATranslatedManifest'] = 
Builder(generator=translatedManifestGenerator)
 
-env['BUILDERS']['gettextMoFile']=env.Builder(
-       action=env.Action(["msgfmt -o $TARGETS $SOURCES"], lambda t, s, e : 
"Compiling translation %s" % s[0]),
-       suffix=".mo",
-       src_suffix=".po"
-)
-
-env['BUILDERS']['gettextPotFile']=env.Builder(
-       action=env.Action(["xgettext --msgid-bugs-address='%s' 
--package-name='%s' --package-version='%s' -c -o $TARGETS $SOURCES" %
-               ("nvda-translations@xxxxxxxxxxxxx", 
buildVars.addon_info['addon-name'], buildVars.addon_info['addon-version'])
-       ], lambda t, s, e : "Generating pot file %s" % t[0]),
-       suffix=".pot")
-env['BUILDERS']['gettextMergePotFile']=env.Builder(
-       action=env.Action(["xgettext --msgid-bugs-address='%s' 
--package-name='%s' --package-version='%s' --omit-header --no-location -c -o 
$TARGETS $SOURCES" %
-               ("nvda-translations@xxxxxxxxxxxxx", 
buildVars.addon_info['addon-name'], buildVars.addon_info['addon-version'])
-       ], lambda t, s, e : "Generating pot file %s" % t[0]),
-       suffix=".pot")
-
 def createAddonHelp(dir):
-       if not os.path.isfile("docHandler.py"):
-               return
-       plugindir = os.path.join(dir, "globalPlugins")
-       docFilename = 
"{addonName}_docHandler.py".format(addonName=buildVars.addon_info["addon-name"])
-       docPath = os.path.join(plugindir, docFilename)
-       docFileTarget = env.Command(docPath, "docHandler.py", Copy("$TARGET", 
"$SOURCE"))
-       env.Depends(addon, docFileTarget)
        docsDir = os.path.join(dir, "doc")
        if os.path.isfile("style.css"):
                cssPath = os.path.join(docsDir, "style.css")
@@ -139,7 +115,7 @@ def generateManifest(source, dest):
 def generateTranslatedManifest(source, language, out):
        _ = gettext.translation("nvda", localedir=os.path.join("addon", 
"locale"), languages=[language]).ugettext
        vars = {}
-       for var in ("addon-summary", "addon-description"):
+       for var in ("addon_summary", "addon_description"):
                vars[var] = _(buildVars.addon_info[var])
        with codecs.open(source, "r", "utf-8") as f:
                manifest_template = f.read()
@@ -168,7 +144,7 @@ for file in pythonFiles:
        env.Depends(addon, file)
 
 #Convert markdown files to html
-createAddonHelp("addon") # We need at least doc in English and should append 
an item to Help menu
+createAddonHelp("addon") # We need at least doc in English and should enable 
the Help button for the add-on in Add-ons Manager
 for mdFile in env.Glob(os.path.join('addon', 'doc', '*', '*.md')):
        htmlFile = env.markdown(mdFile)
        env.Depends(htmlFile, mdFile)
@@ -176,10 +152,16 @@ for mdFile in env.Glob(os.path.join('addon', 'doc', '*', 
'*.md')):
 
 # Pot target
 i18nFiles = expandGlobs(buildVars.i18nSources)
-pot = env.gettextPotFile("%s.pot" % 
"{addon-name}".format(**buildVars.addon_info), i18nFiles)
+gettextvars={
+               'gettext_package_bugs_address' : 
'nvda-translations@xxxxxxxxxxxxx',
+               'gettext_package_name' : buildVars.addon_info['addon_name'],
+               'gettext_package_version' : 
buildVars.addon_info['addon_version']
+       }
+
+pot = env.gettextPotFile("${addon_name}.pot", i18nFiles, **gettextvars)
 env.Alias('pot', pot)
 env.Depends(pot, i18nFiles)
-mergePot = env.gettextMergePotFile("%s-merge.pot" % 
"{addon-name}".format(**buildVars.addon_info), i18nFiles)
+mergePot = env.gettextMergePotFile("${addon_name}-merge.pot", i18nFiles, 
**gettextvars)
 env.Alias('mergePot', mergePot)
 env.Depends(mergePot, i18nFiles)
 

diff --git a/sconstruct.bak b/sconstruct.bak
new file mode 100644
index 0000000..1d54d6e
--- /dev/null
+++ b/sconstruct.bak
@@ -0,0 +1,190 @@
+# NVDA add-on template  SCONSTRUCT file
+#Copyright (C) 2012 Rui Batista <ruiandrebatista@xxxxxxxxx>
+#This file is covered by the GNU General Public License.
+#See the file COPYING.txt for more details.
+
+import codecs
+import gettext
+import os
+import os.path
+import zipfile
+import configobj
+
+import buildVars
+
+
+def md2html(source, dest):
+       import markdown
+       lang = os.path.basename(os.path.dirname(source)).replace('_', '-')
+       title="{addonSummary} 
{addonVersion}".format(addonSummary=buildVars.addon_info["addon-summary"], 
addonVersion=buildVars.addon_info["addon-version"])
+       headerDic = {
+               "[[!meta title=\"": "# ",
+               "\"]]": " #",
+       }
+       with codecs.open(source, "r", "utf-8") as f:
+               mdText = f.read()
+               for k, v in headerDic.iteritems():
+                       mdText = mdText.replace(k, v, 1)
+               htmlText = markdown.markdown(mdText)
+       with codecs.open(dest, "w", "utf-8") as f:
+               f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                       "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 
Strict//EN\"\n" +
+                       "    
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\";>\n" +
+                       "<html xmlns=\"http://www.w3.org/1999/xhtml\"; 
xml:lang=\"%s\" lang=\"%s\">\n" % (lang, lang) +
+                       "<head>\n" +
+                       "<meta http-equiv=\"Content-Type\" content=\"text/html; 
charset=UTF-8\"/>\n" +
+                       "<link rel=\"stylesheet\" type=\"text/css\" 
href=\"../style.css\" media=\"screen\"/>\n" +
+                       "<title>%s</title>\n" % title +
+                       "</head>\n<body>\n"
+               )
+               f.write(htmlText)
+               f.write("\n</body>\n</html>")
+
+def mdTool(env):
+       mdAction=env.Action(
+               lambda target,source,env: md2html(source[0].path, 
target[0].path),
+               lambda target,source,env: 'Generating %s'%target[0],
+       )
+       mdBuilder=env.Builder(
+               action=mdAction,
+               suffix='.html',
+               src_suffix='.md',
+       )
+       env['BUILDERS']['markdown']=mdBuilder
+
+env = Environment(ENV=os.environ, tools=[mdTool])
+
+
+addonFile = 
env.File("{addon-name}-{addon-version}.nvda-addon".format(**buildVars.addon_info))
+
+def addonGenerator(target, source, env, for_signature):
+       action = env.Action(lambda target, source, env : 
createAddonBundleFromPath(source[0].abspath, target[0].abspath) and None,
+       lambda target, source, env : "Generating Addon %s" % target[0])
+       return action
+
+def manifestGenerator(target, source, env, for_signature):
+       action = env.Action(lambda target, source, env : 
generateManifest(source[0].abspath, target[0].abspath) and None,
+       lambda target, source, env : "Generating manifest %s" % target[0])
+       return action
+
+
+def translatedManifestGenerator(target, source, env, for_signature):
+       dir = os.path.abspath(os.path.join(os.path.dirname(str(source[0])), 
".."))
+       lang = os.path.basename(dir)
+       action = env.Action(lambda target, source, env : 
generateTranslatedManifest(source[1].abspath, lang, target[0].abspath) and None,
+       lambda target, source, env : "Generating translated manifest %s" % 
target[0])
+       return action
+
+env['BUILDERS']['NVDAAddon'] = Builder(generator=addonGenerator)
+env['BUILDERS']['NVDAManifest'] = Builder(generator=manifestGenerator)
+env['BUILDERS']['NVDATranslatedManifest'] = 
Builder(generator=translatedManifestGenerator)
+
+env['BUILDERS']['gettextMoFile']=env.Builder(
+       action=env.Action(["msgfmt -o $TARGETS $SOURCES"], lambda t, s, e : 
"Compiling translation %s" % s[0]),
+       suffix=".mo",
+       src_suffix=".po"
+)
+
+env['BUILDERS']['gettextPotFile']=env.Builder(
+       action=env.Action(["xgettext --msgid-bugs-address='%s' 
--package-name='%s' --package-version='%s' -c -o $TARGETS $SOURCES" %
+               ("nvda-translations@xxxxxxxxxxxxx", 
buildVars.addon_info['addon-name'], buildVars.addon_info['addon-version'])
+       ], lambda t, s, e : "Generating pot file %s" % t[0]),
+       suffix=".pot")
+env['BUILDERS']['gettextMergePotFile']=env.Builder(
+       action=env.Action(["xgettext --msgid-bugs-address='%s' 
--package-name='%s' --package-version='%s' --omit-header --no-location -c -o 
$TARGETS $SOURCES" %
+               ("nvda-translations@xxxxxxxxxxxxx", 
buildVars.addon_info['addon-name'], buildVars.addon_info['addon-version'])
+       ], lambda t, s, e : "Generating pot file %s" % t[0]),
+       suffix=".pot")
+
+def createAddonHelp(dir):
+       if not os.path.isfile("docHandler.py"):
+               return
+       plugindir = os.path.join(dir, "globalPlugins")
+       docFilename = 
"{addonName}_docHandler.py".format(addonName=buildVars.addon_info["addon-name"])
+       docPath = os.path.join(plugindir, docFilename)
+       docFileTarget = env.Command(docPath, "docHandler.py", Copy("$TARGET", 
"$SOURCE"))
+       env.Depends(addon, docFileTarget)
+       docsDir = os.path.join(dir, "doc")
+       if os.path.isfile("style.css"):
+               cssPath = os.path.join(docsDir, "style.css")
+               cssTarget = env.Command(cssPath, "style.css", Copy("$TARGET", 
"$SOURCE"))
+               env.Depends(addon, cssTarget)
+       if os.path.isfile("readme.md"):
+               readmePath = os.path.join(docsDir, "en", "readme.md")
+               readmeTarget = env.Command(readmePath, "readme.md", 
Copy("$TARGET", "$SOURCE"))
+               env.Depends(addon, readmeTarget)
+
+
+
+def createAddonBundleFromPath(path, dest):
+       """ Creates a bundle from a directory that contains an addon manifest 
file."""
+       basedir = os.path.abspath(path)
+       with zipfile.ZipFile(dest, 'w', zipfile.ZIP_DEFLATED) as z:
+               # FIXME: the include/exclude feature may or may not be useful. 
Also python files can be pre-compiled.
+               for dir, dirnames, filenames in os.walk(basedir):
+                       relativePath = os.path.relpath(dir, basedir)
+                       for filename in filenames:
+                               pathInBundle = os.path.join(relativePath, 
filename)
+                               absPath = os.path.join(dir, filename)
+                               if pathInBundle not in buildVars.excludedFiles: 
z.write(absPath, pathInBundle)
+       return dest
+
+def generateManifest(source, dest):
+       with codecs.open(source, "r", "utf-8") as f:
+               manifest_template = f.read()
+       manifest = manifest_template.format(**buildVars.addon_info)
+       with codecs.open(dest, "w", "utf-8") as f:
+               f.write(manifest)
+
+def generateTranslatedManifest(source, language, out):
+       _ = gettext.translation("nvda", localedir=os.path.join("addon", 
"locale"), languages=[language]).ugettext
+       vars = {}
+       for var in ("addon-summary", "addon-description"):
+               vars[var] = _(buildVars.addon_info[var])
+       with codecs.open(source, "r", "utf-8") as f:
+               manifest_template = f.read()
+       result = manifest_template.format(**vars)
+       with codecs.open(out, "w", "utf-8") as f:
+               f.write(result)
+
+def expandGlobs(files):
+       return [f for pattern in files for f in env.Glob(pattern)]
+
+addon = env.NVDAAddon(addonFile, env.Dir('addon'))
+
+langDirs = [f for f in env.Glob(os.path.join("addon", "locale", "*"))]
+
+#Allow all NVDA's gettext po files to be compiled in source/locale, and 
manifest files to be generated
+for dir in langDirs:
+       poFile = dir.File(os.path.join("LC_MESSAGES", "nvda.po"))
+       moFile=env.gettextMoFile(poFile)
+       env.Depends(moFile, poFile)
+       translatedManifest = 
env.NVDATranslatedManifest(dir.File("manifest.ini"), [moFile, 
os.path.join("manifest-translated.ini.tpl")])
+       env.Depends(translatedManifest, ["buildVars.py"])
+       env.Depends(addon, [translatedManifest, moFile])
+
+pythonFiles = expandGlobs(buildVars.pythonSources)
+for file in pythonFiles:
+       env.Depends(addon, file)
+
+#Convert markdown files to html
+createAddonHelp("addon") # We need at least doc in English and should append 
an item to Help menu
+for mdFile in env.Glob(os.path.join('addon', 'doc', '*', '*.md')):
+       htmlFile = env.markdown(mdFile)
+       env.Depends(htmlFile, mdFile)
+       env.Depends(addon, htmlFile)
+
+# Pot target
+i18nFiles = expandGlobs(buildVars.i18nSources)
+pot = env.gettextPotFile("%s.pot" % 
"{addon-name}".format(**buildVars.addon_info), i18nFiles)
+env.Alias('pot', pot)
+env.Depends(pot, i18nFiles)
+mergePot = env.gettextMergePotFile("%s-merge.pot" % 
"{addon-name}".format(**buildVars.addon_info), i18nFiles)
+env.Alias('mergePot', mergePot)
+env.Depends(mergePot, i18nFiles)
+
+# Generate Manifest path
+manifest = env.NVDAManifest(os.path.join("addon", "manifest.ini"), 
os.path.join("manifest.ini.tpl"))
+
+env.Depends(addon, manifest)
+env.Default(addon)

diff --git a/site_scons/site_tools/gettexttool/__init__.py 
b/site_scons/site_tools/gettexttool/__init__.py
new file mode 100644
index 0000000..fa3a937
--- /dev/null
+++ b/site_scons/site_tools/gettexttool/__init__.py
@@ -0,0 +1,49 @@
+""" This tool allows generation of gettext .mo compiled files, pot files from 
source code files
+and pot files for merging.
+
+Three new builders are added into the constructed environment:
+
+- gettextMoFile: generates .mo file from .pot file using msgfmt.
+- gettextPotFile: Generates .pot file from source code files.
+- gettextMergePotFile: Creates a .pot file appropriate for merging into 
existing .po files.
+
+To properly configure get text, define the following variables:
+
+- gettext_package_bugs_address
+- gettext_package_name
+- gettext_package_version
+
+
+"""
+from SCons.Action import Action
+
+def exists(env):
+       return True
+
+XGETTEXT_COMMON_ARGS = (
+       "--msgid-bugs-address='$gettext_package_bugs_address' "
+       "--package-name='$gettext_package_name' "
+       "--package-version='$gettext_package_version' "
+       "-c -o $TARGET $SOURCES"
+)
+
+def generate(env):
+       env.SetDefault(gettext_package_bugs_address="example@xxxxxxxxxxx")
+       env.SetDefault(gettext_package_name="")
+       env.SetDefault(gettext_package_version="")
+
+       env['BUILDERS']['gettextMoFile']=env.Builder(
+               action=Action("msgfmt -o $TARGET $SOURCE", "Compiling 
translation $SOURCE"),
+               suffix=".mo",
+               src_suffix=".po"
+       )
+
+       env['BUILDERS']['gettextPotFile']=env.Builder(
+               action=Action("xgettext " + XGETTEXT_COMMON_ARGS, "Generating 
pot file $TARGET"),
+               suffix=".pot")
+
+       env['BUILDERS']['gettextMergePotFile']=env.Builder(
+               action=Action("xgettext " + "--omit-header --no-location " + 
XGETTEXT_COMMON_ARGS,
+                       "Generating pot file $TARGET"),
+               suffix=".pot")
+

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

--

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/RapidSettings: ABuffEr: Various bug fixes, updated readme and template - commits-noreply