mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Auto adding: When automatically adding files from a folder, automatically convert the files to the current output format after adding. This can be turned off via Preferences->Adding Books->Automatic Adding. Fixes #969053 ([Req] Auto-Convert to mobi after Auto-Add)
This commit is contained in:
parent
cdbef8d6b0
commit
207a18c7a5
@ -105,6 +105,7 @@ gprefs.defaults['show_files_after_save'] = True
|
|||||||
gprefs.defaults['auto_add_path'] = None
|
gprefs.defaults['auto_add_path'] = None
|
||||||
gprefs.defaults['auto_add_check_for_duplicates'] = False
|
gprefs.defaults['auto_add_check_for_duplicates'] = False
|
||||||
gprefs.defaults['blocked_auto_formats'] = []
|
gprefs.defaults['blocked_auto_formats'] = []
|
||||||
|
gprefs.defaults['auto_add_auto_convert'] = True
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
NONE = QVariant() #: Null value to return from the data function of item models
|
NONE = QVariant() #: Null value to return from the data function of item models
|
||||||
|
@ -53,6 +53,24 @@ class ConvertAction(InterfaceAction):
|
|||||||
self.queue_convert_jobs(jobs, changed, bad, rows, previous,
|
self.queue_convert_jobs(jobs, changed, bad, rows, previous,
|
||||||
self.book_auto_converted, extra_job_args=[on_card])
|
self.book_auto_converted, extra_job_args=[on_card])
|
||||||
|
|
||||||
|
def auto_convert_auto_add(self, book_ids):
|
||||||
|
previous = self.gui.library_view.currentIndex()
|
||||||
|
db = self.gui.current_db
|
||||||
|
needed = set()
|
||||||
|
of = prefs['output_format'].lower()
|
||||||
|
for book_id in book_ids:
|
||||||
|
fmts = db.formats(book_id, index_is_id=True)
|
||||||
|
fmts = set(x.lower() for x in fmts.split(',')) if fmts else set()
|
||||||
|
if of not in fmts:
|
||||||
|
needed.add(book_id)
|
||||||
|
if needed:
|
||||||
|
jobs, changed, bad = convert_single_ebook(self.gui,
|
||||||
|
self.gui.library_view.model().db, needed, True, of,
|
||||||
|
show_no_format_warning=False)
|
||||||
|
if not jobs: return
|
||||||
|
self.queue_convert_jobs(jobs, changed, bad, list(needed), previous,
|
||||||
|
self.book_converted, rows_are_ids=True)
|
||||||
|
|
||||||
def auto_convert_mail(self, to, fmts, delete_from_library, book_ids, format, subject):
|
def auto_convert_mail(self, to, fmts, delete_from_library, book_ids, format, subject):
|
||||||
previous = self.gui.library_view.currentIndex()
|
previous = self.gui.library_view.currentIndex()
|
||||||
rows = [x.row() for x in \
|
rows = [x.row() for x in \
|
||||||
@ -118,7 +136,7 @@ class ConvertAction(InterfaceAction):
|
|||||||
num, 2000)
|
num, 2000)
|
||||||
|
|
||||||
def queue_convert_jobs(self, jobs, changed, bad, rows, previous,
|
def queue_convert_jobs(self, jobs, changed, bad, rows, previous,
|
||||||
converted_func, extra_job_args=[]):
|
converted_func, extra_job_args=[], rows_are_ids=False):
|
||||||
for func, args, desc, fmt, id, temp_files in jobs:
|
for func, args, desc, fmt, id, temp_files in jobs:
|
||||||
func, _, same_fmt = func.partition(':')
|
func, _, same_fmt = func.partition(':')
|
||||||
same_fmt = same_fmt == 'same_fmt'
|
same_fmt = same_fmt == 'same_fmt'
|
||||||
@ -140,7 +158,11 @@ class ConvertAction(InterfaceAction):
|
|||||||
self.conversion_jobs[job] = tuple(args)
|
self.conversion_jobs[job] = tuple(args)
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
self.gui.library_view.model().refresh_rows(rows)
|
m = self.gui.library_view.model()
|
||||||
|
if rows_are_ids:
|
||||||
|
m.refresh_ids(rows)
|
||||||
|
else:
|
||||||
|
m.refresh_rows(rows)
|
||||||
current = self.gui.library_view.currentIndex()
|
current = self.gui.library_view.currentIndex()
|
||||||
self.gui.library_view.model().current_changed(current, previous)
|
self.gui.library_view.model().current_changed(current, previous)
|
||||||
|
|
||||||
|
@ -113,6 +113,7 @@ class Worker(Thread):
|
|||||||
class AutoAdder(QObject):
|
class AutoAdder(QObject):
|
||||||
|
|
||||||
metadata_read = pyqtSignal(object)
|
metadata_read = pyqtSignal(object)
|
||||||
|
auto_convert = pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self, path, parent):
|
def __init__(self, path, parent):
|
||||||
QObject.__init__(self, parent)
|
QObject.__init__(self, parent)
|
||||||
@ -124,6 +125,8 @@ class AutoAdder(QObject):
|
|||||||
self.metadata_read.connect(self.add_to_db,
|
self.metadata_read.connect(self.add_to_db,
|
||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
QTimer.singleShot(2000, self.initialize)
|
QTimer.singleShot(2000, self.initialize)
|
||||||
|
self.auto_convert.connect(self.do_auto_convert,
|
||||||
|
type=Qt.QueuedConnection)
|
||||||
elif path:
|
elif path:
|
||||||
prints(path,
|
prints(path,
|
||||||
'is not a valid directory to watch for new ebooks, ignoring')
|
'is not a valid directory to watch for new ebooks, ignoring')
|
||||||
@ -163,6 +166,7 @@ class AutoAdder(QObject):
|
|||||||
|
|
||||||
needs_rescan = False
|
needs_rescan = False
|
||||||
duplicates = []
|
duplicates = []
|
||||||
|
added_ids = set()
|
||||||
|
|
||||||
for fname, tdir in data.iteritems():
|
for fname, tdir in data.iteritems():
|
||||||
paths = [os.path.join(self.worker.path, fname)]
|
paths = [os.path.join(self.worker.path, fname)]
|
||||||
@ -187,9 +191,12 @@ class AutoAdder(QObject):
|
|||||||
continue
|
continue
|
||||||
mi = [OPF(open(mi, 'rb'), tdir,
|
mi = [OPF(open(mi, 'rb'), tdir,
|
||||||
populate_spine=False).to_book_metadata()]
|
populate_spine=False).to_book_metadata()]
|
||||||
dups, num = m.add_books(paths,
|
dups, ids = m.add_books(paths,
|
||||||
[os.path.splitext(fname)[1][1:].upper()], mi,
|
[os.path.splitext(fname)[1][1:].upper()], mi,
|
||||||
add_duplicates=not gprefs['auto_add_check_for_duplicates'])
|
add_duplicates=not gprefs['auto_add_check_for_duplicates'],
|
||||||
|
return_ids=True)
|
||||||
|
added_ids |= set(ids)
|
||||||
|
num = len(ids)
|
||||||
if dups:
|
if dups:
|
||||||
path = dups[0][0]
|
path = dups[0][0]
|
||||||
with open(os.path.join(tdir, 'dup_cache.'+dups[1][0].lower()),
|
with open(os.path.join(tdir, 'dup_cache.'+dups[1][0].lower()),
|
||||||
@ -217,8 +224,10 @@ class AutoAdder(QObject):
|
|||||||
_('Books with the same title as the following already '
|
_('Books with the same title as the following already '
|
||||||
'exist in the database. Add them anyway?'),
|
'exist in the database. Add them anyway?'),
|
||||||
'\n'.join(files)):
|
'\n'.join(files)):
|
||||||
dups, num = m.add_books(paths, formats, metadata,
|
dups, ids = m.add_books(paths, formats, metadata,
|
||||||
add_duplicates=True)
|
add_duplicates=True, return_ids=True)
|
||||||
|
added_ids |= set(ids)
|
||||||
|
num = len(ids)
|
||||||
count += num
|
count += num
|
||||||
|
|
||||||
for tdir in data.itervalues():
|
for tdir in data.itervalues():
|
||||||
@ -227,6 +236,9 @@ class AutoAdder(QObject):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if added_ids and gprefs['auto_add_auto_convert']:
|
||||||
|
self.auto_convert.emit(added_ids)
|
||||||
|
|
||||||
if count > 0:
|
if count > 0:
|
||||||
m.books_added(count)
|
m.books_added(count)
|
||||||
gui.status_bar.show_message(_(
|
gui.status_bar.show_message(_(
|
||||||
@ -238,4 +250,7 @@ class AutoAdder(QObject):
|
|||||||
if needs_rescan:
|
if needs_rescan:
|
||||||
QTimer.singleShot(2000, self.dir_changed)
|
QTimer.singleShot(2000, self.dir_changed)
|
||||||
|
|
||||||
|
def do_auto_convert(self, added_ids):
|
||||||
|
gui = self.parent()
|
||||||
|
gui.iactions['Convert Books'].auto_convert_auto_add(added_ids)
|
||||||
|
|
||||||
|
@ -187,9 +187,10 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
self.db = None
|
self.db = None
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def add_books(self, paths, formats, metadata, add_duplicates=False):
|
def add_books(self, paths, formats, metadata, add_duplicates=False,
|
||||||
|
return_ids=False):
|
||||||
ret = self.db.add_books(paths, formats, metadata,
|
ret = self.db.add_books(paths, formats, metadata,
|
||||||
add_duplicates=add_duplicates)
|
add_duplicates=add_duplicates, return_ids=return_ids)
|
||||||
self.count_changed()
|
self.count_changed()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('new_book_tags', prefs, setting=CommaSeparatedList)
|
r('new_book_tags', prefs, setting=CommaSeparatedList)
|
||||||
r('auto_add_path', gprefs, restart_required=True)
|
r('auto_add_path', gprefs, restart_required=True)
|
||||||
r('auto_add_check_for_duplicates', gprefs)
|
r('auto_add_check_for_duplicates', gprefs)
|
||||||
|
r('auto_add_auto_convert', gprefs)
|
||||||
|
|
||||||
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)
|
||||||
|
@ -151,6 +151,19 @@ Author matching is exact.</string>
|
|||||||
<string>&Automatic Adding</string>
|
<string>&Automatic Adding</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_auto_add_check_for_duplicates">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>If set, this option will causes calibre to check if a file
|
||||||
|
being auto-added is already in the calibre library.
|
||||||
|
If it is, a meesage will pop up asking you whether
|
||||||
|
you want to add it anyway.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for &duplicates when auto-adding files</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -168,7 +181,7 @@ Author matching is exact.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Ignore files with the following extensions when automatically adding </string>
|
<string>Ignore files with the following extensions when automatically adding </string>
|
||||||
@ -187,7 +200,7 @@ Author matching is exact.</string>
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="5" column="1">
|
||||||
<spacer name="horizontalSpacer_2">
|
<spacer name="horizontalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
@ -225,16 +238,10 @@ Author matching is exact.</string>
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="2">
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="opt_auto_add_check_for_duplicates">
|
<widget class="QCheckBox" name="opt_auto_add_auto_convert">
|
||||||
<property name="toolTip">
|
|
||||||
<string>If set, this option will causes calibre to check if a file
|
|
||||||
being auto-added is already in the calibre library.
|
|
||||||
If it is, a meesage will pop up asking you whether
|
|
||||||
you want to add it anyway.</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Check for &duplicates when auto-adding files</string>
|
<string>Automatically &convert added files to the current output format</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -25,7 +25,7 @@ from calibre.ebooks.conversion.config import GuiRecommendations, \
|
|||||||
from calibre.gui2.convert import bulk_defaults_for_input_format
|
from calibre.gui2.convert import bulk_defaults_for_input_format
|
||||||
|
|
||||||
def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
|
def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
|
||||||
out_format=None):
|
out_format=None, show_no_format_warning=True):
|
||||||
changed = False
|
changed = False
|
||||||
jobs = []
|
jobs = []
|
||||||
bad = []
|
bad = []
|
||||||
@ -91,7 +91,7 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
|
|||||||
except NoSupportedInputFormats:
|
except NoSupportedInputFormats:
|
||||||
bad.append(book_id)
|
bad.append(book_id)
|
||||||
|
|
||||||
if bad != []:
|
if bad and show_no_format_warning:
|
||||||
res = []
|
res = []
|
||||||
for id in bad:
|
for id in bad:
|
||||||
title = db.title(id, True)
|
title = db.title(id, True)
|
||||||
|
@ -3243,7 +3243,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
return id
|
return id
|
||||||
|
|
||||||
|
|
||||||
def add_books(self, paths, formats, metadata, add_duplicates=True):
|
def add_books(self, paths, formats, metadata, add_duplicates=True,
|
||||||
|
return_ids=False):
|
||||||
'''
|
'''
|
||||||
Add a book to the database. The result cache is not updated.
|
Add a book to the database. The result cache is not updated.
|
||||||
:param:`paths` List of paths to book files or file-like objects
|
:param:`paths` List of paths to book files or file-like objects
|
||||||
@ -3289,7 +3290,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
formats = list(duplicate[1] for duplicate in duplicates)
|
formats = list(duplicate[1] for duplicate in duplicates)
|
||||||
metadata = list(duplicate[2] for duplicate in duplicates)
|
metadata = list(duplicate[2] for duplicate in duplicates)
|
||||||
return (paths, formats, metadata), len(ids)
|
return (paths, formats, metadata), len(ids)
|
||||||
return None, len(ids)
|
return None, (ids if return_ids else len(ids))
|
||||||
|
|
||||||
def import_book(self, mi, formats, notify=True, import_hooks=True,
|
def import_book(self, mi, formats, notify=True, import_hooks=True,
|
||||||
apply_import_tags=True, preserve_uuid=False):
|
apply_import_tags=True, preserve_uuid=False):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user