33
33
import functools
34
34
import subprocess
35
35
import tempfile
36
+ import threading
36
37
37
38
# TODO: Is there a defusedxml substitute for getDOMImplementation?
38
39
# Is one even necessary, or is it safe to use xml.dom.minidom for that?
39
40
from xml .dom import minidom
40
41
41
- from PyQt5 .QtCore import Qt , pyqtSlot , QTimer
42
+ from PyQt5 .QtCore import Qt , pyqtSlot , QTimer , pyqtSignal
42
43
from PyQt5 import QtGui
43
44
from PyQt5 .QtWidgets import (
44
- QWidget , QGraphicsScene ,
45
+ QWidget ,
45
46
QMessageBox , QDialog , QColorDialog , QFontDialog ,
46
47
QPushButton , QLineEdit , QLabel
47
48
)
@@ -63,6 +64,7 @@ class TitleEditor(QDialog):
63
64
64
65
# Path to ui file
65
66
ui_path = os .path .join (info .PATH , 'windows' , 'ui' , 'title-editor.ui' )
67
+ thumbnailReady = pyqtSignal (object )
66
68
67
69
def __init__ (self , * args , edit_file_path = None , duplicate = False , ** kwargs ):
68
70
@@ -71,7 +73,7 @@ def __init__(self, *args, edit_file_path=None, duplicate=False, **kwargs):
71
73
72
74
# A timer to pause until user input stops before updating the svg
73
75
self .update_timer = QTimer (self )
74
- self .update_timer .setInterval (300 )
76
+ self .update_timer .setInterval (50 )
75
77
self .update_timer .setSingleShot (True )
76
78
self .update_timer .timeout .connect (self .save_and_reload )
77
79
@@ -97,6 +99,7 @@ def __init__(self, *args, edit_file_path=None, duplicate=False, **kwargs):
97
99
log .debug ('Removing custom LD_LIBRARY_PATH from environment variables when launching Inkscape' )
98
100
99
101
# Initialize variables
102
+ self .is_thread_busy = False
100
103
self .template_name = ""
101
104
imp = minidom .getDOMImplementation ()
102
105
self .xmldoc = imp .createDocument (None , "any" , None )
@@ -129,6 +132,9 @@ def __init__(self, *args, edit_file_path=None, duplicate=False, **kwargs):
129
132
# Disable Save button on window load
130
133
self .buttonBox .button (self .buttonBox .Save ).setEnabled (False )
131
134
135
+ # Connect thumbnail listener
136
+ self .thumbnailReady .connect (self .display_pixmap )
137
+
132
138
# If editing existing title svg file
133
139
if self .edit_file_path :
134
140
# Hide list of templates
@@ -143,6 +149,10 @@ def __init__(self, *args, edit_file_path=None, duplicate=False, **kwargs):
143
149
# Display image (slight delay to allow screen to be shown first)
144
150
QTimer .singleShot (50 , self .display_svg )
145
151
152
+ def display_pixmap (self , display_pixmap ):
153
+ """Display pixmap of SVG on UI thread"""
154
+ self .lblPreviewLabel .setPixmap (display_pixmap )
155
+
146
156
def txtLine_changed (self , txtWidget ):
147
157
148
158
# Loop through child widgets (and remove them)
@@ -194,7 +204,7 @@ def display_svg(self):
194
204
display_pixmap = QtGui .QIcon (tmp_filename ).pixmap (self .lblPreviewLabel .size ())
195
205
196
206
# Display temp image
197
- self .lblPreviewLabel . setPixmap (display_pixmap )
207
+ self .thumbnailReady . emit (display_pixmap )
198
208
199
209
# Remove temporary file
200
210
os .unlink (tmp_filename )
@@ -375,8 +385,19 @@ def writeToFile(self, xmldoc):
375
385
376
386
def save_and_reload (self ):
377
387
"""Something changed, so update temp SVG and redisplay"""
388
+ if not self .is_thread_busy :
389
+ t = threading .Thread (target = self .save_and_reload_thread , daemon = True )
390
+ t .start ()
391
+ else :
392
+ # Keep retrying until we succeed
393
+ self .update_timer .start ()
394
+
395
+ def save_and_reload_thread (self ):
396
+ """Run inside thread, to update and display new SVG - so we don't block the main UI thread"""
397
+ self .is_thread_busy = True
378
398
self .writeToFile (self .xmldoc )
379
399
self .display_svg ()
400
+ self .is_thread_busy = False
380
401
381
402
@pyqtSlot (QtGui .QColor )
382
403
def color_callback (self , save_fn , refresh_fn , color ):
0 commit comments