PrEditor 1.1.0__py3-none-any.whl → 1.3.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/__init__.py +4 -1
- preditor/about_module.py +6 -2
- preditor/dccs/.hab.json +10 -0
- preditor/dccs/maya/PrEditor_maya.mod +0 -1
- preditor/dccs/maya/README.md +22 -0
- preditor/dccs/maya/plug-ins/PrEditor_maya.py +32 -1
- preditor/dccs/studiomax/PackageContents.xml +32 -0
- preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +8 -0
- preditor/dccs/studiomax/README.md +17 -0
- preditor/dccs/studiomax/preditor.ms +16 -0
- preditor/dccs/studiomax/preditor_menu.mnx +7 -0
- preditor/debug.py +7 -3
- preditor/excepthooks.py +1 -1
- preditor/gui/app.py +2 -2
- preditor/gui/codehighlighter.py +10 -24
- preditor/gui/completer.py +17 -6
- preditor/gui/console.py +94 -47
- preditor/gui/dialog.py +10 -7
- preditor/gui/drag_tab_bar.py +7 -7
- preditor/gui/errordialog.py +2 -2
- preditor/gui/find_files.py +7 -5
- preditor/gui/fuzzy_search/fuzzy_search.py +8 -4
- preditor/gui/group_tab_widget/__init__.py +32 -4
- preditor/gui/group_tab_widget/grouped_tab_models.py +4 -4
- preditor/gui/group_tab_widget/grouped_tab_widget.py +6 -4
- preditor/gui/level_buttons.py +16 -1
- preditor/gui/loggerwindow.py +48 -27
- preditor/gui/set_text_editor_path_dialog.py +3 -1
- preditor/gui/ui/loggerwindow.ui +11 -1
- preditor/gui/window.py +4 -4
- preditor/gui/workbox_mixin.py +43 -14
- preditor/gui/workbox_text_edit.py +7 -5
- preditor/gui/workboxwidget.py +25 -16
- preditor/logging_config.py +5 -2
- preditor/scintilla/__init__.py +19 -1
- preditor/scintilla/delayables/smart_highlight.py +7 -4
- preditor/scintilla/delayables/spell_check.py +5 -4
- preditor/scintilla/documenteditor.py +228 -135
- preditor/scintilla/finddialog.py +3 -3
- preditor/scintilla/lang/language.py +1 -1
- preditor/scintilla/lexers/cpplexer.py +3 -2
- preditor/scintilla/lexers/javascriptlexer.py +6 -4
- preditor/scintilla/lexers/maxscriptlexer.py +8 -7
- preditor/scintilla/lexers/mellexer.py +3 -2
- preditor/scintilla/lexers/mulexer.py +3 -2
- preditor/scintilla/lexers/pythonlexer.py +7 -6
- preditor/utils/cute.py +9 -8
- preditor/version.py +16 -3
- {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/METADATA +69 -32
- {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/RECORD +56 -47
- preditor-1.3.0.dist-info/top_level.txt +3 -0
- tests/find_files/test_find_files.py +74 -0
- tests/ide/test_delayable_engine.py +171 -0
- preditor-1.1.0.dist-info/top_level.txt +0 -1
- {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/WHEEL +0 -0
- {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/entry_points.txt +0 -0
- {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -19,11 +19,9 @@ from collections import OrderedDict
|
|
|
19
19
|
from contextlib import contextmanager
|
|
20
20
|
from functools import partial
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
from
|
|
24
|
-
from Qt import
|
|
25
|
-
from Qt.QtCore import Property, QFile, QPoint, Qt, Signal
|
|
26
|
-
from Qt.QtGui import QColor, QFont, QFontMetrics, QIcon
|
|
22
|
+
import Qt as Qt_py
|
|
23
|
+
from Qt.QtCore import Property, QEvent, QPoint, Qt, Signal
|
|
24
|
+
from Qt.QtGui import QColor, QFont, QFontMetrics, QIcon, QKeyEvent, QKeySequence
|
|
27
25
|
from Qt.QtWidgets import (
|
|
28
26
|
QAction,
|
|
29
27
|
QApplication,
|
|
@@ -37,7 +35,8 @@ from .. import osystem, resourcePath
|
|
|
37
35
|
from ..delayable_engine import DelayableEngine
|
|
38
36
|
from ..enum import Enum, EnumGroup
|
|
39
37
|
from ..gui import QtPropertyInit
|
|
40
|
-
from . import
|
|
38
|
+
from ..gui.workbox_mixin import WorkboxMixin
|
|
39
|
+
from . import QsciScintilla, lang
|
|
41
40
|
|
|
42
41
|
logger = logging.getLogger(__name__)
|
|
43
42
|
|
|
@@ -90,7 +89,7 @@ class DocumentEditor(QsciScintilla):
|
|
|
90
89
|
self.additionalFilenames = []
|
|
91
90
|
self._language = ''
|
|
92
91
|
self._lastSearch = ''
|
|
93
|
-
self.
|
|
92
|
+
self._encoding = 'utf-8'
|
|
94
93
|
self._fileMonitoringActive = False
|
|
95
94
|
self._marginsFont = self._defaultFont
|
|
96
95
|
self._lastSearchDirection = SearchDirection.First
|
|
@@ -99,21 +98,21 @@ class DocumentEditor(QsciScintilla):
|
|
|
99
98
|
self._enableFontResizing = True
|
|
100
99
|
# QSci doesnt provide accessors to these values, so store them internally
|
|
101
100
|
self._foldMarginBackgroundColor = QColor(224, 224, 224)
|
|
102
|
-
self._foldMarginForegroundColor = QColor(Qt.white)
|
|
101
|
+
self._foldMarginForegroundColor = QColor(Qt.GlobalColor.white)
|
|
103
102
|
self._marginsBackgroundColor = QColor(224, 224, 224)
|
|
104
103
|
self._marginsForegroundColor = QColor()
|
|
105
104
|
self._matchedBraceBackgroundColor = QColor(224, 224, 224)
|
|
106
105
|
self._matchedBraceForegroundColor = QColor()
|
|
107
|
-
self._unmatchedBraceBackgroundColor = QColor(Qt.white)
|
|
108
|
-
self._unmatchedBraceForegroundColor = QColor(Qt.blue)
|
|
106
|
+
self._unmatchedBraceBackgroundColor = QColor(Qt.GlobalColor.white)
|
|
107
|
+
self._unmatchedBraceForegroundColor = QColor(Qt.GlobalColor.blue)
|
|
109
108
|
self._caretForegroundColor = QColor()
|
|
110
109
|
self._caretBackgroundColor = QColor(255, 255, 255, 255)
|
|
111
110
|
self._selectionBackgroundColor = QColor(192, 192, 192)
|
|
112
|
-
self._selectionForegroundColor = QColor(Qt.black)
|
|
113
|
-
self._indentationGuidesBackgroundColor = QColor(Qt.white)
|
|
114
|
-
self._indentationGuidesForegroundColor = QColor(Qt.black)
|
|
115
|
-
self._markerBackgroundColor = QColor(Qt.white)
|
|
116
|
-
self._markerForegroundColor = QColor(Qt.black)
|
|
111
|
+
self._selectionForegroundColor = QColor(Qt.GlobalColor.black)
|
|
112
|
+
self._indentationGuidesBackgroundColor = QColor(Qt.GlobalColor.white)
|
|
113
|
+
self._indentationGuidesForegroundColor = QColor(Qt.GlobalColor.black)
|
|
114
|
+
self._markerBackgroundColor = QColor(Qt.GlobalColor.white)
|
|
115
|
+
self._markerForegroundColor = QColor(Qt.GlobalColor.black)
|
|
117
116
|
|
|
118
117
|
# Setup the DelayableEngine and add the document to it
|
|
119
118
|
self.delayable_info = OrderedDict()
|
|
@@ -134,13 +133,13 @@ class DocumentEditor(QsciScintilla):
|
|
|
134
133
|
self.initSettings(first_time=True)
|
|
135
134
|
|
|
136
135
|
# set one time properties
|
|
137
|
-
self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
|
|
138
|
-
self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
|
|
139
|
-
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
|
136
|
+
self.setFolding(QsciScintilla.FoldStyle.BoxedTreeFoldStyle)
|
|
137
|
+
self.setBraceMatching(QsciScintilla.BraceMatch.SloppyBraceMatch)
|
|
138
|
+
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
|
140
139
|
self.setAcceptDrops(False)
|
|
141
140
|
# Not supported by older builds of QsciScintilla
|
|
142
141
|
if hasattr(self, 'setTabDrawMode'):
|
|
143
|
-
self.setTabDrawMode(QsciScintilla.TabStrikeOut)
|
|
142
|
+
self.setTabDrawMode(QsciScintilla.TabDrawMode.TabStrikeOut)
|
|
144
143
|
|
|
145
144
|
# create connections
|
|
146
145
|
self.customContextMenuRequested.connect(self.showMenu)
|
|
@@ -173,23 +172,55 @@ class DocumentEditor(QsciScintilla):
|
|
|
173
172
|
commands = self.standardCommands()
|
|
174
173
|
# Remove the Ctrl+/ "Move left one word part" shortcut so it can be used to
|
|
175
174
|
# comment
|
|
176
|
-
|
|
175
|
+
if Qt_py.IsPyQt6:
|
|
176
|
+
# In Qt6 enums are not longer simple ints. boundTo still requires ints
|
|
177
|
+
def to_int(shortcut):
|
|
178
|
+
return shortcut.toCombined()
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
|
|
182
|
+
def to_int(shortcut):
|
|
183
|
+
return shortcut
|
|
184
|
+
|
|
185
|
+
command = commands.boundTo(
|
|
186
|
+
to_int(Qt.KeyboardModifier.ControlModifier | Qt.Key.Key_Slash)
|
|
187
|
+
)
|
|
177
188
|
if command is not None:
|
|
178
189
|
command.setKey(0)
|
|
179
190
|
|
|
180
191
|
for command in commands.commands():
|
|
181
192
|
if command.description() == 'Move selected lines up one line':
|
|
182
|
-
command.setKey(
|
|
193
|
+
command.setKey(
|
|
194
|
+
to_int(
|
|
195
|
+
Qt.KeyboardModifier.ControlModifier
|
|
196
|
+
| Qt.KeyboardModifier.ShiftModifier
|
|
197
|
+
| Qt.Key.Key_Up
|
|
198
|
+
)
|
|
199
|
+
)
|
|
183
200
|
if command.description() == 'Move selected lines down one line':
|
|
184
|
-
command.setKey(
|
|
201
|
+
command.setKey(
|
|
202
|
+
to_int(
|
|
203
|
+
Qt.KeyboardModifier.ControlModifier
|
|
204
|
+
| Qt.KeyboardModifier.ShiftModifier
|
|
205
|
+
| Qt.Key.Key_Down
|
|
206
|
+
)
|
|
207
|
+
)
|
|
185
208
|
if command.description() == 'Duplicate selection':
|
|
186
|
-
command.setKey(
|
|
209
|
+
command.setKey(
|
|
210
|
+
to_int(
|
|
211
|
+
Qt.KeyboardModifier.ControlModifier
|
|
212
|
+
| Qt.KeyboardModifier.ShiftModifier
|
|
213
|
+
| Qt.Key.Key_D
|
|
214
|
+
)
|
|
215
|
+
)
|
|
187
216
|
if command.description() == 'Cut current line':
|
|
188
217
|
command.setKey(0)
|
|
189
218
|
|
|
190
219
|
# Add QShortcuts
|
|
191
220
|
self.uiShowAutoCompleteSCT = QShortcut(
|
|
192
|
-
Qt.CTRL | Qt.Key_Space,
|
|
221
|
+
QKeySequence(Qt.Modifier.CTRL | Qt.Key.Key_Space),
|
|
222
|
+
self,
|
|
223
|
+
context=Qt.ShortcutContext.WidgetShortcut,
|
|
193
224
|
)
|
|
194
225
|
self.uiShowAutoCompleteSCT.activated.connect(lambda: self.showAutoComplete())
|
|
195
226
|
|
|
@@ -227,11 +258,13 @@ class DocumentEditor(QsciScintilla):
|
|
|
227
258
|
self.window(),
|
|
228
259
|
'Save changes to...',
|
|
229
260
|
'Do you want to save your changes?',
|
|
230
|
-
QMessageBox.Yes
|
|
261
|
+
QMessageBox.StandardButton.Yes
|
|
262
|
+
| QMessageBox.StandardButton.No
|
|
263
|
+
| QMessageBox.StandardButton.Cancel,
|
|
231
264
|
)
|
|
232
|
-
if result == QMessageBox.Yes:
|
|
265
|
+
if result == QMessageBox.StandardButton.Yes:
|
|
233
266
|
return self.save()
|
|
234
|
-
elif result == QMessageBox.Cancel:
|
|
267
|
+
elif result == QMessageBox.StandardButton.Cancel:
|
|
235
268
|
return False
|
|
236
269
|
return True
|
|
237
270
|
|
|
@@ -293,7 +326,8 @@ class DocumentEditor(QsciScintilla):
|
|
|
293
326
|
|
|
294
327
|
with undo_step(self):
|
|
295
328
|
# lookup the selected text positions
|
|
296
|
-
|
|
329
|
+
origSelection = self.expandCursorToLineSelection()
|
|
330
|
+
origStartLine, origStartCol, origEndLine, origEndCol = origSelection
|
|
297
331
|
startLine, startCol, endLine, endCol = self.getSelection()
|
|
298
332
|
|
|
299
333
|
# Collect comments and indents, to determine indentation to use, and whether
|
|
@@ -318,11 +352,14 @@ class DocumentEditor(QsciScintilla):
|
|
|
318
352
|
|
|
319
353
|
# If all lines are comments, we un-comment. If any aren't
|
|
320
354
|
# comments, we comment.
|
|
355
|
+
sel_adjust = 0
|
|
321
356
|
if doWhich is None:
|
|
322
357
|
if all(comments):
|
|
323
358
|
doWhich = "Uncomment"
|
|
359
|
+
sel_adjust = -1 * len(commentSpace)
|
|
324
360
|
else:
|
|
325
361
|
doWhich = "Comment"
|
|
362
|
+
sel_adjust = len(commentSpace)
|
|
326
363
|
|
|
327
364
|
for line in range(startLine, endLine + 1):
|
|
328
365
|
lineText = self.getSelectionCurrentLineText(line)
|
|
@@ -334,19 +371,12 @@ class DocumentEditor(QsciScintilla):
|
|
|
334
371
|
if doWhich == "Comment":
|
|
335
372
|
self.setCursorPosition(line, indent)
|
|
336
373
|
self.insert(commentSpace)
|
|
337
|
-
if cursorIndex is not None and cursorIndex >= indent:
|
|
338
|
-
cursorIndex += len(commentSpace)
|
|
339
|
-
if line == startLine:
|
|
340
|
-
startCol -= len(commentSpace)
|
|
341
|
-
if line == endLine:
|
|
342
|
-
endCol += len(commentSpace)
|
|
343
|
-
|
|
344
374
|
elif doWhich == "Uncomment":
|
|
345
375
|
for curComment in [commentSpace, comment]:
|
|
346
376
|
foundText = self.getSelectedCommentText(
|
|
347
377
|
line, indent, len(curComment)
|
|
348
378
|
)
|
|
349
|
-
startCol, endCol,
|
|
379
|
+
startCol, endCol, _, removed = self.removeComment(
|
|
350
380
|
foundText,
|
|
351
381
|
curComment,
|
|
352
382
|
line,
|
|
@@ -355,16 +385,20 @@ class DocumentEditor(QsciScintilla):
|
|
|
355
385
|
startCol,
|
|
356
386
|
endLine,
|
|
357
387
|
endCol,
|
|
358
|
-
|
|
388
|
+
origEndCol,
|
|
359
389
|
)
|
|
360
390
|
if removed:
|
|
361
391
|
break
|
|
362
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
|
+
|
|
363
398
|
# restore the currently selected text, or cursor position
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
self.setSelection(startLine, startCol, endLine, endCol)
|
|
399
|
+
self.setSelection(
|
|
400
|
+
origStartLine, adjustedStartCol, origEndLine, adjustedendCol
|
|
401
|
+
)
|
|
368
402
|
|
|
369
403
|
def removeComment(
|
|
370
404
|
self,
|
|
@@ -427,11 +461,26 @@ class DocumentEditor(QsciScintilla):
|
|
|
427
461
|
return lineText
|
|
428
462
|
|
|
429
463
|
def expandCursorToLineSelection(self):
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
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
|
|
435
484
|
|
|
436
485
|
def copy(self):
|
|
437
486
|
"""Copies the selected text.
|
|
@@ -508,22 +557,22 @@ class DocumentEditor(QsciScintilla):
|
|
|
508
557
|
if newlineN != -1 and newlineR != -1:
|
|
509
558
|
if newlineN == newlineR + 1:
|
|
510
559
|
# CR LF Windows
|
|
511
|
-
return
|
|
560
|
+
return QsciScintilla.EolMode.EolWindows
|
|
512
561
|
elif newlineR == newlineN + 1:
|
|
513
|
-
# LF CR ACorn and RISC
|
|
562
|
+
# LF CR ACorn and RISC unsupported
|
|
514
563
|
return self.eolMode()
|
|
515
564
|
if newlineN != -1 and newlineR != -1:
|
|
516
565
|
if newlineN < newlineR:
|
|
517
566
|
# First return is a LF
|
|
518
|
-
return
|
|
567
|
+
return QsciScintilla.EolMode.EolUnix
|
|
519
568
|
else:
|
|
520
569
|
# first return is a CR
|
|
521
|
-
return
|
|
570
|
+
return QsciScintilla.EolMode.EolMac
|
|
522
571
|
if newlineN != -1:
|
|
523
|
-
return
|
|
572
|
+
return QsciScintilla.EolMode.EolUnix
|
|
524
573
|
if sys.platform == 'win32':
|
|
525
|
-
return
|
|
526
|
-
return
|
|
574
|
+
return QsciScintilla.EolMode.EolWindows
|
|
575
|
+
return QsciScintilla.EolMode.EolUnix
|
|
527
576
|
|
|
528
577
|
def editPermaHighlight(self):
|
|
529
578
|
text, success = QInputDialog.getText(
|
|
@@ -564,7 +613,7 @@ class DocumentEditor(QsciScintilla):
|
|
|
564
613
|
self.modificationChanged.connect(self.refreshTitle)
|
|
565
614
|
|
|
566
615
|
def eventFilter(self, object, event):
|
|
567
|
-
if event.type() ==
|
|
616
|
+
if event.type() == QEvent.Type.Close and not self.checkForSave():
|
|
568
617
|
event.ignore()
|
|
569
618
|
return True
|
|
570
619
|
return False
|
|
@@ -657,14 +706,8 @@ class DocumentEditor(QsciScintilla):
|
|
|
657
706
|
def load(self, filename):
|
|
658
707
|
filename = str(filename)
|
|
659
708
|
if filename and os.path.exists(filename):
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
text = f.readAll()
|
|
663
|
-
self._textCodec = QTextCodec.codecForUtfText(
|
|
664
|
-
text, QTextCodec.codecForName('UTF-8')
|
|
665
|
-
)
|
|
666
|
-
self.setText(self._textCodec.toUnicode(text))
|
|
667
|
-
f.close()
|
|
709
|
+
self._encoding, text = WorkboxMixin.__open_file__(filename)
|
|
710
|
+
self.setText(text)
|
|
668
711
|
self.updateFilename(filename)
|
|
669
712
|
self.enableFileWatching(True)
|
|
670
713
|
self.setEolMode(self.detectEndLine(self.text()))
|
|
@@ -719,14 +762,14 @@ class DocumentEditor(QsciScintilla):
|
|
|
719
762
|
if find_state.start_pos == find_state.end_pos:
|
|
720
763
|
return -1
|
|
721
764
|
|
|
722
|
-
self.SendScintilla(
|
|
723
|
-
self.SendScintilla(
|
|
765
|
+
self.SendScintilla(QsciScintilla.SCI_SETTARGETSTART, find_state.start_pos)
|
|
766
|
+
self.SendScintilla(QsciScintilla.SCI_SETTARGETEND, find_state.end_pos)
|
|
724
767
|
|
|
725
768
|
# scintilla can't match unicode strings, even in python 3
|
|
726
769
|
# In python 3 you have to cast it to a bytes object
|
|
727
770
|
expr = bytes(str(find_state.expr).encode("utf-8"))
|
|
728
771
|
|
|
729
|
-
return self.SendScintilla(
|
|
772
|
+
return self.SendScintilla(QsciScintilla.SCI_SEARCHINTARGET, len(expr), expr)
|
|
730
773
|
|
|
731
774
|
def find_text(self, find_state):
|
|
732
775
|
"""Finds text in the document without changing the selection.
|
|
@@ -739,10 +782,10 @@ class DocumentEditor(QsciScintilla):
|
|
|
739
782
|
https://github.com/josephwilk/qscintilla/blob/master/Qt4Qt5/qsciscintilla.cpp
|
|
740
783
|
"""
|
|
741
784
|
# Set the search flags
|
|
742
|
-
self.SendScintilla(
|
|
785
|
+
self.SendScintilla(QsciScintilla.SCI_SETSEARCHFLAGS, find_state.flags)
|
|
743
786
|
# If no end was specified, use the end of the document
|
|
744
787
|
if find_state.end_pos is None:
|
|
745
|
-
find_state.end_pos = self.SendScintilla(
|
|
788
|
+
find_state.end_pos = self.SendScintilla(QsciScintilla.SCI_GETLENGTH)
|
|
746
789
|
|
|
747
790
|
pos = self.find_simple(find_state)
|
|
748
791
|
|
|
@@ -751,12 +794,14 @@ class DocumentEditor(QsciScintilla):
|
|
|
751
794
|
if find_state.forward:
|
|
752
795
|
find_state.start_pos = 0
|
|
753
796
|
if find_state.start_pos_original is None:
|
|
754
|
-
find_state.end_pos = self.SendScintilla(
|
|
797
|
+
find_state.end_pos = self.SendScintilla(QsciScintilla.SCI_GETLENGTH)
|
|
755
798
|
else:
|
|
756
799
|
find_state.end_pos = find_state.start_pos_original
|
|
757
800
|
else:
|
|
758
801
|
if find_state.start_pos_original is None:
|
|
759
|
-
find_state.start_pos = self.SendScintilla(
|
|
802
|
+
find_state.start_pos = self.SendScintilla(
|
|
803
|
+
QsciScintilla.SCI_GETLENGTH
|
|
804
|
+
)
|
|
760
805
|
else:
|
|
761
806
|
find_state.start_pos = find_state.start_pos_original
|
|
762
807
|
find_state.end_pos = 0
|
|
@@ -769,8 +814,8 @@ class DocumentEditor(QsciScintilla):
|
|
|
769
814
|
return -1, 0
|
|
770
815
|
|
|
771
816
|
# It was found.
|
|
772
|
-
target_start = self.SendScintilla(
|
|
773
|
-
target_end = self.SendScintilla(
|
|
817
|
+
target_start = self.SendScintilla(QsciScintilla.SCI_GETTARGETSTART)
|
|
818
|
+
target_end = self.SendScintilla(QsciScintilla.SCI_GETTARGETEND)
|
|
774
819
|
|
|
775
820
|
# Finally adjust the start position so that we don't find the same one again.
|
|
776
821
|
if find_state.forward:
|
|
@@ -818,10 +863,12 @@ class DocumentEditor(QsciScintilla):
|
|
|
818
863
|
self,
|
|
819
864
|
'No Text Found',
|
|
820
865
|
msg % (text, line),
|
|
821
|
-
buttons=(
|
|
822
|
-
|
|
866
|
+
buttons=(
|
|
867
|
+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
868
|
+
),
|
|
869
|
+
defaultButton=QMessageBox.StandardButton.Yes,
|
|
823
870
|
)
|
|
824
|
-
if result == QMessageBox.Yes:
|
|
871
|
+
if result == QMessageBox.StandardButton.Yes:
|
|
825
872
|
self.goToLine(line)
|
|
826
873
|
except ValueError:
|
|
827
874
|
QMessageBox.critical(
|
|
@@ -830,20 +877,48 @@ class DocumentEditor(QsciScintilla):
|
|
|
830
877
|
|
|
831
878
|
def keyPressEvent(self, event):
|
|
832
879
|
key = event.key()
|
|
833
|
-
|
|
880
|
+
modifiers = event.modifiers()
|
|
881
|
+
|
|
882
|
+
retPressed = key == Qt.Key.Key_Return
|
|
883
|
+
altPressed = modifiers == Qt.KeyboardModifier.AltModifier
|
|
884
|
+
altReturnPressed = altPressed and retPressed
|
|
885
|
+
|
|
886
|
+
if key == Qt.Key.Key_Backtab:
|
|
834
887
|
self.unindentSelection()
|
|
835
|
-
elif key == Qt.Key_Escape:
|
|
888
|
+
elif key == Qt.Key.Key_Escape:
|
|
836
889
|
# Using QShortcut for Escape did not seem to work.
|
|
837
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
|
+
|
|
838
913
|
else:
|
|
839
914
|
return QsciScintilla.keyPressEvent(self, event)
|
|
840
915
|
|
|
841
916
|
def keyReleaseEvent(self, event):
|
|
842
|
-
if event.key() == Qt.Key_Menu:
|
|
917
|
+
if event.key() == Qt.Key.Key_Menu:
|
|
843
918
|
# Calculate the screen coordinates of the text cursor.
|
|
844
919
|
position = self.positionFromLineIndex(*self.getCursorPosition())
|
|
845
|
-
x = self.SendScintilla(
|
|
846
|
-
y = self.SendScintilla(
|
|
920
|
+
x = self.SendScintilla(QsciScintilla.SCI_POINTXFROMPOSITION, 0, position)
|
|
921
|
+
y = self.SendScintilla(QsciScintilla.SCI_POINTYFROMPOSITION, 0, position)
|
|
847
922
|
# When using the menu key, show the right click menu at the text
|
|
848
923
|
# cursor, not the mouse cursor, it is not in the correct place.
|
|
849
924
|
self.showMenu(QPoint(x, y))
|
|
@@ -867,15 +942,20 @@ class DocumentEditor(QsciScintilla):
|
|
|
867
942
|
self.setShowSmartHighlighting(True)
|
|
868
943
|
self.setBackspaceUnindents(True)
|
|
869
944
|
|
|
870
|
-
self.setEdgeMode(
|
|
945
|
+
self.setEdgeMode(QsciScintilla.EdgeMode.EdgeNone)
|
|
871
946
|
|
|
872
|
-
# set
|
|
873
|
-
self.setAutoCompletionSource(QsciScintilla.AcsAll)
|
|
947
|
+
# set auto-completion settings
|
|
948
|
+
self.setAutoCompletionSource(QsciScintilla.AutoCompletionSource.AcsAll)
|
|
874
949
|
self.setAutoCompletionThreshold(3)
|
|
875
950
|
|
|
876
951
|
self.setFont(self.documentFont)
|
|
877
952
|
self.setMarginsFont(self.marginsFont())
|
|
878
|
-
|
|
953
|
+
metric = QFontMetrics(self.marginsFont())
|
|
954
|
+
if Qt_py.IsPyQt4:
|
|
955
|
+
width = metric.width('0000000')
|
|
956
|
+
else:
|
|
957
|
+
width = metric.horizontalAdvance('0000000')
|
|
958
|
+
self.setMarginWidth(0, width + 5)
|
|
879
959
|
|
|
880
960
|
def markerNext(self):
|
|
881
961
|
line, index = self.getCursorPosition()
|
|
@@ -910,15 +990,15 @@ class DocumentEditor(QsciScintilla):
|
|
|
910
990
|
|
|
911
991
|
def multipleSelection(self):
|
|
912
992
|
"""Returns if multiple selection is enabled."""
|
|
913
|
-
return self.SendScintilla(
|
|
993
|
+
return self.SendScintilla(QsciScintilla.SCI_GETMULTIPLESELECTION)
|
|
914
994
|
|
|
915
995
|
def multipleSelectionAdditionalSelectionTyping(self):
|
|
916
996
|
"""Returns if multiple selection allows additional typing."""
|
|
917
|
-
return self.SendScintilla(
|
|
997
|
+
return self.SendScintilla(QsciScintilla.SCI_GETMULTIPLESELECTION)
|
|
918
998
|
|
|
919
999
|
def multipleSelectionMultiPaste(self):
|
|
920
1000
|
"""Paste into all multiple selections."""
|
|
921
|
-
return self.SendScintilla(
|
|
1001
|
+
return self.SendScintilla(QsciScintilla.SCI_GETMULTIPASTE)
|
|
922
1002
|
|
|
923
1003
|
def paste(self):
|
|
924
1004
|
text = QApplication.clipboard().text()
|
|
@@ -926,9 +1006,9 @@ class DocumentEditor(QsciScintilla):
|
|
|
926
1006
|
return super(DocumentEditor, self).paste()
|
|
927
1007
|
|
|
928
1008
|
def repForMode(mode):
|
|
929
|
-
if mode ==
|
|
1009
|
+
if mode == QsciScintilla.EolMode.EolWindows:
|
|
930
1010
|
return '\r\n'
|
|
931
|
-
elif mode ==
|
|
1011
|
+
elif mode == QsciScintilla.EolMode.EolUnix:
|
|
932
1012
|
return '\n'
|
|
933
1013
|
else:
|
|
934
1014
|
return '\r'
|
|
@@ -987,11 +1067,11 @@ class DocumentEditor(QsciScintilla):
|
|
|
987
1067
|
self.window(),
|
|
988
1068
|
'File Removed...',
|
|
989
1069
|
'File: %s has been deleted.\nKeep file in editor?' % self.filename(),
|
|
990
|
-
QMessageBox.Yes,
|
|
991
|
-
QMessageBox.No,
|
|
1070
|
+
QMessageBox.StandardButton.Yes,
|
|
1071
|
+
QMessageBox.StandardButton.No,
|
|
992
1072
|
)
|
|
993
1073
|
self._dialogShown = False
|
|
994
|
-
if result == QMessageBox.No:
|
|
1074
|
+
if result == QMessageBox.StandardButton.No:
|
|
995
1075
|
logger.debug(
|
|
996
1076
|
'The file was deleted, removing document from editor',
|
|
997
1077
|
)
|
|
@@ -1013,13 +1093,16 @@ class DocumentEditor(QsciScintilla):
|
|
|
1013
1093
|
if not self._dialogShown:
|
|
1014
1094
|
self._dialogShown = True
|
|
1015
1095
|
if self._autoReloadOnChange or not self.isModified():
|
|
1016
|
-
result = QMessageBox.Yes
|
|
1096
|
+
result = QMessageBox.StandardButton.Yes
|
|
1017
1097
|
else:
|
|
1018
1098
|
result = QMessageBox.question(
|
|
1019
|
-
self.window(),
|
|
1099
|
+
self.window(),
|
|
1100
|
+
title,
|
|
1101
|
+
message,
|
|
1102
|
+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
|
1020
1103
|
)
|
|
1021
1104
|
self._dialogShown = False
|
|
1022
|
-
if result == QMessageBox.Yes:
|
|
1105
|
+
if result == QMessageBox.StandardButton.Yes:
|
|
1023
1106
|
return self.load(self.filename())
|
|
1024
1107
|
return False
|
|
1025
1108
|
|
|
@@ -1037,7 +1120,9 @@ class DocumentEditor(QsciScintilla):
|
|
|
1037
1120
|
|
|
1038
1121
|
# replace all of the instances of the text
|
|
1039
1122
|
if all:
|
|
1040
|
-
count = self.text().count(
|
|
1123
|
+
count = self.text().count(
|
|
1124
|
+
searchtext, Qt.CaseSensitivity.CaseInsensitive
|
|
1125
|
+
)
|
|
1041
1126
|
found = 0
|
|
1042
1127
|
while self.findFirst(searchtext, False, False, False, True, True):
|
|
1043
1128
|
if found == count:
|
|
@@ -1084,32 +1169,28 @@ class DocumentEditor(QsciScintilla):
|
|
|
1084
1169
|
if not filename:
|
|
1085
1170
|
newFile = True
|
|
1086
1171
|
filename = self.filename()
|
|
1087
|
-
filename, extFilter = QtCompat.QFileDialog.getSaveFileName(
|
|
1172
|
+
filename, extFilter = Qt_py.QtCompat.QFileDialog.getSaveFileName(
|
|
1088
1173
|
self.window(), 'Save File as...', filename
|
|
1089
1174
|
)
|
|
1090
1175
|
|
|
1091
1176
|
if filename:
|
|
1092
1177
|
self._saveTimer = time.time()
|
|
1093
1178
|
# save the file to disk
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1179
|
+
try:
|
|
1180
|
+
txt = self.text()
|
|
1181
|
+
WorkboxMixin.__write_file__(filename, txt, encoding=self._encoding)
|
|
1182
|
+
with open(filename, "w", encoding=self._encoding) as f:
|
|
1183
|
+
f.write(self.text())
|
|
1184
|
+
except PermissionError as error:
|
|
1185
|
+
logger.debug('An error occurred while saving')
|
|
1099
1186
|
QMessageBox.question(
|
|
1100
1187
|
self.window(),
|
|
1101
1188
|
'Error saving file...',
|
|
1102
|
-
'There was a error saving the file. Error
|
|
1103
|
-
QMessageBox.Ok,
|
|
1189
|
+
'There was a error saving the file. Error: {}'.format(error),
|
|
1190
|
+
QMessageBox.StandardButton.Ok,
|
|
1104
1191
|
)
|
|
1105
|
-
f.close()
|
|
1106
1192
|
return False
|
|
1107
|
-
|
|
1108
|
-
if self._textCodec:
|
|
1109
|
-
f.write(self._textCodec.fromUnicode(self.text()))
|
|
1110
|
-
else:
|
|
1111
|
-
self.write(f)
|
|
1112
|
-
f.close()
|
|
1193
|
+
|
|
1113
1194
|
# notify that the document was saved
|
|
1114
1195
|
self.documentSaved.emit(self, filename)
|
|
1115
1196
|
|
|
@@ -1165,8 +1246,8 @@ class DocumentEditor(QsciScintilla):
|
|
|
1165
1246
|
return False
|
|
1166
1247
|
# Get the word at the start of selection, if the selection doesn't match
|
|
1167
1248
|
# its not a word.
|
|
1168
|
-
start_pos = self.SendScintilla(
|
|
1169
|
-
end_pos = self.SendScintilla(
|
|
1249
|
+
start_pos = self.SendScintilla(QsciScintilla.SCI_WORDSTARTPOSITION, start, True)
|
|
1250
|
+
end_pos = self.SendScintilla(QsciScintilla.SCI_WORDENDPOSITION, start, True)
|
|
1170
1251
|
|
|
1171
1252
|
return start == start_pos and end == end_pos
|
|
1172
1253
|
|
|
@@ -1227,7 +1308,9 @@ class DocumentEditor(QsciScintilla):
|
|
|
1227
1308
|
# from a wordCharactersOverride lexer to a lexer that doesn't define custom
|
|
1228
1309
|
# wordCharacters.
|
|
1229
1310
|
wordCharacters = self.wordCharacters()
|
|
1230
|
-
self.SendScintilla(
|
|
1311
|
+
self.SendScintilla(
|
|
1312
|
+
QsciScintilla.SCI_SETWORDCHARS, wordCharacters.encode('utf8')
|
|
1313
|
+
)
|
|
1231
1314
|
|
|
1232
1315
|
if lexer:
|
|
1233
1316
|
lexer.setFont(font)
|
|
@@ -1250,7 +1333,7 @@ class DocumentEditor(QsciScintilla):
|
|
|
1250
1333
|
ranges by holding down the Ctrl key while dragging with the
|
|
1251
1334
|
mouse.
|
|
1252
1335
|
"""
|
|
1253
|
-
self.SendScintilla(
|
|
1336
|
+
self.SendScintilla(QsciScintilla.SCI_SETMULTIPLESELECTION, state)
|
|
1254
1337
|
|
|
1255
1338
|
def setMultipleSelectionAdditionalSelectionTyping(self, state):
|
|
1256
1339
|
"""Enables or disables multiple selection allows additional typing.
|
|
@@ -1261,7 +1344,7 @@ class DocumentEditor(QsciScintilla):
|
|
|
1261
1344
|
simultaneously. Also allows selection and word and line
|
|
1262
1345
|
deletion commands.
|
|
1263
1346
|
"""
|
|
1264
|
-
self.SendScintilla(
|
|
1347
|
+
self.SendScintilla(QsciScintilla.SCI_SETADDITIONALSELECTIONTYPING, state)
|
|
1265
1348
|
|
|
1266
1349
|
def setMultipleSelectionMultiPaste(self, state):
|
|
1267
1350
|
"""Enables or disables multiple selection allows additional typing.
|
|
@@ -1272,7 +1355,7 @@ class DocumentEditor(QsciScintilla):
|
|
|
1272
1355
|
into each selection with self.SC_MULTIPASTE_EACH.
|
|
1273
1356
|
self.SC_MULTIPASTE_ONCE is the default.
|
|
1274
1357
|
"""
|
|
1275
|
-
self.SendScintilla(
|
|
1358
|
+
self.SendScintilla(QsciScintilla.SCI_SETMULTIPASTE, state)
|
|
1276
1359
|
|
|
1277
1360
|
def setSmartHighlightingRegEx(
|
|
1278
1361
|
self, exp=r'[ \t\n\r\.,?;:!()\[\]+\-\*\/#@^%$"\\~&{}|=<>\']'
|
|
@@ -1300,9 +1383,9 @@ class DocumentEditor(QsciScintilla):
|
|
|
1300
1383
|
|
|
1301
1384
|
def setShowWhitespaces(self, state):
|
|
1302
1385
|
if state:
|
|
1303
|
-
self.setWhitespaceVisibility(QsciScintilla.WsVisible)
|
|
1386
|
+
self.setWhitespaceVisibility(QsciScintilla.WhitespaceVisibility.WsVisible)
|
|
1304
1387
|
else:
|
|
1305
|
-
self.setWhitespaceVisibility(QsciScintilla.WsInvisible)
|
|
1388
|
+
self.setWhitespaceVisibility(QsciScintilla.WhitespaceVisibility.WsInvisible)
|
|
1306
1389
|
|
|
1307
1390
|
def spellCheckEnabled(self):
|
|
1308
1391
|
"""Is spellcheck is enabled for this document."""
|
|
@@ -1320,13 +1403,13 @@ class DocumentEditor(QsciScintilla):
|
|
|
1320
1403
|
self.__speller__.saveAllwords()
|
|
1321
1404
|
self.spellCheck(0, None)
|
|
1322
1405
|
self.pos += len(word)
|
|
1323
|
-
self.SendScintilla(
|
|
1406
|
+
self.SendScintilla(QsciScintilla.SCI_GOTOPOS, self.pos)
|
|
1324
1407
|
|
|
1325
1408
|
def correctSpelling(self, action):
|
|
1326
|
-
self.SendScintilla(
|
|
1327
|
-
self.SendScintilla(
|
|
1409
|
+
self.SendScintilla(QsciScintilla.SCI_GOTOPOS, self.pos)
|
|
1410
|
+
self.SendScintilla(QsciScintilla.SCI_SETANCHOR, self.anchor)
|
|
1328
1411
|
with undo_step(self):
|
|
1329
|
-
self.SendScintilla(
|
|
1412
|
+
self.SendScintilla(QsciScintilla.SCI_REPLACESEL, action.text())
|
|
1330
1413
|
|
|
1331
1414
|
def spellCheck(self, start_pos, end_pos):
|
|
1332
1415
|
"""Check spelling for some text in the document.
|
|
@@ -1360,18 +1443,20 @@ class DocumentEditor(QsciScintilla):
|
|
|
1360
1443
|
or (mtype & self.SC_MOD_DELETETEXT) == self.SC_MOD_DELETETEXT
|
|
1361
1444
|
):
|
|
1362
1445
|
# Only spell-check if text was inserted/deleted
|
|
1363
|
-
line = self.SendScintilla(
|
|
1446
|
+
line = self.SendScintilla(QsciScintilla.SCI_LINEFROMPOSITION, pos)
|
|
1364
1447
|
# More than one line could have been inserted.
|
|
1365
1448
|
# If this number is negative it will cause Qt to crash.
|
|
1366
1449
|
lines_to_check = line + max(0, linesAdded)
|
|
1367
1450
|
self.spellCheck(
|
|
1368
|
-
self.SendScintilla(
|
|
1369
|
-
self.SendScintilla(
|
|
1451
|
+
self.SendScintilla(QsciScintilla.SCI_POSITIONFROMLINE, line),
|
|
1452
|
+
self.SendScintilla(
|
|
1453
|
+
QsciScintilla.SCI_GETLINEENDPOSITION, lines_to_check
|
|
1454
|
+
),
|
|
1370
1455
|
)
|
|
1371
1456
|
|
|
1372
1457
|
def showAutoComplete(self, toggle=False):
|
|
1373
1458
|
# if using autoComplete toggle the autoComplete list
|
|
1374
|
-
if self.autoCompletionSource() == QsciScintilla.AcsAll:
|
|
1459
|
+
if self.autoCompletionSource() == QsciScintilla.AutoCompletionSource.AcsAll:
|
|
1375
1460
|
if self.isListActive(): # is the autoComplete list visible
|
|
1376
1461
|
if toggle:
|
|
1377
1462
|
self.cancelList() # Close the autoComplete list
|
|
@@ -1389,9 +1474,11 @@ class DocumentEditor(QsciScintilla):
|
|
|
1389
1474
|
x = point.x()
|
|
1390
1475
|
y = point.y()
|
|
1391
1476
|
wordUnderMouse = self.wordAtPoint(point)
|
|
1392
|
-
positionMouse = self.SendScintilla(
|
|
1477
|
+
positionMouse = self.SendScintilla(
|
|
1478
|
+
QsciScintilla.SCI_POSITIONFROMPOINT, x, y
|
|
1479
|
+
)
|
|
1393
1480
|
wordStartPosition = self.SendScintilla(
|
|
1394
|
-
|
|
1481
|
+
QsciScintilla.SCI_WORDSTARTPOSITION, positionMouse, True
|
|
1395
1482
|
)
|
|
1396
1483
|
spell_check = self.delayable_engine.delayables['spell_check']
|
|
1397
1484
|
results = spell_check.chunk_re.findall(
|
|
@@ -1556,7 +1643,9 @@ class DocumentEditor(QsciScintilla):
|
|
|
1556
1643
|
return self.delayable_engine.delayable_enabled('smart_highlight')
|
|
1557
1644
|
|
|
1558
1645
|
def showWhitespaces(self):
|
|
1559
|
-
return
|
|
1646
|
+
return (
|
|
1647
|
+
self.whitespaceVisibility() == QsciScintilla.WhitespaceVisibility.WsVisible
|
|
1648
|
+
)
|
|
1560
1649
|
|
|
1561
1650
|
def smartHighlightingRegEx(self):
|
|
1562
1651
|
return self._smartHighlightingRegEx
|
|
@@ -1570,7 +1659,10 @@ class DocumentEditor(QsciScintilla):
|
|
|
1570
1659
|
self.setSelection(lineFrom, indexFrom, lineTo, indexTo)
|
|
1571
1660
|
|
|
1572
1661
|
def toggleFolding(self):
|
|
1573
|
-
self.foldAll(
|
|
1662
|
+
self.foldAll(
|
|
1663
|
+
QApplication.instance().keyboardModifiers()
|
|
1664
|
+
== Qt.KeyboardModifier.ShiftModifier
|
|
1665
|
+
)
|
|
1574
1666
|
|
|
1575
1667
|
def toUpper(self):
|
|
1576
1668
|
with undo_step(self):
|
|
@@ -1710,10 +1802,8 @@ class DocumentEditor(QsciScintilla):
|
|
|
1710
1802
|
epos=epos,
|
|
1711
1803
|
lineCount=eline - sline + 1,
|
|
1712
1804
|
)
|
|
1713
|
-
if self.
|
|
1714
|
-
text = 'Encoding: {enc} {text}'.format(
|
|
1715
|
-
enc=self._textCodec.name(), text=text
|
|
1716
|
-
)
|
|
1805
|
+
if self._encoding:
|
|
1806
|
+
text = 'Encoding: {enc} {text}'.format(enc=self._encoding, text=text)
|
|
1717
1807
|
window.uiCursorInfoLBL.setText(text)
|
|
1718
1808
|
|
|
1719
1809
|
def setAutoReloadOnChange(self, state):
|
|
@@ -1754,7 +1844,10 @@ class DocumentEditor(QsciScintilla):
|
|
|
1754
1844
|
return title
|
|
1755
1845
|
|
|
1756
1846
|
def wheelEvent(self, event):
|
|
1757
|
-
if
|
|
1847
|
+
if (
|
|
1848
|
+
self._enableFontResizing
|
|
1849
|
+
and event.modifiers() == Qt.KeyboardModifier.ControlModifier
|
|
1850
|
+
):
|
|
1758
1851
|
# If used in LoggerWindow, use that wheel event
|
|
1759
1852
|
# May not want to import LoggerWindow, so perhaps
|
|
1760
1853
|
# check by str(type())
|