mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Allow configuring the metadata fields displayed in the popup book details window. To configure, simply click the 'Configure' link at the bottom of the window.
This commit is contained in:
parent
9daf8f7f7e
commit
a6e8d0eb71
@ -471,6 +471,7 @@ class DB(object):
|
||||
('uuid', False), ('comments', True), ('id', False), ('pubdate', False),
|
||||
('last_modified', False), ('size', False), ('languages', False),
|
||||
]
|
||||
defs['popup_book_display_fields'] = [('title', True)] + [(f[0], True) for f in defs['book_display_fields'] if f[0] != 'title']
|
||||
defs['qv_display_fields'] = [('title', True), ('authors', True), ('series', True)]
|
||||
defs['virtual_libraries'] = {}
|
||||
defs['virtual_lib_on_startup'] = defs['cs_virtual_lib_on_startup'] = ''
|
||||
|
@ -87,9 +87,14 @@ def init_manage_action(ac, field, value):
|
||||
return ac
|
||||
|
||||
|
||||
def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=None): # {{{
|
||||
table, comment_fields = (render_data_func or render_data)(mi, all_fields=all_fields,
|
||||
use_roman_numbers=config['use_roman_numerals_for_series_number'])
|
||||
def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=None, pref_name='book_display_fields'): # {{{
|
||||
func = render_data_func or render_data
|
||||
try:
|
||||
table, comment_fields = func(mi, all_fields=all_fields,
|
||||
use_roman_numbers=config['use_roman_numerals_for_series_number'], pref_name=pref_name)
|
||||
except TypeError:
|
||||
table, comment_fields = func(mi, all_fields=all_fields,
|
||||
use_roman_numbers=config['use_roman_numerals_for_series_number'])
|
||||
|
||||
def color_to_string(col):
|
||||
ans = '#000000'
|
||||
@ -145,29 +150,27 @@ def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=No
|
||||
return ans
|
||||
|
||||
|
||||
def get_field_list(fm, use_defaults=False):
|
||||
def get_field_list(fm, use_defaults=False, pref_name='book_display_fields'):
|
||||
from calibre.gui2.ui import get_gui
|
||||
db = get_gui().current_db
|
||||
if use_defaults:
|
||||
src = db.prefs.defaults
|
||||
else:
|
||||
old_val = gprefs.get('book_display_fields', None)
|
||||
if old_val is not None and not db.prefs.has_setting(
|
||||
'book_display_fields'):
|
||||
old_val = gprefs.get(pref_name, None)
|
||||
if old_val is not None and not db.prefs.has_setting(pref_name):
|
||||
src = gprefs
|
||||
else:
|
||||
src = db.prefs
|
||||
fieldlist = list(src['book_display_fields'])
|
||||
names = frozenset([x[0] for x in fieldlist])
|
||||
for field in fm.displayable_field_keys():
|
||||
if field not in names:
|
||||
fieldlist.append((field, True))
|
||||
fieldlist = list(src[pref_name])
|
||||
names = frozenset(x[0] for x in fieldlist)
|
||||
available = frozenset(fm.displayable_field_keys())
|
||||
for field in available - names:
|
||||
fieldlist.append((field, True))
|
||||
return [(f, d) for f, d in fieldlist if f in available]
|
||||
|
||||
|
||||
def render_data(mi, use_roman_numbers=True, all_fields=False):
|
||||
field_list = get_field_list(getattr(mi, 'field_metadata', field_metadata))
|
||||
def render_data(mi, use_roman_numbers=True, all_fields=False, pref_name='book_display_fields'):
|
||||
field_list = get_field_list(getattr(mi, 'field_metadata', field_metadata), pref_name=pref_name)
|
||||
field_list = [(x, all_fields or display) for x, display in field_list]
|
||||
return mi_to_html(mi, field_list=field_list, use_roman_numbers=use_roman_numbers, rtl=is_rtl(),
|
||||
rating_font=rating_font(), default_author_link=default_author_link())
|
||||
|
@ -1,21 +1,71 @@
|
||||
#!/usr/bin/env python2
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
# License: GPLv3 Copyright: 2008, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.Qt import (
|
||||
QCoreApplication, QModelIndex, QTimer, Qt, pyqtSignal, QWidget,
|
||||
QGridLayout, QDialog, QPixmap, QSize, QPalette, QShortcut, QKeySequence,
|
||||
QSplitter, QVBoxLayout, QCheckBox, QPushButton, QIcon, QBrush)
|
||||
QBrush, QCheckBox, QCoreApplication, QDialog, QGridLayout, QHBoxLayout, QIcon,
|
||||
QKeySequence, QLabel, QListView, QModelIndex, QPalette, QPixmap, QPushButton,
|
||||
QShortcut, QSize, QSplitter, Qt, QTimer, QToolButton, QVBoxLayout, QWidget,
|
||||
pyqtSignal
|
||||
)
|
||||
from PyQt5.QtWebKitWidgets import QWebView
|
||||
|
||||
from calibre.gui2 import gprefs, NO_URL_FORMATTING
|
||||
from calibre import fit_image
|
||||
from calibre.gui2.book_details import render_html, details_context_menu_event, css
|
||||
from calibre.gui2 import NO_URL_FORMATTING, gprefs
|
||||
from calibre.gui2.book_details import css, details_context_menu_event, render_html
|
||||
from calibre.gui2.ui import get_gui
|
||||
from calibre.gui2.widgets import CoverView
|
||||
from calibre.gui2.widgets2 import Dialog
|
||||
|
||||
|
||||
class Configure(Dialog):
|
||||
|
||||
def __init__(self, db, parent=None):
|
||||
self.db = db
|
||||
Dialog.__init__(self, _('Configure the book details window'), 'book-details-popup-conf', parent)
|
||||
|
||||
def setup_ui(self):
|
||||
from calibre.gui2.preferences.look_feel import DisplayedFields, move_field_up, move_field_down
|
||||
self.l = QVBoxLayout(self)
|
||||
self.field_display_order = fdo = QListView(self)
|
||||
self.model = DisplayedFields(self.db, fdo, pref_name='popup_book_display_fields')
|
||||
self.model.initialize()
|
||||
fdo.setModel(self.model)
|
||||
fdo.setAlternatingRowColors(True)
|
||||
del self.db
|
||||
self.l.addWidget(QLabel('Select displayed metadata'))
|
||||
h = QHBoxLayout()
|
||||
h.addWidget(fdo)
|
||||
v = QVBoxLayout()
|
||||
self.mub = b = QToolButton(self)
|
||||
b.clicked.connect(partial(move_field_up, fdo, self.model))
|
||||
b.setIcon(QIcon(I('arrow-up.png')))
|
||||
b.setToolTip(_('Move the selected field up'))
|
||||
v.addWidget(b), v.addStretch(10)
|
||||
self.mud = b = QToolButton(self)
|
||||
b.setIcon(QIcon(I('arrow-down.png')))
|
||||
b.setToolTip(_('Move the selected field down'))
|
||||
b.clicked.connect(partial(move_field_down, fdo, self.model))
|
||||
v.addWidget(b)
|
||||
h.addLayout(v)
|
||||
|
||||
self.l.addLayout(h)
|
||||
self.l.addWidget(QLabel('<p>' + _(
|
||||
'Note that <b>comments</b> will always be displayed at the end, regardless of the order you assign here')))
|
||||
|
||||
b = self.bb.addButton(_('Restore &defaults'), self.bb.ActionRole)
|
||||
b.clicked.connect(self.restore_defaults)
|
||||
self.l.addWidget(self.bb)
|
||||
self.setMinimumHeight(500)
|
||||
|
||||
def restore_defaults(self):
|
||||
self.model.initialize(use_defaults=True)
|
||||
|
||||
def accept(self):
|
||||
self.model.commit()
|
||||
return Dialog.accept(self)
|
||||
|
||||
|
||||
class Details(QWebView):
|
||||
@ -74,7 +124,11 @@ class BookInfo(QDialog):
|
||||
|
||||
self.fit_cover = QCheckBox(_('Fit &cover within view'), self)
|
||||
self.fit_cover.setChecked(gprefs.get('book_info_dialog_fit_cover', True))
|
||||
l2.addWidget(self.fit_cover, l2.rowCount(), 0, 1, -1)
|
||||
l2.addWidget(self.fit_cover, l2.rowCount(), 0, 1, 1)
|
||||
self.clabel = QLabel('<div style="text-align: right"><a href="calibre:conf" title="{}" style="text-decoration: none">{}</a>'.format(
|
||||
_('Configure this view'), _('Configure')))
|
||||
self.clabel.linkActivated.connect(self.configure)
|
||||
l2.addWidget(self.clabel, l2.rowCount() - 1, 1, 1, 1)
|
||||
self.previous_button = QPushButton(QIcon(I('previous.png')), _('&Previous'), self)
|
||||
self.previous_button.clicked.connect(self.previous)
|
||||
l2.addWidget(self.previous_button, l2.rowCount(), 0)
|
||||
@ -108,6 +162,14 @@ class BookInfo(QDialog):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def configure(self):
|
||||
d = Configure(get_gui().current_db, self)
|
||||
if d.exec_() == d.Accepted:
|
||||
if self.current_row is not None:
|
||||
mi = self.view.model().get_book_display_info(self.current_row)
|
||||
if mi is not None:
|
||||
self.refresh(self.current_row, mi=mi)
|
||||
|
||||
def link_clicked(self, qurl):
|
||||
link = unicode(qurl.toString(NO_URL_FORMATTING))
|
||||
self.link_delegate(link)
|
||||
@ -212,8 +274,20 @@ class BookInfo(QDialog):
|
||||
dpr = self.devicePixelRatio()
|
||||
self.cover_pixmap.setDevicePixelRatio(dpr)
|
||||
self.resize_cover()
|
||||
html = render_html(mi, self.css, True, self, all_fields=True)
|
||||
html = render_html(mi, self.css, True, self, pref_name='popup_book_display_fields')
|
||||
self.details.setHtml(html)
|
||||
self.marked = mi.marked
|
||||
self.cover.setBackgroundBrush(self.marked_brush if mi.marked else self.normal_brush)
|
||||
self.update_cover_tooltip()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from calibre.gui2 import Application
|
||||
from calibre.library import db
|
||||
app = Application([])
|
||||
app.current_db = db()
|
||||
get_gui.ans = app
|
||||
d = Configure(app.current_db)
|
||||
d.exec_()
|
||||
del d
|
||||
del app
|
||||
|
@ -217,18 +217,20 @@ class IdLinksEditor(Dialog):
|
||||
|
||||
class DisplayedFields(QAbstractListModel): # {{{
|
||||
|
||||
def __init__(self, db, parent=None):
|
||||
def __init__(self, db, parent=None, pref_name=None):
|
||||
self.pref_name = pref_name or 'book_display_fields'
|
||||
QAbstractListModel.__init__(self, parent)
|
||||
|
||||
self.fields = []
|
||||
self.db = db
|
||||
self.changed = False
|
||||
|
||||
def get_field_list(self, use_defaults=False):
|
||||
return get_field_list(self.db.field_metadata, use_defaults=use_defaults, pref_name=self.pref_name)
|
||||
|
||||
def initialize(self, use_defaults=False):
|
||||
self.beginResetModel()
|
||||
self.fields = [[x[0], x[1]] for x in
|
||||
get_field_list(self.db.field_metadata,
|
||||
use_defaults=use_defaults)]
|
||||
self.fields = [[x[0], x[1]] for x in self.get_field_list(use_defaults=use_defaults)]
|
||||
self.endResetModel()
|
||||
self.changed = True
|
||||
|
||||
@ -273,7 +275,7 @@ class DisplayedFields(QAbstractListModel): # {{{
|
||||
|
||||
def commit(self):
|
||||
if self.changed:
|
||||
self.db.new_api.set_pref('book_display_fields', self.fields)
|
||||
self.db.new_api.set_pref(self.pref_name, self.fields)
|
||||
|
||||
def move(self, idx, delta):
|
||||
row = idx.row() + delta
|
||||
@ -287,6 +289,26 @@ class DisplayedFields(QAbstractListModel): # {{{
|
||||
self.changed = True
|
||||
return idx
|
||||
|
||||
|
||||
def move_field_up(widget, model):
|
||||
idx = widget.currentIndex()
|
||||
if idx.isValid():
|
||||
idx = model.move(idx, -1)
|
||||
if idx is not None:
|
||||
sm = widget.selectionModel()
|
||||
sm.select(idx, sm.ClearAndSelect)
|
||||
widget.setCurrentIndex(idx)
|
||||
|
||||
|
||||
def move_field_down(widget, model):
|
||||
idx = widget.currentIndex()
|
||||
if idx.isValid():
|
||||
idx = model.move(idx, 1)
|
||||
if idx is not None:
|
||||
sm = widget.selectionModel()
|
||||
sm.select(idx, sm.ClearAndSelect)
|
||||
widget.setCurrentIndex(idx)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -478,18 +500,18 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.field_display_order)
|
||||
self.display_model.dataChanged.connect(self.changed_signal)
|
||||
self.field_display_order.setModel(self.display_model)
|
||||
self.df_up_button.clicked.connect(partial(self.move_field_up,
|
||||
self.df_up_button.clicked.connect(partial(move_field_up,
|
||||
self.field_display_order, self.display_model))
|
||||
self.df_down_button.clicked.connect(partial(self.move_field_down,
|
||||
self.df_down_button.clicked.connect(partial(move_field_down,
|
||||
self.field_display_order, self.display_model))
|
||||
|
||||
self.qv_display_model = QVDisplayedFields(self.gui.current_db,
|
||||
self.qv_display_order)
|
||||
self.qv_display_model.dataChanged.connect(self.changed_signal)
|
||||
self.qv_display_order.setModel(self.qv_display_model)
|
||||
self.qv_up_button.clicked.connect(partial(self.move_field_up,
|
||||
self.qv_up_button.clicked.connect(partial(move_field_up,
|
||||
self.qv_display_order, self.qv_display_model))
|
||||
self.qv_down_button.clicked.connect(partial(self.move_field_down,
|
||||
self.qv_down_button.clicked.connect(partial(move_field_down,
|
||||
self.qv_display_order, self.qv_display_model))
|
||||
|
||||
self.edit_rules = EditRules(self.tabWidget)
|
||||
@ -702,24 +724,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.font_display.setText(name +
|
||||
' [%dpt]'%fi.pointSize())
|
||||
|
||||
def move_field_up(self, widget, model):
|
||||
idx = widget.currentIndex()
|
||||
if idx.isValid():
|
||||
idx = model.move(idx, -1)
|
||||
if idx is not None:
|
||||
sm = widget.selectionModel()
|
||||
sm.select(idx, sm.ClearAndSelect)
|
||||
widget.setCurrentIndex(idx)
|
||||
|
||||
def move_field_down(self, widget, model):
|
||||
idx = widget.currentIndex()
|
||||
if idx.isValid():
|
||||
idx = model.move(idx, 1)
|
||||
if idx is not None:
|
||||
sm = widget.selectionModel()
|
||||
sm.select(idx, sm.ClearAndSelect)
|
||||
widget.setCurrentIndex(idx)
|
||||
|
||||
def change_font(self, *args):
|
||||
fd = QFontDialog(self.build_font_obj(), self)
|
||||
if fd.exec_() == fd.Accepted:
|
||||
|
@ -87,11 +87,8 @@ class Listener(Thread): # {{{
|
||||
# }}}
|
||||
|
||||
|
||||
_gui = None
|
||||
|
||||
|
||||
def get_gui():
|
||||
return _gui
|
||||
return getattr(get_gui, 'ans', None)
|
||||
|
||||
|
||||
def add_quick_start_guide(library_view, refresh_cover_browser=None):
|
||||
@ -138,7 +135,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
shutting_down = False
|
||||
|
||||
def __init__(self, opts, parent=None, gui_debug=None):
|
||||
global _gui
|
||||
MainWindow.__init__(self, opts, parent=parent, disable_automatic_gc=True)
|
||||
self.setWindowIcon(QApplication.instance().windowIcon())
|
||||
self.jobs_pointer = Pointer(self)
|
||||
@ -147,7 +143,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
self.proceed_question = ProceedQuestion(self)
|
||||
self.job_error_dialog = JobError(self)
|
||||
self.keyboard = Manager(self)
|
||||
_gui = self
|
||||
get_gui.ans = self
|
||||
self.opts = opts
|
||||
self.device_connected = None
|
||||
self.gui_debug = gui_debug
|
||||
|
@ -93,7 +93,7 @@ class Metadata(QWebView): # {{{
|
||||
from calibre.gui2.book_details import render_html, css
|
||||
from calibre.ebooks.metadata.book.render import mi_to_html
|
||||
|
||||
def render_data(mi, use_roman_numbers=True, all_fields=False):
|
||||
def render_data(mi, use_roman_numbers=True, all_fields=False, pref_name='book_display_fields'):
|
||||
return mi_to_html(
|
||||
mi, use_roman_numbers=use_roman_numbers, rating_font=rating_font(), rtl=is_rtl(),
|
||||
default_author_link=default_author_link()
|
||||
|
Loading…
x
Reference in New Issue
Block a user