1
0
Fork 0
mirror of synced 2024-06-29 03:31:06 +12:00
Rare/rare/components/tabs/downloads/groups.py
loathingKernel a3d09ae288 Code cleanup: Use pass instead of ellipsis (...) for abstractmethods
Fix a few other issues pointed out by MultisampledNight

Signed-off-by: loathingKernel <142770+loathingKernel@users.noreply.github.com>
2023-02-20 15:31:04 +02:00

225 lines
8.4 KiB
Python

from collections import deque
from enum import IntEnum
from logging import getLogger
from typing import Optional, Deque
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
from PyQt5.QtWidgets import (
QWidget,
QGroupBox,
QVBoxLayout,
QLabel,
QSizePolicy,
)
from legendary.models.game import Game, InstalledGame
from rare.components.tabs.downloads.widgets import QueueWidget, UpdateWidget
from rare.models.install import InstallOptionsModel, InstallQueueItemModel
from rare.utils.misc import widget_object_name
logger = getLogger("QueueGroup")
class UpdateGroup(QGroupBox):
update_count = pyqtSignal(int)
enqueue = pyqtSignal(InstallOptionsModel)
def __init__(self, parent=None):
super(UpdateGroup, self).__init__(parent=parent)
self.setObjectName(type(self).__name__)
self.setTitle(self.tr("Updates"))
self.__text = QLabel(self.tr("No updates available"))
self.__text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
# lk: For findChildren to work, the update's layout has to be in a widget
self.__container = QWidget(self)
self.__container.setVisible(False)
container_layout = QVBoxLayout(self.__container)
container_layout.setContentsMargins(0, 0, 0, 0)
layout = QVBoxLayout(self)
layout.addWidget(self.__text)
layout.addWidget(self.__container)
def __find_widget(self, app_name: str) -> Optional[UpdateWidget]:
return self.__container.findChild(UpdateWidget, name=widget_object_name(UpdateWidget, app_name))
def count(self) -> int:
return len(self.__container.findChildren(UpdateWidget, options=Qt.FindDirectChildrenOnly))
def contains(self, app_name: str) -> bool:
return self.__find_widget(app_name) is not None
def __update_group(self):
count = self.count()
self.__text.setVisible(not count)
self.__container.setVisible(bool(count))
self.update_count.emit(count)
def append(self, game: Game, igame: InstalledGame):
self.__text.setVisible(False)
self.__container.setVisible(True)
widget: UpdateWidget = self.__find_widget(game.app_name)
if widget is not None:
self.__container.layout().removeWidget(widget)
widget.deleteLater()
widget = UpdateWidget(game, igame, parent=self.__container)
widget.destroyed.connect(self.__update_group)
widget.enqueue.connect(self.enqueue)
self.__container.layout().addWidget(widget)
def remove(self, app_name: str):
widget: UpdateWidget = self.__find_widget(app_name)
self.__container.layout().removeWidget(widget)
widget.deleteLater()
def set_widget_enabled(self, app_name: str, enabled: bool):
widget: UpdateWidget = self.__find_widget(app_name)
widget.set_enabled(enabled)
def get_widget_version(self, app_name: str) -> str:
widget: UpdateWidget = self.__find_widget(app_name)
return widget.version()
class QueueGroup(QGroupBox):
update_count = pyqtSignal(int)
removed = pyqtSignal(str)
force = pyqtSignal(InstallQueueItemModel)
def __init__(self, parent=None):
super(QueueGroup, self).__init__(parent=parent)
self.setObjectName(type(self).__name__)
self.setTitle(self.tr("Queue"))
self.__text = QLabel(self.tr("No downloads in queue"), self)
self.__text.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
# lk: For findChildren to work, the queue's layout has to be in a widget
self.__container = QWidget(self)
self.__container.setVisible(False)
container_layout = QVBoxLayout(self.__container)
container_layout.setContentsMargins(0, 0, 0, 0)
layout = QVBoxLayout(self)
layout.addWidget(self.__text)
layout.addWidget(self.__container)
self.__queue: Deque[str] = deque()
def __find_widget(self, app_name: str) -> Optional[QueueWidget]:
return self.__container.findChild(QueueWidget, name=widget_object_name(QueueWidget, app_name))
def count(self) -> int:
return len(self.__queue)
def contains(self, app_name: str) -> bool:
if app_name in self.__queue:
return self.__find_widget(app_name) is not None
else:
return False
def __update_group(self):
count = self.count()
self.__text.setVisible(not count)
self.__container.setVisible(bool(count))
self.update_count.emit(count)
def __create_widget(self, item: InstallQueueItemModel, old_igame: InstalledGame) -> QueueWidget:
widget: QueueWidget = QueueWidget(item, old_igame, parent=self.__container)
widget.toggle_arrows(self.__queue.index(item.options.app_name), len(self.__queue))
widget.destroyed.connect(self.__update_group)
widget.destroyed.connect(self.__update_arrows)
widget.remove.connect(self.remove)
widget.force.connect(self.__on_force)
widget.move_up.connect(self.__on_move_up)
widget.move_down.connect(self.__on_move_down)
return widget
def push_front(self, item: InstallQueueItemModel, old_igame: InstalledGame):
self.__text.setVisible(False)
self.__container.setVisible(True)
self.__queue.appendleft(item.options.app_name)
widget = self.__create_widget(item, old_igame)
self.__container.layout().insertWidget(0, widget)
if self.count() > 1:
app_name = self.__queue[1]
other: QueueWidget = self.__find_widget(app_name)
other.toggle_arrows(1, len(self.__queue))
def push_back(self, item: InstallQueueItemModel, old_igame: InstalledGame):
self.__text.setVisible(False)
self.__container.setVisible(True)
self.__queue.append(item.download.game.app_name)
widget = self.__create_widget(item, old_igame)
self.__container.layout().addWidget(widget)
if self.count() > 1:
app_name = self.__queue[-2]
other: QueueWidget = self.__find_widget(app_name)
other.toggle_arrows(len(self.__queue) - 2, len(self.__queue))
def pop_front(self) -> InstallQueueItemModel:
app_name = self.__queue.popleft()
widget: QueueWidget = self.__find_widget(app_name)
item = widget.item
widget.deleteLater()
return item
def __update_arrows(self):
"""
Check the first, second, last and second to last widgets in the list
and update their arrows
:return: None
"""
for idx in [0, 1]:
if self.count() > idx:
app_name = self.__queue[idx]
widget: QueueWidget = self.__find_widget(app_name)
widget.toggle_arrows(idx, len(self.__queue))
for idx in [1, 2]:
if self.count() > idx:
app_name = self.__queue[-idx]
widget: QueueWidget = self.__find_widget(app_name)
widget.toggle_arrows(len(self.__queue) - idx, len(self.__queue))
def __remove(self, app_name: str):
self.__queue.remove(app_name)
widget: QueueWidget = self.__find_widget(app_name)
self.__container.layout().removeWidget(widget)
widget.deleteLater()
@pyqtSlot(str)
def remove(self, app_name: str):
self.__remove(app_name)
self.removed.emit(app_name)
@pyqtSlot(InstallQueueItemModel)
def __on_force(self, item: InstallQueueItemModel):
self.__remove(item.options.app_name)
self.force.emit(item)
class MoveDirection(IntEnum):
UP = -1
DOWN = 1
def __move(self, app_name: str, direction: MoveDirection):
"""
Moved the widget for `app_name` up or down in the queue and the container
:param app_name: The app_name associated with the widget
:param direction: -1 to move up, +1 to move down
:return: None
"""
index = self.__queue.index(app_name)
self.__queue.remove(app_name)
self.__queue.insert(index + int(direction), app_name)
widget: QueueWidget = self.__find_widget(app_name)
self.__container.layout().insertWidget(index + int(direction), widget)
self.__update_arrows()
@pyqtSlot(str)
def __on_move_up(self, app_name: str):
self.__move(app_name, QueueGroup.MoveDirection.UP)
@pyqtSlot(str)
def __on_move_down(self, app_name: str):
self.__move(app_name, QueueGroup.MoveDirection.DOWN)