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
ce9b91ef27
@ -105,7 +105,6 @@ function init_sort_combobox() {
|
||||
|
||||
// }}}
|
||||
|
||||
|
||||
function init() {
|
||||
$("#container").corner("30px");
|
||||
$("#header").corner("30px");
|
||||
|
@ -13,7 +13,8 @@ from calibre.devices.errors import UserFeedback
|
||||
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
||||
from calibre.devices.interface import DevicePlugin
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||
from calibre.ebooks.metadata import authors_to_string, MetaInformation
|
||||
from calibre.ebooks.metadata import authors_to_string, MetaInformation, \
|
||||
title_sort
|
||||
from calibre.ebooks.metadata.book.base import Metadata
|
||||
from calibre.ebooks.metadata.epub import set_metadata
|
||||
from calibre.library.server.utils import strftime
|
||||
@ -96,6 +97,9 @@ class ITUNES(DriverBase):
|
||||
|
||||
OPEN_FEEDBACK_MESSAGE = _(
|
||||
'Apple device detected, launching iTunes, please wait ...')
|
||||
BACKLOADING_ERROR_MESSAGE = _(
|
||||
"Cannot copy books directly from iDevice. "
|
||||
"Drag from iTunes Library to desktop, then add to calibre's Library window.")
|
||||
|
||||
# Product IDs:
|
||||
# 0x1291 iPod Touch
|
||||
@ -3128,6 +3132,9 @@ class Book(Metadata):
|
||||
See ebooks.metadata.book.base
|
||||
'''
|
||||
def __init__(self,title,author):
|
||||
|
||||
Metadata.__init__(self, title, authors=[author])
|
||||
|
||||
@property
|
||||
def title_sorter(self):
|
||||
return title_sort(self.title)
|
||||
|
||||
|
@ -39,9 +39,9 @@ class DevicePlugin(Plugin):
|
||||
#: Whether the metadata on books can be set via the GUI.
|
||||
CAN_SET_METADATA = ['title', 'authors', 'collections']
|
||||
|
||||
# Set this to True if the books on the device are files that the GUI can
|
||||
# Set this to None if the books on the device are files that the GUI can
|
||||
# access in order to add the books from the device to the library
|
||||
SUPPORTS_BACKLOADING = False
|
||||
BACKLOADING_ERROR_MESSAGE = _('Cannot get files from this device')
|
||||
|
||||
#: Path separator for paths to books on device
|
||||
path_sep = os.sep
|
||||
|
@ -6,6 +6,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, re, time, sys
|
||||
|
||||
from calibre.ebooks.metadata import title_sort
|
||||
from calibre.ebooks.metadata.book.base import Metadata
|
||||
from calibre.devices.mime import mime_type_ext
|
||||
from calibre.devices.interface import BookList as _BookList
|
||||
@ -54,7 +55,7 @@ class Book(Metadata):
|
||||
def title_sorter(self):
|
||||
doc = '''String to sort the title. If absent, title is returned'''
|
||||
def fget(self):
|
||||
return re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', self.title).rstrip()
|
||||
return title_sort(self.title)
|
||||
return property(doc=doc, fget=fget)
|
||||
|
||||
@dynamic_property
|
||||
|
@ -96,7 +96,7 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
|
||||
# USB disk-based devices can see the book files on the device, so can
|
||||
# copy these back to the library
|
||||
SUPPORTS_BACKLOADING = True
|
||||
BACKLOADING_ERROR_MESSAGE = None
|
||||
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||
detected_device=None):
|
||||
|
@ -235,6 +235,10 @@ class AddAction(InterfaceAction):
|
||||
self.gui.refresh_ondevice()
|
||||
|
||||
def add_books_from_device(self, view, paths=None):
|
||||
backloading_err = self.gui.device_manager.device.BACKLOADING_ERROR_MESSAGE
|
||||
if backloading_err is not None:
|
||||
return error_dialog(self.gui, _('Add to library'), backloading_err,
|
||||
show=True)
|
||||
if paths is None:
|
||||
rows = view.selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
|
@ -19,12 +19,7 @@ class AddToLibraryAction(InterfaceAction):
|
||||
self.qaction.triggered.connect(self.add_books_to_library)
|
||||
|
||||
def location_selected(self, loc):
|
||||
enabled = False
|
||||
if loc != 'library':
|
||||
if self.gui.device_manager.is_device_connected:
|
||||
device = self.gui.device_manager.connected_device
|
||||
if device is not None:
|
||||
enabled = getattr(device, 'SUPPORTS_BACKLOADING', False)
|
||||
enabled = loc != 'library'
|
||||
self.qaction.setEnabled(enabled)
|
||||
|
||||
def add_books_to_library(self, *args):
|
||||
|
@ -794,13 +794,16 @@ class DeviceMixin(object): # {{{
|
||||
mainlist, cardalist, cardblist = job.result
|
||||
self.memory_view.set_database(mainlist)
|
||||
self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA,
|
||||
self.device_manager.device.SUPPORTS_BACKLOADING)
|
||||
self.device_manager.device.BACKLOADING_ERROR_MESSAGE
|
||||
is None)
|
||||
self.card_a_view.set_database(cardalist)
|
||||
self.card_a_view.set_editable(self.device_manager.device.CAN_SET_METADATA,
|
||||
self.device_manager.device.SUPPORTS_BACKLOADING)
|
||||
self.device_manager.device.BACKLOADING_ERROR_MESSAGE
|
||||
is None)
|
||||
self.card_b_view.set_database(cardblist)
|
||||
self.card_b_view.set_editable(self.device_manager.device.CAN_SET_METADATA,
|
||||
self.device_manager.device.SUPPORTS_BACKLOADING)
|
||||
self.device_manager.device.BACKLOADING_ERROR_MESSAGE
|
||||
is None)
|
||||
self.sync_news()
|
||||
self.sync_catalogs()
|
||||
self.refresh_ondevice()
|
||||
|
@ -263,7 +263,7 @@
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>00</height>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@ -357,13 +357,13 @@ from the value in the box</string>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="change_title_to_title_case">
|
||||
<property name="text">
|
||||
<string>Change title to title case</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Force the title to be in title case. If both this and swap authors are checked,
|
||||
title and author are swapped before the title case is set</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Change title to title case</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
@ -486,15 +486,15 @@ Future conversion of these books will use the default settings.</string>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="HistoryLineEdit" name="search_for">
|
||||
<property name="toolTip">
|
||||
<string>Enter the what you are looking for, either plain text or a regular expression, depending on the mode</string>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>100</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enter the what you are looking for, either plain text or a regular expression, depending on the mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
@ -656,6 +656,14 @@ nothing should be put between the original text and the inserted text</string>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="gridLayoutWidget_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>122</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="testgrid">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_31">
|
||||
@ -733,14 +741,33 @@ nothing should be put between the original text and the inserted text</string>
|
||||
<tabstop>author_sort</tabstop>
|
||||
<tabstop>rating</tabstop>
|
||||
<tabstop>publisher</tabstop>
|
||||
<tabstop>tag_editor_button</tabstop>
|
||||
<tabstop>tags</tabstop>
|
||||
<tabstop>tag_editor_button</tabstop>
|
||||
<tabstop>remove_tags</tabstop>
|
||||
<tabstop>remove_all_tags</tabstop>
|
||||
<tabstop>series</tabstop>
|
||||
<tabstop>clear_series</tabstop>
|
||||
<tabstop>autonumber_series</tabstop>
|
||||
<tabstop>series_numbering_restarts</tabstop>
|
||||
<tabstop>series_start_number</tabstop>
|
||||
<tabstop>remove_format</tabstop>
|
||||
<tabstop>remove_conversion_settings</tabstop>
|
||||
<tabstop>swap_title_and_author</tabstop>
|
||||
<tabstop>change_title_to_title_case</tabstop>
|
||||
<tabstop>button_box</tabstop>
|
||||
<tabstop>central_widget</tabstop>
|
||||
<tabstop>search_field</tabstop>
|
||||
<tabstop>search_mode</tabstop>
|
||||
<tabstop>search_for</tabstop>
|
||||
<tabstop>case_sensitive</tabstop>
|
||||
<tabstop>replace_with</tabstop>
|
||||
<tabstop>replace_func</tabstop>
|
||||
<tabstop>destination_field</tabstop>
|
||||
<tabstop>replace_mode</tabstop>
|
||||
<tabstop>comma_separated</tabstop>
|
||||
<tabstop>scrollArea11</tabstop>
|
||||
<tabstop>test_text</tabstop>
|
||||
<tabstop>test_result</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../../resources/images.qrc"/>
|
||||
|
@ -11,6 +11,7 @@ This module implements a simple commandline SMTP client that supports:
|
||||
|
||||
import sys, traceback, os
|
||||
from email import encoders
|
||||
from calibre import isbytestring
|
||||
|
||||
def create_mail(from_, to, subject, text=None, attachment_data=None,
|
||||
attachment_type=None, attachment_name=None):
|
||||
@ -26,7 +27,10 @@ def create_mail(from_, to, subject, text=None, attachment_data=None,
|
||||
|
||||
if text is not None:
|
||||
from email.mime.text import MIMEText
|
||||
msg = MIMEText(text)
|
||||
if isbytestring(text):
|
||||
msg = MIMEText(text)
|
||||
else:
|
||||
msg = MIMEText(text, 'plain', 'utf-8')
|
||||
outer.attach(msg)
|
||||
|
||||
if attachment_data is not None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user