diff --git a/imgsrc/character-set.svg b/imgsrc/character-set.svg
new file mode 100644
index 0000000000..e513ec0451
--- /dev/null
+++ b/imgsrc/character-set.svg
@@ -0,0 +1,201 @@
+
+
+
+
\ No newline at end of file
diff --git a/resources/images/character-set.png b/resources/images/character-set.png
new file mode 100644
index 0000000000..5831b73882
Binary files /dev/null and b/resources/images/character-set.png differ
diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py
index 506eaa9599..c05864725d 100644
--- a/src/calibre/gui2/tweak_book/boss.py
+++ b/src/calibre/gui2/tweak_book/boss.py
@@ -1068,6 +1068,9 @@ class Boss(QObject):
if not editors:
self.gui.preview.clear()
+ def insert_character(self):
+ self.gui.insert_char.show()
+
# Shutdown {{{
def quit(self):
if not self.confirm_quit():
diff --git a/src/calibre/gui2/tweak_book/char_select.py b/src/calibre/gui2/tweak_book/char_select.py
index 3338e46d4f..53da28314e 100644
--- a/src/calibre/gui2/tweak_book/char_select.py
+++ b/src/calibre/gui2/tweak_book/char_select.py
@@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal '
-import unicodedata, re
+import unicodedata, re, weakref
from bisect import bisect
from functools import partial
@@ -548,6 +548,7 @@ class CharDelegate(QStyledItemDelegate):
class CharView(QListView):
show_name = pyqtSignal(object)
+ char_selected = pyqtSignal(object)
def __init__(self, parent=None):
self.last_mouse_idx = -1
@@ -564,6 +565,16 @@ class CharView(QListView):
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.context_menu)
self.showing_favorites = False
+ pi = plugins['progress_indicator'][0]
+ if hasattr(pi, 'set_no_activate_on_click'):
+ pi.set_no_activate_on_click(self)
+ self.activated.connect(self.item_activated)
+ self.clicked.connect(self.item_activated)
+
+ def item_activated(self, index):
+ char_code, ok = self.model().data(index, Qt.UserRole).toInt()
+ if ok:
+ self.char_selected.emit(chr(char_code))
def set_allow_drag_and_drop(self, enabled):
if not enabled:
@@ -640,6 +651,8 @@ class CharSelect(Dialog):
def __init__(self, parent=None):
self.initialized = False
Dialog.__init__(self, _('Insert character'), 'charmap_dialog', parent)
+ self.setWindowIcon(QIcon(I('character-set.png')))
+ self.focus_widget = None
def setup_ui(self):
self.l = l = QGridLayout(self)
@@ -650,6 +663,7 @@ class CharSelect(Dialog):
b.setCheckable(True)
b.setChecked(False)
b.setVisible(False)
+ b.setDefault(True)
self.splitter = s = QSplitter(self)
s.setChildrenCollapsible(False)
@@ -660,6 +674,7 @@ class CharSelect(Dialog):
self.rearrange_button.toggled[bool].connect(self.set_allow_drag_and_drop)
self.category_view.category_selected.connect(self.show_chars)
self.char_view.show_name.connect(self.show_char_info)
+ self.char_view.char_selected.connect(self.char_selected)
s.addWidget(self.category_view), s.addWidget(self.char_view)
self.char_info = la = QLabel('\xa0')
@@ -701,10 +716,29 @@ class CharSelect(Dialog):
self.char_info.clear()
def show(self):
+ try:
+ self.focus_widget = weakref.ref(QApplication.focusWidget())
+ except TypeError:
+ self.focus_widget = None
self.initialize()
Dialog.show(self)
self.raise_()
+ def char_selected(self, c):
+ if QApplication.keyboardModifiers() & Qt.CTRL:
+ self.hide()
+ if self.focus_widget is None or self.focus_widget() is None:
+ QApplication.clipboard().setText(c)
+ return
+ w = self.focus_widget()
+ if hasattr(w, 'textCursor'):
+ cr = w.textCursor()
+ cr.insertText(c)
+ w.setTextCursor(cr)
+ elif hasattr(w, 'insert'):
+ w.insert(c)
+
+
if __name__ == '__main__':
app = QApplication([])
w = CharSelect()
diff --git a/src/calibre/gui2/tweak_book/ui.py b/src/calibre/gui2/tweak_book/ui.py
index 8282c9eae7..81f0134c3c 100644
--- a/src/calibre/gui2/tweak_book/ui.py
+++ b/src/calibre/gui2/tweak_book/ui.py
@@ -29,6 +29,7 @@ from calibre.gui2.tweak_book.preview import Preview
from calibre.gui2.tweak_book.search import SearchPanel
from calibre.gui2.tweak_book.check import Check
from calibre.gui2.tweak_book.toc import TOCViewer
+from calibre.gui2.tweak_book.char_select import CharSelect
from calibre.gui2.tweak_book.editor.widget import register_text_editor_actions
from calibre.gui2.tweak_book.editor.insert_resource import InsertImage
@@ -217,6 +218,7 @@ class Main(MainWindow):
self.check_book = Check(self)
self.toc_view = TOCViewer(self)
self.image_browser = InsertImage(self, for_browsing=True)
+ self.insert_char = CharSelect(self)
self.create_actions()
self.create_toolbars()
@@ -321,6 +323,8 @@ class Main(MainWindow):
_('Beautify current file'))
self.action_pretty_all = reg('format-justify-fill.png', _('&Beautify all files'), partial(self.boss.pretty_print, False), 'pretty-all', (),
_('Beautify all files'))
+ self.action_insert_char = reg('character-set.png', _('&Insert special character'), self.boss.insert_character, 'insert-character', (),
+ _('Insert special character'))
# Polish actions
group = _('Polish Book')
@@ -423,6 +427,7 @@ class Main(MainWindow):
e.addAction(self.action_editor_cut)
e.addAction(self.action_editor_copy)
e.addAction(self.action_editor_paste)
+ e.addAction(self.action_insert_char)
e.addSeparator()
e.addAction(self.action_preferences)
@@ -505,6 +510,7 @@ class Main(MainWindow):
b.setToolTip(_('Donate to support calibre development'))
QTimer.singleShot(10, b.start_animation)
self.global_bar.addWidget(w)
+ self.global_bar.addAction(self.action_insert_char)
a(self.action_help)
a = create(_('Polish book tool bar'), 'polish').addAction