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'
__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 '''
import re
import string
@ -13,8 +14,8 @@ from calibre.web.feeds.recipes import BasicNewsRecipe
class BrandEins(BasicNewsRecipe):
title = u'brand eins'
__author__ = 'Constantin Hofstetter; Steffen Siebert'
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.'
__author__ = 'Constantin Hofstetter'
description = u'Wirtschaftsmagazin'
publisher ='brandeins.de'
category = 'politics, business, wirtschaft, Germany'
use_embedded_content = False
@ -105,10 +106,11 @@ class BrandEins(BasicNewsRecipe):
keys = issue_map.keys()
keys.sort()
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)
# 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://www.brandeins.de/archiv/magazin/tierisch.html"
@ -161,3 +163,4 @@ class BrandEins(BasicNewsRecipe):
current_articles.append({'title': title, 'url': url, 'description': description, 'date':''})
titles_and_articles.append([chapter_title, current_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.nook.driver import NOOK, NOOK_COLOR
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.nokia.driver import N770, N810, E71X, E52
from calibre.devices.eslick.driver import ESLICK, EBK52
@ -742,6 +743,7 @@ plugins += [
EEEREADER,
NEXTBOOK,
ITUNES,
USER_DEFINED,
]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataReader')]

View File

@ -19,6 +19,7 @@ from calibre.utils.config import (make_config_dir, Config, ConfigProxy,
plugin_dir, OptionParser)
from calibre.ebooks.epub.fix import ePubFixer
from calibre.ebooks.metadata.sources.base import Source
from calibre.constants import DEBUG
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)
_initialized_plugins.append(plugin)
except:
print 'Failed to initialize plugin...'
traceback.print_exc()
print 'Failed to initialize plugin:', repr(zfp)
if DEBUG:
traceback.print_exc()
_initialized_plugins.sort(cmp=lambda x,y:cmp(x.priority, y.priority), reverse=True)
reread_filetype_plugins()
reread_metadata_plugins()

View File

@ -156,3 +156,60 @@ def debug(ioreg_to_tmp=False, buf=None):
sys.stdout = oldo
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]},
# Dell
0x413c : { 0xb007 : [0x0100, 0x0224]},
0x413c : { 0xb007 : [0x0100, 0x0224, 0x0226]},
# LG
0x1004 : { 0x61cc : [0x100], 0x61ce : [0x100], 0x618e : [0x226] },
@ -112,7 +112,7 @@ class ANDROID(USBMS):
'MB860', 'MULTI-CARD', 'MID7015A', 'INCREDIBLE', 'A7EB']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
'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'

View File

@ -94,6 +94,9 @@ class DeviceConfig(object):
if isinstance(cls.EXTRA_CUSTOMIZATION_MESSAGE, list):
ec = []
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'):
ec.append(config_widget.opt_extra_customization[i].isChecked())
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 }
.underline { text-decoration: underline }
.mbp_pagebreak {
page-break-after: always; margin: 0; display: block
}
@ -601,6 +603,9 @@ class MobiReader(object):
elif tag.tag == 'i':
tag.tag = 'span'
tag.attrib['class'] = 'italic'
elif tag.tag == 'u':
tag.tag = 'span'
tag.attrib['class'] = 'underline'
elif tag.tag == 'b':
tag.tag = 'span'
tag.attrib['class'] = 'bold'

View File

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

View File

@ -60,7 +60,7 @@ class ViewAction(InterfaceAction):
def build_menus(self, db):
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.addSeparator()
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):
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):
label_text, tt = parse_msg(m)
if not label_text:
self.opt_extra_customization.append(None)
continue
if isinstance(settings.extra_customization[i], bool):
self.opt_extra_customization.append(QCheckBox(label_text))
self.opt_extra_customization[-1].setToolTip(tt)
@ -75,8 +85,9 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
l.setBuddy(self.opt_extra_customization[i])
l.setWordWrap(True)
self.opt_extra_customization[i].setText(settings.extra_customization[i])
self.extra_layout.addWidget(l)
self.extra_layout.addWidget(self.opt_extra_customization[i])
self.extra_layout.addWidget(l, row_func(i, 0), col_func(i))
self.extra_layout.addWidget(self.opt_extra_customization[i],
row_func(i, 1), col_func(i))
else:
self.opt_extra_customization = QLineEdit()
label_text, tt = parse_msg(extra_customization_message)
@ -86,8 +97,8 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
l.setWordWrap(True)
if settings.extra_customization:
self.opt_extra_customization.setText(settings.extra_customization)
self.extra_layout.addWidget(l)
self.extra_layout.addWidget(self.opt_extra_customization)
self.extra_layout.addWidget(l, 0, 0)
self.extra_layout.addWidget(self.opt_extra_customization, 1, 0)
self.opt_save_template.setText(settings.save_template)

View File

@ -101,7 +101,7 @@
</widget>
</item>
<item row="6" column="0">
<layout class="QVBoxLayout" name="extra_layout"/>
<layout class="QGridLayout" name="extra_layout"/>
</item>
<item row="4" column="0">
<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)
self.device_detection_button.clicked.connect(self.debug_device_detection)
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.setVisible(isosx)
@ -38,6 +39,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
d = DebugDevice(self)
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):
from calibre.utils.config import config_dir
open_local_file(config_dir)

View File

@ -58,7 +58,14 @@
</property>
</widget>
</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">
<property name="orientation">
<enum>Qt::Vertical</enum>

View File

@ -8,6 +8,7 @@ from collections import namedtuple
from copy import deepcopy
from xml.sax.saxutils import escape
from lxml import etree
from types import StringType, UnicodeType
from calibre import prints, prepare_string_for_xml, strftime
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.ebooks.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, Tag, NavigableString
from calibre.ebooks.chardet import substitute_entites
from calibre.library.save_to_disk import preprocess_template
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.utils.bibtex import BibTeX
from calibre.utils.config import config_dir
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.logging import default_log as log
from calibre.utils.zipfile import ZipFile, ZipInfo
from calibre.utils.magick.draw import thumbnail
from calibre.utils.zipfile import ZipFile, ZipInfo
FIELDS = ['all', 'title', 'author_sort', 'authors', 'comments',
'cover', 'formats','id', 'isbn', 'ondevice', 'pubdate', 'publisher',
@ -303,12 +307,6 @@ class BIBTEX(CatalogPlugin): # {{{
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,
bibtexdict, citation_bibtex=True, calibre_files=True):
@ -365,6 +363,11 @@ class BIBTEX(CatalogPlugin): # {{{
#\n removal
item = item.replace(u'\r\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))
elif field == 'isbn' :

View File

@ -100,7 +100,9 @@ Device Integration
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|?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -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.
* 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?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -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>`_.
|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:
@ -557,7 +564,7 @@ You have two choices:
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?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -2905,4 +2905,4 @@ class BibTeX:
def bibtex_author_format(self, item):
#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
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)),
capitalize(match.group(2))))
continue