mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make the cover grid customizable
This commit is contained in:
parent
5737ead466
commit
0541a118e6
@ -111,6 +111,10 @@ defs['tags_browser_category_icons'] = {}
|
|||||||
defs['cover_browser_reflections'] = True
|
defs['cover_browser_reflections'] = True
|
||||||
defs['extra_row_spacing'] = 0
|
defs['extra_row_spacing'] = 0
|
||||||
defs['refresh_book_list_on_bulk_edit'] = True
|
defs['refresh_book_list_on_bulk_edit'] = True
|
||||||
|
defs['cover_grid_width'] = 0
|
||||||
|
defs['cover_grid_height'] = 0
|
||||||
|
defs['cover_grid_color'] = (80, 80, 80)
|
||||||
|
defs['cover_grid_cache_size'] = 200
|
||||||
del defs
|
del defs
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -20,8 +20,11 @@ from PyQt4.Qt import (
|
|||||||
QUrl, QDrag, QPoint, QPainter, QRect)
|
QUrl, QDrag, QPoint, QPainter, QRect)
|
||||||
|
|
||||||
from calibre import fit_image
|
from calibre import fit_image
|
||||||
|
from calibre.gui2 import gprefs
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
|
|
||||||
|
CM_TO_INCH = 0.393701
|
||||||
|
|
||||||
# Drag 'n Drop {{{
|
# Drag 'n Drop {{{
|
||||||
def dragMoveEvent(self, event):
|
def dragMoveEvent(self, event):
|
||||||
event.acceptProposedAction()
|
event.acceptProposedAction()
|
||||||
@ -305,15 +308,39 @@ class CoverCache(dict):
|
|||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return id(self)
|
return id(self)
|
||||||
|
|
||||||
|
def set_limit(self, limit):
|
||||||
|
with self.lock:
|
||||||
|
self.limit = limit
|
||||||
|
if len(self.items) > self.limit:
|
||||||
|
extra = len(self.items) - self.limit
|
||||||
|
remove = tuple(self.iterkeys())[:extra]
|
||||||
|
for k in remove:
|
||||||
|
del self.items[k]
|
||||||
|
|
||||||
class CoverDelegate(QStyledItemDelegate):
|
class CoverDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
def __init__(self, parent, width, height):
|
def __init__(self, parent):
|
||||||
super(CoverDelegate, self).__init__(parent)
|
super(CoverDelegate, self).__init__(parent)
|
||||||
|
self.set_dimensions()
|
||||||
|
self.cover_cache = CoverCache(limit=gprefs['cover_grid_cache_size'])
|
||||||
|
self.render_queue = Queue()
|
||||||
|
|
||||||
|
def set_dimensions(self):
|
||||||
|
width = self.original_width = gprefs['cover_grid_width']
|
||||||
|
height = self.original_height = gprefs['cover_grid_height']
|
||||||
|
|
||||||
|
if height < 0.1:
|
||||||
|
height = max(185, QApplication.instance().desktop().availableGeometry(self.parent()).height() / 5.0)
|
||||||
|
else:
|
||||||
|
height *= self.parent().logicalDpiY() * CM_TO_INCH
|
||||||
|
|
||||||
|
if width < 0.1:
|
||||||
|
width = 0.75 * height
|
||||||
|
else:
|
||||||
|
width *= self.parent().logicalDpiX() * CM_TO_INCH
|
||||||
self.cover_size = QSize(width, height)
|
self.cover_size = QSize(width, height)
|
||||||
self.item_size = self.cover_size + QSize(8, 8)
|
self.item_size = self.cover_size + QSize(8, 8)
|
||||||
self.spacing = max(10, min(50, int(0.1 * width)))
|
self.spacing = max(10, min(50, int(0.1 * width)))
|
||||||
self.cover_cache = CoverCache()
|
|
||||||
self.render_queue = Queue()
|
|
||||||
|
|
||||||
def sizeHint(self, option, index):
|
def sizeHint(self, option, index):
|
||||||
return self.item_size
|
return self.item_size
|
||||||
@ -366,11 +393,7 @@ class GridView(QListView):
|
|||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QListView.__init__(self, parent)
|
QListView.__init__(self, parent)
|
||||||
setup_dnd_interface(self)
|
setup_dnd_interface(self)
|
||||||
pal = QPalette(self.palette())
|
self.set_color()
|
||||||
r = g = b = 0x50
|
|
||||||
pal.setColor(pal.Base, QColor(r, g, b))
|
|
||||||
pal.setColor(pal.Text, QColor(Qt.white if (r + g + b)/3.0 < 128 else Qt.black))
|
|
||||||
self.setPalette(pal)
|
|
||||||
self.setUniformItemSizes(True)
|
self.setUniformItemSizes(True)
|
||||||
self.setWrapping(True)
|
self.setWrapping(True)
|
||||||
self.setFlow(self.LeftToRight)
|
self.setFlow(self.LeftToRight)
|
||||||
@ -380,7 +403,7 @@ class GridView(QListView):
|
|||||||
self.setResizeMode(self.Adjust)
|
self.setResizeMode(self.Adjust)
|
||||||
self.setSelectionMode(self.ExtendedSelection)
|
self.setSelectionMode(self.ExtendedSelection)
|
||||||
self.setVerticalScrollMode(self.ScrollPerPixel)
|
self.setVerticalScrollMode(self.ScrollPerPixel)
|
||||||
self.delegate = CoverDelegate(self, 135, 180)
|
self.delegate = CoverDelegate(self)
|
||||||
self.setItemDelegate(self.delegate)
|
self.setItemDelegate(self.delegate)
|
||||||
self.setSpacing(self.delegate.spacing)
|
self.setSpacing(self.delegate.spacing)
|
||||||
self.ignore_render_requests = Event()
|
self.ignore_render_requests = Event()
|
||||||
@ -390,6 +413,21 @@ class GridView(QListView):
|
|||||||
self.gui = parent
|
self.gui = parent
|
||||||
self.context_menu = None
|
self.context_menu = None
|
||||||
|
|
||||||
|
def set_color(self):
|
||||||
|
r, g, b = gprefs['cover_grid_color']
|
||||||
|
pal = QPalette()
|
||||||
|
pal.setColor(pal.Base, QColor(r, g, b))
|
||||||
|
pal.setColor(pal.Text, QColor(Qt.white if (r + g + b)/3.0 < 128 else Qt.black))
|
||||||
|
self.setPalette(pal)
|
||||||
|
|
||||||
|
def refresh_settings(self):
|
||||||
|
if gprefs['cover_grid_width'] != self.delegate.original_width or gprefs['cover_grid_height'] != self.delegate.original_height:
|
||||||
|
self.delegate.set_dimensions()
|
||||||
|
self.setSpacing(self.delegate.spacing)
|
||||||
|
self.delegate.cover_cache.clear()
|
||||||
|
self.set_color()
|
||||||
|
self.delegate.cover_cache.set_limit(gprefs['cover_grid_cache_size'])
|
||||||
|
|
||||||
def shown(self):
|
def shown(self):
|
||||||
if self.render_thread is None:
|
if self.render_thread is None:
|
||||||
self.render_thread = Thread(target=self.render_covers)
|
self.render_thread = Thread(target=self.render_covers)
|
||||||
|
@ -5,8 +5,8 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog,
|
from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog, QColorDialog,
|
||||||
QAbstractListModel, Qt, QIcon, QKeySequence)
|
QAbstractListModel, Qt, QIcon, QKeySequence, QPalette, QColor)
|
||||||
|
|
||||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList
|
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList
|
||||||
from calibre.gui2.preferences.look_feel_ui import Ui_Form
|
from calibre.gui2.preferences.look_feel_ui import Ui_Form
|
||||||
@ -18,7 +18,7 @@ from calibre.utils.icu import sort_key
|
|||||||
from calibre.gui2.book_details import get_field_list
|
from calibre.gui2.book_details import get_field_list
|
||||||
from calibre.gui2.preferences.coloring import EditRules
|
from calibre.gui2.preferences.coloring import EditRules
|
||||||
|
|
||||||
class DisplayedFields(QAbstractListModel): # {{{
|
class DisplayedFields(QAbstractListModel): # {{{
|
||||||
|
|
||||||
def __init__(self, db, parent=None):
|
def __init__(self, db, parent=None):
|
||||||
QAbstractListModel.__init__(self, parent)
|
QAbstractListModel.__init__(self, parent)
|
||||||
@ -110,6 +110,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('tag_browser_old_look', gprefs, restart_required=True)
|
r('tag_browser_old_look', gprefs, restart_required=True)
|
||||||
r('bd_show_cover', gprefs)
|
r('bd_show_cover', gprefs)
|
||||||
r('bd_overlay_cover_size', gprefs)
|
r('bd_overlay_cover_size', gprefs)
|
||||||
|
r('cover_grid_width', gprefs)
|
||||||
|
r('cover_grid_height', gprefs)
|
||||||
|
r('cover_grid_cache_size', gprefs)
|
||||||
|
|
||||||
r('cover_flow_queue_length', config, restart_required=True)
|
r('cover_flow_queue_length', config, restart_required=True)
|
||||||
r('cover_browser_reflections', gprefs)
|
r('cover_browser_reflections', gprefs)
|
||||||
@ -123,7 +126,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
lang = get_lang()
|
lang = get_lang()
|
||||||
if lang is None or lang not in available_translations():
|
if lang is None or lang not in available_translations():
|
||||||
lang = 'en'
|
lang = 'en'
|
||||||
items = [(l, get_esc_lang(l)) for l in available_translations() \
|
items = [(l, get_esc_lang(l)) for l in available_translations()
|
||||||
if l != lang]
|
if l != lang]
|
||||||
if lang != 'en':
|
if lang != 'en':
|
||||||
items.append(('en', get_esc_lang('en')))
|
items.append(('en', get_esc_lang('en')))
|
||||||
@ -170,7 +173,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
|
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
|
||||||
choices=sorted(list(choices), key=sort_key))
|
choices=sorted(list(choices), key=sort_key))
|
||||||
|
|
||||||
|
|
||||||
self.current_font = self.initial_font = None
|
self.current_font = self.initial_font = None
|
||||||
self.change_font_button.clicked.connect(self.change_font)
|
self.change_font_button.clicked.connect(self.change_font)
|
||||||
|
|
||||||
@ -197,6 +199,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
|
keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys]
|
||||||
self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
|
self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
|
||||||
_(' or ').join(keys)))
|
_(' or ').join(keys)))
|
||||||
|
self.cover_grid_color_button.clicked.connect(self.change_cover_grid_color)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
ConfigWidgetBase.initialize(self)
|
ConfigWidgetBase.initialize(self)
|
||||||
@ -215,6 +218,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
mi=None
|
mi=None
|
||||||
self.edit_rules.initialize(db.field_metadata, db.prefs, mi, 'column_color_rules')
|
self.edit_rules.initialize(db.field_metadata, db.prefs, mi, 'column_color_rules')
|
||||||
self.icon_rules.initialize(db.field_metadata, db.prefs, mi, 'column_icon_rules')
|
self.icon_rules.initialize(db.field_metadata, db.prefs, mi, 'column_icon_rules')
|
||||||
|
self.set_cg_color(gprefs['cover_grid_color'])
|
||||||
|
|
||||||
|
def set_cg_color(self, val):
|
||||||
|
pal = QPalette()
|
||||||
|
pal.setColor(QPalette.Window, QColor(*val))
|
||||||
|
self.cover_grid_color_label.setPalette(pal)
|
||||||
|
|
||||||
def restore_defaults(self):
|
def restore_defaults(self):
|
||||||
ConfigWidgetBase.restore_defaults(self)
|
ConfigWidgetBase.restore_defaults(self)
|
||||||
@ -227,6 +236,15 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.edit_rules.clear()
|
self.edit_rules.clear()
|
||||||
self.icon_rules.clear()
|
self.icon_rules.clear()
|
||||||
self.changed_signal.emit()
|
self.changed_signal.emit()
|
||||||
|
self.set_cg_color(gprefs.defaults['cover_grid_color'])
|
||||||
|
|
||||||
|
def change_cover_grid_color(self):
|
||||||
|
col = QColorDialog.getColor(self.cover_grid_color_label.palette().color(QPalette.Window),
|
||||||
|
self.gui, _('Choose background color for cover grid'))
|
||||||
|
if col.isValid():
|
||||||
|
col = tuple(col.getRgb())[:3]
|
||||||
|
self.set_cg_color(col)
|
||||||
|
self.changed_signal.emit()
|
||||||
|
|
||||||
def build_font_obj(self):
|
def build_font_obj(self):
|
||||||
font_info = self.current_font
|
font_info = self.current_font
|
||||||
@ -286,6 +304,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.display_model.commit()
|
self.display_model.commit()
|
||||||
self.edit_rules.commit(self.gui.current_db.prefs)
|
self.edit_rules.commit(self.gui.current_db.prefs)
|
||||||
self.icon_rules.commit(self.gui.current_db.prefs)
|
self.icon_rules.commit(self.gui.current_db.prefs)
|
||||||
|
gprefs['cover_grid_color'] = tuple(self.cover_grid_color_label.palette().color(QPalette.Window).getRgb())[:3]
|
||||||
return rr
|
return rr
|
||||||
|
|
||||||
def refresh_gui(self, gui):
|
def refresh_gui(self, gui):
|
||||||
@ -296,9 +315,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
if hasattr(gui.cover_flow, 'setShowReflections'):
|
if hasattr(gui.cover_flow, 'setShowReflections'):
|
||||||
gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
|
gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
|
||||||
gui.library_view.refresh_row_sizing()
|
gui.library_view.refresh_row_sizing()
|
||||||
|
gui.grid_view.refresh_settings()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from calibre.gui2 import Application
|
from calibre.gui2 import Application
|
||||||
app = Application([])
|
app = Application([])
|
||||||
test_widget('Interface', 'Look & Feel')
|
test_widget('Interface', 'Look & Feel')
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,6 +223,184 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_5">
|
||||||
|
<attribute name="icon">
|
||||||
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
<normaloff>:/images/grid.png</normaloff>:/images/grid.png</iconset>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Cover Grid</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cover &Width: </string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_cover_grid_width</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="opt_cover_grid_width">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The width of displayed covers</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> cm</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cover &Height: </string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_cover_grid_height</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="opt_cover_grid_height">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The height of displayed covers</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> cm</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>A value of zero means set automatically based on screen size</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_14">
|
||||||
|
<property name="text">
|
||||||
|
<string>Background color for the cover grid:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="cover_grid_color_label">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="cover_grid_color_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Change &color</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Number of covers to cache in &memory:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_cover_grid_cache_size</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="opt_cover_grid_cache_size">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>3000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>355</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
<widget class="QWidget" name="tab_4">
|
<widget class="QWidget" name="tab_4">
|
||||||
<attribute name="icon">
|
<attribute name="icon">
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user