PrEditor 1.2.0__py3-none-any.whl → 1.4.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.
Potentially problematic release.
This version of PrEditor might be problematic. Click here for more details.
- preditor/gui/console.py +17 -0
- preditor/gui/drag_tab_bar.py +4 -1
- preditor/gui/group_tab_widget/__init__.py +42 -19
- preditor/gui/group_tab_widget/grouped_tab_widget.py +26 -4
- preditor/gui/group_tab_widget/one_tab_widget.py +42 -0
- preditor/gui/logger_window_plugin.py +3 -0
- preditor/gui/loggerwindow.py +43 -47
- preditor/gui/ui/loggerwindow.ui +11 -1
- preditor/gui/workbox_mixin.py +102 -4
- preditor/gui/workbox_text_edit.py +2 -2
- preditor/gui/workboxwidget.py +9 -4
- preditor/scintilla/documenteditor.py +64 -20
- preditor/version.py +3 -3
- {preditor-1.2.0.dist-info → preditor-1.4.0.dist-info}/METADATA +1 -1
- {preditor-1.2.0.dist-info → preditor-1.4.0.dist-info}/RECORD +19 -19
- {preditor-1.2.0.dist-info → preditor-1.4.0.dist-info}/WHEEL +0 -0
- {preditor-1.2.0.dist-info → preditor-1.4.0.dist-info}/entry_points.txt +0 -0
- {preditor-1.2.0.dist-info → preditor-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {preditor-1.2.0.dist-info → preditor-1.4.0.dist-info}/top_level.txt +0 -0
preditor/gui/console.py
CHANGED
|
@@ -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")
|
preditor/gui/drag_tab_bar.py
CHANGED
|
@@ -139,8 +139,11 @@ class DragTabBar(QTabBar):
|
|
|
139
139
|
"""Used by the tab_menu to rename the tab at index `_context_menu_tab`."""
|
|
140
140
|
if self._context_menu_tab != -1:
|
|
141
141
|
current = self.tabText(self._context_menu_tab)
|
|
142
|
-
msg = 'Rename the {} tab to:'.format(current)
|
|
142
|
+
msg = 'Rename the {} tab to (new name must be unique):'.format(current)
|
|
143
|
+
|
|
143
144
|
name, success = QInputDialog.getText(self, 'Rename Tab', msg, text=current)
|
|
145
|
+
name = self.parent().get_next_available_tab_name(name)
|
|
146
|
+
|
|
144
147
|
if success:
|
|
145
148
|
self.setTabText(self._context_menu_tab, name)
|
|
146
149
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import absolute_import
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import re
|
|
5
4
|
|
|
6
5
|
from Qt.QtCore import Qt
|
|
7
6
|
from Qt.QtGui import QIcon
|
|
@@ -46,6 +45,9 @@ class GroupTabWidget(OneTabWidget):
|
|
|
46
45
|
self.editor_cls = WorkboxTextEdit
|
|
47
46
|
self.core_name = core_name
|
|
48
47
|
self.setStyleSheet(DEFAULT_STYLE_SHEET)
|
|
48
|
+
|
|
49
|
+
self.default_title = 'Group01'
|
|
50
|
+
|
|
49
51
|
corner = QWidget(self)
|
|
50
52
|
lyt = QHBoxLayout(corner)
|
|
51
53
|
lyt.setSpacing(0)
|
|
@@ -69,7 +71,7 @@ class GroupTabWidget(OneTabWidget):
|
|
|
69
71
|
self.uiCornerBTN = corner
|
|
70
72
|
self.setCornerWidget(self.uiCornerBTN, Qt.Corner.TopRightCorner)
|
|
71
73
|
|
|
72
|
-
def add_new_tab(self, group, title=
|
|
74
|
+
def add_new_tab(self, group, title=None, prefs=None):
|
|
73
75
|
"""Adds a new tab to the requested group, creating the group if the group
|
|
74
76
|
doesn't exist.
|
|
75
77
|
|
|
@@ -80,9 +82,6 @@ class GroupTabWidget(OneTabWidget):
|
|
|
80
82
|
If True is passed, then the current group tab is used.
|
|
81
83
|
title (str, optional): The name to give the newly created tab inside
|
|
82
84
|
the group.
|
|
83
|
-
group_fmt(str, optional): If None is passed to group, this string is
|
|
84
|
-
used to search for existing tabs to calculate the last number
|
|
85
|
-
and generate the new group tab name.
|
|
86
85
|
|
|
87
86
|
Returns:
|
|
88
87
|
GroupedTabWidget: The tab group for this group.
|
|
@@ -90,21 +89,14 @@ class GroupTabWidget(OneTabWidget):
|
|
|
90
89
|
"""
|
|
91
90
|
parent = None
|
|
92
91
|
if not group:
|
|
93
|
-
|
|
94
|
-
group_fmt = r'Group {}'
|
|
95
|
-
last = 0
|
|
96
|
-
for i in range(self.count()):
|
|
97
|
-
match = re.match(group_fmt.format(r'(\d+)'), self.tabText(i))
|
|
98
|
-
if match:
|
|
99
|
-
last = max(last, int(match.group(1)))
|
|
100
|
-
group = group_fmt.format(last + 1)
|
|
92
|
+
group = self.get_next_available_tab_name(self.default_title)
|
|
101
93
|
elif group is True:
|
|
102
94
|
group = self.currentIndex()
|
|
103
95
|
if isinstance(group, int):
|
|
104
96
|
group_title = self.tabText(group)
|
|
105
97
|
parent = self.widget(group)
|
|
106
98
|
elif isinstance(group, str):
|
|
107
|
-
group_title = group
|
|
99
|
+
group_title = group.replace(" ", "_")
|
|
108
100
|
index = self.index_for_text(group)
|
|
109
101
|
if index != -1:
|
|
110
102
|
parent = self.widget(index)
|
|
@@ -146,7 +138,7 @@ class GroupTabWidget(OneTabWidget):
|
|
|
146
138
|
self,
|
|
147
139
|
'Close all editors under this tab?',
|
|
148
140
|
'Are you sure you want to close all tabs under the "{}" tab?'.format(
|
|
149
|
-
self.tabText(
|
|
141
|
+
self.tabText(index)
|
|
150
142
|
),
|
|
151
143
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel,
|
|
152
144
|
)
|
|
@@ -154,11 +146,11 @@ class GroupTabWidget(OneTabWidget):
|
|
|
154
146
|
# Clean up all temp files created by this group's editors if they
|
|
155
147
|
# are not using actual saved files.
|
|
156
148
|
tab_widget = self.widget(self.currentIndex())
|
|
157
|
-
for
|
|
158
|
-
editor = tab_widget.widget(
|
|
149
|
+
for editor_index in range(tab_widget.count()):
|
|
150
|
+
editor = tab_widget.widget(editor_index)
|
|
159
151
|
editor.__remove_tempfile__()
|
|
160
152
|
|
|
161
|
-
super(GroupTabWidget, self).close_tab(
|
|
153
|
+
super(GroupTabWidget, self).close_tab(index)
|
|
162
154
|
|
|
163
155
|
def current_groups_widget(self):
|
|
164
156
|
"""Returns the current widget of the currently selected group or None."""
|
|
@@ -166,7 +158,8 @@ class GroupTabWidget(OneTabWidget):
|
|
|
166
158
|
if editor_tab:
|
|
167
159
|
return editor_tab.currentWidget()
|
|
168
160
|
|
|
169
|
-
def default_tab(self, title=
|
|
161
|
+
def default_tab(self, title=None, prefs=None):
|
|
162
|
+
title = title or self.default_title
|
|
170
163
|
widget = GroupedTabWidget(
|
|
171
164
|
parent=self,
|
|
172
165
|
editor_kwargs=self.editor_kwargs,
|
|
@@ -223,6 +216,8 @@ class GroupTabWidget(OneTabWidget):
|
|
|
223
216
|
group_name = group['name']
|
|
224
217
|
tab_widget = None
|
|
225
218
|
|
|
219
|
+
group_name = self.get_next_available_tab_name(group_name)
|
|
220
|
+
|
|
226
221
|
for tab in group.get('tabs', []):
|
|
227
222
|
# Only add this tab if, there is data on disk to load. The user can
|
|
228
223
|
# open multiple instances of PrEditor using the same prefs. The
|
|
@@ -323,3 +318,31 @@ class GroupTabWidget(OneTabWidget):
|
|
|
323
318
|
tab_widget = self.currentWidget()
|
|
324
319
|
tab_widget.setCurrentIndex(editor)
|
|
325
320
|
return tab_widget.currentWidget()
|
|
321
|
+
|
|
322
|
+
def set_current_groups_from_workbox(self, workbox):
|
|
323
|
+
"""Make the specified workbox the current widget. If the workbox is not
|
|
324
|
+
found, the current widget is not changed.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
workbox (WorkboxMixin): The workbox to make current.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
success (bool): Whether the workbox was found and made the current
|
|
331
|
+
widget
|
|
332
|
+
"""
|
|
333
|
+
workbox_infos = self.all_widgets()
|
|
334
|
+
found_info = None
|
|
335
|
+
for workbox_info in workbox_infos:
|
|
336
|
+
if workbox_info[0] == workbox:
|
|
337
|
+
found_info = workbox_info
|
|
338
|
+
break
|
|
339
|
+
if found_info:
|
|
340
|
+
workbox = workbox_info[0]
|
|
341
|
+
group_idx = workbox_info[-2]
|
|
342
|
+
editor_idx = workbox_info[-1]
|
|
343
|
+
|
|
344
|
+
self.setCurrentIndex(group_idx)
|
|
345
|
+
tab_widget = self.currentWidget()
|
|
346
|
+
tab_widget.setCurrentIndex(editor_idx)
|
|
347
|
+
|
|
348
|
+
return bool(found_info)
|
|
@@ -27,7 +27,12 @@ class GroupedTabWidget(OneTabWidget):
|
|
|
27
27
|
self.uiCornerBTN.released.connect(lambda: self.add_new_editor())
|
|
28
28
|
self.setCornerWidget(self.uiCornerBTN, Qt.Corner.TopRightCorner)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
self.default_title = "Workbox01"
|
|
31
|
+
|
|
32
|
+
def add_new_editor(self, title=None, prefs=None):
|
|
33
|
+
title = title or self.default_title
|
|
34
|
+
|
|
35
|
+
title = self.get_next_available_tab_name(title)
|
|
31
36
|
editor, title = self.default_tab(title)
|
|
32
37
|
index = self.addTab(editor, title)
|
|
33
38
|
self.setCurrentIndex(index)
|
|
@@ -45,11 +50,18 @@ class GroupedTabWidget(OneTabWidget):
|
|
|
45
50
|
self, 'Tab can not be closed.', msg, QMessageBox.StandardButton.Ok
|
|
46
51
|
)
|
|
47
52
|
return
|
|
53
|
+
|
|
54
|
+
workbox = self.widget(index)
|
|
55
|
+
name = workbox.__workbox_name__()
|
|
56
|
+
msg = (
|
|
57
|
+
f"Would you like to donate the contents of tab\n{name}\nto the "
|
|
58
|
+
"/dev/null fund for wayward code?"
|
|
59
|
+
)
|
|
60
|
+
|
|
48
61
|
ret = QMessageBox.question(
|
|
49
62
|
self,
|
|
50
63
|
'Donate to the cause?',
|
|
51
|
-
|
|
52
|
-
"for wayward code?",
|
|
64
|
+
msg,
|
|
53
65
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel,
|
|
54
66
|
)
|
|
55
67
|
if ret == QMessageBox.StandardButton.Yes:
|
|
@@ -59,7 +71,8 @@ class GroupedTabWidget(OneTabWidget):
|
|
|
59
71
|
|
|
60
72
|
super(GroupedTabWidget, self).close_tab(index)
|
|
61
73
|
|
|
62
|
-
def default_tab(self, title=
|
|
74
|
+
def default_tab(self, title=None, prefs=None):
|
|
75
|
+
title = title or self.default_title
|
|
63
76
|
kwargs = self.editor_kwargs if self.editor_kwargs else {}
|
|
64
77
|
editor = self.editor_cls(parent=self, core_name=self.core_name, **kwargs)
|
|
65
78
|
return editor, title
|
|
@@ -76,5 +89,14 @@ class GroupedTabWidget(OneTabWidget):
|
|
|
76
89
|
if hasattr(self.window(), "setWorkboxFontBasedOnConsole"):
|
|
77
90
|
self.window().setWorkboxFontBasedOnConsole()
|
|
78
91
|
|
|
92
|
+
def tab_widget(self):
|
|
93
|
+
"""Return the tab widget which contains this group tab
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
self._tab_widget (GroupTabWidget): The tab widget which contains
|
|
97
|
+
this workbox
|
|
98
|
+
"""
|
|
99
|
+
return self.parent().parent()
|
|
100
|
+
|
|
79
101
|
def update_closable_tabs(self):
|
|
80
102
|
self.setTabsClosable(self.count() != 1)
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
from __future__ import absolute_import
|
|
2
2
|
|
|
3
|
+
import re
|
|
4
|
+
|
|
3
5
|
from Qt.QtWidgets import QTabWidget
|
|
4
6
|
|
|
7
|
+
TAB_ITERATION_PATTERN = re.compile(r"(\d+)(?!.*\d)")
|
|
8
|
+
|
|
5
9
|
|
|
6
10
|
class OneTabWidget(QTabWidget):
|
|
7
11
|
"""A QTabWidget that shows the close button only if there is more than one
|
|
@@ -17,6 +21,44 @@ class OneTabWidget(QTabWidget):
|
|
|
17
21
|
super(OneTabWidget, self).__init__(*args, **kwargs)
|
|
18
22
|
self.tabCloseRequested.connect(self.close_tab)
|
|
19
23
|
|
|
24
|
+
def get_next_available_tab_name(self, name):
|
|
25
|
+
"""Get the next available tab name, incrementing an iteration if needed.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
name (str): The desired name
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
name (str): The name, or updated name if needed
|
|
32
|
+
"""
|
|
33
|
+
name = name.replace(" ", "_")
|
|
34
|
+
|
|
35
|
+
existing_names = [self.tabText(i) for i in range(self.count())]
|
|
36
|
+
|
|
37
|
+
# Use regex to find the last set of digits. If found, the base name is
|
|
38
|
+
# a slice of name minus the digits string. Otherwise, the base name is
|
|
39
|
+
# the full name and iteration is zero.
|
|
40
|
+
match = TAB_ITERATION_PATTERN.search(name)
|
|
41
|
+
if match:
|
|
42
|
+
# We found trailing digits, so slice to get base name, and convert
|
|
43
|
+
# iteration to int
|
|
44
|
+
iter_str = match.group()
|
|
45
|
+
base = name[: -len(iter_str)]
|
|
46
|
+
iteration = int(iter_str)
|
|
47
|
+
else:
|
|
48
|
+
# No trailing digits found, so base name is full name and iteration
|
|
49
|
+
# is zero.
|
|
50
|
+
base = name
|
|
51
|
+
iteration = 0
|
|
52
|
+
|
|
53
|
+
if name in existing_names:
|
|
54
|
+
for _ in range(99):
|
|
55
|
+
iteration += 1
|
|
56
|
+
new_iter_str = str(iteration).zfill(2)
|
|
57
|
+
name = base + new_iter_str
|
|
58
|
+
if name not in existing_names:
|
|
59
|
+
break
|
|
60
|
+
return name
|
|
61
|
+
|
|
20
62
|
def addTab(self, *args, **kwargs): # noqa: N802
|
|
21
63
|
ret = super(OneTabWidget, self).addTab(*args, **kwargs)
|
|
22
64
|
self.update_closable_tabs()
|
preditor/gui/loggerwindow.py
CHANGED
|
@@ -48,6 +48,7 @@ from .completer import CompleterMode
|
|
|
48
48
|
from .level_buttons import LoggingLevelButton
|
|
49
49
|
from .set_text_editor_path_dialog import SetTextEditorPathDialog
|
|
50
50
|
from .status_label import StatusLabel
|
|
51
|
+
from .workbox_mixin import WorkboxName
|
|
51
52
|
|
|
52
53
|
logger = logging.getLogger(__name__)
|
|
53
54
|
|
|
@@ -59,31 +60,6 @@ class WorkboxPages:
|
|
|
59
60
|
Workboxes = 1
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
class WorkboxName(str):
|
|
63
|
-
"""The joined name of a workbox `group/workbox` with access to its parts.
|
|
64
|
-
|
|
65
|
-
This subclass provides properties for the group and workbox values separately.
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
def __new__(cls, group, workbox):
|
|
69
|
-
txt = "/".join((group, workbox))
|
|
70
|
-
ret = super().__new__(cls, txt)
|
|
71
|
-
# Preserve the imitable nature of str's by using properties without setters.
|
|
72
|
-
ret._group = group
|
|
73
|
-
ret._workbox = workbox
|
|
74
|
-
return ret
|
|
75
|
-
|
|
76
|
-
@property
|
|
77
|
-
def group(self):
|
|
78
|
-
"""The tab name of the group tab that contains the workbox."""
|
|
79
|
-
return self._group
|
|
80
|
-
|
|
81
|
-
@property
|
|
82
|
-
def workbox(self):
|
|
83
|
-
"""The workbox of the tab for this workbox inside of the group."""
|
|
84
|
-
return self._workbox
|
|
85
|
-
|
|
86
|
-
|
|
87
63
|
class LoggerWindow(Window):
|
|
88
64
|
_instance = None
|
|
89
65
|
styleSheetChanged = Signal(str)
|
|
@@ -93,9 +69,7 @@ class LoggerWindow(Window):
|
|
|
93
69
|
self.name = name if name else get_core_name()
|
|
94
70
|
self._stylesheet = 'Bright'
|
|
95
71
|
|
|
96
|
-
|
|
97
|
-
self.statusTimer = QTimer()
|
|
98
|
-
self.statusTimer.setSingleShot(True)
|
|
72
|
+
self.setupStatusTimer()
|
|
99
73
|
|
|
100
74
|
# Store the previous time a font-resize wheel event was triggered to prevent
|
|
101
75
|
# rapid-fire WheelEvents. Initialize to the current time.
|
|
@@ -292,10 +266,9 @@ class LoggerWindow(Window):
|
|
|
292
266
|
|
|
293
267
|
self.dont_ask_again = []
|
|
294
268
|
|
|
295
|
-
# Load any plugins
|
|
296
|
-
self.
|
|
297
|
-
|
|
298
|
-
self.plugins[name] = plugin(self)
|
|
269
|
+
# Load any plugins, and set window title
|
|
270
|
+
self.loadPlugins()
|
|
271
|
+
self.setWindowTitle(self.defineWindowTitle())
|
|
299
272
|
|
|
300
273
|
self.restorePrefs()
|
|
301
274
|
|
|
@@ -308,17 +281,6 @@ class LoggerWindow(Window):
|
|
|
308
281
|
action.triggered.connect(partial(self.setStyleSheet, style_name))
|
|
309
282
|
|
|
310
283
|
self.uiConsoleTOOLBAR.show()
|
|
311
|
-
loggerName = QApplication.instance().translate(
|
|
312
|
-
'PrEditorWindow', DEFAULT_CORE_NAME
|
|
313
|
-
)
|
|
314
|
-
self.setWindowTitle(
|
|
315
|
-
'{} - {} - {} {}-bit'.format(
|
|
316
|
-
loggerName,
|
|
317
|
-
self.name,
|
|
318
|
-
'{}.{}.{}'.format(*sys.version_info[:3]),
|
|
319
|
-
osystem.getPointerSize(),
|
|
320
|
-
)
|
|
321
|
-
)
|
|
322
284
|
|
|
323
285
|
self.setWorkboxFontBasedOnConsole()
|
|
324
286
|
self.setEditorChooserFontBasedOnConsole()
|
|
@@ -359,6 +321,29 @@ class LoggerWindow(Window):
|
|
|
359
321
|
|
|
360
322
|
self.update_workbox_stack()
|
|
361
323
|
|
|
324
|
+
def loadPlugins(self):
|
|
325
|
+
"""Load any plugins that modify the LoggerWindow."""
|
|
326
|
+
self.plugins = {}
|
|
327
|
+
for name, plugin in plugins.loggerwindow():
|
|
328
|
+
if name not in self.plugins:
|
|
329
|
+
self.plugins[name] = plugin(self)
|
|
330
|
+
|
|
331
|
+
def defineWindowTitle(self):
|
|
332
|
+
"""Define the window title, including and info plugins may add."""
|
|
333
|
+
|
|
334
|
+
# Define the title
|
|
335
|
+
loggerName = QApplication.instance().translate(
|
|
336
|
+
'PrEditorWindow', DEFAULT_CORE_NAME
|
|
337
|
+
)
|
|
338
|
+
pyVersion = '{}.{}.{}'.format(*sys.version_info[:3])
|
|
339
|
+
size = osystem.getPointerSize()
|
|
340
|
+
title = f"{loggerName} - {self.name} - {pyVersion} {size}-bit"
|
|
341
|
+
|
|
342
|
+
# Add any info plugins may add to title
|
|
343
|
+
for _name, plugin in self.plugins.items():
|
|
344
|
+
title = plugin.updateWindowTitle(title)
|
|
345
|
+
return title
|
|
346
|
+
|
|
362
347
|
def comment_toggle(self):
|
|
363
348
|
self.current_workbox().__comment_toggle__()
|
|
364
349
|
|
|
@@ -815,6 +800,7 @@ class LoggerWindow(Window):
|
|
|
815
800
|
'uiStatusLbl_limit': self.uiStatusLBL.limit(),
|
|
816
801
|
'textEditorPath': self.textEditorPath,
|
|
817
802
|
'textEditorCmdTempl': self.textEditorCmdTempl,
|
|
803
|
+
'uiSeparateTracebackACT': self.uiSeparateTracebackACT.isChecked(),
|
|
818
804
|
'currentStyleSheet': self._stylesheet,
|
|
819
805
|
'flash_time': self.uiConsoleTXT.flash_time,
|
|
820
806
|
'find_files_regex': self.uiFindInWorkboxesWGT.uiRegexBTN.isChecked(),
|
|
@@ -967,6 +953,8 @@ class LoggerWindow(Window):
|
|
|
967
953
|
self.textEditorPath = pref.get('textEditorPath', defaultExePath)
|
|
968
954
|
self.textEditorCmdTempl = pref.get('textEditorCmdTempl', defaultCmd)
|
|
969
955
|
|
|
956
|
+
self.uiSeparateTracebackACT.setChecked(pref.get('uiSeparateTracebackACT', True))
|
|
957
|
+
|
|
970
958
|
self.uiWordWrapACT.setChecked(pref.get('wordWrap', True))
|
|
971
959
|
self.setWordWrap(self.uiWordWrapACT.isChecked())
|
|
972
960
|
self.uiClearBeforeRunningACT.setChecked(pref.get('clearBeforeRunning', False))
|
|
@@ -1041,16 +1029,24 @@ class LoggerWindow(Window):
|
|
|
1041
1029
|
self.uiStatusLBL.setText(txt)
|
|
1042
1030
|
self.uiMenuBar.adjustSize()
|
|
1043
1031
|
|
|
1032
|
+
def setupStatusTimer(self):
|
|
1033
|
+
# Create timer to autohide status messages
|
|
1034
|
+
self.statusTimer = QTimer()
|
|
1035
|
+
self.statusTimer.setSingleShot(True)
|
|
1036
|
+
self.statusTimer.setInterval(2000)
|
|
1037
|
+
self.statusTimer.timeout.connect(self.clearStatusText)
|
|
1038
|
+
|
|
1044
1039
|
def clearStatusText(self):
|
|
1045
1040
|
"""Clear any displayed status text"""
|
|
1046
1041
|
self.uiStatusLBL.clear()
|
|
1047
1042
|
self.uiMenuBar.adjustSize()
|
|
1048
1043
|
|
|
1049
1044
|
def autoHideStatusText(self):
|
|
1050
|
-
"""Set timer to automatically clear status text
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1045
|
+
"""Set timer to automatically clear status text.
|
|
1046
|
+
|
|
1047
|
+
If timer is already running, it will be automatically stopped first (We can't
|
|
1048
|
+
use static method QTimer.singleShot for this)
|
|
1049
|
+
"""
|
|
1054
1050
|
self.statusTimer.start()
|
|
1055
1051
|
|
|
1056
1052
|
def setStyleSheet(self, stylesheet, recordPrefs=True):
|
preditor/gui/ui/loggerwindow.ui
CHANGED
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
<x>0</x>
|
|
93
93
|
<y>0</y>
|
|
94
94
|
<width>796</width>
|
|
95
|
-
<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>
|
preditor/gui/workbox_mixin.py
CHANGED
|
@@ -12,6 +12,44 @@ from Qt.QtWidgets import QStackedWidget
|
|
|
12
12
|
from ..prefs import prefs_path
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
class WorkboxName(str):
|
|
16
|
+
"""The joined name of a workbox `group/workbox` with access to its parts.
|
|
17
|
+
|
|
18
|
+
You may pass the group, workbox, or the fully formed workbox name:
|
|
19
|
+
examples:
|
|
20
|
+
workboxName = WorkboxName("Group01", "Workbox05")
|
|
21
|
+
workboxName = WorkboxName("Group01/Workbox05")
|
|
22
|
+
This subclass provides properties for the group and workbox values separately.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __new__(cls, name, sub_name=None):
|
|
26
|
+
if sub_name is not None:
|
|
27
|
+
txt = "/".join((name, sub_name))
|
|
28
|
+
else:
|
|
29
|
+
txt = name
|
|
30
|
+
try:
|
|
31
|
+
name, sub_name = txt.split("/")
|
|
32
|
+
except ValueError:
|
|
33
|
+
msg = "A fully formed name, or a group and name, must be passed in."
|
|
34
|
+
raise ValueError(msg) from None
|
|
35
|
+
|
|
36
|
+
ret = super().__new__(cls, txt)
|
|
37
|
+
# Preserve the imitable nature of str's by using properties without setters.
|
|
38
|
+
ret._group = name
|
|
39
|
+
ret._workbox = sub_name
|
|
40
|
+
return ret
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def group(self):
|
|
44
|
+
"""The tab name of the group tab that contains the workbox."""
|
|
45
|
+
return self._group
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def workbox(self):
|
|
49
|
+
"""The workbox of the tab for this workbox inside of the group."""
|
|
50
|
+
return self._workbox
|
|
51
|
+
|
|
52
|
+
|
|
15
53
|
class WorkboxMixin(object):
|
|
16
54
|
_warning_text = None
|
|
17
55
|
"""When a user is picking this Workbox class, show a warning with this text."""
|
|
@@ -26,6 +64,16 @@ class WorkboxMixin(object):
|
|
|
26
64
|
self._tempfile = tempfile
|
|
27
65
|
self.core_name = core_name
|
|
28
66
|
|
|
67
|
+
self._tab_widget = parent
|
|
68
|
+
|
|
69
|
+
def __tab_widget__(self):
|
|
70
|
+
"""Return the tab widget which contains this workbox
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
GroupedTabWidget: The tab widget which contains this workbox
|
|
74
|
+
"""
|
|
75
|
+
return self._tab_widget
|
|
76
|
+
|
|
29
77
|
def __auto_complete_enabled__(self):
|
|
30
78
|
raise NotImplementedError("Mixin method not overridden.")
|
|
31
79
|
|
|
@@ -84,8 +132,8 @@ class WorkboxMixin(object):
|
|
|
84
132
|
txt = '\n' * line + txt
|
|
85
133
|
|
|
86
134
|
# execute the code
|
|
87
|
-
|
|
88
|
-
ret, was_eval = self.__console__().executeString(txt, filename=
|
|
135
|
+
title = self.__workbox_trace_title__(selection=True)
|
|
136
|
+
ret, was_eval = self.__console__().executeString(txt, filename=title)
|
|
89
137
|
if was_eval:
|
|
90
138
|
# If the selected code was a statement print the result of the statement.
|
|
91
139
|
ret = repr(ret)
|
|
@@ -145,13 +193,63 @@ class WorkboxMixin(object):
|
|
|
145
193
|
|
|
146
194
|
return group, editor
|
|
147
195
|
|
|
148
|
-
def
|
|
196
|
+
def __workbox_trace_title__(self, selection=False):
|
|
149
197
|
title = "WorkboxSelection" if selection else "Workbox"
|
|
150
198
|
group, editor = self.__group_tab_index__()
|
|
151
199
|
if group == -1 or editor == -1:
|
|
152
200
|
return '<{}>'.format(title)
|
|
153
201
|
else:
|
|
154
|
-
|
|
202
|
+
name = self.__workbox_name__()
|
|
203
|
+
return '<{}>:{}'.format(title, name)
|
|
204
|
+
|
|
205
|
+
def __workbox_name__(self, workbox=None):
|
|
206
|
+
"""Returns the name for this workbox or a given workbox.
|
|
207
|
+
The name is the group tab text and the workbox tab text joined by a `/`"""
|
|
208
|
+
workboxTAB = self.window().uiWorkboxTAB
|
|
209
|
+
group_name = None
|
|
210
|
+
workbox_name = None
|
|
211
|
+
|
|
212
|
+
if workbox:
|
|
213
|
+
grouped_tab_widget = workbox.__tab_widget__()
|
|
214
|
+
for group_idx in range(workboxTAB.count()):
|
|
215
|
+
# If a previous iteration determine workbox_name, bust out
|
|
216
|
+
if workbox_name:
|
|
217
|
+
break
|
|
218
|
+
# Check if current group is the workboxes parent group
|
|
219
|
+
cur_group_widget = workboxTAB.widget(group_idx)
|
|
220
|
+
if cur_group_widget == grouped_tab_widget:
|
|
221
|
+
group_name = workboxTAB.tabText(group_idx)
|
|
222
|
+
|
|
223
|
+
# Found the group, now find workbox
|
|
224
|
+
for workbox_idx in range(cur_group_widget.count()):
|
|
225
|
+
cur_workbox_widget = cur_group_widget.widget(workbox_idx)
|
|
226
|
+
if cur_workbox_widget == workbox:
|
|
227
|
+
workbox_name = cur_group_widget.tabText(workbox_idx)
|
|
228
|
+
break
|
|
229
|
+
else:
|
|
230
|
+
grouped = self.__tab_widget__()
|
|
231
|
+
groupedTabBar = grouped.tabBar()
|
|
232
|
+
|
|
233
|
+
idx = -1
|
|
234
|
+
for idx in range(grouped.count()):
|
|
235
|
+
if grouped.widget(idx) == self:
|
|
236
|
+
break
|
|
237
|
+
workbox_name = groupedTabBar.tabText(idx)
|
|
238
|
+
|
|
239
|
+
group = grouped.tab_widget()
|
|
240
|
+
groupTabBar = group.tabBar()
|
|
241
|
+
idx = -1
|
|
242
|
+
for idx in range(group.count()):
|
|
243
|
+
if group.widget(idx) == grouped:
|
|
244
|
+
break
|
|
245
|
+
group_name = groupTabBar.tabText(idx)
|
|
246
|
+
|
|
247
|
+
# If both found, construct workbox name
|
|
248
|
+
if group_name and workbox_name:
|
|
249
|
+
name = WorkboxName(group_name, workbox_name)
|
|
250
|
+
else:
|
|
251
|
+
name = WorkboxName("", "")
|
|
252
|
+
return name
|
|
155
253
|
|
|
156
254
|
def __goto_line__(self, line):
|
|
157
255
|
raise NotImplementedError("Mixin method not overridden.")
|
|
@@ -57,8 +57,8 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
|
|
|
57
57
|
|
|
58
58
|
def __exec_all__(self):
|
|
59
59
|
txt = self.__text__().rstrip()
|
|
60
|
-
|
|
61
|
-
self.__console__().executeString(txt, 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()
|
preditor/gui/workboxwidget.py
CHANGED
|
@@ -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
|
-
|
|
77
|
-
self.__console__().executeString(txt, 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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
|
preditor/version.py
CHANGED
|
@@ -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.
|
|
32
|
-
__version_tuple__ = version_tuple = (1,
|
|
31
|
+
__version__ = version = '1.4.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 0)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g79cb36c80'
|
|
@@ -13,7 +13,7 @@ preditor/plugins.py,sha256=RAeyvdZxQsZY313ae5aAhahqpjuhaXJzDxPyLcR-09U,4401
|
|
|
13
13
|
preditor/prefs.py,sha256=BPtSsdv2yuiRpIaqEml9fxlVYKHNfqQ77hp5YIQRDBg,2172
|
|
14
14
|
preditor/settings.py,sha256=DV9_DbJorEnhdIvW15E7h7PswlQUsy0UlA8bXUYN0og,2206
|
|
15
15
|
preditor/streamhandler_helper.py,sha256=kiU6T9WqJ3JKTTKCa7IUU8brwK7zO5UUpEzLhEfKe44,1788
|
|
16
|
-
preditor/version.py,sha256=
|
|
16
|
+
preditor/version.py,sha256=6vbYTZLusVDz8j8nBu2-Zv-MBvhlzKtADFBJuoWUprg,712
|
|
17
17
|
preditor/weakref.py,sha256=b--KomFAHcMWr3DEAIN2j3XxRhjDWKw0WABXyn1nxDg,12177
|
|
18
18
|
preditor/cores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
preditor/cores/core.py,sha256=mdVXlEPDh8kIdOpMDqi8P1VaqfVvyu5cXBq_toONcaM,586
|
|
@@ -32,35 +32,35 @@ preditor/gui/__init__.py,sha256=DeOH5K4_M0YLNx1i7NRvwCgwjyjkre4vVwlr5OEMx9Q,3423
|
|
|
32
32
|
preditor/gui/app.py,sha256=EhVsVMr5C5WSKNDlxGawzg-3lbTJxDMLi2fPomECacM,5869
|
|
33
33
|
preditor/gui/codehighlighter.py,sha256=wUOgLDhcAQf72DSS65r9_RYdv6PVJwWFXTdOPvvps_A,6790
|
|
34
34
|
preditor/gui/completer.py,sha256=U2FBJA_ceFq_viGqPogncH-6vhrtTcpxAF61SUnaOJ8,7813
|
|
35
|
-
preditor/gui/console.py,sha256=
|
|
35
|
+
preditor/gui/console.py,sha256=BEvEU7yjjn1kz1BF9T7JlqXpLCP7pI5nP6Rbdh2P-os,36476
|
|
36
36
|
preditor/gui/dialog.py,sha256=fasmBDhN-B6uretbSQ3x1SxImsQLSKIMw4PC9B8BimI,6535
|
|
37
|
-
preditor/gui/drag_tab_bar.py,sha256=
|
|
37
|
+
preditor/gui/drag_tab_bar.py,sha256=EgEXdV4odNj_1_YiGP2kmpGKUaBPe75JTwudU8Xj-Gw,8113
|
|
38
38
|
preditor/gui/editor_chooser.py,sha256=lv1eY0UJOulX1l-P-ZQEoneYz6BNX2VkXEbg3GUu1ag,1991
|
|
39
39
|
preditor/gui/errordialog.py,sha256=cRtQ-l40kvQ9awRDqAjetwT8S4oD1iztPbEEly7GYBU,2075
|
|
40
40
|
preditor/gui/find_files.py,sha256=TtsjHXKWvwKrxHYZryB_NPANoFpMRlAxWJp1hA6Ny2I,4360
|
|
41
41
|
preditor/gui/level_buttons.py,sha256=h0pMMzp-ElwcN_qfR4EBQtXn1C666KVcnR9dMoixD3E,12597
|
|
42
42
|
preditor/gui/logger_window_handler.py,sha256=43-DxzuNJq6UV6Ofc4TKRt179Sf5AxDkVDGrtq_Knok,1571
|
|
43
|
-
preditor/gui/logger_window_plugin.py,sha256=
|
|
44
|
-
preditor/gui/loggerwindow.py,sha256=
|
|
43
|
+
preditor/gui/logger_window_plugin.py,sha256=Lj9Q8L82GjzZ21ZI5W0FCHhrPHNALIunT_C9ua15l2w,1272
|
|
44
|
+
preditor/gui/loggerwindow.py,sha256=u0FLCfS5NM8r31PJE0D-iLiq5j40hw46q8elIqnDDOM,54458
|
|
45
45
|
preditor/gui/newtabwidget.py,sha256=5aCWn9xAl5h1oZACqVuEsOAbzKTS2RegrLI41gROC8A,1971
|
|
46
46
|
preditor/gui/set_text_editor_path_dialog.py,sha256=bn8IeQHXPSU4PLYXQmSxKB1V8iuJaI1PA5aDJNgxXks,2292
|
|
47
47
|
preditor/gui/status_label.py,sha256=SlNRmPc28S4E2OFVmErv0DmZstk4011Q_7uLp43SF0A,3320
|
|
48
48
|
preditor/gui/suggest_path_quotes_dialog.py,sha256=QUJf_9hs8wOO6bFOr8_Z2xnNhSA8TfKFMOzheUqUDnY,1822
|
|
49
49
|
preditor/gui/window.py,sha256=6Ztjqb0Xfh8DsI7hBF4Rg-4-gWPZKTV4GRJiz3V8O6Q,5904
|
|
50
|
-
preditor/gui/workbox_mixin.py,sha256=
|
|
51
|
-
preditor/gui/workbox_text_edit.py,sha256=
|
|
52
|
-
preditor/gui/workboxwidget.py,sha256=
|
|
50
|
+
preditor/gui/workbox_mixin.py,sha256=s_JTCmR-_ZXcAuQ-jKsw_DQh08IAFr3SJONYE5bQRP8,18556
|
|
51
|
+
preditor/gui/workbox_text_edit.py,sha256=wrJcGqIJ2-5BqEcP_qVKNlWUD8Geo8IxrIXncnDG6yw,4472
|
|
52
|
+
preditor/gui/workboxwidget.py,sha256=7m2QzuOfoTuB2H9mODnwZ1npX0zI_1bjeQp3_Lh990s,10588
|
|
53
53
|
preditor/gui/fuzzy_search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
preditor/gui/fuzzy_search/fuzzy_search.py,sha256=zohr6oAE99FZFlLjqKZajBrdyJIYLW96rcCOy5Bn1i0,3714
|
|
55
|
-
preditor/gui/group_tab_widget/__init__.py,sha256=
|
|
55
|
+
preditor/gui/group_tab_widget/__init__.py,sha256=EalGlpDcinbI6WdwmG7BK94519rUHfzxA0qez-o4m6k,13637
|
|
56
56
|
preditor/gui/group_tab_widget/grouped_tab_menu.py,sha256=lopd3mjHJIE_5xLdlZL0ghuBzsYo36vO1OZE6L6tqbI,1288
|
|
57
57
|
preditor/gui/group_tab_widget/grouped_tab_models.py,sha256=duwEdtbvsJ1nPKFakrnY8QuCoBx4M7mOpB0_0Nrm6_Y,4027
|
|
58
|
-
preditor/gui/group_tab_widget/grouped_tab_widget.py,sha256=
|
|
59
|
-
preditor/gui/group_tab_widget/one_tab_widget.py,sha256=
|
|
58
|
+
preditor/gui/group_tab_widget/grouped_tab_widget.py,sha256=zIKr2oh_TgGokWmAFDIeyw6touH6vRo3N1MCnOyJQRM,3624
|
|
59
|
+
preditor/gui/group_tab_widget/one_tab_widget.py,sha256=XHIgZwO4g0jtY6rJExB7389vhuLJeKg9HwZnDM1V66k,3383
|
|
60
60
|
preditor/gui/ui/editor_chooser.ui,sha256=cYSVHK0A4-zst6JyDkrBZK9qcAontbhV4Mmnw5ps72E,2736
|
|
61
61
|
preditor/gui/ui/errordialog.ui,sha256=i7cVc28FPxA_b4Xa58W_xmRJ_1GFb5rgtUhR_gZcf4E,1831
|
|
62
62
|
preditor/gui/ui/find_files.ui,sha256=8mdD3Vg3ofRMChdKntxiDHO3JXHQSKjjY6OLY_1W5lc,3328
|
|
63
|
-
preditor/gui/ui/loggerwindow.ui,sha256=
|
|
63
|
+
preditor/gui/ui/loggerwindow.ui,sha256=dkfn2qY9nZeX7-7p9CMZh5W2Y83Tirn1ZeFAXjisquU,31580
|
|
64
64
|
preditor/gui/ui/set_text_editor_path_dialog.ui,sha256=VLBpTvGneXAi9RX1dRd6oPwKoZhQ_m5HO1j1qXPhTxc,5201
|
|
65
65
|
preditor/gui/ui/suggest_path_quotes_dialog.ui,sha256=0hcr7kEFmmMVEp7vv18mDpvWZ0zOrojlkTLhIWCFKww,5923
|
|
66
66
|
preditor/resource/environment_variables.html,sha256=-uWicgOkour-sxtY-crrjMiLMyJzAzshwUXKqSm6TmI,3134
|
|
@@ -116,7 +116,7 @@ preditor/resource/lang/python.json,sha256=CXiQh0jcgd-OCrM-s9IF7s4o-g5WRA4vDaAyTR
|
|
|
116
116
|
preditor/resource/stylesheet/Bright.css,sha256=SfnPRBqfqEL4IF8RGt9PpLX_cSiGpfG9Q2hE1F9uTsk,2480
|
|
117
117
|
preditor/resource/stylesheet/Dark.css,sha256=Sige7beBhRyfav9_mXvn-LhksxbX0_WEgpZSKhmPavc,5384
|
|
118
118
|
preditor/scintilla/__init__.py,sha256=IDndbcS8KW1TMcQTA1Vd-LzcdsNtOUfyldnjkKae0yw,956
|
|
119
|
-
preditor/scintilla/documenteditor.py,sha256=
|
|
119
|
+
preditor/scintilla/documenteditor.py,sha256=9DyZBNPD59W1x8CGFHhxlgf9WTHi6ni7EIlyL7aMnIM,81477
|
|
120
120
|
preditor/scintilla/finddialog.py,sha256=WxNVvkCfXrw_8E3-7tS1DIS9H1-ioLASDgIbniDxz3g,2376
|
|
121
121
|
preditor/scintilla/delayables/__init__.py,sha256=lj9tMc3IL2QeaN858Ixt_n7clJngbKqG2sk66vIcFcQ,275
|
|
122
122
|
preditor/scintilla/delayables/smart_highlight.py,sha256=5emI4StsQCIYizoFsib1rdw0gnUarV9TQ6CwxmzXXpU,3623
|
|
@@ -157,11 +157,11 @@ preditor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
157
157
|
preditor/utils/cute.py,sha256=tLTChQ1-zMzHHaKpG85u4FbtJl_2R1E8-uckpOQbEEM,1057
|
|
158
158
|
preditor/utils/stylesheets.py,sha256=EVWZNq3WnaRiyUPoYMKQo_dLEwbRyKu26b03I1JDA-s,1622
|
|
159
159
|
preditor/utils/text_search.py,sha256=21kuSDTpLIPUcriB81WP1kWfzuDBuP13ZtHUtypP5jE,14218
|
|
160
|
-
preditor-1.
|
|
160
|
+
preditor-1.4.0.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
161
161
|
tests/find_files/test_find_files.py,sha256=ETVe1tC666uTc_5pPhjzPCaMrMkYUB8iKGXDfW9usgI,2722
|
|
162
162
|
tests/ide/test_delayable_engine.py,sha256=Nv6SQXpwIdfgRbEOsEcR-7jhjZ6E0THPdwDoPvAM6y4,5948
|
|
163
|
-
preditor-1.
|
|
164
|
-
preditor-1.
|
|
165
|
-
preditor-1.
|
|
166
|
-
preditor-1.
|
|
167
|
-
preditor-1.
|
|
163
|
+
preditor-1.4.0.dist-info/METADATA,sha256=zA-ZtzJ0KNl6-ufO_quM7e2eyxPAF0xkaUaWRpQHoio,12744
|
|
164
|
+
preditor-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
165
|
+
preditor-1.4.0.dist-info/entry_points.txt,sha256=mpe0HFD_oIEBNPTJNyUEbmMV6Ivrp4EuYyZ34C5d_PU,519
|
|
166
|
+
preditor-1.4.0.dist-info/top_level.txt,sha256=dZSBDecBQovRyqbFdvwk1AvMon636dJ14vr9ov1LSPs,20
|
|
167
|
+
preditor-1.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|