mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Page Setup plugin for config dialog. Also move EPUB specific options from profiles to EPUB plugin.
This commit is contained in:
parent
5cd88d2602
commit
02f808e399
@ -3,7 +3,6 @@ __license__ = 'GPL 3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
from itertools import izip
|
||||
|
||||
from calibre.customize import Plugin as _Plugin
|
||||
@ -141,13 +140,6 @@ class OutputProfile(Plugin):
|
||||
'if you want to produce a document intended to be read at a '
|
||||
'computer or on a range of devices.')
|
||||
|
||||
# ADE dies an agonizing, long drawn out death if HTML files have more
|
||||
# bytes than this.
|
||||
flow_size = -1
|
||||
# ADE runs screaming when it sees these characters
|
||||
remove_special_chars = re.compile(u'[\u200b\u00ad]')
|
||||
# ADE falls to the ground in a dead faint when it sees an <object>
|
||||
remove_object_tags = True
|
||||
# The image size for comics
|
||||
comic_screen_size = (584, 754)
|
||||
|
||||
@ -162,7 +154,6 @@ class SonyReaderOutput(OutputProfile):
|
||||
description = _('This profile is intended for the SONY PRS line. '
|
||||
'The 500/505/700 etc.')
|
||||
|
||||
flow_size = 270000
|
||||
screen_size = (600, 775)
|
||||
dpi = 168.451
|
||||
fbase = 12
|
||||
|
@ -6,7 +6,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, shutil
|
||||
import os, shutil, re
|
||||
from urllib import unquote
|
||||
|
||||
from calibre.customize.conversion import OutputFormatPlugin
|
||||
@ -42,6 +42,13 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='flow_size', recommended_value=260,
|
||||
help=_('Split all HTML files larger than this size (in KB). '
|
||||
'This is necessary as most EPUB readers cannot handle large '
|
||||
'file sizes. The default of %defaultKB is the size required '
|
||||
'for Adobe Digital Editions.')
|
||||
),
|
||||
|
||||
|
||||
])
|
||||
|
||||
@ -104,7 +111,7 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
|
||||
from calibre.ebooks.oeb.transforms.split import Split
|
||||
split = Split(not self.opts.dont_split_on_page_breaks,
|
||||
max_flow_size=self.opts.output_profile.flow_size
|
||||
max_flow_size=self.opts.flow_size*1024
|
||||
)
|
||||
split(self.oeb, self.opts)
|
||||
|
||||
@ -243,14 +250,12 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
br.tail = ''
|
||||
br.tail += sibling.tail
|
||||
|
||||
|
||||
if self.opts.output_profile.remove_object_tags:
|
||||
for tag in XPath('//h:embed')(root):
|
||||
tag.getparent().remove(tag)
|
||||
for tag in XPath('//h:object')(root):
|
||||
if tag.get('type', '').lower().strip() in ('image/svg+xml',):
|
||||
continue
|
||||
tag.getparent().remove(tag)
|
||||
for tag in XPath('//h:embed')(root):
|
||||
tag.getparent().remove(tag)
|
||||
for tag in XPath('//h:object')(root):
|
||||
if tag.get('type', '').lower().strip() in ('image/svg+xml',):
|
||||
continue
|
||||
tag.getparent().remove(tag)
|
||||
|
||||
for tag in XPath('//h:title|//h:style')(root):
|
||||
if not tag.text:
|
||||
@ -276,5 +281,12 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
stylesheet.data.add('a[href] { color: blue; '
|
||||
'text-decoration: underline; cursor:pointer; }')
|
||||
|
||||
special_chars = re.compile(u'[\u200b\u00ad]')
|
||||
for elem in root.iterdescendants():
|
||||
if getattr(elem, 'text', False):
|
||||
elem.text = special_chars.sub('', elem.text)
|
||||
if getattr(elem, 'tail', False):
|
||||
elem.tail = special_chars.sub('', elem.tail)
|
||||
|
||||
|
||||
|
||||
|
@ -154,8 +154,9 @@ class Widget(QWidget):
|
||||
|
||||
|
||||
def get_value(self, g):
|
||||
if self.get_value_handler(g):
|
||||
return
|
||||
ret = self.get_value_handler(g)
|
||||
if ret != 'this is a dummy return value, xcswx1avcx4x':
|
||||
return ret
|
||||
if isinstance(g, (QSpinBox, QDoubleSpinBox)):
|
||||
return g.value()
|
||||
elif isinstance(g, (QLineEdit, QTextEdit)):
|
||||
@ -217,7 +218,7 @@ class Widget(QWidget):
|
||||
pass
|
||||
|
||||
def get_value_handler(self, g):
|
||||
return False
|
||||
return 'this is a dummy return value, xcswx1avcx4x'
|
||||
|
||||
def post_get_value(self, g):
|
||||
pass
|
||||
|
@ -16,7 +16,7 @@ class PluginWidget(Widget, Ui_Form):
|
||||
|
||||
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
||||
Widget.__init__(self, parent, 'epub_output',
|
||||
['dont_split_on_page_breaks']
|
||||
['dont_split_on_page_breaks', 'flow_size']
|
||||
)
|
||||
self.db, self.book_id = db, book_id
|
||||
self.initialize_options(get_option, get_help, db, book_id)
|
||||
|
@ -13,15 +13,41 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="opt_dont_split_on_page_breaks">
|
||||
<property name="text">
|
||||
<string>Do not &split on page breaks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Split files &larger than:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_flow_size</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="opt_flow_size">
|
||||
<property name="suffix">
|
||||
<string> KB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
74
src/calibre/gui2/convert/page_setup.py
Normal file
74
src/calibre/gui2/convert/page_setup.py
Normal file
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
from __future__ import with_statement
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from PyQt4.Qt import Qt, QAbstractListModel, QVariant, SIGNAL
|
||||
|
||||
from calibre.gui2.convert.page_setup_ui import Ui_Form
|
||||
from calibre.gui2.convert import Widget
|
||||
from calibre.gui2 import NONE
|
||||
from calibre.customize.ui import input_profiles, output_profiles
|
||||
|
||||
class ProfileModel(QAbstractListModel):
|
||||
|
||||
def __init__(self, profiles):
|
||||
QAbstractListModel.__init__(self)
|
||||
self.profiles = list(profiles)
|
||||
|
||||
def rowCount(self, *args):
|
||||
return len(self.profiles)
|
||||
|
||||
def data(self, index, role):
|
||||
profile = self.profiles[index.row()]
|
||||
if role == Qt.DisplayRole:
|
||||
return QVariant(profile.name)
|
||||
if role in (Qt.ToolTipRole, Qt.StatusTipRole, Qt.WhatsThisRole):
|
||||
return QVariant(profile.description)
|
||||
return NONE
|
||||
|
||||
class PageSetupWidget(Widget, Ui_Form):
|
||||
|
||||
TITLE = _('Page Setup')
|
||||
|
||||
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
||||
Widget.__init__(self, parent, 'lrf_output',
|
||||
['margin_top', 'margin_left', 'margin_right', 'margin_bottom',
|
||||
'input_profile', 'output_profile']
|
||||
)
|
||||
|
||||
self.db, self.book_id = db, book_id
|
||||
self.input_model = ProfileModel(input_profiles())
|
||||
self.output_model = ProfileModel(output_profiles())
|
||||
self.opt_input_profile.setModel(self.input_model)
|
||||
self.opt_output_profile.setModel(self.output_model)
|
||||
for x in (self.opt_input_profile, self.opt_output_profile):
|
||||
x.setMouseTracking(True)
|
||||
self.connect(x, SIGNAL('entered(QModelIndex)'), self.show_desc)
|
||||
self.initialize_options(get_option, get_help, db, book_id)
|
||||
|
||||
def show_desc(self, index):
|
||||
desc = index.model().data(index, Qt.StatusTipRole).toString()
|
||||
self.profile_description.setText(desc)
|
||||
|
||||
def set_value_handler(self, g, val):
|
||||
if g in (self.opt_input_profile, self.opt_output_profile):
|
||||
g.clearSelection()
|
||||
for idx, p in enumerate(g.model().profiles):
|
||||
if p.short_name == val:
|
||||
break
|
||||
idx = g.model().index(idx)
|
||||
sm = g.selectionModel()
|
||||
g.setCurrentIndex(idx)
|
||||
sm.select(idx, sm.SelectCurrent)
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_value_handler(self, g):
|
||||
if g in (self.opt_input_profile, self.opt_output_profile):
|
||||
idx = g.currentIndex().row()
|
||||
return g.model().profiles[idx].short_name
|
||||
return Widget.get_value_handler(self, g)
|
189
src/calibre/gui2/convert/page_setup.ui
Normal file
189
src/calibre/gui2/convert/page_setup.ui
Normal file
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>572</width>
|
||||
<height>476</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>&Output profile:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_output_profile</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="opt_output_profile"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>4</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Profile description</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="profile_description">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>4</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>&Input profile:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_input_profile</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="opt_input_profile"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>4</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Margins</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>&Left:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_margin_left</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="opt_margin_left">
|
||||
<property name="suffix">
|
||||
<string> pt</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>&Top:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_margin_top</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="opt_margin_top">
|
||||
<property name="suffix">
|
||||
<string> pt</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>&Right:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_margin_right</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="opt_margin_right">
|
||||
<property name="suffix">
|
||||
<string> pt</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>&Bottom:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_margin_bottom</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="opt_margin_bottom">
|
||||
<property name="suffix">
|
||||
<string> pt</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -16,6 +16,7 @@ from calibre.gui2.convert import GuiRecommendations, save_specifics, \
|
||||
from calibre.gui2.convert.single_ui import Ui_Dialog
|
||||
from calibre.gui2.convert.metadata import MetadataWidget
|
||||
from calibre.gui2.convert.look_and_feel import LookAndFeelWidget
|
||||
from calibre.gui2.convert.page_setup import PageSetupWidget
|
||||
|
||||
from calibre.ebooks.conversion.plumber import Plumber, supported_input_formats, \
|
||||
INPUT_FORMAT_PREFERENCES, OUTPUT_FORMAT_PREFERENCES
|
||||
@ -132,6 +133,7 @@ class Config(ResizableDialog, Ui_Dialog):
|
||||
self.mw = widget_factory(MetadataWidget)
|
||||
self.setWindowTitle(_('Convert')+ ' ' + unicode(self.mw.title.text()))
|
||||
lf = widget_factory(LookAndFeelWidget)
|
||||
ps = widget_factory(PageSetupWidget)
|
||||
|
||||
output_widget = None
|
||||
name = self.plumber.output_plugin.name.lower().replace(' ', '_')
|
||||
@ -159,7 +161,7 @@ class Config(ResizableDialog, Ui_Dialog):
|
||||
if not c: break
|
||||
self.stack.removeWidget(c)
|
||||
|
||||
widgets = [self.mw, lf]
|
||||
widgets = [self.mw, lf, ps]
|
||||
if input_widget is not None:
|
||||
widgets.append(input_widget)
|
||||
if output_widget is not None:
|
||||
@ -234,9 +236,9 @@ if __name__ == '__main__':
|
||||
from calibre.library.database2 import LibraryDatabase2
|
||||
from calibre.gui2 import images_rc, Application
|
||||
images_rc
|
||||
a=Application([])
|
||||
a = Application([])
|
||||
db = LibraryDatabase2('/home/kovid/documents/library')
|
||||
d = Config(None, db, 594)
|
||||
d = Config(None, db, 594)
|
||||
d.show()
|
||||
a.exec_()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user