1
0
Fork 0
mirror of synced 2024-05-04 12:42:52 +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 typing import Optional, Tuple, Iterable
from PyQt5.QtCore import pyqtSignal, QSize, Qt, QMimeData, pyqtSlot
from PyQt5.QtGui import QDrag, QDropEvent, QDragEnterEvent, QDragMoveEvent, QFont, QMouseEvent, QShowEvent
from PyQt5.QtCore import pyqtSignal, QSize, Qt, QMimeData, pyqtSlot, QObject, QEvent
from PyQt5.QtGui import (
QDrag,
QDropEvent,
QDragEnterEvent,
QDragMoveEvent,
QFont,
QMouseEvent,
QShowEvent,
QResizeEvent,
)
from PyQt5.QtWidgets import (
QHBoxLayout,
QLabel,
@ -15,7 +24,11 @@ from PyQt5.QtWidgets import (
QWidget,
QScrollArea,
QAction,
QMenu, QStackedWidget, QPushButton, QLineEdit, QVBoxLayout, QComboBox,
QMenu,
QPushButton,
QLineEdit,
QVBoxLayout,
QComboBox,
)
from rare.models.wrapper import Wrapper
@ -172,46 +185,75 @@ class WrapperWidget(QFrame):
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):
def __init__(self, parent=None):
super(WrapperSettings, self).__init__(parent=parent)
self.widget_stack = QStackedWidget(self)
self.wrapper_scroll = QScrollArea(self.widget_stack)
self.wrapper_scroll.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
self.wrapper_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
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.wrapper_label = QLabel(self.tr("No wrappers defined"), self)
self.wrapper_label.setFrameStyle(QLabel.StyledPanel | QLabel.Plain)
self.wrapper_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.add_button = QPushButton(self.tr("Add wrapper"), self)
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
self.setObjectName("WrapperSettings")
self.no_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")
self.wrapper_label.setObjectName(f"{self.objectName()}Label")
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.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.core = RareCore.instance().core()
@ -223,27 +265,6 @@ class WrapperSettings(QWidget):
self.update_state()
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)
def __on_order_changed(self, widget: WrapperWidget, new_index: int):
wrapper = widget.data()
@ -266,16 +287,12 @@ class WrapperSettings(QWidget):
self.add_user_wrapper(wrapper)
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)
if position < 0:
self.wrapper_container.addWidget(widget)
else:
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.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):
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
@ -314,7 +333,7 @@ class WrapperSettings(QWidget):
self.tr("Warning"),
self.tr("Wrapper <b>{0}</b> is not in $PATH. Add it anyway?").format(wrapper.executable),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No
QMessageBox.No,
)
if ans == QMessageBox.No:
return
@ -327,8 +346,7 @@ class WrapperSettings(QWidget):
wrappers.remove(wrapper)
self.wrappers.set_game_wrapper_list(self.app_name, wrappers)
if not wrappers:
self.wrapper_scroll.setMaximumHeight(self.no_wrapper_label.sizeHint().height())
self.widget_stack.setCurrentWidget(self.no_wrapper_label)
self.wrapper_label.setVisible(True)
@pyqtSlot(object, object)
def __update_wrapper(self, old: Wrapper, new: Wrapper):
@ -345,10 +363,7 @@ class WrapperSettings(QWidget):
w.deleteLater()
wrappers = self.wrappers.get_game_wrapper_list(self.app_name)
if not wrappers:
self.wrapper_scroll.setMaximumHeight(self.no_wrapper_label.sizeHint().height())
self.widget_stack.setCurrentWidget(self.no_wrapper_label)
else:
self.widget_stack.setCurrentWidget(self.wrapper_scroll)
self.wrapper_label.setVisible(True)
for wrapper in wrappers:
self.__add_wrapper(wrapper)
@ -357,15 +372,19 @@ class WrapperContainer(QWidget):
# QWidget: moving widget, int: new index
orderChanged: pyqtSignal = pyqtSignal(QWidget, int)
def __init__(self, parent=None):
def __init__(self, label: QLabel, parent=None):
super(WrapperContainer, self).__init__(parent=parent)
self.setAcceptDrops(True)
self.__layout = QHBoxLayout(self)
self.__layout.setContentsMargins(0, 0, 0, 0)
self.__layout.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.__layout = QHBoxLayout()
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
self.setObjectName(type(self).__name__)