mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Remove unused olddb code paths
This commit is contained in:
parent
167d44f234
commit
172e4def71
@ -89,7 +89,7 @@ def get_data_as_dict(self, prefix=None, authors_as_string=False, ids=None, conve
|
|||||||
x = {}
|
x = {}
|
||||||
for field in FIELDS:
|
for field in FIELDS:
|
||||||
x[field] = record[self.FIELD_MAP[field]]
|
x[field] = record[self.FIELD_MAP[field]]
|
||||||
if convert_to_local_tz and hasattr(self, 'new_api'):
|
if convert_to_local_tz:
|
||||||
for tf in ('timestamp', 'pubdate', 'last_modified'):
|
for tf in ('timestamp', 'pubdate', 'last_modified'):
|
||||||
x[tf] = as_local_time(x[tf])
|
x[tf] = as_local_time(x[tf])
|
||||||
|
|
||||||
|
@ -190,10 +190,7 @@ class BackupStatus(QDialog): # {{{
|
|||||||
|
|
||||||
def mark_all_dirty(self):
|
def mark_all_dirty(self):
|
||||||
db = self.db()
|
db = self.db()
|
||||||
if hasattr(db, 'new_api'):
|
db.new_api.mark_as_dirty(db.new_api.all_book_ids())
|
||||||
db.new_api.mark_as_dirty(db.new_api.all_book_ids())
|
|
||||||
else:
|
|
||||||
db.dirtied(list(db.data.iterallids()))
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@ -454,17 +451,14 @@ class ChooseLibraryAction(InterfaceAction):
|
|||||||
self.gui.library_moved(db.library_path, call_close=False)
|
self.gui.library_moved(db.library_path, call_close=False)
|
||||||
|
|
||||||
def check_library(self):
|
def check_library(self):
|
||||||
from calibre.gui2.dialogs.check_library import CheckLibraryDialog, DBCheck, DBCheckNew
|
from calibre.gui2.dialogs.check_library import CheckLibraryDialog, DBCheck
|
||||||
self.gui.library_view.save_state()
|
self.gui.library_view.save_state()
|
||||||
m = self.gui.library_view.model()
|
m = self.gui.library_view.model()
|
||||||
m.stop_metadata_backup()
|
m.stop_metadata_backup()
|
||||||
db = m.db
|
db = m.db
|
||||||
db.prefs.disable_setting = True
|
db.prefs.disable_setting = True
|
||||||
|
|
||||||
if hasattr(db, 'new_api'):
|
d = DBCheck(self.gui, db)
|
||||||
d = DBCheckNew(self.gui, db)
|
|
||||||
else:
|
|
||||||
d = DBCheck(self.gui, db)
|
|
||||||
d.start()
|
d.start()
|
||||||
try:
|
try:
|
||||||
d.conn.close()
|
d.conn.close()
|
||||||
|
@ -3,22 +3,20 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
import os, shutil
|
import os
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from PyQt4.Qt import (QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QLabel,
|
from PyQt4.Qt import (
|
||||||
QPushButton, QDialogButtonBox, QApplication, QTreeWidgetItem,
|
QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QLabel, QPushButton,
|
||||||
QLineEdit, Qt, QProgressBar, QSize, QTimer, QIcon, QTextEdit,
|
QDialogButtonBox, QApplication, QTreeWidgetItem, QLineEdit, Qt, QSize,
|
||||||
QSplitter, QWidget, pyqtSignal)
|
QTimer, QIcon, QTextEdit, QSplitter, QWidget, pyqtSignal)
|
||||||
|
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.library.check_library import CheckLibrary, CHECKS
|
from calibre.library.check_library import CheckLibrary, CHECKS
|
||||||
from calibre.utils.recycle_bin import delete_file, delete_tree
|
from calibre.utils.recycle_bin import delete_file, delete_tree
|
||||||
from calibre import prints, as_unicode
|
from calibre import prints, as_unicode
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
|
||||||
from calibre.library.sqlite import DBThread, OperationalError
|
|
||||||
|
|
||||||
class DBCheckNew(QDialog): # {{{
|
class DBCheck(QDialog): # {{{
|
||||||
|
|
||||||
update_msg = pyqtSignal(object)
|
update_msg = pyqtSignal(object)
|
||||||
|
|
||||||
@ -75,125 +73,6 @@ class DBCheckNew(QDialog): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
class DBCheck(QDialog): # {{{
|
|
||||||
|
|
||||||
def __init__(self, parent, db):
|
|
||||||
QDialog.__init__(self, parent)
|
|
||||||
self.l = QVBoxLayout()
|
|
||||||
self.setLayout(self.l)
|
|
||||||
self.l1 = QLabel(_('Checking database integrity')+'...')
|
|
||||||
self.setWindowTitle(_('Checking database integrity'))
|
|
||||||
self.l.addWidget(self.l1)
|
|
||||||
self.pb = QProgressBar(self)
|
|
||||||
self.l.addWidget(self.pb)
|
|
||||||
self.pb.setMaximum(0)
|
|
||||||
self.pb.setMinimum(0)
|
|
||||||
self.msg = QLabel('')
|
|
||||||
self.l.addWidget(self.msg)
|
|
||||||
self.msg.setWordWrap(True)
|
|
||||||
self.bb = QDialogButtonBox(QDialogButtonBox.Cancel)
|
|
||||||
self.l.addWidget(self.bb)
|
|
||||||
self.bb.rejected.connect(self.reject)
|
|
||||||
self.resize(self.sizeHint() + QSize(100, 50))
|
|
||||||
self.error = None
|
|
||||||
self.db = db
|
|
||||||
self.closed_orig_conn = False
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
self.user_version = self.db.user_version
|
|
||||||
self.rejected = False
|
|
||||||
self.db.clean()
|
|
||||||
self.db.close()
|
|
||||||
self.closed_orig_conn = True
|
|
||||||
t = DBThread(self.db.dbpath, False)
|
|
||||||
t.connect()
|
|
||||||
self.conn = t.conn
|
|
||||||
self.dump = self.conn.iterdump()
|
|
||||||
self.statements = []
|
|
||||||
self.count = 0
|
|
||||||
self.msg.setText(_('Dumping database to SQL'))
|
|
||||||
# Give the backup thread time to stop
|
|
||||||
QTimer.singleShot(2000, self.do_one_dump)
|
|
||||||
self.exec_()
|
|
||||||
|
|
||||||
def do_one_dump(self):
|
|
||||||
if self.rejected:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
self.statements.append(self.dump.next())
|
|
||||||
self.count += 1
|
|
||||||
except StopIteration:
|
|
||||||
self.start_load()
|
|
||||||
return
|
|
||||||
QTimer.singleShot(0, self.do_one_dump)
|
|
||||||
except Exception as e:
|
|
||||||
import traceback
|
|
||||||
self.error = (as_unicode(e), traceback.format_exc())
|
|
||||||
self.reject()
|
|
||||||
|
|
||||||
def start_load(self):
|
|
||||||
try:
|
|
||||||
self.conn.close()
|
|
||||||
self.pb.setMaximum(self.count)
|
|
||||||
self.pb.setValue(0)
|
|
||||||
self.msg.setText(_('Loading database from SQL'))
|
|
||||||
self.db.close()
|
|
||||||
self.ndbpath = PersistentTemporaryFile('.db')
|
|
||||||
self.ndbpath.close()
|
|
||||||
self.ndbpath = self.ndbpath.name
|
|
||||||
t = DBThread(self.ndbpath, False)
|
|
||||||
t.connect()
|
|
||||||
self.conn = t.conn
|
|
||||||
self.conn.execute('create temporary table temp_sequence(id INTEGER PRIMARY KEY AUTOINCREMENT)')
|
|
||||||
self.conn.commit()
|
|
||||||
|
|
||||||
QTimer.singleShot(0, self.do_one_load)
|
|
||||||
except Exception as e:
|
|
||||||
import traceback
|
|
||||||
self.error = (as_unicode(e), traceback.format_exc())
|
|
||||||
self.reject()
|
|
||||||
|
|
||||||
def do_one_load(self):
|
|
||||||
if self.rejected:
|
|
||||||
return
|
|
||||||
if self.count > 0:
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
self.conn.execute(self.statements.pop(0))
|
|
||||||
except OperationalError:
|
|
||||||
if self.count > 1:
|
|
||||||
# The last statement in the dump could be an extra
|
|
||||||
# commit, so ignore it.
|
|
||||||
raise
|
|
||||||
self.pb.setValue(self.pb.value() + 1)
|
|
||||||
self.count -= 1
|
|
||||||
QTimer.singleShot(0, self.do_one_load)
|
|
||||||
except Exception as e:
|
|
||||||
import traceback
|
|
||||||
self.error = (as_unicode(e), traceback.format_exc())
|
|
||||||
self.reject()
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.replace_db()
|
|
||||||
|
|
||||||
def replace_db(self):
|
|
||||||
self.conn.commit()
|
|
||||||
self.conn.execute('pragma user_version=%d'%int(self.user_version))
|
|
||||||
self.conn.commit()
|
|
||||||
self.conn.close()
|
|
||||||
shutil.copyfile(self.ndbpath, self.db.dbpath)
|
|
||||||
self.db = None
|
|
||||||
self.accept()
|
|
||||||
|
|
||||||
def break_cycles(self):
|
|
||||||
self.statements = self.unpickler = self.db = self.conn = None
|
|
||||||
|
|
||||||
def reject(self):
|
|
||||||
self.rejected = True
|
|
||||||
QDialog.reject(self)
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
class Item(QTreeWidgetItem):
|
class Item(QTreeWidgetItem):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -26,8 +26,7 @@ from calibre.utils.icu import sort_key, capitalize
|
|||||||
from calibre.utils.config import prefs, tweaks
|
from calibre.utils.config import prefs, tweaks
|
||||||
from calibre.utils.magick.draw import identify_data
|
from calibre.utils.magick.draw import identify_data
|
||||||
from calibre.utils.date import qt_to_dt
|
from calibre.utils.date import qt_to_dt
|
||||||
from calibre.ptempfile import SpooledTemporaryFile
|
from calibre.db import _get_next_series_num_for_list
|
||||||
from calibre.db import SPOOL_SIZE, _get_next_series_num_for_list
|
|
||||||
|
|
||||||
def get_cover_data(stream, ext): # {{{
|
def get_cover_data(stream, ext): # {{{
|
||||||
from calibre.ebooks.metadata.meta import get_metadata
|
from calibre.ebooks.metadata.meta import get_metadata
|
||||||
@ -59,7 +58,7 @@ Settings = namedtuple('Settings', 'remove_all remove add au aus do_aus rating pu
|
|||||||
'remove_format do_swap_ta do_remove_conv do_auto_author series do_series_restart series_start_value '
|
'remove_format do_swap_ta do_remove_conv do_auto_author series do_series_restart series_start_value '
|
||||||
'do_title_case cover_action clear_series pubdate adddate do_title_sort languages clear_languages restore_original')
|
'do_title_case cover_action clear_series pubdate adddate do_title_sort languages clear_languages restore_original')
|
||||||
|
|
||||||
class MyBlockingBusyNew(QDialog): # {{{
|
class MyBlockingBusy(QDialog): # {{{
|
||||||
|
|
||||||
all_done = pyqtSignal()
|
all_done = pyqtSignal()
|
||||||
|
|
||||||
@ -279,256 +278,6 @@ class MyBlockingBusyNew(QDialog): # {{{
|
|||||||
self.s_r_func(book_id)
|
self.s_r_func(book_id)
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
class MyBlockingBusy(QDialog): # {{{
|
|
||||||
|
|
||||||
do_one_signal = pyqtSignal()
|
|
||||||
|
|
||||||
phases = ['',
|
|
||||||
_('Title/Author'),
|
|
||||||
_('Standard metadata'),
|
|
||||||
_('Custom metadata'),
|
|
||||||
_('Search/Replace'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, msg, args, db, ids, cc_widgets, s_r_func,
|
|
||||||
parent=None, window_title=_('Working')):
|
|
||||||
QDialog.__init__(self, parent)
|
|
||||||
|
|
||||||
self._layout = QVBoxLayout()
|
|
||||||
self.setLayout(self._layout)
|
|
||||||
self.msg_text = msg
|
|
||||||
self.msg = QLabel(msg+' ') # Ensure dialog is wide enough
|
|
||||||
# self.msg.setWordWrap(True)
|
|
||||||
self.font = QFont()
|
|
||||||
self.font.setPointSize(self.font.pointSize() + 8)
|
|
||||||
self.msg.setFont(self.font)
|
|
||||||
self.pi = ProgressIndicator(self)
|
|
||||||
self.pi.setDisplaySize(100)
|
|
||||||
self._layout.addWidget(self.pi, 0, Qt.AlignHCenter)
|
|
||||||
self._layout.addSpacing(15)
|
|
||||||
self._layout.addWidget(self.msg, 0, Qt.AlignHCenter)
|
|
||||||
self.setWindowTitle(window_title)
|
|
||||||
self.resize(self.sizeHint())
|
|
||||||
self.start()
|
|
||||||
|
|
||||||
self.args = args
|
|
||||||
self.series_start_value = None
|
|
||||||
self.db = db
|
|
||||||
self.ids = ids
|
|
||||||
self.error = None
|
|
||||||
self.cc_widgets = cc_widgets
|
|
||||||
self.s_r_func = s_r_func
|
|
||||||
self.do_one_signal.connect(self.do_one_safe, Qt.QueuedConnection)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
self.pi.startAnimation()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self.pi.stopAnimation()
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
self.stop()
|
|
||||||
return QDialog.accept(self)
|
|
||||||
|
|
||||||
def exec_(self):
|
|
||||||
self.current_index = 0
|
|
||||||
self.current_phase = 1
|
|
||||||
self.do_one_signal.emit()
|
|
||||||
return QDialog.exec_(self)
|
|
||||||
|
|
||||||
def do_one_safe(self):
|
|
||||||
try:
|
|
||||||
if self.current_index >= len(self.ids):
|
|
||||||
self.current_phase += 1
|
|
||||||
self.current_index = 0
|
|
||||||
if self.current_phase > 4:
|
|
||||||
self.db.commit()
|
|
||||||
return self.accept()
|
|
||||||
id = self.ids[self.current_index]
|
|
||||||
percent = int((self.current_index*100)/float(len(self.ids)))
|
|
||||||
self.msg.setText(self.msg_text.format(self.phases[self.current_phase],
|
|
||||||
percent))
|
|
||||||
self.do_one(id)
|
|
||||||
except Exception as err:
|
|
||||||
import traceback
|
|
||||||
try:
|
|
||||||
err = unicode(err)
|
|
||||||
except:
|
|
||||||
err = repr(err)
|
|
||||||
self.error = (err, traceback.format_exc())
|
|
||||||
return self.accept()
|
|
||||||
|
|
||||||
def do_one(self, id):
|
|
||||||
remove_all, 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, do_series_restart, \
|
|
||||||
series_start_value, do_title_case, cover_action, clear_series, \
|
|
||||||
pubdate, adddate, do_title_sort, languages, clear_languages, \
|
|
||||||
restore_original = self.args
|
|
||||||
|
|
||||||
# first loop: All changes that modify the filesystem and commit
|
|
||||||
# immediately. We want to
|
|
||||||
# try hard to keep the DB and the file system in sync, even in the face
|
|
||||||
# of exceptions or forced exits.
|
|
||||||
if self.current_phase == 1:
|
|
||||||
title_set = False
|
|
||||||
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)
|
|
||||||
if do_title_case:
|
|
||||||
new_title = titlecase(new_title)
|
|
||||||
self.db.set_title(id, new_title, notify=False)
|
|
||||||
title_set = True
|
|
||||||
if title:
|
|
||||||
new_authors = string_to_authors(title)
|
|
||||||
self.db.set_authors(id, new_authors, notify=False)
|
|
||||||
if do_title_case and not title_set:
|
|
||||||
title = self.db.title(id, index_is_id=True)
|
|
||||||
self.db.set_title(id, titlecase(title), notify=False)
|
|
||||||
if do_title_sort:
|
|
||||||
title = self.db.title(id, index_is_id=True)
|
|
||||||
if languages:
|
|
||||||
lang = languages[0]
|
|
||||||
else:
|
|
||||||
lang = self.db.languages(id, index_is_id=True)
|
|
||||||
if lang:
|
|
||||||
lang = lang.partition(',')[0]
|
|
||||||
self.db.set_title_sort(id, title_sort(title, lang=lang),
|
|
||||||
notify=False)
|
|
||||||
if au:
|
|
||||||
self.db.set_authors(id, string_to_authors(au), notify=False)
|
|
||||||
if cover_action == 'remove':
|
|
||||||
self.db.remove_cover(id)
|
|
||||||
elif cover_action == 'generate':
|
|
||||||
from calibre.ebooks import calibre_cover
|
|
||||||
from calibre.ebooks.metadata import fmt_sidx
|
|
||||||
from calibre.gui2 import config
|
|
||||||
mi = self.db.get_metadata(id, index_is_id=True)
|
|
||||||
series_string = None
|
|
||||||
if mi.series:
|
|
||||||
series_string = _('Book %(sidx)s of %(series)s')%dict(
|
|
||||||
sidx=fmt_sidx(mi.series_index,
|
|
||||||
use_roman=config['use_roman_numerals_for_series_number']),
|
|
||||||
series=mi.series)
|
|
||||||
|
|
||||||
cdata = calibre_cover(mi.title, mi.format_field('authors')[-1],
|
|
||||||
series_string=series_string)
|
|
||||||
self.db.set_cover(id, cdata)
|
|
||||||
elif cover_action == 'fromfmt':
|
|
||||||
fmts = self.db.formats(id, index_is_id=True, verify_formats=False)
|
|
||||||
if fmts:
|
|
||||||
covers = []
|
|
||||||
for fmt in fmts.split(','):
|
|
||||||
fmtf = self.db.format(id, fmt, index_is_id=True,
|
|
||||||
as_file=True)
|
|
||||||
if fmtf is None:
|
|
||||||
continue
|
|
||||||
cdata, area = get_cover_data(fmtf, fmt)
|
|
||||||
if cdata:
|
|
||||||
covers.append((cdata, area))
|
|
||||||
covers.sort(key=lambda x: x[1])
|
|
||||||
if covers:
|
|
||||||
self.db.set_cover(id, covers[-1][0])
|
|
||||||
covers = []
|
|
||||||
elif cover_action == 'trim':
|
|
||||||
from calibre.utils.magick import Image
|
|
||||||
cdata = self.db.cover(id, index_is_id=True)
|
|
||||||
if cdata:
|
|
||||||
im = Image()
|
|
||||||
im.load(cdata)
|
|
||||||
im.trim(tweaks['cover_trim_fuzz_value'])
|
|
||||||
cdata = im.export('jpg')
|
|
||||||
self.db.set_cover(id, cdata)
|
|
||||||
|
|
||||||
if do_remove_format:
|
|
||||||
self.db.remove_format(id, remove_format, index_is_id=True,
|
|
||||||
notify=False, commit=True)
|
|
||||||
|
|
||||||
if restore_original:
|
|
||||||
formats = self.db.formats(id, index_is_id=True)
|
|
||||||
formats = formats.split(',') if formats else []
|
|
||||||
originals = [x.upper() for x in formats if
|
|
||||||
x.upper().startswith('ORIGINAL_')]
|
|
||||||
for ofmt in originals:
|
|
||||||
fmt = ofmt.replace('ORIGINAL_', '')
|
|
||||||
with SpooledTemporaryFile(SPOOL_SIZE) as stream:
|
|
||||||
self.db.copy_format_to(id, ofmt, stream,
|
|
||||||
index_is_id=True)
|
|
||||||
stream.seek(0)
|
|
||||||
self.db.add_format(id, fmt, stream, index_is_id=True,
|
|
||||||
notify=False)
|
|
||||||
self.db.remove_format(id, ofmt, index_is_id=True,
|
|
||||||
notify=False, commit=True)
|
|
||||||
|
|
||||||
elif self.current_phase == 2:
|
|
||||||
# All of these just affect the DB, so we can tolerate a total rollback
|
|
||||||
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 clear_series:
|
|
||||||
self.db.set_series(id, '', notify=False, commit=False)
|
|
||||||
|
|
||||||
if pubdate is not None:
|
|
||||||
self.db.set_pubdate(id, pubdate, notify=False, commit=False)
|
|
||||||
|
|
||||||
if adddate is not None:
|
|
||||||
self.db.set_timestamp(id, adddate, notify=False, commit=False)
|
|
||||||
|
|
||||||
if do_series:
|
|
||||||
if do_series_restart:
|
|
||||||
if self.series_start_value is None:
|
|
||||||
self.series_start_value = series_start_value
|
|
||||||
next = self.series_start_value
|
|
||||||
self.series_start_value += 1
|
|
||||||
else:
|
|
||||||
next = self.db.get_next_series_num_for(series)
|
|
||||||
self.db.set_series(id, series, notify=False, commit=False)
|
|
||||||
if not series:
|
|
||||||
self.db.set_series_index(id, 1.0, notify=False, commit=False)
|
|
||||||
elif do_autonumber: # is True if do_series_restart is True
|
|
||||||
self.db.set_series_index(id, next, notify=False, commit=False)
|
|
||||||
elif tweaks['series_index_auto_increment'] != 'no_change':
|
|
||||||
self.db.set_series_index(id, 1.0, notify=False, commit=False)
|
|
||||||
|
|
||||||
if do_remove_conv:
|
|
||||||
self.db.delete_conversion_options(id, 'PIPE', commit=False)
|
|
||||||
|
|
||||||
if clear_languages:
|
|
||||||
self.db.set_languages(id, [], notify=False, commit=False)
|
|
||||||
elif languages:
|
|
||||||
self.db.set_languages(id, languages, notify=False, commit=False)
|
|
||||||
|
|
||||||
elif self.current_phase == 3:
|
|
||||||
# both of these are fast enough to just do them all
|
|
||||||
for w in self.cc_widgets:
|
|
||||||
w.commit(self.ids)
|
|
||||||
if remove_all:
|
|
||||||
self.db.remove_all_tags(self.ids)
|
|
||||||
self.db.bulk_modify_tags(self.ids, add=add, remove=remove,
|
|
||||||
notify=False)
|
|
||||||
self.current_index = len(self.ids)
|
|
||||||
elif self.current_phase == 4:
|
|
||||||
self.s_r_func(id)
|
|
||||||
# do the next one
|
|
||||||
self.current_index += 1
|
|
||||||
self.do_one_signal.emit()
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
||||||
|
|
||||||
s_r_functions = {'' : lambda x: x,
|
s_r_functions = {'' : lambda x: x,
|
||||||
@ -1242,17 +991,11 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
|||||||
pubdate, adddate, do_title_sort, languages, clear_languages,
|
pubdate, adddate, do_title_sort, languages, clear_languages,
|
||||||
restore_original)
|
restore_original)
|
||||||
|
|
||||||
if hasattr(self.db, 'new_api'):
|
source = self.s_r_sf_itemdata(None)
|
||||||
source = self.s_r_sf_itemdata(None)
|
do_sr = source and self.s_r_obj
|
||||||
do_sr = source and self.s_r_obj
|
bb = MyBlockingBusy(args, self.ids, self.db,
|
||||||
bb = MyBlockingBusyNew(args, self.ids, self.db,
|
getattr(self, 'custom_column_widgets', []),
|
||||||
getattr(self, 'custom_column_widgets', []),
|
self.do_search_replace, do_sr, parent=self)
|
||||||
self.do_search_replace, do_sr, parent=self)
|
|
||||||
else:
|
|
||||||
bb = MyBlockingBusy(_('Applying changes to %d books.\nPhase {0} {1}%%.')
|
|
||||||
%len(self.ids), args, self.db, self.ids,
|
|
||||||
getattr(self, 'custom_column_widgets', []),
|
|
||||||
self.do_search_replace, parent=self)
|
|
||||||
|
|
||||||
# The metadata backup thread causes database commits
|
# The metadata backup thread causes database commits
|
||||||
# which can slow down bulk editing of large numbers of books
|
# which can slow down bulk editing of large numbers of books
|
||||||
|
@ -685,8 +685,6 @@ class GridView(QListView):
|
|||||||
self.thumbnail_cache.shutdown()
|
self.thumbnail_cache.shutdown()
|
||||||
|
|
||||||
def set_database(self, newdb, stage=0):
|
def set_database(self, newdb, stage=0):
|
||||||
if not hasattr(newdb, 'new_api'):
|
|
||||||
return
|
|
||||||
if stage == 0:
|
if stage == 0:
|
||||||
self.ignore_render_requests.set()
|
self.ignore_render_requests.set()
|
||||||
try:
|
try:
|
||||||
|
@ -11,7 +11,7 @@ from collections import defaultdict, namedtuple
|
|||||||
from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
|
from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
|
||||||
QModelIndex, QVariant, QDateTime, QColor, QPixmap)
|
QModelIndex, QVariant, QDateTime, QColor, QPixmap)
|
||||||
|
|
||||||
from calibre.gui2 import NONE, UNDEFINED_QDATETIME, error_dialog
|
from calibre.gui2 import NONE, error_dialog
|
||||||
from calibre.utils.search_query_parser import ParseException
|
from calibre.utils.search_query_parser import ParseException
|
||||||
from calibre.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors
|
from calibre.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors
|
||||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||||
@ -227,20 +227,14 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
elif col in self.custom_columns:
|
elif col in self.custom_columns:
|
||||||
self.headers[col] = self.custom_columns[col]['name']
|
self.headers[col] = self.custom_columns[col]['name']
|
||||||
|
|
||||||
if hasattr(self.db, 'new_api'):
|
self.build_data_convertors()
|
||||||
self.build_new_data_convertors()
|
|
||||||
else:
|
|
||||||
self.build_data_convertors()
|
|
||||||
self.reset()
|
self.reset()
|
||||||
self.database_changed.emit(db)
|
self.database_changed.emit(db)
|
||||||
self.stop_metadata_backup()
|
self.stop_metadata_backup()
|
||||||
self.start_metadata_backup()
|
self.start_metadata_backup()
|
||||||
|
|
||||||
def start_metadata_backup(self):
|
def start_metadata_backup(self):
|
||||||
if hasattr(self.db, 'new_api'):
|
from calibre.db.backup import MetadataBackup
|
||||||
from calibre.db.backup import MetadataBackup
|
|
||||||
else:
|
|
||||||
from calibre.library.caches import MetadataBackup
|
|
||||||
self.metadata_backup = MetadataBackup(self.db)
|
self.metadata_backup = MetadataBackup(self.db)
|
||||||
self.metadata_backup.start()
|
self.metadata_backup.start()
|
||||||
|
|
||||||
@ -315,14 +309,9 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
return ids
|
return ids
|
||||||
|
|
||||||
def delete_books_by_id(self, ids, permanent=False):
|
def delete_books_by_id(self, ids, permanent=False):
|
||||||
if hasattr(self.db, 'new_api'):
|
self.db.new_api.remove_books(ids, permanent=permanent)
|
||||||
self.db.new_api.remove_books(ids, permanent=permanent)
|
self.db.data.books_deleted(tuple(ids))
|
||||||
self.db.data.books_deleted(tuple(ids))
|
self.db.notify('delete', list(ids))
|
||||||
self.db.notify('delete', list(ids))
|
|
||||||
else:
|
|
||||||
for id in ids:
|
|
||||||
self.db.delete_book(id, permanent=permanent, do_clean=False)
|
|
||||||
self.db.clean()
|
|
||||||
self.books_deleted()
|
self.books_deleted()
|
||||||
|
|
||||||
def books_added(self, num):
|
def books_added(self, num):
|
||||||
@ -646,7 +635,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
img = self.default_image
|
img = self.default_image
|
||||||
return img
|
return img
|
||||||
|
|
||||||
def build_new_data_convertors(self):
|
def build_data_convertors(self):
|
||||||
|
|
||||||
def renderer(field, decorator=False):
|
def renderer(field, decorator=False):
|
||||||
idfunc = self.db.id
|
idfunc = self.db.id
|
||||||
@ -762,170 +751,6 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
self.column_to_dc_map = [self.dc[col] for col in self.column_map]
|
self.column_to_dc_map = [self.dc[col] for col in self.column_map]
|
||||||
self.column_to_dc_decorator_map = [self.dc_decorator.get(col, None) for col in self.column_map]
|
self.column_to_dc_decorator_map = [self.dc_decorator.get(col, None) for col in self.column_map]
|
||||||
|
|
||||||
def build_data_convertors(self):
|
|
||||||
def authors(r, idx=-1):
|
|
||||||
au = self.db.data[r][idx]
|
|
||||||
if au:
|
|
||||||
au = [a.strip().replace('|', ',') for a in au.split(',')]
|
|
||||||
return QVariant(' & '.join(au))
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def languages(r, idx=-1):
|
|
||||||
lc = self.db.data[r][idx]
|
|
||||||
if lc:
|
|
||||||
langs = [calibre_langcode_to_name(l.strip()) for l in lc.split(',')]
|
|
||||||
return QVariant(', '.join(langs))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def tags(r, idx=-1):
|
|
||||||
tags = self.db.data[r][idx]
|
|
||||||
if tags:
|
|
||||||
return QVariant(', '.join(sorted(tags.split(','), key=sort_key)))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def series_type(r, idx=-1, siix=-1):
|
|
||||||
series = self.db.data[r][idx]
|
|
||||||
if series:
|
|
||||||
idx = fmt_sidx(self.db.data[r][siix])
|
|
||||||
return QVariant(series + ' [%s]'%idx)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def size(r, idx=-1):
|
|
||||||
size = self.db.data[r][idx]
|
|
||||||
if size:
|
|
||||||
ans = '%.1f'%(float(size)/(1024*1024))
|
|
||||||
if size > 0 and ans == '0.0':
|
|
||||||
ans = '<0.1'
|
|
||||||
return QVariant(ans)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def rating_type(r, idx=-1):
|
|
||||||
r = self.db.data[r][idx]
|
|
||||||
r = r/2.0 if r else 0
|
|
||||||
return QVariant(int(r))
|
|
||||||
|
|
||||||
def datetime_type(r, idx=-1):
|
|
||||||
val = self.db.data[r][idx]
|
|
||||||
if val is not None:
|
|
||||||
return QVariant(QDateTime(as_local_time(val)))
|
|
||||||
else:
|
|
||||||
return QVariant(UNDEFINED_QDATETIME)
|
|
||||||
|
|
||||||
def bool_type(r, idx=-1):
|
|
||||||
return None # displayed using a decorator
|
|
||||||
|
|
||||||
def bool_type_decorator(r, idx=-1, bool_cols_are_tristate=True):
|
|
||||||
val = force_to_bool(self.db.data[r][idx])
|
|
||||||
if val is None:
|
|
||||||
if not bool_cols_are_tristate:
|
|
||||||
return self.bool_no_icon
|
|
||||||
return NONE
|
|
||||||
if val:
|
|
||||||
return self.bool_yes_icon
|
|
||||||
return self.bool_no_icon
|
|
||||||
|
|
||||||
def ondevice_decorator(r, idx=-1):
|
|
||||||
text = self.db.data[r][idx]
|
|
||||||
if text:
|
|
||||||
return self.bool_yes_icon
|
|
||||||
return self.bool_blank_icon
|
|
||||||
|
|
||||||
def text_type(r, mult=None, idx=-1):
|
|
||||||
text = self.db.data[r][idx]
|
|
||||||
if text and mult:
|
|
||||||
jv = mult['list_to_ui']
|
|
||||||
sv = mult['cache_to_list']
|
|
||||||
return QVariant(jv.join(
|
|
||||||
sorted([t.strip() for t in text.split(sv)], key=sort_key)))
|
|
||||||
return QVariant(text)
|
|
||||||
|
|
||||||
def decorated_text_type(r, idx=-1):
|
|
||||||
text = self.db.data[r][idx]
|
|
||||||
if force_to_bool(text) is not None:
|
|
||||||
return None
|
|
||||||
return QVariant(text)
|
|
||||||
|
|
||||||
def number_type(r, idx=-1, fmt=None):
|
|
||||||
if fmt is not None:
|
|
||||||
try:
|
|
||||||
return QVariant(fmt.format(self.db.data[r][idx]))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return QVariant(self.db.data[r][idx])
|
|
||||||
|
|
||||||
self.dc = {
|
|
||||||
'title' : functools.partial(text_type,
|
|
||||||
idx=self.db.field_metadata['title']['rec_index'], mult=None),
|
|
||||||
'authors' : functools.partial(authors,
|
|
||||||
idx=self.db.field_metadata['authors']['rec_index']),
|
|
||||||
'size' : functools.partial(size,
|
|
||||||
idx=self.db.field_metadata['size']['rec_index']),
|
|
||||||
'timestamp': functools.partial(datetime_type,
|
|
||||||
idx=self.db.field_metadata['timestamp']['rec_index']),
|
|
||||||
'pubdate' : functools.partial(datetime_type,
|
|
||||||
idx=self.db.field_metadata['pubdate']['rec_index']),
|
|
||||||
'last_modified': functools.partial(datetime_type,
|
|
||||||
idx=self.db.field_metadata['last_modified']['rec_index']),
|
|
||||||
'rating' : functools.partial(rating_type,
|
|
||||||
idx=self.db.field_metadata['rating']['rec_index']),
|
|
||||||
'publisher': functools.partial(text_type,
|
|
||||||
idx=self.db.field_metadata['publisher']['rec_index'], mult=None),
|
|
||||||
'tags' : functools.partial(tags,
|
|
||||||
idx=self.db.field_metadata['tags']['rec_index']),
|
|
||||||
'series' : functools.partial(series_type,
|
|
||||||
idx=self.db.field_metadata['series']['rec_index'],
|
|
||||||
siix=self.db.field_metadata['series_index']['rec_index']),
|
|
||||||
'ondevice' : functools.partial(text_type,
|
|
||||||
idx=self.db.field_metadata['ondevice']['rec_index'], mult=None),
|
|
||||||
'languages': functools.partial(languages,
|
|
||||||
idx=self.db.field_metadata['languages']['rec_index']),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.dc_decorator = {
|
|
||||||
'ondevice':functools.partial(ondevice_decorator,
|
|
||||||
idx=self.db.field_metadata['ondevice']['rec_index']),
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add the custom columns to the data converters
|
|
||||||
for col in self.custom_columns:
|
|
||||||
idx = self.custom_columns[col]['rec_index']
|
|
||||||
datatype = self.custom_columns[col]['datatype']
|
|
||||||
if datatype in ('text', 'comments', 'composite', 'enumeration'):
|
|
||||||
mult=self.custom_columns[col]['is_multiple']
|
|
||||||
self.dc[col] = functools.partial(text_type, idx=idx, mult=mult)
|
|
||||||
if datatype in ['text', 'composite', 'enumeration'] and not mult:
|
|
||||||
if self.custom_columns[col]['display'].get('use_decorations', False):
|
|
||||||
self.dc[col] = functools.partial(decorated_text_type, idx=idx)
|
|
||||||
self.dc_decorator[col] = functools.partial(
|
|
||||||
bool_type_decorator, idx=idx,
|
|
||||||
bool_cols_are_tristate=
|
|
||||||
self.db.prefs.get('bools_are_tristate'))
|
|
||||||
elif datatype in ('int', 'float'):
|
|
||||||
fmt = self.custom_columns[col]['display'].get('number_format', None)
|
|
||||||
self.dc[col] = functools.partial(number_type, idx=idx, fmt=fmt)
|
|
||||||
elif datatype == 'datetime':
|
|
||||||
self.dc[col] = functools.partial(datetime_type, idx=idx)
|
|
||||||
elif datatype == 'bool':
|
|
||||||
self.dc[col] = functools.partial(bool_type, idx=idx)
|
|
||||||
self.dc_decorator[col] = functools.partial(
|
|
||||||
bool_type_decorator, idx=idx,
|
|
||||||
bool_cols_are_tristate=
|
|
||||||
self.db.prefs.get('bools_are_tristate'))
|
|
||||||
elif datatype == 'rating':
|
|
||||||
self.dc[col] = functools.partial(rating_type, idx=idx)
|
|
||||||
elif datatype == 'series':
|
|
||||||
self.dc[col] = functools.partial(series_type, idx=idx,
|
|
||||||
siix=self.db.field_metadata.cc_series_index_column_for(col))
|
|
||||||
else:
|
|
||||||
print 'What type is this?', col, datatype
|
|
||||||
# build a index column to data converter map, to remove the string lookup in the data loop
|
|
||||||
self.column_to_dc_map = []
|
|
||||||
self.column_to_dc_decorator_map = []
|
|
||||||
for col in self.column_map:
|
|
||||||
self.column_to_dc_map.append(self.dc[col])
|
|
||||||
self.column_to_dc_decorator_map.append(self.dc_decorator.get(col, None))
|
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
col = index.column()
|
col = index.column()
|
||||||
# in obscure cases where custom columns are both edited and added, for a time
|
# in obscure cases where custom columns are both edited and added, for a time
|
||||||
|
@ -544,11 +544,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
self.activateWindow()
|
self.activateWindow()
|
||||||
elif msg.startswith('refreshdb:'):
|
elif msg.startswith('refreshdb:'):
|
||||||
db = self.library_view.model().db
|
db = self.library_view.model().db
|
||||||
if hasattr(db, 'new_api'):
|
db.new_api.reload_from_db()
|
||||||
db.new_api.reload_from_db()
|
self.library_view.model().resort()
|
||||||
self.library_view.model().resort()
|
|
||||||
else:
|
|
||||||
self.library_view.model().refresh()
|
|
||||||
self.library_view.model().research()
|
self.library_view.model().research()
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
self.library_view.model().db.refresh_format_cache()
|
self.library_view.model().db.refresh_format_cache()
|
||||||
|
@ -681,10 +681,7 @@ class BrowseServer(object):
|
|||||||
ids = self.db.get_books_for_category(q, cid)
|
ids = self.db.get_books_for_category(q, cid)
|
||||||
ids = [x for x in ids if x in all_ids]
|
ids = [x for x in ids if x in all_ids]
|
||||||
|
|
||||||
if hasattr(self.db, 'new_api'):
|
items = [self.db.data.tablerow_for_id(x) for x in ids]
|
||||||
items = [self.db.data.tablerow_for_id(x) for x in ids]
|
|
||||||
else:
|
|
||||||
items = [self.db.data._data[x] for x in ids]
|
|
||||||
if category == 'newest':
|
if category == 'newest':
|
||||||
list_sort = 'timestamp'
|
list_sort = 'timestamp'
|
||||||
if dt == 'series':
|
if dt == 'series':
|
||||||
@ -948,10 +945,7 @@ class BrowseServer(object):
|
|||||||
if isbytestring(query):
|
if isbytestring(query):
|
||||||
query = query.decode('UTF-8')
|
query = query.decode('UTF-8')
|
||||||
ids = self.db.search_getting_ids(query.strip(), self.search_restriction)
|
ids = self.db.search_getting_ids(query.strip(), self.search_restriction)
|
||||||
if hasattr(self.db, 'new_api'):
|
items = [self.db.data.tablerow_for_id(x) for x in ids]
|
||||||
items = [self.db.data.tablerow_for_id(x) for x in ids]
|
|
||||||
else:
|
|
||||||
items = [self.db.data._data[x] for x in ids]
|
|
||||||
sort = self.browse_sort_book_list(items, list_sort)
|
sort = self.browse_sort_book_list(items, list_sort)
|
||||||
ids = [x[0] for x in items]
|
ids = [x[0] for x in items]
|
||||||
html = render_book_list(ids, self.opts.url_prefix,
|
html = render_book_list(ids, self.opts.url_prefix,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user