From 0e397ace7db42667585e776874c6392a8699d10b Mon Sep 17 00:00:00 2001 From: taynpg Date: Tue, 24 Mar 2026 22:25:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6=E5=A4=B9?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E8=BF=9B=E5=BA=A6=E6=9B=B4=E6=96=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- ClientCore/ClientCore.cpp | 99 ++++++++++++++++++++++++++++++- ClientCore/ClientCore.h | 49 ++++++++++++++- ClientCore/FileTrans.cpp | 22 ++++++- Gui/Control/FileControl.cpp | 115 +++++++++++------------------------- Gui/Control/FileControl.h | 23 -------- Note/version.md | 107 ++++++++++++++++----------------- Protocol/Protocol.h | 3 + Test/BaseTest.cpp | 4 ++ Test/CMakeLists.txt | 2 +- Util/Util.cpp | 28 +++++++++ Util/Util.h | 1 + 12 files changed, 290 insertions(+), 165 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b84d094..0cc2fd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(frelay VERSION 0.2.6 LANGUAGES CXX) +project(frelay VERSION 0.2.7 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/ClientCore/ClientCore.cpp b/ClientCore/ClientCore.cpp index 439726a..60e6f58 100644 --- a/ClientCore/ClientCore.cpp +++ b/ClientCore/ClientCore.cpp @@ -142,6 +142,10 @@ void ClientCore::handleAsk(QSharedPointer frame) } return; } + // 这个请求的处理可能是耗时的,需要开线程处理。 + if (msg.command == STRMSG_AC_ALL_DIRFILES) { + msg.command = STRMSG_AC_ANSWER_ALL_DIRFILES; + } // 未知信息 qWarning() << QString(tr("未知询问信息类型:%1")).arg(msg.command); } @@ -413,4 +417,97 @@ void WaitThread::interrupCheck() isAlreadyInter_ = true; emit sigCheckOver(); } -} \ No newline at end of file +} + +WaitOper::WaitOper(QObject* parent) : WaitThread(parent) +{ +} + +void WaitOper::run() +{ + isAlreadyInter_ = false; + infoMsg_.msg = STR_NONE; + isRun_ = true; + recvMsg_ = false; + + InfoMsg msg; + msg.command = sendStrType_; + msg.fromPath = stra_; + msg.toPath = strb_; + msg.type = type_; + + auto f = cli_->GetBuffer(msg, FBT_MSGINFO_ASK, cli_->GetRemoteID()); + if (!ClientCore::syncInvoke(cli_, f)) { + auto errMsg = QString(tr("向%1发送%2请求失败。")).arg(cli_->GetRemoteID()).arg(sendStrType_); + emit sigCheckOver(); + qCritical() << errMsg; + return; + } + while (isRun_) { + QThread::msleep(1); + if (isAlreadyInter_) { + qInfo() << tr("线程中断文件操作等待......"); + return; + } + if (!recvMsg_) { + continue; + } + break; + } + isAlreadyInter_ = true; + emit sigCheckOver(); + auto n = QString(tr("向%1的请求%2处理结束。")).arg(cli_->GetRemoteID()).arg(sendStrType_); + qInfo() << n; +} + +void WaitOper::SetType(const QString& sendType, const QString& ansType) +{ + sendStrType_ = sendType; + ansStrType_ = ansType; +} + +void WaitOper::SetPath(const QString& stra, const QString& strb, const QString& type) +{ + stra_ = stra; + strb_ = strb; + type_ = type; +} + +InfoMsg WaitOper::GetMsg() const +{ + return infoMsg_; +} + +void WaitOper::interrupCheck() +{ + qWarning() << QString(tr("中断请求处理%1......")).arg(sendStrType_); + WaitThread::interrupCheck(); +} + +void WaitOper::recvFrame(QSharedPointer frame) +{ + InfoMsg info = infoUnpack(frame->data); + if (info.command == ansStrType_) { + infoMsg_ = info; + recvMsg_ = true; + return; + } + auto n = tr("收到未知Oper的回复信息:") + info.command; + qInfo() << n; +} + +WaitOperOwn::WaitOperOwn(QObject* parent) : WaitThread(parent) +{ +} + +void WaitOperOwn::run() +{ + if (func_) { + func_(); + } + emit sigOver(); +} + +void WaitOperOwn::recvFrame(QSharedPointer frame) +{ +} diff --git a/ClientCore/ClientCore.h b/ClientCore/ClientCore.h index 340d2d5..be50990 100644 --- a/ClientCore/ClientCore.h +++ b/ClientCore/ClientCore.h @@ -123,7 +123,7 @@ public: LocalFile localFile_; }; -// Socket Worker Thread +// 工作线程。 class SocketWorker : public QThread { Q_OBJECT @@ -139,7 +139,7 @@ private: ClientCore* core_{}; }; -// HeatBeat to Server +// 心跳包线程。 class HeatBeat : public QThread { Q_OBJECT @@ -159,6 +159,7 @@ private: ClientCore* core_{}; }; +// 耗时操作线程基本框架。 class WaitThread : public QThread { Q_OBJECT @@ -183,4 +184,48 @@ protected: ClientCore* cli_{}; }; +// 等待对方应答的等待线程。 +class WaitOper : public WaitThread +{ +public: + WaitOper(QObject* parent = nullptr); + +public: + void run() override; + void SetType(const QString& sendType, const QString& ansType); + void SetPath(const QString& stra, const QString& strb, const QString& type); + InfoMsg GetMsg() const; + void interrupCheck() override; + void recvFrame(QSharedPointer frame) override; + +private: + bool recvMsg_{}; + InfoMsg infoMsg_{}; + QString sendStrType_{}; + QString ansStrType_{}; + QString stra_; + QString strb_; + QString type_; +}; + +// 等待自己耗时操作的线程。 +class WaitOperOwn : public WaitThread +{ + Q_OBJECT + +public: + WaitOperOwn(QObject* parent = nullptr); + +signals: + void sigOver(); + +public: + void run() override; + void recvFrame(QSharedPointer frame) override; + +public: + InfoMsg infoMsg_{}; + std::function func_; +}; + #endif // CLIENTCORE_H \ No newline at end of file diff --git a/ClientCore/FileTrans.cpp b/ClientCore/FileTrans.cpp index b355bb8..6c1eea7 100644 --- a/ClientCore/FileTrans.cpp +++ b/ClientCore/FileTrans.cpp @@ -398,7 +398,25 @@ void FileTrans::SendFile(const QSharedPointer& task) QMutexLocker locker(&sthMut_); upTasks_[task->task.localId] = sendThread; - sendThread->run(); + + // 2026-03-24 找了一个可能卡顿的原因。 + /* + 在 Qt 的 QThread类中,start()和 run()有本质区别: + + start()- 创建新线程 sendThread->start(); // ✅ 正确 + + 启动一个新线程,在新线程中执行 run()方法,线程有自己的事件循环(如果调用 exec()) + + 自动处理线程同步和资源管理信号/槽可以跨线程工作 + + run()- 只是普通方法调用 sendThread->run(); // ❌ 错误用法 + + 在当前线程中直接调用这个方法,没有创建新线程阻塞当前线程直到 run()返回 + + 对象的信号/槽仍然在原始线程上下文中 + */ + // sendThread->run(); + sendThread->start(); } SendThread::SendThread(ClientCore* clientCore) : cliCore_(clientCore) @@ -442,7 +460,7 @@ void SendThread::run() } task_->tranSize += frame->data.size(); // 关键点:这里不调用,无法中途收到别人发的数据。 - QCoreApplication::processEvents(); + // QCoreApplication::processEvents(); } qInfo() << QString(tr("结束发送文件:%1")).arg(task_->file.fileName()); diff --git a/Gui/Control/FileControl.cpp b/Gui/Control/FileControl.cpp index 7c9687f..d5ad21e 100644 --- a/Gui/Control/FileControl.cpp +++ b/Gui/Control/FileControl.cpp @@ -511,6 +511,34 @@ void FileManager::UpDown() QMessageBox::information(this, tr("提示"), tr("请选择完整的行。")); return; } + + // + WaitOperOwn wo(this); + auto getAllItems = [this, &datas, &wo]() { + wo.infoMsg_.list.clear(); + for (int i = 0; i < (datas.size() / 5); ++i) { + const auto& curType = datas[i * 5 + 3]->text(); + if (curType == "File") { + wo.infoMsg_.list << datas[i * 5 + 1]->text(); + } else { + QVector fs; + DirFileHelper::GetAllFiles(datas[i * 5 + 1]->text(), fs); + if (!fs.isEmpty()) { + wo.infoMsg_.list << fs; + } + } + } + }; + wo.func_ = getAllItems; + + LoadingDialog checking(this); + checking.setTipsText("正在获取文件列表..."); + checking.setCanCancel(false); + connect(&wo, &WaitOperOwn::sigOver, &checking, &LoadingDialog::cancelBtnClicked); + + wo.start(); + checking.exec(); + QVector tasks; for (int i = 0; i < (datas.size() / 5); ++i) { if (datas[i * 5 + 3]->text() != "File") { @@ -569,7 +597,7 @@ void FileManager::OperNewFolder() if (!isRemote_) { QString ret = Util::NewDir(folder); if (ret.isEmpty()) { - //QMessageBox::information(this, tr("提示"), tr("创建%1成功").arg(folder)); + // QMessageBox::information(this, tr("提示"), tr("创建%1成功").arg(folder)); DirFileInfo nf; nf.size = 0; nf.type = Dir; @@ -609,7 +637,7 @@ void FileManager::OperNewFolder() if (msg.msg == STR_NONE || !msg.msg.isEmpty()) { QMessageBox::information(this, tr("提示"), QString(tr("新建失败=>%1")).arg(msg.msg)); } else { - //QMessageBox::information(this, tr("提示"), QString(tr("新建%1成功。")).arg(folder)); + // QMessageBox::information(this, tr("提示"), QString(tr("新建%1成功。")).arg(folder)); DirFileInfo nf; nf.size = 0; nf.type = Dir; @@ -642,7 +670,7 @@ void FileManager::OperDelete() if (!isRemote_) { QString ret = Util::Delete(name); if (ret.isEmpty()) { - //QMessageBox::information(this, tr("提示"), tr("删除成功")); + // QMessageBox::information(this, tr("提示"), tr("删除成功")); int row = datas[0]->row(); ui->tableWidget->removeRow(row); } else { @@ -676,7 +704,7 @@ void FileManager::OperDelete() if (msg.msg == STR_NONE || !msg.msg.isEmpty()) { QMessageBox::information(this, tr("提示"), QString(tr("删除失败=>%1")).arg(msg.msg)); } else { - //QMessageBox::information(this, tr("提示"), QString(tr("删除成功。"))); + // QMessageBox::information(this, tr("提示"), QString(tr("删除成功。"))); ui->tableWidget->removeRow(datas[0]->row()); } } @@ -824,81 +852,4 @@ void FileManager::doubleClick(int row, int column) QDir dir(GetRoot()); QString np = dir.filePath(item->text()); fileHelper_->GetDirFile(np); -} - -WaitOper::WaitOper(QObject* parent) : WaitThread(parent) -{ -} - -void WaitOper::run() -{ - isAlreadyInter_ = false; - infoMsg_.msg = STR_NONE; - isRun_ = true; - recvMsg_ = false; - - InfoMsg msg; - msg.command = sendStrType_; - msg.fromPath = stra_; - msg.toPath = strb_; - msg.type = type_; - - auto f = cli_->GetBuffer(msg, FBT_MSGINFO_ASK, cli_->GetRemoteID()); - if (!ClientCore::syncInvoke(cli_, f)) { - auto errMsg = QString(tr("向%1发送%2请求失败。")).arg(cli_->GetRemoteID()).arg(sendStrType_); - emit sigCheckOver(); - qCritical() << errMsg; - return; - } - while (isRun_) { - QThread::msleep(1); - if (isAlreadyInter_) { - qInfo() << tr("线程中断文件操作等待......"); - return; - } - if (!recvMsg_) { - continue; - } - break; - } - isAlreadyInter_ = true; - emit sigCheckOver(); - auto n = QString(tr("向%1的请求%2处理结束。")).arg(cli_->GetRemoteID()).arg(sendStrType_); - qInfo() << n; -} - -void WaitOper::SetType(const QString& sendType, const QString& ansType) -{ - sendStrType_ = sendType; - ansStrType_ = ansType; -} - -void WaitOper::SetPath(const QString& stra, const QString& strb, const QString& type) -{ - stra_ = stra; - strb_ = strb; - type_ = type; -} - -InfoMsg WaitOper::GetMsg() const -{ - return infoMsg_; -} - -void WaitOper::interrupCheck() -{ - qWarning() << QString(tr("中断请求处理%1......")).arg(sendStrType_); - WaitThread::interrupCheck(); -} - -void WaitOper::recvFrame(QSharedPointer frame) -{ - InfoMsg info = infoUnpack(frame->data); - if (info.command == ansStrType_) { - infoMsg_ = info; - recvMsg_ = true; - return; - } - auto n = tr("收到未知Oper的回复信息:") + info.command; - qInfo() << n; -} +} \ No newline at end of file diff --git a/Gui/Control/FileControl.h b/Gui/Control/FileControl.h index 094e916..4a7fd2d 100644 --- a/Gui/Control/FileControl.h +++ b/Gui/Control/FileControl.h @@ -28,29 +28,6 @@ enum class SortMethod { SMD_BY_SIZE_ASC, }; -class WaitOper : public WaitThread -{ -public: - WaitOper(QObject* parent = nullptr); - -public: - void run() override; - void SetType(const QString& sendType, const QString& ansType); - void SetPath(const QString& stra, const QString& strb, const QString& type); - InfoMsg GetMsg() const; - void interrupCheck() override; - void recvFrame(QSharedPointer frame) override; - -private: - bool recvMsg_{}; - InfoMsg infoMsg_{}; - QString sendStrType_{}; - QString ansStrType_{}; - QString stra_; - QString strb_; - QString type_; -}; - class FileManager : public QWidget { Q_OBJECT diff --git a/Note/version.md b/Note/version.md index bd00089..79056d7 100644 --- a/Note/version.md +++ b/Note/version.md @@ -6,56 +6,57 @@ ## 问题清单: -| 序号 | 类型 | 内容 | 说明 | 基于版本 | 完成版本 | -| :--: | :--: | ------------------------------------------------------------ | :----: | :------: | :------: | -| 51 | 问题 | 按照类型传输时,类型重复的问题修正 | | 0.2.5 | 0.2.6 | -| 50 | 功能 | 添加日志内容清空按钮。 | | 0.2.4 | 0.2.5 | -| 49 | 功能 | 对照传输支持按照类型传输。 | | 0.2.4 | 0.2.5 | -| 48 | 优化 | 选择上传下载移动到右键菜单中。 | | 0.2.4 | 0.2.5 | -| 47 | 优化 | 删除新建文件(夹)成功时不提示。 | | 0.2.4 | 0.2.5 | -| 46 | 功能 | 需要一个压缩传输功能。 | | 0.2.4 | | -| 45 | 问题 | 出现过重连后无法刷新客户端列表问题。 | 偶发 | 0.2.4 | | -| 44 | 问题 | 出现过多选下载显示远程文件不存在问题,但是单个下没问题。 | 偶发 | 0.2.4 | | -| 43 | 问题 | 资源占用过多问题。 | | 0.2.3 | 0.2.4 | -| 42 | 优化 | 访问文件过多时,界面有卡顿情况。 | | 0.2.3 | 0.2.4 | -| 41 | 问题 | 主动中断检查等待后,软件崩溃。 | | 0.2.3 | 0.2.4 | -| 40 | 问题 | 上传方完成后,接收端未接收完毕不能退出的问题。 | | 0.2.3 | 0.2.4 | -| 39 | 优化 | Console端断联后应当自动退出。 | | 0.2.3 | 0.2.4 | -| 38 | 功能 | PE中使用没有拖拽功能,文件管理器要有下载/上传按钮。 | | 0.2.3 | 0.2.4 | -| 37 | 问题 | 未连接对方客户端时,执行对照传输会崩溃。 | 待复现 | 0.2.3 | | -| 36 | 功能 | 备份文件功能。 | | 0.2.3 | | -| 35 | 功能 | 完善对照功能的界面其他内容。 | | 0.2.3 | | -| 34 | 功能 | 支持删除、重命名、新建文件(夹)。 | | 0.2.3 | 0.2.4 | -| 33 | 功能 | 弹窗查看文件(夹)属性窗口。 | | 0.2.3 | 0.2.4 | -| 32 | 功能 | 路径选择显示驱动器。 | | 0.2.2 | 0.2.3 | -| 31 | 功能 | Server端buffer大小判断,有过多无效数据则踢出该客户端。 | | 0.2.2 | 0.2.4 | -| 30 | 功能 | 传输界面的取消退出,缺失功能处理。 | | 0.2.2 | 0.2.3 | -| 29 | 功能 | 根据接收端的速率限制发送端的速度。 | | 0.2.2 | 0.2.3 | -| 28 | 变更 | 语言简体中文。 | | 0.2.2 | 0.2.3 | -| 27 | 功能 | 传输前检查对方或者自己是否已存在某些文件,提示是否覆盖。 | | 0.2.2 | 0.2.3 | -| 26 | 功能 | 最好能保存关闭界面时Splitter和UI的尺寸。 | | 0.2.2 | | -| 25 | 功能 | 手动输入的文件夹访问路径保存历史记录,以便后续可能再次使用(10条)。 | | 0.2.2 | | -| 24 | 问题 | 发送端如果发送的数据比较大,UI会卡住(功能是正常的)。 | | 0.2.2 | 0.2.3 | -| 23 | 问题 | 作为接收端如果对方断联要处理这个情况。 | | 0.2.2 | 0.2.3 | -| 22 | 功能 | 配置可以切组。 | | 0.2.2 | | -| 21 | 功能 | 可以传输文件夹。 | | 0.2.2 | | -| 20 | 功能 | 对照传输可以打开本地文件夹。 | | 0.2.2 | 0.2.3 | -| 19 | 问题 | 客户之间心跳包,被动/主动失联后断开,清除相关内容,终止相关任务。 | | 0.2.2 | 0.2.3 | -| 18 | 问题 | 断开后重连貌似没有发送心跳包。 | | 0.1 | 0.2 | -| 17 | 问题 | 服务端主动踢出的客户端,主动重连假链接,不可用无反应。 | | 0.1 | 0.2 | -| 16 | 优化 | 传输完成后接收端要刷新一次。 | | 0.1 | | -| 15 | 问题 | 拖动文件夹到对方,应当不处理,并日志提示。 | | 0.1 | 0.2 | -| 14 | 功能 | 文件浏览部分添加右键复制全路径功能。 | | 0.1 | 0.2 | -| 13 | 功能 | IP端口部分要添加可选择历史。 | | 0.1 | 0.2 | -| 12 | 功能 | 对照传输前要先校验文件存在性。 | | 0.1 | 0.2.3 | -| 11 | 问题 | 断连后当前远端ID要清除。 | | 0.1 | 0.2 | -| 10 | 功能 | 对照传输可以支持反向下载。 | | 0.1 | 0.2 | -| 9 | 优化 | 输入路径后可以直接回车访问。 | | 0.1 | 0.2 | -| 8 | 功能 | 文件浏览页面要支持按照类型排序,时间排序,和文件后缀筛选。 | | 0.1 | 0.2 | -| 7 | 优化 | IP和Port宽度要合理一些,IP过小,Port宽度过大。 | | 0.1 | 0.2 | -| 6 | 功能 | 比对控件添加可尝试目录浏览控件跳转到指定目录。 | | 0.1 | 0.2 | -| 5 | 问题 | 未设置心跳包,导致超时被Server端踢出。 | 必改 | 0.1 | 0.2 | -| 4 | 问题 | 重复链接Server会崩溃。 | | 0.1 | 0.2 | -| 3 | 优化 | 首次启动时应当按照当前分辨率进行初始化大小,而不是指定大小。 | | 0.1 | 0.2 | -| 2 | 问题 | 当某个文件传输失败的时候,关闭传输窗口,再次传输显示已经在传输中。 | | 0.1 | 0.2.3 | -| 1 | 问题 | Console端显示未注册QSharedPointer\类型 | | 0.1 | 0.2 | +| 序号 | 类型 | 内容 | 说明 | 基于版本 | 完成版本 | +| :--: | :--: | ------------------------------------------------------------ | :------------: | :------: | :------: | +| 52 | 问题 | 发送大文件时,UI有不流畅现象。 | 完成版本待观察 | 0.2.6 | | +| 51 | 问题 | 按照类型传输时,类型重复的问题修正 | | 0.2.5 | 0.2.6 | +| 50 | 功能 | 添加日志内容清空按钮。 | | 0.2.4 | 0.2.5 | +| 49 | 功能 | 对照传输支持按照类型传输。 | | 0.2.4 | 0.2.5 | +| 48 | 优化 | 选择上传下载移动到右键菜单中。 | | 0.2.4 | 0.2.5 | +| 47 | 优化 | 删除新建文件(夹)成功时不提示。 | | 0.2.4 | 0.2.5 | +| 46 | 功能 | 需要一个压缩传输功能。 | | 0.2.4 | | +| 45 | 问题 | 出现过重连后无法刷新客户端列表问题。 | 偶发 | 0.2.4 | | +| 44 | 问题 | 出现过多选下载显示远程文件不存在问题,但是单个下没问题。 | 偶发 | 0.2.4 | | +| 43 | 问题 | 资源占用过多问题。 | | 0.2.3 | 0.2.4 | +| 42 | 优化 | 访问文件过多时,界面有卡顿情况。 | | 0.2.3 | 0.2.4 | +| 41 | 问题 | 主动中断检查等待后,软件崩溃。 | | 0.2.3 | 0.2.4 | +| 40 | 问题 | 上传方完成后,接收端未接收完毕不能退出的问题。 | | 0.2.3 | 0.2.4 | +| 39 | 优化 | Console端断联后应当自动退出。 | | 0.2.3 | 0.2.4 | +| 38 | 功能 | PE中使用没有拖拽功能,文件管理器要有下载/上传按钮。 | | 0.2.3 | 0.2.4 | +| 37 | 问题 | 未连接对方客户端时,执行对照传输会崩溃。 | 待复现 | 0.2.3 | | +| 36 | 功能 | 备份文件功能。 | | 0.2.3 | | +| 35 | 功能 | 完善对照功能的界面其他内容。 | | 0.2.3 | | +| 34 | 功能 | 支持删除、重命名、新建文件(夹)。 | | 0.2.3 | 0.2.4 | +| 33 | 功能 | 弹窗查看文件(夹)属性窗口。 | | 0.2.3 | 0.2.4 | +| 32 | 功能 | 路径选择显示驱动器。 | | 0.2.2 | 0.2.3 | +| 31 | 功能 | Server端buffer大小判断,有过多无效数据则踢出该客户端。 | | 0.2.2 | 0.2.4 | +| 30 | 功能 | 传输界面的取消退出,缺失功能处理。 | | 0.2.2 | 0.2.3 | +| 29 | 功能 | 根据接收端的速率限制发送端的速度。 | | 0.2.2 | 0.2.3 | +| 28 | 变更 | 语言简体中文。 | | 0.2.2 | 0.2.3 | +| 27 | 功能 | 传输前检查对方或者自己是否已存在某些文件,提示是否覆盖。 | | 0.2.2 | 0.2.3 | +| 26 | 功能 | 最好能保存关闭界面时Splitter和UI的尺寸。 | | 0.2.2 | | +| 25 | 功能 | 手动输入的文件夹访问路径保存历史记录,以便后续可能再次使用(10条)。 | | 0.2.2 | | +| 24 | 问题 | 发送端如果发送的数据比较大,UI会卡住(功能是正常的)。 | | 0.2.2 | 0.2.3 | +| 23 | 问题 | 作为接收端如果对方断联要处理这个情况。 | | 0.2.2 | 0.2.3 | +| 22 | 功能 | 配置可以切组。 | | 0.2.2 | | +| 21 | 功能 | 可以传输文件夹。 | | 0.2.2 | | +| 20 | 功能 | 对照传输可以打开本地文件夹。 | | 0.2.2 | 0.2.3 | +| 19 | 问题 | 客户之间心跳包,被动/主动失联后断开,清除相关内容,终止相关任务。 | | 0.2.2 | 0.2.3 | +| 18 | 问题 | 断开后重连貌似没有发送心跳包。 | | 0.1 | 0.2 | +| 17 | 问题 | 服务端主动踢出的客户端,主动重连假链接,不可用无反应。 | | 0.1 | 0.2 | +| 16 | 优化 | 传输完成后接收端要刷新一次。 | | 0.1 | | +| 15 | 问题 | 拖动文件夹到对方,应当不处理,并日志提示。 | | 0.1 | 0.2 | +| 14 | 功能 | 文件浏览部分添加右键复制全路径功能。 | | 0.1 | 0.2 | +| 13 | 功能 | IP端口部分要添加可选择历史。 | | 0.1 | 0.2 | +| 12 | 功能 | 对照传输前要先校验文件存在性。 | | 0.1 | 0.2.3 | +| 11 | 问题 | 断连后当前远端ID要清除。 | | 0.1 | 0.2 | +| 10 | 功能 | 对照传输可以支持反向下载。 | | 0.1 | 0.2 | +| 9 | 优化 | 输入路径后可以直接回车访问。 | | 0.1 | 0.2 | +| 8 | 功能 | 文件浏览页面要支持按照类型排序,时间排序,和文件后缀筛选。 | | 0.1 | 0.2 | +| 7 | 优化 | IP和Port宽度要合理一些,IP过小,Port宽度过大。 | | 0.1 | 0.2 | +| 6 | 功能 | 比对控件添加可尝试目录浏览控件跳转到指定目录。 | | 0.1 | 0.2 | +| 5 | 问题 | 未设置心跳包,导致超时被Server端踢出。 | 必改 | 0.1 | 0.2 | +| 4 | 问题 | 重复链接Server会崩溃。 | | 0.1 | 0.2 | +| 3 | 优化 | 首次启动时应当按照当前分辨率进行初始化大小,而不是指定大小。 | | 0.1 | 0.2 | +| 2 | 问题 | 当某个文件传输失败的时候,关闭传输窗口,再次传输显示已经在传输中。 | | 0.1 | 0.2.3 | +| 1 | 问题 | Console端显示未注册QSharedPointer\类型 | | 0.1 | 0.2 | diff --git a/Protocol/Protocol.h b/Protocol/Protocol.h index 5f76b53..5f20e18 100644 --- a/Protocol/Protocol.h +++ b/Protocol/Protocol.h @@ -102,6 +102,9 @@ enum FileCheckState { #define STRMSG_AC_UP "upAction" #define STRMSG_AC_DOWN "downAction" +#define STRMSG_AC_ALL_DIRFILES "askAllDirFiles" +#define STRMSG_AC_ANSWER_ALL_DIRFILES "answerAllDirFiles" + #define STRMSG_ST_FILEEXIT "fileExist" #define STRMSG_ST_FILENOEXIT "fileNotExist" #define STRMSG_ST_DIREXIT "dirExist" diff --git a/Test/BaseTest.cpp b/Test/BaseTest.cpp index 6d96019..7329c04 100644 --- a/Test/BaseTest.cpp +++ b/Test/BaseTest.cpp @@ -1,6 +1,7 @@ #include #include #include +#include void DateTimeTest() { @@ -14,5 +15,8 @@ int main(int argc, char** argv) qDebug() << "Running..."; DateTimeTest(); + QVector files; + DirFileHelper::GetAllFiles("D:/备份软件", files); + return app.exec(); } \ No newline at end of file diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt index 0a31571..6bc2f9a 100644 --- a/Test/CMakeLists.txt +++ b/Test/CMakeLists.txt @@ -21,4 +21,4 @@ add_executable(frelayTest ${MSOURCES}) target_link_libraries(frelayTest PRIVATE Protocol Util) add_executable(frelayBaseTest BaseTest.cpp) -target_link_libraries(frelayBaseTest Qt${QT_VERSION_MAJOR}::Core) +target_link_libraries(frelayBaseTest Qt${QT_VERSION_MAJOR}::Core Util Protocol) diff --git a/Util/Util.cpp b/Util/Util.cpp index 0f4bff0..4057363 100644 --- a/Util/Util.cpp +++ b/Util/Util.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,33 @@ QString DirFileHelper::GetErr() const return QString(); } +bool DirFileHelper::GetAllFiles(const QString& rootPath, QVector& files) +{ + QDir rootDir(rootPath); + + if (!rootDir.exists()) { + qWarning() << "目录不存在:" << rootPath; + return false; + } + + QString absoluteRootPath = rootDir.absolutePath(); + QDirIterator it(absoluteRootPath, QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + + while (it.hasNext()) { + it.next(); + QFileInfo fileInfo = it.fileInfo(); + if (fileInfo.isFile()) { + QString absoluteFilePath = fileInfo.absoluteFilePath(); + QString relativePath = absoluteFilePath.mid(absoluteRootPath.length()); + if (relativePath.startsWith('/') || relativePath.startsWith('\\')) { + relativePath = relativePath.mid(1); + } + files.append(relativePath); + } + } + return true; +} + DirFileHelper::DirFileHelper(QObject* parent) : QObject(parent) { } diff --git a/Util/Util.h b/Util/Util.h index 053ab44..2c64850 100644 --- a/Util/Util.h +++ b/Util/Util.h @@ -67,6 +67,7 @@ public: public: QString GetErr() const; + static bool GetAllFiles(const QString& rootPath, QVector& files); signals: void sigHome(const QString& path, const QVector& drivers);