mirror of
https://github.com/kovidgoyal/calibre.git
synced 2026-04-27 19:29:52 -04:00
Bookshelf: Add option to control whether narrow books are widened to make space for second line of spine
This commit is contained in:
parent
400a8df596
commit
52985cd6ff
@ -500,6 +500,7 @@ def create_defs():
|
||||
defs['bookshelf_hover'] = 'shift'
|
||||
defs['bookshelf_up_to_down'] = False
|
||||
defs['bookshelf_height'] = 119
|
||||
defs['bookshelf_make_space_for_second_line'] = False
|
||||
|
||||
# Migrate beta bookshelf_thumbnail
|
||||
if isinstance(btv := gprefs.get('bookshelf_thumbnail'), bool):
|
||||
|
||||
@ -858,7 +858,7 @@ def get_spine_width(
|
||||
book_id: int, db: Cache, spine_size_template: str, template_cache: dict[str, str],
|
||||
lc: LayoutConstraints, cache: dict[int, int]
|
||||
) -> int:
|
||||
if (ans := cache.get(book_id)) is not None:
|
||||
if (ans := cache.get(book_id)) is not None and lc.min_spine_width <= ans <= lc.max_spine_width:
|
||||
return ans
|
||||
|
||||
def linear(f: float):
|
||||
@ -902,6 +902,7 @@ class LayoutPayload(NamedTuple):
|
||||
book_id_to_item_map: dict[int, ShelfItem]
|
||||
book_id_visual_order_map: dict[int, int]
|
||||
book_ids_in_visual_order: list[int]
|
||||
min_line_height: int
|
||||
|
||||
|
||||
class BookCase(QObject):
|
||||
@ -981,7 +982,7 @@ class BookCase(QObject):
|
||||
|
||||
def invalidate(
|
||||
self, layout_constraints: LayoutConstraints = LayoutConstraints(),
|
||||
model: BooksModel | None = None, group_field_name: str = ''
|
||||
model: BooksModel | None = None, group_field_name: str = '', min_line_height: int = 0,
|
||||
) -> None:
|
||||
with self.lock:
|
||||
self.current_invalidate_event.set()
|
||||
@ -1004,7 +1005,8 @@ class BookCase(QObject):
|
||||
self.layout_finished = not bool(self.row_to_book_id)
|
||||
self.payload = LayoutPayload(
|
||||
self.current_invalidate_event, self.layout_constraints, self.group_field_name, self.row_to_book_id,
|
||||
self.book_id_to_item_map, self.book_id_visual_order_map, self.book_ids_in_visual_order)
|
||||
self.book_id_to_item_map, self.book_id_visual_order_map, self.book_ids_in_visual_order,
|
||||
min_line_height)
|
||||
|
||||
def ensure_layouting_is_current(self) -> None:
|
||||
if db := self.dbref():
|
||||
@ -1034,7 +1036,7 @@ class BookCase(QObject):
|
||||
def do_layout_in_worker(
|
||||
self, invalidate: Event, lc: LayoutConstraints, group_field_name: str, row_to_book_id: tuple[int, ...],
|
||||
book_id_to_item_map: dict[int, ShelfItem], book_id_visual_order_map: dict[int, int],
|
||||
book_ids_in_visual_order: list[int],
|
||||
book_ids_in_visual_order: list[int], min_line_height: int,
|
||||
) -> None:
|
||||
if lc.width < lc.max_spine_width:
|
||||
return
|
||||
@ -1055,6 +1057,11 @@ class BookCase(QObject):
|
||||
return
|
||||
db = mdb.new_api
|
||||
spine_size_template = db.pref('bookshelf_spine_size_template') or db.backend.prefs.defaults['bookshelf_spine_size_template']
|
||||
if gprefs['bookshelf_make_space_for_second_line']:
|
||||
prefs = db.backend.prefs
|
||||
author_template = prefs.get('bookshelf_author_template', prefs.defaults.get('bookshelf_author_template')) or ''
|
||||
if author_template.strip():
|
||||
min_line_height *= 2
|
||||
template_cache = {}
|
||||
group_iter = get_grouped_iterator(db, row_to_book_id, group_field_name)
|
||||
_, num_of_groups = next(group_iter)
|
||||
@ -1064,6 +1071,9 @@ class BookCase(QObject):
|
||||
self.num_of_groups = num_of_groups
|
||||
self.num_of_groups_changed.emit()
|
||||
num_of_books_that_need_pages_counted = db.num_of_books_that_need_pages_counted()
|
||||
# Ensure there is enough width for the spine text
|
||||
min_width = min(max(min_line_height, lc.min_spine_width), lc.max_spine_width-1)
|
||||
lc = lc._replace(min_spine_width=min_width)
|
||||
for group_name, book_ids_in_group in group_iter:
|
||||
if invalidate.is_set():
|
||||
return
|
||||
@ -1316,6 +1326,8 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
self.base_font_size_pts = QFontInfo(self.font()).pointSizeF()
|
||||
self.min_font_size = 0.75 * self.base_font_size_pts
|
||||
self.max_font_size = 1.3 * self.base_font_size_pts
|
||||
_, fm, _ = self.get_sized_font(self.min_font_size)
|
||||
self.min_line_height = math.ceil(fm.height())
|
||||
|
||||
self.gui = gui
|
||||
self._model: BooksModel | None = None
|
||||
@ -1336,6 +1348,13 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
self.viewport().setMouseTracking(True)
|
||||
self.viewport().setAttribute(Qt.WidgetAttribute.WA_MouseTracking, True)
|
||||
|
||||
# Cover template caching
|
||||
self.template_inited = False
|
||||
self.template_cache = {}
|
||||
self.template_title = ''
|
||||
self.template_author = ''
|
||||
self.template_title_is_empty = True
|
||||
|
||||
# Initialize drag and drop
|
||||
# so we set the attributes manually
|
||||
self.drag_allowed = True
|
||||
@ -1364,12 +1383,6 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
)
|
||||
self.cover_cache.rendered.connect(self.update_viewport, type=Qt.ConnectionType.QueuedConnection)
|
||||
|
||||
# Cover template caching
|
||||
self.template_inited = False
|
||||
self.template_cache = {}
|
||||
self.template_title = ''
|
||||
self.template_title_is_empty = True
|
||||
|
||||
def calculate_shelf_geometry(self) -> None:
|
||||
lc = self.layout_constraints
|
||||
if (h := gprefs['bookshelf_height']) < 120 or h > 1200:
|
||||
@ -1453,8 +1466,7 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
self.cover_cache.set_thumbnail_size(*self.thumbnail_size())
|
||||
self.cover_cache.set_disk_cache_max_size(gprefs['bookshelf_disk_cache_size'])
|
||||
self.update_ram_cache_size()
|
||||
self.bookcase.clear_spine_width_cache()
|
||||
self.invalidate()
|
||||
self.invalidate(clear_spine_width_cache=True)
|
||||
|
||||
def view_is_visible(self) -> bool:
|
||||
'''Return if the bookshelf view is visible.'''
|
||||
@ -1484,7 +1496,7 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
# Create selection model for sync
|
||||
for s, tgt in signals.items():
|
||||
getattr(self._model, s).connect(getattr(self, tgt))
|
||||
self.invalidate(set_of_books_changed=True)
|
||||
self.invalidate(set_of_books_changed=True, clear_spine_width_cache=True)
|
||||
|
||||
def model(self) -> BooksModel | None:
|
||||
'''Return the model.'''
|
||||
@ -1553,10 +1565,12 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
sw = 0 if self.has_transient_scrollbar else self.verticalScrollBar().width()
|
||||
return self.width() - (2 * self.layout_constraints.side_margin) - sw
|
||||
|
||||
def invalidate(self, set_of_books_changed=True):
|
||||
def invalidate(self, set_of_books_changed: bool = False, clear_spine_width_cache: bool = False) -> None:
|
||||
if clear_spine_width_cache:
|
||||
self.bookcase.clear_spine_width_cache()
|
||||
self.bookcase.invalidate(
|
||||
self.layout_constraints, model=self.model() if set_of_books_changed else None,
|
||||
group_field_name=self.grouping_mode)
|
||||
group_field_name=self.grouping_mode, min_line_height=self.min_line_height)
|
||||
if set_of_books_changed:
|
||||
self.expanded_cover.invalidate()
|
||||
self.update_scrollbar_ranges()
|
||||
@ -1574,7 +1588,7 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
if num_of_books_that_need_pages_counted:
|
||||
self.pages_count_update_check_timer.start()
|
||||
else:
|
||||
self.invalidate()
|
||||
self.invalidate(clear_spine_width_cache=True)
|
||||
|
||||
def on_shelf_layout_done(self, books: CaseItem, shelf: CaseItem) -> None:
|
||||
if self.view_is_visible():
|
||||
@ -1991,8 +2005,7 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea):
|
||||
# Clear caches when database changes
|
||||
self.template_inited = False
|
||||
self.cover_cache.set_database(newdb)
|
||||
self.bookcase.clear_spine_width_cache()
|
||||
self.invalidate(set_of_books_changed=True)
|
||||
self.invalidate(set_of_books_changed=True, clear_spine_width_cache=True)
|
||||
|
||||
def set_context_menu(self, menu: QMenu):
|
||||
self.context_menu = menu
|
||||
|
||||
@ -53,6 +53,7 @@ class BookshelfTab(QTabWidget, LazyConfigWidgetBase, Ui_Form):
|
||||
r('bookshelf_fade_time', gprefs)
|
||||
r('bookshelf_up_to_down', gprefs)
|
||||
r('bookshelf_height', gprefs)
|
||||
r('bookshelf_make_space_for_second_line', gprefs)
|
||||
|
||||
r('bookshelf_thumbnail', gprefs, choices=[
|
||||
(_('Full'), 'full'),
|
||||
|
||||
@ -131,7 +131,7 @@
|
||||
<item>
|
||||
<widget class="QLineEdit" name="opt_bookshelf_author_template">
|
||||
<property name="toolTip">
|
||||
<string><p>The template used to generate an optional second line of text on the spine. This template uses the same syntax as save templates. Defaults to no second line. For very narrow books, this will be skipped when there is insufficient space for a second line. For example, use the value {author_sort} to show the book authors. Note that this setting is per-library, which means that you have to set it again for every different calibre library you use.</p></string>
|
||||
<string><p>The template used to generate an optional second line of text on the spine. This template uses the same syntax as save templates. Defaults to no second line. For example, use the value {author_sort} to show the book authors. Note that this setting is per-library, which means that you have to set it again for every different calibre library you use.</p></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -144,7 +144,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_pages">
|
||||
<property name="text">
|
||||
<string>Template for spine &width:</string>
|
||||
@ -154,7 +154,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="opt_bookshelf_spine_size_template">
|
||||
@ -172,14 +172,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QPushButton" name="use_pages_button">
|
||||
<property name="text">
|
||||
<string>Use a custom &pages column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_fade_time">
|
||||
<property name="text">
|
||||
<string>Duration of hover &animation</string>
|
||||
@ -189,7 +189,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="opt_bookshelf_fade_time">
|
||||
<property name="specialValueText">
|
||||
<string>Disable</string>
|
||||
@ -208,7 +208,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_hover_interact">
|
||||
<property name="text">
|
||||
<string>&Expand the hovered cover:</string>
|
||||
@ -218,14 +218,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="opt_bookshelf_hover">
|
||||
<property name="toolTip">
|
||||
<string>Control what happens when the mouse hovers over the spine of a book.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="12" column="0">
|
||||
<spacer name="vertical_spacer_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -238,7 +238,7 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="recount_button">
|
||||
<property name="toolTip">
|
||||
<string>Have calibre re-count the pages in all books in the current library.</string>
|
||||
@ -248,13 +248,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="show_log_button">
|
||||
<property name="text">
|
||||
<string>Show count &failure log</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="opt_bookshelf_make_space_for_second_line">
|
||||
<property name="toolTip">
|
||||
<string><p>When showing authors in spine, for very narrow books, artifically widen the book to make space for the author line. Without this, the authors wont be displayed for narrow books, with it, narrow books will appear artifically wider than they really are.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Make &space for author line</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="CoverCacheConfig" name="config_cache">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user