mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
A nicer font family chooser combobox
This commit is contained in:
parent
24a9d26176
commit
473ced12de
@ -19,6 +19,7 @@ from calibre.ebooks.conversion.config import load_defaults, \
|
|||||||
load_specifics, GuiRecommendations
|
load_specifics, GuiRecommendations
|
||||||
from calibre import prepare_string_for_xml
|
from calibre import prepare_string_for_xml
|
||||||
from calibre.customize.ui import plugin_for_input_format
|
from calibre.customize.ui import plugin_for_input_format
|
||||||
|
from calibre.gui2.font_family_chooser import FontFamilyChooser
|
||||||
|
|
||||||
def config_widget_for_input_plugin(plugin):
|
def config_widget_for_input_plugin(plugin):
|
||||||
name = plugin.name.lower().replace(' ', '_')
|
name = plugin.name.lower().replace(' ', '_')
|
||||||
@ -144,6 +145,8 @@ class Widget(QWidget):
|
|||||||
return ans
|
return ans
|
||||||
elif isinstance(g, QFontComboBox):
|
elif isinstance(g, QFontComboBox):
|
||||||
return unicode(QFontInfo(g.currentFont()).family())
|
return unicode(QFontInfo(g.currentFont()).family())
|
||||||
|
elif isinstance(g, FontFamilyChooser):
|
||||||
|
return g.font_family
|
||||||
elif isinstance(g, EncodingComboBox):
|
elif isinstance(g, EncodingComboBox):
|
||||||
ans = unicode(g.currentText()).strip()
|
ans = unicode(g.currentText()).strip()
|
||||||
try:
|
try:
|
||||||
@ -208,6 +211,8 @@ class Widget(QWidget):
|
|||||||
getattr(g, 'setCursorPosition', lambda x: x)(0)
|
getattr(g, 'setCursorPosition', lambda x: x)(0)
|
||||||
elif isinstance(g, QFontComboBox):
|
elif isinstance(g, QFontComboBox):
|
||||||
g.setCurrentFont(QFont(val or ''))
|
g.setCurrentFont(QFont(val or ''))
|
||||||
|
elif isinstance(g, FontFamilyChooser):
|
||||||
|
g.font_family = val
|
||||||
elif isinstance(g, EncodingComboBox):
|
elif isinstance(g, EncodingComboBox):
|
||||||
if val:
|
if val:
|
||||||
g.setEditText(val)
|
g.setEditText(val)
|
||||||
|
@ -6,11 +6,8 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from PyQt4.Qt import Qt
|
|
||||||
|
|
||||||
from calibre.gui2.convert.lrf_output_ui import Ui_Form
|
from calibre.gui2.convert.lrf_output_ui import Ui_Form
|
||||||
from calibre.gui2.convert import Widget
|
from calibre.gui2.convert import Widget
|
||||||
from calibre.gui2.widgets import FontFamilyModel
|
|
||||||
|
|
||||||
font_family_model = None
|
font_family_model = None
|
||||||
|
|
||||||
@ -30,13 +27,6 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
'header_separation', 'minimum_indent']
|
'header_separation', 'minimum_indent']
|
||||||
)
|
)
|
||||||
self.db, self.book_id = db, book_id
|
self.db, self.book_id = db, book_id
|
||||||
global font_family_model
|
|
||||||
if font_family_model is None:
|
|
||||||
font_family_model = FontFamilyModel()
|
|
||||||
self.font_family_model = font_family_model
|
|
||||||
self.opt_serif_family.setModel(self.font_family_model)
|
|
||||||
self.opt_sans_family.setModel(self.font_family_model)
|
|
||||||
self.opt_mono_family.setModel(self.font_family_model)
|
|
||||||
|
|
||||||
self.initialize_options(get_option, get_help, db, book_id)
|
self.initialize_options(get_option, get_help, db, book_id)
|
||||||
self.opt_header.toggle(), self.opt_header.toggle()
|
self.opt_header.toggle(), self.opt_header.toggle()
|
||||||
@ -44,14 +34,4 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
self.opt_render_tables_as_images.toggle()
|
self.opt_render_tables_as_images.toggle()
|
||||||
|
|
||||||
|
|
||||||
def set_value_handler(self, g, val):
|
|
||||||
if unicode(g.objectName()) in ('opt_serif_family',
|
|
||||||
'opt_sans_family', 'opt_mono_family'):
|
|
||||||
idx = -1
|
|
||||||
if val:
|
|
||||||
idx = g.findText(val, Qt.MatchFixedString)
|
|
||||||
if idx < 0:
|
|
||||||
idx = 0
|
|
||||||
g.setCurrentIndex(idx)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
@ -176,13 +176,13 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QComboBox" name="opt_serif_family"/>
|
<widget class="FontFamilyChooser" name="opt_serif_family"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="opt_sans_family"/>
|
<widget class="FontFamilyChooser" name="opt_sans_family"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="opt_mono_family"/>
|
<widget class="FontFamilyChooser" name="opt_mono_family"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -202,6 +202,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>FontFamilyChooser</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>calibre/gui2/font_family_chooser.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
168
src/calibre/gui2/font_family_chooser.py
Normal file
168
src/calibre/gui2/font_family_chooser.py
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
|
print_function)
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
from PyQt4.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen,
|
||||||
|
QStyledItemDelegate, QSize, QStyle, QComboBox, QStringListModel,
|
||||||
|
QDialog, QVBoxLayout, QApplication, QFontComboBox)
|
||||||
|
|
||||||
|
from calibre.utils.icu import sort_key
|
||||||
|
|
||||||
|
def writing_system_for_font(font):
|
||||||
|
has_latin = True
|
||||||
|
systems = QFontDatabase().writingSystems(font.family())
|
||||||
|
|
||||||
|
# this just confuses the algorithm below. Vietnamese is Latin with lots of
|
||||||
|
# special chars
|
||||||
|
try:
|
||||||
|
systems.remove(QFontDatabase.Vietnamese)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
system = QFontDatabase.Any
|
||||||
|
|
||||||
|
if (QFontDatabase.Latin not in systems):
|
||||||
|
has_latin = False
|
||||||
|
# we need to show something
|
||||||
|
if systems:
|
||||||
|
system = systems[-1]
|
||||||
|
else:
|
||||||
|
systems.remove(QFontDatabase.Latin)
|
||||||
|
|
||||||
|
if not systems:
|
||||||
|
return system, has_latin
|
||||||
|
|
||||||
|
if (len(systems) == 1 and systems[0] > QFontDatabase.Cyrillic):
|
||||||
|
return systems[0], has_latin
|
||||||
|
|
||||||
|
if (len(systems) <= 2 and
|
||||||
|
systems[-1] > QFontDatabase.Armenian and
|
||||||
|
systems[-1] < QFontDatabase.Vietnamese):
|
||||||
|
return systems[-1], has_latin
|
||||||
|
|
||||||
|
if (len(systems) <= 5 and
|
||||||
|
systems[-1] >= QFontDatabase.SimplifiedChinese and
|
||||||
|
systems[-1] <= QFontDatabase.Korean):
|
||||||
|
system = systems[-1]
|
||||||
|
|
||||||
|
return system, has_latin
|
||||||
|
|
||||||
|
class FontFamilyDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
|
def sizeHint(self, option, index):
|
||||||
|
text = index.data(Qt.DisplayRole).toString()
|
||||||
|
font = QFont(option.font)
|
||||||
|
font.setPointSize(QFontInfo(font).pointSize() * 1.5)
|
||||||
|
m = QFontMetrics(font)
|
||||||
|
return QSize(m.width(text), m.height())
|
||||||
|
|
||||||
|
def paint(self, painter, option, index):
|
||||||
|
text = unicode(index.data(Qt.DisplayRole).toString())
|
||||||
|
font = QFont(option.font)
|
||||||
|
font.setPointSize(QFontInfo(font).pointSize() * 1.5)
|
||||||
|
font2 = QFont(font)
|
||||||
|
font2.setFamily(text)
|
||||||
|
|
||||||
|
system, has_latin = writing_system_for_font(font2)
|
||||||
|
if has_latin:
|
||||||
|
font = font2
|
||||||
|
|
||||||
|
r = option.rect
|
||||||
|
|
||||||
|
if option.state & QStyle.State_Selected:
|
||||||
|
painter.save()
|
||||||
|
painter.setBrush(option.palette.highlight())
|
||||||
|
painter.setPen(Qt.NoPen)
|
||||||
|
painter.drawRect(option.rect)
|
||||||
|
painter.setPen(QPen(option.palette.highlightedText(), 0))
|
||||||
|
|
||||||
|
if (option.direction == Qt.RightToLeft):
|
||||||
|
r.setRight(r.right() - 4)
|
||||||
|
else:
|
||||||
|
r.setLeft(r.left() + 4)
|
||||||
|
|
||||||
|
old = painter.font()
|
||||||
|
painter.setFont(font)
|
||||||
|
painter.drawText(r, Qt.AlignVCenter|Qt.AlignLeading|Qt.TextSingleLine, text)
|
||||||
|
|
||||||
|
if (system != QFontDatabase.Any):
|
||||||
|
w = painter.fontMetrics().width(text + " ")
|
||||||
|
painter.setFont(font2)
|
||||||
|
sample = QFontDatabase().writingSystemSample(system)
|
||||||
|
if (option.direction == Qt.RightToLeft):
|
||||||
|
r.setRight(r.right() - w)
|
||||||
|
else:
|
||||||
|
r.setLeft(r.left() + w)
|
||||||
|
painter.drawText(r, Qt.AlignVCenter|Qt.AlignLeading|Qt.TextSingleLine, sample)
|
||||||
|
|
||||||
|
painter.setFont(old)
|
||||||
|
|
||||||
|
if (option.state & QStyle.State_Selected):
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
|
class FontFamilyChooser(QComboBox):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QComboBox.__init__(self, parent)
|
||||||
|
from calibre.utils.fonts import fontconfig
|
||||||
|
try:
|
||||||
|
self.families = fontconfig.find_font_families()
|
||||||
|
except:
|
||||||
|
self.families = []
|
||||||
|
print ('WARNING: Could not load fonts')
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
# Restrict to Qt families as we need the font to be available in
|
||||||
|
# QFontDatabase
|
||||||
|
qt_families = set([unicode(x) for x in QFontDatabase().families()])
|
||||||
|
self.families = list(qt_families.intersection(set(self.families)))
|
||||||
|
self.families.sort(key=sort_key)
|
||||||
|
self.families.insert(0, _('None'))
|
||||||
|
|
||||||
|
self.m = QStringListModel(self.families)
|
||||||
|
self.setModel(self.m)
|
||||||
|
self.d = FontFamilyDelegate(self)
|
||||||
|
self.setItemDelegate(self.d)
|
||||||
|
self.setCurrentIndex(0)
|
||||||
|
|
||||||
|
def event(self, e):
|
||||||
|
if e.type() == e.Resize:
|
||||||
|
view = self.view()
|
||||||
|
view.window().setFixedWidth(self.width() * 5/3)
|
||||||
|
return QComboBox.event(self, e)
|
||||||
|
|
||||||
|
def sizeHint(self):
|
||||||
|
ans = QComboBox.sizeHint(self)
|
||||||
|
ans.setWidth(QFontMetrics(self.font()).width('m'*14))
|
||||||
|
return ans
|
||||||
|
|
||||||
|
@dynamic_property
|
||||||
|
def font_family(self):
|
||||||
|
def fget(self):
|
||||||
|
idx= self.currentIndex()
|
||||||
|
if idx == 0: return None
|
||||||
|
return self.families[idx]
|
||||||
|
def fset(self, val):
|
||||||
|
if not val:
|
||||||
|
idx = 0
|
||||||
|
try:
|
||||||
|
idx = self.families.index(type(u'')(val))
|
||||||
|
except ValueError:
|
||||||
|
idx = 0
|
||||||
|
self.setCurrentIndex(idx)
|
||||||
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication([])
|
||||||
|
d = QDialog()
|
||||||
|
d.setLayout(QVBoxLayout())
|
||||||
|
d.layout().addWidget(FontFamilyChooser(d))
|
||||||
|
d.layout().addWidget(QFontComboBox(d))
|
||||||
|
d.exec_()
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user