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:
parent
6cfec6c718
commit
e50015c25c
|
@ -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__)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue