mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More work on central widget
This commit is contained in:
parent
fa3e6c9b59
commit
c81536e38f
@ -1,7 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# License: GPLv3 Copyright: 2023, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2023, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from copy import copy
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
|
from dataclasses import dataclass
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
QDialog, QLabel, QPalette, QPointF, QSize, QSizePolicy, QStyle, QStyleOption,
|
QDialog, QLabel, QPalette, QPointF, QSize, QSizePolicy, QStyle, QStyleOption,
|
||||||
QStylePainter, Qt, QVBoxLayout, QWidget, pyqtSignal
|
QStylePainter, Qt, QVBoxLayout, QWidget, pyqtSignal
|
||||||
@ -33,6 +35,7 @@ class SplitterHandle(QWidget):
|
|||||||
drag_ended = pyqtSignal()
|
drag_ended = pyqtSignal()
|
||||||
dragged_to = pyqtSignal(QPointF)
|
dragged_to = pyqtSignal(QPointF)
|
||||||
drag_start = None
|
drag_start = None
|
||||||
|
COLLAPSED_SIZE = 2 # pixels
|
||||||
|
|
||||||
def __init__(self, parent: QWidget=None, orientation: Qt.Orientation = Qt.Orientation.Vertical):
|
def __init__(self, parent: QWidget=None, orientation: Qt.Orientation = Qt.Orientation.Vertical):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -76,7 +79,7 @@ class SplitterHandle(QWidget):
|
|||||||
opt.initFrom(self)
|
opt.initFrom(self)
|
||||||
if self.orientation is Qt.Orientation.Vertical:
|
if self.orientation is Qt.Orientation.Vertical:
|
||||||
opt.state |= QStyle.StateFlag.State_Horizontal
|
opt.state |= QStyle.StateFlag.State_Horizontal
|
||||||
if self.state is HandleState.only_side_visible:
|
if min(opt.rect.width(), opt.rect.height()) == self.COLLAPSED_SIZE:
|
||||||
p.fillRect(opt.rect, opt.palette.color(QPalette.ColorRole.Window))
|
p.fillRect(opt.rect, opt.palette.color(QPalette.ColorRole.Window))
|
||||||
else:
|
else:
|
||||||
p.drawControl(QStyle.ControlElement.CE_Splitter, opt)
|
p.drawControl(QStyle.ControlElement.CE_Splitter, opt)
|
||||||
@ -89,14 +92,21 @@ class Layout(Enum):
|
|||||||
narrow = auto()
|
narrow = auto()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
class WideDesires:
|
class WideDesires:
|
||||||
tag_browser_width = book_details_width = None
|
tag_browser_width: int = None
|
||||||
cover_browser_height = quickview_height = None
|
book_details_width: int = None
|
||||||
|
cover_browser_height: int = None
|
||||||
|
quickview_height: int = None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
class Visibility:
|
class Visibility:
|
||||||
tag_browser = book_details = book_list = True
|
tag_browser: bool = True
|
||||||
cover_browser = quick_view = False
|
book_details: bool = True
|
||||||
|
book_list: bool = True
|
||||||
|
cover_browser: bool = False
|
||||||
|
quick_view: bool = False
|
||||||
|
|
||||||
|
|
||||||
class Central(QWidget):
|
class Central(QWidget):
|
||||||
@ -110,6 +120,7 @@ class Central(QWidget):
|
|||||||
self.tag_browser = Placeholder('tag browser', self)
|
self.tag_browser = Placeholder('tag browser', self)
|
||||||
self.book_list = Placeholder('book list', self)
|
self.book_list = Placeholder('book list', self)
|
||||||
self.cover_browser = Placeholder('cover browser', self)
|
self.cover_browser = Placeholder('cover browser', self)
|
||||||
|
self.cover_browser.setMinimumSize(QSize(300, 150))
|
||||||
self.book_details = Placeholder('book details', self)
|
self.book_details = Placeholder('book details', self)
|
||||||
self.quick_view = Placeholder('quick view', self)
|
self.quick_view = Placeholder('quick view', self)
|
||||||
|
|
||||||
@ -130,10 +141,17 @@ class Central(QWidget):
|
|||||||
|
|
||||||
def splitter_handle_dragged(self, pos):
|
def splitter_handle_dragged(self, pos):
|
||||||
handle = self.sender()
|
handle = self.sender()
|
||||||
|
bv = copy(self.is_visible)
|
||||||
if self.layout is Layout.wide:
|
if self.layout is Layout.wide:
|
||||||
|
bd = copy(self.wide_desires)
|
||||||
self.wide_move_splitter_handle_to(handle, pos)
|
self.wide_move_splitter_handle_to(handle, pos)
|
||||||
|
ad = self.wide_desires
|
||||||
else:
|
else:
|
||||||
|
bd = copy(self.narrow_desires)
|
||||||
self.narrow_move_splitter_handle_to(handle, pos)
|
self.narrow_move_splitter_handle_to(handle, pos)
|
||||||
|
ad = self.narrow_desires
|
||||||
|
if (bv, bd) != (self.is_visible, ad):
|
||||||
|
self.relayout()
|
||||||
|
|
||||||
def refresh_after_config_change(self):
|
def refresh_after_config_change(self):
|
||||||
self.layout = Layout.narrow if config.get('gui_layout') == 'narrow' else Layout.wide
|
self.layout = Layout.narrow if config.get('gui_layout') == 'narrow' else Layout.wide
|
||||||
@ -168,12 +186,15 @@ class Central(QWidget):
|
|||||||
if handle is self.bottom_handle:
|
if handle is self.bottom_handle:
|
||||||
return HandleState.both_visible if self.is_visible.quick_view else HandleState.only_main_visible
|
return HandleState.both_visible if self.is_visible.quick_view else HandleState.only_main_visible
|
||||||
|
|
||||||
|
def min_central_width(self):
|
||||||
|
return max(200, self.cover_browser.minimumWidth())
|
||||||
|
|
||||||
def do_wide_layout(self):
|
def do_wide_layout(self):
|
||||||
s = self.style()
|
s = self.style()
|
||||||
normal_handle_width = int(s.pixelMetric(QStyle.PixelMetric.PM_SplitterWidth, widget=self))
|
normal_handle_width = int(s.pixelMetric(QStyle.PixelMetric.PM_SplitterWidth, widget=self))
|
||||||
available_width = self.width()
|
available_width = self.width()
|
||||||
for h in (self.left_handle, self.right_handle):
|
for h in (self.left_handle, self.right_handle):
|
||||||
width = 1
|
width = h.COLLAPSED_SIZE
|
||||||
hs = h.state
|
hs = h.state
|
||||||
if hs is HandleState.both_visible or hs is HandleState.only_side_visible:
|
if hs is HandleState.both_visible or hs is HandleState.only_side_visible:
|
||||||
width = normal_handle_width
|
width = normal_handle_width
|
||||||
@ -186,9 +207,9 @@ class Central(QWidget):
|
|||||||
bd = self.wide_desires.book_details_width or default_width
|
bd = self.wide_desires.book_details_width or default_width
|
||||||
if not self.is_visible.book_details:
|
if not self.is_visible.book_details:
|
||||||
bd = 0
|
bd = 0
|
||||||
min_book_list_width = max(200, self.cover_browser.minimumWidth(), available_width // 10)
|
min_central_width = self.min_central_width()
|
||||||
if tb + bd > available_width - min_book_list_width:
|
if tb + bd > available_width - min_central_width:
|
||||||
width_to_share = max(0, available_width - min_book_list_width)
|
width_to_share = max(0, available_width - min_central_width)
|
||||||
tb = int(tb * width_to_share / (tb + bd))
|
tb = int(tb * width_to_share / (tb + bd))
|
||||||
bd = width_to_share - tb
|
bd = width_to_share - tb
|
||||||
central_width = available_width - (tb + bd)
|
central_width = available_width - (tb + bd)
|
||||||
@ -200,13 +221,13 @@ class Central(QWidget):
|
|||||||
|
|
||||||
available_height = self.height()
|
available_height = self.height()
|
||||||
for h in (self.top_handle, self.bottom_handle):
|
for h in (self.top_handle, self.bottom_handle):
|
||||||
height = 1
|
height = h.COLLAPSED_SIZE
|
||||||
hs = h.state
|
hs = h.state
|
||||||
if hs is HandleState.both_visible or hs is HandleState.only_side_visible:
|
if hs is HandleState.both_visible or hs is HandleState.only_side_visible:
|
||||||
height = normal_handle_width
|
height = normal_handle_width
|
||||||
if h is self.bottom_handle and hs is HandleState.only_main_visible:
|
if h is self.bottom_handle and hs is HandleState.only_main_visible:
|
||||||
height = 0
|
height = 0
|
||||||
h.resize(self.width(), height)
|
h.resize(central_width, height)
|
||||||
available_height -= height
|
available_height -= height
|
||||||
|
|
||||||
cb = max(self.cover_browser.minimumHeight(), self.wide_desires.cover_browser_height or (2 * available_height // 5))
|
cb = max(self.cover_browser.minimumHeight(), self.wide_desires.cover_browser_height or (2 * available_height // 5))
|
||||||
@ -230,7 +251,41 @@ class Central(QWidget):
|
|||||||
self.quick_view.setGeometry(central_x, self.bottom_handle.y() + self.bottom_handle.height(), central_width, qv)
|
self.quick_view.setGeometry(central_x, self.bottom_handle.y() + self.bottom_handle.height(), central_width, qv)
|
||||||
|
|
||||||
def wide_move_splitter_handle_to(self, handle: SplitterHandle, pos: QPointF):
|
def wide_move_splitter_handle_to(self, handle: SplitterHandle, pos: QPointF):
|
||||||
raise NotImplementedError('TODO: Implement me')
|
if handle is self.left_handle:
|
||||||
|
x = int(pos.x())
|
||||||
|
available_width = self.width() - self.left_handle.width() - self.right_handle.width()
|
||||||
|
self.is_visible.tag_browser = True
|
||||||
|
if x < 10:
|
||||||
|
self.is_visible.tag_browser = False
|
||||||
|
self.wide_desires.tag_browser_width = 10
|
||||||
|
elif x > available_width - self.min_central_width():
|
||||||
|
self.wide_desires.tag_browser_width = available_width - self.min_central_width()
|
||||||
|
else:
|
||||||
|
self.wide_desires.tag_browser_width = x
|
||||||
|
elif handle is self.right_handle:
|
||||||
|
x = int(pos.x())
|
||||||
|
available_width = self.width() - self.left_handle.width() - self.right_handle.width()
|
||||||
|
self.is_visible.book_details = True
|
||||||
|
w = self.width() - x - self.right_handle.width()
|
||||||
|
if w < 10:
|
||||||
|
self.is_visible.book_details = False
|
||||||
|
self.wide_desires.book_details_width = 10
|
||||||
|
elif w > available_width - self.min_central_width():
|
||||||
|
self.wide_desires.book_details_width = available_width - self.min_central_width()
|
||||||
|
else:
|
||||||
|
self.wide_desires.book_details_width = w
|
||||||
|
elif handle is self.top_handle:
|
||||||
|
y = int(pos.y())
|
||||||
|
self.is_visible.cover_browser = True
|
||||||
|
if y < max(self.cover_browser.minimumHeight(), 10):
|
||||||
|
self.is_visible.cover_browser = False
|
||||||
|
self.wide_desires.cover_browser_height = max(10, self.cover_browser.minimumHeight())
|
||||||
|
else:
|
||||||
|
self.wide_desires.cover_browser_height = max(y, self.cover_browser.minimumHeight())
|
||||||
|
elif handle is self.bottom_handle:
|
||||||
|
y = int(pos.y())
|
||||||
|
available_height = self.height() - self.top_handle.height() - self.bottom_handle.height()
|
||||||
|
available_height
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
# Narrow {{{
|
# Narrow {{{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user