1
0
Fork 0
mirror of synced 2024-05-22 21:42:49 +12:00

WrapperSettings: Improve widget structure

* Remove the annoying stacked widget, instead create a double layout in
the container and place a label in that to hold the placeholder message.

* Implement the scroll area as a custom widget. This custom widget installs
an event filter on the container to adjust the scrollarea size when the
container size changes.
This commit is contained in:
loathingKernel 2024-02-24 13:11:28 +02:00
parent 6cfec6c718
commit e50015c25c
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD

View file

@ -4,8 +4,17 @@ import shutil
from logging import getLogger from logging import getLogger
from typing import Optional, Tuple, Iterable from typing import Optional, Tuple, Iterable
from PyQt5.QtCore import pyqtSignal, QSize, Qt, QMimeData, pyqtSlot from PyQt5.QtCore import pyqtSignal, QSize, Qt, QMimeData, pyqtSlot, QObject, QEvent
from PyQt5.QtGui import QDrag, QDropEvent, QDragEnterEvent, QDragMoveEvent, QFont, QMouseEvent, QShowEvent from PyQt5.QtGui import (
QDrag,
QDropEvent,
QDragEnterEvent,
QDragMoveEvent,
QFont,
QMouseEvent,
QShowEvent,
QResizeEvent,
)
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QHBoxLayout, QHBoxLayout,
QLabel, QLabel,
@ -15,7 +24,11 @@ from PyQt5.QtWidgets import (
QWidget, QWidget,
QScrollArea, QScrollArea,
QAction, QAction,
QMenu, QStackedWidget, QPushButton, QLineEdit, QVBoxLayout, QComboBox, QMenu,
QPushButton,
QLineEdit,
QVBoxLayout,
QComboBox,
) )
from rare.models.wrapper import Wrapper from rare.models.wrapper import Wrapper
@ -172,46 +185,75 @@ class WrapperWidget(QFrame):
drag.exec_(Qt.MoveAction) drag.exec_(Qt.MoveAction)
class WrapperSettingsScroll(QScrollArea):
def __init__(self, parent=None):
super(WrapperSettingsScroll, self).__init__(parent=parent)
self.setFrameShape(QFrame.StyledPanel)
self.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.setWidgetResizable(True)
self.setProperty("no_kinetic_scroll", True)
self.setObjectName(type(self).__name__)
self.horizontalScrollBar().setObjectName(f"{self.objectName()}Bar")
self.verticalScrollBar().setObjectName(f"{self.objectName()}Bar")
def setWidget(self, w):
super().setWidget(w)
w.installEventFilter(self)
def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
if a0 is self.widget() and a1.type() == QEvent.Resize:
self.__resize(a0)
return a0.event(a1)
return False
def __resize(self, e: QResizeEvent):
minh = self.horizontalScrollBar().minimum()
maxh = self.horizontalScrollBar().maximum()
# lk: when the scrollbar is not visible, min and max are 0
if maxh > minh:
height = (
e.size().height()
+ self.rect().height() // 2
- self.contentsRect().height() // 2
+ self.widget().layout().spacing()
+ self.horizontalScrollBar().sizeHint().height()
)
else:
height = e.size().height() + self.rect().height() - self.contentsRect().height()
self.setMaximumHeight(max(height, self.minimumHeight()))
class WrapperSettings(QWidget): class WrapperSettings(QWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
super(WrapperSettings, self).__init__(parent=parent) super(WrapperSettings, self).__init__(parent=parent)
self.widget_stack = QStackedWidget(self)
self.wrapper_scroll = QScrollArea(self.widget_stack) self.wrapper_label = QLabel(self.tr("No wrappers defined"), self)
self.wrapper_scroll.setSizeAdjustPolicy(QScrollArea.AdjustToContents) self.wrapper_label.setFrameStyle(QLabel.StyledPanel | QLabel.Plain)
self.wrapper_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.wrapper_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.wrapper_scroll.setWidgetResizable(True)
self.wrapper_scroll.setProperty("no_kinetic_scroll", True)
self.wrapper_container = WrapperContainer(parent=self.wrapper_scroll)
self.wrapper_container.orderChanged.connect(self.__on_order_changed)
self.wrapper_scroll.setWidget(self.wrapper_container)
self.no_wrapper_label = QLabel(self.tr("No wrappers defined"), self.widget_stack)
self.widget_stack.addWidget(self.wrapper_scroll)
self.widget_stack.addWidget(self.no_wrapper_label)
self.add_button = QPushButton(self.tr("Add wrapper"), self) self.add_button = QPushButton(self.tr("Add wrapper"), self)
self.add_button.clicked.connect(self.__on_add) self.add_button.clicked.connect(self.__on_add)
self.wrapper_scroll.horizontalScrollBar().rangeChanged.connect(self.adjust_scrollarea) self.wrapper_scroll = WrapperSettingsScroll(self)
self.wrapper_scroll.setMinimumHeight(self.add_button.minimumSizeHint().height())
self.wrapper_container = WrapperContainer(self.wrapper_label, self.wrapper_scroll)
self.wrapper_container.orderChanged.connect(self.__on_order_changed)
self.wrapper_scroll.setWidget(self.wrapper_container)
# lk: set object names for the stylesheet # lk: set object names for the stylesheet
self.setObjectName("WrapperSettings") self.setObjectName("WrapperSettings")
self.no_wrapper_label.setObjectName(f"{self.objectName()}Label") self.wrapper_label.setObjectName(f"{self.objectName()}Label")
self.wrapper_scroll.setObjectName(f"{self.objectName()}Scroll")
self.wrapper_scroll.horizontalScrollBar().setObjectName(
f"{self.wrapper_scroll.objectName()}Bar")
self.wrapper_scroll.verticalScrollBar().setObjectName(
f"{self.wrapper_scroll.objectName()}Bar")
main_layout = QHBoxLayout(self) main_layout = QHBoxLayout(self)
main_layout.addWidget(self.widget_stack)
main_layout.addWidget(self.add_button, alignment=Qt.AlignTop)
main_layout.setContentsMargins(0, 0, 0, 0) main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setAlignment(Qt.AlignTop) main_layout.addWidget(self.wrapper_scroll, alignment=Qt.AlignTop)
main_layout.addWidget(self.add_button, alignment=Qt.AlignTop)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.app_name: str = "default" self.app_name: str = "default"
self.core = RareCore.instance().core() self.core = RareCore.instance().core()
@ -223,27 +265,6 @@ class WrapperSettings(QWidget):
self.update_state() self.update_state()
return super().showEvent(a0) return super().showEvent(a0)
@pyqtSlot(int, int)
def adjust_scrollarea(self, minh: int, maxh: int):
wrapper_widget = self.wrapper_container.findChild(WrapperWidget)
if not wrapper_widget:
return
# lk: when the scrollbar is not visible, min and max are 0
if maxh > minh:
self.wrapper_scroll.setMaximumHeight(
wrapper_widget.sizeHint().height()
+ self.wrapper_scroll.rect().height() // 2
- self.wrapper_scroll.contentsRect().height() // 2
+ self.wrapper_container.layout().spacing()
+ self.wrapper_scroll.horizontalScrollBar().sizeHint().height()
)
else:
self.wrapper_scroll.setMaximumHeight(
wrapper_widget.sizeHint().height()
+ self.wrapper_scroll.rect().height()
- self.wrapper_scroll.contentsRect().height()
)
@pyqtSlot(QWidget, int) @pyqtSlot(QWidget, int)
def __on_order_changed(self, widget: WrapperWidget, new_index: int): def __on_order_changed(self, widget: WrapperWidget, new_index: int):
wrapper = widget.data() wrapper = widget.data()
@ -266,16 +287,12 @@ class WrapperSettings(QWidget):
self.add_user_wrapper(wrapper) self.add_user_wrapper(wrapper)
def __add_wrapper(self, wrapper: Wrapper, position: int = -1): def __add_wrapper(self, wrapper: Wrapper, position: int = -1):
self.widget_stack.setCurrentWidget(self.wrapper_scroll) self.wrapper_label.setVisible(False)
widget = WrapperWidget(wrapper, self.wrapper_container) widget = WrapperWidget(wrapper, self.wrapper_container)
if position < 0: if position < 0:
self.wrapper_container.addWidget(widget) self.wrapper_container.addWidget(widget)
else: else:
self.wrapper_container.insertWidget(position, widget) self.wrapper_container.insertWidget(position, widget)
self.adjust_scrollarea(
self.wrapper_scroll.horizontalScrollBar().minimum(),
self.wrapper_scroll.horizontalScrollBar().maximum(),
)
widget.update_wrapper.connect(self.__update_wrapper) widget.update_wrapper.connect(self.__update_wrapper)
widget.delete_wrapper.connect(self.__delete_wrapper) widget.delete_wrapper.connect(self.__delete_wrapper)
@ -304,7 +321,9 @@ class WrapperSettings(QWidget):
if wrapper.checksum in self.wrappers.get_game_md5sum_list(self.app_name): if wrapper.checksum in self.wrappers.get_game_md5sum_list(self.app_name):
QMessageBox.warning( QMessageBox.warning(
self, self.tr("Warning"), self.tr("Wrapper <b>{0}</b> is already in the list").format(wrapper.as_str) self,
self.tr("Warning"),
self.tr("Wrapper <b>{0}</b> is already in the list").format(wrapper.as_str),
) )
return return
@ -314,7 +333,7 @@ class WrapperSettings(QWidget):
self.tr("Warning"), self.tr("Warning"),
self.tr("Wrapper <b>{0}</b> is not in $PATH. Add it anyway?").format(wrapper.executable), self.tr("Wrapper <b>{0}</b> is not in $PATH. Add it anyway?").format(wrapper.executable),
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes | QMessageBox.No,
QMessageBox.No QMessageBox.No,
) )
if ans == QMessageBox.No: if ans == QMessageBox.No:
return return
@ -327,8 +346,7 @@ class WrapperSettings(QWidget):
wrappers.remove(wrapper) wrappers.remove(wrapper)
self.wrappers.set_game_wrapper_list(self.app_name, wrappers) self.wrappers.set_game_wrapper_list(self.app_name, wrappers)
if not wrappers: if not wrappers:
self.wrapper_scroll.setMaximumHeight(self.no_wrapper_label.sizeHint().height()) self.wrapper_label.setVisible(True)
self.widget_stack.setCurrentWidget(self.no_wrapper_label)
@pyqtSlot(object, object) @pyqtSlot(object, object)
def __update_wrapper(self, old: Wrapper, new: Wrapper): def __update_wrapper(self, old: Wrapper, new: Wrapper):
@ -345,10 +363,7 @@ class WrapperSettings(QWidget):
w.deleteLater() w.deleteLater()
wrappers = self.wrappers.get_game_wrapper_list(self.app_name) wrappers = self.wrappers.get_game_wrapper_list(self.app_name)
if not wrappers: if not wrappers:
self.wrapper_scroll.setMaximumHeight(self.no_wrapper_label.sizeHint().height()) self.wrapper_label.setVisible(True)
self.widget_stack.setCurrentWidget(self.no_wrapper_label)
else:
self.widget_stack.setCurrentWidget(self.wrapper_scroll)
for wrapper in wrappers: for wrapper in wrappers:
self.__add_wrapper(wrapper) self.__add_wrapper(wrapper)
@ -357,15 +372,19 @@ class WrapperContainer(QWidget):
# QWidget: moving widget, int: new index # QWidget: moving widget, int: new index
orderChanged: pyqtSignal = pyqtSignal(QWidget, int) orderChanged: pyqtSignal = pyqtSignal(QWidget, int)
def __init__(self, parent=None): def __init__(self, label: QLabel, parent=None):
super(WrapperContainer, self).__init__(parent=parent) super(WrapperContainer, self).__init__(parent=parent)
self.setAcceptDrops(True) self.setAcceptDrops(True)
self.__layout = QHBoxLayout(self) self.__layout = QHBoxLayout()
self.__layout.setContentsMargins(0, 0, 0, 0)
self.__layout.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.__drag_widget: Optional[QWidget] = None self.__drag_widget: Optional[QWidget] = None
main_layout = QHBoxLayout(self)
main_layout.addWidget(label)
main_layout.addLayout(self.__layout)
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
main_layout.setSizeConstraint(QHBoxLayout.SetFixedSize)
# lk: set object names for the stylesheet # lk: set object names for the stylesheet
self.setObjectName(type(self).__name__) self.setObjectName(type(self).__name__)