Take 2 on the numeric sort and the tweaks scroll bar changes

This commit is contained in:
Charles Haley 2021-12-13 12:52:47 +00:00 committed by Kovid Goyal
parent 5d9c5ebd58
commit bd7dbfec43
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 28 additions and 13 deletions

View File

@ -25,7 +25,7 @@ def bool_sort_key(bools_are_tristate):
return (lambda x:{True: 1, False: 2, None: 3}.get(x, 3)) if bools_are_tristate else lambda x:{True: 1, False: 2, None: 2}.get(x, 2) return (lambda x:{True: 1, False: 2, None: 3}.get(x, 3)) if bools_are_tristate else lambda x:{True: 1, False: 2, None: 2}.get(x, 2)
def _get_sort_value_for_undefined_numbers(): def sort_value_for_undefined_numbers():
t = tweaks['value_for_undefined_numbers_when_sorting'] t = tweaks['value_for_undefined_numbers_when_sorting']
try: try:
if t == 'minimum': if t == 'minimum':
@ -38,13 +38,10 @@ def _get_sort_value_for_undefined_numbers():
return 0 return 0
sort_value_for_undefined_numbers = _get_sort_value_for_undefined_numbers()
def numeric_sort_key(x): def numeric_sort_key(x):
# It isn't clear whether this function can ever be called with a non-numeric # It isn't clear whether this function can ever be called with a non-numeric
# argument, but we check just in case # argument, but we check just in case
return x if type(x) in (int, float) else sort_value_for_undefined_numbers return x if type(x) in (int, float) else sort_value_for_undefined_numbers()
IDENTITY = lambda x: x IDENTITY = lambda x: x
@ -77,7 +74,7 @@ class Field:
self._default_sort_key = b'' self._default_sort_key = b''
if dt in {'int', 'float', 'rating'}: if dt in {'int', 'float', 'rating'}:
self._default_sort_key = sort_value_for_undefined_numbers self._default_sort_key = sort_value_for_undefined_numbers()
self._sort_key = numeric_sort_key self._sort_key = numeric_sort_key
elif dt == 'bool': elif dt == 'bool':
self._default_sort_key = None self._default_sort_key = None
@ -280,7 +277,7 @@ class CompositeField(OneToOneField):
val = val[:(-2 if p > 1 else -1)].strip() val = val[:(-2 if p > 1 else -1)].strip()
val = atof(val) * p val = atof(val) * p
except (TypeError, AttributeError, ValueError, KeyError): except (TypeError, AttributeError, ValueError, KeyError):
val = sort_value_for_undefined_numbers val = sort_value_for_undefined_numbers()
return val return val
def date_sort_key(self, val): def date_sort_key(self, val):

View File

@ -6,13 +6,14 @@
import textwrap import textwrap
from collections import OrderedDict from collections import OrderedDict
from functools import partial from functools import partial
from math import ceil, floor
from operator import attrgetter from operator import attrgetter
from qt.core import ( from qt.core import (
QAbstractListModel, QApplication, QDialog, QDialogButtonBox, QFont, QGridLayout, QAbstractListModel, QApplication, QDialog, QDialogButtonBox, QFont, QGridLayout,
QGroupBox, QIcon, QLabel, QListView, QMenu, QModelIndex, QPlainTextEdit, QComboBox, QGroupBox, QIcon, QLabel, QListView, QMenu, QModelIndex, QPlainTextEdit, QComboBox,
QPushButton, QSizePolicy, QSplitter, QStyle, QStyledItemDelegate, QAbstractItemView, QItemSelectionModel, QPushButton, QSizePolicy, QSplitter, QStyle, QStyledItemDelegate, QAbstractItemView, QItemSelectionModel,
QStyleOptionViewItem, Qt, QVBoxLayout, QWidget, pyqtSignal QStyleOptionViewItem, Qt, QVBoxLayout, QWidget, pyqtSignal, QTextDocument
) )
from calibre import isbytestring from calibre import isbytestring
@ -139,6 +140,11 @@ class Tweak: # {{{
# }}} # }}}
# This is the width of the tweaks list view. Add the vertical scrollbar and
# the margins to it.
tweaks_list_minimum_width = 280
class Tweaks(QAbstractListModel, AdaptSQP): # {{{ class Tweaks(QAbstractListModel, AdaptSQP): # {{{
def __init__(self, parent=None): def __init__(self, parent=None):
@ -156,7 +162,17 @@ class Tweaks(QAbstractListModel, AdaptSQP): # {{{
except: except:
return None return None
if role == Qt.ItemDataRole.DisplayRole: if role == Qt.ItemDataRole.DisplayRole:
return textwrap.fill(tweak.name, 40) # Compute the display length of the string then word wrap it so it
# fits in minimum_width. This seems much harder than it should be.
d = QTextDocument()
d.setDocumentMargin(0)
if tweak.is_customized:
d.setHtml('<b>' + tweak.name + '</b')
else:
d.setHtml(tweak.name)
avg_char_width = ceil(d.size().width()/len(tweak.name))
num_chars_per_line = int(floor(tweaks_list_minimum_width/avg_char_width))
return textwrap.fill(tweak.name, num_chars_per_line)
if role == Qt.ItemDataRole.FontRole and tweak.is_customized: if role == Qt.ItemDataRole.FontRole and tweak.is_customized:
ans = QFont() ans = QFont()
ans.setBold(True) ans.setBold(True)
@ -374,10 +390,12 @@ class TweaksView(QListView):
self.setAlternatingRowColors(True) self.setAlternatingRowColors(True)
self.setSpacing(5) self.setSpacing(5)
self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
# On windows (at least) the automatic scroll bar appearing hides part # Compute the size of the display area. Tweak strings are wrapped so that
# of the last line in the list view. Force it always on. # they fit in tweaks_list_minimum_width, so we need to add the size of
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) # the scrollbar and a heuristic for margins
self.setMinimumWidth(300) min_width = (tweaks_list_minimum_width + 20 +
QApplication.instance().style().pixelMetric(QStyle.PixelMetric.PM_ScrollBarExtent))
self.setMinimumWidth(min_width)
def currentChanged(self, cur, prev): def currentChanged(self, cur, prev):
QListView.currentChanged(self, cur, prev) QListView.currentChanged(self, cur, prev)