Nicer font family chooser. Should also prevent the open config and crash bug on windows

This commit is contained in:
Kovid Goyal 2012-10-23 15:59:40 +05:30
parent 25db5f9713
commit b0100977bd
6 changed files with 2944 additions and 35 deletions

2862
imgsrc/font.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 119 KiB

BIN
resources/images/font.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -191,6 +191,8 @@ class Widget(QWidget):
elif isinstance(g, (XPathEdit, RegexEdit)): elif isinstance(g, (XPathEdit, RegexEdit)):
g.edit.editTextChanged.connect(f) g.edit.editTextChanged.connect(f)
g.edit.currentIndexChanged.connect(f) g.edit.currentIndexChanged.connect(f)
elif isinstance(g, FontFamilyChooser):
g.family_changed.connect(f)
else: else:
raise Exception('Can\'t connect %s'%type(g)) raise Exception('Can\'t connect %s'%type(g))

View File

@ -418,7 +418,7 @@
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>FontFamilyChooser</class> <class>FontFamilyChooser</class>
<extends>QComboBox</extends> <extends>QWidget</extends>
<header>calibre/gui2/font_family_chooser.h</header> <header>calibre/gui2/font_family_chooser.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View File

@ -205,7 +205,7 @@
<customwidgets> <customwidgets>
<customwidget> <customwidget>
<class>FontFamilyChooser</class> <class>FontFamilyChooser</class>
<extends>QComboBox</extends> <extends>QWidget</extends>
<header>calibre/gui2/font_family_chooser.h</header> <header>calibre/gui2/font_family_chooser.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View File

@ -8,8 +8,10 @@ __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from PyQt4.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen, from PyQt4.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen,
QStyledItemDelegate, QSize, QStyle, QComboBox, QStringListModel, QStyledItemDelegate, QSize, QStyle, QStringListModel, pyqtSignal,
QDialog, QVBoxLayout, QApplication, QFontComboBox) QDialog, QVBoxLayout, QApplication, QFontComboBox, QPushButton,
QToolButton, QGridLayout, QListView, QWidget, QDialogButtonBox, QIcon,
QHBoxLayout, QLabel, QModelIndex)
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
@ -68,6 +70,7 @@ class FontFamilyDelegate(QStyledItemDelegate):
return QSize(m.width(text), m.height()) return QSize(m.width(text), m.height())
def paint(self, painter, option, index): def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, QModelIndex())
painter.save() painter.save()
try: try:
self.do_paint(painter, option, index) self.do_paint(painter, option, index)
@ -89,9 +92,6 @@ class FontFamilyDelegate(QStyledItemDelegate):
r = option.rect r = option.rect
if option.state & QStyle.State_Selected: if option.state & QStyle.State_Selected:
painter.setBrush(option.palette.highlight())
painter.setPen(Qt.NoPen)
painter.drawRect(option.rect)
painter.setPen(QPen(option.palette.highlightedText(), 0)) painter.setPen(QPen(option.palette.highlightedText(), 0))
if (option.direction == Qt.RightToLeft): if (option.direction == Qt.RightToLeft):
@ -112,13 +112,18 @@ class FontFamilyDelegate(QStyledItemDelegate):
r.setLeft(r.left() + w) r.setLeft(r.left() + w)
painter.drawText(r, Qt.AlignVCenter|Qt.AlignLeading|Qt.TextSingleLine, sample) painter.drawText(r, Qt.AlignVCenter|Qt.AlignLeading|Qt.TextSingleLine, sample)
class FontFamilyChooser(QComboBox): class Typefaces(QWidget):
pass
def __init__(self, parent=None): class FontFamilyDialog(QDialog):
QComboBox.__init__(self, parent)
def __init__(self, current_family, parent=None):
QDialog.__init__(self, parent)
self.setWindowTitle(_('Choose font family'))
self.setWindowIcon(QIcon(I('font.png')))
from calibre.utils.fonts import fontconfig from calibre.utils.fonts import fontconfig
try: try:
ok, self.families = fontconfig.find_font_families_no_delay() self.families = fontconfig.find_font_families()
except: except:
self.families = [] self.families = []
print ('WARNING: Could not load fonts') print ('WARNING: Could not load fonts')
@ -131,42 +136,82 @@ class FontFamilyChooser(QComboBox):
self.families.sort(key=sort_key) self.families.sort(key=sort_key)
self.families.insert(0, _('None')) self.families.insert(0, _('None'))
self.l = l = QGridLayout()
self.setLayout(l)
self.view = QListView(self)
self.m = QStringListModel(self.families) self.m = QStringListModel(self.families)
self.setModel(self.m) self.view.setModel(self.m)
self.d = FontFamilyDelegate(self) self.d = FontFamilyDelegate(self)
self.setItemDelegate(self.d) self.view.setItemDelegate(self.d)
self.setCurrentIndex(0) self.view.setCurrentIndex(self.m.index(0))
if current_family:
for i, val in enumerate(self.families):
if icu_lower(val) == icu_lower(current_family):
self.view.setCurrentIndex(self.m.index(i))
break
self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection)
self.view.setSelectionMode(self.view.SingleSelection)
def event(self, e): self.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
if e.type() == e.Resize: self.bb.accepted.connect(self.accept)
view = self.view() self.bb.rejected.connect(self.reject)
view.window().setFixedWidth(self.width() * 5/3) self.ml = QLabel(_('Choose a font family from the list below:'))
return QComboBox.event(self, e)
def sizeHint(self): self.faces = Typefaces(self)
ans = QComboBox.sizeHint(self)
try: l.addWidget(self.ml, 0, 0, 1, 2)
ans.setWidth(QFontMetrics(self.font()).width('m'*14)) l.addWidget(self.view, 1, 0, 1, 1)
except: l.addWidget(self.faces, 1, 1, 1, 1)
pass l.addWidget(self.bb, 2, 0, 1, 2)
return ans
self.resize(600, 500)
@property
def font_family(self):
idx = self.view.currentIndex().row()
if idx == 0: return None
return self.families[idx]
class FontFamilyChooser(QWidget):
family_changed = pyqtSignal(object)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.l = l = QHBoxLayout()
self.setLayout(l)
self.button = QPushButton(self)
self.button.setIcon(QIcon(I('font.png')))
l.addWidget(self.button)
self.default_text = _('Choose &font family')
self.font_family = None
self.button.clicked.connect(self.show_chooser)
self.clear_button = QToolButton(self)
self.clear_button.setIcon(QIcon(I('clear_left.png')))
self.clear_button.clicked.connect(self.clear_family)
l.addWidget(self.clear_button)
def clear_family(self):
self.font_family = None
@dynamic_property @dynamic_property
def font_family(self): def font_family(self):
def fget(self): def fget(self):
idx= self.currentIndex() return self._current_family
if idx == 0: return None
return self.families[idx]
def fset(self, val): def fset(self, val):
if not val: if not val:
idx = 0 val = None
try: self._current_family = val
idx = self.families.index(type(u'')(val)) self.button.setText(val or self.default_text)
except ValueError: self.family_changed.emit(val)
idx = 0
self.setCurrentIndex(idx)
return property(fget=fget, fset=fset) return property(fget=fget, fset=fset)
def show_chooser(self):
d = FontFamilyDialog(self.font_family, self)
if d.exec_() == d.Accepted:
self.font_family = d.font_family
def test(): def test():
app = QApplication([]) app = QApplication([])
app app