Files
frelay/Gui/Control/FileControl.cpp

905 lines
28 KiB
C++
Raw Normal View History

2025-06-17 17:20:54 +08:00
#include "FileControl.h"
2025-06-15 14:31:54 +08:00
#include <LocalFile.h>
2025-06-29 00:13:35 +08:00
#include <QClipboard>
2025-06-15 14:31:54 +08:00
#include <QDateTime>
2025-06-28 23:48:15 +08:00
#include <QDialog>
2025-06-15 14:31:54 +08:00
#include <QDir>
#include <QFile>
#include <QHeaderView>
2025-11-16 19:23:59 +08:00
#include <QInputDialog>
2025-06-28 23:57:46 +08:00
#include <QLineEdit>
2025-06-28 23:48:15 +08:00
#include <QListWidget>
#include <QMessageBox>
#include <QScrollBar>
2025-06-15 14:31:54 +08:00
#include <QTableWidgetItem>
#include <RemoteFile.h>
#include "Form/FileInfoForm.h"
2025-11-16 19:23:59 +08:00
#include "Form/Loading.h"
2025-06-29 00:13:35 +08:00
#include "GuiUtil/Public.h"
2025-06-15 14:31:54 +08:00
#include "ui_FileControl.h"
FileManager::FileManager(QWidget* parent) : QWidget(parent), ui(new Ui::FileManager)
{
ui->setupUi(this);
InitControl();
2025-06-28 23:48:15 +08:00
InitMenu();
2025-06-15 14:31:54 +08:00
}
FileManager::~FileManager()
{
delete ui;
}
void FileManager::SetModeStr(const QString& modeStr, int type, ClientCore* clientCore)
{
2025-06-20 09:45:39 +08:00
cliCore_ = clientCore;
2025-06-15 14:31:54 +08:00
ui->lbMode->setText(modeStr);
if (type == 0) {
2025-06-20 16:00:18 +08:00
isRemote_ = false;
2025-06-15 14:31:54 +08:00
fileHelper_ = std::make_shared<LocalFile>();
} else {
auto remotePtr = std::make_shared<RemoteFile>();
remotePtr->setClientCore(clientCore);
2025-06-20 16:00:18 +08:00
isRemote_ = true;
2025-06-18 14:53:56 +08:00
ui->tableWidget->setIsRemote(true);
2025-06-15 14:31:54 +08:00
fileHelper_ = remotePtr;
2025-10-20 16:40:52 +08:00
connect(cliCore_, &ClientCore::sigDisconnect, this, [this]() { ui->tableWidget->setRowCount(0); });
connect(cliCore_, &ClientCore::sigOffline, this, [this]() { ui->tableWidget->setRowCount(0); });
2025-06-15 14:31:54 +08:00
}
2025-06-20 09:45:39 +08:00
ui->tableWidget->setOwnIDCall([this]() { return cliCore_->GetOwnID(); });
ui->tableWidget->setRemoteIDCall([this]() { return cliCore_->GetRemoteID(); });
connect(fileHelper_.get(), &DirFileHelper::sigHome, this, &FileManager::ShowPath);
connect(fileHelper_.get(), &DirFileHelper::sigDirFile, this, &FileManager::ShowFile);
if (type == 0) {
evtHome();
evtFile();
}
if (isRemote_) {
menu_->addAction(tr("下载"), this, &FileManager::UpDown);
} else {
menu_->addAction(tr("上传"), this, &FileManager::UpDown);
}
2025-06-18 14:53:56 +08:00
}
2025-06-15 14:31:54 +08:00
void FileManager::InitControl()
{
QStringList headers;
2025-11-04 14:52:27 +08:00
headers << tr("") << tr("文件名称") << tr("最后修改时间") << tr("类型") << tr("大小");
2025-06-15 14:31:54 +08:00
ui->tableWidget->setColumnCount(headers.size());
ui->tableWidget->setHorizontalHeaderLabels(headers);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->comboBox->setEditable(true);
// ui->tableWidget->setColumnWidth(0, 50);
ui->tableWidget->setColumnWidth(1, 300);
ui->tableWidget->setColumnWidth(2, 170);
2025-06-15 14:31:54 +08:00
ui->tableWidget->setColumnWidth(3, 70);
ui->tableWidget->setColumnWidth(4, 90);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
// ui->tableWidget->setStyleSheet("QTableWidget::item:hover { background-color: transparent; }");
2025-06-17 17:20:54 +08:00
ui->tableWidget->setDragEnabled(true);
ui->tableWidget->viewport()->setAcceptDrops(true);
ui->tableWidget->setDropIndicatorShown(true);
ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
2025-06-18 17:22:15 +08:00
ui->tableWidget->setDragDropMode(QAbstractItemView::DragDrop);
2025-06-17 17:20:54 +08:00
2025-06-28 23:48:15 +08:00
ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
2025-06-15 14:31:54 +08:00
connect(ui->btnHome, &QPushButton::clicked, this, &FileManager::evtHome);
connect(ui->btnVisit, &QPushButton::clicked, this, &FileManager::evtFile);
connect(ui->tableWidget, &QTableWidget::cellDoubleClicked, this, &FileManager::doubleClick);
connect(ui->btnUp, &QPushButton::clicked, this, &FileManager::evtUp);
connect(ui->tableWidget, &CustomTableWidget::sigTasks, this,
[this](const QVector<TransTask>& tasks) { emit sigSendTasks(tasks); });
2025-06-28 22:53:42 +08:00
2025-06-28 23:48:15 +08:00
connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this,
[this](const QPoint& pos) { menu_->exec(QCursor::pos()); });
2025-06-28 22:53:42 +08:00
connect(ui->tableWidget->horizontalHeader(), &QHeaderView::sectionClicked, this, &FileManager::HeaderClicked);
2025-10-21 10:12:21 +08:00
auto* line = ui->comboBox->lineEdit();
connect(line, &QLineEdit::returnPressed, this, [this]() { ui->btnVisit->click(); });
connect(ui->tableWidget->verticalScrollBar(), &QScrollBar::actionTriggered, this, [this]() { userScrol_ = true; });
2025-06-15 14:31:54 +08:00
}
2025-06-28 23:48:15 +08:00
void FileManager::InitMenu()
2025-06-17 17:20:54 +08:00
{
2025-06-28 23:48:15 +08:00
menu_ = new QMenu(ui->tableWidget);
2025-11-04 15:18:28 +08:00
menu_->addAction(tr("过滤器"), this, &FileManager::ShowFilterForm);
menu_->addAction(tr("复制文件路径"), this, &FileManager::CopyFullPath);
2025-11-11 22:57:38 +08:00
menu_->addAction(tr("属性"), this, &FileManager::ShowProperties);
menu_->addAction(tr("重命名"), this, &FileManager::OperRename);
menu_->addAction(tr("删除"), this, &FileManager::OperDelete);
menu_->addAction(tr("新建文件夹"), this, &FileManager::OperNewFolder);
2025-06-28 23:48:15 +08:00
menu_->addSeparator();
2025-06-17 17:20:54 +08:00
}
2025-11-11 08:52:09 +08:00
void FileManager::ShowPath(const QString& path, const QVector<QString>& drivers)
2025-06-15 14:31:54 +08:00
{
QMutexLocker locker(&cbMut_);
2025-11-09 18:10:54 +08:00
2025-06-15 14:31:54 +08:00
int existingIndex = ui->comboBox->findText(path);
if (existingIndex != -1) {
ui->comboBox->removeItem(existingIndex);
} else if (ui->comboBox->count() >= 20) {
ui->comboBox->removeItem(ui->comboBox->count() - 1);
}
2025-11-09 18:10:54 +08:00
for (const auto& driver : drivers) {
if (ui->comboBox->findText(driver) == -1) {
ui->comboBox->insertItem(0, driver);
}
}
if (ui->comboBox->findText(path) == -1) {
ui->comboBox->insertItem(0, path);
}
2025-06-15 14:31:54 +08:00
ui->comboBox->setCurrentIndex(0);
2025-11-09 18:10:54 +08:00
drivers_ = drivers;
2025-06-15 14:31:54 +08:00
}
void FileManager::ShowFile(const DirFileInfoVec& info)
{
QMutexLocker locker(&tbMut_);
2025-06-28 22:53:42 +08:00
currentInfo_ = info;
SortFileInfo(SortMethod::SMD_BY_TYPE_DESC);
2025-06-28 23:48:15 +08:00
GenFilter();
curSelectTypes_.clear();
currentShowInfo_ = currentInfo_;
2025-06-28 22:53:42 +08:00
RefreshTab();
ui->tableWidget->resizeColumnToContents(0);
SetRoot(currentInfo_.root);
2025-11-09 18:10:54 +08:00
ShowPath(GetRoot(), drivers_);
2025-06-28 22:53:42 +08:00
}
void FileManager::SetRoot(const QString& path)
{
if (isRemote_) {
GlobalData::Ins()->SetRemoteRoot(path);
} else {
GlobalData::Ins()->SetLocalRoot(path);
}
}
void FileManager::SortFileInfo(SortMethod method)
{
auto& vec = currentInfo_.vec;
switch (method) {
case SortMethod::SMD_BY_NAME_ASC:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
return QString::compare(a.name, b.name, Qt::CaseInsensitive) < 0;
});
break;
case SortMethod::SMD_BY_NAME_DESC:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
return QString::compare(a.name, b.name, Qt::CaseInsensitive) > 0;
});
break;
case SortMethod::SMD_BY_TIME_ASC:
std::sort(vec.begin(), vec.end(),
[](const DirFileInfo& a, const DirFileInfo& b) { return a.lastModified < b.lastModified; });
break;
case SortMethod::SMD_BY_TIME_DESC:
std::sort(vec.begin(), vec.end(),
[](const DirFileInfo& a, const DirFileInfo& b) { return a.lastModified > b.lastModified; });
break;
2025-06-15 14:31:54 +08:00
2025-06-28 22:53:42 +08:00
case SortMethod::SMD_BY_TYPE_ASC:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
if (a.type == b.type) {
return QString::compare(a.name, b.name, Qt::CaseInsensitive) < 0;
}
return a.type < b.type;
});
break;
case SortMethod::SMD_BY_TYPE_DESC:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
if (a.type == b.type) {
return QString::compare(a.name, b.name, Qt::CaseInsensitive) < 0;
}
return a.type > b.type;
});
break;
case SortMethod::SMD_BY_SIZE_ASC:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
if (a.type == b.type) {
return a.size < b.size;
}
return a.type == FileType::Dir && b.type != FileType::Dir;
});
break;
case SortMethod::SMD_BY_SIZE_DESC:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
if (a.type == b.type) {
return a.size > b.size;
}
return a.type == FileType::Dir && b.type != FileType::Dir;
});
break;
default:
std::sort(vec.begin(), vec.end(), [](const DirFileInfo& a, const DirFileInfo& b) {
return QString::compare(a.name, b.name, Qt::CaseInsensitive) < 0;
});
break;
}
}
2025-11-16 20:51:56 +08:00
void FileManager::ShowFileItem(const DirFileInfo& f, int i)
{
2025-11-16 23:30:42 +08:00
static QIcon dirIcon = QApplication::style()->standardIcon(QStyle::SP_DirIcon);
static QIcon fileIcon = QApplication::style()->standardIcon(QStyle::SP_FileIcon);
2025-11-16 20:51:56 +08:00
// ***********************************************************************************
auto* iconItem = new QTableWidgetItem("");
iconItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
iconItem->setFlags(iconItem->flags() & ~Qt::ItemIsEditable);
ui->tableWidget->setItem(i, 0, iconItem);
// ***********************************************************************************
auto* fileItem = new QTableWidgetItem(f.name);
fileItem->setFlags(fileItem->flags() & ~Qt::ItemIsEditable);
ui->tableWidget->setItem(i, 1, fileItem);
QDateTime modifyTime = QDateTime::fromMSecsSinceEpoch(f.lastModified);
// ***********************************************************************************
QString timeStr = modifyTime.toString("yyyy-MM-dd hh:mm:ss");
auto* timeItem = new QTableWidgetItem(timeStr);
timeItem->setFlags(timeItem->flags() & ~Qt::ItemIsEditable);
ui->tableWidget->setItem(i, 2, timeItem);
// ***********************************************************************************
QString typeStr;
switch (f.type) {
case File:
typeStr = "File";
2025-11-16 23:30:42 +08:00
iconItem->setIcon(fileIcon);
2025-11-16 20:51:56 +08:00
break;
case Dir:
typeStr = "Dir";
2025-11-16 23:30:42 +08:00
iconItem->setIcon(dirIcon);
2025-11-16 20:51:56 +08:00
break;
case Link:
typeStr = "Link";
break;
case Other:
typeStr = "Other";
break;
default:
typeStr = "Unknown";
break;
}
// ***********************************************************************************
auto* typeItem = new QTableWidgetItem(typeStr);
typeItem->setFlags(typeItem->flags() & ~Qt::ItemIsEditable);
ui->tableWidget->setItem(i, 3, typeItem);
// ***********************************************************************************
QString sizeStr;
if (f.size < 1024) {
sizeStr = QString::number(f.size) + " B";
} else if (f.size < 1024 * 1024) {
sizeStr = QString::number(f.size / 1024.0, 'f', 2) + " KB";
} else {
sizeStr = QString::number(f.size / (1024.0 * 1024.0), 'f', 2) + " MB";
}
QTableWidgetItem* item = nullptr;
if (f.type == File) {
item = new QTableWidgetItem(sizeStr);
} else {
item = new QTableWidgetItem("");
}
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
ui->tableWidget->setItem(i, 4, item);
}
2025-06-28 22:53:42 +08:00
void FileManager::RefreshTab()
{
userScrol_ = false;
ui->tableWidget->clearContents();
2025-06-28 22:53:42 +08:00
ui->tableWidget->setRowCount(0);
2025-06-28 23:48:15 +08:00
for (int i = 0; i < currentShowInfo_.vec.size(); ++i) {
ui->tableWidget->insertRow(ui->tableWidget->rowCount());
2025-06-28 23:48:15 +08:00
const DirFileInfo& fileInfo = currentShowInfo_.vec[i];
2025-11-16 20:51:56 +08:00
ShowFileItem(fileInfo, i);
2025-11-16 23:30:42 +08:00
if (i != 0 && i % 30 == 0) {
QGuiApplication::processEvents();
}
}
if (!userScrol_) {
ui->tableWidget->scrollToTop();
2025-06-15 14:31:54 +08:00
}
2025-06-20 16:00:18 +08:00
}
2025-06-28 22:53:42 +08:00
void FileManager::HeaderClicked(int column)
2025-06-20 16:00:18 +08:00
{
2025-06-28 22:53:42 +08:00
SortMethod curMed{};
switch (column) {
case 1:
if (sortMedRecord_.count(column)) {
curMed = sortMedRecord_[column];
}
curMed = (curMed == SortMethod::SMD_BY_NAME_ASC ? SortMethod::SMD_BY_NAME_DESC : SortMethod::SMD_BY_NAME_ASC);
SortFileInfo(curMed);
sortMedRecord_[column] = curMed;
break;
case 2:
if (sortMedRecord_.count(column)) {
curMed = sortMedRecord_[column];
}
curMed = (curMed == SortMethod::SMD_BY_TIME_ASC ? SortMethod::SMD_BY_TIME_DESC : SortMethod::SMD_BY_TIME_ASC);
SortFileInfo(curMed);
sortMedRecord_[column] = curMed;
break;
case 3:
if (sortMedRecord_.count(column)) {
curMed = sortMedRecord_[column];
}
curMed = (curMed == SortMethod::SMD_BY_TYPE_ASC ? SortMethod::SMD_BY_TYPE_DESC : SortMethod::SMD_BY_TYPE_ASC);
SortFileInfo(curMed);
sortMedRecord_[column] = curMed;
break;
case 4:
if (sortMedRecord_.count(column)) {
curMed = sortMedRecord_[column];
}
curMed = (curMed == SortMethod::SMD_BY_SIZE_ASC ? SortMethod::SMD_BY_SIZE_DESC : SortMethod::SMD_BY_SIZE_ASC);
SortFileInfo(curMed);
sortMedRecord_[column] = curMed;
break;
default:
return;
2025-06-20 16:00:18 +08:00
}
2025-06-28 22:53:42 +08:00
QMetaObject::invokeMethod(this, "RefreshTab", Qt::QueuedConnection);
2025-06-20 16:00:18 +08:00
}
2025-06-30 01:05:28 +08:00
void FileManager::SetUiCurrentPath(const QString& path)
{
if (path.isEmpty()) {
return;
}
ui->comboBox->addItem(path);
ui->comboBox->setCurrentText(path);
}
2025-11-11 08:52:09 +08:00
void FileManager::FilterFile(const QVector<QString>& selectedTypes)
2025-06-28 23:48:15 +08:00
{
if (selectedTypes.contains("*")) {
currentShowInfo_.vec = currentInfo_.vec;
QMetaObject::invokeMethod(this, "RefreshTab", Qt::QueuedConnection);
return;
}
currentShowInfo_.vec.clear();
for (const auto& d : currentInfo_.vec) {
if (d.type == File) {
auto ext = d.fullPath.lastIndexOf('.');
if (ext != -1) {
QString extStr = d.fullPath.mid(ext + 1).toLower();
if (selectedTypes.contains(extStr)) {
currentShowInfo_.vec.push_back(d);
}
}
}
}
QMetaObject::invokeMethod(this, "RefreshTab", Qt::QueuedConnection);
}
void FileManager::GenFilter()
{
fileTypes_.clear();
for (const auto& fileInfo : currentInfo_.vec) {
if (fileInfo.type == File) {
auto ext = fileInfo.fullPath.lastIndexOf('.');
if (ext != -1) {
QString extStr = fileInfo.fullPath.mid(ext + 1).toLower();
fileTypes_.insert(extStr);
}
}
}
}
void FileManager::ShowFilterForm()
{
QDialog dialog(this);
2025-11-04 15:18:28 +08:00
dialog.setWindowTitle("筛选文件类型");
2025-06-28 23:48:15 +08:00
dialog.resize(400, 300);
QListWidget listWidget(&dialog);
listWidget.setSelectionMode(QAbstractItemView::NoSelection);
QListWidgetItem* allItem = new QListWidgetItem("*(ALL)");
allItem->setData(Qt::UserRole, "*");
allItem->setCheckState(curSelectTypes_.contains("*") ? Qt::Checked : Qt::Unchecked);
listWidget.addItem(allItem);
for (const QString& ext : fileTypes_) {
QListWidgetItem* item = new QListWidgetItem(ext);
item->setData(Qt::UserRole, ext);
item->setCheckState(curSelectTypes_.contains(ext) ? Qt::Checked : Qt::Unchecked);
listWidget.addItem(item);
}
QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dialog);
connect(&buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
connect(&buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
QVBoxLayout layout(&dialog);
layout.addWidget(&listWidget);
layout.addWidget(&buttons);
dialog.setLayout(&layout);
if (dialog.exec() == QDialog::Accepted) {
2025-11-11 08:52:09 +08:00
QVector<QString> selectedTypes;
2025-06-28 23:48:15 +08:00
for (int i = 0; i < listWidget.count(); ++i) {
QListWidgetItem* item = listWidget.item(i);
if (item->checkState() == Qt::Checked) {
selectedTypes << item->data(Qt::UserRole).toString();
}
}
FilterFile(selectedTypes);
curSelectTypes_.clear();
for (int i = 0; i < selectedTypes.count(); ++i) {
curSelectTypes_.insert(selectedTypes[i]);
}
}
}
2025-06-29 00:13:35 +08:00
void FileManager::CopyFullPath()
{
int row = ui->tableWidget->currentRow();
if (row < 0) {
return;
}
QClipboard* clip = QApplication::clipboard();
bool found = false;
QString key = ui->tableWidget->item(row, 1)->text();
for (const auto& d : currentInfo_.vec) {
if (d.name == key) {
clip->setText(d.fullPath);
found = true;
return;
}
}
if (!found) {
FTCommon::msg(this, QString(tr("%1 not found.")).arg(key));
}
}
2025-11-11 22:57:38 +08:00
void FileManager::ShowProperties()
{
int row = ui->tableWidget->currentRow();
if (row < 0) {
return;
}
auto* info = new FileInfo(this);
info->baseName_ = ui->tableWidget->item(row, 1)->text();
info->dirName_ = isRemote_ ? GlobalData::Ins()->GetRemoteRoot() : GlobalData::Ins()->GetLocalRoot();
info->fileTime_ = ui->tableWidget->item(row, 2)->text();
info->fileType_ = ui->tableWidget->item(row, 3)->text();
info->fileSize_ = ui->tableWidget->item(row, 4)->text();
info->setWindowTitle(isRemote_ ? tr("远程文件属性") : tr("本地文件属性"));
2025-11-11 22:57:38 +08:00
info->exec();
}
void FileManager::UpDown()
{
auto datas = ui->tableWidget->selectedItems();
if (datas.isEmpty()) {
return;
}
if (datas.size() % 5 != 0) {
QMessageBox::information(this, tr("提示"), tr("请选择完整的行。"));
return;
}
QVector<TransTask> tasks;
for (int i = 0; i < (datas.size() / 5); ++i) {
if (datas[i * 5 + 3]->text() != "File") {
qDebug() << QString(tr("暂不支持传输文件夹:%1")).arg(datas[i * 5 + 3]->text());
continue;
}
/*
DropEvent
DropEvent
*/
TransTask task;
task.taskUUID = Util::UUID();
task.isUpload = !isRemote_;
task.localId = cliCore_->GetOwnID();
task.remoteId = cliCore_->GetRemoteID();
if (isRemote_) {
task.remotePath = Util::Join(GlobalData::Ins()->GetRemoteRoot(), datas[i * 5 + 1]->text());
task.localPath = GlobalData::Ins()->GetLocalRoot();
} else {
task.remotePath = GlobalData::Ins()->GetRemoteRoot();
task.localPath = Util::Join(GlobalData::Ins()->GetLocalRoot(), datas[i * 5 + 1]->text());
}
tasks.push_back(task);
}
if (tasks.isEmpty()) {
return;
}
emit sigSendTasks(tasks);
}
void FileManager::OperNewFolder()
{
2025-11-16 20:51:56 +08:00
QInputDialog dialog(this);
dialog.setWindowTitle("输入");
dialog.setLabelText("要新建的文件夹名称:");
dialog.setOkButtonText("确定");
dialog.setCancelButtonText("取消");
2025-11-16 23:30:42 +08:00
auto size = dialog.minimumSizeHint();
size.setWidth(size.width() + 200);
dialog.setFixedSize(size);
2025-11-16 20:51:56 +08:00
QString text;
if (dialog.exec() == QDialog::Accepted) {
text = dialog.textValue().trimmed();
if (text.isEmpty()) {
return;
}
} else {
return;
}
auto folder = Util::Join(GetRoot(), text);
if (!isRemote_) {
QString ret = Util::NewDir(folder);
if (ret.isEmpty()) {
2026-02-02 21:28:25 +08:00
//QMessageBox::information(this, tr("提示"), tr("创建%1成功").arg(folder));
2025-11-16 20:51:56 +08:00
DirFileInfo nf;
nf.size = 0;
nf.type = Dir;
nf.fullPath = folder;
nf.name = text;
nf.lastModified = QDateTime::currentDateTime().toMSecsSinceEpoch();
ui->tableWidget->insertRow(0);
ShowFileItem(nf, 0);
} else {
QMessageBox::information(this, tr("提示"), ret);
}
return;
}
WaitOper oper(this);
oper.SetClient(cliCore_);
oper.SetType(STRMSG_AC_NEW_DIR, STRMSG_AC_ANSWER_NEW_DIR);
oper.SetPath(folder, "", "");
LoadingDialog checking(this);
checking.setTipsText("正在新建...");
connect(&oper, &WaitOper::sigCheckOver, &checking, &LoadingDialog::cancelBtnClicked);
connect(cliCore_, &ClientCore::sigMsgAnswer, &oper, &WaitOper::recvFrame);
oper.start();
checking.exec();
std::shared_ptr<void> recv(nullptr, [&oper](void*) { oper.wait(); });
if (checking.isUserCancel()) {
oper.interrupCheck();
return;
}
// 检查结果
auto msg = oper.GetMsg();
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
QMessageBox::information(this, tr("提示"), QString(tr("新建失败=>%1")).arg(msg.msg));
} else {
2026-02-02 21:28:25 +08:00
//QMessageBox::information(this, tr("提示"), QString(tr("新建%1成功。")).arg(folder));
2025-11-16 20:51:56 +08:00
DirFileInfo nf;
nf.size = 0;
nf.type = Dir;
nf.fullPath = folder;
nf.name = text;
nf.lastModified = QDateTime::currentDateTime().toMSecsSinceEpoch();
ui->tableWidget->insertRow(0);
ShowFileItem(nf, 0);
}
}
void FileManager::OperDelete()
{
2025-11-16 20:26:08 +08:00
QList<QTableWidgetItem*> datas;
if (!CheckSelect(datas)) {
return;
}
// 确认是否删除
int ret = QMessageBox::question(this, tr("确认删除"), tr("确定要删除%1吗?").arg(datas[1]->text()),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (ret != QMessageBox::Yes) {
return;
}
auto name = Util::Join(GetRoot(), datas[1]->text());
auto type = datas[3]->text();
if (!isRemote_) {
QString ret = Util::Delete(name);
if (ret.isEmpty()) {
2026-02-02 21:28:25 +08:00
//QMessageBox::information(this, tr("提示"), tr("删除成功"));
2025-11-16 20:26:08 +08:00
int row = datas[0]->row();
ui->tableWidget->removeRow(row);
} else {
QMessageBox::information(this, tr("提示"), ret);
}
return;
}
WaitOper oper(this);
oper.SetClient(cliCore_);
oper.SetType(STRMSG_AC_DEL_FILEDIR, STRMSG_AC_ANSWER_DEL_FILEDIR);
oper.SetPath(name, "", "");
LoadingDialog checking(this);
checking.setTipsText("正在删除...");
connect(&oper, &WaitOper::sigCheckOver, &checking, &LoadingDialog::cancelBtnClicked);
connect(cliCore_, &ClientCore::sigMsgAnswer, &oper, &WaitOper::recvFrame);
oper.start();
checking.exec();
std::shared_ptr<void> recv(nullptr, [&oper](void*) { oper.wait(); });
if (checking.isUserCancel()) {
oper.interrupCheck();
return;
}
// 检查结果
auto msg = oper.GetMsg();
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
QMessageBox::information(this, tr("提示"), QString(tr("删除失败=>%1")).arg(msg.msg));
} else {
2026-02-02 21:28:25 +08:00
//QMessageBox::information(this, tr("提示"), QString(tr("删除成功。")));
2025-11-16 20:26:08 +08:00
ui->tableWidget->removeRow(datas[0]->row());
}
}
2025-11-16 20:26:08 +08:00
bool FileManager::CheckSelect(QList<QTableWidgetItem*>& ret)
{
2025-11-16 20:26:08 +08:00
ret = ui->tableWidget->selectedItems();
if (ret.isEmpty()) {
QMessageBox::information(this, tr("提示"), tr("请选择一项。"));
return false;
2025-11-16 19:23:59 +08:00
}
2025-11-16 20:26:08 +08:00
if (ret.size() % 5 != 0) {
QMessageBox::information(this, tr("提示"), tr("请选择单行。"));
return false;
}
return true;
}
void FileManager::OperRename()
{
QList<QTableWidgetItem*> datas;
if (!CheckSelect(datas)) {
2025-11-16 19:23:59 +08:00
return;
}
2025-11-16 20:26:08 +08:00
2025-11-16 19:23:59 +08:00
auto curName = datas[1]->text();
auto curType = datas[3]->text();
2025-11-16 19:23:59 +08:00
QInputDialog dialog(this);
dialog.setWindowTitle("输入");
dialog.setLabelText("请输入新名称:");
dialog.setOkButtonText("确定");
dialog.setCancelButtonText("取消");
2025-11-16 23:30:42 +08:00
auto size = dialog.minimumSizeHint();
size.setWidth(size.width() + 200);
dialog.setFixedSize(size);
dialog.setTextValue(curName);
2025-11-16 19:23:59 +08:00
QString text;
if (dialog.exec() == QDialog::Accepted) {
text = dialog.textValue().trimmed();
if (text.isEmpty()) {
return;
}
2025-11-16 20:51:56 +08:00
} else {
2025-11-16 20:26:08 +08:00
return;
}
2025-11-16 19:23:59 +08:00
QString oldName = Util::Join(GetRoot(), curName);
QString newName = Util::Join(GetRoot(), text);
if (!isRemote_) {
QString ret = Util::Rename(oldName, newName, curType == STR_DIR);
if (!ret.isEmpty()) {
QMessageBox::information(this, tr("提示"), ret);
} else {
datas[1]->setText(text);
}
return;
}
WaitOper oper(this);
oper.SetClient(cliCore_);
oper.SetType(STRMSG_AC_RENAME_FILEDIR, STRMSG_AC_ANSWER_RENAME_FILEDIR);
oper.SetPath(oldName, newName, curType);
LoadingDialog checking(this);
checking.setTipsText("正在重命名...");
connect(&oper, &WaitOper::sigCheckOver, &checking, &LoadingDialog::cancelBtnClicked);
connect(cliCore_, &ClientCore::sigMsgAnswer, &oper, &WaitOper::recvFrame);
oper.start();
checking.exec();
std::shared_ptr<void> recv(nullptr, [&oper](void*) { oper.wait(); });
if (checking.isUserCancel()) {
oper.interrupCheck();
return;
}
// 检查结果
auto msg = oper.GetMsg();
if (msg.msg == STR_NONE || !msg.msg.isEmpty()) {
QMessageBox::information(this, tr("提示"), QString(tr("重命名失败=>%1")).arg(msg.msg));
} else {
2025-11-16 20:26:08 +08:00
datas[1]->setText(text);
2025-11-16 19:23:59 +08:00
}
}
2025-06-20 16:00:18 +08:00
QString FileManager::GetRoot()
{
if (isRemote_) {
return GlobalData::Ins()->GetRemoteRoot();
} else {
return GlobalData::Ins()->GetLocalRoot();
}
2025-06-15 14:31:54 +08:00
}
void FileManager::evtHome()
{
auto r = fileHelper_->GetHome();
auto curPath = ui->comboBox->currentText();
2025-06-20 16:00:18 +08:00
SetRoot(curPath);
2025-11-04 15:18:28 +08:00
qDebug() << QString(tr("%1 获取用户目录结果:%2").arg(__FUNCTION__).arg(r));
2025-06-15 14:31:54 +08:00
}
void FileManager::evtFile()
{
auto curPath = ui->comboBox->currentText();
auto r = fileHelper_->GetDirFile(curPath);
2025-06-20 16:00:18 +08:00
SetRoot(curPath);
2025-11-04 14:52:27 +08:00
qDebug() << QString(tr("%1 获取文件结果:%2").arg(__FUNCTION__).arg(r));
2025-06-15 14:31:54 +08:00
}
void FileManager::evtUp()
{
2025-06-20 16:00:18 +08:00
QString path(GetRoot());
2025-06-15 14:31:54 +08:00
QDir dir(path);
2025-06-15 23:49:07 +08:00
path = QDir::cleanPath(dir.absolutePath() + "/..");
2025-06-15 14:31:54 +08:00
if (path.isEmpty()) {
return;
}
auto r = fileHelper_->GetDirFile(path);
if (r) {
2025-06-20 16:00:18 +08:00
SetRoot(path);
2025-11-09 18:10:54 +08:00
ShowPath(GetRoot(), drivers_);
2025-06-15 14:31:54 +08:00
}
}
void FileManager::doubleClick(int row, int column)
{
Q_UNUSED(column)
auto* item = ui->tableWidget->item(row, 1);
if (item == nullptr) {
return;
}
auto type = ui->tableWidget->item(row, 3)->text();
2025-11-16 19:23:59 +08:00
if (type != STR_DIR) {
2025-06-15 14:31:54 +08:00
return;
}
2025-06-20 16:00:18 +08:00
QDir dir(GetRoot());
2025-06-15 14:31:54 +08:00
QString np = dir.filePath(item->text());
fileHelper_->GetDirFile(np);
}
2025-11-16 19:23:59 +08:00
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;
}