├── manifest-translated.ini.tpl
├── .gitignore
├── manifest.ini.tpl
├── .gitattributes
├── style.css
├── addon
├── globalPlugins
│ └── quickNotetaker
│ │ ├── addonConfig.py
│ │ ├── constants.py
│ │ ├── __init__.py
│ │ ├── notesManager.py
│ │ ├── settingsPanel.py
│ │ ├── helpers.py
│ │ └── dialogs.py
├── doc
│ └── zh_CN
│ │ └── readme.md
└── locale
│ ├── zh_CN
│ └── LC_MESSAGES
│ │ └── nvda.po
│ ├── he
│ └── LC_MESSAGES
│ │ └── nvda.po
│ ├── ar
│ └── LC_MESSAGES
│ │ └── nvda.po
│ ├── de
│ └── LC_MESSAGES
│ │ └── nvda.po
│ └── ru
│ └── LC_MESSAGES
│ └── nvda.po
├── site_scons
└── site_tools
│ └── gettexttool
│ └── __init__.py
├── todo.md
├── sconstruct
├── readme.md
└── COPYING.txt
/manifest-translated.ini.tpl:
--------------------------------------------------------------------------------
1 | summary = "{addon_summary}"
2 | description = """{addon_description}"""
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | addon/doc/*.css
2 | addon/doc/en/
3 | *_docHandler.py
4 | *.html
5 | *.ini
6 | *.mo
7 | *.pot
8 | *.py[co]
9 | *.nvda-addon
10 | .sconsign.dblite
11 |
--------------------------------------------------------------------------------
/manifest.ini.tpl:
--------------------------------------------------------------------------------
1 | name = {addon_name}
2 | summary = "{addon_summary}"
3 | description = """{addon_description}"""
4 | author = "{addon_author}"
5 | url = {addon_url}
6 | version = {addon_version}
7 | docFileName = {addon_docFileName}
8 | minimumNVDAVersion = {addon_minimumNVDAVersion}
9 | lastTestedNVDAVersion = {addon_lastTestedNVDAVersion}
10 | updateChannel = {addon_updateChannel}
11 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behaviour, in case users don't have core.autocrlf set.
2 | * text=auto
3 |
4 | # Try to ensure that po files in the repo does not include
5 | # source code line numbers.
6 | # Every person expected to commit po files should change their personal config file as described here:
7 | # https://mail.gnome.org/archives/kupfer-list/2010-June/msg00002.html
8 | *.po filter=cleanpo
9 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | body {
3 | font-family : Verdana, Arial, Helvetica, Sans-serif;
4 | line-height: 1.2em;
5 | }
6 | h1, h2 {text-align: center}
7 | dt {
8 | font-weight : bold;
9 | float : left;
10 | width: 10%;
11 | clear: left
12 | }
13 | dd {
14 | margin : 0 0 0.4em 0;
15 | float : left;
16 | width: 90%;
17 | display: block;
18 | }
19 | p { clear : both;
20 | }
21 | a { text-decoration : underline;
22 | }
23 | :active {
24 | text-decoration : none;
25 | }
26 | a:focus, a:hover {outline: solid}
27 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/addonConfig.py:
--------------------------------------------------------------------------------
1 | # addonConfig.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | import config
9 | import os
10 | import wx
11 |
12 |
13 | def initialize():
14 | configSpec = {
15 | "notesDocumentsPath": f"string(default={os.path.normpath(os.path.expanduser('~/documents/quickNotetaker'))})",
16 | "askWhereToSaveDocx": "boolean(default=False)",
17 | "openFileAfterCreation": "boolean(default=False)",
18 | "captureActiveWindowTitle": "boolean(default=True)",
19 | "rememberTakerSizeAndPos": "boolean(default=False)",
20 | "autoAlignText": "boolean(default=true)",
21 | "takerXPos": f"integer(default={wx.DefaultPosition.x})",
22 | "takerYPos": f"integer(default={wx.DefaultPosition.y})",
23 | "takerWidth": "integer(default=500)",
24 | "takerHeight": "integer(default=500)",
25 | }
26 | config.conf.spec["quickNotetaker"] = configSpec
27 |
28 |
29 | def getValue(key):
30 | return config.conf["quickNotetaker"][key]
31 |
32 |
33 | def setValue(key, value):
34 | config.conf["quickNotetaker"][key] = value
35 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/constants.py:
--------------------------------------------------------------------------------
1 | # constants.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | import globalVars
9 | import os
10 |
11 | CONFIG_PATH = globalVars.appArgs.configPath
12 |
13 | QUICK_NOTETAKER_PATH = os.path.join(
14 | CONFIG_PATH, "addons", "quickNotetaker", "globalPlugins")
15 |
16 | QUICK_NOTETAKER_PATH_DEV = os.path.join(
17 | CONFIG_PATH, "scratchpad", "globalPlugins", "quickNotetaker")
18 |
19 | # Remember to comment out in production
20 | # QUICK_NOTETAKER_PATH = QUICK_NOTETAKER_PATH_DEV
21 |
22 | DATA_DIR_PATH = os.path.join(CONFIG_PATH, "Quick Notetaker data")
23 |
24 | DATA_FILE_PATH = os.path.join(DATA_DIR_PATH, "notes.json")
25 |
26 | PANDOC_PATH = os.path.join(
27 | QUICK_NOTETAKER_PATH, "quickNotetaker", "lib", "pandoc-3.1.2", "pandoc")
28 |
29 | PANDOC_PATH_DEV = os.path.join(
30 | QUICK_NOTETAKER_PATH_DEV, "lib", "pandoc-3.1.2", "pandoc")
31 |
32 | # Remember to comment out in production
33 | # PANDOC_PATH = PANDOC_PATH_DEV
34 |
35 | TEMP_FILES_PATH = os.path.join(QUICK_NOTETAKER_PATH, "tempFiles")
36 |
37 | DEFAULT_DOCUMENTS_PATH = os.path.normpath(
38 | os.path.expanduser("~/documents/quickNotetaker"))
39 |
--------------------------------------------------------------------------------
/site_scons/site_tools/gettexttool/__init__.py:
--------------------------------------------------------------------------------
1 | """ This tool allows generation of gettext .mo compiled files, pot files from source code files
2 | and pot files for merging.
3 |
4 | Three new builders are added into the constructed environment:
5 |
6 | - gettextMoFile: generates .mo file from .pot file using msgfmt.
7 | - gettextPotFile: Generates .pot file from source code files.
8 | - gettextMergePotFile: Creates a .pot file appropriate for merging into existing .po files.
9 |
10 | To properly configure get text, define the following variables:
11 |
12 | - gettext_package_bugs_address
13 | - gettext_package_name
14 | - gettext_package_version
15 |
16 |
17 | """
18 | from SCons.Action import Action
19 |
20 |
21 | def exists(env):
22 | return True
23 |
24 |
25 | XGETTEXT_COMMON_ARGS = (
26 | "--msgid-bugs-address='$gettext_package_bugs_address' "
27 | "--package-name='$gettext_package_name' "
28 | "--package-version='$gettext_package_version' "
29 | "--keyword=pgettext:1c,2 "
30 | "-c -o $TARGET $SOURCES"
31 | )
32 |
33 |
34 | def generate(env):
35 | env.SetDefault(gettext_package_bugs_address="example@example.com")
36 | env.SetDefault(gettext_package_name="")
37 | env.SetDefault(gettext_package_version="")
38 |
39 | env['BUILDERS']['gettextMoFile'] = env.Builder(
40 | action=Action("msgfmt -o $TARGET $SOURCE", "Compiling translation $SOURCE"),
41 | suffix=".mo",
42 | src_suffix=".po"
43 | )
44 |
45 | env['BUILDERS']['gettextPotFile'] = env.Builder(
46 | action=Action("xgettext " + XGETTEXT_COMMON_ARGS, "Generating pot file $TARGET"),
47 | suffix=".pot")
48 |
49 | env['BUILDERS']['gettextMergePotFile'] = env.Builder(
50 | action=Action(
51 | "xgettext " + "--omit-header --no-location " + XGETTEXT_COMMON_ARGS,
52 | "Generating pot file $TARGET"
53 | ),
54 | suffix=".pot"
55 | )
56 |
--------------------------------------------------------------------------------
/todo.md:
--------------------------------------------------------------------------------
1 | ## Users suggestions
2 |
3 | Those are suggestions by users we document here. The suggestions haven't been discussed internally, so there is no guarantee they will make their way to production.
4 |
5 | * Allow the notes to be tagged. Example tags might be: personal, education, miscellaneous, etc.
6 | * Allow the notes to be organized according to their tags. Maybe a tree view can be used, maybe something else.
7 | * Find a mechanism to allow the user to select a text and then create a note using a key stroke without the need to open any other interface. To achieve this, I think that copying to the clipboard is a mandatory intermediate stage so the add-on can access the selected text.
8 | * Create a mechanism to get the page number the user was reading when they created the note. This info can be found in the status bar. Note however that each program might has a different method to obtain this data, so we need to take into consideration all popular programs and maybe handle each one separately.
9 | * Make the place where we save the notes themself configurable. Currently the notes are saved in NVDA's directory in app data, and the user has no option to change this. Having this option configurable will allow the user to save the notes in an online service such as One Drive or Dropbox for example, so the notes can be synced between different devices.
10 | * Create a mechanism to sync notes between different devices. Note that this feature will be very tricky to implement because of the complexity, and the feasibility of this as well when taking into account that NVDA may not ship with the required libraries.
11 | * Add support for markdown extensions, especially the popular ones such as those that support tables and checkboxes.
12 | * Make the label of the control to specify the place where to save the notes documents emphasize that this corresponds to the Word documents for the notes, and not the notes themself. Also we need to combine this with the option to let the user to choose where the notes themselves are stored, and to create an intuitive UX for this.
13 |
14 | ## Features we plan to investigate
15 |
16 | * Create an option to allow to send the note as email directly using the add-on interface. That is: we may have a button in the interface to open the default email program with the email body as the note content, and the subject as the title. The user needs to fil out the to field, maybe CC and BCC fields also. The first thing to check if this is technically possible.
17 | * Allow the user to press a key combination to start to record NVDA speech in a new note. The user will have another key combination to stop recording. The note maybe saved automatically without displaying any interface, or the Notetaker interface will be opened with the recorded speech as the note content so the user can edit. Maybe this behavior needs to be configurable.
18 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/__init__.py:
--------------------------------------------------------------------------------
1 | # __init__.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | from logHandler import log
9 | import globalPluginHandler
10 | from scriptHandler import script
11 | import gui
12 | from . import dialogs
13 | from .dialogs import NoteTakerDialog, NotesManagerDialog
14 | from .settingsPanel import QuickNotetakerPanel
15 | from . import notesManager
16 | import os
17 | from .constants import TEMP_FILES_PATH
18 | from . import addonConfig
19 | import api
20 | import addonHandler
21 |
22 |
23 | addonHandler.initTranslation()
24 |
25 |
26 | class GlobalPlugin(globalPluginHandler.GlobalPlugin):
27 |
28 | def __init__(self, *args, **kwargs):
29 | super(GlobalPlugin, self).__init__(*args, **kwargs)
30 | addonConfig.initialize()
31 | notesManager.initialize()
32 | try:
33 | os.mkdir(addonConfig.getValue("notesDocumentsPath"))
34 | except FileNotFoundError:
35 | # The user has no documents directory
36 | # Create the add-on documents folder in the user root folder instead
37 | addonConfig.setValue("notesDocumentsPath", os.path.expanduser("~\\QuickNotetaker"))
38 | os.mkdir(addonConfig.getValue("notesDocumentsPath"))
39 | except FileExistsError:
40 | pass
41 | try:
42 | os.mkdir(TEMP_FILES_PATH)
43 | except FileExistsError:
44 | pass
45 | gui.settingsDialogs.NVDASettingsDialog.categoryClasses.append(
46 | QuickNotetakerPanel)
47 |
48 | def terminate(self):
49 | super(GlobalPlugin, self).terminate()
50 | gui.settingsDialogs.NVDASettingsDialog.categoryClasses.remove(
51 | QuickNotetakerPanel)
52 | if not os.path.isdir(TEMP_FILES_PATH):
53 | return
54 | for file in os.listdir(TEMP_FILES_PATH):
55 | os.remove(os.path.join(TEMP_FILES_PATH, file))
56 |
57 | # Translators: the name of the add-on category in input gestures
58 | scriptCategory=_("Quick Notetaker")
59 |
60 | @ script(
61 | # Translators: the description for the command to open the notetaker dialog
62 | description=_("Shows the Notetaker interface for writing a new note"),
63 | gesture="kb:NVDA+alt+n"
64 | )
65 | def script_showNoteTakerUI(self, gesture):
66 | noteTitle=None
67 | if addonConfig.getValue("captureActiveWindowTitle"):
68 | noteTitle=api.getForegroundObject().name
69 | gui.mainFrame.prePopup()
70 | dialogs.noteTakerInstance=NoteTakerDialog(noteTitle=noteTitle)
71 | dialogs.noteTakerInstance.Show()
72 | gui.mainFrame.postPopup()
73 |
74 | @ script(
75 | description=_(
76 | # Translators: the description for the command to open the Notes Manager
77 | "Shows the Notes Manager interface for viewing and managing notes"),
78 | gesture="kb:NVDA+alt+v"
79 | )
80 | def script_showNotesManagerDialogUI(self, gesture):
81 | gui.mainFrame.prePopup()
82 | dialogs.notesManagerInstance=NotesManagerDialog()
83 | dialogs.notesManagerInstance.Show()
84 | gui.mainFrame.postPopup()
85 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/notesManager.py:
--------------------------------------------------------------------------------
1 | # notesManager.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | import os
9 | from logHandler import log
10 | from datetime import datetime
11 | import json
12 | from .constants import DATA_DIR_PATH, DATA_FILE_PATH
13 | from .helpers import getTitle
14 |
15 |
16 | class note(object):
17 | """A class that represents a single note"""
18 |
19 | def __init__(self, id="", title="", content="", lastEdited="", lastEditedStamp="", docxPath=""):
20 | if not id:
21 | self.id = datetime.now().strftime("%Y%m%d%H%M%S")
22 | self.title = getTitle(content)
23 | self.content = content
24 | self.lastEdited = self.prettyFormat(datetime.now())
25 | self.lastEditedStamp = datetime.now().strftime("%Y%m%d%H%M%S")
26 | self.docxPath = docxPath
27 | else:
28 | self.id = id
29 | self.title = title
30 | self.content = content
31 | self.lastEdited = lastEdited
32 | self.lastEditedStamp = lastEditedStamp
33 | self.docxPath = docxPath
34 |
35 | def updateNote(self, newContent, docxPath):
36 | if newContent is not None: #and self.content != newContent:
37 | # for now, allow the user to edit the content even though the content hasn't changed to be able to overcome the title bug present in the first release
38 | self.title = getTitle(newContent)
39 | self.content = newContent
40 | self.lastEdited = self.prettyFormat(datetime.now())
41 | self.lastEditedStamp = datetime.now().strftime("%Y%m%d%H%M%S")
42 | if docxPath is not None and self.docxPath != docxPath:
43 | self.docxPath = docxPath
44 |
45 | def prettyFormat(self, datetime):
46 | return f"{datetime.strftime('%d')}/{datetime.strftime('%m')}/{datetime.strftime('%Y')}, {datetime.strftime('%H')}:{datetime.strftime('%M')}"
47 |
48 |
49 | def initialize():
50 | if os.path.isfile(DATA_FILE_PATH):
51 | return
52 | log.debug(f"Creating a new file {os.path.abspath(DATA_FILE_PATH)}")
53 | try:
54 | if not os.path.isdir(DATA_DIR_PATH):
55 | os.mkdir(DATA_DIR_PATH)
56 | except:
57 | log.error("Can't create the data file directory!")
58 | raise
59 | try:
60 | with open(DATA_FILE_PATH, mode="x", encoding="utf8") as file:
61 | file.write("[]")
62 | except:
63 | log.error("Can't create data file")
64 | raise
65 |
66 |
67 | def loadAllNotes():
68 | with open(DATA_FILE_PATH, mode="r", encoding="utf8") as file:
69 | allNotes = json.load(file, object_hook=deserializeNote)
70 | return allNotes
71 |
72 |
73 | def deserializeNote(dict):
74 | deserializedNote = note(
75 | dict['id'], dict['title'], dict['content'], dict['lastEdited'], dict['lastEditedStamp'], dict['docxPath'])
76 | return deserializedNote
77 |
78 |
79 | def _dumpAllNotes(allNotes):
80 | # Backup the file content
81 | with open(DATA_FILE_PATH, mode="r", encoding="utf8") as file:
82 | allContent = file.read()
83 | # Sort all notes according to the last edited stamp in descending order
84 | allNotes.sort(key=lambda note: note.lastEditedStamp, reverse=True)
85 | try:
86 | with open(DATA_FILE_PATH, mode="w", encoding="utf8") as file:
87 | json.dump([note.__dict__ for note in allNotes],
88 | file, indent=4, ensure_ascii=False)
89 | except:
90 | with open(dataFilePath, mode="w", encoding="utf8") as file:
91 | file.write(allContent)
92 | raise
93 |
94 |
95 | def saveNewNote(noteContent, docxPath=""):
96 | newNote = note(content=noteContent, docxPath=docxPath)
97 | allNotes = loadAllNotes()
98 | allNotes.append(newNote)
99 | _dumpAllNotes(allNotes)
100 |
101 |
102 | def deleteNote(noteID):
103 | allNotes = loadAllNotes()
104 | for note in allNotes:
105 | if note.id == noteID:
106 | allNotes.remove(note)
107 | break
108 | _dumpAllNotes(allNotes)
109 |
110 |
111 | def updateNote(noteID, newContent=None, docxPath=None):
112 | allNotes = loadAllNotes()
113 | for note in allNotes:
114 | if note.id == noteID:
115 | note.updateNote(newContent, docxPath)
116 | break
117 | _dumpAllNotes(allNotes)
118 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/settingsPanel.py:
--------------------------------------------------------------------------------
1 | # settings.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | import os
9 | import gui
10 | import wx
11 | from . import addonConfig
12 | import addonHandler
13 |
14 | addonHandler.initTranslation()
15 |
16 |
17 | class QuickNotetakerPanel(gui.SettingsPanel):
18 |
19 | # Translators: the title of the Quick Notetaker panel in NVDA's settings
20 | title = _("Quick Notetaker")
21 |
22 | def makeSettings(self, settingsSizer):
23 | sHelper = gui.guiHelper.BoxSizerHelper(self, sizer=settingsSizer)
24 | # Translators: the label of the control in Quick Notetaker settings panel for choosing a default folder where the add-on documents will be saved
25 | directoryGroupText = _("Default documents directory:")
26 | groupSizer = wx.StaticBoxSizer(
27 | wx.VERTICAL, self, label=directoryGroupText)
28 | groupHelper = sHelper.addItem(
29 | gui.guiHelper.BoxSizerHelper(self, sizer=groupSizer))
30 | groupBox = groupSizer.GetStaticBox()
31 | # Translators: the label of a button to browse for a directory
32 | browseText = _("Browse...")
33 | dirDialogTitle = _(
34 | # Translators: The title of the dialog presented when browsing for the directory where quick notetaker documents will be stored
35 | "Select a default directory where the documents of Quick Notetaker will be stored")
36 | directoryPathHelper = gui.guiHelper.PathSelectionHelper(
37 | groupBox, browseText, dirDialogTitle)
38 | directoryEntryControl = groupHelper.addItem(directoryPathHelper)
39 | self.documentDirectoryEdit = directoryEntryControl.pathControl
40 | self.documentDirectoryEdit.Value = addonConfig.getValue(
41 | "notesDocumentsPath")
42 | askWhereToSaveDocxText = _(
43 | # Translators: the label of a check box in Quick Notetaker settings panel
44 | "Ask me each time &where to save the note's corresponding Microsoft Word document")
45 | self.askWhereToSaveDocxCheckbox = sHelper.addItem(
46 | wx.CheckBox(self, label=askWhereToSaveDocxText))
47 | self.askWhereToSaveDocxCheckbox.Value = addonConfig.getValue(
48 | "askWhereToSaveDocx")
49 | openFileAfterCreationText = _(
50 | # Translators: the label of a check box in Quick Notetaker settings panel
51 | "&Open the note's corresponding Microsoft Word document after saving or updating")
52 | self.openAfterCreationCheckbox = sHelper.addItem(
53 | wx.CheckBox(self, label=openFileAfterCreationText))
54 | self.openAfterCreationCheckbox.Value = addonConfig.getValue(
55 | "openFileAfterCreation")
56 | captureActiveWindowTitleText = _(
57 | # Translators: the label of a check box in Quick Notetaker settings panel
58 | "&Capture the active window title when creating a new note")
59 | self.captureActiveWindowTitleCheckbox = sHelper.addItem(
60 | wx.CheckBox(self, label=captureActiveWindowTitleText))
61 | self.captureActiveWindowTitleCheckbox.Value = addonConfig.getValue(
62 | "captureActiveWindowTitle")
63 | rememberTakerSizeAndPosText = _(
64 | # Translators: the label of a check box in Quick Notetaker settings panel
65 | "&Remember the note taker window size and position")
66 | self.rememberTakerSizeAndPosCheckbox = sHelper.addItem(
67 | wx.CheckBox(self, label=rememberTakerSizeAndPosText))
68 | self.rememberTakerSizeAndPosCheckbox.Value = addonConfig.getValue(
69 | "rememberTakerSizeAndPos")
70 | autoAlignTextText = _(
71 | # Translators: the label of a check box in Quick Notetaker settings panel
72 | "Au&to align text when editing notes (relevant for RTL languages)")
73 | self.autoAlignTextCheckbox = sHelper.addItem(
74 | wx.CheckBox(self, label=autoAlignTextText))
75 | self.autoAlignTextCheckbox.Value = addonConfig.getValue(
76 | "autoAlignText")
77 |
78 | def onSave(self):
79 | addonConfig.setValue(
80 | "notesDocumentsPath",
81 | os.path.normpath(self.documentDirectoryEdit.Value))
82 | addonConfig.setValue(
83 | "askWhereToSaveDocx",
84 | self.askWhereToSaveDocxCheckbox.Value)
85 | addonConfig.setValue(
86 | "openFileAfterCreation",
87 | self.openAfterCreationCheckbox.Value)
88 | addonConfig.setValue(
89 | "captureActiveWindowTitle",
90 | self.captureActiveWindowTitleCheckbox.Value)
91 | addonConfig.setValue(
92 | "rememberTakerSizeAndPos",
93 | self.rememberTakerSizeAndPosCheckbox.Value)
94 | addonConfig.setValue(
95 | "autoAlignText",
96 | self.autoAlignTextCheckbox.Value)
97 |
--------------------------------------------------------------------------------
/addon/doc/zh_CN/readme.md:
--------------------------------------------------------------------------------
1 | # NVDA 快捷笔记插件
2 |
3 | 快捷笔记插件是一个很好的工具,可以随时随地在用户使用的任何应用程序中快速而轻松地撰写笔记。
4 | 例如,无论用户是在观看视频,还是在参加Zoom、Teams 或 Google 会议,都可一件创建笔记。
5 | 只需按下 NVDA + Alt + n 组合键,屏幕的左上角就会出现一个浮动窗口。
6 | 随后就可以在新弹出的笔记窗口中创建笔记了。
7 |
8 | 在您每次创建笔记时都可以自动捕捉当前窗口的标题作为笔记的一部分,当然这是可选设置。
9 | 利用该特性,后续您可以通过笔记的标题从而得知这个笔记是在什么情况下创建的。
10 | 用户可以在插件的设置面板中调整该设置以决定插件是否自动捕捉当前窗口标题。
11 |
12 | ## Notetaker 对话框
13 |
14 | - 笔记编辑区。
15 |
16 | 当打开记事本界面时,焦点将处于这个编辑区。支持用Markdown(一种标记语言,可以轻松转换为 HTML格式)来撰写笔记内容。
17 | 想了解更多关于 Markdown 的更多信息,请访问[Markdown指南页面](https://www.markdownguide.org/)。
18 |
19 | - 预览笔记:在一个HTML窗口中查看已撰写的笔记。
20 |
21 | - 复制:将笔记内容复制到剪贴板上。
22 |
23 | - 复制 HTML 代码:复制笔记内容的 HTML 代码。对于那些用 Markdown 写作的人来说这是个很有用的功能。
24 |
25 | - 一个复选框,可以将笔记保存为 Microsoft Word 文档,或者更新相应的笔记(如果存在)。
26 |
27 | - 一个保存并关闭按钮。
28 |
29 | - 一个丢弃按钮,在需要时丢弃修改。当存在未保存的修改时,会向用户显示一条警告信息,询问您是否要退出并放弃所有更改。
30 |
31 | ## 笔记管理器界面
32 |
33 | ### 打开和关闭
34 |
35 | - NVDA + Alt + V 可以打开笔记管理器界面。
36 |
37 | - 使用 Escape 键或窗口底部的关闭按钮可以关闭该界面。
38 |
39 | ### 笔记列表
40 |
41 | 笔记是以表格的形式呈现的,其中包括。
42 |
43 | 1. 笔记的标题。如果笔记内容中不是自动补货的窗口标题,那么会将笔记内容的第一行是为标题。
44 |
45 | 2. 最后依次编辑的时间戳。
46 |
47 | 3. 笔记内容的预览文本。
48 |
49 | ### 笔记管理器界面中的可用选项
50 |
51 | - 查看笔记:在一个HTML窗口中查看笔记。
52 |
53 | - 编辑笔记:打开笔记,并在 Notetaker 界面中进行编辑。
54 |
55 | - 复制笔记:将笔记内容复制到剪贴板上。
56 |
57 | - 创建 Microsoft Word 文档。创建一个Microsoft Word文档
58 |
59 | - 在 Microsoft Word 中打开:打开该笔记的 Microsoft Word 版文档。
60 |
61 | - 复制 HTML 代码:复制该笔记的HTML代码。对于那些使用 Markdown 写作的人来说这是个很有用的功能
62 |
63 | - 删除笔记:在删除笔记前会显示一个警告。
64 |
65 | - 新建笔记:从这个界面可以进入Notetaker界面创建新笔记。
66 |
67 | - 打开设置:从这里也可以打开插件的设置。
68 |
69 | - 关闭:关闭该窗口。
70 |
71 | ## 插件的设置
72 |
73 | 插件设置是 NVDA 设置界面的一部分。
74 | 若想转到该设置,可使用 NVDA + n 打开 NVDA 菜单。
75 | 选择“选项” > “设置” 然后向下找到“快捷笔记”类别。
76 |
77 | 在设置界面,用户可以:
78 |
79 | - 默认文档目录:选择保存笔记的默认目录,快捷笔记文档将保存在该目录下。
80 | 可以点击“浏览”按钮以更改该目录。
81 |
82 | - 每次都询问我 Microsoft Word 文档保存到何处:一个复选框(默认情况下未选中)--显示选择文档位置的对话框。以便在笔记的每次保存或更新操作时让用户选择文档的保存位置。
83 |
84 | - 保存或更新后,打开笔记对应的Microsoft Word文档。一个复选框(默认情况下未选中)--允许用户选择是否在保存或更新操作后打开Microsoft Word文档。
85 |
86 | - 新建笔记时使用所聚焦窗口的标题作为笔记标题:一个复选框(默认选中)--允许捕捉用户在创建笔记时的当前窗口标题。此标题也会成为 Microsoft Word 文档的标题(如果有的话)。
87 |
88 | - 记住笔记窗口的大小和位置:一个复选框(默认情况下未选中)--创建或编辑笔记时记住上次笔记窗口的大小和位置。
89 | - 编辑笔记时自动对齐文本 (适用于从右到左的语言环境):
90 | 一个复选框(默认选中)--控制文本的对齐方式,这取决于您的语言环境,例如,如果使用的语言是阿拉伯语或希伯来语,选中此选项时将右对齐,如果语言是英语或法语,选中此选项时文本将左对齐。
91 |
92 | ## 键盘快捷键
93 |
94 | - NVDA + Alt + n:打开 Notetaker 界面。
95 |
96 | - NVDA + Alt + v:打开笔记管理器界面。
97 |
98 | ### 不同界面中的键盘快捷键(英文)
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
Interface
109 |
Command
110 |
Keyboard shortcut
111 |
112 |
113 |
114 |
115 |
Notetaker
116 |
Focus the note edit area
117 |
Alt + n
118 |
119 |
120 |
Notetaker
121 |
Align text to the right
122 |
Control + r
123 |
124 |
125 |
Notetaker
126 |
Align text to the left
127 |
Control + l
128 |
129 |
130 |
Notetaker
131 |
Preview note in an HTML window
132 |
Alt + r
133 |
134 |
135 |
Notetaker
136 |
Copy
137 |
Alt + p
138 |
139 |
140 |
Notetaker
141 |
Copy HTML code
142 |
Alt + h
143 |
144 |
145 |
Notetaker
146 |
Save note as a Microsoft Word document
147 |
Alt + w
148 |
149 |
150 |
Notetaker
151 |
Update the note corresponding Microsoft Word document
152 |
Alt + w
153 |
154 |
155 |
Notetaker
156 |
Save and close
157 |
Alt + s
158 |
159 |
160 |
Notetaker
161 |
Discard
162 |
Alt + d
163 |
164 |
165 |
Notetaker
166 |
Open notes Manager
167 |
Alt + m
168 |
169 |
170 |
Notes Manager
171 |
View note
172 |
Alt + v
173 |
174 |
175 |
Notes Manager
176 |
Edit note
177 |
Alt + e
178 |
179 |
180 |
Notes Manager
181 |
Copy note
182 |
Alt + p
183 |
184 |
185 |
Notes Manager
186 |
Open in Microsoft Word (if such a document exists)
187 |
Alt + o
188 |
189 |
190 |
Notes Manager
191 |
Create a word document for a saved note
192 |
Alt + w
193 |
194 |
195 |
Notes Manager
196 |
Copy HTML code
197 |
Alt + h
198 |
199 |
200 |
Notes Manager
201 |
Delete note
202 |
Alt + d
203 |
204 |
205 |
Notes Manager
206 |
New note
207 |
Alt + n
208 |
209 |
210 |
Notes Manager
211 |
Open settings
212 |
Alt + s
213 |
214 |
215 |
Notes Manager
216 |
Close the interface
217 |
Alt + c
218 |
219 |
220 |
The settings interface
221 |
Ask me each time where to save the note's corresponding Microsoft Word document
222 |
Alt + w
223 |
224 |
225 |
The settings interface
226 |
Open the note's corresponding Microsoft Word document after saving or updating
227 |
Alt + o
228 |
229 |
230 |
The settings interface
231 |
Capture the active window title when creating a new note
232 |
Alt + c
233 |
234 |
235 |
The settings interface
236 |
Remember the note taker window size and position
237 |
Alt + r
238 |
239 |
240 |
The settings interface
241 |
Auto align text when editing notes (relevant for RTL languages)
242 |
Alt + t
243 |
244 |
245 |
246 |
247 | ## 致谢
248 |
249 | - 插件与 Pandoc 密不可分, Pandoc 是一个很棒的工具,它能够在不同格式之间转换文档。没有此工具插件将无法实现现有功能。有关 Pandoc 的更多信息请[访问 Pandoc 主页](https://pandoc.org/)。
250 |
251 | - 插件还依赖于一个名为 Python Markdown 的包,关于此包的更多信息请访问[Github 页面](https://github.com/trentm/python-markdown2)。
252 |
253 | - 非常感谢 NV Access、插件作者以及贡献者!插件的很多设计灵感源于你们的作品和贡献,所以让我们一起保持这个伟大社区的活跃吧!
254 |
--------------------------------------------------------------------------------
/sconstruct:
--------------------------------------------------------------------------------
1 | # NVDA add-on template SCONSTRUCT file
2 | # Copyright (C) 2012-2021 Rui Batista, Noelia Martinez, Joseph Lee
3 | # This file is covered by the GNU General Public License.
4 | # See the file COPYING.txt for more details.
5 |
6 | import codecs
7 | import gettext
8 | import os
9 | import os.path
10 | import zipfile
11 | import sys
12 |
13 | # While names imported below are available by default in every SConscript
14 | # Linters aren't aware about them.
15 | # To avoid Flake8 F821 warnings about them they are imported explicitly.
16 | # When using other Scons functions please add them to the line below.
17 | from SCons.Script import BoolVariable, Builder, Copy, Environment, Variables
18 |
19 | sys.dont_write_bytecode = True
20 |
21 | # Bytecode should not be written for build vars module to keep the repository root folder clean.
22 | import buildVars # NOQA: E402
23 |
24 |
25 | def md2html(source, dest):
26 | import markdown
27 | # Use extensions if defined.
28 | mdExtensions = buildVars.markdownExtensions
29 | lang = os.path.basename(os.path.dirname(source)).replace('_', '-')
30 | localeLang = os.path.basename(os.path.dirname(source))
31 | try:
32 | _ = gettext.translation("nvda", localedir=os.path.join("addon", "locale"), languages=[localeLang]).gettext
33 | summary = _(buildVars.addon_info["addon_summary"])
34 | except Exception:
35 | summary = buildVars.addon_info["addon_summary"]
36 | title = "{addonSummary} {addonVersion}".format(
37 | addonSummary=summary, addonVersion=buildVars.addon_info["addon_version"]
38 | )
39 | headerDic = {
40 | "[[!meta title=\"": "# ",
41 | "\"]]": " #",
42 | }
43 | with codecs.open(source, "r", "utf-8") as f:
44 | mdText = f.read()
45 | for k, v in headerDic.items():
46 | mdText = mdText.replace(k, v, 1)
47 | htmlText = markdown.markdown(mdText, extensions=mdExtensions)
48 | # Optimization: build resulting HTML text in one go instead of writing parts separately.
49 | docText = "\n".join([
50 | "",
51 | "" % lang,
52 | "",
53 | ""
54 | "",
55 | "",
56 | "%s" % title,
57 | "\n",
58 | htmlText,
59 | "\n"
60 | ])
61 | with codecs.open(dest, "w", "utf-8") as f:
62 | f.write(docText)
63 |
64 |
65 | def mdTool(env):
66 | mdAction = env.Action(
67 | lambda target, source, env: md2html(source[0].path, target[0].path),
68 | lambda target, source, env: 'Generating % s' % target[0],
69 | )
70 | mdBuilder = env.Builder(
71 | action=mdAction,
72 | suffix='.html',
73 | src_suffix='.md',
74 | )
75 | env['BUILDERS']['markdown'] = mdBuilder
76 |
77 |
78 | vars = Variables()
79 | vars.Add("version", "The version of this build", buildVars.addon_info["addon_version"])
80 | vars.Add(BoolVariable("dev", "Whether this is a daily development version", False))
81 | vars.Add("channel", "Update channel for this build", buildVars.addon_info["addon_updateChannel"])
82 |
83 | env = Environment(variables=vars, ENV=os.environ, tools=['gettexttool', mdTool])
84 | env.Append(**buildVars.addon_info)
85 |
86 | if env["dev"]:
87 | import datetime
88 | buildDate = datetime.datetime.now()
89 | year, month, day = str(buildDate.year), str(buildDate.month), str(buildDate.day)
90 | env["addon_version"] = "".join([year, month.zfill(2), day.zfill(2), "-dev"])
91 | env["channel"] = "dev"
92 | elif env["version"] is not None:
93 | env["addon_version"] = env["version"]
94 | if "channel" in env and env["channel"] is not None:
95 | env["addon_updateChannel"] = env["channel"]
96 |
97 | buildVars.addon_info["addon_version"] = env["addon_version"]
98 | buildVars.addon_info["addon_updateChannel"] = env["addon_updateChannel"]
99 |
100 | addonFile = env.File("${addon_name}-${addon_version}.nvda-addon")
101 |
102 |
103 | def addonGenerator(target, source, env, for_signature):
104 | action = env.Action(
105 | lambda target, source, env: createAddonBundleFromPath(source[0].abspath, target[0].abspath) and None,
106 | lambda target, source, env: "Generating Addon %s" % target[0]
107 | )
108 | return action
109 |
110 |
111 | def manifestGenerator(target, source, env, for_signature):
112 | action = env.Action(
113 | lambda target, source, env: generateManifest(source[0].abspath, target[0].abspath) and None,
114 | lambda target, source, env: "Generating manifest %s" % target[0]
115 | )
116 | return action
117 |
118 |
119 | def translatedManifestGenerator(target, source, env, for_signature):
120 | dir = os.path.abspath(os.path.join(os.path.dirname(str(source[0])), ".."))
121 | lang = os.path.basename(dir)
122 | action = env.Action(
123 | lambda target, source, env: generateTranslatedManifest(source[1].abspath, lang, target[0].abspath) and None,
124 | lambda target, source, env: "Generating translated manifest %s" % target[0]
125 | )
126 | return action
127 |
128 |
129 | env['BUILDERS']['NVDAAddon'] = Builder(generator=addonGenerator)
130 | env['BUILDERS']['NVDAManifest'] = Builder(generator=manifestGenerator)
131 | env['BUILDERS']['NVDATranslatedManifest'] = Builder(generator=translatedManifestGenerator)
132 |
133 |
134 | def createAddonHelp(dir):
135 | docsDir = os.path.join(dir, "doc")
136 | if os.path.isfile("style.css"):
137 | cssPath = os.path.join(docsDir, "style.css")
138 | cssTarget = env.Command(cssPath, "style.css", Copy("$TARGET", "$SOURCE"))
139 | env.Depends(addon, cssTarget)
140 | if os.path.isfile("readme.md"):
141 | readmePath = os.path.join(docsDir, buildVars.baseLanguage, "readme.md")
142 | readmeTarget = env.Command(readmePath, "readme.md", Copy("$TARGET", "$SOURCE"))
143 | env.Depends(addon, readmeTarget)
144 |
145 |
146 | def createAddonBundleFromPath(path, dest):
147 | """ Creates a bundle from a directory that contains an addon manifest file."""
148 | basedir = os.path.abspath(path)
149 | with zipfile.ZipFile(dest, 'w', zipfile.ZIP_DEFLATED) as z:
150 | # FIXME: the include/exclude feature may or may not be useful. Also python files can be pre-compiled.
151 | for dir, dirnames, filenames in os.walk(basedir):
152 | relativePath = os.path.relpath(dir, basedir)
153 | for filename in filenames:
154 | pathInBundle = os.path.join(relativePath, filename)
155 | absPath = os.path.join(dir, filename)
156 | if pathInBundle not in buildVars.excludedFiles:
157 | z.write(absPath, pathInBundle)
158 | return dest
159 |
160 |
161 | def generateManifest(source, dest):
162 | addon_info = buildVars.addon_info
163 | with codecs.open(source, "r", "utf-8") as f:
164 | manifest_template = f.read()
165 | manifest = manifest_template.format(**addon_info)
166 | with codecs.open(dest, "w", "utf-8") as f:
167 | f.write(manifest)
168 |
169 |
170 | def generateTranslatedManifest(source, language, out):
171 | _ = gettext.translation("nvda", localedir=os.path.join("addon", "locale"), languages=[language]).gettext
172 | vars = {}
173 | for var in ("addon_summary", "addon_description"):
174 | vars[var] = _(buildVars.addon_info[var])
175 | with codecs.open(source, "r", "utf-8") as f:
176 | manifest_template = f.read()
177 | result = manifest_template.format(**vars)
178 | with codecs.open(out, "w", "utf-8") as f:
179 | f.write(result)
180 |
181 |
182 | def expandGlobs(files):
183 | return [f for pattern in files for f in env.Glob(pattern)]
184 |
185 |
186 | addon = env.NVDAAddon(addonFile, env.Dir('addon'))
187 |
188 | langDirs = [f for f in env.Glob(os.path.join("addon", "locale", "*"))]
189 |
190 | # Allow all NVDA's gettext po files to be compiled in source/locale, and manifest files to be generated
191 | for dir in langDirs:
192 | poFile = dir.File(os.path.join("LC_MESSAGES", "nvda.po"))
193 | moFile = env.gettextMoFile(poFile)
194 | env.Depends(moFile, poFile)
195 | translatedManifest = env.NVDATranslatedManifest(
196 | dir.File("manifest.ini"),
197 | [moFile, os.path.join("manifest-translated.ini.tpl")]
198 | )
199 | env.Depends(translatedManifest, ["buildVars.py"])
200 | env.Depends(addon, [translatedManifest, moFile])
201 |
202 | pythonFiles = expandGlobs(buildVars.pythonSources)
203 | for file in pythonFiles:
204 | env.Depends(addon, file)
205 |
206 | # Convert markdown files to html
207 | # We need at least doc in English and should enable the Help button for the add-on in Add-ons Manager
208 | createAddonHelp("addon")
209 | for mdFile in env.Glob(os.path.join('addon', 'doc', '*', '*.md')):
210 | htmlFile = env.markdown(mdFile)
211 | env.Depends(htmlFile, mdFile)
212 | env.Depends(addon, htmlFile)
213 |
214 | # Pot target
215 | i18nFiles = expandGlobs(buildVars.i18nSources)
216 | gettextvars = {
217 | 'gettext_package_bugs_address': 'nvda-translations@groups.io',
218 | 'gettext_package_name': buildVars.addon_info['addon_name'],
219 | 'gettext_package_version': buildVars.addon_info['addon_version']
220 | }
221 |
222 | pot = env.gettextPotFile("${addon_name}.pot", i18nFiles, **gettextvars)
223 | env.Alias('pot', pot)
224 | env.Depends(pot, i18nFiles)
225 | mergePot = env.gettextMergePotFile("${addon_name}-merge.pot", i18nFiles, **gettextvars)
226 | env.Alias('mergePot', mergePot)
227 | env.Depends(mergePot, i18nFiles)
228 |
229 | # Generate Manifest path
230 | manifest = env.NVDAManifest(os.path.join("addon", "manifest.ini"), os.path.join("manifest.ini.tpl"))
231 | # Ensure manifest is rebuilt if buildVars is updated.
232 | env.Depends(manifest, "buildVars.py")
233 |
234 | env.Depends(addon, manifest)
235 | env.Default(addon)
236 | env.Clean(addon, ['.sconsign.dblite', 'addon/doc/' + buildVars.baseLanguage + '/'])
237 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Quick Notetaker add-on for NVDA
2 |
3 | The Quick Notetaker add-on is a wonderful tool which allows writing
4 | notes quickly and easily anytime and from any app the user is using.
5 | Whether the user is watching a video for example, or participating in a
6 | meeting on Zoom, teams or Google meet, they can easily and smoothly open
7 | the notetaker and take a note. In order to create a quick note, NVDA +
8 | Alt + n key combination can be used, a floating window appears at the
9 | top left corner of the screen, so the note can be typed there.
10 |
11 | Every note that is being Created can optionally get the active window
12 | title, and as such, the note content can get the context in which this
13 | note was created by having the note title as the active window title the
14 | user was using. This behavior can be changed from the add-on settings,
15 | where the user can decide whether the active window title is captured
16 | when creating a new note.
17 |
18 | ## The Notetaker dialog
19 |
20 | - The note edit area: When opening the Notetaker interface the focus
21 | will be in this edit area. Writing with Markdown (a markup language
22 | to easily produce HTML content) is supported also. For more info on
23 | Markdown visit [the Markdown guide
24 | page](https://www.markdownguide.org/).
25 |
26 | - Preview note: to view the note in an HTML window.
27 |
28 | - Copy: to copy the note as is to the clipboard.
29 |
30 | - Copy HTML code: to copy the HTML code representing the note. A
31 | useful feature for those who write in Markdown.
32 |
33 | - A checkbox to allow saving the note as Microsoft Word also, or updating the corresponding one if it exists.
34 |
35 | - A save and close button.
36 |
37 | - A discard button to discard changes when desired. When unsaved changes exist, a warning message is displayed to the user asking if they are sure they want to exit and discard their changes.
38 |
39 | ## The Notes Manager interface
40 |
41 | ### Opening and closing this interface
42 |
43 | - NVDA + Alt + v will launch the Notes Manager interface.
44 |
45 | - Using either the Escape key or the close button found at the bottom
46 | of this window will close this interface.
47 |
48 | ### The notes list
49 |
50 | The notes are organized in a tabular list which includes:
51 |
52 | 1. The note title: If the note hasn’t got the active window title, the
53 | first line of the note will be the note title displayed in this
54 | list.
55 |
56 | 2. Last edited time stamp.
57 |
58 | 3. A preview text of the note content.
59 |
60 | ### The options available in Notes Manager interface
61 |
62 | - View note: to view the note in an HTML window.
63 |
64 | - Edit note: opens the note to be edited using Notetaker interface.
65 |
66 | - Copy note: copies the note content as is to the clipboard.
67 |
68 | - Create a Microsoft Word document: Creates a Microsoft Word document
69 | representing this note in case it has no such document.
70 |
71 | - Open in Microsoft Word: opens the Microsoft Word document attached
72 | to this note in case it has a one.
73 |
74 | - Copy HTML code: copies the HTML code representing this note. A
75 | useful feature for those who write in Markdown.
76 |
77 | - Delete note: displays a warning before performing the note deletion.
78 |
79 | - New note: the Notetaker interface can be reached from this interface
80 | to create a new note.
81 |
82 | - Open settings: opening the add-on settings is also possible from
83 | here.
84 |
85 | - Close: to close the window.
86 |
87 | ## The add-on settings
88 |
89 | The add-on settings are a part of NVDA’s settings interface. To reach
90 | those settings, the user needs to open the NVDA menu using NVDA key + n,
91 | choose preferences > settings, and then arrow down until reaching
92 | Quick Notetaker category.
93 |
94 | Using the settings interface the user can:
95 |
96 | - Default documents directory: to choose the default directory where
97 | Quick Notetaker documents will be saved. The user can press the
98 | “Browse” button to change the path of this directory.
99 |
100 | - Ask me each time where to save the note's corresponding Microsoft
101 | Word document: a checkbox (not checked by default) – to show the
102 | dialog for choosing the location where the document will be saved on
103 | each save or update operation for the note’s Microsoft Word document
104 | if such a one exists.
105 |
106 | - Open the note's corresponding Microsoft Word document after saving
107 | or updating: a checkbox (not checked by default) – to allow the user
108 | to choose whether the Microsoft Word document will be opened after a
109 | save or update operation in case the note has such document.
110 |
111 | - Capture the active window title when creating a new note: a checkbox
112 | (checked by default) – to allow the note to get the active window
113 | title the user was using when they created the note. This title will
114 | be also the title of the Microsoft Word document for the note in
115 | case it has a one.
116 |
117 | - Remember the note taker window size and position: a checkbox (not
118 | checked by default) – to tell the add-on to remember the size and
119 | the position of the Notetaker dialog when creating or editing a
120 | note. As such, when the user opens the dialog next time, the
121 | position and the size will be the same as the last time the dialog
122 | was used. The default position of this dialog is at the top left
123 | corner of the screen.
124 |
125 | - Auto align text when editing notes (relevant for RTL languages): a
126 | checkbox (checked by default) – to control whether the text when
127 | creating or editing a note should be auto aligned according to the
128 | language used. This is mostly relevant for right to left languages.
129 | For example, if the language used is Arabic or Hebrew, then the text
130 | will be right aligned when this option is chosen, if the language is
131 | English or French, then the text will be left aligned.
132 |
133 | ## Keyboard shortcuts
134 |
135 | - NVDA + Alt + n: to open the Notetaker interface.
136 |
137 | - NVDA + Alt + v: to open the Notes Manager interface.
138 |
139 | ### Keyboard shortcuts in the different interfaces
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
Interface
150 |
Command
151 |
Keyboard shortcut
152 |
153 |
154 |
155 |
156 |
Notetaker
157 |
Focus the note edit area
158 |
Alt + n
159 |
160 |
161 |
Notetaker
162 |
Align text to the right
163 |
Control + r
164 |
165 |
166 |
Notetaker
167 |
Align text to the left
168 |
Control + l
169 |
170 |
171 |
Notetaker
172 |
Preview note in an HTML window
173 |
Alt + r
174 |
175 |
176 |
Notetaker
177 |
Copy
178 |
Alt + p
179 |
180 |
181 |
Notetaker
182 |
Copy HTML code
183 |
Alt + h
184 |
185 |
186 |
Notetaker
187 |
Save note as a Microsoft Word document
188 |
Alt + w
189 |
190 |
191 |
Notetaker
192 |
Update the note corresponding Microsoft Word document
193 |
Alt + w
194 |
195 |
196 |
Notetaker
197 |
Save and close
198 |
Alt + s
199 |
200 |
201 |
Notetaker
202 |
Discard
203 |
Alt + d
204 |
205 |
206 |
Notetaker
207 |
Open notes Manager
208 |
Alt + m
209 |
210 |
211 |
Notes Manager
212 |
View note
213 |
Alt + v
214 |
215 |
216 |
Notes Manager
217 |
Edit note
218 |
Alt + e
219 |
220 |
221 |
Notes Manager
222 |
Copy note
223 |
Alt + p
224 |
225 |
226 |
Notes Manager
227 |
Open in Microsoft Word (if such a document exists)
228 |
Alt + o
229 |
230 |
231 |
Notes Manager
232 |
Create a word document for a saved note
233 |
Alt + w
234 |
235 |
236 |
Notes Manager
237 |
Copy HTML code
238 |
Alt + h
239 |
240 |
241 |
Notes Manager
242 |
Delete note
243 |
Alt + d
244 |
245 |
246 |
Notes Manager
247 |
New note
248 |
Alt + n
249 |
250 |
251 |
Notes Manager
252 |
Open settings
253 |
Alt + s
254 |
255 |
256 |
Notes Manager
257 |
Close the interface
258 |
Alt + c
259 |
260 |
261 |
The settings interface
262 |
Ask me each time where to save the note's corresponding Microsoft Word document
263 |
Alt + w
264 |
265 |
266 |
The settings interface
267 |
Open the note's corresponding Microsoft Word document after saving or updating
268 |
Alt + o
269 |
270 |
271 |
The settings interface
272 |
Capture the active window title when creating a new note
273 |
Alt + c
274 |
275 |
276 |
The settings interface
277 |
Remember the note taker window size and position
278 |
Alt + r
279 |
280 |
281 |
The settings interface
282 |
Auto align text when editing notes (relevant for RTL languages)
283 |
Alt + t
284 |
285 |
286 |
287 |
288 | ## Acknowledgements
289 |
290 | - The add-on comes bundled with Pandoc, a wonderful tool which allows
291 | converting documents between different formats. Without this tool
292 | the add-on won’t be able to offer the capabilities it offers. For
293 | more info on Pandoc [visit the Pandoc
294 | homepage](https://pandoc.org/).
295 |
296 | - The add-on also relies on a Python Markdown package called
297 | markdown2. For more info on this package [visit the package GitHub
298 | page](https://github.com/trentm/python-markdown2).
299 |
300 | - A great thanks to NV Access, add-on authors, and contributors!
301 | Several parts of the add-on were inspired by your magnificent work
302 | and effort, so please keep up this brilliant ecosystem and the
303 | cooperation.
304 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/helpers.py:
--------------------------------------------------------------------------------
1 | # helpers.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | from .constants import PANDOC_PATH, TEMP_FILES_PATH, DEFAULT_DOCUMENTS_PATH
9 | import subprocess
10 | import re
11 | import wx
12 | from .lib.markdown2 import markdown
13 | import threading
14 | import os
15 | from . import addonConfig
16 | from logHandler import log
17 | import unicodedata
18 | from enum import Enum
19 | from urllib.parse import urlparse
20 | import addonHandler
21 |
22 | addonHandler.initTranslation()
23 |
24 |
25 | def saveAsWord(mdContent, filePath, callback, *args):
26 | saveThread = threading.Thread(target=_saveAsWord, args=(
27 | mdContent, filePath, callback, *args), daemon=True)
28 | saveThread.start()
29 |
30 |
31 | def _saveAsWord(mdContent, filePath, callBack, *args):
32 | title = getTitle(mdContent)
33 | if not os.path.isdir(TEMP_FILES_PATH):
34 | os.mkdir(TEMP_FILES_PATH)
35 | with open(f"{TEMP_FILES_PATH}/{title}.md", mode="w+", encoding="utf8") as input:
36 | input.write(handleMdContent(mdContent))
37 | dirWasChanged = False
38 | if filePath == "":
39 | outputFilePath, dirWasChanged = _findAvailablePath(
40 | addonConfig.getValue("notesDocumentsPath"), title, "docx")
41 | else:
42 | outputFilePath = filePath
43 | outputFilePath, result = _runPandocCommand(
44 | title, outputFilePath, isRtlDocument(mdContent))
45 | dirWasChanged = dirWasChanged or result
46 | if callBack:
47 | callBack(outputFilePath, dirWasChanged, mdContent, *args)
48 | if addonConfig.getValue("openFileAfterCreation"):
49 | os.startfile(outputFilePath)
50 |
51 |
52 | def _runPandocCommand(fileTitle, outputFilePath, isHtmlDocument):
53 | pandocArgs = [PANDOC_PATH, "-f", "markdown", "-t",
54 | "docx", "-s", "-i", f"{TEMP_FILES_PATH}/{fileTitle}.md"]
55 | if isHtmlDocument:
56 | pandocArgs.extend(["-V", "dir[=rtl]"])
57 | pandocArgs.append("-o")
58 | startupInfo = subprocess.STARTUPINFO()
59 | startupInfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
60 | pandocArgs.append(outputFilePath)
61 | try:
62 | subprocess.run(pandocArgs, check=True, startupinfo=startupInfo)
63 | return outputFilePath, False
64 | except subprocess.CalledProcessError:
65 | pandocArgs.remove(outputFilePath)
66 | if not os.path.isdir(addonConfig.getValue("notesDocumentsPath")):
67 | os.mkdir(addonConfig.getValue("notesDocumentsPath"))
68 | log.debug(
69 | "the specified directory name is invalid! Reverting to the user default one.")
70 | outputFilePath = os.path.join(addonConfig.getValue(
71 | "notesDocumentsPath"), f"{fileTitle}.docx")
72 | pandocArgs.append(outputFilePath)
73 | try:
74 | subprocess.run(pandocArgs, check=True, startupinfo=startupInfo)
75 | return outputFilePath, True
76 | except subprocess.CalledProcessError:
77 | pandocArgs.remove(outputFilePath)
78 | if not os.path.isdir(DEFAULT_DOCUMENTS_PATH):
79 | os.mkdir(DEFAULT_DOCUMENTS_PATH)
80 | log.debug(
81 | "The specified directory name is invalid! Reverting to the add-on default one.")
82 | outputFilePath = os.path.join(DEFAULT_DOCUMENTS_PATH, f"{fileTitle}.docx")
83 | pandocArgs.append(outputFilePath)
84 | try:
85 | subprocess.run(pandocArgs, check=True, startupinfo=startupInfo)
86 | return outputFilePath, True
87 | except subprocess.CalledProcessError:
88 | raise
89 |
90 |
91 | def openInWord(filePath, callback, *args):
92 | openThread = threading.Thread(
93 | target=_openInWord, args=(filePath, callback, *args,), daemon=True)
94 | openThread.start()
95 |
96 |
97 | def _openInWord(filePath, callback, *args):
98 | result = False
99 | try:
100 | os.startfile(filePath)
101 | result = True
102 | except:
103 | pass
104 | if callback:
105 | callback(result, *args)
106 |
107 |
108 | def _findAvailablePath(dirName, fileTitle, extension):
109 | """Finds available file path if the given one is already used.
110 | We need this to avoid over riding existing files content"""
111 | dirWasChanged = False
112 | if not os.path.isdir(dirName):
113 | try:
114 | os.mkdir(dirName)
115 | except:
116 | log.debug(
117 | "The user default directory name is invalid! Reverting to the user default one.")
118 | if not os.path.isdir(DEFAULT_DOCUMENTS_PATH):
119 | os.mkdir(DEFAULT_DOCUMENTS_PATH)
120 | dirName = DEFAULT_DOCUMENTS_PATH
121 | dirWasChanged = True
122 | candidatePath = os.path.join(dirName, f"{fileTitle}.{extension}")
123 | if not os.path.isfile(candidatePath):
124 | return candidatePath, dirWasChanged
125 | for i in range(50):
126 | candidatePath = os.path.join(
127 | dirName, f"{fileTitle} ({i + 1}).{extension}")
128 | if not os.path.isfile(candidatePath):
129 | return candidatePath, dirWasChanged
130 |
131 |
132 | #: A regex for matching a URL
133 | #: Taken from https://gist.githubusercontent.com/nishad/ff5d02394afaf8cca5818f023fb88a21/raw/cc631328b9bfc0750379847ecbe415b4df69aa67/urlmarker.py
134 | urlPatternText =\
135 | r"""(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(?)+", " ", htmlText)
192 | # Remove extra spaces if any
193 | extracted = _removeExtraSpaces(extracted)
194 | return extracted
195 |
196 |
197 | def _removeExtraSpaces(text):
198 | text = re.sub(r" +", " ", text)
199 | text = text.strip()
200 | return text
201 |
202 |
203 | def _isRtlParagraph(paragraph):
204 | """determines if the given paragraph is rtl by relying on the first none html text letter of the paragraph"""
205 | rtlClasses = ["R", "AL", "AN"]
206 | # Delete HTML markup if it exists
207 | paragraphWithoutHtml = retrieveTextFromHtml(paragraph)
208 | lettersOnly = re.sub(r"\W+", "", paragraphWithoutHtml)
209 | if not lettersOnly:
210 | return None
211 | if unicodedata.bidirectional(lettersOnly[0]) in rtlClasses:
212 | return True
213 | else:
214 | return False
215 |
216 |
217 | def _makeRtl(content):
218 | """Makes the text rtl if needed by wrapping each paragraph starting with RTL char with a div which has dir = rtl"""
219 | paragraphs = content.split("\n\n")
220 | result = []
221 | for paragraph in paragraphs:
222 | if _isRtlParagraph(paragraph):
223 | result.append(
224 | '
\n%s\n
' % paragraph)
225 | else:
226 | result.append('
\n%s\n
' % paragraph)
227 | return "\n\n".join(result)
228 |
229 |
230 | def isRtlDocument(content):
231 | """Determines if the document is RTL by checking if the document has atleast an rtl paragraph. If it has, then the document is rtl"""
232 | paragraphs = content.split("\n\n")
233 | for paragraph in paragraphs:
234 | if _isRtlParagraph(paragraph):
235 | return True
236 | return False
237 |
238 |
239 | class Align(Enum):
240 | ALIGN_TO_LEFT = 1
241 | ALIGN_TO_RIGHT = 2
242 | NO_CHANGE = 3
243 |
244 |
245 | def handleTextAlignment(text, currentAlignment):
246 | """Determines the alignment of the text relying on the first letter found in the text"""
247 | rtlClasses = ["R", "AL", "AN"]
248 | # Delete HTML markup if it exists
249 | lettersOnly = re.sub(r"\W+", "", text)
250 | if not lettersOnly or not addonConfig.getValue("autoAlignText"):
251 | return Align.NO_CHANGE
252 | if unicodedata.bidirectional(lettersOnly[0]) in rtlClasses and currentAlignment != wx.Layout_RightToLeft:
253 | return Align.ALIGN_TO_RIGHT
254 | elif not unicodedata.bidirectional(lettersOnly[0]) in rtlClasses and currentAlignment != wx.Layout_LeftToRight:
255 | return Align.ALIGN_TO_LEFT
256 | else:
257 | return Align.NO_CHANGE
258 |
--------------------------------------------------------------------------------
/addon/locale/zh_CN/LC_MESSAGES/nvda.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the 'quickNotetaker' package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | msgid ""
7 | msgstr ""
8 | "Project-Id-Version: 'quickNotetaker' '1.0'\n"
9 | "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n"
10 | "POT-Creation-Date: 2021-10-08 21:49+0800\n"
11 | "PO-Revision-Date: 2021-10-08 21:50+0800\n"
12 | "Last-Translator: Mohammad Suliman \n"
13 | "Language-Team: Cary-rowen \n"
14 | "Language: zh\n"
15 | "MIME-Version: 1.0\n"
16 | "Content-Type: text/plain; charset=UTF-8\n"
17 | "Content-Transfer-Encoding: 8bit\n"
18 | "Plural-Forms: nplurals=1; plural=0;\n"
19 | "X-Generator: Poedit 2.4.3\n"
20 |
21 | #. Translators: the name of the add-on category in input gestures
22 | #. Translators: the title of the Quick Notetaker panel in NVDA's settings
23 | #. Add-on summary, usually the user visible name of the addon.
24 | #. Translators: Summary for this add-on
25 | #. to be shown on installation and add-on information found in Add-ons Manager.
26 | #: addon\globalPlugins\quickNotetaker\__init__.py:58
27 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:20 buildVars.py:23
28 | msgid "Quick Notetaker"
29 | msgstr "快捷笔记"
30 |
31 | #. Translators: the description for the command to open the notetaker dialog
32 | #: addon\globalPlugins\quickNotetaker\__init__.py:62
33 | msgid "Shows the Notetaker interface for writing a new note"
34 | msgstr "显示新建笔记界面,用于创建新的笔记。"
35 |
36 | #. Translators: the description for the command to open the Notes Manager
37 | #: addon\globalPlugins\quickNotetaker\__init__.py:77
38 | msgid "Shows the Notes Manager interface for viewing and managing notes"
39 | msgstr "显示笔记管理器界面,用于查看和管理笔记"
40 |
41 | #. Translators: the title for the Quick Notetaker Notetaker window
42 | #: addon\globalPlugins\quickNotetaker\dialogs.py:77
43 | msgid "Notetaker - Quick Notetaker"
44 | msgstr "Notetaker - 快捷笔记"
45 |
46 | #. Translators: a lable of a button in Notetaker dialog
47 | #: addon\globalPlugins\quickNotetaker\dialogs.py:92
48 | msgid "Open Notes &Manager..."
49 | msgstr "打开笔记管理器(&M)..."
50 |
51 | #. Translators: a lable of a button in Notetaker dialog
52 | #: addon\globalPlugins\quickNotetaker\dialogs.py:101
53 | msgid "P&review note..."
54 | msgstr "预览笔记(&P)..."
55 |
56 | #. Translators: a lable of a button in Notetaker dialog
57 | #: addon\globalPlugins\quickNotetaker\dialogs.py:104
58 | msgid "Co&py"
59 | msgstr "复制(&C)"
60 |
61 | #. Translators: a lable of a button in Notetaker dialog
62 | #. Translaters: The lable of a button in Notes Manager dialog
63 | #: addon\globalPlugins\quickNotetaker\dialogs.py:109
64 | #: addon\globalPlugins\quickNotetaker\dialogs.py:392
65 | msgid "Copy &HTML code"
66 | msgstr "复制 HTML 代码(&H)..."
67 |
68 | #. Translators: The lable of the note content edit area in Notetaker dialog
69 | #: addon\globalPlugins\quickNotetaker\dialogs.py:115
70 | msgid "&Note content:"
71 | msgstr "笔记内容(&N)"
72 |
73 | #: addon\globalPlugins\quickNotetaker\dialogs.py:135
74 | msgid "Update the corresponding Microsoft &Word document also"
75 | msgstr "更新相应的 Microsoft Word 文档(&W)"
76 |
77 | #. Translators: The label of the check box in Notetaker dialog when creating a new note or when editing an existing note with no Word document attached to it
78 | #: addon\globalPlugins\quickNotetaker\dialogs.py:138
79 | msgid "Save as Microsoft &Word document also"
80 | msgstr "另存为 Microsoft Word 文档(&W)"
81 |
82 | #. Translators: a lable of a button in Notetaker dialog
83 | #: addon\globalPlugins\quickNotetaker\dialogs.py:148
84 | msgid "&Save and close"
85 | msgstr "保存并关闭(&S)"
86 |
87 | #. Translators: a lable of a button in Notetaker dialog
88 | #: addon\globalPlugins\quickNotetaker\dialogs.py:155
89 | msgid "&Discard"
90 | msgstr "放弃(&D)"
91 |
92 | #. Translators: The message which asks the user whether they want to exit and discard changes in Notetaker dialog
93 | #: addon\globalPlugins\quickNotetaker\dialogs.py:200
94 | msgid "Are you sure you want to exit and discard changes?"
95 | msgstr "您确定要退出并放弃所有更改吗?"
96 |
97 | #. Translators: The title of the message which asks the user whether they want to exit and discard changes in Notetaker dialog
98 | #. Translators: the title of the message telling the user that opening Notes Manager wasn't possible
99 | #. Translators: the title of the message telling the user that editing the note wasn't possible
100 | #. Translators: the title of the message telling the user that opening Notetaker wasn't possible
101 | #. Translators: the title of the message shown to the user when the note attached Word document is no longer available.
102 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
103 | #. Translators: the title of the warning messaged shown to the user when they try to delete a note from Notes Manager
104 | #. Translators: the title of the message telling the user that the directory they tried to save the document in is no longer available.
105 | #. See the message body for more details
106 | #: addon\globalPlugins\quickNotetaker\dialogs.py:202
107 | #: addon\globalPlugins\quickNotetaker\dialogs.py:224
108 | #: addon\globalPlugins\quickNotetaker\dialogs.py:482
109 | #: addon\globalPlugins\quickNotetaker\dialogs.py:506
110 | #: addon\globalPlugins\quickNotetaker\dialogs.py:609
111 | #: addon\globalPlugins\quickNotetaker\dialogs.py:622
112 | #: addon\globalPlugins\quickNotetaker\dialogs.py:659
113 | msgid "Warning"
114 | msgstr "警告"
115 |
116 | #. Translators: the message shown to the user when opening Notes Manager is not possible because a one is already opened
117 | #: addon\globalPlugins\quickNotetaker\dialogs.py:222
118 | msgid "Couldn't open Notes Manager! A Notes Manager window is already opened."
119 | msgstr "无法重复打开笔记管理器,另一个笔记管理器窗口已打开。"
120 |
121 | #. Translators: The message which tells the user that copying the note was successful
122 | #. Translators: the message telling the user that copying the note was successful
123 | #: addon\globalPlugins\quickNotetaker\dialogs.py:260
124 | #: addon\globalPlugins\quickNotetaker\dialogs.py:268
125 | #: addon\globalPlugins\quickNotetaker\dialogs.py:637
126 | #: addon\globalPlugins\quickNotetaker\dialogs.py:647
127 | msgid "Copied to clipboard!"
128 | msgstr "已复制到剪贴板!"
129 |
130 | #. Translators: The title of the Notes Manager dialog
131 | #: addon\globalPlugins\quickNotetaker\dialogs.py:327
132 | msgid "Notes Manager - Quick Notetaker"
133 | msgstr "笔记管理器 - 快捷笔记"
134 |
135 | #. Translators: the label of the notes list in Notes Manager dialog
136 | #: addon\globalPlugins\quickNotetaker\dialogs.py:339
137 | msgid "No&tes:"
138 | msgstr "笔记(&N)"
139 |
140 | #. Translators: the name of the first column in the notes list in Notes Manager dialog
141 | #: addon\globalPlugins\quickNotetaker\dialogs.py:355
142 | msgid "Title"
143 | msgstr "标题"
144 |
145 | #. Translators: the name of the second column in the notes list in Notes Manager dialog
146 | #: addon\globalPlugins\quickNotetaker\dialogs.py:358
147 | msgid "Last Edited"
148 | msgstr "上次编辑"
149 |
150 | #. Translators: the name of the third column in the notes list in Notes Manager dialog
151 | #: addon\globalPlugins\quickNotetaker\dialogs.py:360
152 | msgid "Preview"
153 | msgstr "预览"
154 |
155 | #. Translaters: The lable of a button in Notes Manager dialog
156 | #: addon\globalPlugins\quickNotetaker\dialogs.py:368
157 | msgid "&View note..."
158 | msgstr "查看笔记(&V)..."
159 |
160 | #. Translaters: The lable of a button in Notes Manager dialog
161 | #: addon\globalPlugins\quickNotetaker\dialogs.py:374
162 | msgid "&Edit note..."
163 | msgstr "编辑笔记(&E)..."
164 |
165 | #. Translaters: The lable of a button in Notes Manager dialog
166 | #: addon\globalPlugins\quickNotetaker\dialogs.py:380
167 | msgid "Co&py note"
168 | msgstr "复制笔记(&P)..."
169 |
170 | #. Translaters: The lable of the open in Word button in Notes Manager dialog in case the note has a Word document attached to it
171 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has a Word document attached to it
172 | #: addon\globalPlugins\quickNotetaker\dialogs.py:386
173 | #: addon\globalPlugins\quickNotetaker\dialogs.py:532
174 | msgid "&Open in Microsoft Word..."
175 | msgstr "在 Microsoft Word 中打开(&O)..."
176 |
177 | #. Translaters: The lable of a button in Notes Manager dialog
178 | #: addon\globalPlugins\quickNotetaker\dialogs.py:398
179 | msgid "&Delete note..."
180 | msgstr "删除笔记(&D)..."
181 |
182 | #. Translators: the label of a button in Notes Manager dialog
183 | #: addon\globalPlugins\quickNotetaker\dialogs.py:412
184 | msgid "&New note..."
185 | msgstr "新建笔记(&N)..."
186 |
187 | #: addon\globalPlugins\quickNotetaker\dialogs.py:418
188 | msgid "Open &settings..."
189 | msgstr "打开设置(&S)..."
190 |
191 | #. Translaters: The lable of a button in Notes Manager dialog
192 | #: addon\globalPlugins\quickNotetaker\dialogs.py:433
193 | msgid "&Close"
194 | msgstr "关闭(&C)..."
195 |
196 | #. Translators: the message shown to the user when editing the note is not possible
197 | #: addon\globalPlugins\quickNotetaker\dialogs.py:480
198 | msgid ""
199 | "Couldn't edit note! An open Notetaker window with unsaved changes is present."
200 | msgstr "无法编辑该笔记!另一份笔记尚未保存。"
201 |
202 | #. Translators: the message shown to the user when opening Notetaker is not possible because a one is already opened
203 | #: addon\globalPlugins\quickNotetaker\dialogs.py:504
204 | msgid "Couldn't open Notetaker! A Notetaker window is already opened."
205 | msgstr "无法重复开启!另一个笔记窗口已打开。"
206 |
207 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has no Word document attached to it
208 | #: addon\globalPlugins\quickNotetaker\dialogs.py:535
209 | msgid "Create Microsoft &Word document"
210 | msgstr "创建 Microsoft Word 文档(&W)..."
211 |
212 | #. Translators: the message shown to the user when the note attached Word document is no longer available.
213 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
214 | #: addon\globalPlugins\quickNotetaker\dialogs.py:606
215 | msgid ""
216 | "A document with the specified name was not found! You can create a new one "
217 | "so you would be able to view this note as a Microsoft Word document."
218 | msgstr ""
219 | "未找到具有指定名称的文档!您可以创建一个新的笔记,以便您可以将此笔记作为 "
220 | "Microsoft Word 文档查看。"
221 |
222 | #. Translators: the warning messaged shown to the user when they try to delete a note from Notes Manager
223 | #: addon\globalPlugins\quickNotetaker\dialogs.py:620
224 | msgid "Are you sure you want to delete this note?"
225 | msgstr "你确定要删除这份笔记么?"
226 |
227 | #. Translators: the message which tells the user that the directory they tried to save the file in is no longer available,
228 | #. so the file was saved in the user default one if this was possible.
229 | #. If not, the file was saved in the quick Notetaker directory in documents folder
230 | #: addon\globalPlugins\quickNotetaker\dialogs.py:656
231 | msgid ""
232 | "The saved path for the Microsoft Word document no longer exists! The "
233 | "document was saved in the default directory for the ad-on!"
234 | msgstr ""
235 | "Microsoft Word 文档的保存路径不存在!该文档已保存在插件的默认保存目录中!"
236 |
237 | #. Translators: The title of the dialog which allows the user to choose the folder where they want to save the note's corresponding Word document.
238 | #. This dialog is displayed to the user if the option of "Ask me each time where to save the note's corresponding Word document" in quick Notetaker settings is checked
239 | #: addon\globalPlugins\quickNotetaker\dialogs.py:667
240 | msgid "Select the folder where the document will be saved"
241 | msgstr "选择要保存文档的文件夹"
242 |
243 | #. Translators: the title given to a note if it has no title
244 | #: addon\globalPlugins\quickNotetaker\helpers.py:165
245 | msgid "Untitled"
246 | msgstr "无标题"
247 |
248 | #. Translators: the label of the control in Quick Notetaker settings panel for choosing a default folder where the add-on documents will be saved
249 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:25
250 | msgid "Default documents directory:"
251 | msgstr "默认文档目录:"
252 |
253 | #. Translators: the label of a button to browse for a directory
254 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:32
255 | msgid "Browse..."
256 | msgstr "浏览..."
257 |
258 | #. Translators: The title of the dialog presented when browsing for the directory where quick notetaker documents will be stored
259 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:35
260 | msgid ""
261 | "Select a default directory where the documents of Quick Notetaker will be "
262 | "stored"
263 | msgstr "选择用于保存笔记文档的默认文件夹"
264 |
265 | #. Translators: the label of a check box in Quick Notetaker settings panel
266 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:44
267 | msgid ""
268 | "Ask me each time &where to save the note's corresponding Microsoft Word "
269 | "document"
270 | msgstr "每次都询问我 Microsoft Word 文档保存到何处?"
271 |
272 | #. Translators: the label of a check box in Quick Notetaker settings panel
273 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:51
274 | msgid ""
275 | "&Open the note's corresponding Microsoft Word document after saving or "
276 | "updating"
277 | msgstr "保存或更新后打开笔记对应的 Microsoft Word 文档(&S)"
278 |
279 | #. Translators: the label of a check box in Quick Notetaker settings panel
280 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:58
281 | msgid "&Capture the active window title when creating a new note"
282 | msgstr "新建笔记时使用所聚焦窗口的标题作为笔记标题(&C)"
283 |
284 | #. Translators: the label of a check box in Quick Notetaker settings panel
285 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:65
286 | msgid "&Remember the note taker window size and position"
287 | msgstr "记住笔记窗口的大小和位置(&R)"
288 |
289 | #. Translators: the label of a check box in Quick Notetaker settings panel
290 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:72
291 | msgid "Au&to align text when editing notes (relevant for RTL languages)"
292 | msgstr "编辑笔记时自动对齐文本 (适用于从右到左的语言环境)"
293 |
294 | #. Add-on description
295 | #. Translators: Long description to be shown for this add-on on add-on information from add-ons manager
296 | #: buildVars.py:26
297 | msgid ""
298 | "A note taker for NVDA. Allows the user to create, edit, view, manage and "
299 | "export notes to different formats."
300 | msgstr ""
301 | "用于 NVDA 的快捷笔记插件。该插件可以让用户创建、编辑、查看、管理和导出不同格"
302 | "式的笔记。"
303 |
--------------------------------------------------------------------------------
/addon/locale/he/LC_MESSAGES/nvda.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the 'quickNotetaker' package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: 'quickNotetaker' '1.0'\n"
10 | "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n"
11 | "POT-Creation-Date: 2021-09-21 10:40+0300\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: Eilana Benish , Mohammad Suliman \n"
14 | "Language-Team: Eilana Benish , Mohammad Suliman , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: 'quickNotetaker' '1.0'\n"
10 | "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n"
11 | "POT-Creation-Date: 2021-09-21 12:07+0300\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: Mohammad Suliman \n"
14 | "Language-Team: Mohammad Suliman \n"
15 | "Language: ar\n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=UTF-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 |
20 | #. Translators: the name of the add-on category in input gestures
21 | #. Translators: the title of the Quick Notetaker panel in NVDA's settings
22 | #. Add-on summary, usually the user visible name of the addon.
23 | #. Translators: Summary for this add-on
24 | #. to be shown on installation and add-on information found in Add-ons Manager.
25 | #: addon\globalPlugins\quickNotetaker\__init__.py:47
26 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:18 buildVars.py:23
27 | msgid "Quick Notetaker"
28 | msgstr "Quick Notetaker"
29 |
30 | #. Translators: the description for the command to open the Notetaker dialog
31 | #: addon\globalPlugins\quickNotetaker\__init__.py:51
32 | msgid "Shows the Notetaker interface for writing a new note"
33 | msgstr "يعرض واجهة مدون الملاحظات لكتابة ملاحظة جديدة"
34 |
35 | #. Translators: the description for the command to open the Notes Manager
36 | #: addon\globalPlugins\quickNotetaker\__init__.py:66
37 | msgid "Shows the Note Viewer interface for viewing and managing notes"
38 | msgstr "يعرض واجهة مدير الملاحظات لمشاهدة وادارة الملاحظات"
39 |
40 | #. Translators: the title for the Quick Notetaker Notetaker window
41 | #: addon\globalPlugins\quickNotetaker\dialogs.py:74
42 | msgid "Notetaker - Quick Notetaker"
43 | msgstr "مدون ملاحظات - Quick Notetaker"
44 |
45 | #. Translators: a lable of a button in Notetaker dialog
46 | #: addon\globalPlugins\quickNotetaker\dialogs.py:89
47 | msgid "Open Notes &Manager..."
48 | msgstr "&فتح مدير الملاحظات..."
49 |
50 | #. Translators: a lable of a button in Notetaker dialog
51 | #: addon\globalPlugins\quickNotetaker\dialogs.py:98
52 | msgid "P&review note..."
53 | msgstr "&عرض مسبق للملاحظة..."
54 |
55 | #. Translators: a lable of a button in Notetaker dialog
56 | #: addon\globalPlugins\quickNotetaker\dialogs.py:101
57 | msgid "Co&py"
58 | msgstr "&نسخ"
59 |
60 | #. Translators: a lable of a button in Notetaker dialog
61 | #. Translaters: The lable of a button in Notes Manager dialog
62 | #: addon\globalPlugins\quickNotetaker\dialogs.py:106
63 | #: addon\globalPlugins\quickNotetaker\dialogs.py:361
64 | msgid "Copy &HTML code"
65 | msgstr "نسخ &شيفرة HTML"
66 |
67 | #. Translators: The lable of the note content edit area in Notetaker dialog
68 | #: addon\globalPlugins\quickNotetaker\dialogs.py:112
69 | msgid "&Note content:"
70 | msgstr "&محتوى الملاحظة:"
71 |
72 | #. Translators: The label of the check box in Notetaker dialog when editing a note which has Word document attached to it
73 | #: addon\globalPlugins\quickNotetaker\dialogs.py:129
74 | msgid "Update the corresponding Microsoft &Word document also"
75 | msgstr "&قم بتحديث ملف ال Microsoft Word المرفق للملاحظة أيضا"
76 |
77 | #. Translators: The label of the check box in Notetaker dialog when creating a new note or when editing an existing note with no Word document attached to it
78 | #: addon\globalPlugins\quickNotetaker\dialogs.py:132
79 | msgid "Save as Microsoft &Word document also"
80 | msgstr "&قم بالحفظ كملف Microsoft Word أيضا"
81 |
82 | #. Translators: a lable of a button in Notetaker dialog
83 | #: addon\globalPlugins\quickNotetaker\dialogs.py:142
84 | msgid "&Save and close"
85 | msgstr "&حفظ وإغلاق"
86 |
87 | #. Translators: a lable of a button in Notetaker dialog
88 | #: addon\globalPlugins\quickNotetaker\dialogs.py:149
89 | msgid "&Discard"
90 | msgstr "&تجاهل"
91 |
92 | #. Translators: The message which asks the user whether they want to exit and discard changes in Notetaker dialog
93 | #: addon\globalPlugins\quickNotetaker\dialogs.py:195
94 | msgid "Are you sure you want to exit and discard changes?"
95 | msgstr "هل انت متأكد انه برغبتك الخروج وتجاهل التغييرات؟"
96 |
97 | #. Translators: The title of the message which asks the user whether they want to exit and discard changes in Notetaker dialog
98 | #. Translators: the title of the message telling the user that opening Notes Manager wasn't possible
99 | #. Translators: the title of the message telling the user that editing the note wasn't possible
100 | #. Translators: the title of the message telling the user that opening Notetaker wasn't possible
101 | #. Translators: the title of the message shown to the user when the note attached Word document is no longer available.
102 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
103 | #. Translators: the title of the warning messaged shown to the user when they try to delete a note from Notes Manager
104 | #. Translators: the title of the message telling the user that the directory they tried to save the document in is no longer available.
105 | #. See the message body for more details
106 | #: addon\globalPlugins\quickNotetaker\dialogs.py:199
107 | #: addon\globalPlugins\quickNotetaker\dialogs.py:221
108 | #: addon\globalPlugins\quickNotetaker\dialogs.py:477
109 | #: addon\globalPlugins\quickNotetaker\dialogs.py:501
110 | #: addon\globalPlugins\quickNotetaker\dialogs.py:611
111 | #: addon\globalPlugins\quickNotetaker\dialogs.py:624
112 | #: addon\globalPlugins\quickNotetaker\dialogs.py:661
113 | msgid "Warning"
114 | msgstr "تحذير"
115 |
116 | #. Translators: the message shown to the user when opening Notes Manager is not possible because a one is already opened
117 | #: addon\globalPlugins\quickNotetaker\dialogs.py:219
118 | msgid "Couldn't open Notes Manager! A Notes Manager window is already opened."
119 | msgstr "لم يتمكن عرض مدير الملاحظات! هناك شباك مدير ملاحظات معروض مسبقا."
120 |
121 | #. Translators: The message which tells the user that copying the note was successful
122 | #. Translators: the message telling the user that copying the note was successful
123 | #: addon\globalPlugins\quickNotetaker\dialogs.py:231
124 | #: addon\globalPlugins\quickNotetaker\dialogs.py:238
125 | #: addon\globalPlugins\quickNotetaker\dialogs.py:605
126 | #: addon\globalPlugins\quickNotetaker\dialogs.py:614
127 | msgid "Copied to clipboard!"
128 | msgstr "نسخ للحافظة"
129 |
130 | #. Translators: The title of the Notes Manager dialog
131 | #: addon\globalPlugins\quickNotetaker\dialogs.py:296
132 | msgid "Notes Manager - Quick Notetaker"
133 | msgstr "مدير الملاحظات - Quick Notetaker"
134 |
135 | #. Translators: the label of the notes list in Notes Manager dialog
136 | #: addon\globalPlugins\quickNotetaker\dialogs.py:308
137 | msgid "No&tes:"
138 | msgstr "&الملاحظات"
139 |
140 | #. Translators: the name of the first column in the notes list in Notes Manager dialog
141 | #: addon\globalPlugins\quickNotetaker\dialogs.py:324
142 | msgid "Title"
143 | msgstr "عنوان"
144 |
145 | #. Translators: the name of the second column in the notes list in Notes Manager dialog
146 | #: addon\globalPlugins\quickNotetaker\dialogs.py:327
147 | msgid "Last Edited"
148 | msgstr "آخر تحرير"
149 |
150 | #. Translators: the name of the third column in the notes list in Notes Manager dialog
151 | #: addon\globalPlugins\quickNotetaker\dialogs.py:329
152 | msgid "Preview"
153 | msgstr "عرض مسبق"
154 |
155 | #. Translaters: The lable of a button in Notes Manager dialog
156 | #: addon\globalPlugins\quickNotetaker\dialogs.py:337
157 | msgid "&View note..."
158 | msgstr "&عرض الملاحظة..."
159 |
160 | #. Translaters: The lable of a button in Notes Manager dialog
161 | #: addon\globalPlugins\quickNotetaker\dialogs.py:343
162 | msgid "&Edit note..."
163 | msgstr "&تحرير الملاحظة..."
164 |
165 | #. Translaters: The lable of a button in Notes Manager dialog
166 | #: addon\globalPlugins\quickNotetaker\dialogs.py:349
167 | msgid "Co&py note"
168 | msgstr "&نسخ الملاحظة"
169 |
170 | #. Translaters: The lable of the open in Word button in Notes Manager dialog in case the note has a Word document attached to it
171 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has a Word document attached to it
172 | #: addon\globalPlugins\quickNotetaker\dialogs.py:355
173 | #: addon\globalPlugins\quickNotetaker\dialogs.py:495
174 | msgid "&Open in Microsoft Word..."
175 | msgstr "ال&فتح بواسطة Microsoft Word..."
176 |
177 | #. Translaters: The lable of a button in Notes Manager dialog
178 | #: addon\globalPlugins\quickNotetaker\dialogs.py:367
179 | msgid "&Delete note..."
180 | msgstr "&محو الملاحظة..."
181 |
182 | #. Translators: the label of a button in Notes Manager dialog
183 | #: addon\globalPlugins\quickNotetaker\dialogs.py:381
184 | msgid "&New note..."
185 | msgstr "ملاحظة &جديدة..."
186 |
187 | #. Translaters: The lable of a button in Notes Manager dialog
188 | #: addon\globalPlugins\quickNotetaker\dialogs.py:386
189 | msgid "Open &settings..."
190 | msgstr "فتح الإع&دادات..."
191 |
192 | #. Translaters: The lable of a button in Notes Manager dialog
193 | #: addon\globalPlugins\quickNotetaker\dialogs.py:401
194 | msgid "&Close"
195 | msgstr "إ&غلاق"
196 |
197 | #. Translators: the title given to a note if it has no title
198 | #: addon\globalPlugins\quickNotetaker\helpers.py:128
199 | msgid "Untitled"
200 | msgstr "بلا عنوان"
201 |
202 | #. Translators: the message shown to the user when editing the note is not possible
203 | #: addon\globalPlugins\quickNotetaker\dialogs.py:454
204 | msgid ""
205 | "Couldn't edit note! An open Notetaker window with unsaved changes is present."
206 | msgstr "لا يمكن تحرير الملاحظة! هناك شباك مدون ملاحظات مع تغييرات غير محفوظة لا يزال مفتوحة."
207 |
208 | #. Translators: the message shown to the user when opening Notetaker is not possible because a one is already opened
209 | #: addon\globalPlugins\quickNotetaker\dialogs.py:499
210 | msgid "Couldn't open Notetaker! A Notetaker window is already opened."
211 | msgstr "لم يتمكن عرض مدون الملاحظات! هناك شباك مدون ملاحظات معروض مسبقا."
212 |
213 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has no Word document attached to it
214 | #: addon\globalPlugins\quickNotetaker\dialogs.py:498
215 | msgid "Create Microsoft &Word document"
216 | msgstr "إنشاء مل&ف Microsoft Word"
217 |
218 | #. Translators: the message shown to the user when the note attached Word document is no longer available.
219 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
220 | #: addon\globalPlugins\quickNotetaker\dialogs.py:574
221 | msgid ""
222 | "A document with the specified name was not found! You can create a new one "
223 | "so you would be able to view this note as a Microsoft Word document."
224 | msgstr "لم يتم العثور على ملف بهذا الإسم! يمكنك انشاء ملف جديد حتى تتمكن من مشاهدة الملاحظة كملف Microsoft Word."
225 |
226 | #. Translators: the warning messaged shown to the user when they try to delete a note from Notes Manager
227 | #: addon\globalPlugins\quickNotetaker\dialogs.py:588
228 | msgid "Are you sure you want to delete this note?"
229 | msgstr "هل انت متأكد انك ترغب بمحو الملاحظة؟"
230 |
231 | #. Translators: the message which tells the user that the directory they tried to save the file in is no longer available,
232 | #. so the file was saved in the user default one if this was possible.
233 | #. If not, the file was saved in the quick Notetaker directory in documents folder
234 | #: addon\globalPlugins\quickNotetaker\dialogs.py:623
235 | msgid ""
236 | "The saved path for the Microsoft Word document no longer exists! The "
237 | "document was saved in the default directory for the ad-on!"
238 | msgstr "مسار ملف ال Microsoft Word المحفوظ لهذه الملاحظة لم يعد متوفرا! تم حفظ المستند في المجلد الإفتراضي للاضافة!"
239 |
240 | #. Translators: The title of the dialog which allows the user to choose the folder where they want to save the note's corresponding Word document.
241 | #. This dialog is displayed to the user if the option of "Ask me each time where to save the note's corresponding Word document" in quick Notetaker settings is checked
242 | #: addon\globalPlugins\quickNotetaker\dialogs.py:634
243 | msgid "Select the folder where the document will be saved"
244 | msgstr "قم بإختيار المجلد الذي سيحفظ فيه المستند"
245 |
246 | #. Translators: the label of the control in Quick Notetaker settings panel for choosing a default folder where the add-on documents will be saved
247 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:23
248 | msgid "Default documents directory:"
249 | msgstr "المجلد الإفتراضي للمستندات"
250 |
251 | #. Translators: the label of a button to browse for a directory
252 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:30
253 | msgid "Browse..."
254 | msgstr "استعراض..."
255 |
256 | #. Translators: The title of the dialog presented when browsing for the directory where quick Notetaker documents will be stored
257 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:33
258 | msgid ""
259 | "Select a default directory where the documents of Quick Notetaker will be "
260 | "stored"
261 | msgstr "قم بإختيار المجلد الإفتراضي حيث سيتم حفظ مستندات Quick Notetaker"
262 |
263 | #. Translators: the label of a check box in Quick Notetaker settings panel
264 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:42
265 | msgid ""
266 | "Ask me each time &where to save the note's corresponding Microsoft Word "
267 | "document"
268 | msgstr "إسألني &كل مرة اين سيتم حفظ ملف ال Microsoft Word المرفق للملاحظة"
269 |
270 | #. Translators: the label of a check box in Quick Notetaker settings panel
271 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:49
272 | msgid ""
273 | "&Open the note's corresponding Microsoft Word document after saving or "
274 | "updating"
275 | msgstr "&قم بفتح ملف ال Microsoft Word بعد الحفظ أو التحديث"
276 |
277 | #. Translators: the label of a check box in Quick Notetaker settings panel
278 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:56
279 | msgid "&Capture the active window title when creating a new note"
280 | msgstr "قم بإست&خدام عنوان الشباك النشط كعنوان الملاحظة حين إنشاء ملاحظة جديدة"
281 |
282 | #. Translators: the label of a check box in Quick Notetaker settings panel
283 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:63
284 | msgid "&Remember the note taker window size and position"
285 | msgstr "ت&ذكر موقع وحجم شباك مدون الملاحظات"
286 |
287 | #. Translators: the label of a check box in Quick Notetaker settings panel
288 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:70
289 | msgid "Au&to align text when editing notes (relevant for RTL languages)"
290 | msgstr "قم بمحاذاة ال&نص بشكل تلقائي حين تحرير الملاحظات (هام عند الكتابة بلغات من اليمين الى اليسار)"
291 |
292 | #. Add-on description
293 | #. Translators: Long description to be shown for this add-on on add-on information from add-ons manager
294 | #: buildVars.py:26
295 | msgid ""
296 | "A note taker for NVDA. Allows the user to create, edit, view, manage and "
297 | "export notes to different formats."
298 | msgstr "مدون ملاحظات ل NVDA. يمكن المستخدم من إنشاء، تحرير، عرض، إدارة وتصدير الملاحظات الى صيغ مختلفة."
299 |
--------------------------------------------------------------------------------
/addon/locale/de/LC_MESSAGES/nvda.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the quickNotetaker package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: quickNotetaker 1.0\n"
10 | "Report-Msgid-Bugs-To: nvda-translations@groups.io\n"
11 | "POT-Creation-Date: 2022-02-02 20:19+0100\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: Benjamin Hofer \n"
14 | "Language-Team: Benjamin Hofer \n"
15 | "Language: de\n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=UTF-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 |
20 | #. Translators: the name of the add-on category in input gestures
21 | #. Translators: the title of the Quick Notetaker panel in NVDA's settings
22 | #. Add-on summary, usually the user visible name of the addon.
23 | #. Translators: Summary for this add-on
24 | #. to be shown on installation and add-on information found in Add-ons Manager.
25 | #: addon/globalPlugins/quickNotetaker/__init__.py:58
26 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:20 buildVars.py:23
27 | msgid "Quick Notetaker"
28 | msgstr "Quick Notetaker"
29 |
30 | #. Translators: the description for the command to open the notetaker dialog
31 | #: addon/globalPlugins/quickNotetaker/__init__.py:62
32 | msgid "Shows the Notetaker interface for writing a new note"
33 | msgstr "Zeigt die Notizbuch-Oberfläche zum Schreiben einer neuen Notiz an"
34 |
35 | #. Translators: the description for the command to open the Notes Manager
36 | #: addon/globalPlugins/quickNotetaker/__init__.py:77
37 | msgid "Shows the Notes Manager interface for viewing and managing notes"
38 | msgstr "Zeigt die Oberfläche des Notizbuchs zum Anzeigen und Verwalten von Notizen an"
39 |
40 | #. Translators: the title for the Quick Notetaker Notetaker window
41 | #: addon/globalPlugins/quickNotetaker/dialogs.py:77
42 | msgid "Notetaker - Quick Notetaker"
43 | msgstr "Notizbuch - Quick Notetaker"
44 |
45 | #. Translators: a lable of a button in Notetaker dialog
46 | #: addon/globalPlugins/quickNotetaker/dialogs.py:92
47 | msgid "Open Notes &Manager..."
48 | msgstr "Notizbuch öffnen..."
49 |
50 | #. Translators: a lable of a button in Notetaker dialog
51 | #: addon/globalPlugins/quickNotetaker/dialogs.py:101
52 | msgid "P&review note..."
53 | msgstr "Notizvo&rschau..."
54 |
55 | #. Translators: a lable of a button in Notetaker dialog
56 | #: addon/globalPlugins/quickNotetaker/dialogs.py:104
57 | msgid "Co&py"
58 | msgstr "Ko&pieren"
59 |
60 | #. Translators: a lable of a button in Notetaker dialog
61 | #. Translaters: The lable of a button in Notes Manager dialog
62 | #: addon/globalPlugins/quickNotetaker/dialogs.py:109
63 | #: addon/globalPlugins/quickNotetaker/dialogs.py:392
64 | msgid "Copy &HTML code"
65 | msgstr "&HTML-Code kopieren..."
66 |
67 | #. Translators: The lable of the note content edit area in Notetaker dialog
68 | #: addon/globalPlugins/quickNotetaker/dialogs.py:115
69 | msgid "&Note content:"
70 | msgstr "Inhalt der &Notiz:"
71 |
72 | #: addon/globalPlugins/quickNotetaker/dialogs.py:135
73 | msgid "Update the corresponding Microsoft &Word document also"
74 | msgstr "Auch das zugehörige Microsoft &Word-Dokument aktualisieren"
75 |
76 | #. Translators: The label of the check box in Notetaker dialog when creating a new note or when editing an existing note with no Word document attached to it
77 | #: addon/globalPlugins/quickNotetaker/dialogs.py:138
78 | msgid "Save as Microsoft &Word document also"
79 | msgstr "Auch als Microsoft &Word-Dokument speichern"
80 |
81 | #. Translators: a lable of a button in Notetaker dialog
82 | #: addon/globalPlugins/quickNotetaker/dialogs.py:148
83 | msgid "&Save and close"
84 | msgstr "&Speichern und schließen"
85 |
86 | #. Translators: a lable of a button in Notetaker dialog
87 | #: addon/globalPlugins/quickNotetaker/dialogs.py:155
88 | msgid "&Discard"
89 | msgstr "Verwerfen"
90 |
91 | #. Translators: The message which asks the user whether they want to exit and discard changes in Notetaker dialog
92 | #: addon/globalPlugins/quickNotetaker/dialogs.py:200
93 | msgid "Are you sure you want to exit and discard changes?"
94 | msgstr "Sind Sie sicher, dass Sie das Notizbuch schließen und Ihre Änderungen verwerfen möchten?"
95 |
96 | #. Translators: The title of the message which asks the user whether they want to exit and discard changes in Notetaker dialog
97 | #. Translators: the title of the message telling the user that opening Notes Manager wasn't possible
98 | #. Translators: the title of the message telling the user that editing the note wasn't possible
99 | #. Translators: the title of the message telling the user that opening Notetaker wasn't possible
100 | #. Translators: the title of the message shown to the user when the note attached Word document is no longer available.
101 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
102 | #. Translators: the title of the warning messaged shown to the user when they try to delete a note from Notes Manager
103 | #. Translators: the title of the message telling the user that the directory they tried to save the document in is no longer available.
104 | #. See the message body for more details
105 | #: addon/globalPlugins/quickNotetaker/dialogs.py:202
106 | #: addon/globalPlugins/quickNotetaker/dialogs.py:224
107 | #: addon/globalPlugins/quickNotetaker/dialogs.py:482
108 | #: addon/globalPlugins/quickNotetaker/dialogs.py:506
109 | #: addon/globalPlugins/quickNotetaker/dialogs.py:609
110 | #: addon/globalPlugins/quickNotetaker/dialogs.py:622
111 | #: addon/globalPlugins/quickNotetaker/dialogs.py:659
112 | msgid "Warning"
113 | msgstr "Warnung"
114 |
115 | #. Translators: the message shown to the user when opening Notes Manager is not possible because a one is already opened
116 | #: addon/globalPlugins/quickNotetaker/dialogs.py:222
117 | msgid "Couldn't open Notes Manager! A Notes Manager window is already opened."
118 | msgstr "Das Notizbuch konnte nicht geöffnet werden!"
119 |
120 | #. Translators: The message which tells the user that copying the note was successful
121 | #. Translators: the message telling the user that copying the note was successful
122 | #: addon/globalPlugins/quickNotetaker/dialogs.py:260
123 | #: addon/globalPlugins/quickNotetaker/dialogs.py:268
124 | #: addon/globalPlugins/quickNotetaker/dialogs.py:637
125 | #: addon/globalPlugins/quickNotetaker/dialogs.py:647
126 | msgid "Copied to clipboard!"
127 | msgstr "In Zwischenablage kopiert"
128 |
129 | #. Translators: The title of the Notes Manager dialog
130 | #: addon/globalPlugins/quickNotetaker/dialogs.py:327
131 | msgid "Notes Manager - Quick Notetaker"
132 | msgstr "Notizbuch - Quick Notetaker"
133 |
134 | #. Translators: the label of the notes list in Notes Manager dialog
135 | #: addon/globalPlugins/quickNotetaker/dialogs.py:339
136 | msgid "No&tes:"
137 | msgstr "No&tizen:"
138 |
139 | #. Translators: the name of the first column in the notes list in Notes Manager dialog
140 | #: addon/globalPlugins/quickNotetaker/dialogs.py:355
141 | msgid "Title"
142 | msgstr "Titel"
143 |
144 | #. Translators: the name of the second column in the notes list in Notes Manager dialog
145 | #: addon/globalPlugins/quickNotetaker/dialogs.py:358
146 | msgid "Last Edited"
147 | msgstr "Zuletzt geändert"
148 |
149 | #. Translators: the name of the third column in the notes list in Notes Manager dialog
150 | #: addon/globalPlugins/quickNotetaker/dialogs.py:360
151 | msgid "Preview"
152 | msgstr "Vorschau"
153 |
154 | #. Translaters: The lable of a button in Notes Manager dialog
155 | #: addon/globalPlugins/quickNotetaker/dialogs.py:368
156 | msgid "&View note..."
157 | msgstr "Notiz anzeigen.."
158 |
159 | #. Translaters: The lable of a button in Notes Manager dialog
160 | #: addon/globalPlugins/quickNotetaker/dialogs.py:374
161 | msgid "&Edit note..."
162 | msgstr "Notiz b&earbeiten..."
163 |
164 | #. Translaters: The lable of a button in Notes Manager dialog
165 | #: addon/globalPlugins/quickNotetaker/dialogs.py:380
166 | msgid "Co&py note"
167 | msgstr "Notiz ko&pieren"
168 |
169 | #. Translaters: The lable of the open in Word button in Notes Manager dialog in case the note has a Word document attached to it
170 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has a Word document attached to it
171 | #: addon/globalPlugins/quickNotetaker/dialogs.py:386
172 | #: addon/globalPlugins/quickNotetaker/dialogs.py:532
173 | msgid "&Open in Microsoft Word..."
174 | msgstr "In Microsoft Word öffnen..."
175 |
176 | #. Translaters: The lable of a button in Notes Manager dialog
177 | #: addon/globalPlugins/quickNotetaker/dialogs.py:398
178 | msgid "&Delete note..."
179 | msgstr "Notiz löschen..."
180 |
181 | #. Translators: the label of a button in Notes Manager dialog
182 | #: addon/globalPlugins/quickNotetaker/dialogs.py:412
183 | msgid "&New note..."
184 | msgstr "&Neue Notiz..."
185 |
186 | #: addon/globalPlugins/quickNotetaker/dialogs.py:418
187 | msgid "Open &settings..."
188 | msgstr "Ein&stellungen öffnen..."
189 |
190 | #. Translaters: The lable of a button in Notes Manager dialog
191 | #: addon/globalPlugins/quickNotetaker/dialogs.py:433
192 | msgid "&Close"
193 | msgstr "Schließen"
194 |
195 | #. Translators: the message shown to the user when editing the note is not possible
196 | #: addon/globalPlugins/quickNotetaker/dialogs.py:480
197 | msgid ""
198 | "Couldn't edit note! An open Notetaker window with unsaved changes is present."
199 | msgstr ""
200 | "Die Notiz kann nicht bearbeitet werden, da noch ein Notizbuch mit ungespeicherten Änderungen offen ist."
201 |
202 | #. Translators: the message shown to the user when opening Notetaker is not possible because a one is already opened
203 | #: addon/globalPlugins/quickNotetaker/dialogs.py:504
204 | msgid "Couldn't open Notetaker! A Notetaker window is already opened."
205 | msgstr "Das Notizbuch kann nicht geöffnet werden. Es ist bereits ein Notizbuch-Fenster geöffnet."
206 |
207 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has no Word document attached to it
208 | #: addon/globalPlugins/quickNotetaker/dialogs.py:535
209 | msgid "Create Microsoft &Word document"
210 | msgstr "Microsoft &Word-Dokument erstellen"
211 |
212 | #. Translators: the message shown to the user when the note attached Word document is no longer available.
213 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
214 | #: addon/globalPlugins/quickNotetaker/dialogs.py:606
215 | msgid ""
216 | "A document with the specified name was not found! You can create a new one "
217 | "so you would be able to view this note as a Microsoft Word document."
218 | msgstr ""
219 | "Ein Dokument mit dem angegebenen Namen wurde nicht gefunden! Sie können ein neues Dokument erstellen, "
220 | "und damit diese Notiz als Microsoft Word-Dokument anzeigen können."
221 |
222 | #. Translators: the warning messaged shown to the user when they try to delete a note from Notes Manager
223 | #: addon/globalPlugins/quickNotetaker/dialogs.py:620
224 | msgid "Are you sure you want to delete this note?"
225 | msgstr "Möchten Sie diese Notiz wirklich löschen?"
226 |
227 | #. Translators: the message which tells the user that the directory they tried to save the file in is no longer available,
228 | #. so the file was saved in the user default one if this was possible.
229 | #. If not, the file was saved in the quick Notetaker directory in documents folder
230 | #: addon/globalPlugins/quickNotetaker/dialogs.py:656
231 | msgid ""
232 | "The saved path for the Microsoft Word document no longer exists! The "
233 | "document was saved in the default directory for the ad-on!"
234 | msgstr ""
235 | "Der gespeicherte Pfad für das Microsoft Word-Dokument existiert nicht mehr! Das "
236 | "Dokument wurde im Standardverzeichnis für das Add-On gespeichert!"
237 |
238 | #. Translators: The title of the dialog which allows the user to choose the folder where they want to save the note's corresponding Word document.
239 | #. This dialog is displayed to the user if the option of "Ask me each time where to save the note's corresponding Word document" in quick Notetaker settings is checked
240 | #: addon/globalPlugins/quickNotetaker/dialogs.py:667
241 | msgid "Select the folder where the document will be saved"
242 | msgstr "Wählen Sie das Verzeichnis aus, in dem das Dokument gespeichert werden soll"
243 |
244 | #. Translators: the title given to a note if it has no title
245 | #: addon/globalPlugins/quickNotetaker/helpers.py:165
246 | msgid "Untitled"
247 | msgstr "Unbenannt"
248 |
249 | #. Translators: the label of the control in Quick Notetaker settings panel for choosing a default folder where the add-on documents will be saved
250 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:25
251 | msgid "Default documents directory:"
252 | msgstr "Standardverzeichnis für Dokumente:"
253 |
254 | #. Translators: the label of a button to browse for a directory
255 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:32
256 | msgid "Browse..."
257 | msgstr "Durchsuchen..."
258 |
259 | #. Translators: The title of the dialog presented when browsing for the directory where quick notetaker documents will be stored
260 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:35
261 | msgid ""
262 | "Select a default directory where the documents of Quick Notetaker will be "
263 | "stored"
264 | msgstr ""
265 | "Wählen Sie ein Standardverzeichnis, in dem die Dokumente von Quick Notetaker "
266 | "gespeichert werden"
267 |
268 | #. Translators: the label of a check box in Quick Notetaker settings panel
269 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:44
270 | msgid ""
271 | "Ask me each time &where to save the note's corresponding Microsoft Word "
272 | "document"
273 | msgstr ""
274 | "Immer fragen, &wo das entsprechende Microsoft Word-Dokument der Notiz gespeichert "
275 | "werden soll"
276 |
277 | #. Translators: the label of a check box in Quick Notetaker settings panel
278 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:51
279 | msgid ""
280 | "&Open the note's corresponding Microsoft Word document after saving or "
281 | "updating"
282 | msgstr ""
283 | "Das Microsoft Word-Dokument nach dem Speichern oder Aktualisieren der "
284 | "Notiz öffnen"
285 |
286 | #. Translators: the label of a check box in Quick Notetaker settings panel
287 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:58
288 | msgid "&Capture the active window title when creating a new note"
289 | msgstr "Beim Erstellen einer neuen Notiz den aktuellen Fenstertitel als Name verwenden"
290 |
291 | #. Translators: the label of a check box in Quick Notetaker settings panel
292 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:65
293 | msgid "&Remember the note taker window size and position"
294 | msgstr "Fenstergröße und -position für das Notizbuch-Fenster beibehalten"
295 |
296 | #. Translators: the label of a check box in Quick Notetaker settings panel
297 | #: addon/globalPlugins/quickNotetaker/settingsPanel.py:72
298 | msgid "Au&to align text when editing notes (relevant for RTL languages)"
299 | msgstr "Au&tomatisches Au&srichten von Text beim Bearbeiten von Notizen (relevant für RTL-Sprachen)"
300 |
301 | #. Add-on description
302 | #. Translators: Long description to be shown for this add-on on add-on information from add-ons manager
303 | #: buildVars.py:26
304 | msgid ""
305 | "A note taker for NVDA. Allows the user to create, edit, view, manage and "
306 | "export notes to different formats."
307 | msgstr ""
308 | "Ein Notizbuch für NVDA. Ermöglicht dem Benutzer das Erstellen, Bearbeiten, Anzeigen, Verwalten und "
309 | "Exportieren von Notizen."
310 |
--------------------------------------------------------------------------------
/addon/locale/ru/LC_MESSAGES/nvda.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the 'quickNotetaker' package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | msgid ""
7 | msgstr ""
8 | "Project-Id-Version: 'quickNotetaker' '1.1'\n"
9 | "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n"
10 | "POT-Creation-Date: 2023-03-07 18:44+0400\n"
11 | "PO-Revision-Date: 2023-03-13 21:39+0400\n"
12 | "Last-Translator: Dragan Ratkovich\n"
13 | "Language-Team: \n"
14 | "Language: ru\n"
15 | "MIME-Version: 1.0\n"
16 | "Content-Type: text/plain; charset=UTF-8\n"
17 | "Content-Transfer-Encoding: 8bit\n"
18 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
19 | "n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
20 | "X-Generator: Poedit 3.2.2\n"
21 |
22 | #. Translators: the name of the add-on category in input gestures
23 | #. Translators: the title of the Quick Notetaker panel in NVDA's settings
24 | #. Add-on summary, usually the user visible name of the addon.
25 | #. Translators: Summary for this add-on
26 | #. to be shown on installation and add-on information found in Add-ons Manager.
27 | #: addon\globalPlugins\quickNotetaker\__init__.py:58
28 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:20 buildVars.py:23
29 | msgid "Quick Notetaker"
30 | msgstr "Быстрый блокнот"
31 |
32 | #. Translators: the description for the command to open the notetaker dialog
33 | #: addon\globalPlugins\quickNotetaker\__init__.py:62
34 | msgid "Shows the Notetaker interface for writing a new note"
35 | msgstr "Показывает интерфейс блокнота для написания новой заметки"
36 |
37 | #. Translators: the description for the command to open the Notes Manager
38 | #: addon\globalPlugins\quickNotetaker\__init__.py:77
39 | msgid "Shows the Notes Manager interface for viewing and managing notes"
40 | msgstr ""
41 | "Показывает интерфейс диспетчера заметок для просмотра и управления заметками"
42 |
43 | #. Translators: the title for the Quick Notetaker Notetaker window
44 | #: addon\globalPlugins\quickNotetaker\dialogs.py:77
45 | msgid "Notetaker - Quick Notetaker"
46 | msgstr "Блокнот - Быстрый блокнот"
47 |
48 | #. Translators: a lable of a button in Notetaker dialog
49 | #: addon\globalPlugins\quickNotetaker\dialogs.py:92
50 | msgid "Open Notes &Manager..."
51 | msgstr "Открыть &менеджер заметок..."
52 |
53 | #. Translators: a lable of a button in Notetaker dialog
54 | #: addon\globalPlugins\quickNotetaker\dialogs.py:101
55 | msgid "P&review note..."
56 | msgstr "Предварительный &просмотр заметки..."
57 |
58 | #. Translators: a lable of a button in Notetaker dialog
59 | #: addon\globalPlugins\quickNotetaker\dialogs.py:104
60 | msgid "Co&py"
61 | msgstr "&Копировать"
62 |
63 | #. Translators: a lable of a button in Notetaker dialog
64 | #. Translaters: The lable of a button in Notes Manager dialog
65 | #: addon\globalPlugins\quickNotetaker\dialogs.py:109
66 | #: addon\globalPlugins\quickNotetaker\dialogs.py:392
67 | msgid "Copy &HTML code"
68 | msgstr "Скопировать &HTML-код"
69 |
70 | #. Translators: The lable of the note content edit area in Notetaker dialog
71 | #: addon\globalPlugins\quickNotetaker\dialogs.py:115
72 | msgid "&Note content:"
73 | msgstr "Содержание &заметки:"
74 |
75 | #: addon\globalPlugins\quickNotetaker\dialogs.py:135
76 | msgid "Update the corresponding Microsoft &Word document also"
77 | msgstr "Также обновить соответствующий документ Microsoft &Word"
78 |
79 | #. Translators: The label of the check box in Notetaker dialog when creating a new note or when editing an existing note with no Word document attached to it
80 | #: addon\globalPlugins\quickNotetaker\dialogs.py:138
81 | msgid "Save as Microsoft &Word document also"
82 | msgstr "Также сохранить как документ Microsoft &Word"
83 |
84 | #. Translators: a lable of a button in Notetaker dialog
85 | #: addon\globalPlugins\quickNotetaker\dialogs.py:148
86 | msgid "&Save and close"
87 | msgstr "&Сохранить и закрыть"
88 |
89 | #. Translators: a lable of a button in Notetaker dialog
90 | #: addon\globalPlugins\quickNotetaker\dialogs.py:155
91 | msgid "&Discard"
92 | msgstr "&Отменить"
93 |
94 | #. Translators: The message which asks the user whether they want to exit and discard changes in Notetaker dialog
95 | #: addon\globalPlugins\quickNotetaker\dialogs.py:200
96 | msgid "Are you sure you want to exit and discard changes?"
97 | msgstr "Вы уверены, что хотите выйти и отменить изменения?"
98 |
99 | #. Translators: The title of the message which asks the user whether they want to exit and discard changes in Notetaker dialog
100 | #. Translators: the title of the message telling the user that opening Notes Manager wasn't possible
101 | #. Translators: the title of the message telling the user that editing the note wasn't possible
102 | #. Translators: the title of the message telling the user that opening Notetaker wasn't possible
103 | #. Translators: the title of the message shown to the user when the note attached Word document is no longer available.
104 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
105 | #. Translators: the title of the warning messaged shown to the user when they try to delete a note from Notes Manager
106 | #. Translators: the title of the message telling the user that the directory they tried to save the document in is no longer available.
107 | #. See the message body for more details
108 | #: addon\globalPlugins\quickNotetaker\dialogs.py:202
109 | #: addon\globalPlugins\quickNotetaker\dialogs.py:224
110 | #: addon\globalPlugins\quickNotetaker\dialogs.py:482
111 | #: addon\globalPlugins\quickNotetaker\dialogs.py:506
112 | #: addon\globalPlugins\quickNotetaker\dialogs.py:609
113 | #: addon\globalPlugins\quickNotetaker\dialogs.py:622
114 | #: addon\globalPlugins\quickNotetaker\dialogs.py:659
115 | msgid "Warning"
116 | msgstr "Предупреждение"
117 |
118 | #. Translators: the message shown to the user when opening Notes Manager is not possible because a one is already opened
119 | #: addon\globalPlugins\quickNotetaker\dialogs.py:222
120 | msgid "Couldn't open Notes Manager! A Notes Manager window is already opened."
121 | msgstr ""
122 | "Не удалось открыть менеджер заметок! Окно менеджера заметок уже открыто."
123 |
124 | #. Translators: The message which tells the user that copying the note was successful
125 | #. Translators: the message telling the user that copying the note was successful
126 | #: addon\globalPlugins\quickNotetaker\dialogs.py:260
127 | #: addon\globalPlugins\quickNotetaker\dialogs.py:268
128 | #: addon\globalPlugins\quickNotetaker\dialogs.py:637
129 | #: addon\globalPlugins\quickNotetaker\dialogs.py:647
130 | msgid "Copied to clipboard!"
131 | msgstr "Скопировано в буфер обмена!"
132 |
133 | #. Translators: The title of the Notes Manager dialog
134 | #: addon\globalPlugins\quickNotetaker\dialogs.py:327
135 | msgid "Notes Manager - Quick Notetaker"
136 | msgstr "Менеджер заметок - Быстрый блокнот"
137 |
138 | #. Translators: the label of the notes list in Notes Manager dialog
139 | #: addon\globalPlugins\quickNotetaker\dialogs.py:339
140 | msgid "No&tes:"
141 | msgstr "&Заметки:"
142 |
143 | #. Translators: the name of the first column in the notes list in Notes Manager dialog
144 | #: addon\globalPlugins\quickNotetaker\dialogs.py:355
145 | msgid "Title"
146 | msgstr "Название"
147 |
148 | #. Translators: the name of the second column in the notes list in Notes Manager dialog
149 | #: addon\globalPlugins\quickNotetaker\dialogs.py:358
150 | msgid "Last Edited"
151 | msgstr "Последнее редактирование"
152 |
153 | #. Translators: the name of the third column in the notes list in Notes Manager dialog
154 | #: addon\globalPlugins\quickNotetaker\dialogs.py:360
155 | msgid "Preview"
156 | msgstr "Предварительный просмотр"
157 |
158 | #. Translaters: The lable of a button in Notes Manager dialog
159 | #: addon\globalPlugins\quickNotetaker\dialogs.py:368
160 | msgid "&View note..."
161 | msgstr "&Посмотреть заметку..."
162 |
163 | #. Translaters: The lable of a button in Notes Manager dialog
164 | #: addon\globalPlugins\quickNotetaker\dialogs.py:374
165 | msgid "&Edit note..."
166 | msgstr "&Редактировать заметку..."
167 |
168 | #. Translaters: The lable of a button in Notes Manager dialog
169 | #: addon\globalPlugins\quickNotetaker\dialogs.py:380
170 | msgid "Co&py note"
171 | msgstr "&Копировать заметку"
172 |
173 | #. Translaters: The lable of the open in Word button in Notes Manager dialog in case the note has a Word document attached to it
174 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has a Word document attached to it
175 | #: addon\globalPlugins\quickNotetaker\dialogs.py:386
176 | #: addon\globalPlugins\quickNotetaker\dialogs.py:532
177 | msgid "&Open in Microsoft Word..."
178 | msgstr "Открыть в Microsoft &Word..."
179 |
180 | #. Translaters: The lable of a button in Notes Manager dialog
181 | #: addon\globalPlugins\quickNotetaker\dialogs.py:398
182 | msgid "&Delete note..."
183 | msgstr "&Удалить заметку..."
184 |
185 | #. Translators: the label of a button in Notes Manager dialog
186 | #: addon\globalPlugins\quickNotetaker\dialogs.py:412
187 | msgid "&New note..."
188 | msgstr "&Новая заметка..."
189 |
190 | #: addon\globalPlugins\quickNotetaker\dialogs.py:418
191 | msgid "Open &settings..."
192 | msgstr "Открыть нас&тройки..."
193 |
194 | #. Translaters: The lable of a button in Notes Manager dialog
195 | #: addon\globalPlugins\quickNotetaker\dialogs.py:433
196 | msgid "&Close"
197 | msgstr "&Закрыть"
198 |
199 | #. Translators: the message shown to the user when editing the note is not possible
200 | #: addon\globalPlugins\quickNotetaker\dialogs.py:480
201 | msgid ""
202 | "Couldn't edit note! An open Notetaker window with unsaved changes is present."
203 | msgstr ""
204 | "Не удалось отредактировать заметку! Присутствует открытое окно блокнота с "
205 | "несохраненными изменениями."
206 |
207 | #. Translators: the message shown to the user when opening Notetaker is not possible because a one is already opened
208 | #: addon\globalPlugins\quickNotetaker\dialogs.py:504
209 | msgid "Couldn't open Notetaker! A Notetaker window is already opened."
210 | msgstr "Не могу открыть блокнот! Окно блокнота уже открыто."
211 |
212 | #. Translators: the lable of the open in word button in Notes Manager dialog in case the note has no Word document attached to it
213 | #: addon\globalPlugins\quickNotetaker\dialogs.py:535
214 | msgid "Create Microsoft &Word document"
215 | msgstr "Создать документ Microsoft &Word"
216 |
217 | #. Translators: the message shown to the user when the note attached Word document is no longer available.
218 | #. This message is displayed when trying to open the note's Word document from the Notes Manager dialog
219 | #: addon\globalPlugins\quickNotetaker\dialogs.py:606
220 | msgid ""
221 | "A document with the specified name was not found! You can create a new one "
222 | "so you would be able to view this note as a Microsoft Word document."
223 | msgstr ""
224 | "Документ с указанным именем не найден! Вы можете создать новую, чтобы иметь "
225 | "возможность просматривать эту заметку как документ Microsoft Word."
226 |
227 | #. Translators: the warning messaged shown to the user when they try to delete a note from Notes Manager
228 | #: addon\globalPlugins\quickNotetaker\dialogs.py:620
229 | msgid "Are you sure you want to delete this note?"
230 | msgstr "Вы уверены, что хотите удалить эту заметку?"
231 |
232 | #. Translators: the message which tells the user that the directory they tried to save the file in is no longer available,
233 | #. so the file was saved in the user default one if this was possible.
234 | #. If not, the file was saved in the quick Notetaker directory in documents folder
235 | #: addon\globalPlugins\quickNotetaker\dialogs.py:656
236 | msgid ""
237 | "The saved path for the Microsoft Word document no longer exists! The "
238 | "document was saved in the default directory for the ad-on!"
239 | msgstr ""
240 | "Сохраненный путь к документу Microsoft Word больше не существует! Документ "
241 | "был сохранен в каталоге по умолчанию для дополнения!"
242 |
243 | #. Translators: The title of the dialog which allows the user to choose the folder where they want to save the note's corresponding Word document.
244 | #. This dialog is displayed to the user if the option of "Ask me each time where to save the note's corresponding Word document" in quick Notetaker settings is checked
245 | #: addon\globalPlugins\quickNotetaker\dialogs.py:667
246 | msgid "Select the folder where the document will be saved"
247 | msgstr "Выберите папку, в которой будет сохранен документ"
248 |
249 | #. Translators: the title given to a note if it has no title
250 | #: addon\globalPlugins\quickNotetaker\helpers.py:164
251 | msgid "Untitled"
252 | msgstr "Без названия"
253 |
254 | #. Translators: the label of the control in Quick Notetaker settings panel for choosing a default folder where the add-on documents will be saved
255 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:25
256 | msgid "Default documents directory:"
257 | msgstr "Каталог документов по умолчанию:"
258 |
259 | #. Translators: the label of a button to browse for a directory
260 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:32
261 | msgid "Browse..."
262 | msgstr "Обзор..."
263 |
264 | #. Translators: The title of the dialog presented when browsing for the directory where quick notetaker documents will be stored
265 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:35
266 | msgid ""
267 | "Select a default directory where the documents of Quick Notetaker will be "
268 | "stored"
269 | msgstr ""
270 | "Выберите каталог по умолчанию, в котором будут храниться документы быстрого "
271 | "блокнота"
272 |
273 | #. Translators: the label of a check box in Quick Notetaker settings panel
274 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:44
275 | msgid ""
276 | "Ask me each time &where to save the note's corresponding Microsoft Word "
277 | "document"
278 | msgstr ""
279 | "Спрашивать каждый раз &где сохранить соответствующий документ Microsoft Word "
280 | "для заметки"
281 |
282 | #. Translators: the label of a check box in Quick Notetaker settings panel
283 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:51
284 | msgid ""
285 | "&Open the note's corresponding Microsoft Word document after saving or "
286 | "updating"
287 | msgstr ""
288 | "&Открыть соответствующий документ Microsoft Word после сохранения или "
289 | "обновления"
290 |
291 | #. Translators: the label of a check box in Quick Notetaker settings panel
292 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:58
293 | msgid "&Capture the active window title when creating a new note"
294 | msgstr "&Захватить заголовок активного окна при создании новой заметки"
295 |
296 | #. Translators: the label of a check box in Quick Notetaker settings panel
297 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:65
298 | msgid "&Remember the note taker window size and position"
299 | msgstr "Запомнить &размер и положение окна заметки"
300 |
301 | #. Translators: the label of a check box in Quick Notetaker settings panel
302 | #: addon\globalPlugins\quickNotetaker\settingsPanel.py:72
303 | msgid "Au&to align text when editing notes (relevant for RTL languages)"
304 | msgstr ""
305 | "&Автоматическое выравнивание текста при редактировании заметок (актуально "
306 | "для языков с письмом справа налево)"
307 |
308 | #. Add-on description
309 | #. Translators: Long description to be shown for this add-on on add-on information from add-ons manager
310 | #: buildVars.py:26
311 | msgid ""
312 | "A note taker for NVDA. Allows the user to create, edit, view, manage and "
313 | "export notes to different formats."
314 | msgstr ""
315 | "Блокнот для NVDA. Позволяет пользователю создавать, редактировать, "
316 | "просматривать, управлять и экспортировать заметки в различные форматы."
317 |
--------------------------------------------------------------------------------
/COPYING.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Library General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License
307 | along with this program; if not, write to the Free Software
308 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
309 |
310 |
311 | Also add information on how to contact you by electronic and paper mail.
312 |
313 | If the program is interactive, make it output a short notice like this
314 | when it starts in an interactive mode:
315 |
316 | Gnomovision version 69, Copyright (C) year name of author
317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318 | This is free software, and you are welcome to redistribute it
319 | under certain conditions; type `show c' for details.
320 |
321 | The hypothetical commands `show w' and `show c' should show the appropriate
322 | parts of the General Public License. Of course, the commands you use may
323 | be called something other than `show w' and `show c'; they could even be
324 | mouse-clicks or menu items--whatever suits your program.
325 |
326 | You should also get your employer (if you work as a programmer) or your
327 | school, if any, to sign a "copyright disclaimer" for the program, if
328 | necessary. Here is a sample; alter the names:
329 |
330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
332 |
333 | , 1 April 1989
334 | Ty Coon, President of Vice
335 |
336 | This General Public License does not permit incorporating your program into
337 | proprietary programs. If your program is a subroutine library, you may
338 | consider it more useful to permit linking proprietary applications with the
339 | library. If this is what you want to do, use the GNU Library General
340 | Public License instead of this License.
341 |
--------------------------------------------------------------------------------
/addon/globalPlugins/quickNotetaker/dialogs.py:
--------------------------------------------------------------------------------
1 | # dialogs.py
2 | # -*- coding: utf-8 -*-
3 | # A part from Quick Notetaker add-on
4 | # Copyright (C) 2022 NV Access Limited, Mohammad Suliman, Eilana Benish
5 | # This file is covered by the GNU General Public License.
6 | # See the file COPYING for more details.
7 |
8 | import wx
9 | import gui
10 | from gui import guiHelper
11 | from gui import nvdaControls
12 | from gui.dpiScalingHelper import DpiScalingHelperMixin, DpiScalingHelperMixinWithoutInit
13 | from gui.settingsDialogs import NVDASettingsDialog
14 | from logHandler import log
15 | import ui
16 | from .lib.markdown2 import markdown
17 | import weakref
18 | import api
19 | import re
20 | from . import notesManager
21 | from .helpers import *
22 | from . import addonConfig
23 | from .settingsPanel import QuickNotetakerPanel
24 | import addonHandler
25 |
26 |
27 | addonHandler.initTranslation()
28 |
29 |
30 | #: Stores a Notes Manager instance if it exists
31 | notesManagerInstance = None
32 |
33 |
34 | #: Stores a Notes Taker instance if it exists
35 | noteTakerInstance = None
36 |
37 |
38 | class NoteTakerDialog(wx.Dialog):
39 |
40 | @classmethod
41 | def _instance(cls):
42 | """ type: () -> NoteTakerDialog
43 | return None until this is replaced with a weakref.ref object. Then the instance is retrieved
44 | with by treating that object as a callable.
45 | """
46 | return None
47 |
48 | def __new__(cls, *args, **kwargs):
49 | instance = NoteTakerDialog._instance()
50 | if instance is None:
51 | return super(NoteTakerDialog, cls).__new__(cls, *args, **kwargs)
52 | return instance
53 |
54 | def _getDialogSizeAndPosition(self):
55 | dialogSize = wx.Size(500, 500)
56 | dialogPos = wx.DefaultPosition
57 | if addonConfig.getValue("rememberTakerSizeAndPos"):
58 | log.debug(
59 | "Setting Quick Notetaker Notetaker window position and size")
60 | dialogSize = wx.Size(
61 | addonConfig.getValue("takerWidth"),
62 | addonConfig.getValue("takerHeight")
63 | )
64 | dialogPos = wx.Point(
65 | x=addonConfig.getValue("takerXPos"),
66 | y=addonConfig.getValue("takerYPos")
67 | )
68 | return dialogSize, dialogPos
69 |
70 | def __init__(self, currentNote=None, noteTitle=None):
71 | if NoteTakerDialog._instance() is not None:
72 | return
73 | NoteTakerDialog._instance = weakref.ref(self)
74 |
75 | dialogSize, dialogPos = self._getDialogSizeAndPosition()
76 | # Translators: the title for the Quick Notetaker Notetaker window
77 | title = _("Notetaker - Quick Notetaker")
78 | if noteTitle:
79 | title = f"{noteTitle} - {title}"
80 |
81 | super().__init__(
82 | gui.mainFrame,
83 | title=title,
84 | size=dialogSize,
85 | pos=dialogPos,
86 | style=wx.CAPTION | wx.CLOSE_BOX | wx.RESIZE_BORDER | wx.STAY_ON_TOP
87 | )
88 |
89 | mainSizer = wx.BoxSizer(wx.VERTICAL)
90 | sHelper = guiHelper.BoxSizerHelper(self, wx.VERTICAL)
91 | # Translators: a lable of a button in Notetaker dialog
92 | openManagerButton = wx.Button(self, label=_("Open Notes &Manager..."))
93 | openManagerButton.Bind(wx.EVT_BUTTON, self.onOpenManager)
94 | sHelper.addItem(openManagerButton, flag=wx.ALIGN_CENTER)
95 | if notesManagerInstance:
96 | openManagerButton.Disable()
97 | buttonsHelper = guiHelper.ButtonHelper(wx.HORIZONTAL)
98 | preViewButton = buttonsHelper.addButton(
99 | self,
100 | # Translators: a lable of a button in Notetaker dialog
101 | label=_("P&review note..."))
102 | preViewButton.Bind(wx.EVT_BUTTON, self.onPreview)
103 | # Translators: a lable of a button in Notetaker dialog
104 | copyButton = buttonsHelper.addButton(self, label=_("Co&py"))
105 | copyButton.Bind(wx.EVT_BUTTON, self.onCopy)
106 | copyHtmlButton = buttonsHelper.addButton(
107 | self,
108 | # Translators: a lable of a button in Notetaker dialog
109 | label=_("Copy &HTML code"))
110 | copyHtmlButton.Bind(wx.EVT_BUTTON, self.onCopyAsHtml)
111 | sHelper.addItem(buttonsHelper.sizer)
112 |
113 | sizer = wx.BoxSizer(wx.VERTICAL)
114 | # Translators: The lable of the note content edit area in Notetaker dialog
115 | label = wx.StaticText(self, label=_("&Note content:"))
116 | sizer.Add(label, flag=wx.ALIGN_CENTER_HORIZONTAL)
117 | sizer.AddSpacer(guiHelper.SPACE_BETWEEN_ASSOCIATED_CONTROL_VERTICAL)
118 | self.noteEditArea = wx.TextCtrl(
119 | self, style=wx.TE_RICH2 | wx.TE_MULTILINE)
120 | self.noteEditArea.Bind(wx.EVT_TEXT, self.onCharacter)
121 | self.noteEditArea.Bind(wx.EVT_KEY_UP, self.onKeyUp)
122 | sizer.Add(self.noteEditArea, proportion=1, flag=wx.EXPAND)
123 | sHelper.addItem(sizer, proportion=1, flag=wx.EXPAND)
124 | if noteTitle:
125 | self.noteEditArea.SetValue(noteTitle + "\n\n")
126 | self.noteEditArea.SetInsertionPointEnd()
127 | self.currentNote = currentNote
128 | if self.currentNote:
129 | self.noteEditArea.SetValue(self.currentNote.content)
130 | self.noteEditArea.SetFocus()
131 |
132 | if self.currentNote and self.currentNote.docxPath:
133 | # Translators: The label of the check box in Notetaker dialog when editing a note which has Word document attached to it
134 | checkboxText = _(
135 | "Update the corresponding Microsoft &Word document also")
136 | else:
137 | # Translators: The label of the check box in Notetaker dialog when creating a new note or when editing an existing note with no Word document attached to it
138 | checkboxText = _("Save as Microsoft &Word document also")
139 | self.saveAswordCheckBox = sHelper.addItem(
140 | wx.CheckBox(self, label=checkboxText))
141 | if self.currentNote and self.currentNote.docxPath:
142 | self.saveAswordCheckBox.Value = True
143 | buttons = guiHelper.ButtonHelper(wx.HORIZONTAL)
144 | saveButton = buttons.addButton(
145 | self,
146 | id=wx.ID_OK,
147 | # Translators: a lable of a button in Notetaker dialog
148 | label=_("&Save and close"))
149 | saveButton.SetDefault()
150 | saveButton.Bind(wx.EVT_BUTTON, self.onsaveChanges)
151 | discardButton = buttons.addButton(
152 | self,
153 | id=wx.ID_CLOSE,
154 | # Translators: a lable of a button in Notetaker dialog
155 | label=_("&Discard"))
156 | discardButton.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
157 | sHelper.addDialogDismissButtons(buttons, True)
158 | mainSizer.Add(sHelper.sizer, proportion=1, flag=wx.EXPAND)
159 | self.SetSizer(mainSizer)
160 | self.Bind(wx.EVT_CLOSE, self.onDiscard)
161 | self.Bind(wx.EVT_WINDOW_DESTROY, self.onDestroy)
162 | self.EscapeId = wx.ID_CLOSE
163 |
164 | def onDestroy(self, evt):
165 | global noteTakerInstance
166 | noteTakerInstance = None
167 | evt.Skip()
168 |
169 | def onPreview(self, evt):
170 | mdContent = self.noteEditArea.GetValue()
171 | mdContent = handleMdContent(mdContent)
172 | htmlContent = markdown(mdContent, extras=["markdown-in-html"])
173 | title = getTitle(mdContent)
174 | ui.browseableMessage(htmlContent, title, True)
175 |
176 | def onsaveChanges(self, evt):
177 | newContent = self.noteEditArea.GetValue()
178 | if self.saveAswordCheckBox.Value:
179 | self.saveAsWord(newContent)
180 | return
181 | if self.currentNote:
182 | notesManager.updateNote(self.currentNote.id, newContent)
183 | else:
184 | notesManager.saveNewNote(newContent)
185 | self._savePositionInformation()
186 | self._clean()
187 |
188 | def onDiscard(self, evt):
189 | textAreaContent = self.noteEditArea.GetValue()
190 | if not textAreaContent:
191 | self._savePositionInformation()
192 | self._clean()
193 | return
194 | if self.currentNote and self.currentNote.content == textAreaContent:
195 | self._savePositionInformation()
196 | self._clean()
197 | return
198 | res = gui.messageBox(
199 | # Translators: The message which asks the user whether they want to exit and discard changes in Notetaker dialog
200 | _("Are you sure you want to exit and discard changes?"),
201 | # Translators: The title of the message which asks the user whether they want to exit and discard changes in Notetaker dialog
202 | _("Warning"),
203 | style=wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL,
204 | parent=self)
205 | if res == wx.YES:
206 | self._savePositionInformation()
207 | self._clean()
208 |
209 | def _savePositionInformation(self):
210 | position = self.GetPosition()
211 | addonConfig.setValue("takerXPos", position.x)
212 | addonConfig.setValue("takerYPos", position.y)
213 | size = self.GetSize()
214 | addonConfig.setValue("takerWidth", size.width)
215 | addonConfig.setValue("takerHeight", size.height)
216 |
217 | def onOpenManager(self, evt):
218 | global notesManagerInstance
219 | if notesManagerInstance:
220 | gui.messageBox(
221 | # Translators: the message shown to the user when opening Notes Manager is not possible because a one is already opened
222 | _("Couldn't open Notes Manager! A Notes Manager window is already opened."),
223 | # Translators: the title of the message telling the user that opening Notes Manager wasn't possible
224 | _("Warning"),
225 | style=wx.ICON_WARNING | wx.OK,
226 | parent=self
227 | )
228 | return
229 | gui.mainFrame.prePopup()
230 | notesManagerInstance = NotesManagerDialog()
231 | notesManagerInstance.Show()
232 | gui.mainFrame.postPopup()
233 |
234 | def onKeyUp(self, evt):
235 | if evt.GetModifiers() == wx.MOD_CONTROL:
236 | if evt.GetKeyCode() == ord("R"):
237 | self.noteEditArea.SetLayoutDirection(wx.Layout_RightToLeft)
238 | elif evt.GetKeyCode() == ord("L"):
239 | self.noteEditArea.SetLayoutDirection(wx.Layout_LeftToRight)
240 | evt.Skip()
241 |
242 | def onCharacter(self, evt):
243 | content = self.noteEditArea.GetValue()
244 | if not addonConfig.getValue("autoAlignText"):
245 | evt.Skip()
246 | return
247 | res = handleTextAlignment(
248 | content, self.noteEditArea.GetLayoutDirection())
249 | if res == Align.ALIGN_TO_LEFT:
250 | self.noteEditArea.SetLayoutDirection(wx.Layout_LeftToRight)
251 | elif res == Align.ALIGN_TO_RIGHT:
252 | self.noteEditArea.SetLayoutDirection(wx.Layout_RightToLeft)
253 | evt.Skip()
254 |
255 | def onCopy(self, evt):
256 | content = self.noteEditArea.GetValue()
257 | res = api.copyToClip(content, False)
258 | if res == True:
259 | # Translators: The message which tells the user that copying the note was successful
260 | ui.message(_("Copied to clipboard!"))
261 |
262 | def onCopyAsHtml(self, evt):
263 | content = self.noteEditArea.GetValue()
264 | res = api.copyToClip(
265 | markdown(content, extras=["markdown-in-html"]), False)
266 | if res == True:
267 | # Translators: The message which tells the user that copying the note was successful
268 | ui.message(_("Copied to clipboard!"))
269 |
270 | def saveAsWord(self, newContent):
271 | docxPath = ""
272 | if self.currentNote and self.currentNote.docxPath:
273 | docxPath = self.currentNote.docxPath
274 | elif addonConfig.getValue("askWhereToSaveDocx"):
275 | docxPath = askUserWhereToSave(self, newContent)
276 | if docxPath is None:
277 | return
278 | saveAsWord(
279 | newContent,
280 | docxPath,
281 | self._saveAsWordCallback,
282 | self.currentNote.id if self.currentNote else None
283 | )
284 | self._savePositionInformation()
285 | self._clean()
286 |
287 | def _saveAsWordCallback(self, outputFilePath, dirWasChanged, mdContent, noteID):
288 | if noteID:
289 | notesManager.updateNote(noteID, mdContent, outputFilePath)
290 | else:
291 | notesManager.saveNewNote(mdContent, outputFilePath)
292 | notifyDirWasChanged(dirWasChanged)
293 | if notesManagerInstance:
294 | notesManagerInstance.refreshAllNotesList(
295 | notesManagerInstance.notesList.GetFirstSelected())
296 |
297 | def _clean(self):
298 | self.DestroyChildren()
299 | self.Destroy()
300 |
301 |
302 | class NotesManagerDialog(
303 | DpiScalingHelperMixinWithoutInit,
304 | wx.Dialog # wxPython does not seem to call base class initializer, put last in MRO
305 | ):
306 |
307 | @classmethod
308 | def _instance(cls):
309 | """ type: () -> NotesManagerDialog
310 | return None until this is replaced with a weakref.ref object. Then the instance is retrieved
311 | with by treating that object as a callable.
312 | """
313 | return None
314 |
315 | def __new__(cls, *args, **kwargs):
316 | instance = NotesManagerDialog._instance()
317 | if instance is None:
318 | return super(NotesManagerDialog, cls).__new__(cls, *args, **kwargs)
319 | return instance
320 |
321 | def __init__(self):
322 | if NotesManagerDialog._instance() is not None:
323 | return
324 | NotesManagerDialog._instance = weakref.ref(self)
325 |
326 | # Translators: The title of the Notes Manager dialog
327 | title = _("Notes Manager - Quick Notetaker")
328 | super().__init__(
329 | gui.mainFrame,
330 | title=title,
331 | style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER | wx.MAXIMIZE_BOX,
332 | )
333 | mainSizer = wx.BoxSizer(wx.VERTICAL)
334 | firstTextSizer = wx.BoxSizer(wx.VERTICAL)
335 | listAndButtonsSizerHelper = guiHelper.BoxSizerHelper(
336 | self, sizer=wx.BoxSizer(wx.HORIZONTAL))
337 |
338 | # Translators: the label of the notes list in Notes Manager dialog
339 | entriesLabel = _("No&tes:")
340 | firstTextSizer.Add(wx.StaticText(self, label=entriesLabel))
341 | mainSizer.Add(
342 | firstTextSizer,
343 | border=guiHelper.BORDER_FOR_DIALOGS,
344 | flag=wx.TOP | wx.LEFT | wx.RIGHT
345 | )
346 | self.notesList = listAndButtonsSizerHelper.addItem(
347 | nvdaControls.AutoWidthColumnListCtrl(
348 | parent=self,
349 | style=wx.LC_REPORT | wx.LC_SINGLE_SEL,
350 | ),
351 | flag=wx.EXPAND,
352 | proportion=1,
353 | )
354 | # Translators: the name of the first column in the notes list in Notes Manager dialog
355 | self.notesList.InsertColumn(0, _("Title"), width=self.scaleSize(200))
356 | self.notesList.InsertColumn(
357 | # Translators: the name of the second column in the notes list in Notes Manager dialog
358 | 1, _("Last Edited"), width=self.scaleSize(100))
359 | # Translators: the name of the third column in the notes list in Notes Manager dialog
360 | self.notesList.InsertColumn(2, _("Preview"), width=self.scaleSize(400))
361 | self.notesList.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onListItemSelected)
362 |
363 | # this is the group of buttons that affects the currently selected note
364 | entryButtonsHelper = guiHelper.ButtonHelper(wx.VERTICAL)
365 | self.viewButton = entryButtonsHelper.addButton(
366 | self,
367 | # Translaters: The lable of a button in Notes Manager dialog
368 | label=_("&View note..."))
369 | self.viewButton.Disable()
370 | self.viewButton.Bind(wx.EVT_BUTTON, self.onView)
371 | self.editButton = entryButtonsHelper.addButton(
372 | self,
373 | # Translaters: The lable of a button in Notes Manager dialog
374 | label=_("&Edit note..."))
375 | self.editButton.Disable()
376 | self.editButton.Bind(wx.EVT_BUTTON, self.onEdit)
377 | self.copyButton = entryButtonsHelper.addButton(
378 | self,
379 | # Translaters: The lable of a button in Notes Manager dialog
380 | label=_("Co&py note"))
381 | self.copyButton.Disable()
382 | self.copyButton.Bind(wx.EVT_BUTTON, self.onCopy)
383 | self.openInWordButton = entryButtonsHelper.addButton(
384 | self,
385 | # Translaters: The lable of the open in Word button in Notes Manager dialog in case the note has a Word document attached to it
386 | label=_("&Open in Microsoft Word..."))
387 | self.openInWordButton.Disable()
388 | self.openInWordButton.Bind(wx.EVT_BUTTON, self.onOpenInWord)
389 | self.copyHtmlButton = entryButtonsHelper.addButton(
390 | self,
391 | # Translaters: The lable of a button in Notes Manager dialog
392 | label=_("Copy &HTML code"))
393 | self.copyHtmlButton.Disable()
394 | self.copyHtmlButton.Bind(wx.EVT_BUTTON, self.onCopyAsHtml)
395 | self.deleteButton = entryButtonsHelper.addButton(
396 | self,
397 | # Translaters: The lable of a button in Notes Manager dialog
398 | label=_("&Delete note..."))
399 | self.deleteButton.Disable()
400 | self.deleteButton.Bind(wx.EVT_BUTTON, self.onDelete)
401 | listAndButtonsSizerHelper.addItem(entryButtonsHelper.sizer)
402 |
403 | mainSizer.Add(
404 | listAndButtonsSizerHelper.sizer,
405 | border=guiHelper.BORDER_FOR_DIALOGS,
406 | flag=wx.ALL | wx.EXPAND,
407 | proportion=1,
408 | )
409 |
410 | generalActions = guiHelper.ButtonHelper(wx.HORIZONTAL)
411 | # Translators: the label of a button in Notes Manager dialog
412 | newNoteButton = generalActions.addButton(self, label=_("&New note..."))
413 | newNoteButton.Bind(wx.EVT_BUTTON, self.onNewNote)
414 | if noteTakerInstance:
415 | newNoteButton.Disable()
416 | # Translaters: The lable of a button in Notes Manager dialog
417 | openSettingsButton = generalActions.addButton(
418 | self, label=_("Open &settings..."))
419 | openSettingsButton.Bind(wx.EVT_BUTTON, self.onSettings)
420 | mainSizer.Add(
421 | generalActions.sizer,
422 | border=guiHelper.BORDER_FOR_DIALOGS,
423 | flag=wx.LEFT | wx.RIGHT
424 | )
425 |
426 | mainSizer.Add(
427 | wx.StaticLine(self),
428 | border=guiHelper.BORDER_FOR_DIALOGS,
429 | flag=wx.ALL | wx.EXPAND
430 | )
431 |
432 | # Translaters: The lable of a button in Notes Manager dialog
433 | closeButton = wx.Button(self, label=_("&Close"), id=wx.ID_CLOSE)
434 | closeButton.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
435 | mainSizer.Add(
436 | closeButton,
437 | border=guiHelper.BORDER_FOR_DIALOGS,
438 | flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.CENTER | wx.ALIGN_RIGHT
439 | )
440 | self.Bind(wx.EVT_CLOSE, self.onClose)
441 | self.EscapeId = wx.ID_CLOSE
442 |
443 | mainSizer.Fit(self)
444 | self.SetSizer(mainSizer)
445 |
446 | self.refreshAllNotesList()
447 | self.SetMinSize(mainSizer.GetMinSize())
448 | self.SetSize(self.scaleSize((763, 509)))
449 | self.CentreOnScreen()
450 | self.notesList.SetFocus()
451 | self.Bind(wx.EVT_ACTIVATE, self.onActivate)
452 | self.Bind(wx.EVT_WINDOW_DESTROY, self.onDestroy)
453 |
454 | def onActivate(self, evt):
455 | if evt.GetActive():
456 | self.refreshAllNotesList(self.notesList.GetFirstSelected())
457 | evt.Skip()
458 |
459 | def onDestroy(self, evt):
460 | global notesManagerInstance
461 | notesManagerInstance = None
462 | evt.Skip()
463 |
464 | def onView(self, evt):
465 | curNote = self._getCurrentNote()
466 | if not curNote:
467 | return
468 | content = handleMdContent(curNote.content)
469 | contentAsHtml = markdown(content, extras=["markdown-in-html"])
470 | ui.browseableMessage(contentAsHtml, curNote.title, True)
471 |
472 | def onEdit(self, evt):
473 | curNote = self._getCurrentNote()
474 | if not curNote:
475 | return
476 | global noteTakerInstance
477 | if noteTakerInstance:
478 | gui.messageBox(
479 | # Translators: the message shown to the user when editing the note is not possible
480 | _("Couldn't edit note! An open Notetaker window with unsaved changes is present."),
481 | # Translators: the title of the message telling the user that editing the note wasn't possible
482 | _("Warning"),
483 | style=wx.ICON_WARNING | wx.OK,
484 | parent=self
485 | )
486 | return
487 | gui.mainFrame.prePopup()
488 | noteTakerInstance = NoteTakerDialog(currentNote=curNote)
489 | noteTakerInstance.Show()
490 | gui.mainFrame.postPopup()
491 |
492 | def _getCurrentNote(self):
493 | index = self.notesList.GetFirstSelected()
494 | if index < 0:
495 | return
496 | curNote = notesManager.loadAllNotes()[index]
497 | return curNote
498 |
499 | def onNewNote(self, evt):
500 | global noteTakerInstance
501 | if noteTakerInstance:
502 | gui.messageBox(
503 | # Translators: the message shown to the user when opening Notetaker is not possible because a one is already opened
504 | _("Couldn't open Notetaker! A Notetaker window is already opened."),
505 | # Translators: the title of the message telling the user that opening Notetaker wasn't possible
506 | _("Warning"),
507 | style=wx.ICON_WARNING | wx.OK,
508 | parent=self
509 | )
510 | return
511 | gui.mainFrame.prePopup()
512 | noteTakerInstance = NoteTakerDialog()
513 | noteTakerInstance.Show()
514 | gui.mainFrame.postPopup()
515 |
516 | def onSettings(self, evt):
517 | gui.mainFrame._popupSettingsDialog(
518 | NVDASettingsDialog, QuickNotetakerPanel)
519 |
520 | def onClose(self, evt):
521 | self.DestroyChildren()
522 | self.Destroy()
523 | evt.Skip()
524 |
525 | def onListItemSelected(self, evt):
526 | self.viewButton.Enable()
527 | self.editButton.Enable()
528 | self.copyButton.Enable()
529 | curNote = self._getCurrentNote()
530 | if curNote and curNote.docxPath:
531 | # Translators: the lable of the open in word button in Notes Manager dialog in case the note has a Word document attached to it
532 | label = _("&Open in Microsoft Word...")
533 | else:
534 | # Translators: the lable of the open in word button in Notes Manager dialog in case the note has no Word document attached to it
535 | label = _("Create Microsoft &Word document")
536 | if addonConfig.getValue("askWhereToSaveDocx"):
537 | label += "..."
538 | self.openInWordButton.SetLabel(label)
539 | self.openInWordButton.Enable()
540 | self.copyHtmlButton.Enable()
541 | self.deleteButton.Enable()
542 |
543 | def refreshAllNotesList(self, activeIndex=0):
544 | self.notesList.DeleteAllItems()
545 | for note in notesManager.loadAllNotes():
546 | self.notesList.Append((
547 | note.title,
548 | note.lastEdited,
549 | getPreviewText(note.content)
550 | ))
551 | # Select the given active note or the first one if not given
552 | allNotesLen = len(notesManager.loadAllNotes())
553 | if allNotesLen > 0:
554 | if activeIndex == -1:
555 | activeIndex = allNotesLen - 1
556 | elif activeIndex < 0 or activeIndex >= allNotesLen:
557 | activeIndex = 0
558 | self.notesList.Select(activeIndex, on=1)
559 | self.notesList.SetItemState(
560 | activeIndex, wx.LIST_STATE_FOCUSED, wx.LIST_STATE_FOCUSED)
561 | else:
562 | self.viewButton.Disable()
563 | self.editButton.Disable()
564 | self.copyButton.Disable()
565 | self.openInWordButton.Disable()
566 | self.copyHtmlButton.Disable()
567 | self.deleteButton.Disable()
568 |
569 | def onOpenInWord(self, evt):
570 | curNote = self._getCurrentNote()
571 | if curNote and curNote.docxPath:
572 | openInWord(
573 | curNote.docxPath,
574 | self._openInWordCallback,
575 | curNote.id
576 | )
577 | return
578 | if not curNote:
579 | return
580 | docxPath = ""
581 | if addonConfig.getValue("askWhereToSaveDocx"):
582 | docxPath = askUserWhereToSave(self, curNote.content)
583 | if docxPath is None:
584 | return
585 | saveAsWord(
586 | curNote.content,
587 | docxPath,
588 | self._saveAsWordCallback,
589 | curNote.id
590 | )
591 |
592 | def _saveAsWordCallback(self, outputFilePath, dirWasChanged, mdContent, noteID):
593 | notesManager.updateNote(noteID, docxPath=outputFilePath)
594 | notifyDirWasChanged(dirWasChanged)
595 | if not self:
596 | return
597 | self.refreshAllNotesList(self.notesList.GetFirstSelected())
598 |
599 | def _openInWordCallback(self, hasSucceeded, noteID):
600 | if hasSucceeded:
601 | return
602 | notesManager.updateNote(noteID, docxPath="")
603 | gui.messageBox(
604 | # Translators: the message shown to the user when the note attached Word document is no longer available.
605 | # This message is displayed when trying to open the note's Word document from the Notes Manager dialog
606 | _("A document with the specified name was not found! You can create a new one so you would be able to view this note as a Microsoft Word document."),
607 | # Translators: the title of the message shown to the user when the note attached Word document is no longer available.
608 | # This message is displayed when trying to open the note's Word document from the Notes Manager dialog
609 | _("Warning"),
610 | style=wx.ICON_WARNING | wx.OK,
611 | parent=gui.mainFrame
612 | )
613 |
614 | def onDelete(self, evt):
615 | curNote = self._getCurrentNote()
616 | if not curNote:
617 | return
618 | res = gui.messageBox(
619 | # Translators: the warning messaged shown to the user when they try to delete a note from Notes Manager
620 | _("Are you sure you want to delete this note?"),
621 | # Translators: the title of the warning messaged shown to the user when they try to delete a note from Notes Manager
622 | _("Warning"),
623 | style=wx.YES_NO | wx.NO_DEFAULT,
624 | parent=self)
625 | if res != wx.YES:
626 | return
627 | notesManager.deleteNote(curNote.id)
628 | self.refreshAllNotesList(self.notesList.GetFirstSelected())
629 |
630 | def onCopy(self, evt):
631 | curNote = self._getCurrentNote()
632 | if not curNote:
633 | return
634 | res = api.copyToClip(curNote.content, False)
635 | if res == True:
636 | # Translators: the message telling the user that copying the note was successful
637 | ui.message(_("Copied to clipboard!"))
638 |
639 | def onCopyAsHtml(self, evt):
640 | curNote = self._getCurrentNote()
641 | if not curNote:
642 | return
643 | res = api.copyToClip(
644 | markdown(curNote.content, extras=["markdown-in-html"]), False)
645 | if res:
646 | # Translators: the message telling the user that copying the note was successful
647 | ui.message(_("Copied to clipboard!"))
648 |
649 |
650 | def notifyDirWasChanged(dirWasChanged):
651 | if dirWasChanged:
652 | gui.messageBox(
653 | # Translators: the message which tells the user that the directory they tried to save the file in is no longer available,
654 | # so the file was saved in the user default one if this was possible.
655 | # If not, the file was saved in the quick Notetaker directory in documents folder
656 | _("The saved path for the Microsoft Word document no longer exists! The document was saved in the default directory for the ad-on!"),
657 | # Translators: the title of the message telling the user that the directory they tried to save the document in is no longer available.
658 | # See the message body for more details
659 | _("Warning"),
660 | style=wx.ICON_WARNING | wx.OK,
661 | parent=gui.mainFrame)
662 |
663 |
664 | def askUserWhereToSave(parent, noteContent):
665 | # Translators: The title of the dialog which allows the user to choose the folder where they want to save the note's corresponding Word document.
666 | # This dialog is displayed to the user if the option of "Ask me each time where to save the note's corresponding Word document" in quick Notetaker settings is checked
667 | with wx.DirDialog(parent, _("Select the folder where the document will be saved"), defaultPath=addonConfig.getValue("notesDocumentsPath")) as d:
668 | if d.ShowModal() == wx.ID_OK:
669 | return f"{d.Path}/{getTitle(noteContent)}.docx"
670 | else:
671 | return None
672 |
--------------------------------------------------------------------------------