class RecFolderDialog(QDialog): out = pyqtSignal(object) def __init__(self, files, parent=None): super(RecFolderDialog, self).__init__(parent) self.files = files self.initUI() self.setStyleSheet(others_style) def initUI(self): self.setWindowTitle("查看回收站文件夹内容") self.form = QVBoxLayout() for item in iter(self.files): ico = QPushButton(set_file_icon(item.name), item.name) ico.setStyleSheet( "QPushButton {border:none; background:transparent; color:black;}" ) ico.adjustSize() it = QLabel(f"<font color='#CCCCCC'>({item.size})</font>") hbox = QHBoxLayout() hbox.addWidget(ico) hbox.addStretch(1) hbox.addWidget(it) self.form.addLayout(hbox) self.form.setSpacing(10) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Close) self.buttonBox.button( QDialogButtonBox.StandardButton.Close).setText("关闭") self.buttonBox.setStyleSheet(btn_style) self.buttonBox.rejected.connect(self.reject) vbox = QVBoxLayout() vbox.addLayout(self.form) vbox.addStretch(1) vbox.addWidget(self.buttonBox) self.setLayout(vbox)
class MergeFileDialog(QDialog): check_update = pyqtSignal(str, bool) def __init__(self, user_home, parent=None): super(MergeFileDialog, self).__init__(parent) self.cwd = user_home self.selected = "" self.initUI() self.setStyleSheet(others_style) def initUI(self): self.setWindowTitle("合并文件") self.setWindowIcon(QIcon(SRC_DIR + "upload.ico")) self.logo = QLabel() self.logo.setPixmap(QPixmap(SRC_DIR + "logo3.gif")) self.logo.setStyleSheet("background-color:rgb(0,153,255);") self.logo.setAlignment(Qt.AlignmentFlag.AlignCenter) # lable self.choose_lb = QLabel("选择文件夹") # folder self.choose_folder = MyLineEdit(self) self.choose_folder.setObjectName("choose_folder") self.choose_folder.clicked.connect(self.slot_choose_folder) self.status = QLabel(self) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("提取") self.buttonBox.button( QDialogButtonBox.StandardButton.Cancel).setText("关闭") self.buttonBox.setStyleSheet(btn_style) vbox = QVBoxLayout() hbox_head = QHBoxLayout() hbox_button = QHBoxLayout() hbox_head.addWidget(self.choose_lb) hbox_head.addWidget(self.choose_folder) hbox_button.addWidget(self.buttonBox) vbox.addWidget(self.logo) vbox.addStretch(1) vbox.addWidget(self.status) vbox.addLayout(hbox_head) vbox.addStretch(1) vbox.addLayout(hbox_button) self.setLayout(vbox) self.setMinimumWidth(350) # 设置信号 self.buttonBox.accepted.connect(self.slot_btn_ok) self.buttonBox.rejected.connect(self.slot_btn_no) self.buttonBox.rejected.connect(self.reject) def slot_choose_folder(self): dir_choose = QFileDialog.getExistingDirectory(self, "选择文件夹", self.cwd) # 起始路径 if dir_choose == "": return self.selected = dir_choose self.choose_folder.setText(self.selected) self.status.setText("") self.cwd = os.path.dirname(dir_choose) def slot_btn_no(self): self.selected = "" self.choose_folder.setText(self.selected) self.status.setText("") def slot_btn_ok(self): if self.selected: success, msg = un_serialize(self.selected) if success: text = "提取成功✅" else: text = f"提取失败❌, {msg}" else: text = "未选择文件夹📂" self.status.setText(text)
def initUI(self): self.setWindowTitle("设置") logo = QLabel() logo.setPixmap(QPixmap(SRC_DIR + "logo2.gif")) logo.setStyleSheet("background-color:rgb(255,255,255);") logo.setAlignment(Qt.AlignmentFlag.AlignCenter) self.download_threads_lb = QLabel("同时下载文件数") self.download_threads_var = QLineEdit() self.download_threads_var.setPlaceholderText("范围:1-9") self.download_threads_var.setToolTip("范围:1-9") self.download_threads_var.setInputMask("D") self.max_size_lb = QLabel("分卷大小(MB)") self.max_size_var = QLineEdit() self.max_size_var.setPlaceholderText("普通用户最大100,vip用户根据具体情况设置") self.max_size_var.setToolTip("普通用户最大100,vip用户根据具体情况设置") self.max_size_var.setInputMask("D99") self.timeout_lb = QLabel("请求超时(秒)") self.timeout_var = QLineEdit() self.timeout_var.setPlaceholderText("范围:1-99") self.timeout_var.setToolTip("范围:1-99") self.timeout_var.setInputMask("D9") self.upload_delay_lb = QLabel("上传延时(秒)") self.upload_delay_var = QLineEdit() self.upload_delay_var.setPlaceholderText("范围:1-99") self.upload_delay_var.setToolTip("范围:1-99") self.upload_delay_var.setInputMask("D9") self.dl_path_lb = QLabel("下载保存路径") self.dl_path_var = MyLineEdit(self) self.dl_path_var.clicked.connect(self.set_download_path) self.time_fmt_box = QCheckBox("使用[年-月-日]时间格式") self.time_fmt_box.setToolTip("文件上传日期显示格式") self.to_tray_box = QCheckBox("关闭到系统托盘") self.to_tray_box.setToolTip("点击关闭软件按钮是最小化软件至系统托盘") self.watch_clipboard_box = QCheckBox("监听系统剪切板") self.watch_clipboard_box.setToolTip("检测到系统剪切板中有符合规范的蓝奏链接时自动唤起软件,并提取") self.debug_box = QCheckBox("开启调试日志") self.debug_box.setToolTip("记录软件 debug 信息至 debug-lanzou-gui.log 文件") self.set_pwd_box = QCheckBox("上传文件自动设置密码") self.set_pwd_var = AutoResizingTextEdit() self.set_pwd_var.setPlaceholderText(" 2-8 位数字或字母") self.set_pwd_var.setToolTip("2-8 位数字或字母") self.set_desc_box = QCheckBox("上传文件自动设置描述") self.set_desc_var = AutoResizingTextEdit() self.big_file_box = QCheckBox(f"允许上传超过 {self.max_size}MB 的大文件") self.big_file_box.setToolTip("开启大文件上传支持 (功能下线)") self.upgrade_box = QCheckBox("自动检测新版本") self.upgrade_box.setToolTip("在软件打开时自动检测是否有新的版本发布,如有则弹出更新信息") self.time_fmt_box.toggle() self.time_fmt_box.stateChanged.connect(self.change_time_fmt) self.to_tray_box.stateChanged.connect(self.change_to_tray) self.watch_clipboard_box.stateChanged.connect(self.change_watch_clipboard) self.debug_box.stateChanged.connect(self.change_debug) self.set_pwd_box.stateChanged.connect(self.change_set_pwd) self.set_pwd_var.editingFinished.connect(self.check_pwd) self.set_desc_box.stateChanged.connect(self.change_set_desc) self.big_file_box.stateChanged.connect(self.change_big_file) self.upgrade_box.stateChanged.connect(self.change_upgrade) buttonBox = QDialogButtonBox() buttonBox.setOrientation(Qt.Orientation.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Reset | QDialogButtonBox.StandardButton.Save | QDialogButtonBox.StandardButton.Cancel) buttonBox.button(QDialogButtonBox.StandardButton.Reset).setText("重置") buttonBox.button(QDialogButtonBox.StandardButton.Save).setText("保存") buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消") buttonBox.button(QDialogButtonBox.StandardButton.Reset).clicked.connect(lambda: self.set_values(reset=True)) buttonBox.button(QDialogButtonBox.StandardButton.Save).clicked.connect(self.slot_save) buttonBox.rejected.connect(self.reject) form = QFormLayout() form.setLabelAlignment(Qt.AlignmentFlag.AlignRight) form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow) # 覆盖MacOS的默认样式 form.setSpacing(10) form.addRow(self.download_threads_lb, self.download_threads_var) form.addRow(self.timeout_lb, self.timeout_var) form.addRow(self.upload_delay_lb, self.upload_delay_var) form.addRow(self.max_size_lb, self.max_size_var) form.addRow(self.dl_path_lb, self.dl_path_var) vbox = QVBoxLayout() vbox.addWidget(logo) vbox.addStretch(1) vbox.addLayout(form) vbox.addStretch(1) hbox = QHBoxLayout() hbox.addWidget(self.time_fmt_box) hbox.addWidget(self.to_tray_box) hbox.addWidget(self.watch_clipboard_box) hbox.addWidget(self.debug_box) vbox.addLayout(hbox) vbox.addStretch(1) hbox_2 = QHBoxLayout() hbox_2.addWidget(self.set_pwd_box) hbox_2.addWidget(self.set_pwd_var) vbox.addLayout(hbox_2) vbox.addStretch(1) hbox_3 = QHBoxLayout() hbox_3.addWidget(self.set_desc_box) hbox_3.addWidget(self.set_desc_var) vbox.addLayout(hbox_3) hbox_4 = QHBoxLayout() hbox_4.addWidget(self.big_file_box) hbox_4.addWidget(self.upgrade_box) vbox.addStretch(1) vbox.addLayout(hbox_4) vbox.addStretch(2) vbox.addWidget(buttonBox) self.setLayout(vbox) self.setMinimumWidth(500)
class MoveFileDialog(QDialog): '''移动文件对话框''' new_infos = pyqtSignal(object) def __init__(self, parent=None): super(MoveFileDialog, self).__init__(parent) self.infos = None self.dirs = {} self.initUI() self.setStyleSheet(dialog_qss_style) def update_ui(self): names = "\n".join([i.name for i in self.infos]) names_tip = "\n".join([i.name for i in self.infos]) self.tx_name.setText(names) self.tx_name.setToolTip(names_tip) self.tx_new_path.clear() f_icon = QIcon(SRC_DIR + "folder.gif") for f_name, fid in self.dirs.items(): if len(f_name) > 50: # 防止文件夹名字过长? f_name = f_name[:47] + "..." self.tx_new_path.addItem(f_icon, "id:{:>8},name:{}".format(fid, f_name)) def set_values(self, infos, all_dirs_dict): self.infos = infos self.dirs = all_dirs_dict self.update_ui() self.exec() def initUI(self): self.setWindowTitle("移动文件(夹)") self.setWindowIcon(QIcon(SRC_DIR + "move.ico")) self.lb_name = QLabel() self.lb_name.setText("文件(夹)名:") self.lb_name.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter) self.tx_name = AutoResizingTextEdit() self.tx_name.setFocusPolicy(Qt.FocusPolicy.NoFocus) # 只读 self.tx_name.setReadOnly(True) self.lb_new_path = QLabel() self.lb_new_path.setText("目标文件夹:") self.lb_new_path.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter) self.tx_new_path = QComboBox() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定") self.buttonBox.button( QDialogButtonBox.StandardButton.Cancel).setText("取消") self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.lb_name, 1, 0) self.grid.addWidget(self.tx_name, 1, 1) self.grid.addWidget(self.lb_new_path, 2, 0) self.grid.addWidget(self.tx_new_path, 2, 1) self.grid.addWidget(self.buttonBox, 3, 0, 1, 2) self.setLayout(self.grid) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.setMinimumWidth(280) def btn_ok(self): new_id = self.tx_new_path.currentText().split(",")[0].split(":")[1] for index in range(len(self.infos)): self.infos[index].new_id = int(new_id) self.new_infos.emit(self.infos)
class InfoDialog(QDialog): """文件信息对话框""" get_dl_link = pyqtSignal(str, str) closed = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.infos = None self._short_link_flag = True # 防止多次重试 self.initUI() self.setStyleSheet(dialog_qss_style) def update_ui(self): self.tx_dl_link.setPlaceholderText("单击获取") self.tx_name.setText(self.infos.name) if self.infos.is_file: self.setWindowTitle("文件信息") self.lb_name.setText("文件名:") self.lb_desc.setText("文件描述:") self.tx_dl_link.setText("") # 清空旧的信息 self.lb_dl_link.setVisible(True) self.tx_dl_link.setVisible(True) else: self.setWindowTitle("文件夹信息") self.lb_name.setText("文件夹名:") self.lb_desc.setText("文件夹描述:") self.lb_dl_link.setVisible(False) self.tx_dl_link.setVisible(False) if self.infos.size: self.tx_size.setText(self.infos.size) self.lb_size.setVisible(True) self.tx_size.setVisible(True) else: self.tx_size.setVisible(False) self.lb_size.setVisible(False) if self.infos.time: self.lb_time.setVisible(True) self.tx_time.setVisible(True) self.tx_time.setText(self.infos.time) else: self.lb_time.setVisible(False) self.tx_time.setVisible(False) if self.infos.downs: self.lb_dl_count.setVisible(True) self.tx_dl_count.setVisible(True) self.tx_dl_count.setText(str(self.infos.downs)) else: self.tx_dl_count.setVisible(False) self.lb_dl_count.setVisible(False) if self.infos.pwd: self.tx_pwd.setText(self.infos.pwd) self.tx_pwd.setPlaceholderText("") else: self.tx_pwd.setText("") self.tx_pwd.setPlaceholderText("无") if self.infos.desc: self.tx_desc.setText(self.infos.desc) self.tx_desc.setPlaceholderText("") else: self.tx_desc.setText("") self.tx_desc.setPlaceholderText("无") self.tx_share_url.setText(self.infos.url) self.adjustSize() def set_values(self, infos): self.infos = infos self.update_ui() def set_dl_link_tx(self, text): self.tx_dl_link.setText(text) self.adjustSize() def call_get_dl_link(self): url = self.tx_share_url.text() pwd = self.tx_pwd.text() self.get_dl_link.emit(url, pwd) self.tx_dl_link.setPlaceholderText("后台获取中,请稍候!") def call_get_short_url(self): if self._short_link_flag: self._short_link_flag = False self.tx_short.setPlaceholderText("后台获取中,请稍候!") url = self.tx_share_url.text() from lanzou.api.extra import get_short_url short_url = get_short_url(url) if short_url: self.tx_short.setText(short_url) self.tx_short.setPlaceholderText("") self._short_link_flag = True else: self.tx_short.setText("") self.tx_short.setPlaceholderText("生成失败!api 可能已经失效") def clean(self): self._short_link_flag = True self.tx_short.setText("") self.tx_short.setPlaceholderText("单击获取") def initUI(self): self.setWindowIcon(QIcon(SRC_DIR + "share.ico")) self.setWindowTitle("文件信息") self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Close) self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setText("关闭") self.buttonBox.rejected.connect(self.reject) self.buttonBox.rejected.connect(self.clean) self.buttonBox.rejected.connect(self.closed.emit) self.logo = QLabel() self.logo.setPixmap(QPixmap(SRC_DIR + "q9.gif")) self.logo.setAlignment(Qt.AlignmentFlag.AlignCenter) self.logo.setStyleSheet("background-color:rgb(255,204,51);") self.lb_name = QLabel() self.lb_name.setText("文件名:") self.tx_name = AutoResizingTextEdit() self.tx_name.setReadOnly(True) self.tx_name.setMinimumLines(1) self.lb_size = QLabel() self.lb_size.setText("文件大小:") self.tx_size = QLabel() self.lb_time = QLabel() self.lb_time.setText("上传时间:") self.tx_time = QLabel() self.lb_dl_count = QLabel() self.lb_dl_count.setText("下载次数:") self.tx_dl_count = QLabel() self.lb_share_url = QLabel() self.lb_share_url.setText("分享链接:") self.tx_share_url = QLineEdit() self.tx_share_url.setReadOnly(True) self.lb_pwd = QLabel() self.lb_pwd.setText("提取码:") self.tx_pwd = QLineEdit() self.tx_pwd.setReadOnly(True) self.lb_short = QLabel() self.lb_short.setText("短链接:") self.tx_short = AutoResizingTextEdit(self) self.tx_short.setPlaceholderText("单击获取") self.tx_short.clicked.connect(self.call_get_short_url) self.tx_short.setReadOnly(True) self.tx_short.setMinimumLines(1) self.lb_desc = QLabel() self.lb_desc.setText("文件描述:") self.tx_desc = AutoResizingTextEdit() self.tx_desc.setReadOnly(True) self.tx_desc.setMinimumLines(1) self.lb_dl_link = QLabel() self.lb_dl_link.setText("下载直链:") self.tx_dl_link = AutoResizingTextEdit(self) self.tx_dl_link.setPlaceholderText("单击获取") self.tx_dl_link.clicked.connect(self.call_get_dl_link) self.tx_dl_link.setReadOnly(True) self.tx_dl_link.setMinimumLines(1) vbox = QVBoxLayout() vbox.addWidget(self.logo) vbox.addStretch(1) form = QFormLayout() form.setLabelAlignment(Qt.AlignmentFlag.AlignRight) form.addRow(self.lb_name, self.tx_name) form.addRow(self.lb_size, self.tx_size) form.addRow(self.lb_time, self.tx_time) form.addRow(self.lb_dl_count, self.tx_dl_count) form.addRow(self.lb_share_url, self.tx_share_url) form.addRow(self.lb_pwd, self.tx_pwd) form.addRow(self.lb_short, self.tx_short) form.addRow(self.lb_desc, self.tx_desc) form.addRow(self.lb_dl_link, self.tx_dl_link) form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow) # 覆盖MacOS的默认样式 vbox.addLayout(form) vbox.addStretch(1) vbox.addWidget(self.buttonBox) self.setLayout(vbox) self.setMinimumWidth(500)
class RenameDialog(QDialog): out = pyqtSignal(object) def __init__(self, parent=None): super(RenameDialog, self).__init__(parent) self.infos = [] self.min_width = 400 self.initUI() self.update_text() self.setStyleSheet(dialog_qss_style) def set_values(self, infos=None): self.infos = infos or [] self.update_text() # 更新界面 def initUI(self): self.setWindowIcon(QIcon(SRC_DIR + "desc.ico")) self.lb_name = QLabel() self.lb_name.setText("文件夹名:") self.lb_name.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter) self.tx_name = QLineEdit() self.lb_desc = QLabel() self.tx_desc = QTextEdit() self.lb_desc.setText("描 述:") self.lb_desc.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定") self.buttonBox.button( QDialogButtonBox.StandardButton.Cancel).setText("取消") self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.lb_name, 1, 0) self.grid.addWidget(self.tx_name, 1, 1) self.grid.addWidget(self.lb_desc, 2, 0) self.grid.addWidget(self.tx_desc, 2, 1, 5, 1) self.grid.addWidget(self.buttonBox, 7, 1, 1, 1) self.setLayout(self.grid) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def update_text(self): self.tx_desc.setFocus() num = len(self.infos) if num == 1: self.lb_name.setVisible(True) self.tx_name.setVisible(True) infos = self.infos[0] self.buttonBox.button( QDialogButtonBox.StandardButton.Ok).setToolTip("") # 去除新建文件夹影响 self.buttonBox.button( QDialogButtonBox.StandardButton.Ok).setEnabled( True) # 去除新建文件夹影响 self.setWindowTitle("修改文件夹名与描述") self.tx_name.setText(str(infos.name)) if infos.desc: self.tx_desc.setText(str(infos.desc)) self.tx_desc.setToolTip('原描述:' + str(infos.desc)) else: self.tx_desc.setText("") self.tx_desc.setToolTip('') self.tx_desc.setPlaceholderText("无") self.min_width = len(str(infos.name)) * 8 if infos.is_file: self.setWindowTitle("修改文件描述") self.tx_name.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.tx_name.setReadOnly(True) else: self.tx_name.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.tx_name.setReadOnly(False) self.tx_name.setFocus() elif num > 1: self.lb_name.setVisible(False) self.tx_name.setVisible(False) self.setWindowTitle(f"批量修改{num}个文件(夹)的描述") self.tx_desc.setText('') self.tx_desc.setPlaceholderText("建议160字数以内。") else: self.setWindowTitle("新建文件夹") self.tx_name.setText("") self.buttonBox.button( QDialogButtonBox.StandardButton.Ok).setEnabled(False) self.buttonBox.button( QDialogButtonBox.StandardButton.Ok).setToolTip("请先输入文件名!") self.tx_name.textChanged.connect(self.slot_new_ok_btn) self.tx_name.setPlaceholderText("不支持空格,如有会被自动替换成 _") self.tx_name.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.tx_name.setReadOnly(False) self.tx_desc.setPlaceholderText("可选项,建议160字数以内。") self.tx_name.setFocus() if self.min_width < 400: self.min_width = 400 self.resize(self.min_width, 200) def slot_new_ok_btn(self): """新建文件夹槽函数""" self.buttonBox.button( QDialogButtonBox.StandardButton.Ok).setEnabled(True) self.buttonBox.button( QDialogButtonBox.StandardButton.Ok).setToolTip("") def btn_ok(self): new_name = self.tx_name.text() new_des = self.tx_desc.toPlainText() info_len = len(self.infos) if info_len == 0: # 在 work_id 新建文件夹 if new_name: self.out.emit(("new", new_name, new_des)) elif info_len == 1: if new_name != self.infos[0].name or new_des != self.infos[0].desc: self.infos[0].new_des = new_des self.infos[0].new_name = new_name self.out.emit(("change", self.infos)) else: if new_des: for infos in self.infos: infos.new_des = new_des self.out.emit(("change", self.infos))
class AboutDialog(QDialog): check_update = pyqtSignal(str, bool) def __init__(self, parent=None): super(AboutDialog, self).__init__(parent) self._ver = '' self._github = 'https://github.com/rachpt/lanzou-gui' self._api_url = 'https://github.com/zaxtyson/LanZouCloud-API' self._gitee = 'https://gitee.com/rachpt/lanzou-gui' self._home_page = 'https://rachpt.cn/lanzou-gui/' self.initUI() self.setStyleSheet(others_style) def set_values(self, version): self._ver = version self.lb_name_text.setText(f"v{version} (点击检查更新)") # 更新版本 def show_update(self, ver, msg): self.lb_new_ver = QLabel("新版") # 检测新版 self.lb_new_ver_msg = QLabel() self.lb_new_ver_msg.setOpenExternalLinks(True) self.lb_new_ver_msg.setWordWrap(True) if ver != '0': self.lb_name_text.setText(f"{self._ver} ➡ {ver}") self.lb_new_ver_msg.setText(msg) self.lb_new_ver_msg.setMinimumWidth(700) if self.form.rowCount() < 5: self.form.insertRow(1, self.lb_new_ver, self.lb_new_ver_msg) def initUI(self): self.setWindowTitle("关于 lanzou-gui") about = f'本项目使用PyQt6实现图形界面,可以完成蓝奏云的大部分功能<br/> \ 得益于 <a href="{self._api_url}">API</a> 的功能,可以间接突破单文件最大 100MB 的限制,同时增加了批量上传/下载的功能<br/> \ Python 依赖见<a href="{self._github }/blob/master/requirements.txt">requirements.txt</a>,\ <a href="{self._github}/releases">releases</a> 有打包好了的 Windows 可执行程序,但可能不是最新的' project_url = f'<a href="{self._home_page}">主页</a> | <a href="{self._github}">repo</a> | \ <a href="{self._gitee}">mirror repo</a>' self.logo = QLabel() # logo self.logo.setPixmap(QPixmap(SRC_DIR + "logo2.gif")) self.logo.setStyleSheet("background-color:rgb(255,255,255);") self.logo.setAlignment(Qt.AlignmentFlag.AlignCenter) self.lb_qt_ver = QLabel("依赖") # QT 版本 self.lb_qt_text = QLabel( f"QT: {QT_VERSION_STR}, PyQt: {PYQT_VERSION_STR}") # QT 版本 self.lb_name = QLabel("版本") # 版本 self.lb_name_text = QPushButton("") # 版本 self.lb_name_text.setToolTip("点击检查更新") ver_style = "QPushButton {border:none; background:transparent;font-weight:bold;color:blue;}" self.lb_name_text.setStyleSheet(ver_style) self.lb_name_text.clicked.connect( lambda: self.check_update.emit(self._ver, True)) self.lb_about = QLabel("关于") # about self.lb_about_text = QLabel() self.lb_about_text.setText(about) self.lb_about_text.setOpenExternalLinks(True) self.lb_author = QLabel("作者") # author self.lb_author_mail = QLabel( "<a href='mailto:[email protected]'>rachpt</a>") self.lb_author_mail.setOpenExternalLinks(True) self.lb_update = QLabel("项目") # 更新 self.lb_update_url = QLabel(project_url) self.lb_update_url.setOpenExternalLinks(True) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Close) self.buttonBox.button( QDialogButtonBox.StandardButton.Close).setText("关闭") self.buttonBox.rejected.connect(self.reject) self.buttonBox.setStyleSheet(btn_style) self.recommend = QLabel( "<br />大文件推荐使用 <a href='https://github.com/Aruelius/cloud189'>cloud189-cli</a>" ) self.recommend.setOpenExternalLinks(True) self.line = QLine(QPoint(), QPoint(550, 0)) self.lb_line = QLabel('<html><hr /></html>') vbox = QVBoxLayout() vbox.addWidget(self.logo) vbox.addStretch(1) self.form = QFormLayout() self.form.setLabelAlignment(Qt.AlignmentFlag.AlignRight) self.form.setFormAlignment(Qt.AlignmentFlag.AlignLeft) self.form.setHorizontalSpacing(40) self.form.setVerticalSpacing(15) self.form.addRow(self.lb_qt_ver, self.lb_qt_text) self.form.addRow(self.lb_name, self.lb_name_text) self.form.addRow(self.lb_update, self.lb_update_url) self.form.addRow(self.lb_author, self.lb_author_mail) self.form.addRow(self.lb_about, self.lb_about_text) self.form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy. AllNonFixedFieldsGrow) # 覆盖MacOS的默认样式 vbox.addLayout(self.form) vbox.addStretch(1) vbox.addWidget(self.recommend) vbox.addWidget(self.lb_line) donate = QLabel() donate.setText("<b>捐助我</b> 如果你愿意") donate.setAlignment(Qt.AlignmentFlag.AlignCenter) hbox = QHBoxLayout() hbox.addStretch(2) for it in ["wechat", "alipay", "qqpay"]: lb = QLabel() lb.setPixmap(QPixmap(SRC_DIR + f"{it}.jpg")) hbox.addWidget(lb) hbox.addStretch(1) hbox.addWidget(self.buttonBox) vbox.addWidget(donate) vbox.addLayout(hbox) self.setLayout(vbox) self.setMinimumWidth(720) def paintEvent(self, event): QDialog.paintEvent(self, event) if not self.line.isNull(): painter = QPainter(self) pen = QPen(Qt.GlobalColor.red, 3) painter.setPen(pen) painter.drawLine(self.line)
class SetPwdDialog(QDialog): new_infos = pyqtSignal(object) def __init__(self, parent=None): super(SetPwdDialog, self).__init__(parent) self.infos = [] self.initUI() self.update_text() self.setStyleSheet(dialog_qss_style) def set_values(self, infos): self.infos = infos self.update_text() # 更新界面 def set_tip(self): # 用于提示状态 self.setWindowTitle("请稍等……") def initUI(self): self.setWindowTitle("请稍等……") self.setWindowIcon(QIcon(SRC_DIR + "password.ico")) self.lb_oldpwd = QLabel() self.lb_oldpwd.setText("当前提取码:") self.lb_oldpwd.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter) self.tx_oldpwd = QLineEdit() # 当前提取码 只读 self.tx_oldpwd.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.tx_oldpwd.setReadOnly(True) self.lb_newpwd = QLabel() self.lb_newpwd.setText("新的提取码:") self.lb_newpwd.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter) self.tx_newpwd = QLineEdit() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定") self.buttonBox.button( QDialogButtonBox.StandardButton.Cancel).setText("取消") self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.lb_oldpwd, 1, 0) self.grid.addWidget(self.tx_oldpwd, 1, 1) self.grid.addWidget(self.lb_newpwd, 2, 0) self.grid.addWidget(self.tx_newpwd, 2, 1) self.grid.addWidget(self.buttonBox, 3, 0, 1, 2) self.setLayout(self.grid) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.accepted.connect(self.set_tip) self.buttonBox.rejected.connect(self.reject) self.buttonBox.rejected.connect(self.set_tip) self.setMinimumWidth(280) def update_text(self): num = len(self.infos) if num == 1: self.tx_oldpwd.setVisible(True) self.lb_oldpwd.setVisible(True) infos = self.infos[0] if infos.has_pwd: self.tx_oldpwd.setText(str(infos.pwd)) self.tx_oldpwd.setPlaceholderText("") else: self.tx_oldpwd.setText("") self.tx_oldpwd.setPlaceholderText("无") if isinstance(infos, FileInfos): # 文件 通过size列判断是否为文件 self.setWindowTitle("修改文件提取码") self.tx_newpwd.setPlaceholderText("2-6位字符,关闭请留空") self.tx_newpwd.setMaxLength(6) # 最长6个字符 else: # 文件夹 self.setWindowTitle("修改文件夹名提取码") self.tx_newpwd.setPlaceholderText("2-12位字符,关闭请留空") self.tx_newpwd.setMaxLength(12) # 最长12个字符 elif num > 1: self.tx_oldpwd.setVisible(False) self.lb_oldpwd.setVisible(False) self.setWindowTitle(f"批量修改{num}个文件(夹)的提取码") self.tx_newpwd.setPlaceholderText("2-12位字符,关闭请留空") self.tx_newpwd.setMaxLength(12) # 最长12个字符 self.tx_newpwd.setText('') for infos in self.infos: if isinstance(infos, FileInfos): # 文件 self.tx_newpwd.setPlaceholderText("2-6位字符,文件无法关闭") self.tx_newpwd.setMaxLength(6) # 最长6个字符 break def btn_ok(self): new_pwd = self.tx_newpwd.text() for infos in self.infos: infos.new_pwd = new_pwd self.new_infos.emit(self.infos) # 最后一位用于标示文件还是文件夹
class DeleteDialog(QDialog): new_infos = pyqtSignal(object) def __init__(self, infos, parent=None): super(DeleteDialog, self).__init__(parent) self.infos = infos self.out = [] self.initUI() self.setStyleSheet(dialog_qss_style) def initUI(self): self.setWindowTitle("确认删除") self.setWindowIcon(QIcon(SRC_DIR + "delete.ico")) self.layout = QVBoxLayout() self.list_view = QListView() self.list_view.setViewMode(QListView.ViewMode.ListMode) # 列表 self.slm = QStandardItem() self.model = QStandardItemModel() max_len = 10 count = 0 for info in self.infos: if info.is_file: # 文件 self.model.appendRow( QStandardItem(set_file_icon(info.name), info.name)) else: self.model.appendRow( QStandardItem(QIcon(SRC_DIR + "folder.gif"), info.name)) self.out.append({ 'fid': info.id, 'is_file': info.is_file, 'name': info.name }) # id,文件标示, 文件名 count += 1 if max_len < len(info.name): # 使用最大文件名长度 max_len = len(info.name) self.list_view.setModel(self.model) self.lb_name = QLabel("尝试删除以下{}个文件(夹):".format(count)) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定") self.buttonBox.button( QDialogButtonBox.StandardButton.Cancel).setText("取消") self.layout.addWidget(self.lb_name) self.layout.addWidget(self.list_view) self.layout.addWidget(self.buttonBox) self.setLayout(self.layout) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.setMinimumWidth(400) self.resize(int(max_len * 8), int(count * 34 + 60)) def btn_ok(self): self.new_infos.emit(self.out)
class UploadDialog(QDialog): """文件上传对话框""" new_infos = pyqtSignal(object) def __init__(self, user_home): super().__init__() self.cwd = user_home self._folder_id = -1 self._folder_name = "LanZouCloud" self.set_pwd = False self.set_desc = False self.pwd = '' self.desc = '' self.allow_big_file = False self.max_size = 100 self.selected = [] self.initUI() self.set_size() self.setStyleSheet(dialog_qss_style) def set_pwd_desc_bigfile(self, settings): self.set_pwd = settings["set_pwd"] self.set_desc = settings["set_desc"] self.pwd = settings["pwd"] self.desc = settings["desc"] self.allow_big_file = settings["allow_big_file"] self.max_size = settings["max_size"] if self.allow_big_file: self.btn_chooseMultiFile.setToolTip("") else: self.btn_chooseMultiFile.setToolTip(f"文件大小上限 {self.max_size}MB") def set_values(self, folder_name, folder_id, files): self.setWindowTitle("上传文件至 ➩ " + str(folder_name)) self._folder_id = folder_id self._folder_name = folder_name if files: self.selected = files self.show_selected() self.exec() def initUI(self): self.setWindowTitle("上传文件") self.setWindowIcon(QIcon(SRC_DIR + "upload.ico")) self.logo = QLabel() self.logo.setPixmap(QPixmap(SRC_DIR + "logo3.gif")) self.logo.setStyleSheet("background-color:rgb(0,153,255);") self.logo.setAlignment(Qt.AlignmentFlag.AlignCenter) # btn 1 self.btn_chooseDir = QPushButton("选择文件夹", self) self.btn_chooseDir.setObjectName("btn_chooseDir") self.btn_chooseDir.setObjectName("btn_chooseDir") self.btn_chooseDir.setIcon(QIcon(SRC_DIR + "folder.gif")) # btn 2 self.btn_chooseMultiFile = QPushButton("选择多文件", self) self.btn_chooseDir.setObjectName("btn_chooseMultiFile") self.btn_chooseMultiFile.setObjectName("btn_chooseMultiFile") self.btn_chooseMultiFile.setIcon(QIcon(SRC_DIR + "file.ico")) # btn 3 self.btn_deleteSelect = QPushButton("移除", self) self.btn_deleteSelect.setObjectName("btn_deleteSelect") self.btn_deleteSelect.setIcon(QIcon(SRC_DIR + "delete.ico")) self.btn_deleteSelect.setToolTip("按 Delete 移除选中文件") # 列表 self.list_view = MyListView() self.list_view.drop_files.connect(self.add_drop_files) self.list_view.setViewMode(QListView.ViewMode.ListMode) self.slm = QStandardItem() self.model = QStandardItemModel() self.list_view.setModel(self.model) self.model.removeRows(0, self.model.rowCount()) # 清除旧的选择 self.list_view.setEditTriggers( QAbstractItemView.EditTrigger.NoEditTriggers) self.list_view.setSelectionBehavior( QAbstractItemView.SelectionBehavior.SelectRows) self.list_view.setSelectionMode( QAbstractItemView.SelectionMode.ExtendedSelection) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定") self.buttonBox.button( QDialogButtonBox.StandardButton.Cancel).setText("取消") vbox = QVBoxLayout() hbox_head = QHBoxLayout() hbox_button = QHBoxLayout() hbox_head.addWidget(self.btn_chooseDir) hbox_head.addStretch(1) hbox_head.addWidget(self.btn_chooseMultiFile) hbox_button.addWidget(self.btn_deleteSelect) hbox_button.addStretch(1) hbox_button.addWidget(self.buttonBox) vbox.addWidget(self.logo) vbox.addLayout(hbox_head) vbox.addWidget(self.list_view) vbox.addLayout(hbox_button) self.setLayout(vbox) self.setMinimumWidth(350) # 设置信号 self.btn_chooseDir.clicked.connect(self.slot_btn_chooseDir) self.btn_chooseMultiFile.clicked.connect(self.slot_btn_chooseMultiFile) self.btn_deleteSelect.clicked.connect(self.slot_btn_deleteSelect) self.buttonBox.accepted.connect(self.slot_btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.clear_old) self.buttonBox.rejected.connect(self.reject) def set_size(self): if self.selected: h = 18 if len(self.selected) > 18 else 10 w = 40 for i in self.selected: i_len = len(i) if i_len > 100: w = 100 break if i_len > w: w = i_len self.resize(120 + w * 7, h * 30) else: self.resize(400, 300) def clear_old(self): self.selected = [] self.model.removeRows(0, self.model.rowCount()) self.set_size() def show_selected(self): self.model.removeRows(0, self.model.rowCount()) for item in self.selected: if os.path.isfile(item): self.model.appendRow( QStandardItem(QIcon(SRC_DIR + "file.ico"), item)) else: self.model.appendRow( QStandardItem(QIcon(SRC_DIR + "folder.gif"), item)) self.set_size() def backslash(self): """Windows backslash""" tasks = {} for item in self.selected: url = os.path.normpath(item) total_size = 0 total_file = 0 if os.path.isfile(url): total_size = os.path.getsize(url) if not total_size: continue # 空文件无法上传 total_file += 1 else: for filename in os.listdir(url): file_path = os.path.join(url, filename) if not os.path.isfile(file_path): continue # 跳过子文件夹 total_size += os.path.getsize(file_path) total_file += 1 tasks[url] = UpJob(url=url, fid=self._folder_id, folder=self._folder_name, pwd=self.pwd if self.set_pwd else None, desc=self.desc if self.set_desc else None, total_size=total_size, total_file=total_file) return tasks def slot_btn_ok(self): tasks = self.backslash() if self.selected: self.new_infos.emit(tasks) self.clear_old() def slot_btn_deleteSelect(self): _indexes = self.list_view.selectionModel().selection().indexes() if not _indexes: return indexes = [] for i in _indexes: # 获取所选行号 indexes.append(i.row()) indexes = set(indexes) for i in sorted(indexes, reverse=True): self.selected.remove(self.model.item(i, 0).text()) self.model.removeRow(i) self.set_size() def add_drop_files(self, files): for item in files: if item not in self.selected: self.selected.append(item) self.show_selected() def slot_btn_chooseDir(self): dir_choose = QFileDialog.getExistingDirectory(self, "选择文件夹", self.cwd) # 起始路径 if dir_choose == "": return if dir_choose not in self.selected: self.selected.append(dir_choose) self.cwd = os.path.dirname(dir_choose) self.show_selected() def slot_btn_chooseMultiFile(self): files, _ = QFileDialog.getOpenFileNames(self, "选择多文件", self.cwd, "All Files (*)") if len(files) == 0: return for _file in files: if _file not in self.selected: if os.path.getsize(_file) <= self.max_size * 1048576: self.selected.append(_file) elif self.allow_big_file: self.selected.append(_file) self.show_selected() def keyPressEvent(self, e): if e.key() == Qt.Key.Key_Delete: # delete self.slot_btn_deleteSelect()