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
dc5f3871ed
@ -3,8 +3,9 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
'''Dialog to edit metadata in bulk'''
|
||||
|
||||
from PyQt4.Qt import SIGNAL, QObject, QDialog, QGridLayout, \
|
||||
QThread, Qt
|
||||
from threading import Thread
|
||||
|
||||
from PyQt4.Qt import QDialog, QGridLayout
|
||||
|
||||
from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog
|
||||
from calibre.gui2.dialogs.tag_editor import TagEditor
|
||||
@ -12,18 +13,73 @@ from calibre.ebooks.metadata import string_to_authors, \
|
||||
authors_to_string
|
||||
from calibre.gui2.custom_column_widgets import populate_metadata_page
|
||||
from calibre.gui2.dialogs.progress import BlockingBusy
|
||||
from calibre.gui2 import error_dialog
|
||||
from calibre.gui2 import error_dialog, Dispatcher
|
||||
|
||||
class Worker(QThread):
|
||||
class Worker(Thread):
|
||||
|
||||
def __init__(self, func, parent=None):
|
||||
QThread.__init__(self, parent)
|
||||
self.func = func
|
||||
def __init__(self, args, db, ids, callback):
|
||||
Thread.__init__(self)
|
||||
self.args = args
|
||||
self.db = db
|
||||
self.ids = ids
|
||||
self.error = None
|
||||
self.callback = callback
|
||||
|
||||
def doit(self):
|
||||
remove, add, au, aus, do_aus, rating, pub, do_series, \
|
||||
do_autonumber, do_remove_format, remove_format, do_swap_ta, \
|
||||
do_remove_conv, do_auto_author, series = self.args
|
||||
|
||||
for id in self.ids:
|
||||
if do_swap_ta:
|
||||
title = self.db.title(id, index_is_id=True)
|
||||
aum = self.db.authors(id, index_is_id=True)
|
||||
if aum:
|
||||
aum = [a.strip().replace('|', ',') for a in aum.split(',')]
|
||||
new_title = authors_to_string(aum)
|
||||
self.db.set_title(id, new_title, notify=False)
|
||||
if title:
|
||||
new_authors = string_to_authors(title)
|
||||
self.db.set_authors(id, new_authors, notify=False)
|
||||
|
||||
if au:
|
||||
self.db.set_authors(id, string_to_authors(au), notify=False)
|
||||
|
||||
if do_auto_author:
|
||||
x = self.db.author_sort_from_book(id, index_is_id=True)
|
||||
if x:
|
||||
self.db.set_author_sort(id, x, notify=False)
|
||||
|
||||
if aus and do_aus:
|
||||
self.db.set_author_sort(id, aus, notify=False)
|
||||
|
||||
if rating != -1:
|
||||
self.db.set_rating(id, 2*rating, notify=False)
|
||||
|
||||
if pub:
|
||||
self.db.set_publisher(id, pub, notify=False)
|
||||
|
||||
if do_series:
|
||||
next = self.db.get_next_series_num_for(series)
|
||||
self.db.set_series(id, series, notify=False)
|
||||
num = next if do_autonumber and series else 1.0
|
||||
self.db.set_series_index(id, num, notify=False)
|
||||
|
||||
if do_remove_format:
|
||||
self.db.remove_format(id, remove_format, index_is_id=True, notify=False)
|
||||
|
||||
if do_remove_conv:
|
||||
self.db.delete_conversion_options(id, 'PIPE')
|
||||
|
||||
for w in getattr(self, 'custom_column_widgets', []):
|
||||
w.commit(self.ids)
|
||||
self.db.bulk_modify_tags(self.ids, add=add, remove=remove,
|
||||
notify=False)
|
||||
self.db.clean()
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.func()
|
||||
self.doit()
|
||||
except Exception, err:
|
||||
import traceback
|
||||
try:
|
||||
@ -32,6 +88,9 @@ class Worker(QThread):
|
||||
err = repr(err)
|
||||
self.error = (err, traceback.format_exc())
|
||||
|
||||
self.callback()
|
||||
|
||||
|
||||
class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
|
||||
def __init__(self, window, rows, db):
|
||||
@ -57,9 +116,9 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
|
||||
self.remove_format.setCurrentIndex(-1)
|
||||
|
||||
QObject.connect(self.series, SIGNAL('currentIndexChanged(int)'), self.series_changed)
|
||||
QObject.connect(self.series, SIGNAL('editTextChanged(QString)'), self.series_changed)
|
||||
QObject.connect(self.tag_editor_button, SIGNAL('clicked()'), self.tag_editor)
|
||||
self.series.currentIndexChanged[int].connect(self.series_changed)
|
||||
self.series.editTextChanged.connect(self.series_changed)
|
||||
self.tag_editor_button.clicked.connect(self.tag_editor)
|
||||
if len(db.custom_column_label_map) == 0:
|
||||
self.central_widget.tabBar().setVisible(False)
|
||||
else:
|
||||
@ -113,7 +172,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
self.publisher.addItem(name)
|
||||
self.publisher.setEditText('')
|
||||
|
||||
def tag_editor(self):
|
||||
def tag_editor(self, *args):
|
||||
d = TagEditor(self, self.db, None)
|
||||
d.exec_()
|
||||
if d.result() == QDialog.Accepted:
|
||||
@ -126,6 +185,12 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
if len(self.ids) < 1:
|
||||
return QDialog.accept(self)
|
||||
|
||||
self.changed = bool(self.ids)
|
||||
# Cache values from GUI so that Qt widgets are not used in
|
||||
# non GUI thread
|
||||
for w in getattr(self, 'custom_column_widgets', []):
|
||||
w.gui_val
|
||||
|
||||
remove = unicode(self.remove_tags.text()).strip().split(',')
|
||||
add = unicode(self.tags.text()).strip().split(',')
|
||||
au = unicode(self.authors.text())
|
||||
@ -141,72 +206,16 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
||||
do_swap_ta = self.swap_title_and_author.isChecked()
|
||||
do_remove_conv = self.remove_conversion_settings.isChecked()
|
||||
do_auto_author = self.auto_author_sort.isChecked()
|
||||
self.changed = bool(self.ids)
|
||||
# Cache values from GUI so that Qt widgets are not used in
|
||||
# non GUI thread
|
||||
for w in getattr(self, 'custom_column_widgets', []):
|
||||
w.gui_val
|
||||
|
||||
def doit():
|
||||
# author and title changes cause file system changes as well as
|
||||
# database changes. Do these as individual transactions, so that
|
||||
# exceptions do the smallest amount of damage
|
||||
for id in self.ids:
|
||||
if do_swap_ta:
|
||||
title = self.db.title(id, index_is_id=True)
|
||||
aum = self.db.authors(id, index_is_id=True)
|
||||
if aum:
|
||||
aum = [a.strip().replace('|', ',') for a in aum.split(',')]
|
||||
new_title = authors_to_string(aum)
|
||||
self.db.set_title(id, new_title, notify=False)
|
||||
if title:
|
||||
new_authors = string_to_authors(title)
|
||||
self.db.set_authors(id, new_authors, notify=False)
|
||||
if au:
|
||||
self.db.set_authors(id, string_to_authors(au), notify=False)
|
||||
|
||||
# all of the following are database-only operations, so do them
|
||||
# as a single transaction
|
||||
for id in self.ids:
|
||||
if do_auto_author:
|
||||
x = self.db.author_sort_from_book(id, index_is_id=True)
|
||||
if x:
|
||||
self.db.set_author_sort(id, x, notify=False, commit=False)
|
||||
|
||||
if aus and do_aus:
|
||||
self.db.set_author_sort(id, aus, notify=False, commit=False)
|
||||
|
||||
if rating != -1:
|
||||
self.db.set_rating(id, 2*rating, notify=False, commit=False)
|
||||
|
||||
if pub:
|
||||
self.db.set_publisher(id, pub, notify=False, commit=False)
|
||||
|
||||
if do_series:
|
||||
next = self.db.get_next_series_num_for(series)
|
||||
self.db.set_series(id, series, notify=False, commit=False)
|
||||
num = next if do_autonumber and series else 1.0
|
||||
self.db.set_series_index(id, num, notify=False, commit=False)
|
||||
|
||||
if do_remove_format:
|
||||
self.db.remove_format(id, remove_format, index_is_id=True, notify=False, commit=False)
|
||||
|
||||
if do_remove_conv:
|
||||
self.db.delete_conversion_options(id, 'PIPE')
|
||||
|
||||
self.db.conn.commit()
|
||||
for w in getattr(self, 'custom_column_widgets', []):
|
||||
w.commit(self.ids)
|
||||
self.db.bulk_modify_tags(self.ids, add=add, remove=remove,
|
||||
notify=False)
|
||||
self.db.clean()
|
||||
|
||||
self.worker = Worker(doit, self)
|
||||
self.worker.start()
|
||||
args = (remove, add, au, aus, do_aus, rating, pub, do_series,
|
||||
do_autonumber, do_remove_format, remove_format, do_swap_ta,
|
||||
do_remove_conv, do_auto_author, series)
|
||||
|
||||
bb = BlockingBusy(_('Applying changes to %d books. This may take a while.')
|
||||
%len(self.ids), parent=self)
|
||||
self.worker.finished.connect(bb.accept, type=Qt.QueuedConnection)
|
||||
self.worker = Worker(args, self.db, self.ids, Dispatcher(bb.accept,
|
||||
parent=bb))
|
||||
self.worker.start()
|
||||
bb.exec_()
|
||||
|
||||
if self.worker.error is not None:
|
||||
|
@ -377,7 +377,7 @@ class CustomColumns(object):
|
||||
if add:
|
||||
self.conn.execute(
|
||||
'''
|
||||
INSERT INTO {0}(book, value) SELECT {1}.id, {2}.id FROM {1}, {2}
|
||||
INSERT OR REPLACE INTO {0}(book, value) SELECT {1}.id, {2}.id FROM {1}, {2}
|
||||
'''.format(link_table, temp_tables[0], temp_tables[1])
|
||||
)
|
||||
# get rid of the temp tables
|
||||
|
@ -1438,7 +1438,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
if add:
|
||||
self.conn.execute(
|
||||
'''
|
||||
INSERT INTO books_tags_link(book, tag) SELECT {0}.id, {1}.id FROM
|
||||
INSERT OR REPLACE INTO books_tags_link(book, tag) SELECT {0}.id, {1}.id FROM
|
||||
{0}, {1}
|
||||
'''.format(tables[0], tables[1])
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user