PrEditor 2.1.0__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 (179) hide show
  1. preditor/__init__.py +315 -0
  2. preditor/__main__.py +13 -0
  3. preditor/about_module.py +165 -0
  4. preditor/cli.py +192 -0
  5. preditor/config.py +318 -0
  6. preditor/constants.py +13 -0
  7. preditor/contexts.py +210 -0
  8. preditor/cores/__init__.py +0 -0
  9. preditor/cores/core.py +20 -0
  10. preditor/dccs/.hab.json +10 -0
  11. preditor/dccs/maya/PrEditor_maya.mod +1 -0
  12. preditor/dccs/maya/README.md +22 -0
  13. preditor/dccs/maya/plug-ins/PrEditor_maya.py +141 -0
  14. preditor/dccs/studiomax/PackageContents.xml +32 -0
  15. preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +8 -0
  16. preditor/dccs/studiomax/README.md +17 -0
  17. preditor/dccs/studiomax/preditor.ms +16 -0
  18. preditor/dccs/studiomax/preditor_menu.mnx +7 -0
  19. preditor/debug.py +149 -0
  20. preditor/delayable_engine/__init__.py +302 -0
  21. preditor/delayable_engine/delayables.py +85 -0
  22. preditor/enum.py +728 -0
  23. preditor/excepthooks.py +165 -0
  24. preditor/gui/__init__.py +56 -0
  25. preditor/gui/app.py +163 -0
  26. preditor/gui/codehighlighter.py +289 -0
  27. preditor/gui/completer.py +237 -0
  28. preditor/gui/console.py +605 -0
  29. preditor/gui/console_base.py +911 -0
  30. preditor/gui/dialog.py +181 -0
  31. preditor/gui/drag_tab_bar.py +625 -0
  32. preditor/gui/editor_chooser.py +57 -0
  33. preditor/gui/errordialog.py +69 -0
  34. preditor/gui/find_files.py +137 -0
  35. preditor/gui/fuzzy_search/__init__.py +0 -0
  36. preditor/gui/fuzzy_search/fuzzy_search.py +97 -0
  37. preditor/gui/group_tab_widget/__init__.py +0 -0
  38. preditor/gui/group_tab_widget/group_tab_widget.py +528 -0
  39. preditor/gui/group_tab_widget/grouped_tab_menu.py +35 -0
  40. preditor/gui/group_tab_widget/grouped_tab_models.py +107 -0
  41. preditor/gui/group_tab_widget/grouped_tab_widget.py +223 -0
  42. preditor/gui/group_tab_widget/one_tab_widget.py +96 -0
  43. preditor/gui/level_buttons.py +358 -0
  44. preditor/gui/logger_window_handler.py +77 -0
  45. preditor/gui/logger_window_plugin.py +35 -0
  46. preditor/gui/loggerwindow.py +2405 -0
  47. preditor/gui/newtabwidget.py +69 -0
  48. preditor/gui/output_console.py +11 -0
  49. preditor/gui/qtdesigner/__init__.py +21 -0
  50. preditor/gui/qtdesigner/_log_plugin.py +29 -0
  51. preditor/gui/qtdesigner/console_base_plugin.py +48 -0
  52. preditor/gui/qtdesigner/console_predit_plugin.py +48 -0
  53. preditor/gui/set_text_editor_path_dialog.py +61 -0
  54. preditor/gui/status_label.py +99 -0
  55. preditor/gui/suggest_path_quotes_dialog.py +50 -0
  56. preditor/gui/ui/editor_chooser.ui +93 -0
  57. preditor/gui/ui/errordialog.ui +74 -0
  58. preditor/gui/ui/find_files.ui +140 -0
  59. preditor/gui/ui/loggerwindow.ui +1909 -0
  60. preditor/gui/ui/set_text_editor_path_dialog.ui +189 -0
  61. preditor/gui/ui/suggest_path_quotes_dialog.ui +225 -0
  62. preditor/gui/window.py +161 -0
  63. preditor/gui/workbox_mixin.py +1139 -0
  64. preditor/gui/workbox_text_edit.py +136 -0
  65. preditor/gui/workboxwidget.py +315 -0
  66. preditor/logging_config.py +55 -0
  67. preditor/osystem.py +401 -0
  68. preditor/plugins.py +118 -0
  69. preditor/prefs.py +381 -0
  70. preditor/resource/environment_variables.html +26 -0
  71. preditor/resource/error_mail.html +85 -0
  72. preditor/resource/error_mail_inline.html +41 -0
  73. preditor/resource/img/README.md +17 -0
  74. preditor/resource/img/arrow_forward.png +0 -0
  75. preditor/resource/img/check-bold.png +0 -0
  76. preditor/resource/img/chevron-down.png +0 -0
  77. preditor/resource/img/chevron-up.png +0 -0
  78. preditor/resource/img/close-thick.png +0 -0
  79. preditor/resource/img/comment-edit.png +0 -0
  80. preditor/resource/img/content-copy.png +0 -0
  81. preditor/resource/img/content-cut.png +0 -0
  82. preditor/resource/img/content-duplicate.png +0 -0
  83. preditor/resource/img/content-paste.png +0 -0
  84. preditor/resource/img/content-save.png +0 -0
  85. preditor/resource/img/debug_disabled.png +0 -0
  86. preditor/resource/img/eye-check.png +0 -0
  87. preditor/resource/img/file-plus.png +0 -0
  88. preditor/resource/img/file-remove.png +0 -0
  89. preditor/resource/img/format-align-left.png +0 -0
  90. preditor/resource/img/format-letter-case-lower.png +0 -0
  91. preditor/resource/img/format-letter-case-upper.png +0 -0
  92. preditor/resource/img/format-letter-case.svg +1 -0
  93. preditor/resource/img/information.png +0 -0
  94. preditor/resource/img/logging_critical.png +0 -0
  95. preditor/resource/img/logging_custom.png +0 -0
  96. preditor/resource/img/logging_debug.png +0 -0
  97. preditor/resource/img/logging_error.png +0 -0
  98. preditor/resource/img/logging_info.png +0 -0
  99. preditor/resource/img/logging_not_set.png +0 -0
  100. preditor/resource/img/logging_warning.png +0 -0
  101. preditor/resource/img/marker.png +0 -0
  102. preditor/resource/img/play.png +0 -0
  103. preditor/resource/img/playlist-play.png +0 -0
  104. preditor/resource/img/plus-minus-variant.png +0 -0
  105. preditor/resource/img/preditor.ico +0 -0
  106. preditor/resource/img/preditor.png +0 -0
  107. preditor/resource/img/preditor.psd +0 -0
  108. preditor/resource/img/preditor.svg +44 -0
  109. preditor/resource/img/regex.svg +1 -0
  110. preditor/resource/img/restart.svg +1 -0
  111. preditor/resource/img/skip-forward-outline.png +0 -0
  112. preditor/resource/img/skip-next-outline.png +0 -0
  113. preditor/resource/img/skip-next.png +0 -0
  114. preditor/resource/img/skip-previous.png +0 -0
  115. preditor/resource/img/subdirectory-arrow-right.png +0 -0
  116. preditor/resource/img/text-search-variant.png +0 -0
  117. preditor/resource/img/warning-big.png +0 -0
  118. preditor/resource/lang/python.json +30 -0
  119. preditor/resource/pref_updates/pref_updates.json +17 -0
  120. preditor/resource/settings.ini +25 -0
  121. preditor/resource/stylesheet/Bright.css +76 -0
  122. preditor/resource/stylesheet/Dark.css +210 -0
  123. preditor/scintilla/__init__.py +40 -0
  124. preditor/scintilla/delayables/__init__.py +11 -0
  125. preditor/scintilla/delayables/smart_highlight.py +97 -0
  126. preditor/scintilla/delayables/spell_check.py +174 -0
  127. preditor/scintilla/documenteditor.py +1924 -0
  128. preditor/scintilla/finddialog.py +68 -0
  129. preditor/scintilla/lang/__init__.py +80 -0
  130. preditor/scintilla/lang/config/bash.ini +15 -0
  131. preditor/scintilla/lang/config/batch.ini +14 -0
  132. preditor/scintilla/lang/config/cpp.ini +19 -0
  133. preditor/scintilla/lang/config/css.ini +19 -0
  134. preditor/scintilla/lang/config/eyeonscript.ini +17 -0
  135. preditor/scintilla/lang/config/html.ini +21 -0
  136. preditor/scintilla/lang/config/javascript.ini +24 -0
  137. preditor/scintilla/lang/config/lua.ini +16 -0
  138. preditor/scintilla/lang/config/maxscript.ini +20 -0
  139. preditor/scintilla/lang/config/mel.ini +18 -0
  140. preditor/scintilla/lang/config/mu.ini +22 -0
  141. preditor/scintilla/lang/config/nsi.ini +19 -0
  142. preditor/scintilla/lang/config/perl.ini +19 -0
  143. preditor/scintilla/lang/config/puppet.ini +19 -0
  144. preditor/scintilla/lang/config/python.ini +28 -0
  145. preditor/scintilla/lang/config/ruby.ini +19 -0
  146. preditor/scintilla/lang/config/sql.ini +7 -0
  147. preditor/scintilla/lang/config/xml.ini +21 -0
  148. preditor/scintilla/lang/config/yaml.ini +18 -0
  149. preditor/scintilla/lang/language.py +240 -0
  150. preditor/scintilla/lexers/__init__.py +0 -0
  151. preditor/scintilla/lexers/cpplexer.py +22 -0
  152. preditor/scintilla/lexers/javascriptlexer.py +27 -0
  153. preditor/scintilla/lexers/maxscriptlexer.py +235 -0
  154. preditor/scintilla/lexers/mellexer.py +369 -0
  155. preditor/scintilla/lexers/mulexer.py +33 -0
  156. preditor/scintilla/lexers/pythonlexer.py +42 -0
  157. preditor/scintilla/ui/finddialog.ui +160 -0
  158. preditor/settings.py +71 -0
  159. preditor/stream/__init__.py +72 -0
  160. preditor/stream/console_handler.py +169 -0
  161. preditor/stream/director.py +144 -0
  162. preditor/stream/manager.py +97 -0
  163. preditor/streamhandler_helper.py +46 -0
  164. preditor/utils/__init__.py +191 -0
  165. preditor/utils/call_stack.py +86 -0
  166. preditor/utils/cute.py +106 -0
  167. preditor/utils/stylesheets.py +54 -0
  168. preditor/utils/text_search.py +338 -0
  169. preditor/version.py +34 -0
  170. preditor/weakref.py +363 -0
  171. preditor-2.1.0.dist-info/METADATA +308 -0
  172. preditor-2.1.0.dist-info/RECORD +179 -0
  173. preditor-2.1.0.dist-info/WHEEL +5 -0
  174. preditor-2.1.0.dist-info/entry_points.txt +19 -0
  175. preditor-2.1.0.dist-info/licenses/LICENSE +165 -0
  176. preditor-2.1.0.dist-info/top_level.txt +3 -0
  177. tests/encodings/test_ecoding.py +33 -0
  178. tests/find_files/test_find_files.py +74 -0
  179. tests/ide/test_delayable_engine.py +171 -0
@@ -0,0 +1,69 @@
1
+ from __future__ import absolute_import
2
+
3
+ from Qt.QtCore import QSize, Signal
4
+ from Qt.QtWidgets import QPushButton, QTabBar, QTabWidget
5
+
6
+ # This class is pulled from this example
7
+ # http://stackoverflow.com/a/20098415
8
+
9
+
10
+ class TabBarPlus(QTabBar):
11
+ plusClicked = Signal()
12
+
13
+ def __init__(self, parent=None):
14
+ super(TabBarPlus, self).__init__(parent)
15
+ # Plus Button
16
+ self.uiPlusBTN = QPushButton("+")
17
+ self.uiPlusBTN.setParent(self)
18
+ self.uiPlusBTN.setObjectName('uiPlusBTN')
19
+ self.uiPlusBTN.clicked.connect(self.plusClicked.emit)
20
+ self.movePlusButton()
21
+
22
+ def sizeHint(self):
23
+ sizeHint = QTabBar.sizeHint(self)
24
+ width = sizeHint.width()
25
+ height = sizeHint.height()
26
+ return QSize(width + 25, height)
27
+
28
+ def resizeEvent(self, event):
29
+ super(TabBarPlus, self).resizeEvent(event)
30
+ self.movePlusButton()
31
+
32
+ def tabLayoutChange(self):
33
+ super(TabBarPlus, self).tabLayoutChange()
34
+
35
+ self.movePlusButton()
36
+
37
+ def movePlusButton(self):
38
+ size = 0
39
+ for i in range(self.count()):
40
+ size += self.tabRect(i).width()
41
+
42
+ h = self.geometry().top()
43
+ w = self.width()
44
+ if size > w: # Show just to the left of the scroll buttons
45
+ self.uiPlusBTN.move(w - 54, h)
46
+ else:
47
+ self.uiPlusBTN.move(size, h)
48
+ # Resize the button to fit the height of the tab bar
49
+ hint = self.sizeHint().height()
50
+ self.uiPlusBTN.setMaximumSize(hint, hint)
51
+ self.uiPlusBTN.setMinimumSize(hint, hint)
52
+
53
+
54
+ class NewTabWidget(QTabWidget):
55
+ addTabClicked = Signal()
56
+
57
+ def __init__(self, parent=None):
58
+ super(NewTabWidget, self).__init__(parent)
59
+
60
+ # Tab Bar
61
+ self._tab = TabBarPlus()
62
+ self.setTabBar(self._tab)
63
+
64
+ # Properties
65
+ self.setMovable(True)
66
+ self.setTabsClosable(True)
67
+
68
+ # Signals
69
+ self._tab.plusClicked.connect(self.addTabClicked.emit)
@@ -0,0 +1,11 @@
1
+ from ..utils.cute import QtPropertyInit
2
+ from .console_base import ConsoleBase
3
+
4
+
5
+ class OutputConsole(ConsoleBase):
6
+ """A text widget used to show stdout/stderr writes."""
7
+
8
+ # Enable these settings by default
9
+ use_console_stylesheet = QtPropertyInit(
10
+ "_use_console_stylesheet", True, callback=ConsoleBase.init_stylesheet
11
+ )
@@ -0,0 +1,21 @@
1
+ """
2
+ PYSIDE_DESIGNER_PLUGINS or PYQTDESIGNERPATH
3
+ """
4
+ __all__ = ["QPyDesignerCustomWidgetCollection", "QPyDesignerCustomWidgetPlugin"]
5
+
6
+ import Qt # noqa: E402
7
+
8
+ if Qt.IsPySide6:
9
+ from PySide6.QtDesigner import (
10
+ QPyDesignerCustomWidgetCollection,
11
+ QPyDesignerCustomWidgetPlugin,
12
+ )
13
+ elif Qt.IsPyQt6:
14
+ from PyQt6.QtDesigner import QPyDesignerCustomWidgetPlugin
15
+ elif Qt.IsPySide2:
16
+ from PySide2.QtDesigner import (
17
+ QPyDesignerCustomWidgetCollection,
18
+ QPyDesignerCustomWidgetPlugin,
19
+ )
20
+ elif Qt.IsPyQt5:
21
+ from PyQt5.QtDesigner import QPyDesignerCustomWidgetPlugin
@@ -0,0 +1,29 @@
1
+ """Plugin used to enable access to python's stdout/stderr. Without this we have
2
+ no way to see python output on windows because its not a console app.
3
+
4
+ All output is written to $TEMP/preditor_qdesigner_plugins.log.
5
+ """
6
+
7
+ import sys
8
+ import tempfile
9
+ import traceback
10
+ from pathlib import Path
11
+
12
+ from preditor.debug import logToFile
13
+
14
+ path = Path(tempfile.gettempdir()) / "preditor_qdesigner_plugins.log"
15
+ logToFile(path, useOldStd=False)
16
+
17
+
18
+ def no_crash_excepthook(exc_type, exc_value, tb):
19
+ """This consumes the exception so Qt doesn't exit on un-handled exceptions."""
20
+ if issubclass(exc_type, KeyboardInterrupt):
21
+ sys.__excepthook__(exc_type, exc_value, tb)
22
+ return
23
+
24
+ print("--- Unhanded Exception Start ---")
25
+ print(traceback.print_exception(exc_type, exc_value, tb))
26
+ print("--- Unhanded Exception End ---")
27
+
28
+
29
+ sys.excepthook = no_crash_excepthook
@@ -0,0 +1,48 @@
1
+ from preditor.gui import qtdesigner
2
+
3
+
4
+ class OutputConsolePlugin(qtdesigner.QPyDesignerCustomWidgetPlugin):
5
+ def __init__(self, parent=None):
6
+ super(OutputConsolePlugin, self).__init__()
7
+
8
+ self.initialized = False
9
+
10
+ def initialize(self, core):
11
+ if self.initialized:
12
+ return
13
+
14
+ self.initialized = True
15
+
16
+ def isInitialized(self):
17
+ return self.initialized
18
+
19
+ def createWidget(self, parent):
20
+ from preditor.gui.output_console import OutputConsole
21
+
22
+ return OutputConsole(parent=parent, controller=None)
23
+
24
+ def name(self):
25
+ return "OutputConsole"
26
+
27
+ def group(self):
28
+ return "PrEditor Widgets"
29
+
30
+ def icon(self):
31
+ from Qt.QtGui import QIcon
32
+
33
+ return QIcon("")
34
+
35
+ def toolTip(self):
36
+ return ""
37
+
38
+ def whatsThis(self):
39
+ return ""
40
+
41
+ def isContainer(self):
42
+ return False
43
+
44
+ def includeFile(self):
45
+ return "preditor.gui.output_console"
46
+
47
+ def domXml(self):
48
+ return '<widget class="OutputConsole" name="OutputConsole"/>'
@@ -0,0 +1,48 @@
1
+ from preditor.gui import qtdesigner
2
+
3
+
4
+ class ConsolePrEditPlugin(qtdesigner.QPyDesignerCustomWidgetPlugin):
5
+ def __init__(self, parent=None):
6
+ super(ConsolePrEditPlugin, self).__init__()
7
+
8
+ self.initialized = False
9
+
10
+ def initialize(self, core):
11
+ if self.initialized:
12
+ return
13
+
14
+ self.initialized = True
15
+
16
+ def isInitialized(self):
17
+ return self.initialized
18
+
19
+ def createWidget(self, parent):
20
+ from preditor.gui.console import ConsolePrEdit
21
+
22
+ return ConsolePrEdit(parent=parent, controller=None)
23
+
24
+ def name(self):
25
+ return "ConsolePrEdit"
26
+
27
+ def group(self):
28
+ return "PrEditor Widgets"
29
+
30
+ def icon(self):
31
+ from Qt.QtGui import QIcon
32
+
33
+ return QIcon("")
34
+
35
+ def toolTip(self):
36
+ return ""
37
+
38
+ def whatsThis(self):
39
+ return ""
40
+
41
+ def isContainer(self):
42
+ return False
43
+
44
+ def includeFile(self):
45
+ return "preditor.gui.console"
46
+
47
+ def domXml(self):
48
+ return '<widget class="ConsolePrEdit" name="ConsolePrEdit"/>'
@@ -0,0 +1,61 @@
1
+ from __future__ import absolute_import
2
+
3
+ import os
4
+
5
+ from Qt.QtWidgets import QDialog, QMessageBox
6
+
7
+ from . import loadUi
8
+
9
+
10
+ class SetTextEditorPathDialog(QDialog):
11
+ """A dialog used to set the user's text editor executable path, as well as define a
12
+ 'command template', which allows for the various ways text editor's may implement
13
+ opening a file at a given line number via Command Prompt.
14
+ """
15
+
16
+ def __init__(self, parent=None):
17
+ super(SetTextEditorPathDialog, self).__init__(parent)
18
+ loadUi(__file__, self)
19
+
20
+ # Retrieve existing data from LoggerWindow
21
+ path = self.parent().textEditorPath
22
+ cmdTempl = self.parent().textEditorCmdTempl
23
+
24
+ # If the data exists, place in the UI, otherwise use UI defaults
25
+ if path:
26
+ self.uiTextEditorExecutablePathLE.setText(path)
27
+ if cmdTempl:
28
+ self.uiTextEditorCommandPatternLE.setText(cmdTempl)
29
+
30
+ toolTip = (
31
+ "Examples:\n"
32
+ 'SublimeText: "{exePath}" "{modulePath}":{lineNum}\n'
33
+ 'notepad++: "{exePath}" "{modulePath}" -n{lineNum}\n'
34
+ 'vim: "{exePath}" + {lineNum} "{modulePath}'
35
+ )
36
+ self.uiTextEditorCommandPatternLE.setToolTip(toolTip)
37
+
38
+ def accept(self):
39
+ """Validate that the path exists and is executable.
40
+ Can't really validate the command template, so instead we use try/except when
41
+ issuing the command.
42
+ """
43
+ path = self.uiTextEditorExecutablePathLE.text()
44
+ cmdTempl = self.uiTextEditorCommandPatternLE.text()
45
+
46
+ path = path.strip("\"")
47
+
48
+ # isExecutable is not very accurate, because on Windows, .jpg and .txt, etc
49
+ # files are returned as executable. Perhaps on other systems, it's actually
50
+ # relevant to whether the file is 'executable'.
51
+ isExecutable = os.access(path, os.X_OK)
52
+ if isExecutable:
53
+ self.parent().textEditorPath = path
54
+ self.parent().textEditorCmdTempl = cmdTempl
55
+ super(SetTextEditorPathDialog, self).accept()
56
+ else:
57
+ msg = "That path doesn't exists or isn't an executable file."
58
+ label = 'Incorrect Path'
59
+ QMessageBox.warning(
60
+ self.window(), label, msg, QMessageBox.StandardButton.Ok
61
+ )
@@ -0,0 +1,99 @@
1
+ from __future__ import absolute_import
2
+
3
+ from collections import deque
4
+ from functools import partial
5
+
6
+ from Qt.QtCore import QPoint, QTimer
7
+ from Qt.QtWidgets import QApplication, QInputDialog, QLabel, QMenu
8
+
9
+
10
+ class StatusLabel(QLabel):
11
+ """A label that shows text and an average of code execution times in popup menu."""
12
+
13
+ def __init__(self, *args, limit=5, **kwargs):
14
+ self.render_as_href = False
15
+ super(StatusLabel, self).__init__(*args, **kwargs)
16
+ self.times = deque(maxlen=limit)
17
+
18
+ def clear(self):
19
+ self.setText("")
20
+
21
+ def clearTimes(self):
22
+ """"""
23
+ self.times.clear()
24
+
25
+ def chooseLimit(self):
26
+ limit, success = QInputDialog.getInt(
27
+ self,
28
+ "Choose Avg length",
29
+ "Choose how many execution time history to keep.",
30
+ value=self.limit(),
31
+ min=1,
32
+ max=100,
33
+ )
34
+ if limit:
35
+ self.setLimit(limit)
36
+
37
+ def copy_action_text(self, action):
38
+ """Copy the text of the provided action into the clipboard."""
39
+ QApplication.clipboard().setText(action.text())
40
+
41
+ def mouseReleaseEvent(self, event):
42
+ QTimer.singleShot(0, self.showMenu)
43
+ super(StatusLabel, self).mouseReleaseEvent(event)
44
+
45
+ def secondsText(self, seconds):
46
+ """Generates text to show seconds of exec time."""
47
+ return 'Exec: {:0.04f} Seconds'.format(seconds)
48
+
49
+ def limit(self):
50
+ return self.times.maxlen
51
+
52
+ def setLimit(self, limit):
53
+ self.times = deque(self.times, maxlen=limit)
54
+
55
+ def setText(self, text):
56
+ if self.render_as_href:
57
+ text = '<a href="showMenu">{}</a>'.format(text)
58
+ super(StatusLabel, self).setText(text)
59
+
60
+ def showSeconds(self, seconds):
61
+ self.times.append(seconds)
62
+ self.setText(self.secondsText(seconds[0]))
63
+
64
+ def showMenu(self):
65
+ menu = QMenu(self)
66
+ if self.times:
67
+ # Show the time it took to run the last X code calls
68
+ times = []
69
+ for seconds in self.times:
70
+ secs, cmd = seconds
71
+ times.append(secs)
72
+
73
+ # Add a simplified copy of the command that was run
74
+ cmd = cmd.strip()
75
+ cmds = cmd.split("\n")
76
+ if len(cmds) > 1 or len(cmds[0]) > 50:
77
+ cmd = "{} ...".format(cmds[0][:50])
78
+ # Escape &'s so they dont' get turned into a shortcut'
79
+ cmd = cmd.replace("&", "&&")
80
+ act = menu.addAction("{}: {}".format(self.secondsText(secs), cmd))
81
+ # Selecting this action should copy the time it took to run
82
+ act.triggered.connect(partial(self.copy_action_text, act))
83
+
84
+ menu.addSeparator()
85
+ avg = sum(times) / len(times)
86
+ act = menu.addAction("Average: {:0.04f}s".format(avg))
87
+ act.triggered.connect(partial(self.copy_action_text, act))
88
+
89
+ act = menu.addAction("Clear")
90
+ act.triggered.connect(self.clearTimes)
91
+
92
+ menu.addSeparator()
93
+ act = menu.addAction("Set limit...")
94
+ act.triggered.connect(self.chooseLimit)
95
+
96
+ # Position the menu at the bottom of the widget
97
+ height = self.geometry().height()
98
+ pos = self.mapToGlobal(QPoint(0, height))
99
+ menu.popup(pos)
@@ -0,0 +1,50 @@
1
+ from __future__ import absolute_import
2
+
3
+ from Qt.QtWidgets import QDialog
4
+
5
+ from . import loadUi
6
+
7
+
8
+ class SuggestPathQuotesDialog(QDialog):
9
+ """A dialog to suggest to enclose paths in double-quotes in the cmdTempl which is
10
+ used to launch an external text editor.
11
+ """
12
+
13
+ def __init__(self, parent, oldCmdTempl, newCmdTempl):
14
+ super(SuggestPathQuotesDialog, self).__init__(parent)
15
+ loadUi(__file__, self)
16
+
17
+ self.parentWindow = self.parent().window()
18
+
19
+ self.uiTextEditorOldCommandPatternLE.setText(oldCmdTempl)
20
+ self.uiTextEditorNewCommandPatternLE.setText(newCmdTempl)
21
+
22
+ toolTip = (
23
+ "Examples:\n"
24
+ 'SublimeText: "{exePath}" "{modulePath}":{lineNum}\n'
25
+ 'notepad++: "{exePath}" "{modulePath}" -n{lineNum}\n'
26
+ 'vim: "{exePath}" + {lineNum} "{modulePath}'
27
+ )
28
+ self.uiTextEditorNewCommandPatternLE.setToolTip(toolTip)
29
+
30
+ def accept(self):
31
+ """Set the parentWindow's textEditorCmdTempl property from the dialog, and
32
+ optionally add dialog to parent's dont_ask_again list, and accept.
33
+ """
34
+
35
+ cmdTempl = self.uiTextEditorNewCommandPatternLE.text()
36
+ self.parentWindow.textEditorCmdTempl = cmdTempl
37
+
38
+ if self.uiDontAskAgainCHK.isChecked():
39
+ if hasattr(self.parentWindow, "dont_ask_again"):
40
+ self.parentWindow.dont_ask_again.append(self.objectName())
41
+
42
+ super(SuggestPathQuotesDialog, self).accept()
43
+
44
+ def reject(self):
45
+ """Optionally add dialog to parentWindow's dont_ask_again list, and reject"""
46
+ if self.uiDontAskAgainCHK.isChecked():
47
+ if hasattr(self.parentWindow, "dont_ask_again"):
48
+ self.parentWindow.dont_ask_again.append(self.objectName())
49
+
50
+ super(SuggestPathQuotesDialog, self).reject()
@@ -0,0 +1,93 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>543</width>
10
+ <height>118</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>Form</string>
15
+ </property>
16
+ <layout class="QFormLayout" name="formLayout_2">
17
+ <property name="labelAlignment">
18
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
19
+ </property>
20
+ <item row="0" column="0">
21
+ <widget class="QLabel" name="uiWorkboxEditorLBL">
22
+ <property name="text">
23
+ <string>Editor Class:</string>
24
+ </property>
25
+ </widget>
26
+ </item>
27
+ <item row="0" column="1">
28
+ <widget class="QComboBox" name="uiWorkboxEditorDDL"/>
29
+ </item>
30
+ <item row="1" column="0">
31
+ <widget class="QLabel" name="uiWarningIconLBL">
32
+ <property name="layoutDirection">
33
+ <enum>Qt::RightToLeft</enum>
34
+ </property>
35
+ <property name="text">
36
+ <string>Warning</string>
37
+ </property>
38
+ </widget>
39
+ </item>
40
+ <item row="1" column="1">
41
+ <widget class="QLabel" name="uiWarningTextLBL">
42
+ <property name="text">
43
+ <string>Choose an editor to enable Workboxs.</string>
44
+ </property>
45
+ </widget>
46
+ </item>
47
+ <item row="2" column="1">
48
+ <widget class="QLabel" name="uiWorkboxInfoLBL">
49
+ <property name="sizePolicy">
50
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
51
+ <horstretch>0</horstretch>
52
+ <verstretch>0</verstretch>
53
+ </sizepolicy>
54
+ </property>
55
+ <property name="text">
56
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;New editors are added by pip packages. A list of known pip editors can be found at &lt;a href=&quot;https://github.com/blurstudio/preditor&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/blurstudio/preditor&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
57
+ </property>
58
+ <property name="alignment">
59
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
60
+ </property>
61
+ <property name="wordWrap">
62
+ <bool>true</bool>
63
+ </property>
64
+ <property name="openExternalLinks">
65
+ <bool>true</bool>
66
+ </property>
67
+ </widget>
68
+ </item>
69
+ </layout>
70
+ </widget>
71
+ <resources/>
72
+ <connections>
73
+ <connection>
74
+ <sender>uiWorkboxEditorDDL</sender>
75
+ <signal>currentIndexChanged(int)</signal>
76
+ <receiver>Form</receiver>
77
+ <slot>refresh()</slot>
78
+ <hints>
79
+ <hint type="sourcelabel">
80
+ <x>506</x>
81
+ <y>23</y>
82
+ </hint>
83
+ <hint type="destinationlabel">
84
+ <x>535</x>
85
+ <y>32</y>
86
+ </hint>
87
+ </hints>
88
+ </connection>
89
+ </connections>
90
+ <slots>
91
+ <slot>refresh()</slot>
92
+ </slots>
93
+ </ui>
@@ -0,0 +1,74 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>uiPythonErrorMBOX</class>
4
+ <widget class="QDialog" name="uiPythonErrorMBOX">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>409</width>
10
+ <height>98</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>Dialog</string>
15
+ </property>
16
+ <layout class="QGridLayout" name="gridLayout">
17
+ <item row="0" column="0">
18
+ <layout class="QHBoxLayout" name="uiMainLYT">
19
+ <item>
20
+ <widget class="QLabel" name="uiIconLBL">
21
+ <property name="text">
22
+ <string>TextLabel</string>
23
+ </property>
24
+ </widget>
25
+ </item>
26
+ <item>
27
+ <layout class="QVBoxLayout" name="uiTextLYT">
28
+ <item>
29
+ <widget class="QLabel" name="uiErrorLBL">
30
+ <property name="text">
31
+ <string>TextLabel</string>
32
+ </property>
33
+ </widget>
34
+ </item>
35
+ <item>
36
+ <spacer name="uiHorizontalSPACE">
37
+ <property name="orientation">
38
+ <enum>Qt::Horizontal</enum>
39
+ </property>
40
+ <property name="sizeHint" stdset="0">
41
+ <size>
42
+ <width>40</width>
43
+ <height>20</height>
44
+ </size>
45
+ </property>
46
+ </spacer>
47
+ </item>
48
+ </layout>
49
+ </item>
50
+ </layout>
51
+ </item>
52
+ <item row="1" column="0">
53
+ <layout class="QHBoxLayout" name="uiButtonsLYT">
54
+ <item>
55
+ <widget class="QPushButton" name="uiLoggerBTN">
56
+ <property name="text">
57
+ <string>Show Logger</string>
58
+ </property>
59
+ </widget>
60
+ </item>
61
+ <item>
62
+ <widget class="QPushButton" name="uiIgnoreBTN">
63
+ <property name="text">
64
+ <string>Ignore</string>
65
+ </property>
66
+ </widget>
67
+ </item>
68
+ </layout>
69
+ </item>
70
+ </layout>
71
+ </widget>
72
+ <resources/>
73
+ <connections/>
74
+ </ui>