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
|
||||
from calibre import prepare_string_for_xml
|
||||
from calibre.customize.ui import plugin_for_input_format
|
||||
from calibre.gui2.font_family_chooser import FontFamilyChooser
|
||||
|
||||
def config_widget_for_input_plugin(plugin):
|
||||
name = plugin.name.lower().replace(' ', '_')
|
||||
@ -144,6 +145,8 @@ class Widget(QWidget):
|
||||
return ans
|
||||
elif isinstance(g, QFontComboBox):
|
||||
return unicode(QFontInfo(g.currentFont()).family())
|
||||
elif isinstance(g, FontFamilyChooser):
|
||||
return g.font_family
|
||||
elif isinstance(g, EncodingComboBox):
|
||||
ans = unicode(g.currentText()).strip()
|
||||
try:
|
||||
@ -208,6 +211,8 @@ class Widget(QWidget):
|
||||
getattr(g, 'setCursorPosition', lambda x: x)(0)
|
||||
elif isinstance(g, QFontComboBox):
|
||||
g.setCurrentFont(QFont(val or ''))
|
||||
elif isinstance(g, FontFamilyChooser):
|
||||
g.font_family = val
|
||||
elif isinstance(g, EncodingComboBox):
|
||||
if val:
|
||||
g.setEditText(val)
|
||||
|
@ -6,11 +6,8 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from PyQt4.Qt import Qt
|
||||
|
||||
from calibre.gui2.convert.lrf_output_ui import Ui_Form
|
||||
from calibre.gui2.convert import Widget
|
||||
from calibre.gui2.widgets import FontFamilyModel
|
||||
|
||||
font_family_model = None
|
||||
|
||||
@ -30,13 +27,6 @@ class PluginWidget(Widget, Ui_Form):
|
||||
'header_separation', 'minimum_indent']
|
||||
)
|
||||
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.opt_header.toggle(), self.opt_header.toggle()
|
||||
@ -44,14 +34,4 @@ class PluginWidget(Widget, Ui_Form):
|
||||
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>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="opt_serif_family"/>
|
||||
<widget class="FontFamilyChooser" name="opt_serif_family"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="opt_sans_family"/>
|
||||
<widget class="FontFamilyChooser" name="opt_sans_family"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="opt_mono_family"/>
|
||||
<widget class="FontFamilyChooser" name="opt_mono_family"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -202,6 +202,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FontFamilyChooser</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>calibre/gui2/font_family_chooser.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<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