Use the highlighted matching tags for Live CSS as a performance optimization

This commit is contained in:
Kovid Goyal 2014-08-02 16:48:12 +05:30
parent df15f6120a
commit 6a1f82320d
6 changed files with 25 additions and 19 deletions

View File

@ -1134,14 +1134,6 @@ class Boss(QObject):
if name is not None and getattr(ed, 'syntax', None) == 'html':
self.gui.preview.sync_to_editor(name, ed.current_tag())
def sync_live_css_to_editor(self):
' Sync the Live CSS panel to the current cursor position in the current editor '
ed = self.gui.central.current_editor
if ed is not None:
name = editor_name(ed)
if name is not None and getattr(ed, 'syntax', None) == 'html':
self.gui.live_css.sync_to_editor(name)
def goto_style_declaration(self, data):
name = data['name']
editor = self.edit_file(name, syntax=data['syntax'])
@ -1152,12 +1144,13 @@ class Boss(QObject):
editor.data_changed.connect(self.editor_data_changed)
editor.copy_available_state_changed.connect(self.editor_copy_available_state_changed)
editor.cursor_position_changed.connect(self.sync_preview_to_editor)
editor.cursor_position_changed.connect(self.sync_live_css_to_editor)
editor.cursor_position_changed.connect(self.update_cursor_position)
if hasattr(editor, 'word_ignored'):
editor.word_ignored.connect(self.word_ignored)
if hasattr(editor, 'link_clicked'):
editor.link_clicked.connect(self.editor_link_clicked)
if getattr(editor, 'syntax', None) == 'html':
editor.smart_highlighting_updated.connect(self.gui.live_css.sync_to_editor)
if data is not None:
if use_template:
editor.init_from_template(data)
@ -1284,7 +1277,6 @@ class Boss(QObject):
# focused. This is not inefficient since multiple requests
# to sync are de-bounced with a 100 msec wait.
self.sync_preview_to_editor()
self.sync_live_css_to_editor()
if name is not None:
self.gui.file_list.mark_name_as_current(name)
if ed.has_line_numbers:

View File

@ -20,7 +20,7 @@ class NullSmarts(object):
def verify_for_spellcheck(self, cursor, highlighter):
return False
def cursor_position_with_sourceline(self, cursor):
def cursor_position_with_sourceline(self, cursor, for_position_sync=True):
return None, None
def goto_sourceline(self, editor, sourceline, tags, attribute=None):

View File

@ -270,6 +270,10 @@ def set_style_property(tag, property_name, value, editor):
class HTMLSmarts(NullSmarts):
def __init__(self, *args, **kwargs):
NullSmarts.__init__(self, *args, **kwargs)
self.last_matched_tag = None
def get_extra_selections(self, editor):
ans = []
@ -288,7 +292,7 @@ class HTMLSmarts(NullSmarts):
c = editor.textCursor()
block, offset = c.block(), c.positionInBlock()
tag = find_closest_containing_tag(block, offset, max_tags=2000)
tag = self.last_matched_tag = find_closest_containing_tag(block, offset, max_tags=2000)
if tag is not None:
add_tag(tag)
tag = find_closing_tag(tag, max_tags=4000)
@ -391,13 +395,14 @@ class HTMLSmarts(NullSmarts):
return False
def cursor_position_with_sourceline(self, cursor, for_position_sync=True):
def cursor_position_with_sourceline(self, cursor, for_position_sync=True, use_matched_tag=True):
''' Return the tag just before the current cursor as a source line
number and a list of tags defined on that line upto and including the
containing tag. If ``for_position_sync`` is False then the tag
*containing* the cursor is returned instead of the tag just before the
cursor. Note that finding the containing tag is relative expensive, so
use with care.'''
cursor. Note that finding the containing tag is expensive, so
use with care. As an optimization, the last tag matched by
get_extra_selections is used, unless use_matched_tag is False. '''
block, offset = cursor.block(), cursor.positionInBlock()
if for_position_sync:
nblock, boundary = next_tag_boundary(block, offset, forward=False)
@ -417,7 +422,11 @@ class HTMLSmarts(NullSmarts):
break
block, offset = block.previous(), sys.maxint
else:
tag = find_closest_containing_tag(block, offset, max_tags=2000)
tag = None
if use_matched_tag:
tag = self.last_matched_tag
if tag is None:
tag = find_closest_containing_tag(block, offset, max_tags=2000)
if tag is None:
return None, None
start_block, start_offset = tag.start_block, tag.start_offset

View File

@ -132,6 +132,7 @@ class PlainTextEdit(QPlainTextEdit):
class TextEdit(PlainTextEdit):
link_clicked = pyqtSignal(object)
smart_highlighting_updated = pyqtSignal()
def __init__(self, parent=None, expected_geometry=(100, 50)):
PlainTextEdit.__init__(self, parent)
@ -274,6 +275,7 @@ class TextEdit(PlainTextEdit):
sel.append(self.current_search_mark)
if instant and not self.highlighter.has_requests:
sel.extend(self.smarts.get_extra_selections(self))
self.smart_highlighting_updated.emit()
else:
self.smarts_highlight_timer.start()
self.setExtraSelections(sel)

View File

@ -107,6 +107,7 @@ class Editor(QMainWindow):
cursor_position_changed = pyqtSignal()
word_ignored = pyqtSignal(object, object)
link_clicked = pyqtSignal(object)
smart_highlighting_updated = pyqtSignal()
def __init__(self, syntax, parent=None):
QMainWindow.__init__(self, parent)
@ -129,6 +130,7 @@ class Editor(QMainWindow):
self.editor.copyAvailable.connect(self._copy_available)
self.editor.cursorPositionChanged.connect(self._cursor_position_changed)
self.editor.link_clicked.connect(self.link_clicked)
self.editor.smart_highlighting_updated.connect(self.smart_highlighting_updated)
@dynamic_property
def current_line(self):
@ -328,7 +330,7 @@ class Editor(QMainWindow):
self.restore_state()
def break_cycles(self):
for x in ('modification_state_changed', 'word_ignored', 'link_clicked'):
for x in ('modification_state_changed', 'word_ignored', 'link_clicked', 'smart_highlighting_updated'):
try:
getattr(self, x).disconnect()
except TypeError:
@ -344,6 +346,7 @@ class Editor(QMainWindow):
self.editor.copyAvailable.disconnect()
self.editor.cursorPositionChanged.disconnect()
self.editor.link_clicked.disconnect()
self.editor.smart_highlighting_updated.disconnect()
self.editor.setPlainText('')
self.editor.smarts = None

View File

@ -470,8 +470,8 @@ class LiveCSS(QWidget):
actions['auto-reload-preview'].setEnabled(True)
return QWidget.showEvent(self, ev)
def sync_to_editor(self, name):
self.start_update_timer()
def sync_to_editor(self):
self.update_data()
def update_data(self):
if not self.is_visible or self.preview_is_refreshing: