Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions examples/navigation/navigation_user_card/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# coding:utf-8
import sys
from pathlib import Path

#sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QFrame, QHBoxLayout
from qfluentwidgets import (NavigationItemPosition, MessageBox, FluentWindow, SubtitleLabel, setFont,
NavigationUserCardClickBehavior)
from qfluentwidgets import FluentIcon as FIF


class Widget(QFrame):

def __init__(self, text: str, parent=None):
super().__init__(parent=parent)
self.label = SubtitleLabel(text, self)
self.hBoxLayout = QHBoxLayout(self)

setFont(self.label, 24)
self.label.setAlignment(Qt.AlignCenter)
self.hBoxLayout.addWidget(self.label, 1, Qt.AlignCenter)
self.setObjectName(text.replace(' ', '-'))


class Window(FluentWindow):

def __init__(self):
super().__init__()

# create sub interface
self.homeInterface = Widget('Home Interface', self)
self.musicInterface = Widget('Music Interface', self)
self.videoInterface = Widget('Video Interface', self)
self.settingInterface = Widget('Setting Interface', self)

self.initNavigation()
self.initWindow()

def initNavigation(self):
# add user card with custom parameters
self.userCard = self.navigationInterface.addUserCard(
routeKey='userCard',
avatar='resource/shoko.png',
title='zhiyiYo',
subtitle='[email protected]',
onClick=self.showMessageBox,
position=NavigationItemPosition.TOP,
aboveMenuButton=False # place below the expand/collapse button
)

# customize user card (optional)
# self.userCard.setTitleFontSize(15)
# self.userCard.setSubtitleFontSize(11)
# self.userCard.setAnimationDuration(300)

# placement: set aboveMenuButton=True to place card above expand/collapse button
# default: aboveMenuButton=False (card placed below menu button)

# customize click behavior in compact mode (optional)
# NavigationUserCardClickBehavior.EXPAND: expand navigation panel (default)
# NavigationUserCardClickBehavior.CALLBACK: trigger onClick callback
# NavigationUserCardClickBehavior.EXPAND_AND_CALLBACK: both expand and callback
# self.userCard.setCompactClickBehavior(NavigationUserCardClickBehavior.EXPAND_AND_CALLBACK)

# add navigation items
self.addSubInterface(self.homeInterface, FIF.HOME, 'Home')
self.addSubInterface(self.musicInterface, FIF.MUSIC, 'Music library')

self.navigationInterface.addSeparator()

self.addSubInterface(self.videoInterface, FIF.VIDEO, 'Video library')
self.addSubInterface(self.settingInterface, FIF.SETTING, 'Settings', NavigationItemPosition.BOTTOM)

def initWindow(self):
self.resize(900, 700)
self.setWindowIcon(QIcon('resource/logo.png'))
self.setWindowTitle('Navigation User Card')

desktop = QApplication.desktop().availableGeometry()
w, h = desktop.width(), desktop.height()
self.move(w//2 - self.width()//2, h//2 - self.height()//2)

def showMessageBox(self):
w = MessageBox(
'User Card',
'This is a navigation user card that displays avatar, title and subtitle.\n\n'
'Placement:\n'
'• aboveMenuButton=True: Place above expand/collapse button\n'
'• aboveMenuButton=False: Place below menu button (default)\n\n'
'Click behavior:\n'
'• EXPAND: Expand navigation panel in compact mode (default)\n'
'• CALLBACK: Trigger onClick callback in both modes\n'
'• EXPAND_AND_CALLBACK: Both expand and trigger callback',
self
)
w.exec_()


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_()
50 changes: 50 additions & 0 deletions examples/navigation/navigation_user_card/resource/dark/demo.qss
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
Widget > QLabel {
font: 24px 'Segoe UI', 'Microsoft YaHei';
}

Widget {
border: 1px solid rgb(29, 29, 29);
border-right: none;
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(39, 39, 39);
}

Window {
background-color: rgb(32, 32, 32);
}

StandardTitleBar {
background-color: rgb(32, 32, 32);
}

StandardTitleBar > QLabel,
Widget > QLabel {
color: white;
}


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;
}

16 changes: 16 additions & 0 deletions examples/navigation/navigation_user_card/resource/light/demo.qss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Widget > QLabel {
font: 24px 'Segoe UI', 'Microsoft YaHei';
}

Widget {
border: 1px solid rgb(229, 229, 229);
border-right: none;
border-bottom: none;
border-top-left-radius: 10px;
background-color: rgb(249, 249, 249);
}

Window {
background-color: rgb(243, 243, 243);
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions qfluentwidgets/components/navigation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .navigation_widget import (NavigationWidget, NavigationPushButton, NavigationSeparator, NavigationToolButton,
NavigationTreeWidget, NavigationTreeWidgetBase, NavigationAvatarWidget, NavigationItemHeader)
from .navigation_user_card import NavigationUserCard, NavigationUserCardClickBehavior
from .navigation_panel import NavigationPanel, NavigationItemPosition, NavigationDisplayMode
from .navigation_interface import NavigationInterface
from .navigation_bar import NavigationBarPushButton, NavigationBar
Expand Down
65 changes: 64 additions & 1 deletion qfluentwidgets/components/navigation/navigation_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
from typing import Union

from PyQt5.QtCore import Qt, QEvent, pyqtSignal
from PyQt5.QtGui import QResizeEvent, QIcon
from PyQt5.QtGui import QResizeEvent, QIcon, QPixmap
from PyQt5.QtWidgets import QWidget

from .navigation_panel import NavigationPanel, NavigationItemPosition, NavigationWidget, NavigationDisplayMode
from .navigation_widget import NavigationTreeWidget
from .navigation_user_card import NavigationUserCard
from ...common.style_sheet import FluentStyleSheet
from ...common.icon import FluentIconBase

Expand Down Expand Up @@ -220,6 +221,68 @@ def insertItemHeader(self, index: int, text: str, position=NavigationItemPositio
"""
return self.panel.insertItemHeader(index, text, position)

def addUserCard(self, routeKey: str, avatar: Union[str, QIcon, FluentIconBase] = None,
title: str = '', subtitle: str = '', onClick=None,
position=NavigationItemPosition.TOP, aboveMenuButton: bool = False):
""" add user card to navigation panel

Parameters
----------
routeKey: str
the unique name of user card

avatar: str | QIcon | FluentIconBase
avatar image or icon

title: str
user name or title text

subtitle: str
subtitle text (e.g., email, status)

onClick: callable
the slot connected to card clicked signal

position: NavigationItemPosition
where the card is added

aboveMenuButton: bool
whether to place the card above the menu button (expand/collapse button)

Returns
-------
NavigationUserCard
created user card widget
"""
card = NavigationUserCard(self)

if avatar:
if isinstance(avatar, FluentIconBase):
card.setAvatarIcon(avatar)
else:
card.setAvatar(avatar)

card.setTitle(title)
card.setSubtitle(subtitle)

# calculate insert index if placing above menu button
index = -1
if aboveMenuButton and position == NavigationItemPosition.TOP:
# find menu button index in top layout
layout = self.panel.topLayout
for i in range(layout.count()):
item = layout.itemAt(i)
if item and item.widget() == self.panel.menuButton:
index = i
break

if index >= 0:
self.panel.insertWidget(index, routeKey, card, onClick, position)
else:
self.addWidget(routeKey, card, onClick, position)

return card

def insertSeparator(self, index: int, position=NavigationItemPosition.TOP):
""" add separator

Expand Down
Loading