mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit Book: Make embedding fonts using the manage fonts dialog easier. You can now double click on a font family to see what faces for that family area available on your computer and install new fonts directly from the dialog.
This commit is contained in:
parent
cbfd5f6e38
commit
8ec93d806f
@ -18,6 +18,34 @@ from PyQt5.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen,
|
||||
from calibre.constants import config_dir
|
||||
from calibre.gui2 import choose_files, error_dialog, info_dialog
|
||||
|
||||
|
||||
def add_fonts(parent):
|
||||
from calibre.utils.fonts.metadata import FontMetadata
|
||||
files = choose_files(parent, 'add fonts to calibre',
|
||||
_('Select font files'), filters=[(_('TrueType/OpenType Fonts'),
|
||||
['ttf', 'otf'])], all_files=False)
|
||||
if not files:
|
||||
return
|
||||
families = set()
|
||||
for f in files:
|
||||
try:
|
||||
with open(f, 'rb') as stream:
|
||||
fm = FontMetadata(stream)
|
||||
except:
|
||||
import traceback
|
||||
error_dialog(parent, _('Corrupt font'),
|
||||
_('Failed to read metadata from the font file: %s')%
|
||||
f, det_msg=traceback.format_exc(), show=True)
|
||||
return
|
||||
families.add(fm.font_family)
|
||||
families = sorted(families)
|
||||
|
||||
dest = os.path.join(config_dir, 'fonts')
|
||||
for f in files:
|
||||
shutil.copyfile(f, os.path.join(dest, os.path.basename(f)))
|
||||
|
||||
return families
|
||||
|
||||
def writing_system_for_font(font):
|
||||
has_latin = True
|
||||
systems = QFontDatabase().writingSystems(font.family())
|
||||
@ -136,8 +164,8 @@ class Typefaces(QLabel):
|
||||
'''%(_('Available faces for %s')%family)
|
||||
entries = []
|
||||
for font in faces:
|
||||
sf = (font['wws_subfamily_name'] or font['preferred_subfamily_name']
|
||||
or font['subfamily_name'])
|
||||
sf = (font['wws_subfamily_name'] or font['preferred_subfamily_name'] or
|
||||
font['subfamily_name'])
|
||||
entries.append('''
|
||||
<dt><b>{sf}</b></dt>
|
||||
<dd>font-stretch: <i>{width}</i> font-weight: <i>{weight}</i> font-style:
|
||||
@ -261,29 +289,9 @@ class FontFamilyDialog(QDialog):
|
||||
self.m.setStringList(self.families)
|
||||
|
||||
def add_fonts(self):
|
||||
from calibre.utils.fonts.metadata import FontMetadata
|
||||
files = choose_files(self, 'add fonts to calibre',
|
||||
_('Select font files'), filters=[(_('TrueType/OpenType Fonts'),
|
||||
['ttf', 'otf'])], all_files=False)
|
||||
if not files:
|
||||
families = add_fonts(self)
|
||||
if not families:
|
||||
return
|
||||
families = set()
|
||||
for f in files:
|
||||
try:
|
||||
with open(f, 'rb') as stream:
|
||||
fm = FontMetadata(stream)
|
||||
except:
|
||||
import traceback
|
||||
error_dialog(self, _('Corrupt font'),
|
||||
_('Failed to read metadata from the font file: %s')%
|
||||
f, det_msg=traceback.format_exc(), show=True)
|
||||
return
|
||||
families.add(fm.font_family)
|
||||
families = sorted(families)
|
||||
|
||||
dest = os.path.join(config_dir, 'fonts')
|
||||
for f in files:
|
||||
shutil.copyfile(f, os.path.join(dest, os.path.basename(f)))
|
||||
self.font_scanner.do_scan()
|
||||
self.m.beginResetModel()
|
||||
self.build_font_list()
|
||||
|
@ -6,21 +6,51 @@ from __future__ import (unicode_literals, division, absolute_import,
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import sys
|
||||
import sys, textwrap
|
||||
|
||||
from PyQt5.Qt import (
|
||||
QSplitter, QVBoxLayout, QTableView, QWidget, QLabel, QAbstractTableModel,
|
||||
Qt, QApplication, QTimer, QPushButton, pyqtSignal, QFormLayout, QLineEdit,
|
||||
QIcon, QSize)
|
||||
Qt, QTimer, QPushButton, pyqtSignal, QFormLayout, QLineEdit, QIcon, QSize,
|
||||
QHBoxLayout, QTextEdit)
|
||||
|
||||
from calibre.ebooks.oeb.polish.container import get_container
|
||||
from calibre.ebooks.oeb.polish.fonts import font_family_data, change_font
|
||||
from calibre.gui2 import error_dialog
|
||||
from calibre.gui2 import error_dialog, info_dialog
|
||||
from calibre.gui2.tweak_book import current_container, set_current_container
|
||||
from calibre.gui2.tweak_book.widgets import Dialog, BusyCursor
|
||||
from calibre.utils.icu import primary_sort_key as sort_key
|
||||
from calibre.utils.fonts.scanner import font_scanner, NoFonts
|
||||
|
||||
class EmbeddingData(Dialog):
|
||||
|
||||
def __init__(self, family, faces, parent=None):
|
||||
Dialog.__init__(self, _('Font faces for %s') % family, 'editor-embedding-data', parent)
|
||||
self.family, self.faces = family, faces
|
||||
self.populate_text()
|
||||
|
||||
def sizeHint(self):
|
||||
return QSize(600, 500)
|
||||
|
||||
def setup_ui(self):
|
||||
self.l = l = QVBoxLayout(self)
|
||||
self.text = t = QTextEdit(self)
|
||||
t.setReadOnly(True)
|
||||
l.addWidget(t), l.addWidget(self.bb)
|
||||
self.bb.clear(), self.bb.setStandardButtons(self.bb.Close)
|
||||
|
||||
def populate_text(self):
|
||||
text = ['<h2>' + self.windowTitle() + '</h2><ul>']
|
||||
for face in self.faces:
|
||||
text.append('<li style="margin-bottom:2em">' + _('Path to font file:') + '\xa0\xa0' + '<b>' + face['path'] + '</b>')
|
||||
name = face.get('full_name') or face.get('family_name') or face.get('subfamily_name')
|
||||
if name:
|
||||
text.append('<br>' + _('Name:') + '\xa0<b>' + type('')(name) + '</b>')
|
||||
if 'font-weight' in face:
|
||||
text.append('<br>' + 'font-weight:\xa0' + type('')(face['font-weight']))
|
||||
if 'font-style' in face:
|
||||
text.append('<br>' + 'font-style:\xa0' + type('')(face['font-style']))
|
||||
self.text.setHtml('\n'.join(text))
|
||||
|
||||
class AllFonts(QAbstractTableModel):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@ -65,7 +95,20 @@ class AllFonts(QAbstractTableModel):
|
||||
if role == Qt.TextAlignmentRole:
|
||||
col = index.column()
|
||||
if col == 0:
|
||||
return Qt.AlignHCenter
|
||||
return Qt.AlignHCenter | Qt.AlignVCenter
|
||||
if role in (Qt.UserRole, Qt.UserRole + 1):
|
||||
row = index.row()
|
||||
try:
|
||||
name = self.items[row]
|
||||
except (IndexError, KeyError):
|
||||
return
|
||||
if role == Qt.UserRole:
|
||||
try:
|
||||
return font_scanner.fonts_for_family(name)
|
||||
except NoFonts:
|
||||
return []
|
||||
else:
|
||||
return name
|
||||
|
||||
def sort(self, col, order=Qt.AscendingOrder):
|
||||
sorted_on = (('name' if col == 1 else 'embedded'), order == Qt.AscendingOrder)
|
||||
@ -152,9 +195,16 @@ class ManageFonts(Dialog):
|
||||
self.bb.clear()
|
||||
self.bb.addButton(self.bb.Close)
|
||||
self.splitter = s = QSplitter(self)
|
||||
l.addWidget(s), l.addWidget(self.bb)
|
||||
self.h = h = QHBoxLayout()
|
||||
h.setContentsMargins(0, 0, 0, 0)
|
||||
self.install_fonts_button = b = QPushButton(_('&Install fonts'), self)
|
||||
h.addWidget(b), b.setIcon(QIcon(I('plus.png')))
|
||||
b.setToolTip(textwrap.fill(_('Install fonts from .ttf/.otf files to make them available for embedding')))
|
||||
b.clicked.connect(self.install_fonts)
|
||||
l.addWidget(s), l.addLayout(h), h.addStretch(10), h.addWidget(self.bb)
|
||||
|
||||
self.fonts_view = fv = QTableView(self)
|
||||
fv.doubleClicked.connect(self.show_embedding_data)
|
||||
self.model = m = AllFonts(fv)
|
||||
fv.horizontalHeader().setStretchLastSection(True)
|
||||
fv.setModel(m)
|
||||
@ -190,14 +240,36 @@ class ManageFonts(Dialog):
|
||||
b.setIcon(QIcon(I('view-refresh.png')))
|
||||
b.clicked.connect(self.refresh)
|
||||
|
||||
self.la = la = QLabel('<p>' + _(
|
||||
''' All the fonts declared in this book are shown to the left, along with whether they are embedded or not.
|
||||
You can remove or replace any selected font and also embed any declared fonts that are not already embedded.'''))
|
||||
self.la = la = QLabel(
|
||||
'<p>' + _(
|
||||
''' All the fonts declared in this book are shown to the left, along with whether they are embedded or not.
|
||||
You can remove or replace any selected font and also embed any declared fonts that are not already embedded.''') + '<p>' + _(
|
||||
''' Double click any font family to see if the font is available for embedding on your computer. ''')
|
||||
)
|
||||
la.setWordWrap(True)
|
||||
l.addWidget(la)
|
||||
|
||||
l.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
|
||||
|
||||
def show_embedding_data(self, index):
|
||||
faces = index.data(Qt.UserRole)
|
||||
family = index.data(Qt.UserRole + 1)
|
||||
if not faces:
|
||||
return error_dialog(self, _('Not found'), _(
|
||||
'The font <b>%s</b> was not found on your computer. If you have the font files,'
|
||||
' you can install it using the "Install fonts" button in the lower left corner.'
|
||||
) % family, show=True)
|
||||
EmbeddingData(family, faces, self).exec_()
|
||||
|
||||
def install_fonts(self):
|
||||
from calibre.gui2.font_family_chooser import add_fonts
|
||||
families = add_fonts(self)
|
||||
if not families:
|
||||
return
|
||||
font_scanner.do_scan()
|
||||
self.refresh()
|
||||
info_dialog(self, _('Added fonts'), _('Added font families: %s')%(', '.join(families)), show=True)
|
||||
|
||||
def sizeHint(self):
|
||||
return Dialog.sizeHint(self) + QSize(100, 50)
|
||||
|
||||
@ -250,7 +322,8 @@ class ManageFonts(Dialog):
|
||||
self.model.build()
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication([])
|
||||
from calibre.gui2 import Application
|
||||
app = Application([])
|
||||
c = get_container(sys.argv[-1], tweak_mode=True)
|
||||
set_current_container(c)
|
||||
d = ManageFonts()
|
||||
|
Loading…
x
Reference in New Issue
Block a user