PrEditor 1.0.0__py3-none-any.whl → 1.2.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/config.py +16 -0
  4. preditor/dccs/.hab.json +10 -0
  5. preditor/dccs/maya/PrEditor_maya.mod +0 -1
  6. preditor/dccs/maya/README.md +22 -0
  7. preditor/dccs/maya/plug-ins/PrEditor_maya.py +32 -1
  8. preditor/dccs/studiomax/PackageContents.xml +32 -0
  9. preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +8 -0
  10. preditor/dccs/studiomax/README.md +17 -0
  11. preditor/dccs/studiomax/preditor.ms +16 -0
  12. preditor/dccs/studiomax/preditor_menu.mnx +7 -0
  13. preditor/debug.py +7 -3
  14. preditor/excepthooks.py +15 -6
  15. preditor/gui/app.py +2 -2
  16. preditor/gui/codehighlighter.py +10 -24
  17. preditor/gui/completer.py +17 -6
  18. preditor/gui/console.py +77 -47
  19. preditor/gui/dialog.py +10 -7
  20. preditor/gui/drag_tab_bar.py +7 -7
  21. preditor/gui/errordialog.py +2 -2
  22. preditor/gui/find_files.py +7 -5
  23. preditor/gui/fuzzy_search/fuzzy_search.py +8 -4
  24. preditor/gui/group_tab_widget/__init__.py +4 -4
  25. preditor/gui/group_tab_widget/grouped_tab_models.py +4 -4
  26. preditor/gui/group_tab_widget/grouped_tab_widget.py +6 -4
  27. preditor/gui/level_buttons.py +16 -1
  28. preditor/gui/loggerwindow.py +51 -28
  29. preditor/gui/set_text_editor_path_dialog.py +3 -1
  30. preditor/gui/window.py +4 -4
  31. preditor/gui/workbox_mixin.py +40 -11
  32. preditor/gui/workbox_text_edit.py +5 -3
  33. preditor/gui/workboxwidget.py +16 -12
  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 +165 -116
  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.0.0.dist-info → preditor-1.2.0.dist-info}/METADATA +69 -32
  50. {preditor-1.0.0.dist-info → preditor-1.2.0.dist-info}/RECORD +56 -47
  51. preditor-1.2.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.0.0.dist-info/top_level.txt +0 -1
  55. {preditor-1.0.0.dist-info → preditor-1.2.0.dist-info}/WHEEL +0 -0
  56. {preditor-1.0.0.dist-info → preditor-1.2.0.dist-info}/entry_points.txt +0 -0
  57. {preditor-1.0.0.dist-info → preditor-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function
2
2
 
3
3
  import itertools
4
4
  import json
5
+ import logging
5
6
  import os
6
7
  import re
7
8
  import sys
@@ -11,15 +12,17 @@ from datetime import datetime, timedelta
11
12
  from functools import partial
12
13
 
13
14
  import __main__
15
+ import Qt as Qt_py
14
16
  from Qt import QtCompat, QtCore, QtWidgets
15
17
  from Qt.QtCore import QByteArray, Qt, QTimer, Signal, Slot
16
- from Qt.QtGui import QCursor, QFont, QIcon, QTextCursor
18
+ from Qt.QtGui import QCursor, QFont, QIcon, QKeySequence, QTextCursor
17
19
  from Qt.QtWidgets import (
18
20
  QApplication,
19
21
  QFontDialog,
20
22
  QInputDialog,
21
23
  QMessageBox,
22
24
  QTextBrowser,
25
+ QTextEdit,
23
26
  QToolTip,
24
27
  QVBoxLayout,
25
28
  )
@@ -27,7 +30,7 @@ from Qt.QtWidgets import (
27
30
  from .. import (
28
31
  DEFAULT_CORE_NAME,
29
32
  about_preditor,
30
- core,
33
+ config,
31
34
  debug,
32
35
  get_core_name,
33
36
  osystem,
@@ -46,6 +49,8 @@ from .level_buttons import LoggingLevelButton
46
49
  from .set_text_editor_path_dialog import SetTextEditorPathDialog
47
50
  from .status_label import StatusLabel
48
51
 
52
+ logger = logging.getLogger(__name__)
53
+
49
54
 
50
55
  class WorkboxPages:
51
56
  """Nice names for the uiWorkboxSTACK indexes."""
@@ -195,7 +200,7 @@ class LoggerWindow(Window):
195
200
  self.uiCompleterModeMENU.addSeparator()
196
201
  action = self.uiCompleterModeMENU.addAction('Cycle mode')
197
202
  action.setObjectName('uiCycleModeACT')
198
- action.setShortcut(Qt.CTRL | Qt.Key_M)
203
+ action.setShortcut(QKeySequence(Qt.Modifier.CTRL | Qt.Key.Key_M))
199
204
  action.triggered.connect(self.cycleCompleterMode)
200
205
  self.uiCompleterModeMENU.hovered.connect(self.handleMenuHovered)
201
206
 
@@ -487,7 +492,7 @@ class LoggerWindow(Window):
487
492
 
488
493
  def openSetPreferredTextEditorDialog(self):
489
494
  dlg = SetTextEditorPathDialog(parent=self)
490
- dlg.exec_()
495
+ dlg.exec()
491
496
 
492
497
  def focusToConsole(self):
493
498
  """Move focus to the console"""
@@ -526,7 +531,7 @@ class LoggerWindow(Window):
526
531
 
527
532
  cursor = console.textCursor()
528
533
  if not cursor.hasSelection():
529
- cursor.select(QTextCursor.LineUnderCursor)
534
+ cursor.select(QTextCursor.SelectionType.LineUnderCursor)
530
535
  text = cursor.selectedText()
531
536
  prompt = console.prompt()
532
537
  if text.startswith(prompt):
@@ -562,7 +567,7 @@ class LoggerWindow(Window):
562
567
 
563
568
  def wheelEvent(self, event):
564
569
  """adjust font size on ctrl+scrollWheel"""
565
- if event.modifiers() == Qt.ControlModifier:
570
+ if event.modifiers() == Qt.KeyboardModifier.ControlModifier:
566
571
  # WheelEvents can be emitted in a cluster, but we only want one at a time
567
572
  # (ie to change font size by 1, rather than 2 or 3). Let's bail if previous
568
573
  # font-resize wheel event was within a certain threshhold.
@@ -602,7 +607,10 @@ class LoggerWindow(Window):
602
607
  else:
603
608
  text = action.toolTip()
604
609
 
605
- menu = action.parentWidget()
610
+ if Qt_py.IsPyQt4:
611
+ menu = action.parentWidget()
612
+ else:
613
+ menu = action.parent()
606
614
  QToolTip.showText(QCursor.pos(), text, menu)
607
615
 
608
616
  def selectFont(self, monospace=False, proportional=False):
@@ -617,13 +625,16 @@ class LoggerWindow(Window):
617
625
  curFontFamily = origFont.family()
618
626
 
619
627
  if monospace and proportional:
620
- options = QFontDialog.MonospacedFonts | QFontDialog.ProportionalFonts
628
+ options = (
629
+ QFontDialog.FontDialogOption.MonospacedFonts
630
+ | QFontDialog.FontDialogOption.ProportionalFonts
631
+ )
621
632
  kind = "monospace or proportional "
622
633
  elif monospace:
623
- options = QFontDialog.MonospacedFonts
634
+ options = QFontDialog.FontDialogOption.MonospacedFonts
624
635
  kind = "monospace "
625
636
  elif proportional:
626
- options = QFontDialog.ProportionalFonts
637
+ options = QFontDialog.FontDialogOption.ProportionalFonts
627
638
  kind = "proportional "
628
639
 
629
640
  # Present a QFontDialog for user to choose a font
@@ -683,9 +694,9 @@ class LoggerWindow(Window):
683
694
 
684
695
  def adjustWorkboxOrientation(self, state):
685
696
  if state:
686
- self.uiSplitterSPLIT.setOrientation(Qt.Horizontal)
697
+ self.uiSplitterSPLIT.setOrientation(Qt.Orientation.Horizontal)
687
698
  else:
688
- self.uiSplitterSPLIT.setOrientation(Qt.Vertical)
699
+ self.uiSplitterSPLIT.setOrientation(Qt.Orientation.Vertical)
689
700
 
690
701
  def backupPreferences(self):
691
702
  """Saves a copy of the current preferences to a zip archive."""
@@ -754,7 +765,11 @@ class LoggerWindow(Window):
754
765
 
755
766
  def keyPressEvent(self, event):
756
767
  # Fix 'Maya : Qt tools lose focus' https://redmine.blur.com/issues/34430
757
- if event.modifiers() & (Qt.AltModifier | Qt.ControlModifier | Qt.ShiftModifier):
768
+ if event.modifiers() & (
769
+ Qt.KeyboardModifier.AltModifier
770
+ | Qt.KeyboardModifier.ControlModifier
771
+ | Qt.KeyboardModifier.ShiftModifier
772
+ ):
758
773
  pass
759
774
  else:
760
775
  super(LoggerWindow, self).keyPressEvent(event)
@@ -778,7 +793,7 @@ class LoggerWindow(Window):
778
793
  pref.update(
779
794
  {
780
795
  'loggergeom': [geo.x(), geo.y(), geo.width(), geo.height()],
781
- 'windowState': int(self.windowState()),
796
+ 'windowState': QtCompat.enumValue(self.windowState()),
782
797
  'SplitterVertical': self.uiEditorVerticalACT.isChecked(),
783
798
  'SplitterSize': self.uiSplitterSPLIT.sizes(),
784
799
  'tabIndent': self.uiIndentationsTabsACT.isChecked(),
@@ -860,7 +875,7 @@ class LoggerWindow(Window):
860
875
  if dialog.objectName() in self.dont_ask_again:
861
876
  return
862
877
 
863
- dialog.exec_()
878
+ dialog.exec()
864
879
 
865
880
  def restartLogger(self):
866
881
  """Closes this PrEditor instance and starts a new process with the same
@@ -908,7 +923,7 @@ class LoggerWindow(Window):
908
923
  sizes = pref.get('SplitterSize')
909
924
  if sizes:
910
925
  self.uiSplitterSPLIT.setSizes(sizes)
911
- self.setWindowState(Qt.WindowStates(pref.get('windowState', 0)))
926
+ self.setWindowState(Qt.WindowState(pref.get('windowState', 0)))
912
927
  self.uiIndentationsTabsACT.setChecked(pref.get('tabIndent', True))
913
928
  self.uiCopyTabsToSpacesACT.setChecked(pref.get('copyIndentsAsSpaces', False))
914
929
 
@@ -980,7 +995,7 @@ class LoggerWindow(Window):
980
995
  _font = pref.get('consoleFont', None)
981
996
  if _font:
982
997
  font = QFont()
983
- if font.fromString(_font):
998
+ if QtCompat.QFont.fromString(font, _font):
984
999
  self.console().setConsoleFont(font)
985
1000
 
986
1001
  self.dont_ask_again = pref.get('dont_ask_again', [])
@@ -1163,9 +1178,9 @@ class LoggerWindow(Window):
1163
1178
 
1164
1179
  def setWordWrap(self, state):
1165
1180
  if state:
1166
- self.uiConsoleTXT.setLineWrapMode(self.uiConsoleTXT.WidgetWidth)
1181
+ self.uiConsoleTXT.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
1167
1182
  else:
1168
- self.uiConsoleTXT.setLineWrapMode(self.uiConsoleTXT.NoWrap)
1183
+ self.uiConsoleTXT.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
1169
1184
 
1170
1185
  def show_about(self):
1171
1186
  """Shows `preditor.about_preditor()`'s output in a message box."""
@@ -1245,7 +1260,7 @@ class LoggerWindow(Window):
1245
1260
 
1246
1261
  # if this is the global instance, then allow it to be deleted on close
1247
1262
  if self == LoggerWindow._instance:
1248
- self.setAttribute(Qt.WA_DeleteOnClose, True)
1263
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
1249
1264
  LoggerWindow._instance = None
1250
1265
 
1251
1266
  # clear out the system
@@ -1335,18 +1350,16 @@ class LoggerWindow(Window):
1335
1350
  parent, name=name, run_workbox=run_workbox, standalone=standalone
1336
1351
  )
1337
1352
 
1338
- # RV has a Unique window structure. It makes more sense to not parent a
1339
- # singleton window than to parent it to a specific top level window.
1340
- if core.objectName() == 'rv':
1341
- inst.setParent(None)
1342
- inst.setAttribute(Qt.WA_QuitOnClose, False)
1343
-
1344
1353
  # protect the memory
1345
- inst.setAttribute(Qt.WA_DeleteOnClose, False)
1354
+ inst.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False)
1346
1355
 
1347
1356
  # cache the instance
1348
1357
  LoggerWindow._instance = inst
1349
1358
 
1359
+ # Allow customization when the instance is first created.
1360
+ if config.on_create_callback:
1361
+ config.on_create_callback(inst)
1362
+
1350
1363
  return LoggerWindow._instance
1351
1364
 
1352
1365
  def installLogToFile(self):
@@ -1380,6 +1393,16 @@ class LoggerWindow(Window):
1380
1393
  bool: If a shutdown was required
1381
1394
  """
1382
1395
  if cls._instance:
1383
- cls._instance.shutdown()
1396
+ try:
1397
+ cls._instance.shutdown()
1398
+ except RuntimeError as error:
1399
+ # If called after the host Qt application has been closed then
1400
+ # the instance has been deleted and we can't save preferences
1401
+ # without getting a RuntimeError about C/C++ being deleted.
1402
+ logger.warning(
1403
+ f"instance_shutdown failed PrEditor prefs likely not saved: {error}"
1404
+ )
1405
+ return False
1406
+
1384
1407
  return True
1385
1408
  return False
@@ -56,4 +56,6 @@ class SetTextEditorPathDialog(QDialog):
56
56
  else:
57
57
  msg = "That path doesn't exists or isn't an executable file."
58
58
  label = 'Incorrect Path'
59
- QMessageBox.warning(self.window(), label, msg, QMessageBox.Ok)
59
+ QMessageBox.warning(
60
+ self.window(), label, msg, QMessageBox.StandardButton.Ok
61
+ )
preditor/gui/window.py CHANGED
@@ -25,7 +25,7 @@ class Window(QMainWindow):
25
25
  if not cls._instance:
26
26
  cls._instance = cls(parent=parent)
27
27
  # protect the memory
28
- cls._instance.setAttribute(Qt.WA_DeleteOnClose, False)
28
+ cls._instance.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False)
29
29
  return cls._instance
30
30
 
31
31
  def __init__(self, parent=None, flags=0):
@@ -67,7 +67,7 @@ class Window(QMainWindow):
67
67
  # dead dialogs
68
68
 
69
69
  # set the delete attribute to clean up the window once it is closed
70
- self.setAttribute(Qt.WA_DeleteOnClose, True)
70
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
71
71
  # If this value is set to False calling setGeometry on this window will not
72
72
  # adjust the geometry to ensure the window is on a valid screen.
73
73
  self.checkScreenGeo = True
@@ -103,7 +103,7 @@ class Window(QMainWindow):
103
103
  def closeEvent(self, event):
104
104
  # ensure this object gets deleted
105
105
  wwidget = None
106
- if self.testAttribute(Qt.WA_DeleteOnClose):
106
+ if self.testAttribute(Qt.WidgetAttribute.WA_DeleteOnClose):
107
107
  # collect the win widget to uncache it
108
108
  if self.parent() and self.parent().inherits('QWinWidget'):
109
109
  wwidget = self.parent()
@@ -141,7 +141,7 @@ class Window(QMainWindow):
141
141
  # allow the global instance to be cleared
142
142
  if this == cls._instance:
143
143
  cls._instance = None
144
- this.setAttribute(Qt.WA_DeleteOnClose, True)
144
+ this.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
145
145
  try:
146
146
  this.close()
147
147
  except RuntimeError:
@@ -1,9 +1,11 @@
1
1
  from __future__ import absolute_import, print_function
2
2
 
3
+ import io
3
4
  import os
4
5
  import tempfile
5
6
  import textwrap
6
7
 
8
+ import chardet
7
9
  from Qt.QtCore import Qt
8
10
  from Qt.QtWidgets import QStackedWidget
9
11
 
@@ -317,14 +319,37 @@ class WorkboxMixin(object):
317
319
  os.remove(tempfile)
318
320
 
319
321
  @classmethod
320
- def __open_file__(cls, filename):
321
- with open(filename) as fle:
322
- return fle.read()
323
- return ""
322
+ def __open_file__(cls, filename, strict=True):
323
+ """Open a file and try to detect the text encoding it was saved as.
324
+
325
+ Returns:
326
+ encoding(str): The detected encoding, Defaults to "utf-8" if unable
327
+ to detect encoding.
328
+ text(str): The contents of the file decoded to a str.
329
+ """
330
+ with open(filename, "rb") as f:
331
+ text_bytes = f.read()
332
+
333
+ # Open file, detect source encoding and convert to utf-8
334
+ encoding = chardet.detect(text_bytes)['encoding'] or 'utf-8'
335
+ try:
336
+ text = text_bytes.decode(encoding)
337
+ except UnicodeDecodeError as e:
338
+ if strict:
339
+ raise UnicodeDecodeError( # noqa: B904
340
+ e.encoding,
341
+ e.object,
342
+ e.start,
343
+ e.end,
344
+ f"{e.reason}, Filename: {filename}",
345
+ )
346
+ encoding = 'utf-8'
347
+ text = text_bytes.decode(encoding, errors="ignore")
348
+ return encoding, text
324
349
 
325
350
  @classmethod
326
- def __write_file__(cls, filename, txt):
327
- with open(filename, 'w') as fle:
351
+ def __write_file__(cls, filename, txt, encoding=None):
352
+ with io.open(filename, 'w', newline='\n', encoding=encoding) as fle:
328
353
  fle.write(txt)
329
354
 
330
355
  def __show__(self):
@@ -335,7 +360,7 @@ class WorkboxMixin(object):
335
360
  if self._filename_pref:
336
361
  self.__load__(self._filename_pref)
337
362
  elif self._tempfile:
338
- txt = self.__open_file__(self.__tempfile__())
363
+ _, txt = self.__open_file__(self.__tempfile__(), strict=False)
339
364
  self.__set_text__(txt)
340
365
 
341
366
  def process_shortcut(self, event, run=True):
@@ -365,10 +390,14 @@ class WorkboxMixin(object):
365
390
  modifiers = event.modifiers()
366
391
 
367
392
  # Determine which relevant combos are pressed
368
- ret = key == Qt.Key_Return
369
- enter = key == Qt.Key_Enter
370
- shift = modifiers == Qt.ShiftModifier
371
- ctrlShift = modifiers == Qt.ControlModifier | Qt.ShiftModifier
393
+ ret = key == Qt.Key.Key_Return
394
+ enter = key == Qt.Key.Key_Enter
395
+ shift = modifiers == Qt.KeyboardModifier.ShiftModifier
396
+ ctrlShift = (
397
+ modifiers
398
+ == Qt.KeyboardModifier.ControlModifier
399
+ | Qt.KeyboardModifier.ShiftModifier
400
+ )
372
401
 
373
402
  # Determine which actions to take
374
403
  evalTrunc = enter or (ret and shift)
@@ -27,6 +27,7 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
27
27
  ):
28
28
  super(WorkboxTextEdit, self).__init__(parent=parent, core_name=core_name)
29
29
  self._filename = None
30
+ self._encoding = None
30
31
  self.__set_console__(console)
31
32
  highlight = CodeHighlighter(self)
32
33
  highlight.setLanguage('Python')
@@ -64,7 +65,7 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
64
65
 
65
66
  def __set_font__(self, font):
66
67
  metrics = QFontMetrics(font)
67
- self.setTabStopDistance(metrics.width(" ") * 4)
68
+ self.setTabStopDistance(metrics.horizontalAdvance(" ") * 4)
68
69
  super(WorkboxTextEdit, self).setFont(font)
69
70
 
70
71
  def __goto_line__(self, line):
@@ -79,7 +80,8 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
79
80
 
80
81
  def __load__(self, filename):
81
82
  self._filename = filename
82
- txt = self.__open_file__(self._filename)
83
+ enc, txt = self.__open_file__(self._filename)
84
+ self._encoding = enc
83
85
  self.__set_text__(txt)
84
86
 
85
87
  def __margins_font__(self):
@@ -114,7 +116,7 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
114
116
 
115
117
  selectText = self.window().uiSelectTextACT.isChecked() or selectText
116
118
  if selectText:
117
- cursor.select(QTextCursor.LineUnderCursor)
119
+ cursor.select(QTextCursor.SelectionType.LineUnderCursor)
118
120
  self.setTextCursor(cursor)
119
121
 
120
122
  return text, line
@@ -1,6 +1,5 @@
1
1
  from __future__ import absolute_import, print_function
2
2
 
3
- import io
4
3
  import re
5
4
  import time
6
5
 
@@ -10,6 +9,7 @@ from Qt.QtWidgets import QAction
10
9
 
11
10
  from .. import core, resourcePath
12
11
  from ..gui.workbox_mixin import WorkboxMixin
12
+ from ..scintilla import QsciScintilla
13
13
  from ..scintilla.documenteditor import DocumentEditor, SearchOptions
14
14
  from ..scintilla.finddialog import FindDialog
15
15
 
@@ -36,15 +36,19 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
36
36
  self.initShortcuts()
37
37
  self.setLanguage('Python')
38
38
  # Default to unix newlines
39
- self.setEolMode(self.EolUnix)
39
+ self.setEolMode(QsciScintilla.EolMode.EolUnix)
40
40
  if hasattr(self.window(), "setWorkboxFontBasedOnConsole"):
41
41
  self.window().setWorkboxFontBasedOnConsole()
42
42
 
43
43
  def __auto_complete_enabled__(self):
44
- return self.autoCompletionSource() == self.AcsAll
44
+ return self.autoCompletionSource() == QsciScintilla.AutoCompletionSource.AcsAll
45
45
 
46
46
  def __set_auto_complete_enabled__(self, state):
47
- state = self.AcsAll if state else self.AcsNone
47
+ state = (
48
+ QsciScintilla.AutoCompletionSource.AcsAll
49
+ if state
50
+ else QsciScintilla.AutoCompletionSource.AcsNone
51
+ )
48
52
  self.setAutoCompletionSource(state)
49
53
 
50
54
  def __clear__(self):
@@ -120,7 +124,7 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
120
124
  try:
121
125
  marker = self._marker
122
126
  except AttributeError:
123
- self._marker = self.markerDefine(self.Circle)
127
+ self._marker = self.markerDefine(QsciScintilla.MarkerSymbol.Circle)
124
128
  marker = self._marker
125
129
  self.markerAdd(line, marker)
126
130
 
@@ -197,10 +201,10 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
197
201
  self.setText(txt)
198
202
 
199
203
  @classmethod
200
- def __write_file__(cls, filename, txt):
201
- with io.open(filename, 'w', newline='\n') as fle:
202
- # Save unix newlines for simplicity
203
- fle.write(cls.__unix_end_lines__(txt))
204
+ def __write_file__(cls, filename, txt, encoding=None):
205
+ # Save unix newlines for simplicity
206
+ txt = cls.__unix_end_lines__(txt)
207
+ super(WorkboxWidget, cls).__write_file__(filename, txt, encoding=encoding)
204
208
 
205
209
  def keyPressEvent(self, event):
206
210
  """Check for certain keyboard shortcuts, and handle them as needed,
@@ -216,13 +220,13 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
216
220
  when Return is pressed), so this combination is not detectable.
217
221
  """
218
222
  if self._software == 'softimage':
219
- DocumentEditor.keyPressEvent(self, event)
223
+ super(WorkboxWidget, self).keyPressEvent(event)
220
224
  else:
221
225
  if self.process_shortcut(event):
222
226
  return
223
227
  else:
224
228
  # Send regular keystroke
225
- DocumentEditor.keyPressEvent(self, event)
229
+ super(WorkboxWidget, self).keyPressEvent(event)
226
230
 
227
231
  def initShortcuts(self):
228
232
  """Use this to set up shortcuts when the DocumentEditor"""
@@ -248,7 +252,7 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
248
252
 
249
253
  # create the search dialog and connect actions
250
254
  self._searchDialog = FindDialog(self)
251
- self._searchDialog.setAttribute(Qt.WA_DeleteOnClose, False)
255
+ self._searchDialog.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False)
252
256
  self.uiFindACT.triggered.connect(
253
257
  lambda: self._searchDialog.search(self.searchText())
254
258
  )
@@ -9,9 +9,12 @@ from .prefs import prefs_path
9
9
 
10
10
 
11
11
  class LoggingConfig(object):
12
- def __init__(self, core_name, version=1):
12
+ def __init__(self, core_name, version=1, disable_existing_loggers=False):
13
13
  self._filename = None
14
- self.cfg = {'version': version}
14
+ self.cfg = {
15
+ 'version': version,
16
+ 'disable_existing_loggers': disable_existing_loggers,
17
+ }
15
18
  self.core_name = core_name
16
19
 
17
20
  def add_logger(self, name, logger):
@@ -1,5 +1,23 @@
1
1
  from __future__ import absolute_import
2
2
 
3
+ __all__ = ["delayables", "FindState", "Qsci", "QsciScintilla"]
4
+
5
+ import Qt
6
+
7
+ if Qt.IsPyQt6:
8
+ from PyQt6 import Qsci
9
+ from PyQt6.Qsci import QsciScintilla
10
+ elif Qt.IsPyQt5:
11
+ from PyQt5 import Qsci
12
+ from PyQt5.Qsci import QsciScintilla
13
+ elif Qt.IsPyQt4:
14
+ from PyQt4 import Qsci
15
+ from PyQt4.Qsci import QsciScintilla
16
+ else:
17
+ raise ImportError(
18
+ "QScintilla library is not supported by {}".format(Qt.__binding__)
19
+ )
20
+
3
21
 
4
22
  class FindState(object):
5
23
  """
@@ -19,4 +37,4 @@ class FindState(object):
19
37
  self.end_pos = None
20
38
 
21
39
 
22
- from . import delayables # noqa: F401, E402
40
+ from . import delayables # noqa: E402
@@ -1,17 +1,17 @@
1
1
  from __future__ import absolute_import, print_function
2
2
 
3
- from PyQt5.Qsci import QsciScintilla
3
+ import Qt
4
4
  from Qt.QtCore import QSignalMapper
5
5
  from Qt.QtWidgets import QWidget
6
6
 
7
7
  from ...delayable_engine.delayables import SearchDelayable
8
- from .. import FindState
8
+ from .. import FindState, QsciScintilla
9
9
 
10
10
 
11
11
  class SmartHighlight(SearchDelayable):
12
12
  key = 'smart_highlight'
13
13
  indicator_number = 30
14
- indicator_style = QsciScintilla.StraightBoxIndicator
14
+ indicator_style = QsciScintilla.IndicatorStyle.StraightBoxIndicator
15
15
  border_alpha = 255
16
16
 
17
17
  def __init__(self, engine):
@@ -36,7 +36,10 @@ class SmartHighlight(SearchDelayable):
36
36
  )
37
37
 
38
38
  self.signal_mapper.setMapping(document, document)
39
- self.signal_mapper.mapped[QWidget].connect(self.update_highlighter)
39
+ if Qt.IsPyQt4:
40
+ self.signal_mapper.mapped[QWidget].connect(self.update_highlighter)
41
+ else:
42
+ self.signal_mapper.mappedObject.connect(self.update_highlighter)
40
43
  document.selectionChanged.connect(self.signal_mapper.map)
41
44
 
42
45
  def clear_markings(self, document):
@@ -4,12 +4,11 @@ import logging
4
4
  import re
5
5
  import string
6
6
 
7
- from PyQt5.Qsci import QsciScintilla
8
7
  from Qt.QtCore import Qt
9
8
  from Qt.QtGui import QColor
10
9
 
11
10
  from ...delayable_engine.delayables import RangeDelayable
12
- from .. import lang
11
+ from .. import QsciScintilla, lang
13
12
 
14
13
  logger = logging.getLogger(__name__)
15
14
 
@@ -49,12 +48,14 @@ else:
49
48
  # https://www.scintilla.org/ScintillaDox.html#SCI_INDICSETSTYLE
50
49
  # https://qscintilla.com/#clickable_text/indicators
51
50
  document.indicatorDefine(
52
- QsciScintilla.SquiggleLowIndicator, self.indicator_number
51
+ QsciScintilla.IndicatorStyle.SquiggleLowIndicator, self.indicator_number
53
52
  )
54
53
  document.SendScintilla(
55
54
  QsciScintilla.SCI_SETINDICATORCURRENT, self.indicator_number
56
55
  )
57
- document.setIndicatorForegroundColor(QColor(Qt.red), self.indicator_number)
56
+ document.setIndicatorForegroundColor(
57
+ QColor(Qt.GlobalColor.red), self.indicator_number
58
+ )
58
59
 
59
60
  document.SCN_MODIFIED.connect(document.onTextModified)
60
61