1
1
#----------------------------------------------------------------------------------------------------------
2
2
# Wouter Gilsing
3
3
# woutergilsing@hotmail.com
4
- version = '1.3 '
5
- releaseDate = 'Sept 4 2016'
4
+ version = '1.4 '
5
+ releaseDate = 'November 16 2016'
6
6
7
7
#----------------------------------------------------------------------------------------------------------
8
8
#
@@ -201,12 +201,14 @@ def __init__(self, path = ''):
201
201
self .scriptEditorNameLayout .addWidget (self .scriptEditorNameLabel )
202
202
self .scriptEditorNameLayout .addWidget (self .scriptEditorName )
203
203
204
- self .scriptEditorScript = QtGui . QPlainTextEdit ()
204
+ self .scriptEditorScript = scriptEditorWidget ()
205
205
self .scriptEditorScript .setMinimumHeight (200 )
206
206
self .scriptEditorScript .setMinimumWidth (500 )
207
207
self .scriptEditorScript .setReadOnly (True )
208
208
self .scriptEditorScript .setStyleSheet ('background:#262626' )
209
209
210
+ scriptEditorHighlighter (self .scriptEditorScript .document ())
211
+
210
212
scriptEditorFont = QtGui .QFont ()
211
213
scriptEditorFont .setFamily ("Courier" )
212
214
scriptEditorFont .setStyleHint (QtGui .QFont .Monospace )
@@ -448,16 +450,19 @@ def loadScriptEditor(self):
448
450
openFile = open (self .loadedScript ).readlines ()
449
451
for index , line in enumerate (openFile ):
450
452
if not line .startswith ('#' ):
451
- self .scriptEditorScript .setPlainText ('' .join (openFile [index + 1 :]))
453
+ text = '' .join (openFile [index + 1 :]).replace ('\t ' ,' ' * 4 )
454
+ self .scriptEditorScript .setPlainText (text )
452
455
break
453
456
self .scriptEditorScript .setReadOnly (False )
454
457
458
+
455
459
else :
456
460
457
461
#set name
458
462
self .scriptEditorName .setText (open (self .loadedScript + '/_name.json' ).read ())
459
463
self .scriptEditorScript .setReadOnly (True )
460
464
self .scriptEditorScript .setStyleSheet ('background:%s' % lockedColor )
465
+ self .scriptEditorScript .highlightCurrentLine ()
461
466
self .scriptEditorScript .clear ()
462
467
463
468
self .scriptEditorName .setReadOnly (False )
@@ -476,8 +481,6 @@ def loadScriptEditor(self):
476
481
self .scriptEditorName .setStyleSheet ('background:%s' % lockedColor )
477
482
self .scriptEditorScript .setStyleSheet ('background:%s' % lockedColor )
478
483
479
-
480
-
481
484
def importScriptEditor (self ):
482
485
'''
483
486
Set the current content of the script editor by importing an existing file.
@@ -486,7 +489,8 @@ def importScriptEditor(self):
486
489
if self .loadedScript != None :
487
490
488
491
importFile = nuke .getFilename ('select file to import' ,'*.py *.json' )
489
- self .scriptEditorScript .setPlainText (open (importFile ).read ())
492
+ text = open (importFile ).read ().replace ('\t ' ,' ' * 4 )
493
+ self .scriptEditorScript .setPlainText (text )
490
494
491
495
def saveScriptEditor (self ):
492
496
'''
@@ -747,9 +751,474 @@ def openAboutDialog(self):
747
751
aboutDialogInstance .close ()
748
752
aboutDialogInstance = aboutDialog ()
749
753
aboutDialogInstance .show ()
754
+ #------------------------------------------------------------------------------------------------------
755
+ #Script Editor
756
+ #------------------------------------------------------------------------------------------------------
757
+
758
+ class scriptEditorWidget (QtGui .QPlainTextEdit ):
759
+ '''
760
+ Script editor widget.
761
+
762
+
763
+ '''
764
+
765
+ #Signal that will be emitted when the user has changed the text
766
+ userChangedEvent = QtCore .Signal ()
767
+
768
+ def __init__ (self ):
769
+ super (scriptEditorWidget , self ).__init__ ()
770
+
771
+ #Setup line numbers
772
+ self .lineNumberArea = LineNumberArea (self )
773
+ self .blockCountChanged .connect (self .updateLineNumberAreaWidth )
774
+ self .updateRequest .connect (self .updateLineNumberArea )
775
+ self .updateLineNumberAreaWidth ()
776
+
777
+ #highlight line
778
+ self .cursorPositionChanged .connect (self .highlightCurrentLine )
779
+
780
+ #--------------------------------------------------------------------------------------------------
781
+ #Line Numbers
782
+
783
+ #While researching the implementation of line number, I had a look at Nuke's Blinkscript node.
784
+ #This node has an excellent C++ editor, built with Qt.
785
+ #The source code for that editor can be found here (or in Nuke's installation folder):
786
+ #thefoundry.co.uk/products/nuke/developers/100/pythonreference/nukescripts.blinkscripteditor-pysrc.html
787
+ #I stripped and modified the useful bits of the line number related parts of the code
788
+ #and implemented it in the Hotbox Manager. Credits to theFoundry for writing the blinkscripteditor,
789
+ #best example code I could wish for.
790
+ #--------------------------------------------------------------------------------------------------
791
+
792
+ def lineNumberAreaWidth (self ):
793
+ digits = 1
794
+ maxNum = max (1 , self .blockCount ())
795
+ while (maxNum >= 10 ):
796
+ maxNum /= 10
797
+ digits += 1
798
+
799
+ space = 7 + self .fontMetrics ().width ('9' ) * digits
800
+ return space
801
+
802
+ def updateLineNumberAreaWidth (self ):
803
+ self .setViewportMargins (self .lineNumberAreaWidth (), 0 , 0 , 0 )
804
+
805
+ def updateLineNumberArea (self , rect , dy ):
806
+
807
+ if (dy ):
808
+ self .lineNumberArea .scroll (0 , dy )
809
+ else :
810
+ self .lineNumberArea .update (0 , rect .y (), self .lineNumberArea .width (), rect .height ())
811
+
812
+ if (rect .contains (self .viewport ().rect ())):
813
+ self .updateLineNumberAreaWidth ()
814
+
815
+ def resizeEvent (self , event ):
816
+ QtGui .QPlainTextEdit .resizeEvent (self , event )
817
+
818
+ cr = self .contentsRect ()
819
+ self .lineNumberArea .setGeometry (QtCore .QRect (cr .left (), cr .top (), self .lineNumberAreaWidth (), cr .height ()))
820
+
821
+ def lineNumberAreaPaintEvent (self , event ):
822
+
823
+ if self .isReadOnly ():
824
+ return
825
+
826
+ painter = QtGui .QPainter (self .lineNumberArea )
827
+ painter .fillRect (event .rect (), QtGui .QColor (38 , 38 , 38 ))
828
+
829
+ block = self .firstVisibleBlock ()
830
+ blockNumber = block .blockNumber ()
831
+ top = int ( self .blockBoundingGeometry (block ).translated (self .contentOffset ()).top () )
832
+ bottom = top + int ( self .blockBoundingRect (block ).height () )
833
+ currentLine = self .document ().findBlock (self .textCursor ().position ()).blockNumber ()
834
+
835
+ painter .setPen ( self .palette ().color (QtGui .QPalette .Text ) )
836
+
837
+ while (block .isValid () and top <= event .rect ().bottom ()):
838
+
839
+ textColor = QtGui .QColor (155 , 155 , 155 )
840
+
841
+ if blockNumber == currentLine and self .hasFocus ():
842
+ textColor = QtGui .QColor (255 , 170 , 0 )
843
+
844
+ painter .setPen (textColor )
845
+
846
+
847
+ number = "%s " % str (blockNumber + 1 )
848
+ painter .drawText (0 , top , self .lineNumberArea .width (), self .fontMetrics ().height (), QtCore .Qt .AlignRight , number )
849
+
850
+ #Move to the next block
851
+ block = block .next ()
852
+ top = bottom
853
+ bottom = top + int (self .blockBoundingRect (block ).height ())
854
+ blockNumber += 1
855
+
856
+ #--------------------------------------------------------------------------------------------------
857
+ #Auto indent
858
+ #--------------------------------------------------------------------------------------------------
859
+
860
+ def keyPressEvent (self , event ):
861
+ '''
862
+ Custom actions for specific keystrokes
863
+ '''
864
+
865
+
866
+ #if Tab convert to Space
867
+ if event .key () == 16777217 :
868
+ self .indentation ('indent' )
869
+
870
+ #if Shift+Tab remove indent
871
+ elif event .key () == 16777218 :
872
+
873
+ self .indentation ('unindent' )
874
+
875
+ #if BackSpace try to snap to previous indent level
876
+ elif event .key () == 16777219 :
877
+ if not self .unindentBackspace ():
878
+ QtGui .QPlainTextEdit .keyPressEvent (self , event )
879
+
880
+ #if enter or return, match indent level
881
+ elif event .key () in [16777220 ,16777221 ]:
882
+ #QtGui.QPlainTextEdit.keyPressEvent(self, event)
883
+ self .indentNewLine ()
884
+ else :
885
+ QtGui .QPlainTextEdit .keyPressEvent (self , event )
886
+ #--------------------------------------------------------------------------------------------------
887
+
888
+ def getCursorInfo (self ):
889
+
890
+
891
+ self .cursor = self .textCursor ()
892
+
893
+ self .firstChar = self .cursor .selectionStart ()
894
+ self .lastChar = self .cursor .selectionEnd ()
895
+
896
+ self .noSelection = False
897
+ if self .firstChar == self .lastChar :
898
+ self .noSelection = True
899
+
900
+ self .originalPosition = self .cursor .position ()
901
+ self .cursorBlockPos = self .cursor .positionInBlock ()
902
+ #--------------------------------------------------------------------------------------------------
903
+
904
+ def unindentBackspace (self ):
905
+ '''
906
+ #snap to previous indent level
907
+ '''
908
+ self .getCursorInfo ()
909
+
910
+ if not self .noSelection or self .cursorBlockPos == 0 :
911
+ return False
912
+
913
+ #check text in front of cursor
914
+ textInFront = self .document ().findBlock (self .firstChar ).text ()[:self .cursorBlockPos ]
915
+
916
+ #check whether solely spaces
917
+ if textInFront != ' ' * self .cursorBlockPos :
918
+ return False
919
+
920
+ #snap to previous indent level
921
+ spaces = len (textInFront )
922
+ for space in range (spaces - ((spaces - 1 ) / 4 ) * 4 - 1 ):
923
+ self .cursor .deletePreviousChar ()
924
+
925
+ def indentNewLine (self ):
926
+
927
+ #in case selection covers multiple line, make it one line first
928
+ self .insertPlainText ('' )
929
+
930
+ self .getCursorInfo ()
931
+
932
+ #check how many spaces after cursor
933
+ text = self .document ().findBlock (self .firstChar ).text ()
750
934
935
+ textInFront = text [:self .cursorBlockPos ]
936
+
937
+ if len (textInFront ) == 0 :
938
+ self .insertPlainText ('\n ' )
939
+ return
940
+
941
+ indentLevel = 0
942
+ for i in textInFront :
943
+ if i == ' ' :
944
+ indentLevel += 1
945
+ else :
946
+ break
947
+
948
+ indentLevel /= 4
949
+
950
+ #find out whether textInFront's last character was a ':'
951
+ #if that's the case add another indent.
952
+ #ignore any spaces at the end, however also
953
+ #make sure textInFront is not just an indent
954
+ if textInFront .count (' ' ) != len (textInFront ):
955
+ while textInFront [- 1 ] == ' ' :
956
+ textInFront = textInFront [:- 1 ]
957
+
958
+ if textInFront [- 1 ] == ':' :
959
+ indentLevel += 1
960
+
961
+ #new line
962
+ self .insertPlainText ('\n ' )
963
+ #match indent
964
+ self .insertPlainText (' ' * (4 * indentLevel ))
965
+
966
+ def indentation (self , mode ):
967
+
968
+ self .getCursorInfo ()
969
+
970
+ #if nothing is selected and mode is set to indent, simply insert as many
971
+ #space as needed to reach the next indentation level.
972
+ if self .noSelection and mode == 'indent' :
973
+
974
+ remainingSpaces = 4 - (self .cursorBlockPos % 4 )
975
+ self .insertPlainText (' ' * remainingSpaces )
976
+ return
977
+
978
+ selectedBlocks = self .findBlocks (self .firstChar , self .lastChar )
979
+ beforeBlocks = self .findBlocks (last = self .firstChar - 1 , exclude = selectedBlocks )
980
+ afterBlocks = self .findBlocks (first = self .lastChar + 1 , exclude = selectedBlocks )
981
+
982
+ beforeBlocksText = self .blocks2list (beforeBlocks )
983
+ selectedBlocksText = self .blocks2list (selectedBlocks , mode )
984
+ afterBlocksText = self .blocks2list (afterBlocks )
985
+
986
+ combinedText = '\n ' .join (beforeBlocksText + selectedBlocksText + afterBlocksText )
987
+
988
+ #make sure the line count stays the same
989
+ originalBlockCount = len (self .toPlainText ().split ('\n ' ))
990
+ combinedText = '\n ' .join (combinedText .split ('\n ' )[:originalBlockCount ])
991
+
992
+ self .clear ()
993
+ self .setPlainText (combinedText )
994
+
995
+ if self .noSelection :
996
+ self .cursor .setPosition (self .lastChar )
997
+
998
+ #check whether the the orignal selection was from top to bottom or vice versa
999
+ else :
1000
+ if self .originalPosition == self .firstChar :
1001
+ first = self .lastChar
1002
+ last = self .firstChar
1003
+ firstBlockSnap = QtGui .QTextCursor .EndOfBlock
1004
+ lastBlockSnap = QtGui .QTextCursor .StartOfBlock
1005
+ else :
1006
+ first = self .firstChar
1007
+ last = self .lastChar
1008
+ firstBlockSnap = QtGui .QTextCursor .StartOfBlock
1009
+ lastBlockSnap = QtGui .QTextCursor .EndOfBlock
1010
+
1011
+ self .cursor .setPosition (first )
1012
+ self .cursor .movePosition (firstBlockSnap ,QtGui .QTextCursor .MoveAnchor )
1013
+ self .cursor .setPosition (last ,QtGui .QTextCursor .KeepAnchor )
1014
+ self .cursor .movePosition (lastBlockSnap ,QtGui .QTextCursor .KeepAnchor )
1015
+
1016
+ self .setTextCursor (self .cursor )
1017
+
1018
+ def findBlocks (self , first = 0 , last = None , exclude = []):
1019
+ blocks = []
1020
+ if last == None :
1021
+ last = self .document ().characterCount ()
1022
+ for pos in range (first ,last + 1 ):
1023
+ block = self .document ().findBlock (pos )
1024
+ if block not in blocks and block not in exclude :
1025
+ blocks .append (block )
1026
+ return blocks
1027
+
1028
+ def blocks2list (self , blocks , mode = None ):
1029
+ text = []
1030
+ for block in blocks :
1031
+ blockText = block .text ()
1032
+ if mode == 'unindent' :
1033
+ if blockText .startswith (' ' * 4 ):
1034
+ blockText = blockText [4 :]
1035
+ self .lastChar -= 4
1036
+ elif blockText .startswith ('\t ' ):
1037
+ blockText = blockText [1 :]
1038
+ self .lastChar -= 1
1039
+
1040
+ elif mode == 'indent' :
1041
+ blockText = ' ' * 4 + blockText
1042
+ self .lastChar += 4
1043
+
1044
+ text .append (blockText )
1045
+
1046
+ return text
1047
+
1048
+ #--------------------------------------------------------------------------------------------------
1049
+ #syntax hightlighting
1050
+ #--------------------------------------------------------------------------------------------------
1051
+
1052
+ def highlightCurrentLine (self ):
1053
+ '''
1054
+ Highlight currently selected line
1055
+ '''
1056
+ extraSelections = []
1057
+
1058
+ selection = QtGui .QTextEdit .ExtraSelection ()
1059
+
1060
+ lineColor = QtGui .QColor (88 , 88 , 88 , 255 )
1061
+
1062
+ if not self .hasFocus ():
1063
+ lineColor = QtGui .QColor (88 , 88 , 88 , 0 )
1064
+
1065
+ selection .format .setBackground (lineColor )
1066
+ selection .format .setProperty (QtGui .QTextFormat .FullWidthSelection , True )
1067
+ selection .cursor = self .textCursor ()
1068
+ selection .cursor .clearSelection ()
1069
+
1070
+ extraSelections .append (selection )
1071
+
1072
+ self .setExtraSelections (extraSelections )
1073
+
1074
+ class LineNumberArea (QtGui .QWidget ):
1075
+ def __init__ (self , scriptEditor ):
1076
+ super (LineNumberArea , self ).__init__ (scriptEditor )
1077
+
1078
+ self .scriptEditor = scriptEditor
1079
+ self .setStyleSheet ("text-align: center;" )
1080
+
1081
+ def paintEvent (self , event ):
1082
+ self .scriptEditor .lineNumberAreaPaintEvent (event )
1083
+ return
1084
+
1085
+ class scriptEditorHighlighter (QtGui .QSyntaxHighlighter ):
1086
+ '''
1087
+ Modified, simplified version of some code found I found when researching:
1088
+ wiki.python.org/moin/PyQt/Python%20syntax%20highlighting
1089
+ They did an awesome job, so credits to them. I only needed to make some
1090
+ modifications to make it fit my needs.
1091
+ '''
1092
+
1093
+ def __init__ (self , document ):
1094
+
1095
+ super (scriptEditorHighlighter , self ).__init__ (document )
1096
+
1097
+ self .styles = {
1098
+ 'keyword' : self .format ([238 ,117 ,181 ],'bold' ),
1099
+ 'string' : self .format ([242 , 136 , 135 ]),
1100
+ 'comment' : self .format ([143 , 221 , 144 ]),
1101
+ 'numbers' : self .format ([174 , 129 , 255 ])
1102
+ }
1103
+
1104
+ self .keywords = [
1105
+ 'and' , 'assert' , 'break' , 'class' , 'continue' , 'def' ,
1106
+ 'del' , 'elif' , 'else' , 'except' , 'exec' , 'finally' ,
1107
+ 'for' , 'from' , 'global' , 'if' , 'import' , 'in' ,
1108
+ 'is' , 'lambda' , 'not' , 'or' , 'pass' , 'print' ,
1109
+ 'raise' , 'return' , 'try' , 'while' , 'yield'
1110
+ ]
1111
+
1112
+ self .operatorKeywords = [
1113
+ '=' ,'==' , '!=' , '<' , '<=' , '>' , '>=' ,
1114
+ '\+' , '-' , '\*' , '/' , '//' , '\%' , '\*\*' ,
1115
+ '\+=' , '-=' , '\*=' , '/=' , '\%=' ,
1116
+ '\^' , '\|' , '\&' , '\~' , '>>' , '<<'
1117
+ ]
1118
+
1119
+ self .numbers = ['True' , 'False' ,'None' ]
1120
+
1121
+ self .tri_single = (QtCore .QRegExp ("'''" ), 1 , self .styles ['comment' ])
1122
+ self .tri_double = (QtCore .QRegExp ('"""' ), 2 , self .styles ['comment' ])
1123
+
1124
+ #rules
1125
+ rules = []
1126
+
1127
+ rules += [(r'\b%s\b' % i , 0 , self .styles ['keyword' ]) for i in self .keywords ]
1128
+ rules += [(i , 0 , self .styles ['keyword' ]) for i in self .operatorKeywords ]
1129
+ rules += [(r'\b%s\b' % i , 0 , self .styles ['numbers' ]) for i in self .numbers ]
1130
+
1131
+ rules += [
1132
+
1133
+ # integers
1134
+ (r'\b[0-9]+\b' , 0 , self .styles ['numbers' ]),
1135
+ # Double-quoted string, possibly containing escape sequences
1136
+ (r'"[^"\\]*(\\.[^"\\]*)*"' , 0 , self .styles ['string' ]),
1137
+ # Single-quoted string, possibly containing escape sequences
1138
+ (r"'[^'\\]*(\\.[^'\\]*)*'" , 0 , self .styles ['string' ]),
1139
+ # From '#' until a newline
1140
+ (r'#[^\n]*' , 0 , self .styles ['comment' ]),
1141
+ ]
1142
+
1143
+ # Build a QRegExp for each pattern
1144
+ self .rules = [(QtCore .QRegExp (pat ), index , fmt ) for (pat , index , fmt ) in rules ]
1145
+
1146
+ def format (self ,rgb , style = '' ):
1147
+ '''
1148
+ Return a QtGui.QTextCharFormat with the given attributes.
1149
+ '''
1150
+
1151
+ color = QtGui .QColor (* rgb )
1152
+ textFormat = QtGui .QTextCharFormat ()
1153
+ textFormat .setForeground (color )
1154
+
1155
+ if 'bold' in style :
1156
+ textFormat .setFontWeight (QtGui .QFont .Bold )
1157
+ if 'italic' in style :
1158
+ textFormat .setFontItalic (True )
1159
+
1160
+ return textFormat
1161
+
1162
+ def highlightBlock (self , text ):
1163
+ '''
1164
+ Apply syntax highlighting to the given block of text.
1165
+ '''
1166
+ # Do other syntax formatting
1167
+ for expression , nth , format in self .rules :
1168
+ index = expression .indexIn (text , 0 )
1169
+
1170
+ while index >= 0 :
1171
+ # We actually want the index of the nth match
1172
+ index = expression .pos (nth )
1173
+ length = len (expression .cap (nth ))
1174
+ self .setFormat (index , length , format )
1175
+ index = expression .indexIn (text , index + length )
1176
+
1177
+ self .setCurrentBlockState (0 )
1178
+
1179
+ # Do multi-line strings
1180
+ in_multiline = self .match_multiline (text , * self .tri_single )
1181
+ if not in_multiline :
1182
+ in_multiline = self .match_multiline (text , * self .tri_double )
1183
+
1184
+ def match_multiline (self , text , delimiter , in_state , style ):
1185
+ '''
1186
+ Check whether highlighting reuires multiple lines.
1187
+ '''
1188
+ # If inside triple-single quotes, start at 0
1189
+ if self .previousBlockState () == in_state :
1190
+ start = 0
1191
+ add = 0
1192
+ # Otherwise, look for the delimiter on this line
1193
+ else :
1194
+ start = delimiter .indexIn (text )
1195
+ # Move past this match
1196
+ add = delimiter .matchedLength ()
1197
+
1198
+ # As long as there's a delimiter match on this line...
1199
+ while start >= 0 :
1200
+ # Look for the ending delimiter
1201
+ end = delimiter .indexIn (text , start + add )
1202
+ # Ending delimiter on this line?
1203
+ if end >= add :
1204
+ length = end - start + add + delimiter .matchedLength ()
1205
+ self .setCurrentBlockState (0 )
1206
+ # No; multi-line string
1207
+ else :
1208
+ self .setCurrentBlockState (in_state )
1209
+ length = len (text ) - start + add
1210
+ # Apply formatting
1211
+ self .setFormat (start , length , style )
1212
+ # Look for the next match
1213
+ start = delimiter .indexIn (text , start + length )
1214
+
1215
+ # Return True if still inside a multi-line string, False otherwise
1216
+ if self .currentBlockState () == in_state :
1217
+ return True
1218
+ else :
1219
+ return False
751
1220
#------------------------------------------------------------------------------------------------------
752
- #Modified Qt classes
1221
+ #Tree View
753
1222
#------------------------------------------------------------------------------------------------------
754
1223
755
1224
class QTreeViewCustom (QtGui .QTreeView ):
@@ -1389,7 +1858,6 @@ def enterEvent(self, event):
1389
1858
def leaveEvent (self ,event ):
1390
1859
self .deactivate ()
1391
1860
1392
-
1393
1861
def mouseReleaseEvent (self ,event ):
1394
1862
1395
1863
webbrowser .open (self .link )
@@ -1400,17 +1868,17 @@ def mouseReleaseEvent(self,event):
1400
1868
1401
1869
class fileHeader ():
1402
1870
def __init__ (self ,name ):
1403
- self .text = '\n ' .join (['#----------------------------------------------------------------------------------------------------------' ,
1871
+ dividerLine = '-' * 106
1872
+ self .text = '\n ' .join (['#%s' % dividerLine ,
1404
1873
'#' ,
1405
1874
'# AUTOMATICALLY GENERATED FILE TO BE USED BY W_HOTBOX' ,
1406
1875
'#' ,
1407
1876
'# NAME: %s' % name ,
1408
1877
'#' ,
1409
- '#---------------------------------------------------------------------------------------------------------- \n \n ' ])
1878
+ '#%s \n \n ' % dividerLine ])
1410
1879
def getHeader (self ):
1411
1880
return self .text
1412
1881
1413
- #------------------------------------------------------------------------------------------------------
1414
1882
1415
1883
#------------------------------------------------------------------------------------------------------
1416
1884
#Repair
@@ -1562,7 +2030,6 @@ def clearHotboxManager(sections = ['Single','Multiple','All']):
1562
2030
except :
1563
2031
pass
1564
2032
1565
-
1566
2033
#--------------------------------------------------------------------------------------------------
1567
2034
1568
2035
hotboxManagerInstance = None
0 commit comments