PrEditor 1.2.0__tar.gz → 1.3.0__tar.gz

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.

Potentially problematic release.


This version of PrEditor might be problematic. Click here for more details.

Files changed (190) hide show
  1. {preditor-1.2.0 → preditor-1.3.0}/PKG-INFO +1 -1
  2. {preditor-1.2.0 → preditor-1.3.0}/PrEditor.egg-info/PKG-INFO +1 -1
  3. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/console.py +17 -0
  4. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/group_tab_widget/__init__.py +28 -0
  5. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/loggerwindow.py +16 -7
  6. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/ui/loggerwindow.ui +11 -1
  7. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/workbox_mixin.py +3 -3
  8. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/workbox_text_edit.py +2 -2
  9. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/workboxwidget.py +9 -4
  10. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/documenteditor.py +64 -20
  11. {preditor-1.2.0 → preditor-1.3.0}/preditor/version.py +3 -3
  12. {preditor-1.2.0 → preditor-1.3.0}/.coveragerc +0 -0
  13. {preditor-1.2.0 → preditor-1.3.0}/.github/ISSUE_TEMPLATE/BUG_REPORT.md +0 -0
  14. {preditor-1.2.0 → preditor-1.3.0}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
  15. {preditor-1.2.0 → preditor-1.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  16. {preditor-1.2.0 → preditor-1.3.0}/.github/workflows/release.yml +0 -0
  17. {preditor-1.2.0 → preditor-1.3.0}/.github/workflows/static-analysis-and-test.yml +0 -0
  18. {preditor-1.2.0 → preditor-1.3.0}/.gitignore +0 -0
  19. {preditor-1.2.0 → preditor-1.3.0}/.pre-commit-config.yaml +0 -0
  20. {preditor-1.2.0 → preditor-1.3.0}/CODE_OF_CONDUCT.md +0 -0
  21. {preditor-1.2.0 → preditor-1.3.0}/CONTRIBUTING.md +0 -0
  22. {preditor-1.2.0 → preditor-1.3.0}/LICENSE +0 -0
  23. {preditor-1.2.0 → preditor-1.3.0}/MANIFEST.in +0 -0
  24. {preditor-1.2.0 → preditor-1.3.0}/PrEditor.egg-info/SOURCES.txt +0 -0
  25. {preditor-1.2.0 → preditor-1.3.0}/PrEditor.egg-info/dependency_links.txt +0 -0
  26. {preditor-1.2.0 → preditor-1.3.0}/PrEditor.egg-info/entry_points.txt +0 -0
  27. {preditor-1.2.0 → preditor-1.3.0}/PrEditor.egg-info/requires.txt +0 -0
  28. {preditor-1.2.0 → preditor-1.3.0}/PrEditor.egg-info/top_level.txt +0 -0
  29. {preditor-1.2.0 → preditor-1.3.0}/README.md +0 -0
  30. {preditor-1.2.0 → preditor-1.3.0}/examples/add_to_app.py +0 -0
  31. {preditor-1.2.0 → preditor-1.3.0}/examples/output_capture_and_show.py +0 -0
  32. {preditor-1.2.0 → preditor-1.3.0}/preditor/__init__.py +0 -0
  33. {preditor-1.2.0 → preditor-1.3.0}/preditor/__main__.py +0 -0
  34. {preditor-1.2.0 → preditor-1.3.0}/preditor/about_module.py +0 -0
  35. {preditor-1.2.0 → preditor-1.3.0}/preditor/cli.py +0 -0
  36. {preditor-1.2.0 → preditor-1.3.0}/preditor/config.py +0 -0
  37. {preditor-1.2.0 → preditor-1.3.0}/preditor/contexts.py +0 -0
  38. {preditor-1.2.0 → preditor-1.3.0}/preditor/cores/__init__.py +0 -0
  39. {preditor-1.2.0 → preditor-1.3.0}/preditor/cores/core.py +0 -0
  40. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/.hab.json +0 -0
  41. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/maya/PrEditor_maya.mod +0 -0
  42. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/maya/README.md +0 -0
  43. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/maya/plug-ins/PrEditor_maya.py +0 -0
  44. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/studiomax/PackageContents.xml +0 -0
  45. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +0 -0
  46. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/studiomax/README.md +0 -0
  47. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/studiomax/preditor.ms +0 -0
  48. {preditor-1.2.0 → preditor-1.3.0}/preditor/dccs/studiomax/preditor_menu.mnx +0 -0
  49. {preditor-1.2.0 → preditor-1.3.0}/preditor/debug.py +0 -0
  50. {preditor-1.2.0 → preditor-1.3.0}/preditor/delayable_engine/__init__.py +0 -0
  51. {preditor-1.2.0 → preditor-1.3.0}/preditor/delayable_engine/delayables.py +0 -0
  52. {preditor-1.2.0 → preditor-1.3.0}/preditor/enum.py +0 -0
  53. {preditor-1.2.0 → preditor-1.3.0}/preditor/excepthooks.py +0 -0
  54. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/__init__.py +0 -0
  55. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/app.py +0 -0
  56. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/codehighlighter.py +0 -0
  57. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/completer.py +0 -0
  58. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/dialog.py +0 -0
  59. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/drag_tab_bar.py +0 -0
  60. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/editor_chooser.py +0 -0
  61. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/errordialog.py +0 -0
  62. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/find_files.py +0 -0
  63. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/fuzzy_search/__init__.py +0 -0
  64. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/fuzzy_search/fuzzy_search.py +0 -0
  65. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/group_tab_widget/grouped_tab_menu.py +0 -0
  66. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/group_tab_widget/grouped_tab_models.py +0 -0
  67. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/group_tab_widget/grouped_tab_widget.py +0 -0
  68. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/group_tab_widget/one_tab_widget.py +0 -0
  69. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/level_buttons.py +0 -0
  70. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/logger_window_handler.py +0 -0
  71. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/logger_window_plugin.py +0 -0
  72. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/newtabwidget.py +0 -0
  73. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/set_text_editor_path_dialog.py +0 -0
  74. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/status_label.py +0 -0
  75. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/suggest_path_quotes_dialog.py +0 -0
  76. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/ui/editor_chooser.ui +0 -0
  77. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/ui/errordialog.ui +0 -0
  78. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/ui/find_files.ui +0 -0
  79. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/ui/set_text_editor_path_dialog.ui +0 -0
  80. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/ui/suggest_path_quotes_dialog.ui +0 -0
  81. {preditor-1.2.0 → preditor-1.3.0}/preditor/gui/window.py +0 -0
  82. {preditor-1.2.0 → preditor-1.3.0}/preditor/logging_config.py +0 -0
  83. {preditor-1.2.0 → preditor-1.3.0}/preditor/osystem.py +0 -0
  84. {preditor-1.2.0 → preditor-1.3.0}/preditor/plugins.py +0 -0
  85. {preditor-1.2.0 → preditor-1.3.0}/preditor/prefs.py +0 -0
  86. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/environment_variables.html +0 -0
  87. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/error_mail.html +0 -0
  88. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/error_mail_inline.html +0 -0
  89. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/README.md +0 -0
  90. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/arrow_forward.png +0 -0
  91. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/check-bold.png +0 -0
  92. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/chevron-down.png +0 -0
  93. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/chevron-up.png +0 -0
  94. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/close-thick.png +0 -0
  95. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/comment-edit.png +0 -0
  96. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/content-copy.png +0 -0
  97. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/content-cut.png +0 -0
  98. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/content-duplicate.png +0 -0
  99. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/content-paste.png +0 -0
  100. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/content-save.png +0 -0
  101. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/debug_disabled.png +0 -0
  102. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/eye-check.png +0 -0
  103. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/file-plus.png +0 -0
  104. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/file-remove.png +0 -0
  105. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/format-align-left.png +0 -0
  106. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/format-letter-case-lower.png +0 -0
  107. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/format-letter-case-upper.png +0 -0
  108. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/format-letter-case.svg +0 -0
  109. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/information.png +0 -0
  110. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_critical.png +0 -0
  111. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_custom.png +0 -0
  112. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_debug.png +0 -0
  113. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_error.png +0 -0
  114. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_info.png +0 -0
  115. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_not_set.png +0 -0
  116. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/logging_warning.png +0 -0
  117. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/marker.png +0 -0
  118. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/play.png +0 -0
  119. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/playlist-play.png +0 -0
  120. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/plus-minus-variant.png +0 -0
  121. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/preditor.ico +0 -0
  122. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/preditor.png +0 -0
  123. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/preditor.psd +0 -0
  124. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/preditor.svg +0 -0
  125. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/regex.svg +0 -0
  126. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/restart.svg +0 -0
  127. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/skip-forward-outline.png +0 -0
  128. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/skip-next-outline.png +0 -0
  129. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/skip-next.png +0 -0
  130. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/skip-previous.png +0 -0
  131. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/subdirectory-arrow-right.png +0 -0
  132. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/text-search-variant.png +0 -0
  133. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/img/warning-big.png +0 -0
  134. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/lang/python.json +0 -0
  135. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/settings.ini +0 -0
  136. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/stylesheet/Bright.css +0 -0
  137. {preditor-1.2.0 → preditor-1.3.0}/preditor/resource/stylesheet/Dark.css +0 -0
  138. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/__init__.py +0 -0
  139. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/delayables/__init__.py +0 -0
  140. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/delayables/smart_highlight.py +0 -0
  141. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/delayables/spell_check.py +0 -0
  142. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/finddialog.py +0 -0
  143. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/__init__.py +0 -0
  144. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/bash.ini +0 -0
  145. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/batch.ini +0 -0
  146. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/cpp.ini +0 -0
  147. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/css.ini +0 -0
  148. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/eyeonscript.ini +0 -0
  149. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/html.ini +0 -0
  150. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/javascript.ini +0 -0
  151. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/lua.ini +0 -0
  152. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/maxscript.ini +0 -0
  153. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/mel.ini +0 -0
  154. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/mu.ini +0 -0
  155. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/nsi.ini +0 -0
  156. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/perl.ini +0 -0
  157. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/puppet.ini +0 -0
  158. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/python.ini +0 -0
  159. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/ruby.ini +0 -0
  160. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/sql.ini +0 -0
  161. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/xml.ini +0 -0
  162. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/config/yaml.ini +0 -0
  163. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lang/language.py +0 -0
  164. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/__init__.py +0 -0
  165. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/cpplexer.py +0 -0
  166. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/javascriptlexer.py +0 -0
  167. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/maxscriptlexer.py +0 -0
  168. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/mellexer.py +0 -0
  169. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/mulexer.py +0 -0
  170. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/lexers/pythonlexer.py +0 -0
  171. {preditor-1.2.0 → preditor-1.3.0}/preditor/scintilla/ui/finddialog.ui +0 -0
  172. {preditor-1.2.0 → preditor-1.3.0}/preditor/settings.py +0 -0
  173. {preditor-1.2.0 → preditor-1.3.0}/preditor/stream/__init__.py +0 -0
  174. {preditor-1.2.0 → preditor-1.3.0}/preditor/stream/director.py +0 -0
  175. {preditor-1.2.0 → preditor-1.3.0}/preditor/stream/manager.py +0 -0
  176. {preditor-1.2.0 → preditor-1.3.0}/preditor/streamhandler_helper.py +0 -0
  177. {preditor-1.2.0 → preditor-1.3.0}/preditor/utils/__init__.py +0 -0
  178. {preditor-1.2.0 → preditor-1.3.0}/preditor/utils/cute.py +0 -0
  179. {preditor-1.2.0 → preditor-1.3.0}/preditor/utils/stylesheets.py +0 -0
  180. {preditor-1.2.0 → preditor-1.3.0}/preditor/utils/text_search.py +0 -0
  181. {preditor-1.2.0 → preditor-1.3.0}/preditor/weakref.py +0 -0
  182. {preditor-1.2.0 → preditor-1.3.0}/pyproject.toml +0 -0
  183. {preditor-1.2.0 → preditor-1.3.0}/requirements-cli.txt +0 -0
  184. {preditor-1.2.0 → preditor-1.3.0}/requirements-dev.txt +0 -0
  185. {preditor-1.2.0 → preditor-1.3.0}/requirements-qsci5.txt +0 -0
  186. {preditor-1.2.0 → preditor-1.3.0}/requirements-qsci6.txt +0 -0
  187. {preditor-1.2.0 → preditor-1.3.0}/requirements-shortcut.txt +0 -0
  188. {preditor-1.2.0 → preditor-1.3.0}/requirements.txt +0 -0
  189. {preditor-1.2.0 → preditor-1.3.0}/setup.cfg +0 -0
  190. {preditor-1.2.0 → preditor-1.3.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PrEditor
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: A python REPL and Editor and console based on Qt.
5
5
  Author-email: Blur Studio <opensource@blur.com>
6
6
  License: LGPL-3.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PrEditor
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: A python REPL and Editor and console based on Qt.
5
5
  Author-email: Blur Studio <opensource@blur.com>
6
6
  License: LGPL-3.0
@@ -63,6 +63,8 @@ class ConsolePrEdit(QTextEdit):
63
63
 
64
64
  self._firstShow = True
65
65
 
66
+ self.addSepNewline = False
67
+
66
68
  # When executing code, that takes longer than this seconds, flash the window
67
69
  self.flash_time = 1.0
68
70
  self.flash_window = None
@@ -817,6 +819,10 @@ class ConsolePrEdit(QTextEdit):
817
819
  hasattr(window, 'uiErrorHyperlinksACT')
818
820
  and window.uiErrorHyperlinksACT.isChecked()
819
821
  )
822
+ sepPreditorTrace = (
823
+ hasattr(window, 'uiSeparateTracebackACT')
824
+ and window.uiSeparateTracebackACT.isChecked()
825
+ )
820
826
  self.moveCursor(QTextCursor.MoveOperation.End)
821
827
 
822
828
  charFormat = QTextCharFormat()
@@ -855,6 +861,17 @@ class ConsolePrEdit(QTextEdit):
855
861
  filename = info.get("filename", "") if info else ""
856
862
  isConsolePrEdit = '<ConsolePrEdit>' in filename
857
863
 
864
+ # To make it easier to see relevant lines of a traceback, optionally insert
865
+ # a newline separating internal PrEditor code from the code run by user.
866
+ if self.addSepNewline:
867
+ if sepPreditorTrace:
868
+ msg += "\n"
869
+ self.addSepNewline = False
870
+
871
+ preditorCalls = ("cmdresult = e", "exec(compiled,")
872
+ if msg.strip().startswith(preditorCalls):
873
+ self.addSepNewline = True
874
+
858
875
  if info and doHyperlink and not isConsolePrEdit:
859
876
  fileStart = info.get("fileStart")
860
877
  fileEnd = info.get("fileEnd")
@@ -323,3 +323,31 @@ class GroupTabWidget(OneTabWidget):
323
323
  tab_widget = self.currentWidget()
324
324
  tab_widget.setCurrentIndex(editor)
325
325
  return tab_widget.currentWidget()
326
+
327
+ def set_current_groups_from_workbox(self, workbox):
328
+ """Make the specified workbox the current widget. If the workbox is not
329
+ found, the current widget is not changed.
330
+
331
+ Args:
332
+ workbox (WorkboxMixin): The workbox to make current.
333
+
334
+ Returns:
335
+ success (bool): Whether the workbox was found and made the current
336
+ widget
337
+ """
338
+ workbox_infos = self.all_widgets()
339
+ found_info = None
340
+ for workbox_info in workbox_infos:
341
+ if workbox_info[0] == workbox:
342
+ found_info = workbox_info
343
+ break
344
+ if found_info:
345
+ workbox = workbox_info[0]
346
+ group_idx = workbox_info[-2]
347
+ editor_idx = workbox_info[-1]
348
+
349
+ self.setCurrentIndex(group_idx)
350
+ tab_widget = self.currentWidget()
351
+ tab_widget.setCurrentIndex(editor_idx)
352
+
353
+ return bool(found_info)
@@ -93,9 +93,7 @@ class LoggerWindow(Window):
93
93
  self.name = name if name else get_core_name()
94
94
  self._stylesheet = 'Bright'
95
95
 
96
- # Create timer to autohide status messages
97
- self.statusTimer = QTimer()
98
- self.statusTimer.setSingleShot(True)
96
+ self.setupStatusTimer()
99
97
 
100
98
  # Store the previous time a font-resize wheel event was triggered to prevent
101
99
  # rapid-fire WheelEvents. Initialize to the current time.
@@ -815,6 +813,7 @@ class LoggerWindow(Window):
815
813
  'uiStatusLbl_limit': self.uiStatusLBL.limit(),
816
814
  'textEditorPath': self.textEditorPath,
817
815
  'textEditorCmdTempl': self.textEditorCmdTempl,
816
+ 'uiSeparateTracebackACT': self.uiSeparateTracebackACT.isChecked(),
818
817
  'currentStyleSheet': self._stylesheet,
819
818
  'flash_time': self.uiConsoleTXT.flash_time,
820
819
  'find_files_regex': self.uiFindInWorkboxesWGT.uiRegexBTN.isChecked(),
@@ -967,6 +966,8 @@ class LoggerWindow(Window):
967
966
  self.textEditorPath = pref.get('textEditorPath', defaultExePath)
968
967
  self.textEditorCmdTempl = pref.get('textEditorCmdTempl', defaultCmd)
969
968
 
969
+ self.uiSeparateTracebackACT.setChecked(pref.get('uiSeparateTracebackACT', True))
970
+
970
971
  self.uiWordWrapACT.setChecked(pref.get('wordWrap', True))
971
972
  self.setWordWrap(self.uiWordWrapACT.isChecked())
972
973
  self.uiClearBeforeRunningACT.setChecked(pref.get('clearBeforeRunning', False))
@@ -1041,16 +1042,24 @@ class LoggerWindow(Window):
1041
1042
  self.uiStatusLBL.setText(txt)
1042
1043
  self.uiMenuBar.adjustSize()
1043
1044
 
1045
+ def setupStatusTimer(self):
1046
+ # Create timer to autohide status messages
1047
+ self.statusTimer = QTimer()
1048
+ self.statusTimer.setSingleShot(True)
1049
+ self.statusTimer.setInterval(2000)
1050
+ self.statusTimer.timeout.connect(self.clearStatusText)
1051
+
1044
1052
  def clearStatusText(self):
1045
1053
  """Clear any displayed status text"""
1046
1054
  self.uiStatusLBL.clear()
1047
1055
  self.uiMenuBar.adjustSize()
1048
1056
 
1049
1057
  def autoHideStatusText(self):
1050
- """Set timer to automatically clear status text"""
1051
- if self.statusTimer.isActive():
1052
- self.statusTimer.stop()
1053
- self.statusTimer.singleShot(2000, self.clearStatusText)
1058
+ """Set timer to automatically clear status text.
1059
+
1060
+ If timer is already running, it will be automatically stopped first (We can't
1061
+ use static method QTimer.singleShot for this)
1062
+ """
1054
1063
  self.statusTimer.start()
1055
1064
 
1056
1065
  def setStyleSheet(self, stylesheet, recordPrefs=True):
@@ -92,7 +92,7 @@
92
92
  <x>0</x>
93
93
  <y>0</y>
94
94
  <width>796</width>
95
- <height>21</height>
95
+ <height>22</height>
96
96
  </rect>
97
97
  </property>
98
98
  <widget class="QMenu" name="uiDebugMENU">
@@ -193,6 +193,8 @@
193
193
  <addaction name="uiSetFlashWindowIntervalACT"/>
194
194
  <addaction name="separator"/>
195
195
  <addaction name="uiErrorHyperlinksACT"/>
196
+ <addaction name="uiSeparateTracebackACT"/>
197
+ <addaction name="separator"/>
196
198
  <addaction name="uiSetPreferredTextEditorPathACT"/>
197
199
  <addaction name="uiSetWorkboxEditorACT"/>
198
200
  </widget>
@@ -1003,6 +1005,14 @@ at the indicated line in the specified text editor.
1003
1005
  <string>Highlight Exact Completion</string>
1004
1006
  </property>
1005
1007
  </action>
1008
+ <action name="uiSeparateTracebackACT">
1009
+ <property name="checkable">
1010
+ <bool>true</bool>
1011
+ </property>
1012
+ <property name="text">
1013
+ <string>Visually Separate PrEditor Traceback</string>
1014
+ </property>
1015
+ </action>
1006
1016
  </widget>
1007
1017
  <customwidgets>
1008
1018
  <customwidget>
@@ -84,8 +84,8 @@ class WorkboxMixin(object):
84
84
  txt = '\n' * line + txt
85
85
 
86
86
  # execute the code
87
- filename = self.__workbox_filename__(selection=True)
88
- ret, was_eval = self.__console__().executeString(txt, filename=filename)
87
+ title = self.__workbox_trace_title__(selection=True)
88
+ ret, was_eval = self.__console__().executeString(txt, filename=title)
89
89
  if was_eval:
90
90
  # If the selected code was a statement print the result of the statement.
91
91
  ret = repr(ret)
@@ -145,7 +145,7 @@ class WorkboxMixin(object):
145
145
 
146
146
  return group, editor
147
147
 
148
- def __workbox_filename__(self, selection=False):
148
+ def __workbox_trace_title__(self, selection=False):
149
149
  title = "WorkboxSelection" if selection else "Workbox"
150
150
  group, editor = self.__group_tab_index__()
151
151
  if group == -1 or editor == -1:
@@ -57,8 +57,8 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
57
57
 
58
58
  def __exec_all__(self):
59
59
  txt = self.__text__().rstrip()
60
- filename = self.__workbox_filename__()
61
- self.__console__().executeString(txt, filename=filename)
60
+ title = self.__workbox_trace_title__()
61
+ self.__console__().executeString(txt, filename=title)
62
62
 
63
63
  def __font__(self):
64
64
  return self.font()
@@ -73,8 +73,8 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
73
73
 
74
74
  def __exec_all__(self):
75
75
  txt = self.__unix_end_lines__(self.text()).rstrip()
76
- filename = self.__workbox_filename__()
77
- self.__console__().executeString(txt, filename=filename)
76
+ title = self.__workbox_trace_title__()
77
+ self.__console__().executeString(txt, filename=title)
78
78
 
79
79
  def __file_monitoring_enabled__(self):
80
80
  return self._fileMonitoringActive
@@ -150,7 +150,12 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
150
150
 
151
151
  def __selected_text__(self, start_of_line=False, selectText=False):
152
152
  line, s, end, e = self.getSelection()
153
- if line == -1:
153
+
154
+ # Sometime self.getSelection returns values that equate to a non-existent
155
+ # selection, ie start and end are the same, so let's process it as if there is
156
+ # no selection
157
+ selectionIsEmpty = line == end and s == e
158
+ if line == -1 or selectionIsEmpty:
154
159
  # Nothing is selected, return the current line of text
155
160
  line, index = self.getCursorPosition()
156
161
  txt = self.text(line)
@@ -188,7 +193,7 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
188
193
  Returns:
189
194
  str: The requested text.
190
195
  """
191
- if line:
196
+ if line is not None:
192
197
  return self.text(line)
193
198
  elif (start is None) != (end is None):
194
199
  raise ValueError('You must pass start and end if you pass either.')
@@ -21,7 +21,7 @@ from functools import partial
21
21
 
22
22
  import Qt as Qt_py
23
23
  from Qt.QtCore import Property, QEvent, QPoint, Qt, Signal
24
- from Qt.QtGui import QColor, QFont, QFontMetrics, QIcon, QKeySequence
24
+ from Qt.QtGui import QColor, QFont, QFontMetrics, QIcon, QKeyEvent, QKeySequence
25
25
  from Qt.QtWidgets import (
26
26
  QAction,
27
27
  QApplication,
@@ -326,7 +326,8 @@ class DocumentEditor(QsciScintilla):
326
326
 
327
327
  with undo_step(self):
328
328
  # lookup the selected text positions
329
- cursorLine, cursorIndex = self.expandCursorToLineSelection()
329
+ origSelection = self.expandCursorToLineSelection()
330
+ origStartLine, origStartCol, origEndLine, origEndCol = origSelection
330
331
  startLine, startCol, endLine, endCol = self.getSelection()
331
332
 
332
333
  # Collect comments and indents, to determine indentation to use, and whether
@@ -351,11 +352,14 @@ class DocumentEditor(QsciScintilla):
351
352
 
352
353
  # If all lines are comments, we un-comment. If any aren't
353
354
  # comments, we comment.
355
+ sel_adjust = 0
354
356
  if doWhich is None:
355
357
  if all(comments):
356
358
  doWhich = "Uncomment"
359
+ sel_adjust = -1 * len(commentSpace)
357
360
  else:
358
361
  doWhich = "Comment"
362
+ sel_adjust = len(commentSpace)
359
363
 
360
364
  for line in range(startLine, endLine + 1):
361
365
  lineText = self.getSelectionCurrentLineText(line)
@@ -367,19 +371,12 @@ class DocumentEditor(QsciScintilla):
367
371
  if doWhich == "Comment":
368
372
  self.setCursorPosition(line, indent)
369
373
  self.insert(commentSpace)
370
- if cursorIndex is not None and cursorIndex >= indent:
371
- cursorIndex += len(commentSpace)
372
- if line == startLine:
373
- startCol -= len(commentSpace)
374
- if line == endLine:
375
- endCol += len(commentSpace)
376
-
377
374
  elif doWhich == "Uncomment":
378
375
  for curComment in [commentSpace, comment]:
379
376
  foundText = self.getSelectedCommentText(
380
377
  line, indent, len(curComment)
381
378
  )
382
- startCol, endCol, cursorIndex, removed = self.removeComment(
379
+ startCol, endCol, _, removed = self.removeComment(
383
380
  foundText,
384
381
  curComment,
385
382
  line,
@@ -388,16 +385,20 @@ class DocumentEditor(QsciScintilla):
388
385
  startCol,
389
386
  endLine,
390
387
  endCol,
391
- cursorIndex,
388
+ origEndCol,
392
389
  )
393
390
  if removed:
394
391
  break
395
392
 
393
+ # Adjust columns so selection moves in or out with comment. If startCol
394
+ # began at 0 keep it there.
395
+ adjustedStartCol = origStartCol + sel_adjust if origStartCol else 0
396
+ adjustedendCol = origEndCol + sel_adjust
397
+
396
398
  # restore the currently selected text, or cursor position
397
- if cursorLine is not None:
398
- startLine, endLine = cursorLine, cursorLine
399
- startCol, endCol = cursorIndex, cursorIndex
400
- self.setSelection(startLine, startCol, endLine, endCol)
399
+ self.setSelection(
400
+ origStartLine, adjustedStartCol, origEndLine, adjustedendCol
401
+ )
401
402
 
402
403
  def removeComment(
403
404
  self,
@@ -460,11 +461,26 @@ class DocumentEditor(QsciScintilla):
460
461
  return lineText
461
462
 
462
463
  def expandCursorToLineSelection(self):
463
- line, index = None, None
464
- if not self.hasSelectedText():
465
- line, index = self.getCursorPosition()
466
- self.setSelection(line, 0, line, self.lineLength(line))
467
- return line, index
464
+ start_line = None
465
+ start_idx = None
466
+ end_line = None
467
+ end_idx = None
468
+ lineLength = None
469
+
470
+ if self.hasSelectedText():
471
+ start_line, start_idx, end_line, end_idx = self.getSelection()
472
+ else:
473
+ start_line, start_idx = self.getCursorPosition()
474
+ end_line = start_line
475
+ end_idx = start_idx
476
+
477
+ if start_line is not None:
478
+ # Get lineLength this way instead of self.lineLength (QScintilla) because
479
+ # that gets confused by \r\n vs \n , so linked files will behave
480
+ # incorrectly.
481
+ lineLength = len(self.text(end_line).rstrip())
482
+ self.setSelection(start_line, 0, end_line, lineLength)
483
+ return start_line, start_idx, end_line, end_idx
468
484
 
469
485
  def copy(self):
470
486
  """Copies the selected text.
@@ -861,11 +877,39 @@ class DocumentEditor(QsciScintilla):
861
877
 
862
878
  def keyPressEvent(self, event):
863
879
  key = event.key()
880
+ modifiers = event.modifiers()
881
+
882
+ retPressed = key == Qt.Key.Key_Return
883
+ altPressed = modifiers == Qt.KeyboardModifier.AltModifier
884
+ altReturnPressed = altPressed and retPressed
885
+
864
886
  if key == Qt.Key.Key_Backtab:
865
887
  self.unindentSelection()
866
888
  elif key == Qt.Key.Key_Escape:
867
889
  # Using QShortcut for Escape did not seem to work.
868
890
  self.showAutoComplete(True)
891
+ elif altReturnPressed:
892
+ # If Alt Return pressed, create new unindented line
893
+
894
+ # Capture initial autoIndent state, then ensure it's disabled
895
+ autoIndent = self.autoIndent()
896
+ self.setAutoIndent(False)
897
+
898
+ # Create and send a new KeyEvent, just Return (Cannot just send original
899
+ # event, it doesn't register.
900
+ new_event = QKeyEvent(
901
+ event.type(),
902
+ Qt.Key.Key_Return,
903
+ Qt.KeyboardModifier(0),
904
+ "",
905
+ event.isAutoRepeat(),
906
+ event.count(),
907
+ )
908
+ QsciScintilla.keyPressEvent(self, new_event)
909
+
910
+ # Reset autoIndent property
911
+ self.setAutoIndent(autoIndent)
912
+
869
913
  else:
870
914
  return QsciScintilla.keyPressEvent(self, event)
871
915
 
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.2.0'
32
- __version_tuple__ = version_tuple = (1, 2, 0)
31
+ __version__ = version = '1.3.0'
32
+ __version_tuple__ = version_tuple = (1, 3, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g5a9de95c6'
34
+ __commit_id__ = commit_id = 'gaa3ec1d05'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes