添加文件夹传输进度更新。
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
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 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
|||||||
@@ -142,6 +142,10 @@ void ClientCore::handleAsk(QSharedPointer<FrameBuffer> frame)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 这个请求的处理可能是耗时的,需要开线程处理。
|
||||||
|
if (msg.command == STRMSG_AC_ALL_DIRFILES) {
|
||||||
|
msg.command = STRMSG_AC_ANSWER_ALL_DIRFILES;
|
||||||
|
}
|
||||||
// 未知信息
|
// 未知信息
|
||||||
qWarning() << QString(tr("未知询问信息类型:%1")).arg(msg.command);
|
qWarning() << QString(tr("未知询问信息类型:%1")).arg(msg.command);
|
||||||
}
|
}
|
||||||
@@ -413,4 +417,97 @@ void WaitThread::interrupCheck()
|
|||||||
isAlreadyInter_ = true;
|
isAlreadyInter_ = true;
|
||||||
emit sigCheckOver();
|
emit sigCheckOver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<InfoMsg>(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<FrameBuffer> frame)
|
||||||
|
{
|
||||||
|
InfoMsg info = infoUnpack<InfoMsg>(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<FrameBuffer> frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
LocalFile localFile_;
|
LocalFile localFile_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Socket Worker Thread
|
// 工作线程。
|
||||||
class SocketWorker : public QThread
|
class SocketWorker : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -139,7 +139,7 @@ private:
|
|||||||
ClientCore* core_{};
|
ClientCore* core_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// HeatBeat to Server
|
// 心跳包线程。
|
||||||
class HeatBeat : public QThread
|
class HeatBeat : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -159,6 +159,7 @@ private:
|
|||||||
ClientCore* core_{};
|
ClientCore* core_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 耗时操作线程基本框架。
|
||||||
class WaitThread : public QThread
|
class WaitThread : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -183,4 +184,48 @@ protected:
|
|||||||
ClientCore* cli_{};
|
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<FrameBuffer> 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<FrameBuffer> frame) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
InfoMsg infoMsg_{};
|
||||||
|
std::function<void()> func_;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CLIENTCORE_H
|
#endif // CLIENTCORE_H
|
||||||
@@ -398,7 +398,25 @@ void FileTrans::SendFile(const QSharedPointer<DoTransTask>& task)
|
|||||||
|
|
||||||
QMutexLocker locker(&sthMut_);
|
QMutexLocker locker(&sthMut_);
|
||||||
upTasks_[task->task.localId] = sendThread;
|
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)
|
SendThread::SendThread(ClientCore* clientCore) : cliCore_(clientCore)
|
||||||
@@ -442,7 +460,7 @@ void SendThread::run()
|
|||||||
}
|
}
|
||||||
task_->tranSize += frame->data.size();
|
task_->tranSize += frame->data.size();
|
||||||
// 关键点:这里不调用,无法中途收到别人发的数据。
|
// 关键点:这里不调用,无法中途收到别人发的数据。
|
||||||
QCoreApplication::processEvents();
|
// QCoreApplication::processEvents();
|
||||||
}
|
}
|
||||||
qInfo() << QString(tr("结束发送文件:%1")).arg(task_->file.fileName());
|
qInfo() << QString(tr("结束发送文件:%1")).arg(task_->file.fileName());
|
||||||
|
|
||||||
|
|||||||
@@ -511,6 +511,34 @@ void FileManager::UpDown()
|
|||||||
QMessageBox::information(this, tr("提示"), tr("请选择完整的行。"));
|
QMessageBox::information(this, tr("提示"), tr("请选择完整的行。"));
|
||||||
return;
|
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<QString> 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<TransTask> tasks;
|
QVector<TransTask> tasks;
|
||||||
for (int i = 0; i < (datas.size() / 5); ++i) {
|
for (int i = 0; i < (datas.size() / 5); ++i) {
|
||||||
if (datas[i * 5 + 3]->text() != "File") {
|
if (datas[i * 5 + 3]->text() != "File") {
|
||||||
@@ -569,7 +597,7 @@ void FileManager::OperNewFolder()
|
|||||||
if (!isRemote_) {
|
if (!isRemote_) {
|
||||||
QString ret = Util::NewDir(folder);
|
QString ret = Util::NewDir(folder);
|
||||||
if (ret.isEmpty()) {
|
if (ret.isEmpty()) {
|
||||||
//QMessageBox::information(this, tr("提示"), tr("创建%1成功").arg(folder));
|
// QMessageBox::information(this, tr("提示"), tr("创建%1成功").arg(folder));
|
||||||
DirFileInfo nf;
|
DirFileInfo nf;
|
||||||
nf.size = 0;
|
nf.size = 0;
|
||||||
nf.type = Dir;
|
nf.type = Dir;
|
||||||
@@ -609,7 +637,7 @@ void FileManager::OperNewFolder()
|
|||||||
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
|
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
|
||||||
QMessageBox::information(this, tr("提示"), QString(tr("新建失败=>%1")).arg(msg.msg));
|
QMessageBox::information(this, tr("提示"), QString(tr("新建失败=>%1")).arg(msg.msg));
|
||||||
} else {
|
} else {
|
||||||
//QMessageBox::information(this, tr("提示"), QString(tr("新建%1成功。")).arg(folder));
|
// QMessageBox::information(this, tr("提示"), QString(tr("新建%1成功。")).arg(folder));
|
||||||
DirFileInfo nf;
|
DirFileInfo nf;
|
||||||
nf.size = 0;
|
nf.size = 0;
|
||||||
nf.type = Dir;
|
nf.type = Dir;
|
||||||
@@ -642,7 +670,7 @@ void FileManager::OperDelete()
|
|||||||
if (!isRemote_) {
|
if (!isRemote_) {
|
||||||
QString ret = Util::Delete(name);
|
QString ret = Util::Delete(name);
|
||||||
if (ret.isEmpty()) {
|
if (ret.isEmpty()) {
|
||||||
//QMessageBox::information(this, tr("提示"), tr("删除成功"));
|
// QMessageBox::information(this, tr("提示"), tr("删除成功"));
|
||||||
int row = datas[0]->row();
|
int row = datas[0]->row();
|
||||||
ui->tableWidget->removeRow(row);
|
ui->tableWidget->removeRow(row);
|
||||||
} else {
|
} else {
|
||||||
@@ -676,7 +704,7 @@ void FileManager::OperDelete()
|
|||||||
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
|
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
|
||||||
QMessageBox::information(this, tr("提示"), QString(tr("删除失败=>%1")).arg(msg.msg));
|
QMessageBox::information(this, tr("提示"), QString(tr("删除失败=>%1")).arg(msg.msg));
|
||||||
} else {
|
} else {
|
||||||
//QMessageBox::information(this, tr("提示"), QString(tr("删除成功。")));
|
// QMessageBox::information(this, tr("提示"), QString(tr("删除成功。")));
|
||||||
ui->tableWidget->removeRow(datas[0]->row());
|
ui->tableWidget->removeRow(datas[0]->row());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -824,81 +852,4 @@ void FileManager::doubleClick(int row, int column)
|
|||||||
QDir dir(GetRoot());
|
QDir dir(GetRoot());
|
||||||
QString np = dir.filePath(item->text());
|
QString np = dir.filePath(item->text());
|
||||||
fileHelper_->GetDirFile(np);
|
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<InfoMsg>(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<FrameBuffer> frame)
|
|
||||||
{
|
|
||||||
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
|
|
||||||
if (info.command == ansStrType_) {
|
|
||||||
infoMsg_ = info;
|
|
||||||
recvMsg_ = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto n = tr("收到未知Oper的回复信息:") + info.command;
|
|
||||||
qInfo() << n;
|
|
||||||
}
|
|
||||||
@@ -28,29 +28,6 @@ enum class SortMethod {
|
|||||||
SMD_BY_SIZE_ASC,
|
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<FrameBuffer> frame) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool recvMsg_{};
|
|
||||||
InfoMsg infoMsg_{};
|
|
||||||
QString sendStrType_{};
|
|
||||||
QString ansStrType_{};
|
|
||||||
QString stra_;
|
|
||||||
QString strb_;
|
|
||||||
QString type_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FileManager : public QWidget
|
class FileManager : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
107
Note/version.md
107
Note/version.md
@@ -6,56 +6,57 @@
|
|||||||
|
|
||||||
## 问题清单:
|
## 问题清单:
|
||||||
|
|
||||||
| 序号 | 类型 | 内容 | 说明 | 基于版本 | 完成版本 |
|
| 序号 | 类型 | 内容 | 说明 | 基于版本 | 完成版本 |
|
||||||
| :--: | :--: | ------------------------------------------------------------ | :----: | :------: | :------: |
|
| :--: | :--: | ------------------------------------------------------------ | :------------: | :------: | :------: |
|
||||||
| 51 | 问题 | 按照类型传输时,类型重复的问题修正 | | 0.2.5 | 0.2.6 |
|
| 52 | 问题 | 发送大文件时,UI有不流畅现象。 | 完成版本待观察 | 0.2.6 | |
|
||||||
| 50 | 功能 | 添加日志内容清空按钮。 | | 0.2.4 | 0.2.5 |
|
| 51 | 问题 | 按照类型传输时,类型重复的问题修正 | | 0.2.5 | 0.2.6 |
|
||||||
| 49 | 功能 | 对照传输支持按照类型传输。 | | 0.2.4 | 0.2.5 |
|
| 50 | 功能 | 添加日志内容清空按钮。 | | 0.2.4 | 0.2.5 |
|
||||||
| 48 | 优化 | 选择上传下载移动到右键菜单中。 | | 0.2.4 | 0.2.5 |
|
| 49 | 功能 | 对照传输支持按照类型传输。 | | 0.2.4 | 0.2.5 |
|
||||||
| 47 | 优化 | 删除新建文件(夹)成功时不提示。 | | 0.2.4 | 0.2.5 |
|
| 48 | 优化 | 选择上传下载移动到右键菜单中。 | | 0.2.4 | 0.2.5 |
|
||||||
| 46 | 功能 | 需要一个压缩传输功能。 | | 0.2.4 | |
|
| 47 | 优化 | 删除新建文件(夹)成功时不提示。 | | 0.2.4 | 0.2.5 |
|
||||||
| 45 | 问题 | 出现过重连后无法刷新客户端列表问题。 | 偶发 | 0.2.4 | |
|
| 46 | 功能 | 需要一个压缩传输功能。 | | 0.2.4 | |
|
||||||
| 44 | 问题 | 出现过多选下载显示远程文件不存在问题,但是单个下没问题。 | 偶发 | 0.2.4 | |
|
| 45 | 问题 | 出现过重连后无法刷新客户端列表问题。 | 偶发 | 0.2.4 | |
|
||||||
| 43 | 问题 | 资源占用过多问题。 | | 0.2.3 | 0.2.4 |
|
| 44 | 问题 | 出现过多选下载显示远程文件不存在问题,但是单个下没问题。 | 偶发 | 0.2.4 | |
|
||||||
| 42 | 优化 | 访问文件过多时,界面有卡顿情况。 | | 0.2.3 | 0.2.4 |
|
| 43 | 问题 | 资源占用过多问题。 | | 0.2.3 | 0.2.4 |
|
||||||
| 41 | 问题 | 主动中断检查等待后,软件崩溃。 | | 0.2.3 | 0.2.4 |
|
| 42 | 优化 | 访问文件过多时,界面有卡顿情况。 | | 0.2.3 | 0.2.4 |
|
||||||
| 40 | 问题 | 上传方完成后,接收端未接收完毕不能退出的问题。 | | 0.2.3 | 0.2.4 |
|
| 41 | 问题 | 主动中断检查等待后,软件崩溃。 | | 0.2.3 | 0.2.4 |
|
||||||
| 39 | 优化 | Console端断联后应当自动退出。 | | 0.2.3 | 0.2.4 |
|
| 40 | 问题 | 上传方完成后,接收端未接收完毕不能退出的问题。 | | 0.2.3 | 0.2.4 |
|
||||||
| 38 | 功能 | PE中使用没有拖拽功能,文件管理器要有下载/上传按钮。 | | 0.2.3 | 0.2.4 |
|
| 39 | 优化 | Console端断联后应当自动退出。 | | 0.2.3 | 0.2.4 |
|
||||||
| 37 | 问题 | 未连接对方客户端时,执行对照传输会崩溃。 | 待复现 | 0.2.3 | |
|
| 38 | 功能 | PE中使用没有拖拽功能,文件管理器要有下载/上传按钮。 | | 0.2.3 | 0.2.4 |
|
||||||
| 36 | 功能 | 备份文件功能。 | | 0.2.3 | |
|
| 37 | 问题 | 未连接对方客户端时,执行对照传输会崩溃。 | 待复现 | 0.2.3 | |
|
||||||
| 35 | 功能 | 完善对照功能的界面其他内容。 | | 0.2.3 | |
|
| 36 | 功能 | 备份文件功能。 | | 0.2.3 | |
|
||||||
| 34 | 功能 | 支持删除、重命名、新建文件(夹)。 | | 0.2.3 | 0.2.4 |
|
| 35 | 功能 | 完善对照功能的界面其他内容。 | | 0.2.3 | |
|
||||||
| 33 | 功能 | 弹窗查看文件(夹)属性窗口。 | | 0.2.3 | 0.2.4 |
|
| 34 | 功能 | 支持删除、重命名、新建文件(夹)。 | | 0.2.3 | 0.2.4 |
|
||||||
| 32 | 功能 | 路径选择显示驱动器。 | | 0.2.2 | 0.2.3 |
|
| 33 | 功能 | 弹窗查看文件(夹)属性窗口。 | | 0.2.3 | 0.2.4 |
|
||||||
| 31 | 功能 | Server端buffer大小判断,有过多无效数据则踢出该客户端。 | | 0.2.2 | 0.2.4 |
|
| 32 | 功能 | 路径选择显示驱动器。 | | 0.2.2 | 0.2.3 |
|
||||||
| 30 | 功能 | 传输界面的取消退出,缺失功能处理。 | | 0.2.2 | 0.2.3 |
|
| 31 | 功能 | Server端buffer大小判断,有过多无效数据则踢出该客户端。 | | 0.2.2 | 0.2.4 |
|
||||||
| 29 | 功能 | 根据接收端的速率限制发送端的速度。 | | 0.2.2 | 0.2.3 |
|
| 30 | 功能 | 传输界面的取消退出,缺失功能处理。 | | 0.2.2 | 0.2.3 |
|
||||||
| 28 | 变更 | 语言简体中文。 | | 0.2.2 | 0.2.3 |
|
| 29 | 功能 | 根据接收端的速率限制发送端的速度。 | | 0.2.2 | 0.2.3 |
|
||||||
| 27 | 功能 | 传输前检查对方或者自己是否已存在某些文件,提示是否覆盖。 | | 0.2.2 | 0.2.3 |
|
| 28 | 变更 | 语言简体中文。 | | 0.2.2 | 0.2.3 |
|
||||||
| 26 | 功能 | 最好能保存关闭界面时Splitter和UI的尺寸。 | | 0.2.2 | |
|
| 27 | 功能 | 传输前检查对方或者自己是否已存在某些文件,提示是否覆盖。 | | 0.2.2 | 0.2.3 |
|
||||||
| 25 | 功能 | 手动输入的文件夹访问路径保存历史记录,以便后续可能再次使用(10条)。 | | 0.2.2 | |
|
| 26 | 功能 | 最好能保存关闭界面时Splitter和UI的尺寸。 | | 0.2.2 | |
|
||||||
| 24 | 问题 | 发送端如果发送的数据比较大,UI会卡住(功能是正常的)。 | | 0.2.2 | 0.2.3 |
|
| 25 | 功能 | 手动输入的文件夹访问路径保存历史记录,以便后续可能再次使用(10条)。 | | 0.2.2 | |
|
||||||
| 23 | 问题 | 作为接收端如果对方断联要处理这个情况。 | | 0.2.2 | 0.2.3 |
|
| 24 | 问题 | 发送端如果发送的数据比较大,UI会卡住(功能是正常的)。 | | 0.2.2 | 0.2.3 |
|
||||||
| 22 | 功能 | 配置可以切组。 | | 0.2.2 | |
|
| 23 | 问题 | 作为接收端如果对方断联要处理这个情况。 | | 0.2.2 | 0.2.3 |
|
||||||
| 21 | 功能 | 可以传输文件夹。 | | 0.2.2 | |
|
| 22 | 功能 | 配置可以切组。 | | 0.2.2 | |
|
||||||
| 20 | 功能 | 对照传输可以打开本地文件夹。 | | 0.2.2 | 0.2.3 |
|
| 21 | 功能 | 可以传输文件夹。 | | 0.2.2 | |
|
||||||
| 19 | 问题 | 客户之间心跳包,被动/主动失联后断开,清除相关内容,终止相关任务。 | | 0.2.2 | 0.2.3 |
|
| 20 | 功能 | 对照传输可以打开本地文件夹。 | | 0.2.2 | 0.2.3 |
|
||||||
| 18 | 问题 | 断开后重连貌似没有发送心跳包。 | | 0.1 | 0.2 |
|
| 19 | 问题 | 客户之间心跳包,被动/主动失联后断开,清除相关内容,终止相关任务。 | | 0.2.2 | 0.2.3 |
|
||||||
| 17 | 问题 | 服务端主动踢出的客户端,主动重连假链接,不可用无反应。 | | 0.1 | 0.2 |
|
| 18 | 问题 | 断开后重连貌似没有发送心跳包。 | | 0.1 | 0.2 |
|
||||||
| 16 | 优化 | 传输完成后接收端要刷新一次。 | | 0.1 | |
|
| 17 | 问题 | 服务端主动踢出的客户端,主动重连假链接,不可用无反应。 | | 0.1 | 0.2 |
|
||||||
| 15 | 问题 | 拖动文件夹到对方,应当不处理,并日志提示。 | | 0.1 | 0.2 |
|
| 16 | 优化 | 传输完成后接收端要刷新一次。 | | 0.1 | |
|
||||||
| 14 | 功能 | 文件浏览部分添加右键复制全路径功能。 | | 0.1 | 0.2 |
|
| 15 | 问题 | 拖动文件夹到对方,应当不处理,并日志提示。 | | 0.1 | 0.2 |
|
||||||
| 13 | 功能 | IP端口部分要添加可选择历史。 | | 0.1 | 0.2 |
|
| 14 | 功能 | 文件浏览部分添加右键复制全路径功能。 | | 0.1 | 0.2 |
|
||||||
| 12 | 功能 | 对照传输前要先校验文件存在性。 | | 0.1 | 0.2.3 |
|
| 13 | 功能 | IP端口部分要添加可选择历史。 | | 0.1 | 0.2 |
|
||||||
| 11 | 问题 | 断连后当前远端ID要清除。 | | 0.1 | 0.2 |
|
| 12 | 功能 | 对照传输前要先校验文件存在性。 | | 0.1 | 0.2.3 |
|
||||||
| 10 | 功能 | 对照传输可以支持反向下载。 | | 0.1 | 0.2 |
|
| 11 | 问题 | 断连后当前远端ID要清除。 | | 0.1 | 0.2 |
|
||||||
| 9 | 优化 | 输入路径后可以直接回车访问。 | | 0.1 | 0.2 |
|
| 10 | 功能 | 对照传输可以支持反向下载。 | | 0.1 | 0.2 |
|
||||||
| 8 | 功能 | 文件浏览页面要支持按照类型排序,时间排序,和文件后缀筛选。 | | 0.1 | 0.2 |
|
| 9 | 优化 | 输入路径后可以直接回车访问。 | | 0.1 | 0.2 |
|
||||||
| 7 | 优化 | IP和Port宽度要合理一些,IP过小,Port宽度过大。 | | 0.1 | 0.2 |
|
| 8 | 功能 | 文件浏览页面要支持按照类型排序,时间排序,和文件后缀筛选。 | | 0.1 | 0.2 |
|
||||||
| 6 | 功能 | 比对控件添加可尝试目录浏览控件跳转到指定目录。 | | 0.1 | 0.2 |
|
| 7 | 优化 | IP和Port宽度要合理一些,IP过小,Port宽度过大。 | | 0.1 | 0.2 |
|
||||||
| 5 | 问题 | 未设置心跳包,导致超时被Server端踢出。 | 必改 | 0.1 | 0.2 |
|
| 6 | 功能 | 比对控件添加可尝试目录浏览控件跳转到指定目录。 | | 0.1 | 0.2 |
|
||||||
| 4 | 问题 | 重复链接Server会崩溃。 | | 0.1 | 0.2 |
|
| 5 | 问题 | 未设置心跳包,导致超时被Server端踢出。 | 必改 | 0.1 | 0.2 |
|
||||||
| 3 | 优化 | 首次启动时应当按照当前分辨率进行初始化大小,而不是指定大小。 | | 0.1 | 0.2 |
|
| 4 | 问题 | 重复链接Server会崩溃。 | | 0.1 | 0.2 |
|
||||||
| 2 | 问题 | 当某个文件传输失败的时候,关闭传输窗口,再次传输显示已经在传输中。 | | 0.1 | 0.2.3 |
|
| 3 | 优化 | 首次启动时应当按照当前分辨率进行初始化大小,而不是指定大小。 | | 0.1 | 0.2 |
|
||||||
| 1 | 问题 | Console端显示未注册QSharedPointer\<FrameBuffer\>类型 | | 0.1 | 0.2 |
|
| 2 | 问题 | 当某个文件传输失败的时候,关闭传输窗口,再次传输显示已经在传输中。 | | 0.1 | 0.2.3 |
|
||||||
|
| 1 | 问题 | Console端显示未注册QSharedPointer\<FrameBuffer\>类型 | | 0.1 | 0.2 |
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ enum FileCheckState {
|
|||||||
#define STRMSG_AC_UP "upAction"
|
#define STRMSG_AC_UP "upAction"
|
||||||
#define STRMSG_AC_DOWN "downAction"
|
#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_FILEEXIT "fileExist"
|
||||||
#define STRMSG_ST_FILENOEXIT "fileNotExist"
|
#define STRMSG_ST_FILENOEXIT "fileNotExist"
|
||||||
#define STRMSG_ST_DIREXIT "dirExist"
|
#define STRMSG_ST_DIREXIT "dirExist"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <Util.h>
|
||||||
|
|
||||||
void DateTimeTest()
|
void DateTimeTest()
|
||||||
{
|
{
|
||||||
@@ -14,5 +15,8 @@ int main(int argc, char** argv)
|
|||||||
qDebug() << "Running...";
|
qDebug() << "Running...";
|
||||||
DateTimeTest();
|
DateTimeTest();
|
||||||
|
|
||||||
|
QVector<QString> files;
|
||||||
|
DirFileHelper::GetAllFiles("D:/备份软件", files);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
@@ -21,4 +21,4 @@ add_executable(frelayTest ${MSOURCES})
|
|||||||
target_link_libraries(frelayTest PRIVATE Protocol Util)
|
target_link_libraries(frelayTest PRIVATE Protocol Util)
|
||||||
|
|
||||||
add_executable(frelayBaseTest BaseTest.cpp)
|
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)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QFileDevice>
|
#include <QFileDevice>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
@@ -190,6 +191,33 @@ QString DirFileHelper::GetErr() const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DirFileHelper::GetAllFiles(const QString& rootPath, QVector<QString>& 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)
|
DirFileHelper::DirFileHelper(QObject* parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QString GetErr() const;
|
QString GetErr() const;
|
||||||
|
static bool GetAllFiles(const QString& rootPath, QVector<QString>& files);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigHome(const QString& path, const QVector<QString>& drivers);
|
void sigHome(const QString& path, const QVector<QString>& drivers);
|
||||||
|
|||||||
Reference in New Issue
Block a user