diff --git a/src/calibre/gui2/library/bookshelf_view.py b/src/calibre/gui2/library/bookshelf_view.py index 7d0098570a..178a12e90c 100644 --- a/src/calibre/gui2/library/bookshelf_view.py +++ b/src/calibre/gui2/library/bookshelf_view.py @@ -103,9 +103,9 @@ def normalised_size(size_bytes: int) -> float: # Average ebook: ~1-2KB per page, so estimate pages from size if size_bytes and size_bytes > 0: # Estimate: ~1500 bytes per page (conservative) - estimated_pages = max(50, size_bytes // 1500) - # Cap at reasonable max - return min(estimated_pages, 2000) / 2000. + estimated_pages = size_bytes // 1500 + # Normalise the value + return min(estimated_pages / 2000, 1) return 0. @@ -1565,42 +1565,28 @@ class BookshelfView(MomentumScrollMixin, QAbstractScrollArea): db = self.dbref() self.init_template(db) - def frac(f: float): + def linear(f: float): return self.SPINE_WIDTH_MIN + int(max(0, min(f, 1)) * (self.SPINE_WIDTH_MAX - self.SPINE_WIDTH_MIN)) - - def choice(choice: float) -> int: - choice = max(0, min(choice, 7)) - if choice <= 1: - ans = self.SPINE_WIDTH_MIN + 3 * choice - elif choice <= 2: - ans = self.SPINE_WIDTH_MIN + 3 + 4 * (choice - 1) - elif choice <= 3: - ans = self.SPINE_WIDTH_MIN + 7 + 6 * (choice - 2) - elif choice <= 4: - ans = self.SPINE_WIDTH_MIN + 13 + 7 * (choice - 3) - elif choice <= 5: - ans = self.SPINE_WIDTH_MIN + 20 + 8 * (choice - 4) - elif choice <= 6: - ans = self.SPINE_WIDTH_MIN + 28 + 7 * (choice - 5) - elif choice <= 7: - ans = self.SPINE_WIDTH_MIN + 35 + 10 * (choice - 6) - return min(ans, self.SPINE_WIDTH_MAX) + def log(f: float): + b = 100 + return linear(math.log(1+max(0, min(f, 1))*b, b+1)) match self.size_template: case '': return self.SPINE_WIDTH_DEFAULT case '{size}' | 'size': - return frac(normalised_size(db.field_for('size', book_id, 0))) + return log(normalised_size(db.field_for('size', book_id, 0))) case '{random}' | 'random': - return choice(book_id & 7) + # range: 0.25-0.75 + return linear((25+pseudo_random(book_id, 50))/100) case _: with suppress(Exception): - if 0 <= (x := float(self.size_template)) <= 7: - return choice(x) + if 0 <= (x := float(self.size_template)) <= 1: + return linear(x) with suppress(Exception): mi = db.get_proxy_metadata(book_id) rslt = mi.formatter.safe_format(self.template_pages, mi, TEMPLATE_ERROR, mi, template_cache=self.template_cache) - return choice(float(rslt)) + return linear(float(rslt)) return self.SPINE_WIDTH_DEFAULT def _get_height_modifier(self, book_id: int) -> int: diff --git a/src/calibre/gui2/preferences/look_feel_tabs/bookshelf_view.py b/src/calibre/gui2/preferences/look_feel_tabs/bookshelf_view.py index b42064b369..3ef6c4ef48 100644 --- a/src/calibre/gui2/preferences/look_feel_tabs/bookshelf_view.py +++ b/src/calibre/gui2/preferences/look_feel_tabs/bookshelf_view.py @@ -46,11 +46,11 @@ class BookshelfTab(QTabWidget, LazyConfigWidgetBase, Ui_Form): ) self.opt_bookshelf_spine_size_template.setToolTip(_('''

The template used to calculate a width for the displayed spine. -The template must evaluate to a number between 0 and 7, which will be used to set the width of the books spine. +The template must evaluate to a decimal number between 0.0 and 1.0, which will be used to set the width of the books spine. An empty template means a fixed spine size for all books. The special template {0} uses the book size to estimate a spine size. The special template {1} uses a random size. -You can also use the numbers between 0 and 7 to pick a fixed size. +You can also use a number between 0.0 and 1.0 to pick a fixed size.

Note that this setting is per-library, which means that you have to set it again for every different calibre library you use.

''').format('{size}', '{random}')) @@ -89,26 +89,14 @@ different calibre library you use.

''').format('{size}', '{random}')) template = f'''\ python: def evaluate(book, context): + import math val = book.get({key!r}) try: - pages = max(0, int(float(val))) + pages = max(0, int(val)) except Exception: - return '3.5' - if pages <= 20: - return str(pages/20) - if pages <= 50: - return str(1 + (pages-20)/30) - if pages <= 100: - return str(2 + (pages-50)/50) - if pages <= 200: - return str(3 + (pages-100)/100) - if pages <= 350: - return str(4 + (pages-200)/150) - if pages <= 500: - return str(4 + (pages-200)/150) - if pages <= 750: - return str(5 + (pages-500)/250) - return str(min(6 + (pages - 750) / 187.5, 7)) + return '0.56' + base = 100 + return str(math.log(1+max(0, min(pages/15), base), base+1) ''' self.opt_bookshelf_spine_size_template.setText(template)