Cleanup previous PR

- Improve rendering of splitter handle using fewer, closer spaced,
  circular dots

- Fix book details splitter not being rendered correctly on first start
  when there is no saved state to restore

- Remove geometry save/restore of splitter as this is handled by
  restore_state

- Remove call to setChildrenCollapsible before any children were added,
  causing Qt to print an error to stderr

Fixes #1994065 [Enhancement Request: Details pane: Splitter between cover and details](https://bugs.launchpad.net/calibre/+bug/1994065)
This commit is contained in:
Kovid Goyal 2022-10-26 20:13:41 +05:30
parent 2fb78716f9
commit 98811a1999
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 16 additions and 21 deletions

View File

@ -10,7 +10,7 @@ from qt.core import (
QAction, QApplication, QClipboard, QColor, QDialog, QEasingCurve, QIcon, QAction, QApplication, QClipboard, QColor, QDialog, QEasingCurve, QIcon,
QKeySequence, QMenu, QMimeData, QPainter, QPen, QPixmap, QKeySequence, QMenu, QMimeData, QPainter, QPen, QPixmap,
QPropertyAnimation, QRect, QSize, QSizePolicy, Qt, QUrl, QWidget, pyqtProperty, QPropertyAnimation, QRect, QSize, QSizePolicy, Qt, QUrl, QWidget, pyqtProperty,
QTimer, pyqtSignal pyqtSignal
) )
from calibre import fit_image, sanitize_file_name from calibre import fit_image, sanitize_file_name
@ -920,13 +920,9 @@ class DetailsLayout(BasicSplitter): # {{{
orientation = Qt.Orientation.Vertical if vertical else Qt.Orientation.Horizontal orientation = Qt.Orientation.Vertical if vertical else Qt.Orientation.Horizontal
BasicSplitter.__init__(self, orientation, parent) BasicSplitter.__init__(self, orientation, parent)
self.vertical = vertical self.vertical = vertical
self.setCollapsible(0, True)
self._children = [] self._children = []
self.min_size = QSize(190, 200) if vertical else QSize(120, 120) self.min_size = QSize(190, 200) if vertical else QSize(120, 120)
self.setContentsMargins(0, 0, 0, 0) self.setContentsMargins(0, 0, 0, 0)
self.restore_geometry(gprefs, 'book_details_splitter')
self.splitterMoved.connect(self.do_splitter_moved) self.splitterMoved.connect(self.do_splitter_moved)
def minimumSize(self): def minimumSize(self):
@ -945,14 +941,16 @@ class DetailsLayout(BasicSplitter): # {{{
def restore_splitter_state(self): def restore_splitter_state(self):
s = gprefs.get('book_details_widget_splitter_state') s = gprefs.get('book_details_widget_splitter_state')
if s is not None: if s is None:
# Without this on first start the splitter is rendered over the cover
self.setSizes([20, 80])
else:
self.restoreState(s) self.restoreState(s)
self.setOrientation(Qt.Orientation.Vertical if self.vertical else Qt.Orientation.Horizontal) self.setOrientation(Qt.Orientation.Vertical if self.vertical else Qt.Orientation.Horizontal)
def setGeometry(self, r): def setGeometry(self, r):
BasicSplitter.setGeometry(self, r) super().setGeometry(r)
self.do_layout(r) self.do_layout(r)
self.restore_splitter_state()
def do_splitter_moved(self, *args): def do_splitter_moved(self, *args):
gprefs['book_details_widget_splitter_state'] = bytearray(self.saveState()) gprefs['book_details_widget_splitter_state'] = bytearray(self.saveState())
@ -1004,8 +1002,7 @@ class DetailsLayout(BasicSplitter): # {{{
cover.setGeometry(QRect(x, y, cw, r.height())) cover.setGeometry(QRect(x, y, cw, r.height()))
x += cw + 5 x += cw + 5
details.setGeometry(QRect(x, y, r.width() - cw - 5, r.height())) details.setGeometry(QRect(x, y, r.width() - cw - 5, r.height()))
self.restore_splitter_state() # only required on first call to do_layout, but ... self.restore_splitter_state() # only required on first call to do_layout, but ...
self.save_geometry(gprefs, 'book_details_splitter')
cover.do_layout() cover.do_layout()
# }}} # }}}

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import functools import functools
from qt.core import ( from qt.core import (
QAction, QApplication, QDialog, QEvent, QIcon, QLabel, QMenu, QPixmap, QUrl, QAction, QApplication, QDialog, QEvent, QIcon, QLabel, QMenu, QPixmap, QUrl,
QSizePolicy, QSplitter, QStackedWidget, QStatusBar, QStyle, QStyleOption, QSizePolicy, QStackedWidget, QStatusBar, QStyle, QStyleOption,
QStylePainter, Qt, QTabBar, QTimer, QToolButton, QVBoxLayout, QWidget QStylePainter, Qt, QTabBar, QTimer, QToolButton, QVBoxLayout, QWidget
) )

View File

@ -982,10 +982,6 @@ class PythonHighlighter(QSyntaxHighlighter): # {{{
class BasicSplitterHandle(QSplitterHandle): class BasicSplitterHandle(QSplitterHandle):
def __init__(self, orientation, splitter):
QSplitterHandle.__init__(self, orientation, splitter)
self.handle_width = splitter.handleWidth()
def paintEvent(self, event): def paintEvent(self, event):
rect = event.rect() rect = event.rect()
painter = QPainter(self) painter = QPainter(self)
@ -997,16 +993,18 @@ class BasicSplitterHandle(QSplitterHandle):
# draw the dots # draw the dots
painter.setBrush(palette.color(QPalette.ColorGroup.Normal, QPalette.ColorRole.Shadow)) painter.setBrush(palette.color(QPalette.ColorGroup.Normal, QPalette.ColorRole.Shadow))
horizontal = self.orientation() == Qt.Orientation.Horizontal horizontal = self.orientation() == Qt.Orientation.Horizontal
dot_count = 6 dot_count = 4
dot_size = int(max(1, self.handle_width/2)) cr = self.contentsRect()
handle_width = cr.width() if horizontal else cr.height()
dot_size = int(max(1, handle_width))
start_point = max(0, int((rect.height()/2 if horizontal else rect.width()/2) - (dot_count*dot_size/2))) start_point = max(0, int((rect.height()/2 if horizontal else rect.width()/2) - (dot_count*dot_size/2)))
for i in range(dot_count): for i in range(dot_count):
# Move the rect to leave 2 dot spaces between the dots # Move the rect to leave spaces between the dots
if horizontal: if horizontal:
dot_rect = QRect(1, start_point + i*dot_size*3, dot_size, dot_size) dot_rect = QRect(0, start_point + i*dot_size*2, dot_size, dot_size)
else: else:
dot_rect = QRect(start_point + i*dot_size*3, 1, dot_size, dot_size) dot_rect = QRect(start_point + i*dot_size*2, 0, dot_size, dot_size)
painter.drawRect(dot_rect) painter.drawEllipse(dot_rect)
painter.end() painter.end()