191 lines
7.0 KiB
Python

from PySide6.QtCore import QModelIndex, Qt, Signal, Slot
from PySide6.QtGui import QFont, QIcon, QKeySequence, QShortcut
from PySide6.QtWidgets import (
QListWidget,
QListWidgetItem,
QPushButton,
QVBoxLayout,
QWidget,
)
from ui.navigation.navhost import NavHost, NavItem, navHost
from ui.widgets.slidingstackedwidget import SlidingStackedWidget
class NavItemListWidget(QListWidget):
NavItemRole = Qt.ItemDataRole.UserRole
def __init__(self, parent=None):
super().__init__(parent)
font = QFont(self.font())
font.setPointSize(14)
self.setFont(font)
self.clicked.connect(self.activated)
def setNavItems(self, items: list[NavItem]):
self.clear()
for navItem in items:
if navItem.icon:
listWidgetItem = QListWidgetItem(QIcon(navItem.icon), navItem.text())
else:
listWidgetItem = QListWidgetItem(navItem.text())
listWidgetItem.setData(self.NavItemRole, navItem)
listWidgetItem.setTextAlignment(
Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignVCenter
)
self.addItem(listWidgetItem)
def selectNavItem(self, navItemId: str):
navItemIds = [
self.item(r).data(self.NavItemRole).id for r in range(self.count())
]
index = navItemIds.index(navItemId)
self.setCurrentIndex(self.model().index(index, 0))
class NavigationWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.navHost = navHost
self.verticalLayout = QVBoxLayout(self)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.backButton = QPushButton(QIcon(":/icons/back.svg"), "")
self.backButton.setFlat(True)
self.backButton.setFixedHeight(20)
self.verticalLayout.addWidget(self.backButton)
self.navListWidget = NavItemListWidget(self)
self.verticalLayout.addWidget(self.navListWidget)
def setNavigationItems(self, items: list[NavItem]):
self.navListWidget.setNavItems(items)
class NavigationSideBar(QWidget):
navItemActivated = Signal(NavItem)
def __init__(self, parent=None, navHost=navHost):
super().__init__(parent)
self.navHost = None
self.navigateUpKeyboardShortcut = QShortcut(
QKeySequence(Qt.Modifier.ALT | Qt.Key.Key_Left), self, lambda: True
)
self.verticalLayout = QVBoxLayout(self)
self.navigateUpButton = QPushButton(QIcon(":/icons/back.svg"), "")
self.navigateUpButton.setFlat(True)
self.navigateUpButton.setFixedHeight(20)
self.verticalLayout.addWidget(self.navigateUpButton)
self.slidingStackedWidget = SlidingStackedWidget(self)
self.slidingStackedWidget.animationFinished.connect(
self.endChangingNavItemListWidget
)
self.verticalLayout.addWidget(self.slidingStackedWidget)
navItemListWidget = NavItemListWidget(self)
navItemListWidget.activated.connect(self.navItemListWidgetActivatedProxy)
self.slidingStackedWidget.addWidget(navItemListWidget)
self.setNavHost(navHost)
self.reloadNavWidget()
def setNavHost(self, navHost: NavHost):
if self.navHost is not None:
self.navHost.navItemsChanged.disconnect(self.reloadNavWidget)
self.navHost.activated.disconnect(self.navItemChanged)
self.navigateUpKeyboardShortcut.activated.disconnect(
self.navHost.navigateUp
)
self.navigateUpButton.clicked.disconnect(self.navHost.navigateUp)
self.navHost = navHost
self.navHost.navItemsChanged.connect(self.reloadNavWidget)
self.navHost.activated.connect(self.navItemChanged)
self.navigateUpKeyboardShortcut.activated.connect(self.navHost.navigateUp)
self.navigateUpButton.clicked.connect(self.navHost.navigateUp)
@Slot(QModelIndex)
def navItemListWidgetActivatedProxy(self, index: QModelIndex):
self.navHost.navigate(index.data(NavItemListWidget.NavItemRole).id)
self.navItemActivated.emit(index.data(NavItemListWidget.NavItemRole))
def fillNavItemListWidget(
self, currentNavItem: NavItem, listWidget: NavItemListWidget
):
currentNavItemParent = self.navHost.getNavItemRelatives(
currentNavItem.id
).parent
currentNavItems = self.navHost.getNavItemRelatives(
currentNavItemParent.id if currentNavItemParent else ""
)
listWidget.setNavItems(currentNavItems.children)
listWidget.selectNavItem(currentNavItem.id)
def reloadNavWidget(self):
self.fillNavItemListWidget(
self.navHost.currentNavItem, self.slidingStackedWidget.widget(0)
)
self.navItemChanged(self.navHost.currentNavItem, self.navHost.currentNavItem)
@Slot(NavItem, NavItem)
def navItemChanged(self, oldNavItem: NavItem, newNavItem: NavItem):
# update navigateUpButton text
if newNavItemParent := self.navHost.getNavItemRelatives(newNavItem.id).parent:
self.navigateUpButton.setText(newNavItemParent.text())
else:
self.navigateUpButton.setText("Arcaea Offline")
# update navItemListWidget
oldNavItemIdSplitted = self.navHost.getNavItemIdSplitted(oldNavItem.id)
newNavItemIdSplitted = self.navHost.getNavItemIdSplitted(newNavItem.id)
oldNavItemDepth = len(oldNavItemIdSplitted)
newNavItemDepth = len(newNavItemIdSplitted)
if oldNavItemDepth != newNavItemDepth:
# navItem depth changed, replace current NavItemListWidget
newNavItemListWidget = NavItemListWidget(self)
slidingDirection = (
self.slidingStackedWidget.slidingDirection.RightToLeft
if newNavItemDepth > oldNavItemDepth
else self.slidingStackedWidget.slidingDirection.LeftToRight
)
self.fillNavItemListWidget(newNavItem, newNavItemListWidget)
newNavItemListWidget.activated.connect(self.navItemListWidgetActivatedProxy)
self.startChangingNavItemListWidget(newNavItemListWidget, slidingDirection)
def startChangingNavItemListWidget(
self, newNavItemListWidget: NavItemListWidget, slidingDirection
):
newIndex = self.slidingStackedWidget.addWidget(newNavItemListWidget)
[
self.slidingStackedWidget.widget(i).setEnabled(False)
for i in range(self.slidingStackedWidget.count())
]
self.navigateUpButton.setEnabled(False)
self.navigateUpKeyboardShortcut.setEnabled(False)
self.slidingStackedWidget.slideInIdx(newIndex, slidingDirection)
def endChangingNavItemListWidget(self):
oldWidget = self.slidingStackedWidget.widget(0)
self.slidingStackedWidget.removeWidget(oldWidget)
oldWidget.deleteLater()
newWidget = self.slidingStackedWidget.widget(0)
newWidget.setEnabled(True)
self.navigateUpButton.setEnabled(True)
self.navigateUpKeyboardShortcut.setEnabled(True)