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.

Files changed (57) hide show
  1. preditor/__init__.py +4 -1
  2. preditor/about_module.py +6 -2
  3. preditor/dccs/.hab.json +10 -0
  4. preditor/dccs/maya/PrEditor_maya.mod +0 -1
  5. preditor/dccs/maya/README.md +22 -0
  6. preditor/dccs/maya/plug-ins/PrEditor_maya.py +32 -1
  7. preditor/dccs/studiomax/PackageContents.xml +32 -0
  8. preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +8 -0
  9. preditor/dccs/studiomax/README.md +17 -0
  10. preditor/dccs/studiomax/preditor.ms +16 -0
  11. preditor/dccs/studiomax/preditor_menu.mnx +7 -0
  12. preditor/debug.py +7 -3
  13. preditor/excepthooks.py +1 -1
  14. preditor/gui/app.py +2 -2
  15. preditor/gui/codehighlighter.py +10 -24
  16. preditor/gui/completer.py +17 -6
  17. preditor/gui/console.py +94 -47
  18. preditor/gui/dialog.py +10 -7
  19. preditor/gui/drag_tab_bar.py +7 -7
  20. preditor/gui/errordialog.py +2 -2
  21. preditor/gui/find_files.py +7 -5
  22. preditor/gui/fuzzy_search/fuzzy_search.py +8 -4
  23. preditor/gui/group_tab_widget/__init__.py +32 -4
  24. preditor/gui/group_tab_widget/grouped_tab_models.py +4 -4
  25. preditor/gui/group_tab_widget/grouped_tab_widget.py +6 -4
  26. preditor/gui/level_buttons.py +16 -1
  27. preditor/gui/loggerwindow.py +48 -27
  28. preditor/gui/set_text_editor_path_dialog.py +3 -1
  29. preditor/gui/ui/loggerwindow.ui +11 -1
  30. preditor/gui/window.py +4 -4
  31. preditor/gui/workbox_mixin.py +43 -14
  32. preditor/gui/workbox_text_edit.py +7 -5
  33. preditor/gui/workboxwidget.py +25 -16
  34. preditor/logging_config.py +5 -2
  35. preditor/scintilla/__init__.py +19 -1
  36. preditor/scintilla/delayables/smart_highlight.py +7 -4
  37. preditor/scintilla/delayables/spell_check.py +5 -4
  38. preditor/scintilla/documenteditor.py +228 -135
  39. preditor/scintilla/finddialog.py +3 -3
  40. preditor/scintilla/lang/language.py +1 -1
  41. preditor/scintilla/lexers/cpplexer.py +3 -2
  42. preditor/scintilla/lexers/javascriptlexer.py +6 -4
  43. preditor/scintilla/lexers/maxscriptlexer.py +8 -7
  44. preditor/scintilla/lexers/mellexer.py +3 -2
  45. preditor/scintilla/lexers/mulexer.py +3 -2
  46. preditor/scintilla/lexers/pythonlexer.py +7 -6
  47. preditor/utils/cute.py +9 -8
  48. preditor/version.py +16 -3
  49. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/METADATA +69 -32
  50. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/RECORD +56 -47
  51. preditor-1.3.0.dist-info/top_level.txt +3 -0
  52. tests/find_files/test_find_files.py +74 -0
  53. tests/ide/test_delayable_engine.py +171 -0
  54. preditor-1.1.0.dist-info/top_level.txt +0 -1
  55. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/WHEEL +0 -0
  56. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/entry_points.txt +0 -0
  57. {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
- from PyQt5.Qsci import QsciScintilla
23
- from PyQt5.QtCore import QTextCodec
24
- from Qt import QtCompat
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 lang
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._textCodec = None
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
- command = commands.boundTo(Qt.ControlModifier | Qt.Key_Slash)
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(Qt.ControlModifier | Qt.ShiftModifier | Qt.Key_Up)
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(Qt.ControlModifier | Qt.ShiftModifier | Qt.Key_Down)
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(Qt.ControlModifier | Qt.ShiftModifier | Qt.Key_D)
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, self, context=Qt.WidgetShortcut
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 | QMessageBox.No | QMessageBox.Cancel,
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
- cursorLine, cursorIndex = self.expandCursorToLineSelection()
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, cursorIndex, removed = self.removeComment(
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
- cursorIndex,
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
- if cursorLine is not None:
365
- startLine, endLine = cursorLine, cursorLine
366
- startCol, endCol = cursorIndex, cursorIndex
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
- line, index = None, None
431
- if not self.hasSelectedText():
432
- line, index = self.getCursorPosition()
433
- self.setSelection(line, 0, line, self.lineLength(line))
434
- return line, index
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 self.EolWindows
560
+ return QsciScintilla.EolMode.EolWindows
512
561
  elif newlineR == newlineN + 1:
513
- # LF CR ACorn and RISC unsuported
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 self.EolUnix
567
+ return QsciScintilla.EolMode.EolUnix
519
568
  else:
520
569
  # first return is a CR
521
- return self.EolMac
570
+ return QsciScintilla.EolMode.EolMac
522
571
  if newlineN != -1:
523
- return self.EolUnix
572
+ return QsciScintilla.EolMode.EolUnix
524
573
  if sys.platform == 'win32':
525
- return self.EolWindows
526
- return self.EolUnix
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() == event.Close and not self.checkForSave():
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
- f = QFile(filename)
661
- f.open(QFile.ReadOnly)
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(self.SCI_SETTARGETSTART, find_state.start_pos)
723
- self.SendScintilla(self.SCI_SETTARGETEND, find_state.end_pos)
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(self.SCI_SEARCHINTARGET, len(expr), expr)
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(self.SCI_SETSEARCHFLAGS, find_state.flags)
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(self.SCI_GETLENGTH)
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(self.SCI_GETLENGTH)
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(self.SCI_GETLENGTH)
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(self.SCI_GETTARGETSTART)
773
- target_end = self.SendScintilla(self.SCI_GETTARGETEND)
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=(QMessageBox.Yes | QMessageBox.No),
822
- defaultButton=QMessageBox.Yes,
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
- if key == Qt.Key_Backtab:
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(self.SCI_POINTXFROMPOSITION, 0, position)
846
- y = self.SendScintilla(self.SCI_POINTYFROMPOSITION, 0, position)
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(self.EdgeNone)
945
+ self.setEdgeMode(QsciScintilla.EdgeMode.EdgeNone)
871
946
 
872
- # set autocompletion settings
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
- self.setMarginWidth(0, QFontMetrics(self.marginsFont()).width('0000000') + 5)
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(self.SCI_GETMULTIPLESELECTION)
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(self.SCI_GETMULTIPLESELECTION)
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(self.SCI_GETMULTIPASTE)
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 == self.EolWindows:
1009
+ if mode == QsciScintilla.EolMode.EolWindows:
930
1010
  return '\r\n'
931
- elif mode == self.EolUnix:
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(), title, message, QMessageBox.Yes | QMessageBox.No
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(searchtext, Qt.CaseInsensitive)
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
- f = QFile(filename)
1095
- f.open(QFile.WriteOnly)
1096
- # make sure the file is writeable
1097
- if f.error() != QFile.NoError:
1098
- logger.debug('An error occured while saving')
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 Code: %i' % f.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
- # Attempt to save the file using the same codec that it used to display it
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(self.SCI_WORDSTARTPOSITION, start, True)
1169
- end_pos = self.SendScintilla(self.SCI_WORDENDPOSITION, start, True)
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(self.SCI_SETWORDCHARS, wordCharacters.encode('utf8'))
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(self.SCI_SETMULTIPLESELECTION, state)
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(self.SCI_SETADDITIONALSELECTIONTYPING, state)
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(self.SCI_SETMULTIPASTE, state)
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(self.SCI_GOTOPOS, self.pos)
1406
+ self.SendScintilla(QsciScintilla.SCI_GOTOPOS, self.pos)
1324
1407
 
1325
1408
  def correctSpelling(self, action):
1326
- self.SendScintilla(self.SCI_GOTOPOS, self.pos)
1327
- self.SendScintilla(self.SCI_SETANCHOR, self.anchor)
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(self.SCI_REPLACESEL, action.text())
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(self.SCI_LINEFROMPOSITION, pos)
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(self.SCI_POSITIONFROMLINE, line),
1369
- self.SendScintilla(self.SCI_GETLINEENDPOSITION, lines_to_check),
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(self.SCI_POSITIONFROMPOINT, x, y)
1477
+ positionMouse = self.SendScintilla(
1478
+ QsciScintilla.SCI_POSITIONFROMPOINT, x, y
1479
+ )
1393
1480
  wordStartPosition = self.SendScintilla(
1394
- self.SCI_WORDSTARTPOSITION, positionMouse, True
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 self.whitespaceVisibility() == QsciScintilla.WsVisible
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(QApplication.instance().keyboardModifiers() == Qt.ShiftModifier)
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._textCodec and self._textCodec.name() != 'System':
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 self._enableFontResizing and event.modifiers() == Qt.ControlModifier:
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())