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,136 @@
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,
27
+ console=None,
28
+ core_name=None,
29
+ delayable_engine='default',
30
+ parent=None,
31
+ **kwargs,
32
+ ):
33
+ super(WorkboxTextEdit, self).__init__(
34
+ parent=parent, core_name=core_name, **kwargs
35
+ )
36
+ self.__set_console__(console)
37
+ self._encoding = None
38
+ highlight = CodeHighlighter(self, 'Python')
39
+ self.uiCodeHighlighter = highlight
40
+
41
+ def __auto_complete_enabled__(self):
42
+ pass
43
+
44
+ def __set_auto_complete_enabled__(self, state):
45
+ pass
46
+
47
+ def __clear__(self):
48
+ self.clear()
49
+ self.__set_last_saved_text__(self.__text__())
50
+
51
+ def __copy_indents_as_spaces__(self):
52
+ """When copying code, should it convert leading tabs to spaces?"""
53
+ return False
54
+
55
+ def __set_copy_indents_as_spaces__(self, state):
56
+ logger.info(
57
+ "WorkboxTextEdit does not support converting indents to spaces on copy."
58
+ )
59
+
60
+ def __cursor_position__(self):
61
+ """Returns the line and index of the cursor."""
62
+ cursor = self.textCursor()
63
+ sc = QTextCursor(self.document())
64
+ sc.setPosition(cursor.selectionStart())
65
+ return sc.blockNumber(), sc.positionInBlock()
66
+
67
+ def __font__(self):
68
+ return self.font()
69
+
70
+ def __set_font__(self, font):
71
+ metrics = QFontMetrics(font)
72
+ self.setTabStopDistance(metrics.horizontalAdvance(" ") * 4)
73
+ super(WorkboxTextEdit, self).setFont(font)
74
+
75
+ def __goto_line__(self, line):
76
+ cursor = QTextCursor(self.document().findBlockByLineNumber(line - 1))
77
+ self.setTextCursor(cursor)
78
+
79
+ def __indentations_use_tabs__(self):
80
+ return True
81
+
82
+ def __set_indentations_use_tabs__(self, state):
83
+ logger.info("WorkboxTextEdit does not support using spaces for tabs.")
84
+
85
+ def __margins_font__(self):
86
+ return QFont()
87
+
88
+ def __set_margins_font__(self, font):
89
+ pass
90
+
91
+ def __tab_width__(self):
92
+ # TODO: Implement custom tab widths
93
+ return 4
94
+
95
+ def __text__(self):
96
+ """Returns the text in this widget
97
+ Returns:
98
+ str: Returns the text in this widget
99
+ """
100
+ return self.toPlainText()
101
+
102
+ def __selected_text__(self, start_of_line=False, selectText=False):
103
+ cursor = self.textCursor()
104
+
105
+ # Get starting line number. Must set the cursor's position to the start of the
106
+ # selection, otherwise we may instead get the ending line number.
107
+ tempCursor = self.textCursor()
108
+ tempCursor.setPosition(tempCursor.selectionStart())
109
+ line = tempCursor.block().firstLineNumber()
110
+
111
+ # If no selection, return the current line
112
+ if cursor.selection().isEmpty():
113
+ text = cursor.block().text()
114
+
115
+ if selectText:
116
+ cursor.select(QTextCursor.SelectionType.LineUnderCursor)
117
+ self.setTextCursor(cursor)
118
+
119
+ return text, line
120
+
121
+ # Otherwise return the selected text
122
+ if start_of_line:
123
+ sc = QTextCursor(self.document())
124
+ sc.setPosition(cursor.selectionStart())
125
+ sc.movePosition(cursor.StartOfLine, sc.MoveAnchor)
126
+ sc.setPosition(cursor.selectionEnd(), sc.KeepAnchor)
127
+
128
+ return sc.selection().toPlainText(), line
129
+
130
+ return self.textCursor().selection().toPlainText(), line
131
+
132
+ def keyPressEvent(self, event):
133
+ if self.process_shortcut(event):
134
+ return
135
+ else:
136
+ super(WorkboxTextEdit, self).keyPressEvent(event)
@@ -0,0 +1,315 @@
1
+ from __future__ import absolute_import, print_function
2
+
3
+ import os
4
+ import re
5
+ from pathlib import Path
6
+
7
+ from Qt.QtCore import QEvent, Qt
8
+ from Qt.QtGui import QIcon
9
+ from Qt.QtWidgets import QAction, QMessageBox
10
+
11
+ from .. import core, resourcePath
12
+ from ..gui.workbox_mixin import WorkboxMixin
13
+ from ..scintilla import QsciScintilla
14
+ from ..scintilla.documenteditor import DocumentEditor, SearchOptions
15
+ from ..scintilla.finddialog import FindDialog
16
+
17
+
18
+ class WorkboxWidget(WorkboxMixin, DocumentEditor):
19
+ def __init__(
20
+ self,
21
+ parent=None,
22
+ console=None,
23
+ delayable_engine='default',
24
+ core_name=None,
25
+ **kwargs,
26
+ ):
27
+ self.__set_console__(console)
28
+ self._searchFlags = 0
29
+ self._searchText = ''
30
+ self._searchDialog = None
31
+
32
+ # initialize the super class
33
+ super(WorkboxWidget, self).__init__(
34
+ parent, delayable_engine=delayable_engine, core_name=core_name, **kwargs
35
+ )
36
+
37
+ # Store the software name so we can handle custom keyboard shortcuts based on
38
+ # software
39
+ self._software = core.objectName()
40
+ # Used to remove any trailing whitespace when running selected text
41
+ self.regex = re.compile(r'\s+$')
42
+ self.initShortcuts()
43
+
44
+ self._defaultLanguage = "Python"
45
+ self.setLanguage(self._defaultLanguage)
46
+ # Default to unix newlines
47
+ self.setEolMode(QsciScintilla.EolMode.EolUnix)
48
+ if hasattr(self.window(), "setWorkboxFontBasedOnConsole"):
49
+ self.window().setWorkboxFontBasedOnConsole()
50
+
51
+ def __auto_complete_enabled__(self):
52
+ return self.autoCompletionSource() == QsciScintilla.AutoCompletionSource.AcsAll
53
+
54
+ def __set_auto_complete_enabled__(self, state):
55
+ state = (
56
+ QsciScintilla.AutoCompletionSource.AcsAll
57
+ if state
58
+ else QsciScintilla.AutoCompletionSource.AcsNone
59
+ )
60
+ self.setAutoCompletionSource(state)
61
+
62
+ def __clear__(self):
63
+ self.clear()
64
+ self.__set_last_saved_text__(self.__text__())
65
+
66
+ def __comment_toggle__(self):
67
+ self.commentToggle()
68
+
69
+ def __copy_indents_as_spaces__(self):
70
+ return self.copyIndentsAsSpaces
71
+
72
+ def __set_copy_indents_as_spaces__(self, state):
73
+ self.copyIndentsAsSpaces = state
74
+
75
+ def __cursor_position__(self):
76
+ """Returns the line and index of the cursor."""
77
+ return self.getCursorPosition()
78
+
79
+ def __set_cursor_position__(self, line, index):
80
+ """Set the cursor to this line number and index"""
81
+ self.setCursorPosition(line, index)
82
+
83
+ def __check_for_save__(self):
84
+ if self.isModified():
85
+ result = QMessageBox.question(
86
+ self.window(),
87
+ 'Save changes to...',
88
+ 'Do you want to save your changes?',
89
+ QMessageBox.StandardButton.Yes
90
+ | QMessageBox.StandardButton.No
91
+ | QMessageBox.StandardButton.Cancel,
92
+ )
93
+ if result == QMessageBox.StandardButton.Yes:
94
+ return self.save()
95
+ elif result == QMessageBox.StandardButton.Cancel:
96
+ return False
97
+ return True
98
+
99
+ def eventFilter(self, object, event):
100
+ if event.type() == QEvent.Type.Close and not self.__check_for_save__():
101
+ event.ignore()
102
+ return True
103
+ return False
104
+
105
+ def execStandalone(self):
106
+ if self.__save__():
107
+ os.startfile(str(self.filename()))
108
+
109
+ def __filename__(self):
110
+ return self.filename()
111
+
112
+ def __set_filename__(self, filename):
113
+ self.set_filename(filename)
114
+
115
+ def __font__(self):
116
+ if self.lexer():
117
+ return self.lexer().font(0)
118
+ else:
119
+ return self.font()
120
+
121
+ def __set_font__(self, font):
122
+ self.documentFont = font
123
+ if self.lexer():
124
+ self.lexer().setFont(font)
125
+ else:
126
+ self.setFont(font)
127
+
128
+ def __goto_line__(self, line):
129
+ self.goToLine(line)
130
+
131
+ def __indentations_use_tabs__(self):
132
+ return self.indentationsUseTabs()
133
+
134
+ def __set_indentations_use_tabs__(self, state):
135
+ self.setIndentationsUseTabs(state)
136
+
137
+ def __insert_text__(self, txt):
138
+ self.insert(txt)
139
+
140
+ def __load__(self, filename):
141
+ if filename and Path(filename).is_file():
142
+ # This is overriding WorkboxMixin.__load__, make sure to base class
143
+ # method.
144
+ super().__load__(filename)
145
+
146
+ # DocumentEditor specific calls
147
+ font = self.__font__()
148
+ self.updateFilename(str(filename))
149
+ self.__set_font__(font)
150
+ self.setEolMode(self.detectEndLine(self.__text__()))
151
+
152
+ def __save__(self):
153
+ font = self.__font__()
154
+ super().__save__()
155
+ filename = self.__filename__()
156
+ if filename:
157
+ self.updateFilename(filename)
158
+ self.__set_font__(font)
159
+
160
+ def __margins_font__(self):
161
+ return self.marginsFont()
162
+
163
+ def __set_margins_font__(self, font):
164
+ self.setMarginsFont(font)
165
+
166
+ def __marker_add__(self, line):
167
+ try:
168
+ marker = self._marker
169
+ except AttributeError:
170
+ self._marker = self.markerDefine(QsciScintilla.MarkerSymbol.Circle)
171
+ marker = self._marker
172
+ self.markerAdd(line, marker)
173
+
174
+ def __marker_clear_all__(self):
175
+ try:
176
+ self.markerDeleteAll(self._marker)
177
+ except AttributeError:
178
+ # self._marker has not been created yet
179
+ pass
180
+
181
+ def __remove_selected_text__(self):
182
+ self.removeSelectedText()
183
+
184
+ def __selected_text__(self, start_of_line=False, selectText=False):
185
+ line, s, end, e = self.getSelection()
186
+
187
+ # Sometime self.getSelection returns values that equate to a non-existent
188
+ # selection, ie start and end are the same, so let's process it as if there is
189
+ # no selection
190
+ selectionIsEmpty = line == end and s == e
191
+ if line == -1 or selectionIsEmpty:
192
+ # Nothing is selected, return the current line of text
193
+ line, index = self.getCursorPosition()
194
+ txt = self.__text_part__(lineNum=line)
195
+
196
+ if selectText:
197
+ lineLength = len(txt.rstrip())
198
+ self.setSelection(line, 0, line, lineLength)
199
+
200
+ elif start_of_line:
201
+ ss = self.positionFromLineIndex(line, 0)
202
+ ee = self.positionFromLineIndex(end, e)
203
+ txt = self.__text_part__(start=ss, end=ee)
204
+ else:
205
+ txt = self.selectedText()
206
+ return self.regex.split(txt)[0], line
207
+
208
+ def __tab_width__(self):
209
+ return self.tabWidth()
210
+
211
+ def __set_tab_width__(self, width):
212
+ self.setTabWidth(width)
213
+
214
+ def __text__(self):
215
+ """Returns the text in this widget
216
+ Returns:
217
+ str: Returns the text in this widget
218
+ """
219
+ return self.text()
220
+
221
+ def keyPressEvent(self, event):
222
+ """Check for certain keyboard shortcuts, and handle them as needed,
223
+ otherwise pass the keyPress to the superclass.
224
+
225
+ NOTE! We handle the "shift+return" shortcut here, rather than the
226
+ QAction's shortcut, because the workbox will always intercept that
227
+ shortcut. So, we handle it here, and call the main window's
228
+ execSelected, which ultimately calls this workbox's __exec_selected__.
229
+
230
+ Also note, it would make sense to have ctrl+Enter also execute without
231
+ truncation, but no modifiers are registered when Enter is pressed (unlike
232
+ when Return is pressed), so this combination is not detectable.
233
+ """
234
+ tab_widget = self.__tab_widget__()
235
+ if tab_widget is not None:
236
+ tab_widget.tabBar().update()
237
+
238
+ if self.process_shortcut(event):
239
+ return
240
+ else:
241
+ # Send regular keystroke
242
+ super(WorkboxWidget, self).keyPressEvent(event)
243
+
244
+ def initShortcuts(self):
245
+ """Use this to set up shortcuts when the DocumentEditor"""
246
+ icon = QIcon(resourcePath('img/text-search-variant.png'))
247
+ self.uiFindACT = QAction(icon, 'Find...', self)
248
+ self.uiFindACT.setShortcut("Ctrl+F")
249
+ self.addAction(self.uiFindACT)
250
+
251
+ icon = QIcon(resourcePath('img/skip-previous.png'))
252
+ self.uiFindPrevACT = QAction(icon, 'Find Prev', self)
253
+ self.uiFindPrevACT.setShortcut("Ctrl+F3")
254
+ self.addAction(self.uiFindPrevACT)
255
+
256
+ icon = QIcon(resourcePath('img/skip-next.png'))
257
+ self.uiFindNextACT = QAction(icon, 'Find Next', self)
258
+ self.uiFindNextACT.setShortcut("F3")
259
+ self.addAction(self.uiFindNextACT)
260
+
261
+ self.uiSelectCurrentLineACT = QAction(icon, 'Select Line', self)
262
+ self.uiSelectCurrentLineACT.triggered.connect(self.expandCursorToLineSelection)
263
+ self.uiSelectCurrentLineACT.setShortcut('Ctrl+L')
264
+ self.addAction(self.uiSelectCurrentLineACT)
265
+
266
+ # create the search dialog and connect actions
267
+ self._searchDialog = FindDialog(self)
268
+ self._searchDialog.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False)
269
+ self.uiFindACT.triggered.connect(
270
+ lambda: self._searchDialog.search(self.searchText())
271
+ )
272
+ self.uiFindPrevACT.triggered.connect(
273
+ lambda: self.findPrev(self.searchText(), self.searchFlags())
274
+ )
275
+ self.uiFindNextACT.triggered.connect(
276
+ lambda: self.findNext(self.searchText(), self.searchFlags())
277
+ )
278
+
279
+ def searchFlags(self):
280
+ return self._searchFlags
281
+
282
+ def searchText(self):
283
+ if not self._searchDialog:
284
+ return ''
285
+ # refresh the search text unless we are using regular expressions
286
+ if (
287
+ not self._searchDialog.isVisible()
288
+ and not self._searchFlags & SearchOptions.QRegExp
289
+ ):
290
+ txt = self.selectedText()
291
+ if txt:
292
+ self._searchText = txt
293
+ return self._searchText
294
+
295
+ def setSearchFlags(self, flags):
296
+ self._searchFlags = flags
297
+
298
+ def setSearchText(self, txt):
299
+ self._searchText = txt
300
+
301
+ def showMenu(self, pos):
302
+ menu = super(WorkboxWidget, self).showMenu(pos, popup=False)
303
+ menu.addSeparator()
304
+ submenu = menu.addMenu('Options')
305
+ act = submenu.addAction('Toggle end line visibility')
306
+ act.setCheckable(True)
307
+ act.setChecked(self.eolVisibility())
308
+ act.triggered.connect(self.setEolVisibility)
309
+
310
+ act = submenu.addAction('Show Whitespace')
311
+ act.setCheckable(True)
312
+ act.setChecked(self.showWhitespaces())
313
+ act.triggered.connect(self.setShowWhitespaces)
314
+
315
+ menu.popup(self._clickPos)
@@ -0,0 +1,55 @@
1
+ from __future__ import absolute_import
2
+
3
+ import json
4
+ import logging
5
+ import logging.config
6
+ import os
7
+
8
+ from . import utils
9
+ from .prefs import prefs_path
10
+
11
+
12
+ class LoggingConfig(object):
13
+ def __init__(self, core_name, version=1, disable_existing_loggers=False):
14
+ self._filename = None
15
+ self.cfg = {
16
+ 'version': version,
17
+ 'disable_existing_loggers': disable_existing_loggers,
18
+ }
19
+ self.core_name = core_name
20
+
21
+ def add_logger(self, name, logger):
22
+ if not logger.level:
23
+ # No need to record a logger that is inheriting its logging level
24
+ return
25
+
26
+ # Build the required dictionaries
27
+ loggers = self.cfg.setdefault('loggers', {})
28
+ log = loggers.setdefault(name, {})
29
+ log['level'] = logger.level
30
+
31
+ def build(self):
32
+ self.add_logger("", logging.root)
33
+ for name, logger in logging.root.manager.loggerDict.items():
34
+ if not isinstance(logger, logging.PlaceHolder):
35
+ self.add_logger(name, logger)
36
+
37
+ @property
38
+ def filename(self):
39
+ if self._filename:
40
+ return self._filename
41
+
42
+ self._filename = prefs_path('logging_prefs.json', core_name=self.core_name)
43
+ return self._filename
44
+
45
+ def load(self):
46
+ if not os.path.exists(self.filename):
47
+ return False
48
+
49
+ self.cfg = utils.Json(self.filename).load()
50
+ logging.config.dictConfig(self.cfg)
51
+ return True
52
+
53
+ def save(self):
54
+ with open(self.filename, 'w') as fle:
55
+ json.dump(self.cfg, fle, indent=4)