363 lines
12 KiB
Python
363 lines
12 KiB
Python
# coding: utf-8
|
|
|
|
from loguru import logger
|
|
from PyQt6.QtCore import Qt, pyqtSignal
|
|
from PyQt6.QtGui import QPixmap
|
|
from PyQt6.QtWidgets import QHBoxLayout
|
|
from qfluentwidgets import Action, BodyLabel, CardWidget, ImageLabel, InfoBar, InfoBarPosition, MenuAnimationType, \
|
|
MessageBox, PushButton, RoundMenu, StrongBodyLabel
|
|
from qfluentwidgets import FluentIcon as FIF
|
|
|
|
from app.core import (DeleteFileThread, formatDate, formatSize, getFileIcon, lang, signalBus)
|
|
from app.view.widgets.share_file_messageBox import ShareFileMessageBox
|
|
|
|
|
|
class FileCard(CardWidget):
|
|
def __init__(self, _id, fileName, fileType, path, date, size, parent=None):
|
|
super().__init__(parent)
|
|
self._id = _id
|
|
self.fileName = fileName
|
|
self.fileSize = size
|
|
self.changeTime = date
|
|
self.fileType = fileType
|
|
self.filePath = path
|
|
self.setFixedHeight(50)
|
|
|
|
self.iconLabel = ImageLabel(self)
|
|
|
|
self.fileNameLabel = StrongBodyLabel(self.fileName, self)
|
|
self.fileSizeLabel = BodyLabel(formatSize(self.fileSize), self)
|
|
self.changeTimeLabel = BodyLabel(formatDate(self.changeTime), self)
|
|
|
|
self.hBoxLayout = QHBoxLayout(self)
|
|
self.hBoxLayout.addWidget(self.iconLabel)
|
|
self.hBoxLayout.addWidget(self.fileNameLabel)
|
|
self.hBoxLayout.addWidget(self.fileSizeLabel)
|
|
self.hBoxLayout.addWidget(self.changeTimeLabel)
|
|
|
|
self.hBoxLayout.setStretch(0, 1)
|
|
self.hBoxLayout.setStretch(1, 2)
|
|
self.hBoxLayout.setStretch(2, 1)
|
|
|
|
self.hBoxLayout.setContentsMargins(10, 10, 10, 10)
|
|
self.hBoxLayout.setSpacing(10)
|
|
|
|
self.loadIcon()
|
|
|
|
if self.fileType == "dir":
|
|
self.clicked.connect(self.dirClicked)
|
|
|
|
self.suffix = fileName.split(".")[-1].lower()
|
|
|
|
def mousePressEvent(self, event):
|
|
"""重写鼠标点击事件,区分左右键"""
|
|
if event.button() == Qt.MouseButton.RightButton:
|
|
# 使用globalPosition()获取全局位置并转换为适合菜单显示的坐标
|
|
global_pos = event.globalPosition().toPoint()
|
|
if self.fileType == "file":
|
|
self.showFileContextMenu(global_pos)
|
|
else:
|
|
self.showFolderContextMenu(global_pos)
|
|
else:
|
|
super().mousePressEvent(event)
|
|
|
|
def loadIcon(self):
|
|
icon_name = getFileIcon(self.fileType, self.fileName)
|
|
self.iconLabel.setImage(QPixmap(f":app/icons/{icon_name}"))
|
|
self.iconLabel.scaledToHeight(25)
|
|
self.iconLabel.scaledToWidth(25)
|
|
|
|
def dirClicked(self):
|
|
if self.filePath == "/":
|
|
paths = "/" + self.fileName
|
|
else:
|
|
paths = f"{self.filePath}/{self.fileName}"
|
|
signalBus.dirOpenSignal.emit(paths)
|
|
|
|
def selfPreview(self):
|
|
if self.fileType == "file" and self.suffix in [
|
|
"jpg",
|
|
"png",
|
|
"jpeg",
|
|
"bmp",
|
|
"gif",
|
|
]:
|
|
signalBus.imagePreviewSignal.emit(self._id)
|
|
if self.fileType == "file" and self.suffix in ["txt", "py", "md"]:
|
|
signalBus.txtPreviewSignal.emit(self._id)
|
|
|
|
def downloadFile(self):
|
|
if self.fileType == "file":
|
|
# 构建Cloudreve V4 API所需的正确路径格式
|
|
# 确保不会出现重复的前缀和文件名
|
|
if self.filePath == "/":
|
|
# 根目录情况
|
|
full_path = f"cloudreve://my/{self.fileName}"
|
|
else:
|
|
# 子目录情况,确保正确拼接路径
|
|
# 清理路径,避免重复的斜杠
|
|
clean_path = self.filePath.lstrip("/")
|
|
full_path = f"cloudreve://my/{clean_path}/{self.fileName}"
|
|
# 确保路径格式正确,没有重复的部分
|
|
full_path = full_path.replace("cloudreve://my/cloudreve://my", "cloudreve://my")
|
|
# 确保没有重复的文件名
|
|
if f"/{self.fileName}/{self.fileName}" in full_path:
|
|
full_path = full_path.replace(f"/{self.fileName}/{self.fileName}", f"/{self.fileName}")
|
|
|
|
signalBus.addDownloadFileTask.emit(
|
|
f"own.{self.suffix}", self.fileName, full_path
|
|
)
|
|
|
|
def showFileContextMenu(self, pos):
|
|
"""显示上下文菜单"""
|
|
menu = RoundMenu(parent=self)
|
|
|
|
menu.addActions(
|
|
[
|
|
Action(
|
|
FIF.DOWNLOAD, lang("下载"), triggered=lambda: self.downloadFile()
|
|
),
|
|
Action(
|
|
FIF.PROJECTOR, lang("预览"), triggered=lambda: self.selfPreview()
|
|
),
|
|
]
|
|
)
|
|
|
|
menu.addSeparator()
|
|
menu.addActions(
|
|
[
|
|
Action(FIF.DELETE, lang("删除"), triggered=lambda: self.deleteSelf()),
|
|
]
|
|
)
|
|
|
|
menu.exec(pos, aniType=MenuAnimationType.DROP_DOWN)
|
|
|
|
def showFolderContextMenu(self, pos):
|
|
"""显示上下文菜单"""
|
|
menu = RoundMenu(parent=self)
|
|
|
|
menu.addActions(
|
|
[
|
|
Action(FIF.DOWNLOAD, lang("进入"), triggered=lambda: self.dirClicked()),
|
|
]
|
|
)
|
|
|
|
menu.addSeparator()
|
|
menu.addActions(
|
|
[
|
|
Action(FIF.DELETE, lang("删除"), triggered=lambda: self.deleteSelf()),
|
|
]
|
|
)
|
|
|
|
menu.exec(pos, aniType=MenuAnimationType.DROP_DOWN)
|
|
|
|
def deleteSelf(self):
|
|
w = MessageBox(
|
|
"确认删除",
|
|
f"你确定要删除{self.fileName}吗?\n删除后不可恢复噢!",
|
|
parent=self.window(),
|
|
)
|
|
if w.exec():
|
|
self.deleteThread = DeleteFileThread(self._id, self.fileType)
|
|
self.deleteThread.successDelete.connect(self.deleteSuccess)
|
|
self.deleteThread.errorDelete.connect(self.deleteError)
|
|
self.deleteThread.start()
|
|
else:
|
|
InfoBar.info(
|
|
"提示",
|
|
"删除已取消",
|
|
Qt.Orientation.Horizontal,
|
|
True,
|
|
1000,
|
|
InfoBarPosition.TOP_RIGHT,
|
|
self.window(),
|
|
)
|
|
|
|
def deleteSuccess(self):
|
|
InfoBar.success(
|
|
"成功",
|
|
"成功删除",
|
|
Qt.Orientation.Horizontal,
|
|
True,
|
|
1000,
|
|
InfoBarPosition.TOP_RIGHT,
|
|
self.window(),
|
|
)
|
|
signalBus.refreshFolderListSignal.emit()
|
|
|
|
def deleteError(self, error_msg):
|
|
InfoBar.error(
|
|
"失败",
|
|
"删除失败",
|
|
Qt.Orientation.Horizontal,
|
|
True,
|
|
1000,
|
|
InfoBarPosition.TOP_RIGHT,
|
|
self.window(),
|
|
)
|
|
logger.error(f"删除文件失败:{error_msg}")
|
|
|
|
def contextMenuEvent(self, e):
|
|
"""重写上下文菜单事件,确保只有右键点击才会触发"""
|
|
pass
|
|
|
|
|
|
class ShareFileCard(CardWidget):
|
|
def __init__(self, data, parent=None):
|
|
super().__init__(parent)
|
|
self._id = data["key"]
|
|
self.fileName = data["source"]["name"]
|
|
self.fileSize = data["source"]["size"]
|
|
self.changeTime = data["create_date"]
|
|
self.fileType = "dir" if data["is_dir"] else "file"
|
|
self.preview = data["preview"]
|
|
self.passWord = data["password"]
|
|
self.remainDownloads = data["remain_downloads"]
|
|
self.downloads = data["downloads"]
|
|
self.score = data["score"]
|
|
self.views = data["views"]
|
|
self.expireTime = data["expire"]
|
|
self.setFixedHeight(50)
|
|
|
|
self.iconLabel = ImageLabel(self)
|
|
|
|
self.fileNameLabel = StrongBodyLabel(self.fileName, self)
|
|
self.changeTimeLabel = BodyLabel(formatDate(self.changeTime), self)
|
|
|
|
self.viewButton = PushButton("查看", self)
|
|
self.viewButton.clicked.connect(self.viewFile)
|
|
|
|
self.hBoxLayout = QHBoxLayout(self)
|
|
self.hBoxLayout.addWidget(self.iconLabel)
|
|
self.hBoxLayout.addWidget(self.fileNameLabel)
|
|
self.hBoxLayout.addWidget(self.changeTimeLabel)
|
|
self.hBoxLayout.addWidget(self.viewButton)
|
|
|
|
self.hBoxLayout.setStretch(0, 1)
|
|
self.hBoxLayout.setStretch(1, 2)
|
|
self.hBoxLayout.setStretch(2, 1)
|
|
|
|
self.hBoxLayout.setContentsMargins(10, 10, 10, 10)
|
|
self.hBoxLayout.setSpacing(10)
|
|
|
|
self.loadIcon()
|
|
self.suffix = self.fileName.split(".")[-1].lower()
|
|
|
|
def loadIcon(self):
|
|
icon_name = getFileIcon(self.fileType, self.fileName)
|
|
self.iconLabel.setImage(QPixmap(f":app/icons/{icon_name}"))
|
|
self.iconLabel.scaledToHeight(25)
|
|
self.iconLabel.scaledToWidth(25)
|
|
|
|
def viewFile(self):
|
|
if self.fileType == "file":
|
|
w = ShareFileMessageBox(
|
|
self._id, self.iconLabel.pixmap(), self.suffix, self.window()
|
|
)
|
|
if w.exec():
|
|
...
|
|
else:
|
|
signalBus.shareFolderViewSignal.emit(self._id)
|
|
|
|
|
|
class SharedFolderFileCard(CardWidget):
|
|
shareFileDownloadSignal = pyqtSignal() # 共享文件下载信号
|
|
|
|
def __init__(self, key, _id, fileName, fileType, path, date, size, parent=None):
|
|
super().__init__(parent)
|
|
self._id = _id
|
|
self.key = key
|
|
self.fileName = fileName
|
|
self.fileSize = size
|
|
self.changeTime = date
|
|
self.fileType = fileType
|
|
self.filePath = path
|
|
self.setFixedHeight(50)
|
|
|
|
self.iconLabel = ImageLabel(self)
|
|
|
|
self.fileNameLabel = StrongBodyLabel(self.fileName, self)
|
|
self.fileSizeLabel = BodyLabel(formatSize(self.fileSize), self)
|
|
self.changeTimeLabel = BodyLabel(formatDate(self.changeTime), self)
|
|
|
|
self.hBoxLayout = QHBoxLayout(self)
|
|
self.hBoxLayout.addWidget(self.iconLabel)
|
|
self.hBoxLayout.addWidget(self.fileNameLabel)
|
|
self.hBoxLayout.addWidget(self.fileSizeLabel)
|
|
self.hBoxLayout.addWidget(self.changeTimeLabel)
|
|
|
|
self.hBoxLayout.setStretch(0, 1)
|
|
self.hBoxLayout.setStretch(1, 2)
|
|
self.hBoxLayout.setStretch(2, 1)
|
|
|
|
self.hBoxLayout.setContentsMargins(10, 10, 10, 10)
|
|
self.hBoxLayout.setSpacing(10)
|
|
|
|
self.loadIcon()
|
|
|
|
self.suffix = self.fileName.split(".")[-1].lower()
|
|
|
|
if self.fileType == "dir":
|
|
# 连接左键点击信号
|
|
self.clicked.connect(self.dirClicked)
|
|
|
|
def mousePressEvent(self, event):
|
|
"""重写鼠标点击事件,区分左右键"""
|
|
if event.button() == Qt.MouseButton.RightButton:
|
|
# 右键点击,显示上下文菜单
|
|
if self.fileType == "file":
|
|
self.showFileContextMenu(event.globalPos())
|
|
else:
|
|
self.showFolderContextMenu(event.globalPos())
|
|
else:
|
|
# 左键或其他按钮点击,调用父类处理
|
|
super().mousePressEvent(event)
|
|
|
|
def loadIcon(self):
|
|
icon_name = getFileIcon(self.fileType, self.fileName)
|
|
self.iconLabel.setImage(QPixmap(f":app/icons/{icon_name}"))
|
|
self.iconLabel.scaledToHeight(25)
|
|
self.iconLabel.scaledToWidth(25)
|
|
|
|
def dirClicked(self):
|
|
if self.filePath == "/":
|
|
paths = "/" + self.fileName
|
|
else:
|
|
paths = f"{self.filePath}/{self.fileName}"
|
|
signalBus.shareDirOpenSignal.emit(paths)
|
|
|
|
def downloadFile(self):
|
|
if self.fileType == "file":
|
|
signalBus.addDownloadFileTask.emit(
|
|
f"share.{self.suffix}",
|
|
self.fileName,
|
|
f"{self.filePath}/{self.fileName}.{self.key}",
|
|
)
|
|
signalBus.shareFileDownloadSignal.emit()
|
|
|
|
def showFileContextMenu(self, pos):
|
|
"""显示上下文菜单"""
|
|
menu = RoundMenu(parent=self)
|
|
|
|
menu.addActions(
|
|
[
|
|
Action(
|
|
FIF.DOWNLOAD, lang("下载"), triggered=lambda: self.downloadFile()
|
|
),
|
|
]
|
|
)
|
|
|
|
menu.exec(pos, aniType=MenuAnimationType.DROP_DOWN)
|
|
|
|
def showFolderContextMenu(self, pos):
|
|
"""显示上下文菜单"""
|
|
menu = RoundMenu(parent=self)
|
|
|
|
menu.addActions(
|
|
[
|
|
Action(FIF.DOWNLOAD, lang("进入"), triggered=lambda: self.dirClicked()),
|
|
]
|
|
)
|
|
|
|
menu.exec(pos, aniType=MenuAnimationType.DROP_DOWN)
|