Make the cover grid customizable

This commit is contained in:
Kovid Goyal 2013-08-02 16:23:24 +05:30
parent 5737ead466
commit 0541a118e6
4 changed files with 255 additions and 14 deletions

View File

@ -111,6 +111,10 @@ defs['tags_browser_category_icons'] = {}
defs['cover_browser_reflections'] = True
defs['extra_row_spacing'] = 0
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
# }}}

View File

@ -20,8 +20,11 @@ from PyQt4.Qt import (
QUrl, QDrag, QPoint, QPainter, QRect)
from calibre import fit_image
from calibre.gui2 import gprefs
from calibre.utils.config import prefs
CM_TO_INCH = 0.393701
# Drag 'n Drop {{{
def dragMoveEvent(self, event):
event.acceptProposedAction()
@ -305,15 +308,39 @@ class CoverCache(dict):
def __hash__(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):
def __init__(self, parent, width, height):
def __init__(self, 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.item_size = self.cover_size + QSize(8, 8)
self.spacing = max(10, min(50, int(0.1 * width)))
self.cover_cache = CoverCache()
self.render_queue = Queue()
def sizeHint(self, option, index):
return self.item_size
@ -366,11 +393,7 @@ class GridView(QListView):
def __init__(self, parent):
QListView.__init__(self, parent)
setup_dnd_interface(self)
pal = QPalette(self.palette())
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.set_color()
self.setUniformItemSizes(True)
self.setWrapping(True)
self.setFlow(self.LeftToRight)
@ -380,7 +403,7 @@ class GridView(QListView):
self.setResizeMode(self.Adjust)
self.setSelectionMode(self.ExtendedSelection)
self.setVerticalScrollMode(self.ScrollPerPixel)
self.delegate = CoverDelegate(self, 135, 180)
self.delegate = CoverDelegate(self)
self.setItemDelegate(self.delegate)
self.setSpacing(self.delegate.spacing)
self.ignore_render_requests = Event()
@ -390,6 +413,21 @@ class GridView(QListView):
self.gui = parent
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):
if self.render_thread is None:
self.render_thread = Thread(target=self.render_covers)

View File

@ -5,8 +5,8 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog,
QAbstractListModel, Qt, QIcon, QKeySequence)
from PyQt4.Qt import (QApplication, QFont, QFontInfo, QFontDialog, QColorDialog,
QAbstractListModel, Qt, QIcon, QKeySequence, QPalette, QColor)
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, CommaSeparatedList
from calibre.gui2.preferences.look_feel_ui import Ui_Form
@ -110,6 +110,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('tag_browser_old_look', gprefs, restart_required=True)
r('bd_show_cover', 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_browser_reflections', gprefs)
@ -123,7 +126,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
lang = get_lang()
if lang is None or lang not in available_translations():
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 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,
choices=sorted(list(choices), key=sort_key))
self.current_font = self.initial_font = None
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]
self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
_(' or ').join(keys)))
self.cover_grid_color_button.clicked.connect(self.change_cover_grid_color)
def initialize(self):
ConfigWidgetBase.initialize(self)
@ -215,6 +218,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
mi=None
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.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):
ConfigWidgetBase.restore_defaults(self)
@ -227,6 +236,15 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.edit_rules.clear()
self.icon_rules.clear()
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):
font_info = self.current_font
@ -286,6 +304,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.display_model.commit()
self.edit_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
def refresh_gui(self, gui):
@ -296,9 +315,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
if hasattr(gui.cover_flow, 'setShowReflections'):
gui.cover_flow.setShowReflections(gprefs['cover_browser_reflections'])
gui.library_view.refresh_row_sizing()
gui.grid_view.refresh_settings()
if __name__ == '__main__':
from calibre.gui2 import Application
app = Application([])
test_widget('Interface', 'Look & Feel')

View File

@ -223,6 +223,184 @@
</item>
</layout>
</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 &amp;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 &amp;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 &amp;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 &amp;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">
<attribute name="icon">
<iconset resource="../../../../resources/images.qrc">