mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit Book: Live CSS: Improve detection of which tag the cursor is inside when there are multiple tags on the same line. See #1350495 (Private bug)
This commit is contained in:
parent
609609e688
commit
b6a82bf657
@ -384,12 +384,14 @@ class HTMLSmarts(NullSmarts):
|
||||
|
||||
return False
|
||||
|
||||
def cursor_position_with_sourceline(self, cursor):
|
||||
''' Return the tag containing the current cursor as a source line
|
||||
def cursor_position_with_sourceline(self, cursor, for_position_sync=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. '''
|
||||
containing tag. If ``for_position_sync`` is False then the tag
|
||||
*containing* the cursor is returned instead of the tag just before the
|
||||
cursor. '''
|
||||
block = cursor.block()
|
||||
offset = cursor.position() - block.position()
|
||||
offset = cursor.positionInBlock()
|
||||
nblock, boundary = next_tag_boundary(block, offset, forward=False)
|
||||
if boundary is None:
|
||||
return None, None
|
||||
@ -412,8 +414,52 @@ class HTMLSmarts(NullSmarts):
|
||||
ud = start_block.userData()
|
||||
if ud is None:
|
||||
return None, None
|
||||
all_tags = [t.name for t in ud.tags if (t.is_start and not t.closing and t.offset <= start_offset)]
|
||||
return sourceline, all_tags
|
||||
if for_position_sync:
|
||||
return sourceline, [
|
||||
t.name for t in ud.tags if (t.is_start and not t.closing and t.offset <= start_offset)]
|
||||
# We discard self-closing as well as tags that are both opened and
|
||||
# closed from the end of the list of tags as we want the tag that
|
||||
# contains the cursor, not the last tag before the cursor
|
||||
class Tag(object):
|
||||
__slots__ = 'name', 'is_closed'
|
||||
def __init__(self, name, is_closed):
|
||||
self.name = name
|
||||
self.is_closed = is_closed
|
||||
def __repr__(self):
|
||||
return '<%s%s>' % (self.name, ('/' if self.is_closed else ''))
|
||||
|
||||
if cursor.block().blockNumber() == start_block.blockNumber():
|
||||
offset = cursor.positionInBlock()
|
||||
tag_stack = []
|
||||
in_tag = None
|
||||
for t in ud.tags:
|
||||
if t.offset < offset:
|
||||
if t.is_start:
|
||||
if t.closing:
|
||||
# </tag
|
||||
for tag in reversed(tag_stack):
|
||||
is_match = not tag.is_closed and tag.name == t.name
|
||||
tag.is_closed = True
|
||||
if is_match:
|
||||
break
|
||||
else:
|
||||
# <tag
|
||||
in_tag = t.name
|
||||
else:
|
||||
# tag>
|
||||
if in_tag is not None:
|
||||
tag_stack.append(Tag(in_tag, t.self_closing))
|
||||
in_tag = None
|
||||
|
||||
all_tags = []
|
||||
found_open = False
|
||||
for tag in reversed(tag_stack):
|
||||
if not tag.is_closed:
|
||||
found_open = True
|
||||
if found_open:
|
||||
all_tags.append(tag.name)
|
||||
|
||||
return sourceline, list(reversed(all_tags))
|
||||
|
||||
def goto_sourceline(self, editor, sourceline, tags, attribute=None):
|
||||
''' Move the cursor to the tag identified by sourceline and tags (a
|
||||
|
@ -790,8 +790,8 @@ class TextEdit(PlainTextEdit):
|
||||
if hasattr(self.smarts, 'rename_block_tag'):
|
||||
self.smarts.rename_block_tag(self, new_name)
|
||||
|
||||
def current_tag(self):
|
||||
return self.smarts.cursor_position_with_sourceline(self.textCursor())
|
||||
def current_tag(self, for_position_sync=True):
|
||||
return self.smarts.cursor_position_with_sourceline(self.textCursor(), for_position_sync=for_position_sync)
|
||||
|
||||
def goto_sourceline(self, sourceline, tags, attribute=None):
|
||||
return self.smarts.goto_sourceline(self, sourceline, tags, attribute=attribute)
|
||||
|
@ -138,8 +138,8 @@ class Editor(QMainWindow):
|
||||
self.editor.go_to_line(val)
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
def current_tag(self):
|
||||
return self.editor.current_tag()
|
||||
def current_tag(self, for_position_sync=True):
|
||||
return self.editor.current_tag(for_position_sync=for_position_sync)
|
||||
|
||||
@property
|
||||
def number_of_lines(self):
|
||||
|
@ -481,7 +481,7 @@ class LiveCSS(QWidget):
|
||||
if self.update_timer.isActive() or (ed is None and editor_name is not None):
|
||||
return QTimer.singleShot(100, self.update_data)
|
||||
if ed is not None:
|
||||
sourceline, tags = ed.current_tag()
|
||||
sourceline, tags = ed.current_tag(for_position_sync=False)
|
||||
if self.refresh_needed or self.now_showing != (editor_name, sourceline, tags):
|
||||
self.show_data(editor_name, sourceline, tags)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user