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
d2ad85e45d
@ -54,10 +54,10 @@ class NewYorker(BasicNewsRecipe):
|
|||||||
,dict(attrs={'id':['show-header','show-footer'] })
|
,dict(attrs={'id':['show-header','show-footer'] })
|
||||||
]
|
]
|
||||||
remove_attributes = ['lang']
|
remove_attributes = ['lang']
|
||||||
feeds = [(u'The New Yorker', u'http://www.newyorker.com/services/rss/feeds/everything.xml')]
|
feeds = [(u'The New Yorker', u'http://www.newyorker.com/services/mrss/feeds/everything.xml')]
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
return 'http://www.newyorker.com' + url + '?printable=true'
|
return url + '?printable=true'
|
||||||
|
|
||||||
def image_url_processor(self, baseurl, url):
|
def image_url_processor(self, baseurl, url):
|
||||||
return url.strip()
|
return url.strip()
|
||||||
|
@ -19,10 +19,15 @@ class ANDROID(USBMS):
|
|||||||
|
|
||||||
VENDOR_ID = {
|
VENDOR_ID = {
|
||||||
# HTC
|
# HTC
|
||||||
0x0bb4 : { 0x0c02 : [0x100, 0x0227, 0x0226], 0x0c01 : [0x100,
|
0x0bb4 : { 0x0c02 : [0x100, 0x0227, 0x0226],
|
||||||
0x0227, 0x0226], 0x0ff9
|
0x0c01 : [0x100, 0x0227, 0x0226],
|
||||||
: [0x0100, 0x0227, 0x0226], 0x0c87: [0x0100, 0x0227, 0x0226],
|
0x0ff9 : [0x0100, 0x0227, 0x0226],
|
||||||
0xc92 : [0x100], 0xc97: [0x226], 0xc99 : [0x0100]},
|
0x0c87 : [0x0100, 0x0227, 0x0226],
|
||||||
|
0xc92 : [0x100],
|
||||||
|
0xc97 : [0x226],
|
||||||
|
0xc99 : [0x0100],
|
||||||
|
0xca3 : [0x100],
|
||||||
|
},
|
||||||
|
|
||||||
# Eken
|
# Eken
|
||||||
0x040d : { 0x8510 : [0x0001], 0x0851 : [0x1] },
|
0x040d : { 0x8510 : [0x0001], 0x0851 : [0x1] },
|
||||||
|
@ -172,10 +172,10 @@ class INVESBOOK(EB600):
|
|||||||
gui_name = 'Inves Book 600'
|
gui_name = 'Inves Book 600'
|
||||||
|
|
||||||
FORMATS = ['epub', 'mobi', 'prc', 'fb2', 'html', 'pdf', 'rtf', 'txt']
|
FORMATS = ['epub', 'mobi', 'prc', 'fb2', 'html', 'pdf', 'rtf', 'txt']
|
||||||
|
BCD = [0x110, 0x323]
|
||||||
|
|
||||||
VENDOR_NAME = 'INVES_E6'
|
VENDOR_NAME = ['INVES_E6', 'INVES-WI']
|
||||||
WINDOWS_MAIN_MEM = '00INVES_E600'
|
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['00INVES_E600', 'INVES-WIBOOK']
|
||||||
WINDOWS_CARD_A_MEM = '00INVES_E600'
|
|
||||||
|
|
||||||
class BOOQ(EB600):
|
class BOOQ(EB600):
|
||||||
name = 'Booq Device Interface'
|
name = 'Booq Device Interface'
|
||||||
|
@ -50,6 +50,7 @@ gprefs.defaults['action-layout-context-menu-device'] = (
|
|||||||
|
|
||||||
gprefs.defaults['show_splash_screen'] = True
|
gprefs.defaults['show_splash_screen'] = True
|
||||||
gprefs.defaults['toolbar_icon_size'] = 'medium'
|
gprefs.defaults['toolbar_icon_size'] = 'medium'
|
||||||
|
gprefs.defaults['automerge'] = 'ignore'
|
||||||
gprefs.defaults['toolbar_text'] = 'auto'
|
gprefs.defaults['toolbar_text'] = 'auto'
|
||||||
gprefs.defaults['show_child_bar'] = False
|
gprefs.defaults['show_child_bar'] = False
|
||||||
gprefs.defaults['font'] = None
|
gprefs.defaults['font'] = None
|
||||||
|
@ -244,8 +244,8 @@ class AddAction(InterfaceAction):
|
|||||||
x.decode(preferred_encoding, 'replace') for x in
|
x.decode(preferred_encoding, 'replace') for x in
|
||||||
self._adder.merged_books])
|
self._adder.merged_books])
|
||||||
info_dialog(self.gui, _('Merged some books'),
|
info_dialog(self.gui, _('Merged some books'),
|
||||||
_('Some duplicates were found and merged into the '
|
_('The following duplicate books were found and incoming book formats were '
|
||||||
'following existing books:'), det_msg=books, show=True)
|
'processed and merged into your Calibre database according to your automerge settings:'), det_msg=books, show=True)
|
||||||
if getattr(self._adder, 'critical', None):
|
if getattr(self._adder, 'critical', None):
|
||||||
det_msg = []
|
det_msg = []
|
||||||
for name, log in self._adder.critical.items():
|
for name, log in self._adder.critical.items():
|
||||||
|
@ -8,7 +8,7 @@ from functools import partial
|
|||||||
from PyQt4.Qt import QThread, QObject, Qt, QProgressDialog, pyqtSignal, QTimer
|
from PyQt4.Qt import QThread, QObject, Qt, QProgressDialog, pyqtSignal, QTimer
|
||||||
|
|
||||||
from calibre.gui2.dialogs.progress import ProgressDialog
|
from calibre.gui2.dialogs.progress import ProgressDialog
|
||||||
from calibre.gui2 import question_dialog, error_dialog, info_dialog
|
from calibre.gui2 import question_dialog, error_dialog, info_dialog, gprefs
|
||||||
from calibre.ebooks.metadata.opf2 import OPF
|
from calibre.ebooks.metadata.opf2 import OPF
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
from calibre.constants import preferred_encoding, filesystem_encoding, DEBUG
|
from calibre.constants import preferred_encoding, filesystem_encoding, DEBUG
|
||||||
@ -179,23 +179,46 @@ class DBAdder(QObject): # {{{
|
|||||||
cover = f.read()
|
cover = f.read()
|
||||||
orig_formats = formats
|
orig_formats = formats
|
||||||
formats = [f for f in formats if not f.lower().endswith('.opf')]
|
formats = [f for f in formats if not f.lower().endswith('.opf')]
|
||||||
if prefs['add_formats_to_existing']:
|
if prefs['add_formats_to_existing']: #automerge is on
|
||||||
identical_book_list = self.db.find_identical_books(mi)
|
identical_book_list = self.db.find_identical_books(mi)
|
||||||
|
|
||||||
if identical_book_list: # books with same author and nearly same title exist in db
|
if identical_book_list: # books with same author and nearly same title exist in db
|
||||||
self.merged_books.add(mi.title)
|
self.merged_books.add(mi.title)
|
||||||
|
a_new_record_has_been_created = False
|
||||||
for identical_book in identical_book_list:
|
for identical_book in identical_book_list:
|
||||||
|
if gprefs['automerge'] == 'ignore':
|
||||||
self.add_formats(identical_book, formats, replace=False)
|
self.add_formats(identical_book, formats, replace=False)
|
||||||
else:
|
if gprefs['automerge'] == 'overwrite':
|
||||||
id = self.db.create_book_entry(mi, cover=cover, add_duplicates=True)
|
self.add_formats(identical_book, formats, replace=True)
|
||||||
|
if gprefs['automerge'] == 'new record' and not a_new_record_has_been_created:
|
||||||
|
'''
|
||||||
|
We are here because we have at least one book record in the db that matches the one file/format being processed
|
||||||
|
We need to check if the file/format being processed matches a format in the matching book record.
|
||||||
|
If so, create new record (as below), else, add to existing record, as above.
|
||||||
|
Test if format exists in matching record. identical_book is an id, formats is a FQPN path in a list
|
||||||
|
'''
|
||||||
|
for path in formats:
|
||||||
|
fmt = os.path.splitext(path)[-1].replace('.', '').upper()
|
||||||
|
ib_fmts = self.db.formats(identical_book, index_is_id=True)
|
||||||
|
if ib_fmts and fmt in ib_fmts: # Create a new record
|
||||||
|
if not a_new_record_has_been_created:
|
||||||
|
id_ = self.db.create_book_entry(mi, cover=cover, add_duplicates=True)
|
||||||
self.number_of_books_added += 1
|
self.number_of_books_added += 1
|
||||||
self.add_formats(id, formats)
|
self.add_formats(id_, formats)
|
||||||
else:
|
a_new_record_has_been_created = True
|
||||||
id = self.db.create_book_entry(mi, cover=cover, add_duplicates=False)
|
else: #new record not required
|
||||||
if id is None:
|
self.add_formats(identical_book, formats, replace=False)
|
||||||
|
|
||||||
|
else: # books with same author and nearly same title do not exist in db
|
||||||
|
id_ = self.db.create_book_entry(mi, cover=cover, add_duplicates=True)
|
||||||
|
self.number_of_books_added += 1
|
||||||
|
self.add_formats(id_, formats)
|
||||||
|
|
||||||
|
else: #automerge is off
|
||||||
|
id_ = self.db.create_book_entry(mi, cover=cover, add_duplicates=False)
|
||||||
|
if id_ is None:
|
||||||
self.duplicates.append((mi, cover, orig_formats))
|
self.duplicates.append((mi, cover, orig_formats))
|
||||||
else:
|
else:
|
||||||
self.add_formats(id, formats)
|
self.add_formats(id_, formats)
|
||||||
self.number_of_books_added += 1
|
self.number_of_books_added += 1
|
||||||
else:
|
else:
|
||||||
self.names.append(name)
|
self.names.append(name)
|
||||||
|
@ -57,7 +57,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
self.setWindowIcon(icon)
|
self.setWindowIcon(icon)
|
||||||
|
|
||||||
self.to_rename = {}
|
self.to_rename = {}
|
||||||
self.to_delete = set()
|
self.to_delete = set([])
|
||||||
self.all_tags = {}
|
self.all_tags = {}
|
||||||
|
|
||||||
for k,v in data:
|
for k,v in data:
|
||||||
@ -65,7 +65,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
for tag in sorted(self.all_tags.keys(), key=key):
|
for tag in sorted(self.all_tags.keys(), key=key):
|
||||||
item = ListWidgetItem(tag)
|
item = ListWidgetItem(tag)
|
||||||
item.setData(Qt.UserRole, self.all_tags[tag])
|
item.setData(Qt.UserRole, self.all_tags[tag])
|
||||||
item.setFlags (item.flags() | Qt.ItemIsEditable);
|
item.setFlags (item.flags() | Qt.ItemIsEditable)
|
||||||
self.available_tags.addItem(item)
|
self.available_tags.addItem(item)
|
||||||
|
|
||||||
if tag_to_match is not None:
|
if tag_to_match is not None:
|
||||||
|
@ -12,6 +12,7 @@ from calibre.gui2.preferences import ConfigWidgetBase, test_widget, \
|
|||||||
from calibre.gui2.preferences.adding_ui import Ui_Form
|
from calibre.gui2.preferences.adding_ui import Ui_Form
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.gui2.widgets import FilenamePattern
|
from calibre.gui2.widgets import FilenamePattern
|
||||||
|
from calibre.gui2 import gprefs
|
||||||
|
|
||||||
class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||||
|
|
||||||
@ -23,18 +24,23 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('read_file_metadata', prefs)
|
r('read_file_metadata', prefs)
|
||||||
r('swap_author_names', prefs)
|
r('swap_author_names', prefs)
|
||||||
r('add_formats_to_existing', prefs)
|
r('add_formats_to_existing', prefs)
|
||||||
|
choices = [
|
||||||
|
(_('Ignore duplicate incoming formats'), 'ignore'),
|
||||||
|
(_('Overwrite existing duplicate formats'), 'overwrite'),
|
||||||
|
(_('Create new record for each duplicate format'), 'new record')]
|
||||||
|
r('automerge', gprefs, choices=choices)
|
||||||
r('new_book_tags', prefs, setting=CommaSeparatedList)
|
r('new_book_tags', prefs, setting=CommaSeparatedList)
|
||||||
|
|
||||||
self.filename_pattern = FilenamePattern(self)
|
self.filename_pattern = FilenamePattern(self)
|
||||||
self.metadata_box.layout().insertWidget(0, self.filename_pattern)
|
self.metadata_box.layout().insertWidget(0, self.filename_pattern)
|
||||||
self.filename_pattern.changed_signal.connect(self.changed_signal.emit)
|
self.filename_pattern.changed_signal.connect(self.changed_signal.emit)
|
||||||
|
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
ConfigWidgetBase.initialize(self)
|
ConfigWidgetBase.initialize(self)
|
||||||
self.filename_pattern.blockSignals(True)
|
self.filename_pattern.blockSignals(True)
|
||||||
self.filename_pattern.initialize()
|
self.filename_pattern.initialize()
|
||||||
self.filename_pattern.blockSignals(False)
|
self.filename_pattern.blockSignals(False)
|
||||||
|
self.opt_automerge.setEnabled(self.opt_add_formats_to_existing.isChecked())
|
||||||
|
|
||||||
def restore_defaults(self):
|
def restore_defaults(self):
|
||||||
ConfigWidgetBase.restore_defaults(self)
|
ConfigWidgetBase.restore_defaults(self)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>750</width>
|
<width>753</width>
|
||||||
<height>339</height>
|
<height>339</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -58,16 +58,33 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="2" column="0">
|
||||||
<widget class="QCheckBox" name="opt_add_formats_to_existing">
|
<widget class="QCheckBox" name="opt_add_formats_to_existing">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>If an existing book with a similar title and author is found that does not have the format being added, the format is added
|
<string>Automerge: If books with similar titles and authors found, merge the incoming formats automatically into
|
||||||
to the existing book, instead of creating a new entry. If the existing book already has the format, then it is silently ignored.
|
existing book records. The box to the right controls what happens when an existing record already has
|
||||||
|
the incoming format. Note that this option also affects the Copy to library action.
|
||||||
|
|
||||||
Title match ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc. Author match is exact.</string>
|
Title match ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc. Author match is exact.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>If books with similar titles and authors found, &merge the new files automatically</string>
|
<string>&Automerge added books if they already exist in the calibre library:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="opt_automerge">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Automerge: If books with similar titles and authors found, merge the incoming formats automatically into
|
||||||
|
existing book records. This box controls what happens when an existing record already has
|
||||||
|
the incoming format:
|
||||||
|
|
||||||
|
Ignore duplicate incoming files - means that existing files in your calibre library will not be replaced
|
||||||
|
Overwrite existing duplicate files - means that existing files in your calibre library will be replaced
|
||||||
|
Create new record for each duplicate file - means that a new book entry will be created for each duplicate file
|
||||||
|
|
||||||
|
Title matching ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc.
|
||||||
|
Author matching is exact.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -113,5 +130,22 @@ Title match ignores leading indefinite articles ("the", "a",
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>opt_add_formats_to_existing</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>opt_automerge</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>406</x>
|
||||||
|
<y>83</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>457</x>
|
||||||
|
<y>83</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -124,7 +124,6 @@ class ContentServer(object):
|
|||||||
cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \
|
cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \
|
||||||
ua.startswith('Stanza')
|
ua.startswith('Stanza')
|
||||||
|
|
||||||
# A better search would be great
|
|
||||||
want_mobile = self.is_mobile_browser(ua)
|
want_mobile = self.is_mobile_browser(ua)
|
||||||
if self.opts.develop and not want_mobile:
|
if self.opts.develop and not want_mobile:
|
||||||
cherrypy.log('User agent: '+ua)
|
cherrypy.log('User agent: '+ua)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user