mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
c7c5a3700b
@ -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
|
||||
|
||||
|
@ -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')]
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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:
|
||||
|
0
src/calibre/devices/user_defined/__init__.py
Normal file
0
src/calibre/devices/user_defined/__init__.py
Normal file
110
src/calibre/devices/user_defined/driver.py
Normal file
110
src/calibre/devices/user_defined/driver.py
Normal 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)
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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">
|
||||
|
105
src/calibre/gui2/preferences/device_user_defined.py
Normal file
105
src/calibre/gui2/preferences/device_user_defined.py
Normal 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_()
|
@ -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)
|
||||
|
@ -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 &user defined device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
@ -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' :
|
||||
|
@ -102,6 +102,8 @@ 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.
|
||||
|
||||
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?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -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]))
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user