提交 69c850d1 编写于 作者: 之一Yo's avatar 之一Yo

添加导航历史记录功能

上级 a0d4f10a
...@@ -155,6 +155,9 @@ class Window(FramelessWindow): ...@@ -155,6 +155,9 @@ class Window(FramelessWindow):
position=NavigationItemPostion.BOTTOM position=NavigationItemPostion.BOTTOM
) )
#!IMPORTANT: don't forget set the default route key
self.navigationInterface.setDefaultRouteKey(self.musicInterface.objectName())
self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged) self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged)
self.stackWidget.setCurrentIndex(1) self.stackWidget.setCurrentIndex(1)
......
...@@ -3,15 +3,8 @@ Widget > QLabel { ...@@ -3,15 +3,8 @@ Widget > QLabel {
} }
Widget { Widget {
border: 1px solid rgb(229, 229, 229); border: 1px solid rgb(29, 29, 29);
border-right: none; background-color: rgb(39, 39, 39);
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(249, 249, 249);
}
Window {
background-color: rgb(243, 243, 243);
} }
Window { Window {
...@@ -27,11 +20,6 @@ Widget > QLabel { ...@@ -27,11 +20,6 @@ Widget > QLabel {
color: white; color: white;
} }
Widget {
border: 1px solid rgb(29, 29, 29);
background-color: rgb(39, 39, 39);
}
MinimizeButton { MinimizeButton {
qproperty-normalColor: white; qproperty-normalColor: white;
......
# coding:utf-8
import sys
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QIcon, QPainter, QImage, QBrush, QColor, QFont
from PyQt5.QtWidgets import QApplication, QFrame, QStackedWidget, QHBoxLayout, QLabel
from qfluentwidgets import (NavigationInterface, NavigationItemPostion, NavigationWidget, MessageBox,
isDarkTheme, setTheme, Theme)
from qfluentwidgets import FluentIcon as FIF
from qframelesswindow import FramelessWindow, TitleBar
class Widget(QFrame):
def __init__(self, text: str, parent=None):
super().__init__(parent=parent)
self.setObjectName(text.replace(' ', '-'))
self.label = QLabel(text, self)
self.label.setAlignment(Qt.AlignCenter)
self.hBoxLayout = QHBoxLayout(self)
self.hBoxLayout.addWidget(self.label, 1, Qt.AlignCenter)
# leave some space for title bar
self.hBoxLayout.setContentsMargins(0, 32, 0, 0)
class AvatarWidget(NavigationWidget):
""" Avatar widget """
def __init__(self, parent=None):
super().__init__(isSelectable=False, parent=parent)
self.avatar = QImage('resource/shoko.png').scaled(
24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
def paintEvent(self, e):
painter = QPainter(self)
painter.setRenderHints(
QPainter.SmoothPixmapTransform | QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
if self.isPressed:
painter.setOpacity(0.7)
# draw background
if self.isEnter:
c = 255 if isDarkTheme() else 0
painter.setBrush(QColor(c, c, c, 10))
painter.drawRoundedRect(self.rect(), 5, 5)
# draw avatar
painter.setBrush(QBrush(self.avatar))
painter.translate(8, 6)
painter.drawEllipse(0, 0, 24, 24)
painter.translate(-8, -6)
if not self.isCompacted:
painter.setPen(Qt.white if isDarkTheme() else Qt.black)
font = QFont('Segoe UI')
font.setPixelSize(14)
painter.setFont(font)
painter.drawText(QRect(44, 0, 255, 36), Qt.AlignVCenter, 'zhiyiYo')
class CustomTitleBar(TitleBar):
""" Title bar with icon and title """
def __init__(self, parent):
super().__init__(parent)
# add window icon
self.iconLabel = QLabel(self)
self.iconLabel.setFixedSize(18, 18)
self.hBoxLayout.insertSpacing(0, 10)
self.hBoxLayout.insertWidget(1, self.iconLabel, 0, Qt.AlignLeft | Qt.AlignBottom)
self.window().windowIconChanged.connect(self.setIcon)
# add title label
self.titleLabel = QLabel(self)
self.hBoxLayout.insertWidget(2, self.titleLabel, 0, Qt.AlignLeft | Qt.AlignBottom)
self.titleLabel.setObjectName('titleLabel')
self.window().windowTitleChanged.connect(self.setTitle)
def setTitle(self, title):
self.titleLabel.setText(title)
self.titleLabel.adjustSize()
def setIcon(self, icon):
self.iconLabel.setPixmap(QIcon(icon).pixmap(18, 18))
class Window(FramelessWindow):
def __init__(self):
super().__init__()
self.setTitleBar(CustomTitleBar(self))
# use dark theme mode
setTheme(Theme.DARK)
self.hBoxLayout = QHBoxLayout(self)
self.navigationInterface = NavigationInterface(
self, showMenuButton=True, showReturnButton=True)
self.stackWidget = QStackedWidget(self)
# create sub interface
self.searchInterface = Widget('Search Interface', self)
self.musicInterface = Widget('Music Interface', self)
self.videoInterface = Widget('Video Interface', self)
self.folderInterface = Widget('Folder Interface', self)
self.settingInterface = Widget('Setting Interface', self)
self.stackWidget.addWidget(self.searchInterface)
self.stackWidget.addWidget(self.musicInterface)
self.stackWidget.addWidget(self.videoInterface)
self.stackWidget.addWidget(self.folderInterface)
self.stackWidget.addWidget(self.settingInterface)
# initialize layout
self.initLayout()
# add items to navigation interface
self.initNavigation()
self.initWindow()
def initLayout(self):
self.hBoxLayout.setSpacing(0)
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
self.hBoxLayout.addWidget(self.navigationInterface)
self.hBoxLayout.addWidget(self.stackWidget)
self.hBoxLayout.setStretchFactor(self.stackWidget, 1)
self.titleBar.raise_()
self.navigationInterface.displayModeChanged.connect(self.titleBar.raise_)
def initNavigation(self):
self.navigationInterface.addItem(
routeKey=self.searchInterface.objectName(),
icon=FIF.SEARCH,
text='Search',
onClick=lambda: self.switchTo(self.searchInterface)
)
self.navigationInterface.addItem(
routeKey=self.musicInterface.objectName(),
icon=FIF.MUSIC,
text='Music library',
onClick=lambda: self.switchTo(self.musicInterface)
)
self.navigationInterface.addItem(
routeKey=self.videoInterface.objectName(),
icon=FIF.VIDEO,
text='Video library',
onClick=lambda: self.switchTo(self.videoInterface)
)
self.navigationInterface.addSeparator()
# add navigation items to scroll area
self.navigationInterface.addItem(
routeKey=self.folderInterface.objectName(),
icon=FIF.FOLDER,
text='Folder library',
onClick=lambda: self.switchTo(self.folderInterface),
position=NavigationItemPostion.SCROLL
)
# for i in range(1, 21):
# self.navigationInterface.addItem(
# f'folder{i}',
# FIF.FOLDER,
# f'Folder {i}',
# lambda: print('Folder clicked'),
# position=NavigationItemPostion.SCROLL
# )
# add custom widget to bottom
self.navigationInterface.addWidget(
routeKey='avatar',
widget=AvatarWidget(),
onClick=self.showMessageBox,
position=NavigationItemPostion.BOTTOM
)
self.navigationInterface.addItem(
routeKey=self.settingInterface.objectName(),
icon=FIF.SETTING,
text='Settings',
onClick=lambda: self.switchTo(self.settingInterface),
position=NavigationItemPostion.BOTTOM
)
#!IMPORTANT: don't forget set the default route key
self.navigationInterface.setDefaultRouteKey(self.musicInterface.objectName())
self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged)
self.stackWidget.setCurrentIndex(1)
def initWindow(self):
self.resize(900, 700)
self.setWindowIcon(QIcon('resource/logo.png'))
self.setWindowTitle('PyQt-Fluent-Widgets')
self.titleBar.setAttribute(Qt.WA_StyledBackground)
desktop = QApplication.desktop().availableGeometry()
w, h = desktop.width(), desktop.height()
self.move(w//2 - self.width()//2, h//2 - self.height()//2)
self.setQss()
def setQss(self):
color = 'dark' if isDarkTheme() else 'light'
with open(f'resource/{color}/demo.qss', encoding='utf-8') as f:
self.setStyleSheet(f.read())
def switchTo(self, widget):
self.stackWidget.setCurrentWidget(widget)
def onCurrentInterfaceChanged(self, index):
widget = self.stackWidget.widget(index)
self.navigationInterface.setCurrentItem(widget.objectName())
def showMessageBox(self):
w = MessageBox(
'This is a help message',
'You clicked a customized navigation widget. You can add more custom widgets by calling `NavigationInterface.addWidget()` 😉',
self
)
w.exec()
def resizeEvent(self, e):
self.titleBar.move(46, 0)
self.titleBar.resize(self.width()-46, self.titleBar.height())
if __name__ == '__main__':
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
w = Window()
w.show()
app.exec_()
Widget > QLabel {
font: 24px 'Segoe UI', 'Microsoft YaHei';
}
Widget {
border-left: 1px solid rgb(29, 29, 29);
background-color: rgb(39, 39, 39);
}
Window {
background-color: rgb(39, 39, 39);
}
CustomTitleBar {
background-color: transparent;
}
CustomTitleBar > QLabel,
Widget > QLabel {
color: white;
}
CustomTitleBar>QLabel#titleLabel {
background: transparent;
font: 13px 'Segoe UI';
padding: 0 4px
}
MinimizeButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: white;
qproperty-hoverBackgroundColor: rgba(255, 255, 255, 26);
qproperty-pressedColor: white;
qproperty-pressedBackgroundColor: rgba(255, 255, 255, 51)
}
MaximizeButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
qproperty-hoverColor: white;
qproperty-hoverBackgroundColor: rgba(255, 255, 255, 26);
qproperty-pressedColor: white;
qproperty-pressedBackgroundColor: rgba(255, 255, 255, 51)
}
CloseButton {
qproperty-normalColor: white;
qproperty-normalBackgroundColor: transparent;
}
Widget > QLabel {
font: 24px 'Segoe UI', 'Microsoft YaHei';
}
Widget {
border-left: 1px solid rgb(229, 229, 229);
background-color: rgb(249, 249, 249);
}
Window {
background-color: rgb(249, 249, 249);
}
CustomTitleBar > QLabel#titleLabel {
background: transparent;
font: 13px 'Segoe UI';
padding: 0 4px
}
\ No newline at end of file
...@@ -12,7 +12,7 @@ Examples are available at https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/ma ...@@ -12,7 +12,7 @@ Examples are available at https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/ma
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
__version__ = "0.3.1" __version__ = "0.3.2"
from .components import * from .components import *
from .common import * from .common import *
......
<?xml version="1.0" encoding="utf-8"?>
<svg id="" width="16" height="16" style="width:16px;height:16px;" version="1.1"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" enable-background="new 0 0 2048 2048"
xml:space="preserve">
<path fill="#000000" transform="translate(150, 250) scale(0.8, 0.8)" d="M2048 960 q0 26 -19 45 q-19 19 -45 19 l-1765 0 l786 787 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 l-893 -893 q-11 -11 -16.5 -22 q-5.5 -11 -5.5 -26 q0 -15 5.5 -26 q5.5 -11 16.5 -22 l893 -893 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-786 787 l1765 0 q26 0 45 19 q19 19 19 45 Z"/>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<svg id="" width="16" height="16" style="width:16px;height:16px;" version="1.1"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" enable-background="new 0 0 2048 2048"
xml:space="preserve">
<path fill="#ffffff" transform="translate(150, 250) scale(0.8, 0.8)" d="M2048 960 q0 26 -19 45 q-19 19 -45 19 l-1765 0 l786 787 q19 19 19 45 q0 26 -19 45 q-19 19 -45 19 q-26 0 -45 -19 l-893 -893 q-11 -11 -16.5 -22 q-5.5 -11 -5.5 -26 q0 -15 5.5 -26 q5.5 -11 16.5 -22 l893 -893 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-786 787 l1765 0 q26 0 45 19 q19 19 19 45 Z"/>
</svg>
\ No newline at end of file
此差异已折叠。
...@@ -77,6 +77,8 @@ ...@@ -77,6 +77,8 @@
<file>images/icons/Language_white.svg</file> <file>images/icons/Language_white.svg</file>
<file>images/icons/Menu_black.svg</file> <file>images/icons/Menu_black.svg</file>
<file>images/icons/Menu_white.svg</file> <file>images/icons/Menu_white.svg</file>
<file>images/icons/Return_black.svg</file>
<file>images/icons/Return_white.svg</file>
<file>images/state_tool_tip/close_normal.svg</file> <file>images/state_tool_tip/close_normal.svg</file>
<file>images/state_tool_tip/close_hover.svg</file> <file>images/state_tool_tip/close_hover.svg</file>
<file>images/state_tool_tip/close_pressed.svg</file> <file>images/state_tool_tip/close_pressed.svg</file>
......
...@@ -166,6 +166,7 @@ class FluentIcon(FluentIconBase, Enum): ...@@ -166,6 +166,7 @@ class FluentIcon(FluentIconBase, Enum):
FOLDER = "Folder" FOLDER = "Folder"
SEARCH = "Search" SEARCH = "Search"
UPDATE = "Update" UPDATE = "Update"
RETURN = "Return"
SETTING = "Setting" SETTING = "Setting"
PALETTE = "Palette" PALETTE = "Palette"
FEEDBACK = "Feedback" FEEDBACK = "Feedback"
......
from .navigation_widget import NavigationWidget, NavigationButton, NavigationSeparator from .navigation_widget import NavigationWidget, NavigationPushButton, NavigationSeparator, NavigationToolButton
from .navigation_panel import NavigationPanel, NavigationItemPostion from .navigation_panel import NavigationPanel, NavigationItemPostion, NavigationDisplayMode
from .navigation_interface import NavigationInterface from .navigation_interface import NavigationInterface
\ No newline at end of file
# coding:utf-8 # coding:utf-8
from typing import Union from typing import Union
from PyQt5.QtCore import Qt, QEvent from PyQt5.QtCore import Qt, QEvent, pyqtSignal
from PyQt5.QtGui import QResizeEvent, QIcon from PyQt5.QtGui import QResizeEvent, QIcon
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
...@@ -13,20 +13,27 @@ from ...common.icon import FluentIconBase ...@@ -13,20 +13,27 @@ from ...common.icon import FluentIconBase
class NavigationInterface(QWidget): class NavigationInterface(QWidget):
""" Navigation interface """ """ Navigation interface """
def __init__(self, parent=None, showMenuButton=True): displayModeChanged = pyqtSignal(NavigationDisplayMode)
def __init__(self, parent=None, showMenuButton=True, showReturnButton=False):
""" """
Parameters Parameters
---------- ----------
parent: widget
parent widget
showMenuButton: bool showMenuButton: bool
whether to show menu button whether to show menu button
parent: widget showReturnButton: bool
parent widget whether to show return button
""" """
super().__init__(parent=parent) super().__init__(parent=parent)
self.panel = NavigationPanel(self) self.panel = NavigationPanel(self)
self.panel.setMenuButtonVisible(showMenuButton) self.panel.setMenuButtonVisible(showMenuButton)
self.panel.setReturnButtonVisible(showReturnButton)
self.panel.installEventFilter(self) self.panel.installEventFilter(self)
self.panel.displayModeChanged.connect(self.displayModeChanged)
self.resize(48, self.height()) self.resize(48, self.height())
self.setMinimumWidth(48) self.setMinimumWidth(48)
...@@ -100,6 +107,10 @@ class NavigationInterface(QWidget): ...@@ -100,6 +107,10 @@ class NavigationInterface(QWidget):
""" """
self.panel.setCurrentItem(name) self.panel.setCurrentItem(name)
def setDefaultRouteKey(self, key: str):
""" set the routing key to use when the navigation history is empty """
self.panel.setDefaultRouteKey(key)
def eventFilter(self, obj, e: QEvent): def eventFilter(self, obj, e: QEvent):
if obj is not self.panel or e.type() != QEvent.Resize: if obj is not self.panel or e.type() != QEvent.Resize:
return super().eventFilter(obj, e) return super().eventFilter(obj, e)
......
...@@ -2,14 +2,15 @@ ...@@ -2,14 +2,15 @@
from enum import Enum from enum import Enum
from typing import Dict, Union from typing import Dict, Union
from PyQt5.QtCore import Qt, QPropertyAnimation, QRect, QSize, QEvent, QEasingCurve from PyQt5.QtCore import Qt, QPropertyAnimation, QRect, QSize, QEvent, QEasingCurve, pyqtSignal, QObject
from PyQt5.QtGui import QResizeEvent, QIcon from PyQt5.QtGui import QResizeEvent, QIcon
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QFrame, QApplication from PyQt5.QtWidgets import QWidget, QVBoxLayout, QFrame, QApplication
from .navigation_widget import NavigationButton, MenuButton, NavigationWidget, NavigationSeparator from .navigation_widget import NavigationPushButton, NavigationToolButton, NavigationWidget, NavigationSeparator
from ..widgets.scroll_area import ScrollArea from ..widgets.scroll_area import ScrollArea
from ...common.style_sheet import setStyleSheet, getStyleSheet from ...common.style_sheet import setStyleSheet
from ...common.icon import FluentIconBase from ...common.icon import FluentIconBase
from ...common.icon import FluentIcon as FIF
class NavigationDisplayMode(Enum): class NavigationDisplayMode(Enum):
...@@ -30,19 +31,24 @@ class NavigationItemPostion(Enum): ...@@ -30,19 +31,24 @@ class NavigationItemPostion(Enum):
class NavigationPanel(QFrame): class NavigationPanel(QFrame):
""" Navigation panel """ """ Navigation panel """
displayModeChanged = pyqtSignal(NavigationDisplayMode)
def __init__(self, parent=None, isMinimalEnabled=False): def __init__(self, parent=None, isMinimalEnabled=False):
super().__init__(parent=parent) super().__init__(parent=parent)
self._parent = parent # type: QWidget self._parent = parent # type: QWidget
self.scrollArea = ScrollArea(self) self.scrollArea = ScrollArea(self)
self.scrollWidget = QWidget() self.scrollWidget = QWidget()
self.menuButton = MenuButton(self) self.menuButton = NavigationToolButton(FIF.MENU, self)
self.returnButton = NavigationToolButton(FIF.RETURN, self)
self.vBoxLayout = NavigationItemLayout(self) self.vBoxLayout = NavigationItemLayout(self)
self.topLayout = NavigationItemLayout() self.topLayout = NavigationItemLayout()
self.bottomLayout = NavigationItemLayout() self.bottomLayout = NavigationItemLayout()
self.scrollLayout = NavigationItemLayout(self.scrollWidget) self.scrollLayout = NavigationItemLayout(self.scrollWidget)
self.items = {} # type: Dict[str, NavigationWidget] self.items = {} # type: Dict[str, NavigationWidget]
self.history = NavigationHistory(self.items)
self.expandAni = QPropertyAnimation(self, b'geometry', self) self.expandAni = QPropertyAnimation(self, b'geometry', self)
...@@ -59,6 +65,9 @@ class NavigationPanel(QFrame): ...@@ -59,6 +65,9 @@ class NavigationPanel(QFrame):
self.setAttribute(Qt.WA_StyledBackground) self.setAttribute(Qt.WA_StyledBackground)
self.window().installEventFilter(self) self.window().installEventFilter(self)
self.returnButton.hide()
self.returnButton.setDisabled(True)
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scrollArea.setWidget(self.scrollWidget) self.scrollArea.setWidget(self.scrollWidget)
...@@ -69,6 +78,8 @@ class NavigationPanel(QFrame): ...@@ -69,6 +78,8 @@ class NavigationPanel(QFrame):
self.menuButton.clicked.connect(self.toggle) self.menuButton.clicked.connect(self.toggle)
self.expandAni.finished.connect(self._onExpandAniFinished) self.expandAni.finished.connect(self._onExpandAniFinished)
self.history.emptyChanged.connect(self.returnButton.setDisabled)
self.returnButton.clicked.connect(self.history.pop)
self.setProperty('menu', False) self.setProperty('menu', False)
self.scrollWidget.setObjectName('scrollWidget') self.scrollWidget.setObjectName('scrollWidget')
...@@ -94,6 +105,7 @@ class NavigationPanel(QFrame): ...@@ -94,6 +105,7 @@ class NavigationPanel(QFrame):
self.scrollLayout.setAlignment(Qt.AlignTop) self.scrollLayout.setAlignment(Qt.AlignTop)
self.bottomLayout.setAlignment(Qt.AlignBottom) self.bottomLayout.setAlignment(Qt.AlignBottom)
self.topLayout.addWidget(self.returnButton, 0, Qt.AlignTop)
self.topLayout.addWidget(self.menuButton, 0, Qt.AlignTop) self.topLayout.addWidget(self.menuButton, 0, Qt.AlignTop)
def addItem(self, routeKey: str, icon: Union[str, QIcon, FluentIconBase], text: str, onClick, selectable=True, position=NavigationItemPostion.TOP): def addItem(self, routeKey: str, icon: Union[str, QIcon, FluentIconBase], text: str, onClick, selectable=True, position=NavigationItemPostion.TOP):
...@@ -119,10 +131,10 @@ class NavigationPanel(QFrame): ...@@ -119,10 +131,10 @@ class NavigationPanel(QFrame):
selectable: bool selectable: bool
whether the item is selectable whether the item is selectable
""" """
if text in self.items: if routeKey in self.items:
return return
button = NavigationButton(icon, text, selectable, self) button = NavigationPushButton(icon, text, selectable, self)
self.addWidget(routeKey, button, onClick, position) self.addWidget(routeKey, button, onClick, position)
def addWidget(self, routeKey: str, widget: NavigationWidget, onClick, position=NavigationItemPostion.TOP): def addWidget(self, routeKey: str, widget: NavigationWidget, onClick, position=NavigationItemPostion.TOP):
...@@ -181,6 +193,10 @@ class NavigationPanel(QFrame): ...@@ -181,6 +193,10 @@ class NavigationPanel(QFrame):
""" set whether the menu button is visible """ """ set whether the menu button is visible """
self.menuButton.setVisible(isVisible) self.menuButton.setVisible(isVisible)
def setReturnButtonVisible(self, isVisible: bool):
""" set whether the menu button is visible """
self.returnButton.setVisible(isVisible)
def expand(self): def expand(self):
""" expand navigation panel """ """ expand navigation panel """
self._setWidgetCompacted(False) self._setWidgetCompacted(False)
...@@ -201,6 +217,7 @@ class NavigationPanel(QFrame): ...@@ -201,6 +217,7 @@ class NavigationPanel(QFrame):
self.show() self.show()
self.displayModeChanged.emit(self.displayMode)
self.expandAni.setStartValue( self.expandAni.setStartValue(
QRect(self.pos(), QSize(48, self.height()))) QRect(self.pos(), QSize(48, self.height())))
self.expandAni.setEndValue( self.expandAni.setEndValue(
...@@ -237,6 +254,7 @@ class NavigationPanel(QFrame): ...@@ -237,6 +254,7 @@ class NavigationPanel(QFrame):
if routeKey not in self.items: if routeKey not in self.items:
return return
self.history.push(routeKey)
for k, item in self.items.items(): for k, item in self.items.items():
item.setSelected(k == routeKey) item.setSelected(k == routeKey)
...@@ -282,7 +300,8 @@ class NavigationPanel(QFrame): ...@@ -282,7 +300,8 @@ class NavigationPanel(QFrame):
else: else:
self.displayMode = NavigationDisplayMode.COMPACT self.displayMode = NavigationDisplayMode.COMPACT
s = getStyleSheet('navigation_interface') self.displayModeChanged.emit(self.displayMode)
if self.displayMode == NavigationDisplayMode.MINIMAL: if self.displayMode == NavigationDisplayMode.MINIMAL:
self.hide() self.hide()
self.setProperty('menu', False) self.setProperty('menu', False)
...@@ -312,6 +331,9 @@ class NavigationPanel(QFrame): ...@@ -312,6 +331,9 @@ class NavigationPanel(QFrame):
spacing += self.bottomLayout.count() * self.bottomLayout.spacing() spacing += self.bottomLayout.count() * self.bottomLayout.spacing()
return 36 + th + bh + sh + spacing return 36 + th + bh + sh + spacing
def setDefaultRouteKey(self, key: str):
""" set the routing key to use when the navigation history is empty """
self.history.defaultRouteKey = key
class NavigationItemLayout(QVBoxLayout): class NavigationItemLayout(QVBoxLayout):
""" Navigation layout """ """ Navigation layout """
...@@ -323,3 +345,47 @@ class NavigationItemLayout(QVBoxLayout): ...@@ -323,3 +345,47 @@ class NavigationItemLayout(QVBoxLayout):
if isinstance(item.widget(), NavigationSeparator): if isinstance(item.widget(), NavigationSeparator):
geo = item.geometry() geo = item.geometry()
item.widget().setGeometry(0, geo.y(), geo.width(), geo.height()) item.widget().setGeometry(0, geo.y(), geo.width(), geo.height())
class NavigationHistory(QObject):
""" Navigation history """
emptyChanged = pyqtSignal(bool)
def __init__(self, items: Dict[str, NavigationWidget]):
super().__init__()
self.items = items
self.history = []
self._defaultRouteKey = None
@property
def defaultRouteKey(self):
return self._defaultRouteKey
@defaultRouteKey.setter
def defaultRouteKey(self, key):
if key not in self.items:
raise ValueError(f'The route key `{key}` has not been registered yet.')
self._defaultRouteKey = key
def push(self, routeKey: str):
if not self.history and self.defaultRouteKey != routeKey:
self.history.append(routeKey)
self.emptyChanged.emit(False)
elif self.history and self.history[-1] != routeKey:
self.history.append(routeKey)
def pop(self):
if not self.history:
return
self.history.pop()
if self.history:
self.items[self.history[-1]].clicked.emit()
else:
if self.defaultRouteKey is not None:
self.items[self.defaultRouteKey].clicked.emit()
self.emptyChanged.emit(True)
...@@ -70,8 +70,8 @@ class NavigationWidget(QWidget): ...@@ -70,8 +70,8 @@ class NavigationWidget(QWidget):
self.update() self.update()
class NavigationButton(NavigationWidget): class NavigationPushButton(NavigationWidget):
""" Navigation button """ """ Navigation push button """
def __init__(self, icon: Union[str, QIcon, FIF], text: str, isSelectable: bool, parent=None): def __init__(self, icon: Union[str, QIcon, FIF], text: str, isSelectable: bool, parent=None):
""" """
...@@ -89,7 +89,7 @@ class NavigationButton(NavigationWidget): ...@@ -89,7 +89,7 @@ class NavigationButton(NavigationWidget):
self._text = text self._text = text
self.setStyleSheet( self.setStyleSheet(
"NavigationButton{font: 14px 'Segoe UI', 'Microsoft YaHei'}") "NavigationPushButton{font: 14px 'Segoe UI', 'Microsoft YaHei'}")
def text(self): def text(self):
return self._text return self._text
...@@ -102,6 +102,8 @@ class NavigationButton(NavigationWidget): ...@@ -102,6 +102,8 @@ class NavigationButton(NavigationWidget):
if self.isPressed: if self.isPressed:
painter.setOpacity(0.7) painter.setOpacity(0.7)
if not self.isEnabled():
painter.setOpacity(0.4)
# draw background # draw background
c = 255 if isDarkTheme() else 0 c = 255 if isDarkTheme() else 0
...@@ -113,7 +115,7 @@ class NavigationButton(NavigationWidget): ...@@ -113,7 +115,7 @@ class NavigationButton(NavigationWidget):
color = QColor(41, 247, 255) if isDarkTheme() else QColor(0, 153, 188) color = QColor(41, 247, 255) if isDarkTheme() else QColor(0, 153, 188)
painter.setBrush(color) painter.setBrush(color)
painter.drawRoundedRect(0, 10, 3, 16, 1.5, 1.5) painter.drawRoundedRect(0, 10, 3, 16, 1.5, 1.5)
elif self.isEnter: elif self.isEnter and self.isEnabled():
painter.setBrush(QColor(c, c, c, 10)) painter.setBrush(QColor(c, c, c, 10))
painter.drawRoundedRect(self.rect(), 5, 5) painter.drawRoundedRect(self.rect(), 5, 5)
...@@ -127,11 +129,11 @@ class NavigationButton(NavigationWidget): ...@@ -127,11 +129,11 @@ class NavigationButton(NavigationWidget):
self.height()), Qt.AlignVCenter, self.text()) self.height()), Qt.AlignVCenter, self.text())
class MenuButton(NavigationButton): class NavigationToolButton(NavigationPushButton):
""" Menu button """ """ Navigation tool button """
def __init__(self, parent=None): def __init__(self, icon: Union[str, QIcon, FIF], parent=None):
super().__init__(FIF.MENU, '', parent) super().__init__(icon, '', False, parent)
def setCompacted(self, isCompacted: bool): def setCompacted(self, isCompacted: bool):
self.setFixedSize(40, 36) self.setFixedSize(40, 36)
......
...@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f: ...@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f:
setuptools.setup( setuptools.setup(
name="PyQt-Fluent-Widgets", name="PyQt-Fluent-Widgets",
version="0.3.1", version="0.3.2",
keywords="pyqt fluent widgets", keywords="pyqt fluent widgets",
author="zhiyiYo", author="zhiyiYo",
author_email="shokokawaii@outlook.com", author_email="shokokawaii@outlook.com",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册