plover 5.0.0.dev2__py3-none-any.whl → 5.0.0.dev3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. plover/__init__.py +8 -7
  2. plover/__main__.py +1 -1
  3. plover/command/set_config.py +7 -4
  4. plover/config.py +177 -74
  5. plover/dictionary/base.py +21 -9
  6. plover/dictionary/helpers.py +6 -4
  7. plover/dictionary/json_dict.py +10 -12
  8. plover/dictionary/loading_manager.py +8 -10
  9. plover/dictionary/rtfcre_dict.py +46 -43
  10. plover/dictionary/rtfcre_parse.py +116 -100
  11. plover/engine.py +112 -96
  12. plover/exception.py +4 -1
  13. plover/formatting.py +198 -140
  14. plover/gui_none/add_translation.py +17 -16
  15. plover/gui_none/engine.py +1 -3
  16. plover/gui_none/main.py +2 -2
  17. plover/gui_qt/about_dialog.py +17 -17
  18. plover/gui_qt/add_translation_dialog.py +8 -9
  19. plover/gui_qt/add_translation_widget.py +66 -63
  20. plover/gui_qt/config_window.py +274 -154
  21. plover/gui_qt/console_widget.py +9 -13
  22. plover/gui_qt/dictionaries_widget.py +140 -119
  23. plover/gui_qt/dictionary_editor.py +60 -61
  24. plover/gui_qt/engine.py +3 -3
  25. plover/gui_qt/info_browser.py +50 -4
  26. plover/gui_qt/log_qt.py +3 -2
  27. plover/gui_qt/lookup_dialog.py +9 -9
  28. plover/gui_qt/machine_options.py +38 -37
  29. plover/gui_qt/main.py +19 -19
  30. plover/gui_qt/main_window.py +88 -71
  31. plover/gui_qt/paper_tape.py +69 -52
  32. plover/gui_qt/paper_tape_ui.py +0 -3
  33. plover/gui_qt/plugins_manager.py +47 -43
  34. plover/gui_qt/resources_rc.py +28 -28
  35. plover/gui_qt/run_dialog.py +7 -6
  36. plover/gui_qt/steno_validator.py +2 -3
  37. plover/gui_qt/suggestions_dialog.py +34 -38
  38. plover/gui_qt/suggestions_widget.py +22 -16
  39. plover/gui_qt/tool.py +1 -3
  40. plover/gui_qt/trayicon.py +19 -19
  41. plover/gui_qt/utils.py +19 -9
  42. plover/i18n.py +9 -8
  43. plover/key_combo.py +130 -130
  44. plover/log.py +26 -26
  45. plover/machine/base.py +40 -35
  46. plover/machine/geminipr.py +7 -7
  47. plover/machine/keyboard.py +16 -14
  48. plover/machine/keyboard_capture/__init__.py +0 -1
  49. plover/machine/keymap.py +24 -20
  50. plover/machine/passport.py +6 -5
  51. plover/machine/procat.py +12 -16
  52. plover/machine/stentura.py +45 -29
  53. plover/machine/txbolt.py +5 -3
  54. plover/macro/repeat.py +0 -1
  55. plover/macro/retro.py +9 -9
  56. plover/macro/undo.py +4 -3
  57. plover/meta/attach.py +12 -10
  58. plover/meta/case.py +2 -1
  59. plover/meta/conditional.py +3 -3
  60. plover/meta/currency.py +4 -4
  61. plover/meta/mode.py +15 -15
  62. plover/meta/punctuation.py +1 -0
  63. plover/misc.py +21 -17
  64. plover/orthography.py +12 -10
  65. plover/oslayer/__init__.py +7 -5
  66. plover/oslayer/config.py +16 -15
  67. plover/oslayer/controller.py +13 -13
  68. plover/oslayer/linux/i18n.py +2 -1
  69. plover/oslayer/linux/keyboardcontrol.py +2 -2
  70. plover/oslayer/linux/keyboardcontrol_uinput.py +48 -3
  71. plover/oslayer/linux/keyboardcontrol_x11.py +860 -851
  72. plover/oslayer/linux/log.py +1 -1
  73. plover/oslayer/linux/log_dbus.py +97 -65
  74. plover/oslayer/linux/serial.py +2 -2
  75. plover/oslayer/linux/wmctrl_x11.py +11 -15
  76. plover/oslayer/osx/keyboardcontrol.py +194 -99
  77. plover/oslayer/osx/keyboardlayout.py +138 -119
  78. plover/oslayer/osx/log.py +14 -8
  79. plover/oslayer/osx/serial.py +1 -1
  80. plover/oslayer/osx/wmctrl.py +6 -1
  81. plover/oslayer/windows/keyboardcontrol.py +195 -89
  82. plover/oslayer/windows/keyboardlayout.py +367 -334
  83. plover/oslayer/windows/log.py +5 -3
  84. plover/oslayer/windows/serial.py +4 -5
  85. plover/oslayer/windows/wmctrl.py +1 -1
  86. plover/output/__init__.py +1 -2
  87. plover/output/keyboard.py +15 -15
  88. plover/plugins_manager/__main__.py +42 -39
  89. plover/plugins_manager/global_registry.py +2 -5
  90. plover/plugins_manager/local_registry.py +11 -13
  91. plover/plugins_manager/package_index.py +12 -18
  92. plover/plugins_manager/pip_wrapper.py +5 -5
  93. plover/plugins_manager/plugin_metadata.py +17 -9
  94. plover/plugins_manager/registry.py +39 -28
  95. plover/plugins_manager/requests.py +2 -4
  96. plover/plugins_manager/utils.py +9 -7
  97. plover/registry.py +28 -26
  98. plover/resource.py +13 -10
  99. plover/scripts/dist_main.py +7 -7
  100. plover/scripts/main.py +57 -34
  101. plover/scripts/send_command.py +13 -7
  102. plover/steno.py +16 -9
  103. plover/steno_dictionary.py +47 -21
  104. plover/suggestions.py +11 -11
  105. plover/system/__init__.py +39 -23
  106. plover/system/english_stenotype.py +231 -229
  107. plover/translation.py +67 -51
  108. {plover-5.0.0.dev2.dist-info → plover-5.0.0.dev3.dist-info}/METADATA +1 -1
  109. plover-5.0.0.dev3.dist-info/RECORD +216 -0
  110. plover_build_utils/check_requirements.py +5 -6
  111. plover_build_utils/download.py +10 -8
  112. plover_build_utils/get_pip.py +10 -5
  113. plover_build_utils/install_wheels.py +33 -31
  114. plover_build_utils/pyqt.py +24 -22
  115. plover_build_utils/setup.py +64 -54
  116. plover_build_utils/source_less.py +6 -6
  117. plover_build_utils/testing/blackbox.py +31 -31
  118. plover_build_utils/testing/dict.py +3 -3
  119. plover_build_utils/testing/output.py +5 -6
  120. plover_build_utils/testing/parametrize.py +5 -3
  121. plover_build_utils/testing/steno_dictionary.py +145 -124
  122. plover_build_utils/tree.py +21 -19
  123. plover_build_utils/trim.py +5 -5
  124. plover_build_utils/zipdir.py +3 -3
  125. plover-5.0.0.dev2.dist-info/RECORD +0 -216
  126. {plover-5.0.0.dev2.dist-info → plover-5.0.0.dev3.dist-info}/WHEEL +0 -0
  127. {plover-5.0.0.dev2.dist-info → plover-5.0.0.dev3.dist-info}/entry_points.txt +0 -0
  128. {plover-5.0.0.dev2.dist-info → plover-5.0.0.dev3.dist-info}/licenses/LICENSE.txt +0 -0
  129. {plover-5.0.0.dev2.dist-info → plover-5.0.0.dev3.dist-info}/top_level.txt +0 -0
  130. {plover-5.0.0.dev2.dist-info → plover-5.0.0.dev3.dist-info}/zip-safe +0 -0
@@ -1,4 +1,3 @@
1
-
2
1
  from threading import Thread
3
2
  import atexit
4
3
  import html
@@ -6,7 +5,13 @@ import os
6
5
  import sys
7
6
 
8
7
  from PySide6.QtCore import Qt, Signal, Slot
9
- from PySide6.QtWidgets import QDialog, QMessageBox, QTableWidgetItem, QInputDialog,QWidget
8
+ from PySide6.QtWidgets import (
9
+ QDialog,
10
+ QMessageBox,
11
+ QTableWidgetItem,
12
+ QInputDialog,
13
+ QWidget,
14
+ )
10
15
 
11
16
  from plover.gui_qt.tool import Tool
12
17
  from plover.gui_qt.info_browser import InfoBrowser
@@ -18,10 +23,9 @@ from plover.plugins_manager.__main__ import pip
18
23
 
19
24
 
20
25
  class PluginsManager(Tool, Ui_PluginsManager):
21
-
22
- TITLE = 'Plugins Manager'
23
- ROLE = 'plugins_manager'
24
- ICON = ':/resources/plugins_manager.svg'
26
+ TITLE = "Plugins Manager"
27
+ ROLE = "plugins_manager"
28
+ ICON = ":/resources/plugins_manager.svg"
25
29
 
26
30
  # We use a class instance so the state is persistent
27
31
  # accross different executions of the dialog when
@@ -46,7 +50,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
46
50
 
47
51
  def _need_restart(self):
48
52
  for state in self._packages:
49
- if state.status in ('removed', 'updated'):
53
+ if state.status in ("removed", "updated"):
50
54
  return True
51
55
  return False
52
56
 
@@ -62,7 +66,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
62
66
  self.table.setSortingEnabled(False)
63
67
  self.table.setRowCount(len(self._packages))
64
68
  for row, state in enumerate(self._packages):
65
- for column, attr in enumerate('status name version summary'.split()):
69
+ for column, attr in enumerate("status name version summary".split()):
66
70
  item = QTableWidgetItem(getattr(state, attr, "N/A"))
67
71
  item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEditable)
68
72
  self.table.setItem(row, column, item)
@@ -80,12 +84,12 @@ class PluginsManager(Tool, Ui_PluginsManager):
80
84
  if item.column() != 0:
81
85
  continue
82
86
  state = self._get_state(item.row())
83
- if state.status in ('installed', 'updated'):
87
+ if state.status in ("installed", "updated"):
84
88
  can_uninstall.append(state.name)
85
- elif state.status in ('outdated',):
89
+ elif state.status in ("outdated",):
86
90
  can_uninstall.append(state.name)
87
91
  can_install.append(state.name)
88
- elif state.status != 'unsupported' and state.latest:
92
+ elif state.status != "unsupported" and state.latest:
89
93
  can_install.append(state.name)
90
94
  return can_install, can_uninstall
91
95
 
@@ -108,7 +112,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
108
112
  metadata = self._get_state(current_item.row()).metadata
109
113
  if metadata is None:
110
114
  return
111
- prologue = '<h1>%s (%s)</h1>' % (
115
+ prologue = "<h1>%s (%s)</h1>" % (
112
116
  html.escape(metadata.name),
113
117
  html.escape(metadata.version),
114
118
  )
@@ -122,7 +126,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
122
126
  metadata.home_page,
123
127
  html.escape(metadata.home_page),
124
128
  )
125
- prologue += '<hr>'
129
+ prologue += "<hr>"
126
130
  if metadata.description:
127
131
  description = metadata.description
128
132
  description_content_type = metadata.description_content_type
@@ -138,7 +142,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
138
142
  self._engine.restart()
139
143
  else:
140
144
  atexit._run_exitfuncs()
141
- args = [sys.executable, '-m', __spec__.name]
145
+ args = [sys.executable, "-m", __spec__.name]
142
146
  os.execv(args[0], args)
143
147
 
144
148
  def _update_packages(self):
@@ -146,7 +150,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
146
150
  self._packages_updated.emit()
147
151
 
148
152
  def _clear_info(self):
149
- self.info.setHtml('')
153
+ self.info.setHtml("")
150
154
 
151
155
  @Slot()
152
156
  def refresh(self):
@@ -159,43 +163,42 @@ class PluginsManager(Tool, Ui_PluginsManager):
159
163
  @Slot()
160
164
  def install_from_git(self):
161
165
  url, ok = QInputDialog.getText(
162
- self, "Install from Git repo",
163
- '<b>WARNING: Installing plugins is a security risk.<br>'
164
- 'A plugin from a Git repo can contain malicious code.<br>'
165
- 'Only install it if you got it from a trusted source.</b><br><br>'
166
- 'Enter repository link for plugin<br>'
167
- '(will look similar to '
168
- 'https://github.com/user/repository.git): <br>'
169
- )
166
+ self,
167
+ "Install from Git repo",
168
+ "<b>WARNING: Installing plugins is a security risk.<br>"
169
+ "A plugin from a Git repo can contain malicious code.<br>"
170
+ "Only install it if you got it from a trusted source.</b><br><br>"
171
+ "Enter repository link for plugin<br>"
172
+ "(will look similar to "
173
+ "https://github.com/user/repository.git): <br>",
174
+ )
170
175
  if not ok or not url:
171
176
  return
172
177
 
173
- code = self._run(
174
- ['install'] +
175
- ['git+' + url]
176
- )
178
+ code = self._run(["install"] + ["git+" + url])
177
179
  if code == QDialog.DialogCode.Accepted:
178
180
  self._update_table()
179
181
  self.restart_button.setEnabled(True)
180
-
182
+
181
183
  @Slot()
182
184
  def install_selected_package(self):
183
185
  packages = self._get_selection()[0]
184
- if QMessageBox.warning(
185
- self, 'Install ' + ', '.join(packages),
186
- 'Installing plugins is a <b>security risk</b>. '
187
- 'A plugin can contain virus/malware. '
188
- 'Only install it if you got it from a trusted source.'
189
- ' Are you sure you want to proceed?'
190
- ,
191
- buttons=QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
192
- defaultButton=QMessageBox.StandardButton.No
193
- ) != QMessageBox.StandardButton.Yes:
186
+ if (
187
+ QMessageBox.warning(
188
+ self,
189
+ "Install " + ", ".join(packages),
190
+ "Installing plugins is a <b>security risk</b>. "
191
+ "A plugin can contain virus/malware. "
192
+ "Only install it if you got it from a trusted source."
193
+ " Are you sure you want to proceed?",
194
+ buttons=QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
195
+ defaultButton=QMessageBox.StandardButton.No,
196
+ )
197
+ != QMessageBox.StandardButton.Yes
198
+ ):
194
199
  return
195
200
  code = self._run(
196
- ['install'] +
197
- [self._packages[name].latest.requirement
198
- for name in packages]
201
+ ["install"] + [self._packages[name].latest.requirement for name in packages]
199
202
  )
200
203
  if code == QDialog.DialogCode.Accepted:
201
204
  for name in packages:
@@ -207,7 +210,7 @@ class PluginsManager(Tool, Ui_PluginsManager):
207
210
  @Slot()
208
211
  def uninstall_selected_package(self):
209
212
  packages = self._get_selection()[1]
210
- code = self._run(['uninstall', '-y'] + packages)
213
+ code = self._run(["uninstall", "-y"] + packages)
211
214
  if code == QDialog.DialogCode.Accepted:
212
215
  for name in packages:
213
216
  state = self._packages[name]
@@ -216,8 +219,9 @@ class PluginsManager(Tool, Ui_PluginsManager):
216
219
  self.restart_button.setEnabled(True)
217
220
 
218
221
 
219
- if __name__ == '__main__':
222
+ if __name__ == "__main__":
220
223
  from PySide6.QtWidgets import QApplication
224
+
221
225
  app = QApplication([])
222
226
  dlg = PluginsManager(None)
223
227
  dlg.show()
@@ -2853,61 +2853,61 @@ qt_resource_struct = b"\
2853
2853
  \x00\x00\x00\x00\x00\x02\x00\x00\x00\x1c\x00\x00\x00\x02\
2854
2854
  \x00\x00\x00\x00\x00\x00\x00\x00\
2855
2855
  \x00\x00\x01\x84\x00\x00\x00\x00\x00\x01\x00\x00:\x0b\
2856
- \x00\x00\x01\x97o\xda\xdfx\
2856
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2857
2857
  \x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xac\
2858
- \x00\x00\x01\x97o\xda\xdfx\
2858
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2859
2859
  \x00\x00\x03H\x00\x00\x00\x00\x00\x01\x00\x00\x9aw\
2860
- \x00\x00\x01\x97o\xda\xdfx\
2860
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2861
2861
  \x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x1a\xf6\
2862
- \x00\x00\x01\x97o\xda\xdfx\
2862
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2863
2863
  \x00\x00\x00X\x00\x00\x00\x00\x00\x01\x00\x00\x04*\
2864
- \x00\x00\x01\x97o\xda\xdfx\
2864
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2865
2865
  \x00\x00\x00.\x00\x00\x00\x00\x00\x01\x00\x00\x01\x06\
2866
- \x00\x00\x01\x97o\xda\xdfx\
2866
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2867
2867
  \x00\x00\x03.\x00\x00\x00\x00\x00\x01\x00\x00\x98\xcc\
2868
- \x00\x00\x01\x97o\xda\xdfx\
2868
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2869
2869
  \x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
2870
- \x00\x00\x01\x97o\xda\xdfw\
2870
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2871
2871
  \x00\x00\x03\x00\x00\x00\x00\x00\x00\x01\x00\x00\x93:\
2872
- \x00\x00\x01\x97o\xda\xdfw\
2872
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2873
2873
  \x00\x00\x01p\x00\x00\x00\x00\x00\x01\x00\x0072\
2874
- \x00\x00\x01\x97o\xda\xdfx\
2874
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2875
2875
  \x00\x00\x01\xee\x00\x00\x00\x00\x00\x01\x00\x00E\x9b\
2876
- \x00\x00\x01\x97o\xda\xdfw\
2876
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2877
2877
  \x00\x00\x00\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x0bW\
2878
- \x00\x00\x01\x97o\xda\xdfx\
2878
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2879
2879
  \x00\x00\x01H\x00\x00\x00\x00\x00\x01\x00\x00%i\
2880
- \x00\x00\x01\x97o\xda\xdfx\
2880
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2881
2881
  \x00\x00\x03p\x00\x00\x00\x00\x00\x01\x00\x00\x9b\xd6\
2882
- \x00\x00\x01\x97o\xda\xdfx\
2882
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2883
2883
  \x00\x00\x00\x8a\x00\x00\x00\x00\x00\x01\x00\x00\x06\xc2\
2884
- \x00\x00\x01\x97o\xda\xdfx\
2884
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2885
2885
  \x00\x00\x01\x04\x00\x00\x00\x00\x00\x01\x00\x00\x16:\
2886
- \x00\x00\x01\x97o\xda\xdfx\
2886
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2887
2887
  \x00\x00\x03\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x9f\xae\
2888
- \x00\x00\x01\x97o\xda\xdfx\
2888
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2889
2889
  \x00\x00\x01\xa4\x00\x00\x00\x00\x00\x01\x00\x00?\xd7\
2890
- \x00\x00\x01\x97o\xda\xdfx\
2890
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2891
2891
  \x00\x00\x02F\x00\x00\x00\x00\x00\x01\x00\x00si\
2892
- \x00\x00\x01\x97o\xda\xdfw\
2892
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2893
2893
  \x00\x00\x01\xbe\x00\x00\x00\x00\x00\x01\x00\x00C\x93\
2894
- \x00\x00\x01\x97o\xda\xdfw\
2894
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2895
2895
  \x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x0c]\
2896
- \x00\x00\x01\x97o\xda\xdfx\
2896
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2897
2897
  \x00\x00\x02z\x00\x00\x00\x00\x00\x01\x00\x00{\x0c\
2898
- \x00\x00\x01\x97o\xda\xdfx\
2898
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2899
2899
  \x00\x00\x02\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x8c^\
2900
- \x00\x00\x01\x97o\xda\xdfw\
2900
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2901
2901
  \x00\x00\x02\x1c\x00\x00\x00\x00\x00\x01\x00\x00p\xec\
2902
- \x00\x00\x01\x97o\xda\xdfx\
2902
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2903
2903
  \x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x10\xac\
2904
- \x00\x00\x01\x97o\xda\xdfx\
2904
+ \x00\x00\x01\x98\x07\x8f\x01\x0c\
2905
2905
  \x00\x00\x02\x02\x00\x00\x00\x00\x00\x01\x00\x00F\xd9\
2906
- \x00\x00\x01\x97o\xda\xdfx\
2906
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2907
2907
  \x00\x00\x00D\x00\x00\x00\x00\x00\x01\x00\x00\x02Y\
2908
- \x00\x00\x01\x97o\xda\xdfx\
2908
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2909
2909
  \x00\x00\x02\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x7f#\
2910
- \x00\x00\x01\x97o\xda\xdfw\
2910
+ \x00\x00\x01\x98\x07\x8f\x01\x0b\
2911
2911
  "
2912
2912
 
2913
2913
  def qInitResources():
@@ -1,4 +1,3 @@
1
-
2
1
  from PySide6.QtWidgets import QDialogButtonBox, QDialog
3
2
 
4
3
  from plover.gui_qt.console_widget import ConsoleWidget
@@ -6,7 +5,6 @@ from plover.gui_qt.run_dialog_ui import Ui_RunDialog
6
5
 
7
6
 
8
7
  class RunDialog(QDialog, Ui_RunDialog):
9
-
10
8
  def __init__(self, run_args, popen=None):
11
9
  super().__init__()
12
10
  self.setupUi(self)
@@ -24,16 +22,19 @@ class RunDialog(QDialog, Ui_RunDialog):
24
22
 
25
23
  def reject(self):
26
24
  if self._successful is not None:
27
- super().done(getattr(QDialog.DialogCode, 'Accepted'
28
- if self._successful
29
- else 'Rejected'))
25
+ super().done(
26
+ getattr(
27
+ QDialog.DialogCode, "Accepted" if self._successful else "Rejected"
28
+ )
29
+ )
30
30
  return
31
31
  self._console.terminate()
32
32
 
33
33
 
34
- if __name__ == '__main__':
34
+ if __name__ == "__main__":
35
35
  import sys
36
36
  from PySide6.QtWidgets import QApplication
37
+
37
38
  app = QApplication([])
38
39
  dlg = RunDialog(sys.argv[1:])
39
40
  dlg.show()
@@ -4,12 +4,11 @@ from plover.steno import normalize_steno
4
4
 
5
5
 
6
6
  class StenoValidator(QValidator):
7
-
8
7
  def validate(self, text, pos):
9
- if not text.strip('-/'):
8
+ if not text.strip("-/"):
10
9
  state = QValidator.State.Intermediate
11
10
  else:
12
- prefix = text.rstrip('-/')
11
+ prefix = text.rstrip("-/")
13
12
  if text == prefix:
14
13
  state = QValidator.State.Acceptable
15
14
  steno = text
@@ -1,4 +1,3 @@
1
-
2
1
  import re
3
2
 
4
3
  from PySide6.QtCore import Qt, Slot
@@ -16,22 +15,22 @@ from plover import _
16
15
  from plover.suggestions import Suggestion
17
16
  from plover.formatting import RetroFormatter
18
17
 
18
+ from plover.gui_qt import utils
19
19
  from plover.gui_qt.suggestions_dialog_ui import Ui_SuggestionsDialog
20
20
  from plover.gui_qt.utils import ToolBar
21
21
  from plover.gui_qt.tool import Tool
22
22
 
23
23
 
24
24
  class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
25
-
26
25
  # i18n: Widget: “SuggestionsDialog”, tooltip.
27
- __doc__ = _('Suggest possible strokes for the last written words.')
26
+ __doc__ = _("Suggest possible strokes for the last written words.")
28
27
 
29
- TITLE = _('Suggestions')
30
- ICON = ':/resources/lightbulb.svg'
31
- ROLE = 'suggestions'
32
- SHORTCUT = 'Ctrl+J'
28
+ TITLE = _("Suggestions")
29
+ ICON = ":/resources/lightbulb.svg"
30
+ ROLE = "suggestions"
31
+ SHORTCUT = "Ctrl+J"
33
32
 
34
- WORD_RX = re.compile(r'(?:\w+|[^\w\s]+)\s*')
33
+ WORD_RX = re.compile(r"(?:\w+|[^\w\s]+)\s*")
35
34
 
36
35
  STYLE_TRANSLATION, STYLE_STROKES = range(2)
37
36
 
@@ -46,20 +45,25 @@ class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
46
45
  self.setupUi(self)
47
46
  self._last_suggestions = None
48
47
  # Toolbar.
49
- self.layout().addWidget(ToolBar(
50
- self.action_ToggleOnTop,
48
+ actions = [
51
49
  self.action_SelectFont,
52
50
  self.action_Clear,
53
- ))
51
+ ]
52
+ if not utils.is_wayland():
53
+ # Wayland does not support window on top.
54
+ actions.insert(0, self.action_ToggleOnTop)
55
+
56
+ self.layout().addWidget(ToolBar(*actions))
57
+
54
58
  self.action_Clear.setEnabled(False)
55
59
  # Font popup menu.
56
60
  self._font_menu = QMenu()
57
61
  # i18n: Widget: “SuggestionsDialog”, “font” menu.
58
- self._font_menu_text = QAction(_('&Text'), self._font_menu)
62
+ self._font_menu_text = QAction(_("&Text"), self._font_menu)
59
63
  # i18n: Widget: “SuggestionsDialog”, “font” menu.
60
- self._font_menu_strokes = QAction(_('&Strokes'), self._font_menu)
64
+ self._font_menu_strokes = QAction(_("&Strokes"), self._font_menu)
61
65
  self._font_menu.addActions([self._font_menu_text, self._font_menu_strokes])
62
- engine.signal_connect('translated', self.on_translation)
66
+ engine.signal_connect("translated", self.on_translation)
63
67
  self.suggestions.setFocus()
64
68
  self.restore_state()
65
69
  self.finished.connect(self.save_state)
@@ -72,8 +76,8 @@ class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
72
76
 
73
77
  def _restore_state(self, settings):
74
78
  for name in (
75
- 'text_font',
76
- 'strokes_font',
79
+ "text_font",
80
+ "strokes_font",
77
81
  ):
78
82
  font_string = settings.value(name)
79
83
  if font_string is None:
@@ -82,21 +86,21 @@ class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
82
86
  if not font.fromString(font_string):
83
87
  continue
84
88
  self._set_font(name, font)
85
- ontop = settings.value('ontop', None, bool)
89
+ ontop = settings.value("ontop", None, bool)
86
90
  if ontop is not None:
87
91
  self.action_ToggleOnTop.setChecked(ontop)
88
92
  self.toggle_ontop(ontop)
89
93
 
90
94
  def _save_state(self, settings):
91
95
  for name in (
92
- 'text_font',
93
- 'strokes_font',
96
+ "text_font",
97
+ "strokes_font",
94
98
  ):
95
99
  font = self._get_font(name)
96
100
  font_string = font.toString()
97
101
  settings.setValue(name, font_string)
98
102
  ontop = bool(self.windowFlags() & Qt.WindowType.WindowStaysOnTopHint)
99
- settings.setValue('ontop', ontop)
103
+ settings.setValue("ontop", ontop)
100
104
 
101
105
  def _show_suggestions(self, suggestion_list):
102
106
  self.suggestions.append(suggestion_list)
@@ -104,19 +108,18 @@ class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
104
108
 
105
109
  @staticmethod
106
110
  def tails(ls):
107
- ''' Return all tail combinations (a la Haskell)
111
+ """Return all tail combinations (a la Haskell)
108
112
 
109
- tails :: [x] -> [[x]]
110
- >>> tails('abcd')
111
- ['abcd', 'bcd', 'cd', d']
113
+ tails :: [x] -> [[x]]
114
+ >>> tails('abcd')
115
+ ['abcd', 'bcd', 'cd', d']
112
116
 
113
- '''
117
+ """
114
118
 
115
119
  for i in range(len(ls)):
116
120
  yield ls[i:]
117
121
 
118
122
  def on_translation(self, old, new):
119
-
120
123
  # Check for new output.
121
124
  for a in reversed(new):
122
125
  if a.text and not a.text.isspace():
@@ -132,7 +135,7 @@ class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
132
135
 
133
136
  suggestion_list = []
134
137
  for phrase in self.tails(split_words):
135
- phrase = ''.join(phrase)
138
+ phrase = "".join(phrase)
136
139
  suggestion_list.extend(self._engine.get_suggestions(phrase))
137
140
 
138
141
  if not suggestion_list and split_words:
@@ -148,24 +151,17 @@ class SuggestionsDialog(Tool, Ui_SuggestionsDialog):
148
151
  if action is None:
149
152
  return
150
153
  if action == self._font_menu_text:
151
- name = 'text_font'
152
- font_options = ()
154
+ name = "text_font"
153
155
  elif action == self._font_menu_strokes:
154
- name = 'strokes_font'
155
- font_options = (QFontDialog.FontDialogOption.MonospacedFonts,)
156
+ name = "strokes_font"
156
157
  font = self._get_font(name)
157
- ok, font = QFontDialog.getFont(font, self, '', *font_options)
158
+ ok, font = QFontDialog.getFont(font, self, "")
158
159
  if ok:
159
160
  self._set_font(name, font)
160
161
 
161
162
  @Slot(bool)
162
163
  def toggle_ontop(self, ontop):
163
- flags = self.windowFlags()
164
- if ontop:
165
- flags |= Qt.WindowType.WindowStaysOnTopHint
166
- else:
167
- flags &= ~Qt.WindowType.WindowStaysOnTopHint
168
- self.setWindowFlags(flags)
164
+ self.setWindowFlag(Qt.WindowStaysOnTopHint, ontop)
169
165
  self.show()
170
166
 
171
167
  @Slot()
@@ -24,12 +24,11 @@ from .utils import ActionCopyViewSelectionToClipboard
24
24
 
25
25
 
26
26
  # i18n: Widget: “SuggestionsWidget”.
27
- NO_SUGGESTIONS_STRING = _('no suggestions')
27
+ NO_SUGGESTIONS_STRING = _("no suggestions")
28
28
  MAX_SUGGESTIONS_COUNT = 10
29
29
 
30
30
 
31
31
  class SuggestionsDelegate(QStyledItemDelegate):
32
-
33
32
  def __init__(self, parent=None):
34
33
  super().__init__(parent=parent)
35
34
  self._doc = QTextDocument()
@@ -61,13 +60,13 @@ class SuggestionsDelegate(QStyledItemDelegate):
61
60
 
62
61
  def _format_suggestion(self, index):
63
62
  suggestion = index.data(Qt.ItemDataRole.DisplayRole)
64
- translation = escape_translation(suggestion.text) + ':'
63
+ translation = escape_translation(suggestion.text) + ":"
65
64
  if not suggestion.steno_list:
66
- translation += ' ' + NO_SUGGESTIONS_STRING
65
+ translation += " " + NO_SUGGESTIONS_STRING
67
66
  return translation, None
68
- strokes = ''
67
+ strokes = ""
69
68
  for strokes_list in suggestion.steno_list[:MAX_SUGGESTIONS_COUNT]:
70
- strokes += '\n ' + '/'.join(strokes_list)
69
+ strokes += "\n " + "/".join(strokes_list)
71
70
  return translation, strokes
72
71
 
73
72
  def _suggestion_size_hint(self, index):
@@ -106,7 +105,6 @@ class SuggestionsDelegate(QStyledItemDelegate):
106
105
 
107
106
 
108
107
  class SuggestionsModel(QAbstractListModel):
109
-
110
108
  def __init__(self):
111
109
  super().__init__()
112
110
  self._suggestion_list = []
@@ -123,11 +121,13 @@ class SuggestionsModel(QAbstractListModel):
123
121
  if role == Qt.ItemDataRole.AccessibleTextRole:
124
122
  translation = escape_translation(suggestion.text)
125
123
  if suggestion.steno_list:
126
- steno = ', '.join('/'.join(strokes_list) for strokes_list in
127
- suggestion.steno_list[:MAX_SUGGESTIONS_COUNT])
124
+ steno = ", ".join(
125
+ "/".join(strokes_list)
126
+ for strokes_list in suggestion.steno_list[:MAX_SUGGESTIONS_COUNT]
127
+ )
128
128
  else:
129
129
  steno = NO_SUGGESTIONS_STRING
130
- return translation + ': ' + steno
130
+ return translation + ": " + steno
131
131
  return None
132
132
 
133
133
  def clear(self):
@@ -142,19 +142,25 @@ class SuggestionsModel(QAbstractListModel):
142
142
  self.endInsertRows()
143
143
 
144
144
  def mimeTypes(self):
145
- return ['text/plain']
145
+ return ["text/plain"]
146
146
 
147
147
  def mimeData(self, indexes):
148
148
  data = QMimeData()
149
- data.setText('\n'.join(filter(None, (
150
- self.data(index, Qt.ItemDataRole.AccessibleTextRole)
151
- for index in indexes
152
- ))))
149
+ data.setText(
150
+ "\n".join(
151
+ filter(
152
+ None,
153
+ (
154
+ self.data(index, Qt.ItemDataRole.AccessibleTextRole)
155
+ for index in indexes
156
+ ),
157
+ )
158
+ )
159
+ )
153
160
  return data
154
161
 
155
162
 
156
163
  class SuggestionsWidget(QListView):
157
-
158
164
  def __init__(self, parent=None):
159
165
  super().__init__(parent=parent)
160
166
  self.setResizeMode(self.ResizeMode.Adjust)
plover/gui_qt/tool.py CHANGED
@@ -1,11 +1,9 @@
1
-
2
1
  from PySide6.QtWidgets import QDialog
3
2
 
4
3
  from plover.gui_qt.utils import WindowStateMixin
5
4
 
6
5
 
7
6
  class Tool(QDialog, WindowStateMixin):
8
-
9
7
  # Used for dialog window title, menu entry text.
10
8
  TITLE = None
11
9
  # Optional path to icon image.
@@ -20,7 +18,7 @@ class Tool(QDialog, WindowStateMixin):
20
18
  self._engine = engine
21
19
 
22
20
  def _update_title(self):
23
- self.setWindowTitle('Plover: ' + self.TITLE)
21
+ self.setWindowTitle("Plover: " + self.TITLE)
24
22
 
25
23
  def setupUi(self, widget):
26
24
  super().setupUi(widget)