init
This commit is contained in:
297
app/view/widgets/ownFiled_widgets.py
Normal file
297
app/view/widgets/ownFiled_widgets.py
Normal file
@@ -0,0 +1,297 @@
|
||||
from loguru import logger
|
||||
from PyQt6.QtCore import Qt, pyqtSignal
|
||||
from PyQt6.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from qfluentwidgets import (Action, InfoBar, InfoBarPosition, LineEdit, MenuAnimationType, PillPushButton,
|
||||
PrimarySplitPushButton, PushButton, RoundMenu, ScrollArea)
|
||||
|
||||
from app.core import DeleteTagThread, userConfig, lang
|
||||
from app.view.widgets.add_tag_messageBox import AddTagMessageBox
|
||||
|
||||
|
||||
class TagsScrollArea(ScrollArea):
|
||||
"""标签滚动区域组件,支持动态添加和移除标签,支持单选模式"""
|
||||
|
||||
# 信号:标签被点击时发出,传递标签文本
|
||||
tagClicked = pyqtSignal(str, str)
|
||||
TAG_TYPES = {"video": "视频", "doc": "文档", "image": "图片", "audio": "音乐"}
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.tagsDict = {} # 存储所有标签按钮
|
||||
self.currentCheckedTag = None # 当前选中的标签ID
|
||||
|
||||
self.setupUi()
|
||||
logger.debug("初始化标签滚动区域组件")
|
||||
|
||||
def setupUi(self):
|
||||
"""初始化UI"""
|
||||
self.widgets = QWidget()
|
||||
self.layouts = QHBoxLayout(self.widgets)
|
||||
self.setWidget(self.widgets)
|
||||
self.setWidgetResizable(True)
|
||||
self.setMaximumWidth(400)
|
||||
|
||||
# 设置布局属性
|
||||
self.layouts.setContentsMargins(0, 0, 0, 0)
|
||||
self.layouts.setSpacing(10)
|
||||
|
||||
# 初始化默认标签
|
||||
self.initDefaultTags()
|
||||
|
||||
# 设置样式
|
||||
self.widgets.setStyleSheet("background-color: transparent; border: none;")
|
||||
self.setStyleSheet("background-color: transparent; border: none;")
|
||||
|
||||
# 设置滚动策略
|
||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
|
||||
# 安全地获取 tags 字段,如果不存在则使用空列表
|
||||
self.tags = userConfig.userData.get("data", {}).get("tags", [])
|
||||
|
||||
for tag in self.tags:
|
||||
self.addTag(tag["id"], tag["name"])
|
||||
self.tagsDict[tag["id"]] = tag["name"]
|
||||
|
||||
def initDefaultTags(self):
|
||||
"""初始化默认标签"""
|
||||
logger.debug("初始化默认标签")
|
||||
for tagId, tagText in self.TAG_TYPES.items():
|
||||
self.addTag(tagId, tagText)
|
||||
|
||||
def addTag(self, tagId, text):
|
||||
"""添加一个新标签
|
||||
|
||||
Args:
|
||||
tagId: 标签的唯一标识符
|
||||
text: 标签显示的文本
|
||||
|
||||
Returns:
|
||||
创建的标签按钮对象
|
||||
"""
|
||||
self.tagsDict[tagId] = text
|
||||
logger.debug(f"添加新标签: {tagId} - {text}")
|
||||
tagBtn = PillPushButton(text, self.widgets)
|
||||
tagBtn.setObjectName(f"tag_{tagId}")
|
||||
tagBtn.setCheckable(True) # 设置为可选中状态
|
||||
tagBtn.setContextMenuPolicy(
|
||||
Qt.ContextMenuPolicy.CustomContextMenu
|
||||
) # 启用自定义上下文菜单
|
||||
|
||||
# 连接点击信号,实现单选逻辑
|
||||
tagBtn.clicked.connect(
|
||||
lambda checked, tid=tagId: self.onTagClicked(tid, checked)
|
||||
)
|
||||
|
||||
# 连接右键菜单信号
|
||||
tagBtn.customContextMenuRequested.connect(
|
||||
lambda pos, tid=tagId: self.onTagRightClicked(tid, pos)
|
||||
)
|
||||
|
||||
self.layouts.addWidget(tagBtn)
|
||||
|
||||
return tagBtn
|
||||
|
||||
def onTagClicked(self, tagId, checked):
|
||||
"""处理标签点击事件,实现单选逻辑"""
|
||||
if checked:
|
||||
# 如果当前点击的标签被选中,取消之前选中的标签
|
||||
if self.currentCheckedTag and self.currentCheckedTag != tagId:
|
||||
# 找到之前选中的标签并取消选中
|
||||
previousTagBtn = self.findChild(
|
||||
QWidget, f"tag_{self.currentCheckedTag}"
|
||||
)
|
||||
if previousTagBtn:
|
||||
previousTagBtn.setChecked(False)
|
||||
|
||||
# 更新当前选中的标签
|
||||
self.currentCheckedTag = tagId
|
||||
|
||||
if tagId in ["video", "doc", "image", "audio"]:
|
||||
self.tagClicked.emit("internalTag", tagId)
|
||||
else:
|
||||
self.tagClicked.emit("externalTag", tagId)
|
||||
logger.debug(f"选中标签: {tagId}")
|
||||
else:
|
||||
# 如果取消选中当前标签,清空当前选中的标签
|
||||
if self.currentCheckedTag == tagId:
|
||||
self.currentCheckedTag = None
|
||||
logger.debug(f"取消选中标签: {tagId}")
|
||||
|
||||
# 发出标签点击信号
|
||||
|
||||
def onTagRightClicked(self, tagId, pos):
|
||||
"""处理标签右键点击事件"""
|
||||
logger.debug(f"标签被右键点击: {tagId}")
|
||||
tagBtn = self.findChild(QWidget, f"tag_{tagId}")
|
||||
if tagBtn:
|
||||
global_pos = tagBtn.mapToGlobal(pos)
|
||||
if tagBtn.text() in ["视频", "文档", "图片", "音乐"]:
|
||||
return
|
||||
menu = RoundMenu(parent=self)
|
||||
|
||||
menu.addAction(Action(lang("删除"), triggered=lambda: self.deleteTag(tagId)))
|
||||
|
||||
menu.exec(global_pos, aniType=MenuAnimationType.DROP_DOWN)
|
||||
|
||||
def deleteTag(self, tagId):
|
||||
self.deleteTagThread = DeleteTagThread(tagId)
|
||||
self.deleteTagThread.successDeleteSignal.connect(
|
||||
lambda: self._onTagDeleteError(tagId)
|
||||
)
|
||||
self.deleteTagThread.errorSignal.connect(self._onTagDeleteError)
|
||||
self.deleteTagThread.start()
|
||||
|
||||
def _onTagDeleteError(self, msg):
|
||||
InfoBar.error(
|
||||
"失败",
|
||||
msg,
|
||||
Qt.Orientation.Horizontal,
|
||||
True,
|
||||
1000,
|
||||
InfoBarPosition.TOP_RIGHT,
|
||||
self.window(),
|
||||
)
|
||||
|
||||
def _onTagDeleteError(self, tagId):
|
||||
self.removeTag(tagId)
|
||||
InfoBar.success(
|
||||
"成功",
|
||||
"标签删除成功",
|
||||
Qt.Orientation.Horizontal,
|
||||
True,
|
||||
1000,
|
||||
InfoBarPosition.TOP_RIGHT,
|
||||
self.window(),
|
||||
)
|
||||
|
||||
def removeTag(self, tagId):
|
||||
"""移除指定标签"""
|
||||
if tagId in self.tagsDict:
|
||||
logger.debug(f"移除标签: {tagId}")
|
||||
|
||||
# 如果移除的是当前选中的标签,清空选中状态
|
||||
if self.currentCheckedTag == tagId:
|
||||
self.currentCheckedTag = None
|
||||
|
||||
tagBtn = self.findChild(QWidget, f"tag_{tagId}")
|
||||
if tagBtn:
|
||||
self.layouts.removeWidget(tagBtn)
|
||||
tagBtn.deleteLater()
|
||||
del self.tagsDict[tagId]
|
||||
else:
|
||||
logger.warning(f"尝试移除不存在的标签: {tagId}")
|
||||
|
||||
def getCheckedTag(self):
|
||||
"""获取当前选中的标签ID"""
|
||||
return self.currentCheckedTag
|
||||
|
||||
def setCheckedTag(self, tagId):
|
||||
"""设置指定标签为选中状态"""
|
||||
if tagId in self.tagsDict:
|
||||
tagBtn = self.findChild(QWidget, f"tag_{tagId}")
|
||||
if tagBtn:
|
||||
tagBtn.setChecked(True)
|
||||
# onTagClicked 方法会自动处理单选逻辑
|
||||
else:
|
||||
logger.warning(f"尝试选中不存在的标签: {tagId}")
|
||||
|
||||
def clearChecked(self):
|
||||
"""清除所有选中状态"""
|
||||
if self.currentCheckedTag:
|
||||
tagBtn = self.findChild(QWidget, f"tag_{self.currentCheckedTag}")
|
||||
if tagBtn:
|
||||
tagBtn.setChecked(False)
|
||||
self.currentCheckedTag = None
|
||||
|
||||
|
||||
class TagWidget(QWidget):
|
||||
"""标签管理组件"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.tagScrollArea = TagsScrollArea(self)
|
||||
self.addPushButton = PushButton(lang("添加标签"), self)
|
||||
|
||||
logger.debug("初始化标签管理组件")
|
||||
|
||||
self.setupUi()
|
||||
self.connectSignals()
|
||||
|
||||
def setupUi(self):
|
||||
"""初始化UI"""
|
||||
self.hBoxLayout = QHBoxLayout(self)
|
||||
self.hBoxLayout.addWidget(self.tagScrollArea)
|
||||
self.hBoxLayout.addSpacing(10)
|
||||
self.hBoxLayout.addWidget(self.addPushButton, Qt.AlignmentFlag.AlignRight)
|
||||
|
||||
def connectSignals(self):
|
||||
"""连接信号与槽"""
|
||||
logger.debug("连接标签管理组件信号")
|
||||
self.addPushButton.clicked.connect(self.addTag)
|
||||
|
||||
def addTag(self):
|
||||
w = AddTagMessageBox(self.window())
|
||||
w.successAddTagSignal.connect(self.onAddTagSuccess)
|
||||
if w.exec():
|
||||
...
|
||||
|
||||
def onAddTagSuccess(self, name, result):
|
||||
"""处理标签添加成功事件"""
|
||||
InfoBar.success(
|
||||
"成功",
|
||||
"标签添加成功",
|
||||
Qt.Orientation.Horizontal,
|
||||
True,
|
||||
1000,
|
||||
InfoBarPosition.TOP_RIGHT,
|
||||
self.window(),
|
||||
)
|
||||
self.tagScrollArea.addTag(result["data"], name)
|
||||
|
||||
|
||||
class SearchWidget(QWidget):
|
||||
"""搜索组件"""
|
||||
|
||||
# 信号:搜索请求时发出,传递搜索关键词
|
||||
searchRequested = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.searchLineEdit = LineEdit(self)
|
||||
self.searchButton = PrimarySplitPushButton(lang("仓内搜索"), self)
|
||||
|
||||
self.menu = RoundMenu(parent=self)
|
||||
self.menu.addAction(
|
||||
Action(
|
||||
lang("仓内搜索"),
|
||||
triggered=lambda: self.changeButtonText(lang("仓内搜索")),
|
||||
)
|
||||
)
|
||||
self.menu.addAction(
|
||||
Action(
|
||||
lang("站内搜索"),
|
||||
triggered=lambda: self.changeButtonText(lang("站内搜索")),
|
||||
)
|
||||
)
|
||||
|
||||
self.searchButton.setFlyout(self.menu)
|
||||
|
||||
logger.debug("初始化搜索组件")
|
||||
|
||||
self.setupUi()
|
||||
|
||||
def changeButtonText(self, text):
|
||||
self.searchButton.setText(text)
|
||||
|
||||
def setupUi(self):
|
||||
"""初始化UI"""
|
||||
self.searchLineEdit.setPlaceholderText(lang("搜索文件"))
|
||||
|
||||
self.hBoxLayout = QHBoxLayout(self)
|
||||
self.hBoxLayout.setContentsMargins(0, 24, 0, 0)
|
||||
self.hBoxLayout.addWidget(self.searchLineEdit)
|
||||
self.hBoxLayout.addWidget(self.searchButton)
|
||||
Reference in New Issue
Block a user