PrEditor 0.0.0.dev1__py2.py3-none-any.whl → 0.1.0__py2.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.

Potentially problematic release.


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

Files changed (363) hide show
  1. PrEditor-0.1.0.dist-info/LICENSE +165 -0
  2. PrEditor-0.1.0.dist-info/METADATA +212 -0
  3. PrEditor-0.1.0.dist-info/RECORD +149 -0
  4. {PrEditor-0.0.0.dev1.dist-info → PrEditor-0.1.0.dist-info}/WHEEL +1 -1
  5. PrEditor-0.1.0.dist-info/entry_points.txt +18 -0
  6. PrEditor-0.1.0.dist-info/top_level.txt +1 -0
  7. preditor/__init__.py +301 -0
  8. {blurdev → preditor}/__main__.py +13 -13
  9. preditor/about_module.py +166 -0
  10. preditor/cli.py +192 -0
  11. {blurdev → preditor}/contexts.py +119 -119
  12. preditor/cores/core.py +65 -0
  13. preditor/dccs/maya/PrEditor_maya.mod +2 -0
  14. preditor/dccs/maya/plug-ins/PrEditor_maya.py +108 -0
  15. preditor/debug.py +294 -0
  16. blurdev/scintilla/delayable_engine.py → preditor/delayable_engine/__init__.py +310 -299
  17. blurdev/scintilla/delayables/base.py → preditor/delayable_engine/delayables.py +85 -85
  18. {blurdev → preditor}/enum.py +728 -1003
  19. {blurdev → preditor}/gui/__init__.py +84 -125
  20. preditor/gui/app.py +159 -0
  21. {blurdev → preditor}/gui/codehighlighter.py +209 -219
  22. {blurdev → preditor}/gui/completer.py +226 -236
  23. {blurdev → preditor}/gui/console.py +801 -858
  24. {blurdev → preditor}/gui/dialog.py +200 -216
  25. preditor/gui/drag_tab_bar.py +190 -0
  26. preditor/gui/editor_chooser.py +57 -0
  27. {blurdev → preditor}/gui/errordialog.py +100 -97
  28. preditor/gui/fuzzy_search/fuzzy_search.py +93 -0
  29. preditor/gui/group_tab_widget/__init__.py +319 -0
  30. preditor/gui/group_tab_widget/grouped_tab_menu.py +35 -0
  31. preditor/gui/group_tab_widget/grouped_tab_models.py +108 -0
  32. preditor/gui/group_tab_widget/grouped_tab_widget.py +75 -0
  33. preditor/gui/group_tab_widget/one_tab_widget.py +54 -0
  34. preditor/gui/level_buttons.py +349 -0
  35. {blurdev → preditor}/gui/logger_window_handler.py +46 -45
  36. {blurdev → preditor}/gui/loggerwindow.py +1205 -1417
  37. {blurdev → preditor}/gui/newtabwidget.py +69 -68
  38. {blurdev → preditor}/gui/redmine_login_dialog.py +63 -61
  39. {blurdev → preditor}/gui/set_text_editor_path_dialog.py +59 -57
  40. preditor/gui/ui/editor_chooser.ui +93 -0
  41. {blurdev → preditor}/gui/ui/errordialog.ui +81 -81
  42. {blurdev → preditor}/gui/ui/loggerwindow.ui +1030 -864
  43. {blurdev → preditor}/gui/ui/redmine_login_dialog.ui +124 -124
  44. {blurdev → preditor}/gui/ui/set_text_editor_path_dialog.ui +149 -149
  45. {blurdev → preditor}/gui/window.py +183 -199
  46. preditor/gui/workbox_mixin.py +357 -0
  47. preditor/gui/workbox_text_edit.py +117 -0
  48. preditor/gui/workboxwidget.py +276 -0
  49. preditor/logging_config.py +52 -0
  50. preditor/osystem.py +401 -0
  51. preditor/plugins.py +65 -0
  52. preditor/prefs.py +74 -0
  53. {blurdev → preditor}/resource/environment_variables.html +26 -38
  54. {blurdev → preditor}/resource/error_mail.html +85 -85
  55. {blurdev → preditor}/resource/error_mail_inline.html +41 -41
  56. preditor/resource/img/README.md +7 -0
  57. preditor/resource/img/arrow_forward.png +0 -0
  58. preditor/resource/img/check-bold.png +0 -0
  59. preditor/resource/img/chevron-down.png +0 -0
  60. preditor/resource/img/chevron-up.png +0 -0
  61. preditor/resource/img/close-thick.png +0 -0
  62. preditor/resource/img/comment-edit.png +0 -0
  63. preditor/resource/img/content-copy.png +0 -0
  64. preditor/resource/img/content-cut.png +0 -0
  65. preditor/resource/img/content-duplicate.png +0 -0
  66. preditor/resource/img/content-paste.png +0 -0
  67. preditor/resource/img/content-save.png +0 -0
  68. preditor/resource/img/debug_disabled.png +0 -0
  69. preditor/resource/img/eye-check.png +0 -0
  70. preditor/resource/img/file-plus.png +0 -0
  71. preditor/resource/img/file-remove.png +0 -0
  72. preditor/resource/img/format-align-left.png +0 -0
  73. preditor/resource/img/format-letter-case-lower.png +0 -0
  74. preditor/resource/img/format-letter-case-upper.png +0 -0
  75. preditor/resource/img/information.png +0 -0
  76. preditor/resource/img/logging_critical.png +0 -0
  77. preditor/resource/img/logging_custom.png +0 -0
  78. preditor/resource/img/logging_debug.png +0 -0
  79. preditor/resource/img/logging_error.png +0 -0
  80. preditor/resource/img/logging_info.png +0 -0
  81. preditor/resource/img/logging_not_set.png +0 -0
  82. preditor/resource/img/logging_warning.png +0 -0
  83. preditor/resource/img/marker.png +0 -0
  84. preditor/resource/img/play.png +0 -0
  85. preditor/resource/img/playlist-play.png +0 -0
  86. preditor/resource/img/plus-minus-variant.png +0 -0
  87. preditor/resource/img/preditor.ico +0 -0
  88. preditor/resource/img/preditor.png +0 -0
  89. preditor/resource/img/preditor.psd +0 -0
  90. preditor/resource/img/preditor.svg +44 -0
  91. preditor/resource/img/restart.svg +1 -0
  92. preditor/resource/img/skip-forward-outline.png +0 -0
  93. preditor/resource/img/skip-next-outline.png +0 -0
  94. preditor/resource/img/skip-next.png +0 -0
  95. preditor/resource/img/skip-previous.png +0 -0
  96. preditor/resource/img/subdirectory-arrow-right.png +0 -0
  97. preditor/resource/img/text-search-variant.png +0 -0
  98. {blurdev → preditor}/resource/lang/python.json +30 -30
  99. preditor/resource/settings.ini +25 -0
  100. {blurdev/resource/stylesheet/logger → preditor/resource/stylesheet}/Bright.css +56 -61
  101. {blurdev → preditor}/resource/stylesheet/Dark.css +190 -132
  102. {blurdev → preditor}/scintilla/__init__.py +22 -28
  103. preditor/scintilla/delayables/__init__.py +11 -0
  104. {blurdev → preditor}/scintilla/delayables/smart_highlight.py +94 -93
  105. {blurdev → preditor}/scintilla/delayables/spell_check.py +173 -172
  106. {blurdev → preditor}/scintilla/documenteditor.py +2039 -2115
  107. {blurdev → preditor}/scintilla/finddialog.py +68 -81
  108. {blurdev → preditor}/scintilla/lang/__init__.py +80 -93
  109. {blurdev → preditor}/scintilla/lang/config/bash.ini +15 -15
  110. {blurdev → preditor}/scintilla/lang/config/batch.ini +14 -14
  111. {blurdev → preditor}/scintilla/lang/config/cpp.ini +19 -19
  112. {blurdev → preditor}/scintilla/lang/config/css.ini +19 -19
  113. {blurdev → preditor}/scintilla/lang/config/eyeonscript.ini +17 -17
  114. {blurdev → preditor}/scintilla/lang/config/html.ini +21 -21
  115. {blurdev → preditor}/scintilla/lang/config/javascript.ini +24 -24
  116. {blurdev → preditor}/scintilla/lang/config/lua.ini +16 -16
  117. {blurdev → preditor}/scintilla/lang/config/maxscript.ini +20 -20
  118. {blurdev → preditor}/scintilla/lang/config/mel.ini +18 -18
  119. {blurdev → preditor}/scintilla/lang/config/mu.ini +22 -22
  120. {blurdev → preditor}/scintilla/lang/config/nsi.ini +5 -5
  121. {blurdev → preditor}/scintilla/lang/config/perl.ini +19 -19
  122. {blurdev → preditor}/scintilla/lang/config/puppet.ini +19 -19
  123. {blurdev → preditor}/scintilla/lang/config/python.ini +28 -28
  124. {blurdev → preditor}/scintilla/lang/config/ruby.ini +19 -19
  125. {blurdev → preditor}/scintilla/lang/config/sql.ini +7 -7
  126. {blurdev → preditor}/scintilla/lang/config/xml.ini +21 -21
  127. {blurdev → preditor}/scintilla/lang/config/yaml.ini +18 -18
  128. {blurdev → preditor}/scintilla/lang/language.py +240 -250
  129. preditor/scintilla/lexers/__init__.py +0 -0
  130. {blurdev → preditor}/scintilla/lexers/cpplexer.py +21 -30
  131. {blurdev → preditor}/scintilla/lexers/javascriptlexer.py +25 -34
  132. {blurdev → preditor}/scintilla/lexers/maxscriptlexer.py +234 -253
  133. {blurdev → preditor}/scintilla/lexers/mellexer.py +368 -376
  134. {blurdev → preditor}/scintilla/lexers/mulexer.py +32 -41
  135. {blurdev → preditor}/scintilla/lexers/pythonlexer.py +41 -50
  136. {blurdev → preditor}/scintilla/ui/finddialog.ui +160 -160
  137. preditor/settings.py +71 -0
  138. preditor/stream/__init__.py +80 -0
  139. preditor/stream/director.py +56 -0
  140. preditor/stream/manager.py +74 -0
  141. preditor/streamhandler_helper.py +46 -0
  142. preditor/utils/__init__.py +0 -0
  143. preditor/utils/cute.py +30 -0
  144. preditor/utils/stylesheets.py +54 -0
  145. {blurdev → preditor}/version.py +5 -5
  146. preditor/weakref.py +363 -0
  147. PrEditor-0.0.0.dev1.dist-info/METADATA +0 -51
  148. PrEditor-0.0.0.dev1.dist-info/RECORD +0 -279
  149. PrEditor-0.0.0.dev1.dist-info/top_level.txt +0 -1
  150. blurdev/__init__.py +0 -356
  151. blurdev/cores/__init__.py +0 -98
  152. blurdev/cores/application.py +0 -26
  153. blurdev/cores/core.py +0 -634
  154. blurdev/debug.py +0 -593
  155. blurdev/external.py +0 -391
  156. blurdev/gui/level_buttons.py +0 -585
  157. blurdev/gui/workboxwidget.py +0 -205
  158. blurdev/logger.py +0 -238
  159. blurdev/osystem.py +0 -813
  160. blurdev/prefs.py +0 -33
  161. blurdev/protocols/__init__.py +0 -71
  162. blurdev/protocols/write_std_output_handler.py +0 -83
  163. blurdev/resource/designer_plugins.xml +0 -9
  164. blurdev/resource/error_email_old.html +0 -41
  165. blurdev/resource/img/add.png +0 -0
  166. blurdev/resource/img/ajax-loader.gif +0 -0
  167. blurdev/resource/img/application.png +0 -0
  168. blurdev/resource/img/applications.png +0 -0
  169. blurdev/resource/img/assburner.png +0 -0
  170. blurdev/resource/img/assfreezer.png +0 -0
  171. blurdev/resource/img/bar.gif +0 -0
  172. blurdev/resource/img/blank.png +0 -0
  173. blurdev/resource/img/blurdev.png +0 -0
  174. blurdev/resource/img/calendar_disabled.png +0 -0
  175. blurdev/resource/img/calendar_enabled.png +0 -0
  176. blurdev/resource/img/cancel.png +0 -0
  177. blurdev/resource/img/custom.png +0 -0
  178. blurdev/resource/img/debug_high.png +0 -0
  179. blurdev/resource/img/debug_low.png +0 -0
  180. blurdev/resource/img/debug_mid.png +0 -0
  181. blurdev/resource/img/debug_off.png +0 -0
  182. blurdev/resource/img/django.png +0 -0
  183. blurdev/resource/img/doc.png +0 -0
  184. blurdev/resource/img/edit.png +0 -0
  185. blurdev/resource/img/elemental.png +0 -0
  186. blurdev/resource/img/explore.png +0 -0
  187. blurdev/resource/img/favorite.png +0 -0
  188. blurdev/resource/img/file.png +0 -0
  189. blurdev/resource/img/folder.png +0 -0
  190. blurdev/resource/img/ide/add.png +0 -0
  191. blurdev/resource/img/ide/add_note.png +0 -0
  192. blurdev/resource/img/ide/arrow_down.png +0 -0
  193. blurdev/resource/img/ide/arrow_up.png +0 -0
  194. blurdev/resource/img/ide/check.png +0 -0
  195. blurdev/resource/img/ide/class.png +0 -0
  196. blurdev/resource/img/ide/clean.png +0 -0
  197. blurdev/resource/img/ide/clearlog.png +0 -0
  198. blurdev/resource/img/ide/close.png +0 -0
  199. blurdev/resource/img/ide/comment_add.png +0 -0
  200. blurdev/resource/img/ide/comment_remove.png +0 -0
  201. blurdev/resource/img/ide/comment_toggle.png +0 -0
  202. blurdev/resource/img/ide/console.png +0 -0
  203. blurdev/resource/img/ide/copy.png +0 -0
  204. blurdev/resource/img/ide/copylstrip.png +0 -0
  205. blurdev/resource/img/ide/cut.png +0 -0
  206. blurdev/resource/img/ide/edit.png +0 -0
  207. blurdev/resource/img/ide/find.png +0 -0
  208. blurdev/resource/img/ide/find_replace.png +0 -0
  209. blurdev/resource/img/ide/findnext.png +0 -0
  210. blurdev/resource/img/ide/findprev.png +0 -0
  211. blurdev/resource/img/ide/folder_find.png +0 -0
  212. blurdev/resource/img/ide/function.png +0 -0
  213. blurdev/resource/img/ide/git-bash.png +0 -0
  214. blurdev/resource/img/ide/git-gui.png +0 -0
  215. blurdev/resource/img/ide/gitk.png +0 -0
  216. blurdev/resource/img/ide/goto.png +0 -0
  217. blurdev/resource/img/ide/goto_def.png +0 -0
  218. blurdev/resource/img/ide/help.png +0 -0
  219. blurdev/resource/img/ide/highlighter.png +0 -0
  220. blurdev/resource/img/ide/lowercase.png +0 -0
  221. blurdev/resource/img/ide/newfile.png +0 -0
  222. blurdev/resource/img/ide/newfolder.png +0 -0
  223. blurdev/resource/img/ide/newproject.png +0 -0
  224. blurdev/resource/img/ide/newwizard.png +0 -0
  225. blurdev/resource/img/ide/open.png +0 -0
  226. blurdev/resource/img/ide/paste.png +0 -0
  227. blurdev/resource/img/ide/pdb_continue.png +0 -0
  228. blurdev/resource/img/ide/pdb_down.png +0 -0
  229. blurdev/resource/img/ide/pdb_next.png +0 -0
  230. blurdev/resource/img/ide/pdb_step.png +0 -0
  231. blurdev/resource/img/ide/pdb_up.png +0 -0
  232. blurdev/resource/img/ide/plus_minus.png +0 -0
  233. blurdev/resource/img/ide/preferences.png +0 -0
  234. blurdev/resource/img/ide/project_find.png +0 -0
  235. blurdev/resource/img/ide/python.png +0 -0
  236. blurdev/resource/img/ide/pyular.png +0 -0
  237. blurdev/resource/img/ide/qt.png +0 -0
  238. blurdev/resource/img/ide/quit.png +0 -0
  239. blurdev/resource/img/ide/redo.png +0 -0
  240. blurdev/resource/img/ide/refresh.png +0 -0
  241. blurdev/resource/img/ide/remove.png +0 -0
  242. blurdev/resource/img/ide/ruler.png +0 -0
  243. blurdev/resource/img/ide/run.png +0 -0
  244. blurdev/resource/img/ide/runall.png +0 -0
  245. blurdev/resource/img/ide/runallclear.png +0 -0
  246. blurdev/resource/img/ide/runselected.png +0 -0
  247. blurdev/resource/img/ide/runselectedclear.png +0 -0
  248. blurdev/resource/img/ide/save.png +0 -0
  249. blurdev/resource/img/ide/saveas.png +0 -0
  250. blurdev/resource/img/ide/sdk.png +0 -0
  251. blurdev/resource/img/ide/separator.png +0 -0
  252. blurdev/resource/img/ide/tabbed.png +0 -0
  253. blurdev/resource/img/ide/tile.png +0 -0
  254. blurdev/resource/img/ide/toolbar.png +0 -0
  255. blurdev/resource/img/ide/undo.png +0 -0
  256. blurdev/resource/img/ide/uppercase.png +0 -0
  257. blurdev/resource/img/ide/view_as.png +0 -0
  258. blurdev/resource/img/ide/windowed.png +0 -0
  259. blurdev/resource/img/ide.ico +0 -0
  260. blurdev/resource/img/ide.png +0 -0
  261. blurdev/resource/img/ide48.png +0 -0
  262. blurdev/resource/img/info.png +0 -0
  263. blurdev/resource/img/legacy tool.png +0 -0
  264. blurdev/resource/img/library.png +0 -0
  265. blurdev/resource/img/logger/about.png +0 -0
  266. blurdev/resource/img/logger/arrow_forward.png +0 -0
  267. blurdev/resource/img/logger/clear.png +0 -0
  268. blurdev/resource/img/logger/close.png +0 -0
  269. blurdev/resource/img/logger/debug_disabled.png +0 -0
  270. blurdev/resource/img/logger/debug_high.png +0 -0
  271. blurdev/resource/img/logger/debug_low.png +0 -0
  272. blurdev/resource/img/logger/debug_mid.png +0 -0
  273. blurdev/resource/img/logger/down.png +0 -0
  274. blurdev/resource/img/logger/find.png +0 -0
  275. blurdev/resource/img/logger/logging_critical.png +0 -0
  276. blurdev/resource/img/logger/logging_debug.png +0 -0
  277. blurdev/resource/img/logger/logging_error.png +0 -0
  278. blurdev/resource/img/logger/logging_info.png +0 -0
  279. blurdev/resource/img/logger/logging_not_set.png +0 -0
  280. blurdev/resource/img/logger/logging_warning.png +0 -0
  281. blurdev/resource/img/logger/next.png +0 -0
  282. blurdev/resource/img/logger/play.png +0 -0
  283. blurdev/resource/img/logger/playlist_play.png +0 -0
  284. blurdev/resource/img/logger/previous.png +0 -0
  285. blurdev/resource/img/logger/return.png +0 -0
  286. blurdev/resource/img/logger/save.png +0 -0
  287. blurdev/resource/img/logger/subdirectory_arrow_right.png +0 -0
  288. blurdev/resource/img/logger/up.png +0 -0
  289. blurdev/resource/img/lovebar.png +0 -0
  290. blurdev/resource/img/new.png +0 -0
  291. blurdev/resource/img/new_selected.png +0 -0
  292. blurdev/resource/img/node.png +0 -0
  293. blurdev/resource/img/ok.png +0 -0
  294. blurdev/resource/img/options.png +0 -0
  295. blurdev/resource/img/packages.png +0 -0
  296. blurdev/resource/img/preview/add.png +0 -0
  297. blurdev/resource/img/preview/brush.png +0 -0
  298. blurdev/resource/img/preview/delete.png +0 -0
  299. blurdev/resource/img/preview/delte.png +0 -0
  300. blurdev/resource/img/preview/fill.png +0 -0
  301. blurdev/resource/img/preview/layers.png +0 -0
  302. blurdev/resource/img/preview/media.png +0 -0
  303. blurdev/resource/img/preview/navigate.png +0 -0
  304. blurdev/resource/img/preview/pencil.png +0 -0
  305. blurdev/resource/img/preview/select.png +0 -0
  306. blurdev/resource/img/preview/type.png +0 -0
  307. blurdev/resource/img/preview/visible.png +0 -0
  308. blurdev/resource/img/project.png +0 -0
  309. blurdev/resource/img/python_logger.ico +0 -0
  310. blurdev/resource/img/python_logger.png +0 -0
  311. blurdev/resource/img/refresh.png +0 -0
  312. blurdev/resource/img/remove.png +0 -0
  313. blurdev/resource/img/reset.png +0 -0
  314. blurdev/resource/img/richtext/font_bold.png +0 -0
  315. blurdev/resource/img/richtext/font_italic.png +0 -0
  316. blurdev/resource/img/richtext/link_image.png +0 -0
  317. blurdev/resource/img/richtext/spell_check.png +0 -0
  318. blurdev/resource/img/richtext/unordered_list.png +0 -0
  319. blurdev/resource/img/save.png +0 -0
  320. blurdev/resource/img/savesettings.png +0 -0
  321. blurdev/resource/img/settings.png +0 -0
  322. blurdev/resource/img/tool.png +0 -0
  323. blurdev/resource/img/toolbarHandleHorizontal.png +0 -0
  324. blurdev/resource/img/toolbarHandleVertical.png +0 -0
  325. blurdev/resource/img/trash.png +0 -0
  326. blurdev/resource/img/trax.png +0 -0
  327. blurdev/resource/img/tree.png +0 -0
  328. blurdev/resource/img/treegrunt.ico +0 -0
  329. blurdev/resource/img/treegrunt.png +0 -0
  330. blurdev/resource/img/treegruntedit.png +0 -0
  331. blurdev/resource/img/user interface.png +0 -0
  332. blurdev/resource/img/warning.png +0 -0
  333. blurdev/resource/img/watermark.png +0 -0
  334. blurdev/resource/sdk/blurdev.sdk +0 -3
  335. blurdev/resource/settings.ini +0 -82
  336. blurdev/resource/softimage/BlurApplication.dll +0 -0
  337. blurdev/resource/softimage/BlurApplication64.dll +0 -0
  338. blurdev/resource/stylesheet/Carbon.css +0 -35
  339. blurdev/resource/stylesheet/logger/Dark.css +0 -62
  340. blurdev/resource/templ/py_comment.templ +0 -1
  341. blurdev/resource/templ/py_debug_raise_error.templ +0 -7
  342. blurdev/resource/templ/py_doc_string.templ +0 -10
  343. blurdev/resource/templ/py_header.templ +0 -9
  344. blurdev/resource/templ/py_line_comment.templ +0 -1
  345. blurdev/resource/templ/py_log_to_file.templ +0 -22
  346. blurdev/resource/templ/py_module_path.templ +0 -1
  347. blurdev/resource/templ/py_pyqt_core.templ +0 -1
  348. blurdev/resource/templ/py_pyqt_gui.templ +0 -1
  349. blurdev/resource/templ/py_splashscreen.templ +0 -6
  350. blurdev/resource/templ/py_testing_note.templ +0 -1
  351. blurdev/resource/templ/py_testing_note_end.templ +0 -1
  352. blurdev/resource/tools_environments.json +0 -72
  353. blurdev/resource/tools_environments.xml +0 -11
  354. blurdev/resource/tools_environments_linux.xml +0 -11
  355. blurdev/resource/tools_environments_offline.xml +0 -7
  356. blurdev/runtimes/__init__.py +0 -2
  357. blurdev/runtimes/logger.py +0 -44
  358. blurdev/scintilla/delayables/__init__.py +0 -9
  359. blurdev/settings.py +0 -312
  360. blurdev/utils/error.py +0 -389
  361. {blurdev/scintilla/lexers → preditor/cores}/__init__.py +0 -0
  362. {blurdev/utils → preditor/gui/fuzzy_search}/__init__.py +0 -0
  363. {blurdev → preditor}/resource/img/warning-big.png +0 -0
@@ -0,0 +1,357 @@
1
+ from __future__ import absolute_import, print_function
2
+
3
+ import os
4
+ import tempfile
5
+ import textwrap
6
+
7
+ from Qt.QtCore import Qt
8
+ from Qt.QtWidgets import QStackedWidget
9
+
10
+ from ..prefs import prefs_path
11
+
12
+
13
+ class WorkboxMixin(object):
14
+ _warning_text = None
15
+ """When a user is picking this Workbox class, show a warning with this text."""
16
+
17
+ def __init__(
18
+ self, parent=None, tempfile=None, filename=None, core_name=None, **kwargs
19
+ ):
20
+ super(WorkboxMixin, self).__init__(parent=parent, **kwargs)
21
+ self._filename_pref = filename
22
+ self._is_loaded = False
23
+ self._tempdir = None
24
+ self._tempfile = tempfile
25
+ self.core_name = core_name
26
+
27
+ def __auto_complete_enabled__(self):
28
+ raise NotImplementedError("Mixin method not overridden.")
29
+
30
+ def __set_auto_complete_enabled__(self, state):
31
+ raise NotImplementedError("Mixin method not overridden.")
32
+
33
+ def __clear__(self):
34
+ raise NotImplementedError("Mixin method not overridden.")
35
+
36
+ def __close__(self):
37
+ """Called just before the LoggerWindow is closed to allow for workbox cleanup"""
38
+
39
+ def __comment_toggle__(self):
40
+ raise NotImplementedError("Mixin method not overridden.")
41
+
42
+ def __console__(self):
43
+ """Returns the PrEditor console to code is executed in if set."""
44
+ try:
45
+ return self._console
46
+ except AttributeError:
47
+ self._console = None
48
+
49
+ def __set_console__(self, console):
50
+ self._console = console
51
+
52
+ def __copy_indents_as_spaces__(self):
53
+ """When copying code, should it convert leading tabs to spaces?"""
54
+ raise NotImplementedError("Mixin method not overridden.")
55
+
56
+ def __set_copy_indents_as_spaces__(self, state):
57
+ raise NotImplementedError("Mixin method not overridden.")
58
+
59
+ def __cursor_position__(self):
60
+ """Returns the line and index of the cursor."""
61
+ raise NotImplementedError("Mixin method not overridden.")
62
+
63
+ def __set_cursor_position__(self, line, index):
64
+ """Set the cursor to this line number and index"""
65
+ raise NotImplementedError("Mixin method not overridden.")
66
+
67
+ def __exec_all__(self):
68
+ raise NotImplementedError("Mixin method not overridden.")
69
+
70
+ def __exec_selected__(self):
71
+ txt = self.__selected_text__()
72
+
73
+ # Remove any leading white space shared across all lines
74
+ txt = textwrap.dedent(txt)
75
+
76
+ # Get rid of pesky \r's
77
+ txt = self.__unix_end_lines__(txt)
78
+
79
+ # Make workbox line numbers match the workbox line numbers.
80
+ line, _ = self.__cursor_position__()
81
+ txt = '\n' * line + txt
82
+
83
+ # execute the code
84
+ filename = self.__workbox_filename__(selection=True)
85
+ ret, was_eval = self.__console__().executeString(txt, filename=filename)
86
+ if was_eval:
87
+ # If the selected code was a statement print the result of the statement.
88
+ ret = repr(ret)
89
+ self.__console__().startOutputLine()
90
+ print(self.truncate_middle(ret, 100))
91
+
92
+ def __file_monitoring_enabled__(self):
93
+ """Returns True if this workbox supports file monitoring.
94
+ This allows the editor to update its text if the linked
95
+ file is changed on disk."""
96
+ return False
97
+
98
+ def __set_file_monitoring_enabled__(self, state):
99
+ pass
100
+
101
+ def __filename__(self):
102
+ raise NotImplementedError("Mixin method not overridden.")
103
+
104
+ def __font__(self):
105
+ raise NotImplementedError("Mixin method not overridden.")
106
+
107
+ def __set_font__(self, font):
108
+ raise NotImplementedError("Mixin method not overridden.")
109
+
110
+ def __group_tab_index__(self):
111
+ """Returns the group and editor indexes if this editor is being used in
112
+ a GroupTabWidget.
113
+
114
+ Returns:
115
+ group, editor: The index of the group tab and the index of the
116
+ editor's tab under the group tab. -1 is returned for both if
117
+ this isn't parent to a GroupTabWidget.
118
+ """
119
+ group = editor = -1
120
+
121
+ # This widget's parent should be a stacked widget and we can get the
122
+ # editors index from that
123
+ stack = self.parent()
124
+ if stack and isinstance(stack, QStackedWidget):
125
+ editor = stack.indexOf(self)
126
+ else:
127
+ return -1, -1
128
+
129
+ # The parent of the stacked widget should be a tab widget, get its parent
130
+ editor_tab = stack.parent()
131
+ if not editor_tab:
132
+ return -1, -1
133
+
134
+ # This should be a stacked widget under a tab widget, we can get group
135
+ # from it without needing to get its parent.
136
+ stack = editor_tab.parent()
137
+ if stack and isinstance(stack, QStackedWidget):
138
+ group = stack.indexOf(editor_tab)
139
+
140
+ return group, editor
141
+
142
+ def __workbox_filename__(self, selection=False):
143
+ title = "WorkboxSelection" if selection else "Workbox"
144
+ group, editor = self.__group_tab_index__()
145
+ if group == -1 or editor == -1:
146
+ return '<{}>'.format(title)
147
+ else:
148
+ return '<{}>:{},{}'.format(title, group, editor)
149
+
150
+ def __goto_line__(self, line):
151
+ raise NotImplementedError("Mixin method not overridden.")
152
+
153
+ def __indentations_use_tabs__(self):
154
+ raise NotImplementedError("Mixin method not overridden.")
155
+
156
+ def __set_indentations_use_tabs__(self, state):
157
+ raise NotImplementedError("Mixin method not overridden.")
158
+
159
+ def __insert_text__(self, txt):
160
+ raise NotImplementedError("Mixin method not overridden.")
161
+
162
+ def __load__(self, filename):
163
+ raise NotImplementedError("Mixin method not overridden.")
164
+
165
+ def __margins_font__(self):
166
+ raise NotImplementedError("Mixin method not overridden.")
167
+
168
+ def __set_margins_font__(self, font):
169
+ raise NotImplementedError("Mixin method not overridden.")
170
+
171
+ def __marker_add__(self, line):
172
+ raise NotImplementedError("Mixin method not overridden.")
173
+
174
+ def __marker_clear_all__(self):
175
+ raise NotImplementedError("Mixin method not overridden.")
176
+
177
+ def __reload_file__(self):
178
+ raise NotImplementedError("Mixin method not overridden.")
179
+
180
+ def __remove_selected_text__(self):
181
+ raise NotImplementedError("Mixin method not overridden.")
182
+
183
+ def __save__(self):
184
+ raise NotImplementedError("Mixin method not overridden.")
185
+
186
+ def __selected_text__(self, start_of_line=False):
187
+ """Returns selected text or the current line of text.
188
+
189
+ If text is selected, it is returned. If nothing is selected, returns the
190
+ entire line of text the cursor is currently on.
191
+
192
+ Args:
193
+ start_of_line (bool, optional): If text is selected, include any
194
+ leading text from the first line of the selection.
195
+ """
196
+ raise NotImplementedError("Mixin method not overridden.")
197
+
198
+ def __tab_width__(self):
199
+ raise NotImplementedError("Mixin method not overridden.")
200
+
201
+ def __set_tab_width__(self, width):
202
+ raise NotImplementedError("Mixin method not overridden.")
203
+
204
+ def __text__(self, line=None, start=None, end=None):
205
+ """Returns the text in this widget, possibly limited in scope.
206
+
207
+ Note: Only pass line, or (start and end) to this method.
208
+
209
+ Args:
210
+ line (int, optional): Limit the returned scope to just this line number.
211
+ start (int, optional): Limit the scope to text between this and end.
212
+ end (int, optional): Limit the scope to text between start and this.
213
+
214
+ Returns:
215
+ str: The requested text.
216
+ """
217
+ raise NotImplementedError("Mixin method not overridden.")
218
+
219
+ def __set_text__(self, txt):
220
+ """Replace all of the current text with txt. This method should be overridden
221
+ by sub-classes, and call super to mark the widget as having been loaded.
222
+ If text is being set on the widget, it most likely should be marked as
223
+ having been loaded.
224
+ """
225
+ self._is_loaded = True
226
+
227
+ def truncate_middle(self, s, n, sep=' ... '):
228
+ """Truncates the provided text to a fixed length, putting the sep in the middle.
229
+ https://www.xormedia.com/string-truncate-middle-with-ellipsis/
230
+ """
231
+ if len(s) <= n:
232
+ # string is already short-enough
233
+ return s
234
+ # half of the size, minus the seperator
235
+ n_2 = int(n) // 2 - len(sep)
236
+ # whatever's left
237
+ n_1 = n - n_2 - len(sep)
238
+ return '{0}{1}{2}'.format(s[:n_1], sep, s[-n_2:])
239
+
240
+ @classmethod
241
+ def __unix_end_lines__(cls, txt):
242
+ """Replaces all windows and then mac line endings with unix line endings."""
243
+ return txt.replace('\r\n', '\n').replace('\r', '\n')
244
+
245
+ def __restore_prefs__(self, prefs):
246
+ self._filename_pref = prefs.get('filename')
247
+ self._tempfile = prefs.get('tempfile')
248
+
249
+ def __save_prefs__(self, name, current=None):
250
+ ret = {}
251
+ # Hopefully the alphabetical sorting of this dict is preserved in py3
252
+ # to make it easy to diff the json pref file if ever required.
253
+ if current is not None:
254
+ ret['current'] = current
255
+ ret['filename'] = self._filename_pref
256
+ ret['name'] = name
257
+ ret['tempfile'] = self._tempfile
258
+
259
+ if not self._is_loaded:
260
+ return ret
261
+
262
+ if self._filename_pref:
263
+ self.__save__()
264
+ else:
265
+ if not self._tempfile:
266
+ self._tempfile = self.__create_tempfile__()
267
+ ret['tempfile'] = self._tempfile
268
+ self.__write_file__(
269
+ self.__tempfile__(create=True),
270
+ self.__text__(),
271
+ )
272
+
273
+ return ret
274
+
275
+ def __tempdir__(self, create=False):
276
+ if self._tempdir is None:
277
+ self._tempdir = prefs_path('workboxes', core_name=self.core_name)
278
+
279
+ if create and not os.path.exists(self._tempdir):
280
+ os.makedirs(self._tempdir)
281
+
282
+ return self._tempdir
283
+
284
+ def __tempfile__(self, create=False):
285
+ if self._tempfile:
286
+ return os.path.join(self.__tempdir__(create=create), self._tempfile)
287
+
288
+ def __create_tempfile__(self):
289
+ """Creates a temporary file to be used by `__tempfile__` to store this
290
+ editors text contents stored in `__tempdir__`."""
291
+ with tempfile.NamedTemporaryFile(
292
+ prefix='workbox_',
293
+ suffix='.py',
294
+ dir=self.__tempdir__(create=True),
295
+ delete=False,
296
+ ) as fle:
297
+ name = fle.name
298
+
299
+ return os.path.basename(name)
300
+
301
+ def __remove_tempfile__(self):
302
+ """Removes `__tempfile__` if it is being used."""
303
+ tempfile = self.__tempfile__()
304
+ if tempfile and os.path.exists(tempfile):
305
+ os.remove(tempfile)
306
+
307
+ @classmethod
308
+ def __open_file__(cls, filename):
309
+ with open(filename) as fle:
310
+ return fle.read()
311
+ return ""
312
+
313
+ @classmethod
314
+ def __write_file__(cls, filename, txt):
315
+ with open(filename, 'w') as fle:
316
+ fle.write(txt)
317
+
318
+ def __show__(self):
319
+ if self._is_loaded:
320
+ return
321
+
322
+ self._is_loaded = True
323
+ if self._filename_pref:
324
+ self.__load__(self._filename_pref)
325
+ elif self._tempfile:
326
+ txt = self.__open_file__(self.__tempfile__())
327
+ self.__set_text__(txt)
328
+
329
+ def process_shortcut(self, event, run=True):
330
+ """Check for workbox shortcuts and optionally call them.
331
+
332
+ Args:
333
+ event (QEvent): The keyPressEvent to process.
334
+ run (bool, optional): Run the expected action if possible.
335
+
336
+ Returns:
337
+ str or False: Returns False if the key press was not handled, indicating
338
+ that the subclass needs to handle it(or call super). If a known
339
+ shortcut was detected, a string indicating the action is returned
340
+ after running the action if enabled and supported.
341
+
342
+ Known actions:
343
+ __exec_selected__: If the user pressed Shift + Return or pressed the
344
+ number pad enter key calling `__exec_selected__`.
345
+ """
346
+ if event.key() == Qt.Key_Enter or (
347
+ event.key() == Qt.Key_Return and event.modifiers() == Qt.ShiftModifier
348
+ ):
349
+ # Number pad enter, or Shift + Return pressed, execute selected
350
+ if run:
351
+ self.__exec_selected__()
352
+
353
+ if self.window().uiAutoPromptACT.isChecked():
354
+ self.__console__().startInputLine()
355
+ return '__exec_selected__'
356
+
357
+ return False
@@ -0,0 +1,117 @@
1
+ from __future__ import absolute_import
2
+
3
+ import logging
4
+
5
+ from Qt.QtGui import QFont, QFontMetrics, QTextCursor
6
+ from Qt.QtWidgets import QTextEdit
7
+
8
+ from .codehighlighter import CodeHighlighter
9
+ from .workbox_mixin import WorkboxMixin
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
15
+ """A very simple multi-line text editor without any bells and whistles.
16
+
17
+ It's better than nothing, but not by much.
18
+ """
19
+
20
+ _warning_text = (
21
+ "This is a bare bones workbox, if you have another option, it's probably"
22
+ "a better option."
23
+ )
24
+
25
+ def __init__(
26
+ self, parent=None, console=None, delayable_engine='default', core_name=None
27
+ ):
28
+ super(WorkboxTextEdit, self).__init__(parent=parent, core_name=core_name)
29
+ self._filename = None
30
+ self.__set_console__(console)
31
+ highlight = CodeHighlighter(self)
32
+ highlight.setLanguage('Python')
33
+ self.uiCodeHighlighter = highlight
34
+
35
+ def __copy_indents_as_spaces__(self):
36
+ """When copying code, should it convert leading tabs to spaces?"""
37
+ return False
38
+
39
+ def __set_copy_indents_as_spaces__(self, state):
40
+ logger.info(
41
+ "WorkboxTextEdit does not support converting indents to spaces on copy."
42
+ )
43
+
44
+ def __cursor_position__(self):
45
+ """Returns the line and index of the cursor."""
46
+ cursor = self.textCursor()
47
+ sc = QTextCursor(self.document())
48
+ sc.setPosition(cursor.selectionStart())
49
+ return sc.blockNumber(), sc.positionInBlock()
50
+
51
+ def __exec_all__(self):
52
+ txt = self.__text__().rstrip()
53
+ filename = self.__workbox_filename__()
54
+ self.__console__().executeString(txt, filename=filename)
55
+
56
+ def __font__(self):
57
+ return self.font()
58
+
59
+ def __set_font__(self, font):
60
+ metrics = QFontMetrics(font)
61
+ self.setTabStopDistance(metrics.width(" ") * 4)
62
+ super(WorkboxTextEdit, self).setFont(font)
63
+
64
+ def __goto_line__(self, line):
65
+ cursor = QTextCursor(self.document().findBlockByLineNumber(line - 1))
66
+ self.setTextCursor(cursor)
67
+
68
+ def __indentations_use_tabs__(self):
69
+ return True
70
+
71
+ def __set_indentations_use_tabs__(self, state):
72
+ logger.info("WorkboxTextEdit does not support using spaces for tabs.")
73
+
74
+ def __load__(self, filename):
75
+ self._filename = filename
76
+ txt = self.__open_file__(self._filename)
77
+ self.__set_text__(txt)
78
+
79
+ def __margins_font__(self):
80
+ return QFont()
81
+
82
+ def __set_margins_font__(self, font):
83
+ pass
84
+
85
+ def __tab_width__(self):
86
+ # TODO: Implement custom tab widths
87
+ return 4
88
+
89
+ def __text__(self, line=None, start=None, end=None):
90
+ return self.toPlainText()
91
+
92
+ def __set_text__(self, text):
93
+ super(WorkboxTextEdit, self).__set_text__(text)
94
+ self.setPlainText(text)
95
+
96
+ def __selected_text__(self, start_of_line=False):
97
+ cursor = self.textCursor()
98
+
99
+ # If no selection, return the current line
100
+ if cursor.selection().isEmpty():
101
+ return cursor.block().text()
102
+
103
+ # Otherwise return the selected text
104
+ if start_of_line:
105
+ sc = QTextCursor(self.document())
106
+ sc.setPosition(cursor.selectionStart())
107
+ sc.movePosition(cursor.StartOfLine, sc.MoveAnchor)
108
+ sc.setPosition(cursor.selectionEnd(), sc.KeepAnchor)
109
+ return sc.selection().toPlainText()
110
+
111
+ return self.textCursor().selection().toPlainText()
112
+
113
+ def keyPressEvent(self, event):
114
+ if self.process_shortcut(event):
115
+ return
116
+ else:
117
+ super(WorkboxTextEdit, self).keyPressEvent(event)