The `status_label` displays what is currently going on with the game. It reflects the current operation running on it or if it requires special attention (update, needs verification etc) The `tooltip_label` displays hover information such as what happens if a part of the widget is clicked or in the case of the launch button if the game can run (without version check, offline etc) The context menu on the widgets will be updated and populated according to the installation state of the game. Since the context menu was revised the shortcut creation code was revised too to make it more compact. the `create_desktop_link` and `get_rare_executable` functions are moved from `rare.utils.misc` to `rare.utils.paths` to avoid cyclical imports and better grouping. Two functions are added, `desktop_link_path` to uniformly calculate the path of the shortcut and `desktop_links_supported` which checks if Rare supports creating shortcuts on the current platform. `desktop_links_supported` should be used as safeguard before `desktop_link_path`. Desktop links are currently untested on Windows but if `shortcut.Description` works as expected, it should be good to go.
183 lines
6.7 KiB
Python
183 lines
6.7 KiB
Python
from PyQt5.QtCore import Qt, QPropertyAnimation, QEasingCurve, QSize
|
|
from PyQt5.QtWidgets import (
|
|
QWidget,
|
|
QVBoxLayout,
|
|
QGraphicsOpacityEffect,
|
|
QSpacerItem,
|
|
QSizePolicy,
|
|
QHBoxLayout,
|
|
QLabel,
|
|
QPushButton,
|
|
)
|
|
|
|
from rare.utils.misc import icon
|
|
from rare.widgets.elide_label import ElideLabel
|
|
|
|
|
|
class IconWidget(object):
|
|
def __init__(self):
|
|
self._effect = None
|
|
self._animation: QPropertyAnimation = None
|
|
|
|
self.status_label: ElideLabel = None
|
|
self.mini_widget: QWidget = None
|
|
self.mini_effect: QGraphicsOpacityEffect = None
|
|
self.title_label: QLabel = None
|
|
self.tooltip_label: ElideLabel = None
|
|
self.launch_btn: QPushButton = None
|
|
self.install_btn: QPushButton = None
|
|
|
|
def setupUi(self, widget: QWidget):
|
|
# information at top
|
|
self.status_label = ElideLabel(parent=widget)
|
|
self.status_label.setObjectName(f"{type(self).__name__}StatusLabel")
|
|
self.status_label.setStyleSheet(
|
|
f"QLabel#{self.status_label.objectName()}"
|
|
"{"
|
|
"font-weight: bold;"
|
|
"color: white;"
|
|
"background-color: rgba(0, 0, 0, 65%);"
|
|
"border-radius: 5%;"
|
|
"border-top-left-radius: 11%;"
|
|
"border-top-right-radius: 11%;"
|
|
"}"
|
|
)
|
|
self.status_label.setContentsMargins(6, 6, 6, 6)
|
|
self.status_label.setAutoFillBackground(False)
|
|
|
|
# on-hover popup
|
|
self.mini_widget = QWidget(parent=widget)
|
|
self.mini_widget.setObjectName(f"{type(self).__name__}MiniWidget")
|
|
self.mini_widget.setStyleSheet(
|
|
f"QWidget#{self.mini_widget.objectName()}"
|
|
"{"
|
|
"color: rgb(238, 238, 238);"
|
|
"background-color: rgba(0, 0, 0, 65%);"
|
|
"border-radius: 5%;"
|
|
"border-bottom-left-radius: 9%;"
|
|
"border-bottom-right-radius: 9%;"
|
|
"}"
|
|
)
|
|
self.mini_widget.setFixedHeight(widget.height() // 3)
|
|
|
|
self.mini_effect = QGraphicsOpacityEffect(self.mini_widget)
|
|
self.mini_widget.setGraphicsEffect(self.mini_effect)
|
|
|
|
# game title
|
|
self.title_label = QLabel(parent=self.mini_widget)
|
|
self.title_label.setObjectName(f"{type(self).__name__}TitleLabel")
|
|
self.title_label.setStyleSheet(
|
|
f"QLabel#{self.title_label.objectName()}"
|
|
"{"
|
|
"font-weight: bold;"
|
|
"background-color: rgba(0, 0, 0, 0%); color: white;"
|
|
"}"
|
|
)
|
|
self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
self.title_label.setAlignment(Qt.AlignVCenter)
|
|
self.title_label.setAutoFillBackground(False)
|
|
self.title_label.setWordWrap(True)
|
|
|
|
# information below title
|
|
self.tooltip_label = ElideLabel(parent=self.mini_widget)
|
|
self.tooltip_label.setObjectName(f"{type(self).__name__}StatusLabel")
|
|
self.tooltip_label.setStyleSheet(
|
|
f"QLabel#{self.tooltip_label.objectName()}"
|
|
"{"
|
|
"background-color: rgba(0, 0, 0, 0%); color: white;"
|
|
"}"
|
|
)
|
|
self.tooltip_label.setAutoFillBackground(False)
|
|
|
|
# play button
|
|
self.launch_btn = QPushButton(parent=self.mini_widget)
|
|
self.launch_btn.setObjectName(f"{type(self).__name__}LaunchButton")
|
|
self.launch_btn.setStyleSheet(
|
|
f"QPushButton#{self.launch_btn.objectName()}"
|
|
"{"
|
|
"border-radius: 10%;"
|
|
"background-color: rgba(0, 0, 0, 65%);"
|
|
"border-color: black; border-width: 1px;"
|
|
"}"
|
|
f"QPushButton#{self.launch_btn.objectName()}::hover"
|
|
"{"
|
|
"border-color: gray;"
|
|
"}"
|
|
)
|
|
self.launch_btn.setIcon(icon("ei.play-alt", color="white"))
|
|
self.launch_btn.setIconSize(QSize(20, 20))
|
|
self.launch_btn.setFixedSize(QSize(widget.width() // 4, widget.width() // 4))
|
|
|
|
self.install_btn = QPushButton(parent=self.mini_widget)
|
|
self.install_btn.setObjectName(f"{type(self).__name__}InstallButton")
|
|
self.install_btn.setStyleSheet(
|
|
f"QPushButton#{self.install_btn.objectName()}"
|
|
"{"
|
|
"border-radius: 10%;"
|
|
"background-color: rgba(0, 0, 0, 65%);"
|
|
"border-color: black; border-width: 1px;"
|
|
"}"
|
|
f"QPushButton#{self.install_btn.objectName()}::hover"
|
|
"{"
|
|
"border-color: gray;"
|
|
"}"
|
|
)
|
|
self.install_btn.setIcon(icon("ri.install-fill", color="white"))
|
|
self.install_btn.setIconSize(QSize(20, 20))
|
|
self.install_btn.setFixedSize(QSize(widget.width() // 4, widget.width() // 4))
|
|
|
|
# Create layouts
|
|
# layout for the image, holds the mini widget and a spacer item
|
|
image_layout = QVBoxLayout()
|
|
image_layout.setContentsMargins(2, 2, 2, 2)
|
|
|
|
# layout for the mini widget, holds the top row and the info label
|
|
mini_layout = QVBoxLayout()
|
|
mini_layout.setSpacing(0)
|
|
|
|
# layout for the top row, holds the title and the launch button
|
|
row_layout = QHBoxLayout()
|
|
row_layout.setSpacing(0)
|
|
row_layout.setAlignment(Qt.AlignTop)
|
|
|
|
# Layout the widgets
|
|
# (from inner to outer)
|
|
row_layout.addWidget(self.title_label, stretch=2)
|
|
row_layout.addWidget(self.launch_btn)
|
|
row_layout.addWidget(self.install_btn)
|
|
mini_layout.addLayout(row_layout, stretch=2)
|
|
mini_layout.addWidget(self.tooltip_label)
|
|
self.mini_widget.setLayout(mini_layout)
|
|
|
|
image_layout.addWidget(self.status_label)
|
|
image_layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
|
|
image_layout.addWidget(self.mini_widget)
|
|
widget.setLayout(image_layout)
|
|
|
|
# layout.addWidget(widget.image)
|
|
# widget.setLayout(layout)
|
|
|
|
widget.setContextMenuPolicy(Qt.ActionsContextMenu)
|
|
widget.leaveEvent(None)
|
|
|
|
self.translateUi(widget)
|
|
|
|
def translateUi(self, widget: QWidget):
|
|
pass
|
|
|
|
def enterAnimation(self, widget: QWidget):
|
|
self._animation = QPropertyAnimation(self.mini_effect, b"opacity")
|
|
self._animation.setDuration(250)
|
|
self._animation.setStartValue(0)
|
|
self._animation.setEndValue(1)
|
|
self._animation.setEasingCurve(QEasingCurve.InSine)
|
|
self._animation.start(QPropertyAnimation.DeleteWhenStopped)
|
|
|
|
def leaveAnimation(self, widget: QWidget):
|
|
self._animation = QPropertyAnimation(self.mini_effect, b"opacity")
|
|
self._animation.setDuration(150)
|
|
self._animation.setStartValue(1)
|
|
self._animation.setEndValue(0)
|
|
self._animation.setEasingCurve(QEasingCurve.OutSine)
|
|
self._animation.start(QPropertyAnimation.DeleteWhenStopped)
|