mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
0415cf3266
@ -4,6 +4,101 @@
|
||||
# for important features/bug fixes.
|
||||
# Also, each release can have new and improved recipes.
|
||||
|
||||
- version: 0.7.35
|
||||
date: 2010-12-23
|
||||
|
||||
new features:
|
||||
- title: "Add a simple to use Rich text editor for comments to the edit metadata dialog."
|
||||
description: >
|
||||
"You can now easily add formatting like bold/italic/lists/headings/colors/etc. to book comments via the
|
||||
edit metadata dialog"
|
||||
type: major
|
||||
|
||||
- title: "E-book viewer: Add a right click menu item 'Inspect' that allows you to inspect the underlying HTML/CSS source of the currently displayed content"
|
||||
type: major
|
||||
|
||||
- title: "When deleting books from the library if a device is connected and the books are also present on the device ask the user if the books should be deleted from the device, the library, or both."
|
||||
|
||||
- title: "Add device drivers for Trekstore eBook Player 7, Sanda Bambook, ALuratek Color, Samsung Galaxy, LG Optimus, Motorola Droid 2 and Sunstech EB700"
|
||||
tickets: [8021, 7966, 7973, 7956]
|
||||
|
||||
- title: "Add an entry to the menu of the calibre library button to select a random book from your calibre library"
|
||||
tickets: [8010]
|
||||
|
||||
- title: "SONY driver: Add a couple of special extra collections for all books by author and all books by title, to workaround the broken sorting on newer SONY models. To enable these collections, go to Preferences->Plugins->Device Interface plugins and customize the SONY plugin."
|
||||
|
||||
- title: "Edit metadata dialog: When downloading metadata, make the table of matching books sortable"
|
||||
tickets: [7951]
|
||||
|
||||
- title: "Add a success message after a database integrity check completes successfully"
|
||||
|
||||
- title: "Search and replace: When using regular expression mode, add a special input field '{template}' that allows use the templating language to create complex input fields. Also allow setting of series_index by search and replace using the same syntax as in the book list, namely, Series Name [series number]"
|
||||
|
||||
- title: "Bulk metadata edit: Add option to automatically set cover from the cover present in the actual ebook files"
|
||||
tickets: [7947]
|
||||
|
||||
- title: "E-book viewer: Show format of current book in the title bar."
|
||||
tickets: [7974]
|
||||
|
||||
- title: "Add a tweak to control how author names are displayed in the Tag Browser and Content Server"
|
||||
|
||||
- title: "FB2 Output: Restore sectionizing functionality"
|
||||
|
||||
bug fixes:
|
||||
- title: "When in narrow layout, reserve 40% of available width in the book details panel for series/formats/etc and use the rest for comments"
|
||||
tickets: [8028]
|
||||
|
||||
- title: "PDB Input: Fix failure to block-indent PML \t sections"
|
||||
tickets: [8019]
|
||||
|
||||
- title: "Tag browser: When renaming items dont reset the library view and try not to scroll the Tag Browser itself"
|
||||
|
||||
- title: "Conversion pipeline: Fix broken link rewriting for inline CSS embedded in HTML"
|
||||
|
||||
- title: "Fix regression in 0.7.34 that broke recipes using extra_css to link to SONY device fonts"
|
||||
tickets: [7995]
|
||||
|
||||
- title: "SONY driver: Don't upload thumbnails as they slow down post disconnect processing on older models"
|
||||
|
||||
- title: "Content server: Fix a bug that allowed remote users to read arbitrary png/gif/js/css/html files"
|
||||
tickets: [7980]
|
||||
|
||||
- title: "On X11 initialize fontconfig in the GUI thread as Qt also uses fontconfig internally and fontconfig is not thread safe. Fixes a few random crashes on calibre strartup"
|
||||
|
||||
- title: "When using the remove specific format actions, only show available formats in the selected books"
|
||||
tickets: [7967]
|
||||
|
||||
- title: "Linux binary build: If setting system default locale fails, try setting locale to en_US.UTF-8 instead"
|
||||
|
||||
- title: "Have the title sort tweak respected everywhere"
|
||||
|
||||
- title: "PocketBook 701 driver: Swap the main memory and card drives on windows"
|
||||
|
||||
- title: "Fix regression in templating that caused series_index to be shown even when book had no series"
|
||||
tickets: [7949]
|
||||
|
||||
- title: "Content server: Fix regressiont hat broke browsing by rating"
|
||||
|
||||
- title: "Content server OPDS feeds: Fix parsing of author names as XML"
|
||||
tickets: [7938]
|
||||
|
||||
improved recipes:
|
||||
- Business Week Magazine
|
||||
- Gazet van Antwerpen
|
||||
- La Nacion
|
||||
- New England Journal of Medicine
|
||||
- Journal of Hospital Medicine
|
||||
|
||||
new recipes:
|
||||
- title: "NRC Handelsblad (EPUB version)"
|
||||
author: "veezh"
|
||||
|
||||
- title: "CND and wenxuecity - znjy"
|
||||
author: "Derek Liang"
|
||||
|
||||
- title: "Mish's Global Economic Trend Analysis"
|
||||
author: "Darko Miletic"
|
||||
|
||||
- version: 0.7.34
|
||||
date: 2010-12-17
|
||||
|
||||
|
BIN
resources/images/edit-clear.png
Normal file
BIN
resources/images/edit-clear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__appname__ = 'calibre'
|
||||
__version__ = '0.7.34'
|
||||
__version__ = '0.7.35'
|
||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||
|
||||
import re
|
||||
|
@ -477,7 +477,8 @@ from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS, \
|
||||
SOVOS, PICO, SUNSTECH_EB700
|
||||
from calibre.devices.sne.driver import SNE
|
||||
from calibre.devices.misc import PALMPRE, AVANT, SWEEX, PDNOVEL, KOGAN, \
|
||||
GEMEI, VELOCITYMICRO, PDNOVEL_KOBO, Q600, LUMIREAD, ALURATEK_COLOR
|
||||
GEMEI, VELOCITYMICRO, PDNOVEL_KOBO, Q600, LUMIREAD, ALURATEK_COLOR, \
|
||||
TREKSTOR
|
||||
from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG
|
||||
from calibre.devices.kobo.driver import KOBO
|
||||
from calibre.devices.bambook.driver import BAMBOOK
|
||||
@ -603,6 +604,7 @@ plugins += [
|
||||
LUMIREAD,
|
||||
ALURATEK_COLOR,
|
||||
BAMBOOK,
|
||||
TREKSTOR,
|
||||
ITUNES,
|
||||
]
|
||||
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
|
||||
|
@ -224,3 +224,23 @@ class ALURATEK_COLOR(USBMS):
|
||||
VENDOR_NAME = 'USB_2.0'
|
||||
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'USB_FLASH_DRIVER'
|
||||
|
||||
class TREKSTOR(USBMS):
|
||||
|
||||
name = 'Trekstor E-book player device interface'
|
||||
gui_name = 'Trekstor'
|
||||
description = _('Communicate with the Trekstor')
|
||||
author = 'Kovid Goyal'
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
|
||||
# Ordered list of supported formats
|
||||
FORMATS = ['epub', 'txt', 'pdf']
|
||||
|
||||
VENDOR_ID = [0x1e68]
|
||||
PRODUCT_ID = [0x0041]
|
||||
BCD = [0x0002]
|
||||
|
||||
EBOOK_DIR_MAIN = 'Ebooks'
|
||||
|
||||
VENDOR_NAME = 'TREKSTOR'
|
||||
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'EBOOK_PLAYER_7'
|
||||
|
||||
|
56
src/calibre/ebooks/oeb/transforms/margins.py
Normal file
56
src/calibre/ebooks/oeb/transforms/margins.py
Normal file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
class RemoveFakeMargins(object):
|
||||
'''
|
||||
Try to detect and remove fake margins inserted by asinine ebook creation
|
||||
software on each paragraph/wrapper div. Can be used only after CSS
|
||||
flattening.
|
||||
'''
|
||||
|
||||
def __call__(self, oeb, opts, log):
|
||||
self.oeb, self.opts, self.log = oeb, opts, log
|
||||
|
||||
from calibre.ebooks.oeb.base import XPath, OEB_STYLES
|
||||
|
||||
stylesheet = None
|
||||
for item in self.oeb.manifest:
|
||||
if item.media_type.lower() in OEB_STYLES:
|
||||
stylesheet = item.data
|
||||
break
|
||||
|
||||
if stylesheet is None:
|
||||
return
|
||||
|
||||
|
||||
top_level_elements = {}
|
||||
second_level_elements = {}
|
||||
|
||||
for x in self.oeb.spine:
|
||||
root = x.data
|
||||
body = XPath('//h:body')(root)
|
||||
if body:
|
||||
body = body[0]
|
||||
|
||||
if not hasattr(body, 'xpath'):
|
||||
continue
|
||||
|
||||
# Check for margins on top level elements
|
||||
for lb in XPath('./h:div|./h:p|./*/h:div|./*/h:p')(body):
|
||||
cls = lb.get('class', '')
|
||||
level = top_level_elements if lb.getparent() is body else \
|
||||
second_level_elements
|
||||
if cls not in level:
|
||||
level[cls] = []
|
||||
top_level_elements[cls] = []
|
||||
level[cls].append(lb)
|
||||
|
||||
|
||||
def get_margins(self, stylesheet, cls):
|
||||
pass
|
||||
|
@ -249,7 +249,7 @@ class BookInfo(QWebView):
|
||||
left_pane = u'<table>%s</table>'%rows
|
||||
right_pane = u'<div>%s</div>'%comments
|
||||
self.setHtml(templ%(u'<table><tr><td valign="top" '
|
||||
'style="padding-right:2em">%s</td><td valign="top">%s</td></tr></table>'
|
||||
'style="padding-right:2em; width:40%%">%s</td><td valign="top">%s</td></tr></table>'
|
||||
% (left_pane, right_pane)))
|
||||
|
||||
def mouseDoubleClickEvent(self, ev):
|
||||
|
@ -62,6 +62,8 @@ class EditorWidget(QWebView): # {{{
|
||||
def __init__(self, parent=None):
|
||||
QWebView.__init__(self, parent)
|
||||
|
||||
self.comments_pat = re.compile(r'<!--.*?-->', re.DOTALL)
|
||||
|
||||
for wac, name, icon, text, checkable in [
|
||||
('ToggleBold', 'bold', 'format-text-bold', _('Bold'), True),
|
||||
('ToggleItalic', 'italic', 'format-text-italic', _('Italic'),
|
||||
@ -137,10 +139,19 @@ class EditorWidget(QWebView): # {{{
|
||||
self.action_insert_link = QAction(QIcon(I('insert-link.png')),
|
||||
_('Insert link'), self)
|
||||
self.action_insert_link.triggered.connect(self.insert_link)
|
||||
self.action_clear = QAction(QIcon(I('edit-clear')), _('Clear'), self)
|
||||
self.action_clear.triggered.connect(self.clear_text)
|
||||
|
||||
self.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
|
||||
self.page().linkClicked.connect(self.link_clicked)
|
||||
|
||||
self.setHtml('')
|
||||
self.page().setContentEditable(True)
|
||||
|
||||
def clear_text(self, *args):
|
||||
self.action_select_all.trigger()
|
||||
self.action_cut.trigger()
|
||||
|
||||
def link_clicked(self, url):
|
||||
open_url(url)
|
||||
|
||||
@ -210,6 +221,7 @@ class EditorWidget(QWebView): # {{{
|
||||
raw = unicode(self.page().mainFrame().toHtml())
|
||||
raw = xml_to_unicode(raw, strip_encoding_pats=True,
|
||||
resolve_entities=True)[0]
|
||||
raw = self.comments_pat.sub('', raw)
|
||||
|
||||
try:
|
||||
root = html.fromstring(raw)
|
||||
@ -218,12 +230,17 @@ class EditorWidget(QWebView): # {{{
|
||||
|
||||
elems = []
|
||||
for body in root.xpath('//body'):
|
||||
if body.text:
|
||||
elems.append(body.text)
|
||||
elems += [html.tostring(x, encoding=unicode) for x in body if
|
||||
x.tag != 'script']
|
||||
x.tag not in ('script', 'style')]
|
||||
|
||||
if len(elems) > 1:
|
||||
ans = u'<div>%s</div>'%(u''.join(elems))
|
||||
else:
|
||||
ans = u''.join(elems)
|
||||
if not ans.startswith('<'):
|
||||
ans = '<p>%s</p>'%ans
|
||||
ans = xml_replace_entities(ans)
|
||||
except:
|
||||
import traceback
|
||||
@ -500,6 +517,7 @@ class Editor(QWidget): # {{{
|
||||
self.toolbar1.addAction(self.editor.action_redo)
|
||||
self.toolbar1.addAction(self.editor.action_select_all)
|
||||
self.toolbar1.addAction(self.editor.action_remove_format)
|
||||
self.toolbar1.addAction(self.editor.action_clear)
|
||||
self.toolbar1.addSeparator()
|
||||
|
||||
for x in ('copy', 'cut', 'paste'):
|
||||
@ -519,7 +537,7 @@ class Editor(QWidget): # {{{
|
||||
self.toolbar1.addAction(self.editor.action_block_style)
|
||||
w = self.toolbar1.widgetForAction(self.editor.action_block_style)
|
||||
w.setPopupMode(w.InstantPopup)
|
||||
self.toolbar1.addAction(self.editor.action_insert_link)
|
||||
self.toolbar2.addAction(self.editor.action_insert_link)
|
||||
|
||||
self.code_edit.textChanged.connect(self.code_dirtied)
|
||||
self.editor.page().contentsChanged.connect(self.wyswyg_dirtied)
|
||||
|
@ -103,7 +103,7 @@ class PluginModel(QAbstractItemModel): # {{{
|
||||
plugin = self.index_to_plugin(index)
|
||||
if role == Qt.DisplayRole:
|
||||
ver = '.'.join(map(str, plugin.version))
|
||||
desc = '\n'.join(textwrap.wrap(plugin.description, 50))
|
||||
desc = '\n'.join(textwrap.wrap(plugin.description, 100))
|
||||
ans='%s (%s) %s %s\n%s'%(plugin.name, ver, _('by'), plugin.author, desc)
|
||||
c = plugin_customization(plugin)
|
||||
if c:
|
||||
|
@ -51,6 +51,10 @@ def comments_to_html(comments):
|
||||
if not isinstance(comments, unicode):
|
||||
comments = comments.decode(preferred_encoding, 'replace')
|
||||
|
||||
if comments.lstrip().startswith('<'):
|
||||
# Comment is already HTML do not mess with it
|
||||
return comments
|
||||
|
||||
if '<' not in comments:
|
||||
comments = prepare_string_for_xml(comments)
|
||||
parts = [u'<p class="description">%s</p>'%x.replace(u'\n', u'<br />')
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user