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 = {}
|
||||
for field in FIELDS:
|
||||
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'):
|
||||
x[tf] = as_local_time(x[tf])
|
||||
|
||||
|
@ -190,10 +190,7 @@ class BackupStatus(QDialog): # {{{
|
||||
|
||||
def mark_all_dirty(self):
|
||||
db = self.db()
|
||||
if hasattr(db, 'new_api'):
|
||||
db.new_api.mark_as_dirty(db.new_api.all_book_ids())
|
||||
else:
|
||||
db.dirtied(list(db.data.iterallids()))
|
||||
db.new_api.mark_as_dirty(db.new_api.all_book_ids())
|
||||
|
||||
# }}}
|
||||
|
||||
@ -454,17 +451,14 @@ class ChooseLibraryAction(InterfaceAction):
|
||||
self.gui.library_moved(db.library_path, call_close=False)
|
||||
|
||||
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()
|
||||
m = self.gui.library_view.model()
|
||||
m.stop_metadata_backup()
|
||||
db = m.db
|
||||
db.prefs.disable_setting = True
|
||||
|
||||
if hasattr(db, 'new_api'):
|
||||
d = DBCheckNew(self.gui, db)
|
||||
else:
|
||||
d = DBCheck(self.gui, db)
|
||||
d = DBCheck(self.gui, db)
|
||||
d.start()
|
||||
try:
|
||||
d.conn.close()
|
||||
|
@ -3,22 +3,20 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__license__ = 'GPL v3'
|
||||
|
||||
import os, shutil
|
||||
import os
|
||||
from threading import Thread
|
||||
|
||||
from PyQt4.Qt import (QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QLabel,
|
||||
QPushButton, QDialogButtonBox, QApplication, QTreeWidgetItem,
|
||||
QLineEdit, Qt, QProgressBar, QSize, QTimer, QIcon, QTextEdit,
|
||||
QSplitter, QWidget, pyqtSignal)
|
||||
from PyQt4.Qt import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QLabel, QPushButton,
|
||||
QDialogButtonBox, QApplication, QTreeWidgetItem, QLineEdit, Qt, QSize,
|
||||
QTimer, QIcon, QTextEdit, QSplitter, QWidget, pyqtSignal)
|
||||
|
||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||
from calibre.library.check_library import CheckLibrary, CHECKS
|
||||
from calibre.utils.recycle_bin import delete_file, delete_tree
|
||||
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)
|
||||
|
||||
@ -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):
|
||||
pass
|
||||
|
||||
|
@ -26,8 +26,7 @@ from calibre.utils.icu import sort_key, capitalize
|
||||
from calibre.utils.config import prefs, tweaks
|
||||
from calibre.utils.magick.draw import identify_data
|
||||
from calibre.utils.date import qt_to_dt
|
||||
from calibre.ptempfile import SpooledTemporaryFile
|
||||
from calibre.db import SPOOL_SIZE, _get_next_series_num_for_list
|
||||
from calibre.db import _get_next_series_num_for_list
|
||||
|
||||
def get_cover_data(stream, ext): # {{{
|
||||
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 '
|
||||
'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()
|
||||
|
||||
@ -279,256 +278,6 @@ class MyBlockingBusyNew(QDialog): # {{{
|
||||
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):
|
||||
|
||||
s_r_functions = {'' : lambda x: x,
|
||||
@ -1242,17 +991,11 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
|
||||
pubdate, adddate, do_title_sort, languages, clear_languages,
|
||||
restore_original)
|
||||
|
||||
if hasattr(self.db, 'new_api'):
|
||||
source = self.s_r_sf_itemdata(None)
|
||||
do_sr = source and self.s_r_obj
|
||||
bb = MyBlockingBusyNew(args, self.ids, self.db,
|
||||
getattr(self, 'custom_column_widgets', []),
|
||||
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)
|
||||
source = self.s_r_sf_itemdata(None)
|
||||
do_sr = source and self.s_r_obj
|
||||
bb = MyBlockingBusy(args, self.ids, self.db,
|
||||
getattr(self, 'custom_column_widgets', []),
|
||||
self.do_search_replace, do_sr, parent=self)
|
||||
|
||||
# The metadata backup thread causes database commits
|
||||
# which can slow down bulk editing of large numbers of books
|
||||
|
@ -685,8 +685,6 @@ class GridView(QListView):
|
||||
self.thumbnail_cache.shutdown()
|
||||
|
||||
def set_database(self, newdb, stage=0):
|
||||
if not hasattr(newdb, 'new_api'):
|
||||
return
|
||||
if stage == 0:
|
||||
self.ignore_render_requests.set()
|
||||
try:
|
||||
|
@ -11,7 +11,7 @@ from collections import defaultdict, namedtuple
|
||||
from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
|
||||
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.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors
|
||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||
@ -227,20 +227,14 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
elif col in self.custom_columns:
|
||||
self.headers[col] = self.custom_columns[col]['name']
|
||||
|
||||
if hasattr(self.db, 'new_api'):
|
||||
self.build_new_data_convertors()
|
||||
else:
|
||||
self.build_data_convertors()
|
||||
self.build_data_convertors()
|
||||
self.reset()
|
||||
self.database_changed.emit(db)
|
||||
self.stop_metadata_backup()
|
||||
self.start_metadata_backup()
|
||||
|
||||
def start_metadata_backup(self):
|
||||
if hasattr(self.db, 'new_api'):
|
||||
from calibre.db.backup import MetadataBackup
|
||||
else:
|
||||
from calibre.library.caches import MetadataBackup
|
||||
from calibre.db.backup import MetadataBackup
|
||||
self.metadata_backup = MetadataBackup(self.db)
|
||||
self.metadata_backup.start()
|
||||
|
||||
@ -315,14 +309,9 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
return ids
|
||||
|
||||
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.data.books_deleted(tuple(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.db.new_api.remove_books(ids, permanent=permanent)
|
||||
self.db.data.books_deleted(tuple(ids))
|
||||
self.db.notify('delete', list(ids))
|
||||
self.books_deleted()
|
||||
|
||||
def books_added(self, num):
|
||||
@ -646,7 +635,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
img = self.default_image
|
||||
return img
|
||||
|
||||
def build_new_data_convertors(self):
|
||||
def build_data_convertors(self):
|
||||
|
||||
def renderer(field, decorator=False):
|
||||
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_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):
|
||||
col = index.column()
|
||||
# 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()
|
||||
elif msg.startswith('refreshdb:'):
|
||||
db = self.library_view.model().db
|
||||
if hasattr(db, 'new_api'):
|
||||
db.new_api.reload_from_db()
|
||||
self.library_view.model().resort()
|
||||
else:
|
||||
self.library_view.model().refresh()
|
||||
db.new_api.reload_from_db()
|
||||
self.library_view.model().resort()
|
||||
self.library_view.model().research()
|
||||
self.tags_view.recount()
|
||||
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 = [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]
|
||||
else:
|
||||
items = [self.db.data._data[x] for x in ids]
|
||||
items = [self.db.data.tablerow_for_id(x) for x in ids]
|
||||
if category == 'newest':
|
||||
list_sort = 'timestamp'
|
||||
if dt == 'series':
|
||||
@ -948,10 +945,7 @@ class BrowseServer(object):
|
||||
if isbytestring(query):
|
||||
query = query.decode('UTF-8')
|
||||
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]
|
||||
else:
|
||||
items = [self.db.data._data[x] for x in ids]
|
||||
items = [self.db.data.tablerow_for_id(x) for x in ids]
|
||||
sort = self.browse_sort_book_list(items, list_sort)
|
||||
ids = [x[0] for x in items]
|
||||
html = render_book_list(ids, self.opts.url_prefix,
|
||||
|
Loading…
x
Reference in New Issue
Block a user