mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit metadata dialog: Change the remove unused series button to a clear series button (as the remove unused series function is now automatic)
This commit is contained in:
parent
d7908b9f1f
commit
e48a9d1e57
@ -5,7 +5,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os, shutil
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt4.Qt import QMenu, QModelIndex, QTimer
|
from PyQt4.Qt import QMenu, QModelIndex, QTimer
|
||||||
@ -16,6 +16,7 @@ from calibre.gui2.dialogs.confirm_delete import confirm
|
|||||||
from calibre.gui2.dialogs.device_category_editor import DeviceCategoryEditor
|
from calibre.gui2.dialogs.device_category_editor import DeviceCategoryEditor
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
from calibre.ebooks.metadata import authors_to_string
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
|
from calibre.ebooks.metadata.opf2 import OPF
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
from calibre.db.errors import NoSuchFormat
|
from calibre.db.errors import NoSuchFormat
|
||||||
|
|
||||||
@ -79,14 +80,27 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
Dispatcher(self.metadata_downloaded),
|
Dispatcher(self.metadata_downloaded),
|
||||||
ensure_fields=ensure_fields)
|
ensure_fields=ensure_fields)
|
||||||
|
|
||||||
|
def cleanup_bulk_download(self, tdir, log_file):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(tdir, ignore_errors=True)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
os.remove(log_file)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def metadata_downloaded(self, job):
|
def metadata_downloaded(self, job):
|
||||||
if job.failed:
|
if job.failed:
|
||||||
self.gui.job_exception(job, dialog_title=_('Failed to download metadata'))
|
self.gui.job_exception(job, dialog_title=_('Failed to download metadata'))
|
||||||
return
|
return
|
||||||
from calibre.gui2.metadata.bulk_download import get_job_details
|
from calibre.gui2.metadata.bulk_download import get_job_details
|
||||||
id_map, failed_ids, failed_covers, all_failed, det_msg = \
|
(aborted, id_map, tdir, log_file, failed_ids, failed_covers, all_failed,
|
||||||
get_job_details(job)
|
det_msg, lm_map) = get_job_details(job)
|
||||||
|
if aborted:
|
||||||
|
return self.cleanup_bulk_download(tdir, log_file)
|
||||||
if all_failed:
|
if all_failed:
|
||||||
|
self.cleanup_bulk_download(tdir, log_file)
|
||||||
return error_dialog(self.gui, _('Download failed'),
|
return error_dialog(self.gui, _('Download failed'),
|
||||||
_('Failed to download metadata or covers for any of the %d'
|
_('Failed to download metadata or covers for any of the %d'
|
||||||
' book(s).') % len(id_map), det_msg=det_msg, show=True)
|
' book(s).') % len(id_map), det_msg=det_msg, show=True)
|
||||||
@ -103,28 +117,26 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
msg += '<p>'+_('Could not download metadata and/or covers for %d of the books. Click'
|
msg += '<p>'+_('Could not download metadata and/or covers for %d of the books. Click'
|
||||||
' "Show details" to see which books.')%num
|
' "Show details" to see which books.')%num
|
||||||
|
|
||||||
payload = (id_map, failed_ids, failed_covers)
|
payload = (id_map, tdir, log_file, lm_map)
|
||||||
from calibre.gui2.dialogs.message_box import ProceedNotification
|
from calibre.gui2.dialogs.message_box import ProceedNotification
|
||||||
p = ProceedNotification(self.apply_downloaded_metadata,
|
p = ProceedNotification(self.apply_downloaded_metadata,
|
||||||
payload, job.html_details,
|
payload, open(log_file, 'rb').read().decode('utf-8'),
|
||||||
_('Download log'), _('Download complete'), msg,
|
_('Download log'), _('Download complete'), msg,
|
||||||
det_msg=det_msg, show_copy_button=show_copy_button,
|
det_msg=det_msg, show_copy_button=show_copy_button,
|
||||||
parent=self.gui)
|
parent=self.gui)
|
||||||
p.show()
|
p.show()
|
||||||
|
|
||||||
def apply_downloaded_metadata(self, payload):
|
def apply_downloaded_metadata(self, payload):
|
||||||
id_map, failed_ids, failed_covers = payload
|
good_ids, tdir, log_file, lm_map = payload
|
||||||
id_map = dict([(k, v) for k, v in id_map.iteritems() if k not in
|
if not good_ids:
|
||||||
failed_ids])
|
|
||||||
if not id_map:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
modified = set()
|
modified = set()
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
|
|
||||||
for i, mi in id_map.iteritems():
|
for i in good_ids:
|
||||||
lm = db.metadata_last_modified(i, index_is_id=True)
|
lm = db.metadata_last_modified(i, index_is_id=True)
|
||||||
if lm > mi.last_modified:
|
if lm > lm_map[i]:
|
||||||
title = db.title(i, index_is_id=True)
|
title = db.title(i, index_is_id=True)
|
||||||
authors = db.authors(i, index_is_id=True)
|
authors = db.authors(i, index_is_id=True)
|
||||||
if authors:
|
if authors:
|
||||||
@ -144,7 +156,18 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
'Do you want to proceed?'), det_msg='\n'.join(modified)):
|
'Do you want to proceed?'), det_msg='\n'.join(modified)):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.apply_metadata_changes(id_map)
|
id_map = {}
|
||||||
|
for bid in good_ids:
|
||||||
|
opf = os.path.join(tdir, '%d.mi')
|
||||||
|
if not os.path.exists(opf):
|
||||||
|
opf = None
|
||||||
|
cov = os.path.join(tdir, '%d.cover'%bid)
|
||||||
|
if not os.path.exists(cov):
|
||||||
|
cov = None
|
||||||
|
id_map[bid] = (opf, cov)
|
||||||
|
|
||||||
|
self.apply_metadata_changes(id_map, callback=lambda x:
|
||||||
|
self.cleanup_bulk_download(tdir, log_file))
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@ -468,6 +491,11 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
callback can be either None or a function accepting a single argument,
|
callback can be either None or a function accepting a single argument,
|
||||||
in which case it is called after applying is complete with the list of
|
in which case it is called after applying is complete with the list of
|
||||||
changed ids.
|
changed ids.
|
||||||
|
|
||||||
|
id_map can also be a mapping of ids to 2-tuple's where each 2-tuple
|
||||||
|
contains the absolute paths to an OPF and cover file respectively. If
|
||||||
|
either of the paths is None, then the corresponding metadata is not
|
||||||
|
updated.
|
||||||
'''
|
'''
|
||||||
if title is None:
|
if title is None:
|
||||||
title = _('Applying changed metadata')
|
title = _('Applying changed metadata')
|
||||||
@ -492,28 +520,48 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
return self.finalize_apply()
|
return self.finalize_apply()
|
||||||
|
|
||||||
i, mi = self.apply_id_map[self.apply_current_idx]
|
i, mi = self.apply_id_map[self.apply_current_idx]
|
||||||
|
if isinstance(mi, tuple):
|
||||||
|
opf, cover = mi
|
||||||
|
if opf:
|
||||||
|
mi = OPF(open(opf, 'rb'), basedir=os.path.dirname(opf),
|
||||||
|
populate_spine=False).to_book_metadata()
|
||||||
|
self.apply_mi(i, mi)
|
||||||
|
if cover:
|
||||||
|
self.gui.current_db.set_cover(i, open(cover, 'rb'),
|
||||||
|
notify=False, commit=False)
|
||||||
|
else:
|
||||||
|
self.apply_mi(i, mi)
|
||||||
|
|
||||||
|
self.apply_current_idx += 1
|
||||||
|
if self.apply_pd is not None:
|
||||||
|
self.apply_pd.value += 1
|
||||||
|
QTimer.singleShot(50, self.do_one_apply)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_mi(self, book_id, mi):
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
|
|
||||||
try:
|
try:
|
||||||
set_title = not mi.is_null('title')
|
set_title = not mi.is_null('title')
|
||||||
set_authors = not mi.is_null('authors')
|
set_authors = not mi.is_null('authors')
|
||||||
idents = db.get_identifiers(i, index_is_id=True)
|
idents = db.get_identifiers(book_id, index_is_id=True)
|
||||||
if mi.identifiers:
|
if mi.identifiers:
|
||||||
idents.update(mi.identifiers)
|
idents.update(mi.identifiers)
|
||||||
mi.identifiers = idents
|
mi.identifiers = idents
|
||||||
if mi.is_null('series'):
|
if mi.is_null('series'):
|
||||||
mi.series_index = None
|
mi.series_index = None
|
||||||
if self._am_merge_tags:
|
if self._am_merge_tags:
|
||||||
old_tags = db.tags(i, index_is_id=True)
|
old_tags = db.tags(book_id, index_is_id=True)
|
||||||
if old_tags:
|
if old_tags:
|
||||||
tags = [x.strip() for x in old_tags.split(',')] + (
|
tags = [x.strip() for x in old_tags.split(',')] + (
|
||||||
mi.tags if mi.tags else [])
|
mi.tags if mi.tags else [])
|
||||||
mi.tags = list(set(tags))
|
mi.tags = list(set(tags))
|
||||||
db.set_metadata(i, mi, commit=False, set_title=set_title,
|
db.set_metadata(book_id, mi, commit=False, set_title=set_title,
|
||||||
set_authors=set_authors, notify=False)
|
set_authors=set_authors, notify=False)
|
||||||
self.applied_ids.append(i)
|
self.applied_ids.append(book_id)
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
self.apply_failures.append((i, traceback.format_exc()))
|
self.apply_failures.append((book_id, traceback.format_exc()))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if mi.cover:
|
if mi.cover:
|
||||||
@ -521,11 +569,6 @@ class EditMetadataAction(InterfaceAction):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.apply_current_idx += 1
|
|
||||||
if self.apply_pd is not None:
|
|
||||||
self.apply_pd.value += 1
|
|
||||||
QTimer.singleShot(50, self.do_one_apply)
|
|
||||||
|
|
||||||
def finalize_apply(self):
|
def finalize_apply(self):
|
||||||
db = self.gui.current_db
|
db = self.gui.current_db
|
||||||
db.commit()
|
db.commit()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user