mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1920733 [Quickview: Slight lag when viewing composite column in quickview](https://bugs.launchpad.net/calibre/+bug/1920733)
This commit is contained in:
commit
4bce133294
@ -12,7 +12,7 @@ from functools import partial
|
|||||||
from qt.core import (
|
from qt.core import (
|
||||||
Qt, QDialog, QAbstractItemView, QTableWidgetItem, QIcon, QListWidgetItem,
|
Qt, QDialog, QAbstractItemView, QTableWidgetItem, QIcon, QListWidgetItem,
|
||||||
QCoreApplication, QEvent, QObject, QApplication, pyqtSignal, QByteArray, QMenu,
|
QCoreApplication, QEvent, QObject, QApplication, pyqtSignal, QByteArray, QMenu,
|
||||||
QShortcut)
|
QShortcut, QTimer)
|
||||||
|
|
||||||
from calibre.customize.ui import find_plugin
|
from calibre.customize.ui import find_plugin
|
||||||
from calibre.gui2 import gprefs
|
from calibre.gui2 import gprefs
|
||||||
@ -29,13 +29,18 @@ class TableItem(QTableWidgetItem):
|
|||||||
A QTableWidgetItem that sorts on a separate string and uses ICU rules
|
A QTableWidgetItem that sorts on a separate string and uses ICU rules
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, val, sort, idx=0):
|
def __init__(self, getter=None):
|
||||||
self.sort = sort
|
self.val = ''
|
||||||
self.sort_idx = idx
|
self.sort = None
|
||||||
QTableWidgetItem.__init__(self, val)
|
self.sort_idx = 0
|
||||||
|
self.getter = getter
|
||||||
|
self.resolved = False
|
||||||
|
QTableWidgetItem.__init__(self, '')
|
||||||
self.setFlags(Qt.ItemFlag.ItemIsEnabled|Qt.ItemFlag.ItemIsSelectable)
|
self.setFlags(Qt.ItemFlag.ItemIsEnabled|Qt.ItemFlag.ItemIsSelectable)
|
||||||
|
|
||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
|
self.get_data()
|
||||||
|
other.get_data()
|
||||||
if self.sort is None:
|
if self.sort is None:
|
||||||
if other.sort is None:
|
if other.sort is None:
|
||||||
# None == None therefore >=
|
# None == None therefore >=
|
||||||
@ -59,6 +64,8 @@ class TableItem(QTableWidgetItem):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
|
self.get_data()
|
||||||
|
other.get_data()
|
||||||
if self.sort is None:
|
if self.sort is None:
|
||||||
if other.sort is None:
|
if other.sort is None:
|
||||||
# None == None therefore not <
|
# None == None therefore not <
|
||||||
@ -81,6 +88,17 @@ class TableItem(QTableWidgetItem):
|
|||||||
return self.sort_idx < other.sort_idx
|
return self.sort_idx < other.sort_idx
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
if not self.resolved and self.getter:
|
||||||
|
self.resolved = True
|
||||||
|
self.val, self.sort, self.sort_idx = self.getter()
|
||||||
|
|
||||||
|
def data(self, role):
|
||||||
|
self.get_data()
|
||||||
|
if role == Qt.DisplayRole:
|
||||||
|
return self.val
|
||||||
|
return QTableWidgetItem.data(self, role)
|
||||||
|
|
||||||
|
|
||||||
IN_WIDGET_ITEMS = 0
|
IN_WIDGET_ITEMS = 0
|
||||||
IN_WIDGET_BOOKS = 1
|
IN_WIDGET_BOOKS = 1
|
||||||
@ -228,7 +246,7 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
# resizeRowsToContents can word wrap long cell contents, creating
|
# resizeRowsToContents can word wrap long cell contents, creating
|
||||||
# double-high rows
|
# double-high rows
|
||||||
self.books_table.setRowCount(1)
|
self.books_table.setRowCount(1)
|
||||||
self.books_table.setItem(0, 0, TableItem('A', ''))
|
self.books_table.setItem(0, 0, TableItem())
|
||||||
self.books_table.resizeRowsToContents()
|
self.books_table.resizeRowsToContents()
|
||||||
self.books_table_row_height = self.books_table.rowHeight(0)
|
self.books_table_row_height = self.books_table.rowHeight(0)
|
||||||
self.books_table.setRowCount(0)
|
self.books_table.setRowCount(0)
|
||||||
@ -236,10 +254,13 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
# Add the data
|
# Add the data
|
||||||
self.refresh(row)
|
self.refresh(row)
|
||||||
|
|
||||||
self.view.clicked.connect(self.slave)
|
self.slave_timers = [QTimer(self), QTimer(self), QTimer(self)]
|
||||||
self.view.selectionModel().currentColumnChanged.connect(self.column_slave)
|
self.view.clicked.connect(partial(self.delayed_slave, func=self.slave, dex=0))
|
||||||
|
self.view.selectionModel().currentColumnChanged.connect(
|
||||||
|
partial(self.delayed_slave, func=self.column_slave, dex=1))
|
||||||
QCoreApplication.instance().aboutToQuit.connect(self.save_state)
|
QCoreApplication.instance().aboutToQuit.connect(self.save_state)
|
||||||
self.view.model().new_bookdisplay_data.connect(self.book_was_changed)
|
self.view.model().new_bookdisplay_data.connect(
|
||||||
|
partial(self.delayed_slave, func=self.book_was_changed, dex=2))
|
||||||
|
|
||||||
self.close_button.setDefault(False)
|
self.close_button.setDefault(False)
|
||||||
self.close_button_tooltip = _('The Quickview shortcut ({0}) shows/hides the Quickview panel')
|
self.close_button_tooltip = _('The Quickview shortcut ({0}) shows/hides the Quickview panel')
|
||||||
@ -285,6 +306,14 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
self.close_button.setToolTip(_('Alternate shortcut: ') +
|
self.close_button.setToolTip(_('Alternate shortcut: ') +
|
||||||
toggle_shortcut.toString())
|
toggle_shortcut.toString())
|
||||||
|
|
||||||
|
def delayed_slave(self, current, func=None, dex=None):
|
||||||
|
self.slave_timers[dex].stop()
|
||||||
|
t = self.slave_timers[dex] = QTimer(self)
|
||||||
|
t.timeout.connect(partial(func, current))
|
||||||
|
t.setSingleShot(True)
|
||||||
|
t.setInterval(200)
|
||||||
|
t.start()
|
||||||
|
|
||||||
def item_doubleclicked(self, item):
|
def item_doubleclicked(self, item):
|
||||||
tb = self.gui.stack.tb_widget
|
tb = self.gui.stack.tb_widget
|
||||||
tb.set_focus_to_find_box()
|
tb.set_focus_to_find_box()
|
||||||
@ -513,7 +542,7 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
self.items.clear()
|
self.items.clear()
|
||||||
self.books_table.setRowCount(0)
|
self.books_table.setRowCount(0)
|
||||||
|
|
||||||
mi = self.db.get_metadata(book_id, index_is_id=True, get_user_categories=False)
|
mi = self.db.new_api.get_proxy_metadata(book_id)
|
||||||
vals = mi.get(key, None)
|
vals = mi.get(key, None)
|
||||||
if self.fm[key]['datatype'] == 'composite' and self.fm[key]['is_multiple']:
|
if self.fm[key]['datatype'] == 'composite' and self.fm[key]['is_multiple']:
|
||||||
sep = self.fm[key]['is_multiple'].get('cache_to_list', ',')
|
sep = self.fm[key]['is_multiple'].get('cache_to_list', ',')
|
||||||
@ -605,47 +634,12 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
'which also changes the selected book.'
|
'which also changes the selected book.'
|
||||||
) + '</p>')
|
) + '</p>')
|
||||||
for row, b in enumerate(books):
|
for row, b in enumerate(books):
|
||||||
mi = self.db.new_api.get_proxy_metadata(b)
|
|
||||||
for col in self.column_order:
|
for col in self.column_order:
|
||||||
try:
|
a = TableItem(partial(self.get_item_data, b, col))
|
||||||
if col == 'title':
|
if col == 'title':
|
||||||
a = TableItem(mi.title, mi.title_sort)
|
if b == self.current_book_id:
|
||||||
if b == self.current_book_id:
|
select_item = a
|
||||||
select_item = a
|
# The data is supplied on demand when the item is displayed
|
||||||
elif col == 'authors':
|
|
||||||
a = TableItem(' & '.join(mi.authors), mi.author_sort)
|
|
||||||
elif col == 'series':
|
|
||||||
series = mi.format_field('series')[1]
|
|
||||||
if series is None:
|
|
||||||
a = TableItem('', '', 0)
|
|
||||||
else:
|
|
||||||
a = TableItem(series, mi.series, mi.series_index)
|
|
||||||
elif col == 'size':
|
|
||||||
v = mi.get('book_size')
|
|
||||||
if v is not None:
|
|
||||||
a = TableItem('{:n}'.format(v), v)
|
|
||||||
a.setTextAlignment(Qt.AlignmentFlag.AlignRight)
|
|
||||||
else:
|
|
||||||
a = TableItem(' ', None)
|
|
||||||
elif self.fm[col]['datatype'] == 'series':
|
|
||||||
v = mi.format_field(col)[1]
|
|
||||||
a = TableItem(v, mi.get(col), mi.get(col+'_index'))
|
|
||||||
elif self.fm[col]['datatype'] == 'datetime':
|
|
||||||
v = mi.format_field(col)[1]
|
|
||||||
d = mi.get(col)
|
|
||||||
if d is None:
|
|
||||||
d = UNDEFINED_DATE
|
|
||||||
a = TableItem(v, timestampfromdt(d))
|
|
||||||
elif self.fm[col]['datatype'] in ('float', 'int'):
|
|
||||||
v = mi.format_field(col)[1]
|
|
||||||
sort_val = mi.get(col)
|
|
||||||
a = TableItem(v, sort_val)
|
|
||||||
else:
|
|
||||||
v = mi.format_field(col)[1]
|
|
||||||
a = TableItem(v, v)
|
|
||||||
except:
|
|
||||||
traceback.print_exc()
|
|
||||||
a = TableItem(_('Something went wrong while filling in the table'), '')
|
|
||||||
a.setData(Qt.ItemDataRole.UserRole, b)
|
a.setData(Qt.ItemDataRole.UserRole, b)
|
||||||
a.setToolTip(tt)
|
a.setToolTip(tt)
|
||||||
self.books_table.setItem(row, self.key_to_table_widget_column(col), a)
|
self.books_table.setItem(row, self.key_to_table_widget_column(col), a)
|
||||||
@ -657,6 +651,45 @@ class Quickview(QDialog, Ui_Quickview):
|
|||||||
self.books_table.scrollToItem(select_item, QAbstractItemView.ScrollHint.PositionAtCenter)
|
self.books_table.scrollToItem(select_item, QAbstractItemView.ScrollHint.PositionAtCenter)
|
||||||
self.set_search_text(sv)
|
self.set_search_text(sv)
|
||||||
|
|
||||||
|
def get_item_data(self, book_id, col):
|
||||||
|
mi = self.db.new_api.get_proxy_metadata(book_id)
|
||||||
|
try:
|
||||||
|
if col == 'title':
|
||||||
|
return (mi.title, mi.title_sort, 0)
|
||||||
|
elif col == 'authors':
|
||||||
|
return (' & '.join(mi.authors), mi.author_sort, 0)
|
||||||
|
elif col == 'series':
|
||||||
|
series = mi.format_field('series')[1]
|
||||||
|
if series is None:
|
||||||
|
return ('', None, 0)
|
||||||
|
else:
|
||||||
|
return (series, mi.series, mi.series_index)
|
||||||
|
elif col == 'size':
|
||||||
|
v = mi.get('book_size')
|
||||||
|
if v is not None:
|
||||||
|
return ('{:n}'.format(v), v, 0)
|
||||||
|
else:
|
||||||
|
return ('', None, 0)
|
||||||
|
elif self.fm[col]['datatype'] == 'series':
|
||||||
|
v = mi.format_field(col)[1]
|
||||||
|
return (v, mi.get(col), mi.get(col+'_index'))
|
||||||
|
elif self.fm[col]['datatype'] == 'datetime':
|
||||||
|
v = mi.format_field(col)[1]
|
||||||
|
d = mi.get(col)
|
||||||
|
if d is None:
|
||||||
|
d = UNDEFINED_DATE
|
||||||
|
return (v, timestampfromdt(d), 0)
|
||||||
|
elif self.fm[col]['datatype'] in ('float', 'int'):
|
||||||
|
v = mi.format_field(col)[1]
|
||||||
|
sort_val = mi.get(col)
|
||||||
|
return (v, sort_val, 0)
|
||||||
|
else:
|
||||||
|
v = mi.format_field(col)[1]
|
||||||
|
return (v, v, 0)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
return (_('Something went wrong while filling in the table'), '', 0)
|
||||||
|
|
||||||
# Deal with sizing the table columns. Done here because the numbers are not
|
# Deal with sizing the table columns. Done here because the numbers are not
|
||||||
# correct until the first paint.
|
# correct until the first paint.
|
||||||
def resizeEvent(self, *args):
|
def resizeEvent(self, *args):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user