Live CSS: Handle updates more gracefully when the cursor is in a CSS editor or a <style> tag

We prevent incorrect data from being returned by ensuring that updates
are not done while the preview panel is being refreshed. We also only
update data after the event loop has run for some time after a refresh.
This commit is contained in:
Kovid Goyal 2014-05-22 21:24:51 +05:30
parent 94f7a1d927
commit 5c7ff48e9f
2 changed files with 36 additions and 5 deletions

View File

@ -297,12 +297,16 @@ class LiveCSS(QWidget):
def __init__(self, preview, parent=None): def __init__(self, preview, parent=None):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
self.preview = preview self.preview = preview
preview.refreshed.connect(self.update_data) self.preview_is_refreshing = False
preview.refresh_starting.connect(self.preview_refresh_starting)
preview.refreshed.connect(self.preview_refreshed)
self.apply_theme() self.apply_theme()
self.setAutoFillBackground(True) self.setAutoFillBackground(True)
self.update_timer = QTimer(self) self.update_timer = QTimer(self)
self.update_timer.timeout.connect(self.update_data) self.update_timer.timeout.connect(self.update_data)
self.update_timer.setSingleShot(True) self.update_timer.setSingleShot(True)
self.update_timer.setInterval(500)
self.now_showing = (None, None, None)
self.stack = s = QStackedLayout(self) self.stack = s = QStackedLayout(self)
self.setLayout(s) self.setLayout(s)
@ -322,6 +326,15 @@ class LiveCSS(QWidget):
sc.setWidgetResizable(True) sc.setWidgetResizable(True)
s.addWidget(sc) s.addWidget(sc)
def preview_refresh_starting(self):
self.preview_is_refreshing = True
def preview_refreshed(self):
self.preview_is_refreshing = False
# We must let the event loop run otherwise the webview will return
# stale data in read_data()
self.start_update_timer()
def apply_theme(self): def apply_theme(self):
f = self.font() f = self.font()
f.setFamily(tprefs['editor_font_family'] or default_font_family()) f.setFamily(tprefs['editor_font_family'] or default_font_family())
@ -344,13 +357,29 @@ class LiveCSS(QWidget):
self.stack.setCurrentIndex(0) self.stack.setCurrentIndex(0)
def show_data(self, editor_name, sourceline, tags): def show_data(self, editor_name, sourceline, tags):
if self.preview_is_refreshing:
return
if sourceline is None: if sourceline is None:
self.clear() self.clear()
else: else:
data = self.read_data(sourceline, tags) data = self.read_data(sourceline, tags)
if data is None or len(data['computed_css']) < 1: if data is None or len(data['computed_css']) < 1:
if editor_name == self.current_name and (editor_name, sourceline, tags) == self.now_showing:
# Try again in a little while in case there was a transient
# error in the web view
self.start_update_timer()
return
if self.now_showing == (None, None, None) or self.now_showing[0] != self.current_name:
self.clear() self.clear()
return return
# Try to refresh the data for the currently shown tag instead
# of clearing
editor_name, sourceline, tags = self.now_showing
data = self.read_data(sourceline, tags)
if data is None or len(data['computed_css']) < 1:
self.clear()
return
self.now_showing = (editor_name, sourceline, tags)
data['html_name'] = editor_name data['html_name'] = editor_name
self.box.show_data(data) self.box.show_data(data)
self.stack.setCurrentIndex(1) self.stack.setCurrentIndex(1)
@ -391,7 +420,7 @@ class LiveCSS(QWidget):
self.start_update_timer() self.start_update_timer()
def update_data(self): def update_data(self):
if not self.is_visible: if not self.is_visible or self.preview_is_refreshing:
return return
editor_name = self.current_name editor_name = self.current_name
ed = editors.get(editor_name, None) ed = editors.get(editor_name, None)
@ -403,7 +432,7 @@ class LiveCSS(QWidget):
def start_update_timer(self): def start_update_timer(self):
if self.is_visible: if self.is_visible:
self.update_timer.start(1000) self.update_timer.start()
def stop_update_timer(self): def stop_update_timer(self):
self.update_timer.stop() self.update_timer.stop()

View File

@ -450,6 +450,7 @@ class Preview(QWidget):
split_requested = pyqtSignal(object, object, object) split_requested = pyqtSignal(object, object, object)
split_start_requested = pyqtSignal() split_start_requested = pyqtSignal()
link_clicked = pyqtSignal(object, object) link_clicked = pyqtSignal(object, object)
refresh_starting = pyqtSignal()
refreshed = pyqtSignal() refreshed = pyqtSignal()
def __init__(self, parent=None): def __init__(self, parent=None):
@ -569,6 +570,7 @@ class Preview(QWidget):
parse_worker.add_request(self.current_name) parse_worker.add_request(self.current_name)
# Tell webkit to reload all html and associated resources # Tell webkit to reload all html and associated resources
current_url = QUrl.fromLocalFile(current_container().name_to_abspath(self.current_name)) current_url = QUrl.fromLocalFile(current_container().name_to_abspath(self.current_name))
self.refresh_starting.emit()
if current_url != self.view.url(): if current_url != self.view.url():
# The container was changed # The container was changed
self.view.setUrl(current_url) self.view.setUrl(current_url)