Sync to trunk.

This commit is contained in:
John Schember 2011-05-02 20:41:32 -04:00
commit c7c5a3700b
20 changed files with 351 additions and 30 deletions

View File

@ -3,7 +3,8 @@
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2010, Constantin Hofstetter <consti at consti.de>, Steffen Siebert <calibre at steffensiebert.de>' __copyright__ = '2010, Constantin Hofstetter <consti at consti.de>, Steffen Siebert <calibre at steffensiebert.de>'
__version__ = '0.98' # 2011-04-10 __version__ = '0.98'
''' http://brandeins.de - Wirtschaftsmagazin ''' ''' http://brandeins.de - Wirtschaftsmagazin '''
import re import re
import string import string
@ -13,8 +14,8 @@ from calibre.web.feeds.recipes import BasicNewsRecipe
class BrandEins(BasicNewsRecipe): class BrandEins(BasicNewsRecipe):
title = u'brand eins' title = u'brand eins'
__author__ = 'Constantin Hofstetter; Steffen Siebert' __author__ = 'Constantin Hofstetter'
description = u'Wirtschaftsmagazin: Gets the last full issue on default. Set a integer value for the username-field to get older issues: 1 -> the newest (but not complete) issue, 2 -> the last complete issue (default), 3 -> the issue before 2 etc.' description = u'Wirtschaftsmagazin'
publisher ='brandeins.de' publisher ='brandeins.de'
category = 'politics, business, wirtschaft, Germany' category = 'politics, business, wirtschaft, Germany'
use_embedded_content = False use_embedded_content = False
@ -105,10 +106,11 @@ class BrandEins(BasicNewsRecipe):
keys = issue_map.keys() keys = issue_map.keys()
keys.sort() keys.sort()
keys.reverse() keys.reverse()
selected_issue = issue_map[keys[issue-1]] selected_issue_key = keys[issue - 1]
selected_issue = issue_map[selected_issue_key]
url = selected_issue.get('href', False) url = selected_issue.get('href', False)
# Get the title for the magazin - build it out of the title of the cover - take the issue and year; # Get the title for the magazin - build it out of the title of the cover - take the issue and year;
self.title = "brand eins "+ re.search(r"(?P<date>\d\d\/\d\d\d\d)", selected_issue.find('img').get('title', False)).group('date') self.title = "brand eins " + selected_issue_key[4:] + "/" + selected_issue_key[0:4]
url = 'http://brandeins.de/'+url url = 'http://brandeins.de/'+url
# url = "http://www.brandeins.de/archiv/magazin/tierisch.html" # url = "http://www.brandeins.de/archiv/magazin/tierisch.html"
@ -161,3 +163,4 @@ class BrandEins(BasicNewsRecipe):
current_articles.append({'title': title, 'url': url, 'description': description, 'date':''}) current_articles.append({'title': title, 'url': url, 'description': description, 'date':''})
titles_and_articles.append([chapter_title, current_articles]) titles_and_articles.append([chapter_title, current_articles])
return titles_and_articles return titles_and_articles

View File

@ -595,6 +595,7 @@ from calibre.devices.jetbook.driver import JETBOOK, MIBUK, JETBOOK_MINI
from calibre.devices.kindle.driver import KINDLE, KINDLE2, KINDLE_DX from calibre.devices.kindle.driver import KINDLE, KINDLE2, KINDLE_DX
from calibre.devices.nook.driver import NOOK, NOOK_COLOR from calibre.devices.nook.driver import NOOK, NOOK_COLOR
from calibre.devices.prs505.driver import PRS505 from calibre.devices.prs505.driver import PRS505
from calibre.devices.user_defined.driver import USER_DEFINED
from calibre.devices.android.driver import ANDROID, S60 from calibre.devices.android.driver import ANDROID, S60
from calibre.devices.nokia.driver import N770, N810, E71X, E52 from calibre.devices.nokia.driver import N770, N810, E71X, E52
from calibre.devices.eslick.driver import ESLICK, EBK52 from calibre.devices.eslick.driver import ESLICK, EBK52
@ -742,6 +743,7 @@ plugins += [
EEEREADER, EEEREADER,
NEXTBOOK, NEXTBOOK,
ITUNES, ITUNES,
USER_DEFINED,
] ]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \ plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataReader')] x.__name__.endswith('MetadataReader')]

View File

@ -19,6 +19,7 @@ from calibre.utils.config import (make_config_dir, Config, ConfigProxy,
plugin_dir, OptionParser) plugin_dir, OptionParser)
from calibre.ebooks.epub.fix import ePubFixer from calibre.ebooks.epub.fix import ePubFixer
from calibre.ebooks.metadata.sources.base import Source from calibre.ebooks.metadata.sources.base import Source
from calibre.constants import DEBUG
builtin_names = frozenset([p.name for p in builtin_plugins]) builtin_names = frozenset([p.name for p in builtin_plugins])
@ -487,8 +488,9 @@ def initialize_plugins():
plugin = initialize_plugin(plugin, None if isinstance(zfp, type) else zfp) plugin = initialize_plugin(plugin, None if isinstance(zfp, type) else zfp)
_initialized_plugins.append(plugin) _initialized_plugins.append(plugin)
except: except:
print 'Failed to initialize plugin...' print 'Failed to initialize plugin:', repr(zfp)
traceback.print_exc() if DEBUG:
traceback.print_exc()
_initialized_plugins.sort(cmp=lambda x,y:cmp(x.priority, y.priority), reverse=True) _initialized_plugins.sort(cmp=lambda x,y:cmp(x.priority, y.priority), reverse=True)
reread_filetype_plugins() reread_filetype_plugins()
reread_metadata_plugins() reread_metadata_plugins()

View File

@ -156,3 +156,60 @@ def debug(ioreg_to_tmp=False, buf=None):
sys.stdout = oldo sys.stdout = oldo
sys.stderr = olde sys.stderr = olde
def device_info(ioreg_to_tmp=False, buf=None):
from calibre.devices.scanner import DeviceScanner, win_pnp_drives
from calibre.constants import iswindows
import re
res = {}
device_details = {}
device_set = set()
drive_details = {}
drive_set = set()
res['device_set'] = device_set
res['device_details'] = device_details
res['drive_details'] = drive_details
res['drive_set'] = drive_set
try:
s = DeviceScanner()
s.scan()
devices = (s.devices)
if not iswindows:
devices = [list(x) for x in devices]
for dev in devices:
for i in range(3):
dev[i] = hex(dev[i])
d = dev[0] + dev[1] + dev[2]
device_set.add(d)
device_details[d] = dev[0:3]
else:
for dev in devices:
vid = re.search('vid_([0-9a-f]*)&', dev)
if vid:
vid = vid.group(1)
pid = re.search('pid_([0-9a-f]*)&', dev)
if pid:
pid = pid.group(1)
rev = re.search('rev_([0-9a-f]*)$', dev)
if rev:
rev = rev.group(1)
d = vid+pid+rev
device_set.add(d)
device_details[d] = (vid, pid, rev)
drives = win_pnp_drives(debug=False)
for drive,details in drives.iteritems():
order = 'ORD_' + str(drive.order)
ven = re.search('VEN_([^&]*)&', details)
if ven:
ven = ven.group(1)
prod = re.search('PROD_([^&]*)&', details)
if prod:
prod = prod.group(1)
d = (order, ven, prod)
drive_details[drive] = d
drive_set.add(drive)
finally:
pass
return res

View File

@ -62,7 +62,7 @@ class ANDROID(USBMS):
0x502 : { 0x3203 : [0x0100]}, 0x502 : { 0x3203 : [0x0100]},
# Dell # Dell
0x413c : { 0xb007 : [0x0100, 0x0224]}, 0x413c : { 0xb007 : [0x0100, 0x0224, 0x0226]},
# LG # LG
0x1004 : { 0x61cc : [0x100], 0x61ce : [0x100], 0x618e : [0x226] }, 0x1004 : { 0x61cc : [0x100], 0x61ce : [0x100], 0x618e : [0x226] },
@ -112,7 +112,7 @@ class ANDROID(USBMS):
'MB860', 'MULTI-CARD', 'MID7015A', 'INCREDIBLE', 'A7EB'] 'MB860', 'MULTI-CARD', 'MID7015A', 'INCREDIBLE', 'A7EB']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897', WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB'] 'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD']
OSX_MAIN_MEM = 'Android Device Main Memory' OSX_MAIN_MEM = 'Android Device Main Memory'

View File

@ -94,6 +94,9 @@ class DeviceConfig(object):
if isinstance(cls.EXTRA_CUSTOMIZATION_MESSAGE, list): if isinstance(cls.EXTRA_CUSTOMIZATION_MESSAGE, list):
ec = [] ec = []
for i in range(0, len(cls.EXTRA_CUSTOMIZATION_MESSAGE)): for i in range(0, len(cls.EXTRA_CUSTOMIZATION_MESSAGE)):
if config_widget.opt_extra_customization[i] is None:
ec.append(None)
continue
if hasattr(config_widget.opt_extra_customization[i], 'isChecked'): if hasattr(config_widget.opt_extra_customization[i], 'isChecked'):
ec.append(config_widget.opt_extra_customization[i].isChecked()) ec.append(config_widget.opt_extra_customization[i].isChecked())
else: else:

View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from calibre.devices.usbms.driver import USBMS
class USER_DEFINED(USBMS):
name = 'User Defined USB driver'
gui_name = 'User Defined USB Device'
author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
FORMATS = ['epub', 'mobi', 'pdf']
VENDOR_ID = 0xFFFF
PRODUCT_ID = 0xFFFF
BCD = None
EBOOK_DIR_MAIN = ''
EBOOK_DIR_CARD_A = ''
VENDOR_NAME = []
WINDOWS_MAIN_MEM = ''
WINDOWS_CARD_A_MEM = ''
OSX_MAIN_MEM = 'Device Main Memory'
MAIN_MEMORY_VOLUME_LABEL = 'Device Main Memory'
SUPPORTS_SUB_DIRS = True
EXTRA_CUSTOMIZATION_MESSAGE = [
_('USB Vendor ID (in hex)') + ':::<p>' +
_('Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
_('USB Product ID (in hex)')+ ':::<p>' +
_('Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
_('USB Revision ID (in hex)')+ ':::<p>' +
_('Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
'',
_('Windows main memory vendor string') + ':::<p>' +
_('This field is used only on windows. '
'Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
_('Windows main memory ID string') + ':::<p>' +
_('This field is used only on windows. '
'Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
_('Windows card A vendor string') + ':::<p>' +
_('This field is used only on windows. '
'Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
_('Windows card A ID string') + ':::<p>' +
_('This field is used only on windows. '
'Get this ID using Preferences -> Misc -> Get information to '
'set up the user-defined device') + '</p>',
_('Main memory folder') + ':::<p>' +
_('Enter the folder where the books are to be stored. This folder '
'is prepended to any send_to_device template') + '</p>',
_('Card A folder') + ':::<p>' +
_('Enter the folder where the books are to be stored. This folder '
'is prepended to any send_to_device template') + '</p>',
]
EXTRA_CUSTOMIZATION_DEFAULT = [
'0x0000',
'0x0000',
'0x0000',
None,
'',
'',
'',
'',
'',
'',
]
OPT_USB_VENDOR_ID = 0
OPT_USB_PRODUCT_ID = 1
OPT_USB_REVISION_ID = 2
OPT_USB_WINDOWS_MM_VEN_ID = 4
OPT_USB_WINDOWS_MM_ID = 5
OPT_USB_WINDOWS_CA_VEN_ID = 6
OPT_USB_WINDOWS_CA_ID = 7
OPT_MAIN_MEM_FOLDER = 8
OPT_CARD_A_FOLDER = 9
def initialize(self):
try:
e = self.settings().extra_customization
self.VENDOR_ID = int(e[self.OPT_USB_VENDOR_ID], 16)
self.PRODUCT_ID = int(e[self.OPT_USB_PRODUCT_ID], 16)
self.BCD = [int(e[self.OPT_USB_REVISION_ID], 16)]
if e[self.OPT_USB_WINDOWS_MM_VEN_ID]:
self.VENDOR_NAME.append(e[self.OPT_USB_WINDOWS_MM_VEN_ID])
if e[self.OPT_USB_WINDOWS_CA_VEN_ID] and \
e[self.OPT_USB_WINDOWS_CA_VEN_ID] not in self.VENDOR_NAME:
self.VENDOR_NAME.append(e[self.OPT_USB_WINDOWS_CA_VEN_ID])
self.WINDOWS_MAIN_MEM = e[self.OPT_USB_WINDOWS_MM_ID] + '&'
self.WINDOWS_CARD_A_MEM = e[self.OPT_USB_WINDOWS_CA_ID] + '&'
self.EBOOK_DIR_MAIN = e[self.OPT_MAIN_MEM_FOLDER]
self.EBOOK_DIR_CARD_A = e[self.OPT_CARD_A_FOLDER]
except:
import traceback
traceback.print_exc()
USBMS.initialize(self)

View File

@ -253,6 +253,8 @@ class MobiReader(object):
.italic { font-style: italic } .italic { font-style: italic }
.underline { text-decoration: underline }
.mbp_pagebreak { .mbp_pagebreak {
page-break-after: always; margin: 0; display: block page-break-after: always; margin: 0; display: block
} }
@ -601,6 +603,9 @@ class MobiReader(object):
elif tag.tag == 'i': elif tag.tag == 'i':
tag.tag = 'span' tag.tag = 'span'
tag.attrib['class'] = 'italic' tag.attrib['class'] = 'italic'
elif tag.tag == 'u':
tag.tag = 'span'
tag.attrib['class'] = 'underline'
elif tag.tag == 'b': elif tag.tag == 'b':
tag.tag = 'span' tag.tag = 'span'
tag.attrib['class'] = 'bold' tag.attrib['class'] = 'bold'

View File

@ -1049,8 +1049,8 @@ class Manifest(object):
# Remove hyperlinks with no content as they cause rendering # Remove hyperlinks with no content as they cause rendering
# artifacts in browser based renderers # artifacts in browser based renderers
# Also remove empty <b> and <i> tags # Also remove empty <b>, <u> and <i> tags
for a in xpath(data, '//h:a[@href]|//h:i|//h:b'): for a in xpath(data, '//h:a[@href]|//h:i|//h:b|//h:u'):
if a.get('id', None) is None and a.get('name', None) is None \ if a.get('id', None) is None and a.get('name', None) is None \
and len(a) == 0 and not a.text: and len(a) == 0 and not a.text:
remove_elem(a) remove_elem(a)

View File

@ -60,7 +60,7 @@ class ViewAction(InterfaceAction):
def build_menus(self, db): def build_menus(self, db):
self.view_menu.clear() self.view_menu.clear()
self.view_menu.addAction(self.qaction) self.view_menu.addAction(self.view_action)
self.view_menu.addAction(self.view_specific_action) self.view_menu.addAction(self.view_specific_action)
self.view_menu.addSeparator() self.view_menu.addSeparator()
self.view_menu.addAction(self.action_pick_random) self.view_menu.addAction(self.action_pick_random)

View File

@ -62,8 +62,18 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
if isinstance(extra_customization_message, list): if isinstance(extra_customization_message, list):
self.opt_extra_customization = [] self.opt_extra_customization = []
if len(extra_customization_message) > 6:
row_func = lambda x, y: ((x/2) * 2) + y
col_func = lambda x: x%2
else:
row_func = lambda x, y: x*2 + y
col_func = lambda x: 0
for i, m in enumerate(extra_customization_message): for i, m in enumerate(extra_customization_message):
label_text, tt = parse_msg(m) label_text, tt = parse_msg(m)
if not label_text:
self.opt_extra_customization.append(None)
continue
if isinstance(settings.extra_customization[i], bool): if isinstance(settings.extra_customization[i], bool):
self.opt_extra_customization.append(QCheckBox(label_text)) self.opt_extra_customization.append(QCheckBox(label_text))
self.opt_extra_customization[-1].setToolTip(tt) self.opt_extra_customization[-1].setToolTip(tt)
@ -75,8 +85,9 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
l.setBuddy(self.opt_extra_customization[i]) l.setBuddy(self.opt_extra_customization[i])
l.setWordWrap(True) l.setWordWrap(True)
self.opt_extra_customization[i].setText(settings.extra_customization[i]) self.opt_extra_customization[i].setText(settings.extra_customization[i])
self.extra_layout.addWidget(l) self.extra_layout.addWidget(l, row_func(i, 0), col_func(i))
self.extra_layout.addWidget(self.opt_extra_customization[i]) self.extra_layout.addWidget(self.opt_extra_customization[i],
row_func(i, 1), col_func(i))
else: else:
self.opt_extra_customization = QLineEdit() self.opt_extra_customization = QLineEdit()
label_text, tt = parse_msg(extra_customization_message) label_text, tt = parse_msg(extra_customization_message)
@ -86,8 +97,8 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
l.setWordWrap(True) l.setWordWrap(True)
if settings.extra_customization: if settings.extra_customization:
self.opt_extra_customization.setText(settings.extra_customization) self.opt_extra_customization.setText(settings.extra_customization)
self.extra_layout.addWidget(l) self.extra_layout.addWidget(l, 0, 0)
self.extra_layout.addWidget(self.opt_extra_customization) self.extra_layout.addWidget(self.opt_extra_customization, 1, 0)
self.opt_save_template.setText(settings.save_template) self.opt_save_template.setText(settings.save_template)

View File

@ -101,7 +101,7 @@
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="6" column="0">
<layout class="QVBoxLayout" name="extra_layout"/> <layout class="QGridLayout" name="extra_layout"/>
</item> </item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">

View File

@ -0,0 +1,105 @@
#!/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 QDialog, QVBoxLayout, QPlainTextEdit, QTimer, \
QDialogButtonBox, QPushButton, QApplication, QIcon, QMessageBox
from calibre.constants import iswindows
def step_dialog(parent, title, msg, det_msg=''):
d = QMessageBox(parent)
d.setWindowTitle(title)
d.setText(msg)
d.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
return d.exec_() & QMessageBox.Cancel
class UserDefinedDevice(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self._layout = QVBoxLayout(self)
self.setLayout(self._layout)
self.log = QPlainTextEdit(self)
self._layout.addWidget(self.log)
self.log.setPlainText(_('Getting device information')+'...')
self.copy = QPushButton(_('Copy to &clipboard'))
self.copy.setDefault(True)
self.setWindowTitle(_('User-defined device information'))
self.setWindowIcon(QIcon(I('debug.png')))
self.copy.clicked.connect(self.copy_to_clipboard)
self.ok = QPushButton('&OK')
self.ok.setAutoDefault(False)
self.ok.clicked.connect(self.accept)
self.bbox = QDialogButtonBox(self)
self.bbox.addButton(self.copy, QDialogButtonBox.ActionRole)
self.bbox.addButton(self.ok, QDialogButtonBox.AcceptRole)
self._layout.addWidget(self.bbox)
self.resize(750, 500)
self.bbox.setEnabled(False)
QTimer.singleShot(1000, self.device_info)
def device_info(self):
try:
from calibre.devices import device_info
r = step_dialog(self.parent(), _('Device Detection'),
_('Ensure your device is disconnected, then press OK'))
if r:
self.close()
return
before = device_info()
r = step_dialog(self.parent(), _('Device Detection'),
_('Ensure your device is connected, then press OK'))
if r:
self.close()
return
after = device_info()
new_drives = after['drive_set'] - before['drive_set']
new_devices = after['device_set'] - before['device_set']
res = ''
if (not iswindows or len(new_drives)) and len(new_devices) == 1:
for d in new_devices:
res = _('USB Vendor ID (in hex)') + ': 0x' + \
after['device_details'][d][0] + '\n'
res += _('USB Product ID (in hex)') + ': 0x' + \
after['device_details'][d][1] + '\n'
res += _('USB Revision ID (in hex)') + ': 0x' + \
after['device_details'][d][2] + '\n'
if iswindows:
# sort the drives by the order number
for i,d in enumerate(sorted(new_drives,
key=lambda x: after['drive_details'][x][0])):
if i == 0:
res += _('Windows main memory ID string') + ': ' + \
after['drive_details'][d][1] + '\n'
res += _('Windows main memory ID string') + ': ' + \
after['drive_details'][d][2] + '\n'
else:
res += _('Windows card A vendor string') + ': ' + \
after['drive_details'][d][1] + '\n'
res += _('Windows card A ID string') + ': ' + \
after['drive_details'][d][2] + '\n'
trailer = _(
'Copy these values to the clipboard, paste them into an '
'editor, then enter them into the USER_DEVICE by '
'customizing the device plugin in Preferences->Plugins. '
'Remember to also enter the folders where you want the books to '
'be put. You must restart calibre for your changes '
'to take effect.\n')
self.log.setPlainText(res + '\n\n' + trailer)
finally:
self.bbox.setEnabled(True)
def copy_to_clipboard(self):
QApplication.clipboard().setText(self.log.toPlainText())
if __name__ == '__main__':
app = QApplication([])
d = UserDefinedDevice()
d.exec_()

View File

@ -30,6 +30,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('enforce_cpu_limit', config, restart_required=True) r('enforce_cpu_limit', config, restart_required=True)
self.device_detection_button.clicked.connect(self.debug_device_detection) self.device_detection_button.clicked.connect(self.debug_device_detection)
self.button_open_config_dir.clicked.connect(self.open_config_dir) self.button_open_config_dir.clicked.connect(self.open_config_dir)
self.user_defined_device_button.clicked.connect(self.user_defined_device)
self.button_osx_symlinks.clicked.connect(self.create_symlinks) self.button_osx_symlinks.clicked.connect(self.create_symlinks)
self.button_osx_symlinks.setVisible(isosx) self.button_osx_symlinks.setVisible(isosx)
@ -38,6 +39,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
d = DebugDevice(self) d = DebugDevice(self)
d.exec_() d.exec_()
def user_defined_device(self, *args):
from calibre.gui2.preferences.device_user_defined import UserDefinedDevice
d = UserDefinedDevice(self)
d.exec_()
def open_config_dir(self, *args): def open_config_dir(self, *args):
from calibre.utils.config import config_dir from calibre.utils.config import config_dir
open_local_file(config_dir) open_local_file(config_dir)

View File

@ -58,7 +58,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="4" column="0" colspan="2">
<widget class="QPushButton" name="user_defined_device_button">
<property name="text">
<string>Get information to setup the &amp;user defined device</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer_6"> <spacer name="verticalSpacer_6">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>

View File

@ -8,6 +8,7 @@ from collections import namedtuple
from copy import deepcopy from copy import deepcopy
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
from lxml import etree from lxml import etree
from types import StringType, UnicodeType
from calibre import prints, prepare_string_for_xml, strftime from calibre import prints, prepare_string_for_xml, strftime
from calibre.constants import preferred_encoding, DEBUG from calibre.constants import preferred_encoding, DEBUG
@ -15,13 +16,16 @@ from calibre.customize import CatalogPlugin
from calibre.customize.conversion import OptionRecommendation, DummyReporter from calibre.customize.conversion import OptionRecommendation, DummyReporter
from calibre.ebooks.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, Tag, NavigableString from calibre.ebooks.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, Tag, NavigableString
from calibre.ebooks.chardet import substitute_entites from calibre.ebooks.chardet import substitute_entites
from calibre.library.save_to_disk import preprocess_template
from calibre.ptempfile import PersistentTemporaryDirectory from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.utils.bibtex import BibTeX
from calibre.utils.config import config_dir from calibre.utils.config import config_dir
from calibre.utils.date import format_date, isoformat, is_date_undefined, now as nowf from calibre.utils.date import format_date, isoformat, is_date_undefined, now as nowf
from calibre.utils.html2text import html2text
from calibre.utils.icu import capitalize from calibre.utils.icu import capitalize
from calibre.utils.logging import default_log as log from calibre.utils.logging import default_log as log
from calibre.utils.zipfile import ZipFile, ZipInfo
from calibre.utils.magick.draw import thumbnail from calibre.utils.magick.draw import thumbnail
from calibre.utils.zipfile import ZipFile, ZipInfo
FIELDS = ['all', 'title', 'author_sort', 'authors', 'comments', FIELDS = ['all', 'title', 'author_sort', 'authors', 'comments',
'cover', 'formats','id', 'isbn', 'ondevice', 'pubdate', 'publisher', 'cover', 'formats','id', 'isbn', 'ondevice', 'pubdate', 'publisher',
@ -303,12 +307,6 @@ class BIBTEX(CatalogPlugin): # {{{
def run(self, path_to_output, opts, db, notification=DummyReporter()): def run(self, path_to_output, opts, db, notification=DummyReporter()):
from types import StringType, UnicodeType
from calibre.library.save_to_disk import preprocess_template
#Bibtex functions
from calibre.utils.bibtex import BibTeX
def create_bibtex_entry(entry, fields, mode, template_citation, def create_bibtex_entry(entry, fields, mode, template_citation,
bibtexdict, citation_bibtex=True, calibre_files=True): bibtexdict, citation_bibtex=True, calibre_files=True):
@ -365,6 +363,11 @@ class BIBTEX(CatalogPlugin): # {{{
#\n removal #\n removal
item = item.replace(u'\r\n',u' ') item = item.replace(u'\r\n',u' ')
item = item.replace(u'\n',u' ') item = item.replace(u'\n',u' ')
#html to text
try:
item = html2text(item)
except:
log.warn("Failed to convert comments to text")
bibtex_entry.append(u'note = "%s"' % bibtexdict.utf8ToBibtex(item)) bibtex_entry.append(u'note = "%s"' % bibtexdict.utf8ToBibtex(item))
elif field == 'isbn' : elif field == 'isbn' :

View File

@ -100,7 +100,9 @@ Device Integration
What devices does |app| support? What devices does |app| support?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At the moment |app| has full support for the SONY PRS line, Barnes & Noble Nook line, Cybook Gen 3/Opus, Amazon Kindle line, Entourage Edge, Longshine ShineBook, Ectaco Jetbook, BeBook/BeBook Mini, Irex Illiad/DR1000, Foxit eSlick, PocketBook line, Italica, eClicto, Iriver Story, Airis dBook, Hanvon N515, Binatone Readme, Teclast K3 and clones, SpringDesign Alex, Kobo Reader, various Android phones and the iPhone/iPad. In addition, using the :guilabel:`Connect to folder` function you can use it with any ebook reader that exports itself as a USB disk. At the moment |app| has full support for the SONY PRS line, Barnes & Noble Nook line, Cybook Gen 3/Opus, Amazon Kindle line, Entourage Edge, Longshine ShineBook, Ectaco Jetbook, BeBook/BeBook Mini, Irex Illiad/DR1000, Foxit eSlick, PocketBook line, Italica, eClicto, Iriver Story, Airis dBook, Hanvon N515, Binatone Readme, Teclast K3 and clones, SpringDesign Alex, Kobo Reader, various Android phones and the iPhone/iPad. In addition, using the :guilabel:`Connect to folder` function you can use it with any ebook reader that exports itself as a USB disk.
There is also a special ``User Defined`` device plugin that can be used to connect to arbitrary devices that present their memory as disk drives. See the device plugin ``Preferences -> Plugins -> Device Plugins -> User Defined`` and ``Preferences -> Miscelleaneous -> Get information to setup the user defined device`` for more information.
How can I help get my device supported in |app|? How can I help get my device supported in |app|?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -133,6 +135,11 @@ Follow these steps to find the problem:
* In calibre, go to Preferences->Plugins->Device Interface plugin and make sure the plugin for your device is enabled, the plugin icon next to it should be green when it is enabled. * In calibre, go to Preferences->Plugins->Device Interface plugin and make sure the plugin for your device is enabled, the plugin icon next to it should be green when it is enabled.
* If all the above steps fail, go to Preferences->Miscellaneous and click debug device detection with your device attached and post the output as a ticket on `the calibre bug tracker <http://bugs.calibre-ebook.com>`_. * If all the above steps fail, go to Preferences->Miscellaneous and click debug device detection with your device attached and post the output as a ticket on `the calibre bug tracker <http://bugs.calibre-ebook.com>`_.
My device is non-standard or unusual. What can I do to connect to it?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In addition to the :guilabel:`Connect to Folder` function found under the Connect/Share button, |app| provides a ``User Defined`` device plugin that can be used to connect to any USB device that presents that shows up as a disk drive in your operating system. See the device plugin ``Preferences -> Plugins -> Device Plugins -> User Defined`` and ``Preferences -> Miscellaneous -> Get information to setup the user defined device`` for more information.
How does |app| manage collections on my SONY reader? How does |app| manage collections on my SONY reader?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -468,7 +475,7 @@ If it still wont launch, start a command prompt (press the windows key and R; th
Post any output you see in a help message on the `Forum <http://www.mobileread.com/forums/forumdisplay.php?f=166>`_. Post any output you see in a help message on the `Forum <http://www.mobileread.com/forums/forumdisplay.php?f=166>`_.
|app| freeze when I click on anything? |app| freezes when I click on anything?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are three possible things I know of, that can cause this: There are three possible things I know of, that can cause this:
@ -557,7 +564,7 @@ You have two choices:
How is |app| licensed? How is |app| licensed?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|app| is licensed under the GNU General Public License v3 (an open source license). This means that you are free to redistribute |app| as long as you make the source code available. So if you want to put |app| on a CD with your product, you must also put the |app| source code on the CD. The source code is available for download `from googlecode <http://code.google.com/p/calibre-ebook/downloads/list>`_. You are free to use the results of conversions from |app| however you want. You cannot use code, libraries from |app| in your software without maing your software open source. For details, see `The GNU GPL v3 <http://www.gnu.org/licenses/gpl.html>`_. |app| is licensed under the GNU General Public License v3 (an open source license). This means that you are free to redistribute |app| as long as you make the source code available. So if you want to put |app| on a CD with your product, you must also put the |app| source code on the CD. The source code is available for download `from googlecode <http://code.google.com/p/calibre-ebook/downloads/list>`_. You are free to use the results of conversions from |app| however you want. You cannot use code, libraries from |app| in your software without making your software open source. For details, see `The GNU GPL v3 <http://www.gnu.org/licenses/gpl.html>`_.
How do I run calibre from my USB stick? How do I run calibre from my USB stick?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -2905,4 +2905,4 @@ class BibTeX:
def bibtex_author_format(self, item): def bibtex_author_format(self, item):
#Format authors for Bibtex compliance (get a list as input) #Format authors for Bibtex compliance (get a list as input)
return self.utf8ToBibtex(u' and'.join([author for author in item])) return self.utf8ToBibtex(u' and '.join([author for author in item]))

View File

@ -68,7 +68,7 @@ def titlecase(text):
continue continue
match = MAC_MC.match(word) match = MAC_MC.match(word)
if match and not match.group(2).startswith('hin'): if match and not match.group(2)[:3] in ('hin', 'ht'):
line.append("%s%s" % (capitalize(match.group(1)), line.append("%s%s" % (capitalize(match.group(1)),
capitalize(match.group(2)))) capitalize(match.group(2))))
continue continue