Edit Book: When inserting hyperlinks, allow specifying the text for the hyperlink in the insert hyperlink dialog

This commit is contained in:
Kovid Goyal 2014-03-16 10:58:27 +05:30
parent b5dba545cd
commit 82e1000626
6 changed files with 64 additions and 19 deletions

View File

@ -643,9 +643,9 @@ class Boss(QObject):
ed.insert_image(href) ed.insert_image(href)
elif action[0] == 'insert_hyperlink': elif action[0] == 'insert_hyperlink':
self.commit_all_editors_to_container() self.commit_all_editors_to_container()
d = InsertLink(current_container(), edname, parent=self.gui) d = InsertLink(current_container(), edname, initial_text=ed.get_smart_selection(), parent=self.gui)
if d.exec_() == d.Accepted: if d.exec_() == d.Accepted:
ed.insert_hyperlink(d.href) ed.insert_hyperlink(d.href, d.text)
else: else:
ed.action_triggered(action) ed.action_triggered(action)

View File

@ -14,3 +14,6 @@ class NullSmarts(object):
def get_extra_selections(self, editor): def get_extra_selections(self, editor):
return () return ()
def get_smart_selection(self, editor, update=True):
return editor.selected_text

View File

@ -129,7 +129,7 @@ def rename_tag(cursor, opening_tag, closing_tag, new_name, insert=False):
cursor.insertText(text) cursor.insertText(text)
cursor.endEditBlock() cursor.endEditBlock()
def ensure_not_within_tag_definition(cursor): def ensure_not_within_tag_definition(cursor, forward=True):
''' Ensure the cursor is not inside a tag definition <>. Returns True iff the cursor was moved. ''' ''' Ensure the cursor is not inside a tag definition <>. Returns True iff the cursor was moved. '''
block, offset = cursor.block(), cursor.positionInBlock() block, offset = cursor.block(), cursor.positionInBlock()
b, boundary = next_tag_boundary(block, offset, forward=False) b, boundary = next_tag_boundary(block, offset, forward=False)
@ -137,10 +137,15 @@ def ensure_not_within_tag_definition(cursor):
return False return False
if boundary.is_start: if boundary.is_start:
# We are inside a tag # We are inside a tag
block, boundary = next_tag_boundary(block, offset) if forward:
if block is not None: block, boundary = next_tag_boundary(block, offset)
cursor.setPosition(block.position() + boundary.offset + 1) if block is not None:
cursor.setPosition(block.position() + boundary.offset + 1)
return True
else:
cursor.setPosition(b.position() + boundary.offset)
return True return True
return False return False
class HTMLSmarts(NullSmarts): class HTMLSmarts(NullSmarts):
@ -195,7 +200,27 @@ class HTMLSmarts(NullSmarts):
return error_dialog(editor, _('No found'), _( return error_dialog(editor, _('No found'), _(
'No suitable block level tag was found to rename'), show=True) 'No suitable block level tag was found to rename'), show=True)
def insert_hyperlink(self, editor, target): def get_smart_selection(self, editor, update=True):
cursor = editor.textCursor()
if not cursor.hasSelection():
return ''
left = min(cursor.anchor(), cursor.position())
right = max(cursor.anchor(), cursor.position())
cursor.setPosition(left)
ensure_not_within_tag_definition(cursor)
left = cursor.position()
cursor.setPosition(right)
ensure_not_within_tag_definition(cursor, forward=False)
right = cursor.position()
cursor.setPosition(left), cursor.setPosition(right, cursor.KeepAnchor)
if update:
editor.setTextCursor(cursor)
return editor.selected_text_from_cursor(cursor)
def insert_hyperlink(self, editor, target, text):
c = editor.textCursor() c = editor.textCursor()
if c.hasSelection(): if c.hasSelection():
c.insertText('') # delete any existing selected text c.insertText('') # delete any existing selected text
@ -204,4 +229,6 @@ class HTMLSmarts(NullSmarts):
p = c.position() p = c.position()
c.insertText('</a>') c.insertText('</a>')
c.setPosition(p) # ensure cursor is positioned inside the newly created tag c.setPosition(p) # ensure cursor is positioned inside the newly created tag
if text:
c.insertText(text)
editor.setTextCursor(c) editor.setTextCursor(c)

View File

@ -101,9 +101,12 @@ class PlainTextEdit(QPlainTextEdit):
self.copy() self.copy()
self.textCursor().removeSelectedText() self.textCursor().removeSelectedText()
def selected_text_from_cursor(self, cursor):
return unicodedata.normalize('NFC', unicode(cursor.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0'))
@property @property
def selected_text(self): def selected_text(self):
return unicodedata.normalize('NFC', unicode(self.textCursor().selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0')) return self.selected_text_from_cursor(self.textCursor())
def selection_changed(self): def selection_changed(self):
# Workaround Qt replacing nbsp with normal spaces on copy # Workaround Qt replacing nbsp with normal spaces on copy
@ -602,9 +605,9 @@ class TextEdit(PlainTextEdit):
c.setPosition(left + len(text), c.KeepAnchor) c.setPosition(left + len(text), c.KeepAnchor)
self.setTextCursor(c) self.setTextCursor(c)
def insert_hyperlink(self, target): def insert_hyperlink(self, target, text):
if hasattr(self.smarts, 'insert_hyperlink'): if hasattr(self.smarts, 'insert_hyperlink'):
self.smarts.insert_hyperlink(self, target) self.smarts.insert_hyperlink(self, target, text)
def keyPressEvent(self, ev): def keyPressEvent(self, ev):
if ev.key() == Qt.Key_X and ev.modifiers() == Qt.AltModifier: if ev.key() == Qt.Key_X and ev.modifiers() == Qt.AltModifier:

View File

@ -144,8 +144,8 @@ class Editor(QMainWindow):
def insert_image(self, href): def insert_image(self, href):
self.editor.insert_image(href) self.editor.insert_image(href)
def insert_hyperlink(self, href): def insert_hyperlink(self, href, text):
self.editor.insert_hyperlink(href) self.editor.insert_hyperlink(href, text)
def undo(self): def undo(self):
self.editor.undo() self.editor.undo()
@ -157,6 +157,9 @@ class Editor(QMainWindow):
def selected_text(self): def selected_text(self):
return self.editor.selected_text return self.editor.selected_text
def get_smart_selection(self, update=True):
return self.editor.smarts.get_smart_selection(self.editor, update=update)
# Search and replace {{{ # Search and replace {{{
def mark_selected_text(self): def mark_selected_text(self):
self.editor.mark_selected_text() self.editor.mark_selected_text()

View File

@ -537,9 +537,10 @@ def create_filterable_names_list(names, filter_text=None, parent=None):
# Insert Link {{{ # Insert Link {{{
class InsertLink(Dialog): class InsertLink(Dialog):
def __init__(self, container, source_name, parent=None): def __init__(self, container, source_name, initial_text=None, parent=None):
self.container = container self.container = container
self.source_name = source_name self.source_name = source_name
self.initial_text = initial_text
Dialog.__init__(self, _('Insert Hyperlink'), 'insert-hyperlink', parent=parent) Dialog.__init__(self, _('Insert Hyperlink'), 'insert-hyperlink', parent=parent)
self.anchor_cache = {} self.anchor_cache = {}
@ -573,14 +574,18 @@ class InsertLink(Dialog):
fnl.addWidget(la), fnl.addWidget(f), fnl.addWidget(fn) fnl.addWidget(la), fnl.addWidget(f), fnl.addWidget(fn)
h.addLayout(fnl), h.setStretch(1, 1) h.addLayout(fnl), h.setStretch(1, 1)
self.tl = tl = QHBoxLayout() self.tl = tl = QFormLayout()
self.la3 = la = QLabel(_('&Target:'))
tl.addWidget(la)
self.target = t = QLineEdit(self) self.target = t = QLineEdit(self)
la.setBuddy(t) t.setPlaceholderText(_('The destination (href) for the link'))
tl.addWidget(t) tl.addRow(_('&Target:'), t)
l.addLayout(tl) l.addLayout(tl)
self.text_edit = t = QLineEdit(self)
la.setBuddy(t)
tl.addRow(_('Te&xt:'), t)
t.setText(self.initial_text or '')
t.setPlaceholderText(_('The (optional) text for the link'))
l.addWidget(self.bb) l.addWidget(self.bb)
def selected_file_changed(self, *args): def selected_file_changed(self, *args):
@ -622,6 +627,10 @@ class InsertLink(Dialog):
def href(self): def href(self):
return unicode(self.target.text()).strip() return unicode(self.target.text()).strip()
@property
def text(self):
return unicode(self.text_edit.text()).strip()
@classmethod @classmethod
def test(cls): def test(cls):
import sys import sys
@ -629,7 +638,7 @@ class InsertLink(Dialog):
c = get_container(sys.argv[-1], tweak_mode=True) c = get_container(sys.argv[-1], tweak_mode=True)
d = cls(c, next(c.spine_names)[0]) d = cls(c, next(c.spine_names)[0])
if d.exec_() == d.Accepted: if d.exec_() == d.Accepted:
print (d.href) print (d.href, d.text)
# }}} # }}}