comp:Drag-and-drop implementation in the interface is bound to the sending logic.

This commit is contained in:
2025-06-22 01:17:44 +08:00
parent fd8bb4c9f1
commit 1f9275ed72
8 changed files with 332 additions and 23 deletions

View File

@@ -8,7 +8,7 @@ ClientCore::ClientCore(QObject* parent) : QObject(parent)
void ClientCore::Instance() void ClientCore::Instance()
{ {
//qDebug() << "Instance() thread:" << QThread::currentThread(); // qDebug() << "Instance() thread:" << QThread::currentThread();
socket_ = new QTcpSocket(this); socket_ = new QTcpSocket(this);
connect(socket_, &QTcpSocket::readyRead, this, &ClientCore::onReadyRead); connect(socket_, &QTcpSocket::readyRead, this, &ClientCore::onReadyRead);
connect(socket_, &QTcpSocket::disconnected, this, &ClientCore::onDisconnected); connect(socket_, &QTcpSocket::disconnected, this, &ClientCore::onDisconnected);
@@ -20,7 +20,7 @@ ClientCore::~ClientCore()
void ClientCore::DoConnect(const QString& ip, quint16 port) void ClientCore::DoConnect(const QString& ip, quint16 port)
{ {
//qDebug() << "doConnect thread:" << QThread::currentThread(); // qDebug() << "doConnect thread:" << QThread::currentThread();
emit connecting(); emit connecting();
if (!Connect(ip, port)) { if (!Connect(ip, port)) {
emit conFailed(); emit conFailed();
@@ -88,6 +88,7 @@ void ClientCore::UseFrame(QSharedPointer<FrameBuffer> frame)
} }
case FrameBufferType::FBT_SER_MSG_YOURID: { case FrameBufferType::FBT_SER_MSG_YOURID: {
ownID_ = frame->data; ownID_ = frame->data;
GlobalData::Ins()->SetLocalID(ownID_);
qInfo() << QString(tr("own id: %1")).arg(ownID_); qInfo() << QString(tr("own id: %1")).arg(ownID_);
break; break;
} }
@@ -210,6 +211,7 @@ bool ClientCore::Send(const char* data, qint64 len)
void ClientCore::SetRemoteID(const QString& id) void ClientCore::SetRemoteID(const QString& id)
{ {
GlobalData::Ins()->SetRemoteID(id);
remoteID_ = id; remoteID_ = id;
} }
@@ -225,9 +227,9 @@ QString ClientCore::GetOwnID()
SocketWorker::SocketWorker(ClientCore* core, QObject* parent) : QThread(parent), core_(core) SocketWorker::SocketWorker(ClientCore* core, QObject* parent) : QThread(parent), core_(core)
{ {
//connect(core_, &ClientCore::sigDisconnect, this, [this]() { // connect(core_, &ClientCore::sigDisconnect, this, [this]() {
// thread()->quit(); // thread()->quit();
//}); // });
} }
SocketWorker::~SocketWorker() SocketWorker::~SocketWorker()
@@ -236,7 +238,7 @@ SocketWorker::~SocketWorker()
void SocketWorker::run() void SocketWorker::run()
{ {
//qDebug() << "SocketWorker thread:" << QThread::currentThread(); // qDebug() << "SocketWorker thread:" << QThread::currentThread();
core_->Instance(); core_->Instance();
exec(); exec();
} }

View File

@@ -1,5 +1,10 @@
#include "CompareControl.h" #include "CompareControl.h"
#include <QFile>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include "GuiUtil/Public.h"
#include "ui_CompareControl.h" #include "ui_CompareControl.h"
Compare::Compare(QWidget* parent) : QWidget(parent), ui(new Ui::Compare) Compare::Compare(QWidget* parent) : QWidget(parent), ui(new Ui::Compare)
@@ -16,30 +21,248 @@ Compare::~Compare()
void Compare::InitControl() void Compare::InitControl()
{ {
InitTabWidget(); InitTabWidget();
connect(ui->btnSave, &QPushButton::clicked, this, &Compare::Save);
connect(ui->btnLoad, &QPushButton::clicked, this, &Compare::Load);
connect(ui->btnLeft, &QPushButton::clicked, this, &Compare::TransToLeft);
connect(ui->btnRight, &QPushButton::clicked, this, &Compare::TransToRight);
LoadTitles();
} }
void Compare::InitTabWidget() void Compare::InitTabWidget()
{ {
QStringList headers; QStringList headers;
headers << tr("") << tr("LocalPath") << tr("RemotePath"); headers << tr("") << tr("LocalPath") << tr("RemotePath");
ui->tableWidget->setColumnCount(headers.size()); ui->tableWidget->setColumnCount(headers.size());
ui->tableWidget->setHorizontalHeaderLabels(headers); ui->tableWidget->setHorizontalHeaderLabels(headers);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->comboBox->setEditable(true); ui->comboBox->setEditable(true);
// ui->tableWidget->setColumnWidth(0, 50); // ui->tableWidget->setColumnWidth(0, 50);
ui->tableWidget->setColumnWidth(1, 500); ui->tableWidget->setColumnWidth(1, 500);
ui->tableWidget->setColumnWidth(2, 500); ui->tableWidget->setColumnWidth(2, 500);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); ui->tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); ui->tableWidget->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
ui->tableWidget->setDragEnabled(false); ui->tableWidget->setDragEnabled(false);
ui->tableWidget->viewport()->setAcceptDrops(true); ui->tableWidget->viewport()->setAcceptDrops(true);
ui->tableWidget->setDropIndicatorShown(true); ui->tableWidget->setDropIndicatorShown(true);
ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->tableWidget->setDragDropMode(QAbstractItemView::DropOnly); ui->tableWidget->setDragDropMode(QAbstractItemView::DropOnly);
ui->comboBox->setFixedWidth(100);
}
void Compare::Save()
{
auto titleKey = ui->comboBox->currentText().trimmed();
if (titleKey.isEmpty()) {
FTCommon::msg(this, tr("Please select or input a title."));
return;
}
QFile file("CompareData.xml");
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
FTCommon::msg(this, tr("Failed to open data file."));
return;
}
QString existingContent;
QMap<QString, QStringList> dataMap;
if (file.size() > 0) {
existingContent = file.readAll();
file.seek(0);
QXmlStreamReader reader(existingContent);
while (!reader.atEnd()) {
if (reader.isStartElement() && reader.name() == "Entry") {
QString key = reader.attributes().value("title").toString();
QStringList paths;
while (!(reader.isEndElement() && reader.name() == "Entry")) {
reader.readNext();
if (reader.isStartElement() && reader.name() == "LocalPath") {
paths << reader.readElementText();
}
if (reader.isStartElement() && reader.name() == "RemotePath") {
paths << reader.readElementText();
}
}
dataMap.insert(key, paths);
}
reader.readNext();
}
}
QStringList paths;
for (int row = 0; row < ui->tableWidget->rowCount(); ++row) {
QTableWidgetItem* localItem = ui->tableWidget->item(row, 1);
QTableWidgetItem* remoteItem = ui->tableWidget->item(row, 2);
paths << (localItem ? localItem->text() : "");
paths << (remoteItem ? remoteItem->text() : "");
}
dataMap[titleKey] = paths;
file.resize(0);
QXmlStreamWriter writer(&file);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeStartElement("CompareData");
for (auto it = dataMap.begin(); it != dataMap.end(); ++it) {
writer.writeStartElement("Entry");
writer.writeAttribute("title", it.key());
const QStringList& pathList = it.value();
for (int i = 0; i < pathList.size(); i += 2) {
writer.writeTextElement("LocalPath", pathList[i]);
writer.writeTextElement("RemotePath", pathList[i + 1]);
}
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndDocument();
file.close();
if (ui->comboBox->findText(titleKey) == -1) {
ui->comboBox->addItem(titleKey);
}
FTCommon::msg(this, tr("Data saved successfully."));
}
void Compare::Load()
{
auto titleKey = ui->comboBox->currentText().trimmed();
if (titleKey.isEmpty()) {
FTCommon::msg(this, tr("Please select or input a title."));
return;
}
QFile file("CompareData.xml");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
FTCommon::msg(this, tr("Failed to open data file."));
return;
}
QXmlStreamReader reader(&file);
bool found = false;
ui->tableWidget->setRowCount(0);
while (!reader.atEnd() && !found) {
if (reader.isStartElement() && reader.name() == "Entry") {
if (reader.attributes().value("title").toString() == titleKey) {
found = true;
QStringList paths;
while (!(reader.isEndElement() && reader.name() == "Entry")) {
reader.readNext();
if (reader.isStartElement() && reader.name() == "LocalPath") {
paths << reader.readElementText();
}
if (reader.isStartElement() && reader.name() == "RemotePath") {
paths << reader.readElementText();
}
}
for (int i = 0; i < paths.size(); i += 2) {
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
QTableWidgetItem* localItem = new QTableWidgetItem(paths[i]);
QTableWidgetItem* remoteItem = new QTableWidgetItem(paths[i + 1]);
ui->tableWidget->setItem(row, 1, localItem);
ui->tableWidget->setItem(row, 2, remoteItem);
}
}
}
reader.readNext();
}
file.close();
if (!found) {
FTCommon::msg(this, tr("No data found for the selected title."));
} else {
FTCommon::msg(this, tr("Data loaded successfully."));
}
}
void Compare::LoadTitles()
{
QFile file("CompareData.xml");
if (!file.exists()) {
return;
}
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
FTCommon::msg(this, tr("Failed to open data file."));
return;
}
QString currentText = ui->comboBox->currentText();
ui->comboBox->clear();
ui->comboBox->setEditText(currentText);
QXmlStreamReader reader(&file);
while (!reader.atEnd()) {
if (reader.isStartElement() && reader.name() == "Entry") {
QString title = reader.attributes().value("title").toString();
if (!title.isEmpty() && ui->comboBox->findText(title) == -1) {
ui->comboBox->addItem(title);
}
}
reader.readNext();
}
file.close();
if (ui->comboBox->count() > 0) {
ui->comboBox->setCurrentIndex(0);
}
}
void Compare::TransToLeft()
{
QVector<TransTask> tasks;
QModelIndexList indexList = ui->tableWidget->selectionModel()->selectedRows();
for (int i = 0; i < indexList.size(); ++i) {
const QTableWidgetItem* itemF = ui->tableWidget->item(indexList[i].row(), 1);
const QTableWidgetItem* itemT = ui->tableWidget->item(indexList[i].row(), 2);
TransTask task;
task.isUpload = false;
task.localId = GlobalData::Ins()->GetLocalID();
task.localPath = itemF->text();
task.remoteId = GlobalData::Ins()->GetRemoteID();
task.remotePath = itemT->text();
tasks.push_back(task);
}
emit sigTasks(tasks);
}
void Compare::TransToRight()
{
QVector<TransTask> tasks;
QModelIndexList indexList = ui->tableWidget->selectionModel()->selectedRows();
for (int i = 0; i < indexList.size(); ++i) {
const QTableWidgetItem* itemF = ui->tableWidget->item(indexList[i].row(), 1);
const QTableWidgetItem* itemT = ui->tableWidget->item(indexList[i].row(), 2);
TransTask task;
task.isUpload = true;
task.localId = GlobalData::Ins()->GetLocalID();
task.localPath = itemF->text();
task.remoteId = GlobalData::Ins()->GetRemoteID();
task.remotePath = itemT->text();
tasks.push_back(task);
}
emit sigTasks(tasks);
} }

View File

@@ -1,6 +1,8 @@
#ifndef COMPARECONTROL_H #ifndef COMPARECONTROL_H
#define COMPARECONTROL_H #define COMPARECONTROL_H
#include <FileTrans.h>
#include <QVector>
#include <QWidget> #include <QWidget>
namespace Ui { namespace Ui {
@@ -15,10 +17,21 @@ public:
explicit Compare(QWidget* parent = nullptr); explicit Compare(QWidget* parent = nullptr);
~Compare(); ~Compare();
signals:
void sigTasks(const QVector<TransTask>& tasks);
private: private:
void InitControl(); void InitControl();
void InitTabWidget(); void InitTabWidget();
private:
void Save();
void Load();
void LoadTitles();
void TransToLeft();
void TransToRight();
private: private:
Ui::Compare* ui; Ui::Compare* ui;
}; };

View File

@@ -6,14 +6,27 @@
#include <QPainter> #include <QPainter>
#include <Util.h> #include <Util.h>
#include "GuiUtil/Public.h"
CpTableWidget::CpTableWidget(QWidget* parent) : QTableWidget(parent) CpTableWidget::CpTableWidget(QWidget* parent) : QTableWidget(parent)
{ {
contexMenu_ = new QMenu(this);
delAction_ = new QAction(tr("delete"), this);
connect(delAction_, &QAction::triggered, this, &CpTableWidget::deleteSelectedRows);
contexMenu_->addAction(delAction_);
} }
CpTableWidget::~CpTableWidget() CpTableWidget::~CpTableWidget()
{ {
} }
void CpTableWidget::contextMenuEvent(QContextMenuEvent* event)
{
if (selectedItems().count() > 0) {
contexMenu_->exec(event->globalPos());
}
}
void CpTableWidget::dropEvent(QDropEvent* event) void CpTableWidget::dropEvent(QDropEvent* event)
{ {
if (!event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) { if (!event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
@@ -78,3 +91,22 @@ void CpTableWidget::dragEnterEvent(QDragEnterEvent* event)
event->ignore(); event->ignore();
} }
} }
void CpTableWidget::deleteSelectedRows()
{
auto r = FTCommon::affirm(this, tr("confirm"), tr("delete selected rows?"));
if (!r) {
return;
}
QList<int> rowsToDelete;
for (QTableWidgetItem* item : selectedItems()) {
int row = item->row();
if (!rowsToDelete.contains(row)) {
rowsToDelete.append(row);
}
}
std::sort(rowsToDelete.begin(), rowsToDelete.end(), std::greater<int>());
for (int row : rowsToDelete) {
removeRow(row);
}
}

View File

@@ -1,8 +1,10 @@
#ifndef CP_TABLEWIDET_H #ifndef CP_TABLEWIDET_H
#define CP_TABLEWIDET_H #define CP_TABLEWIDET_H
#include <QTableWidget> #include <QAction>
#include <QDropEvent> #include <QDropEvent>
#include <QMenu>
#include <QTableWidget>
class CpTableWidget : public QTableWidget class CpTableWidget : public QTableWidget
{ {
@@ -14,6 +16,14 @@ public:
protected: protected:
void dropEvent(QDropEvent* event) override; void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event); void dragEnterEvent(QDragEnterEvent* event);
void contextMenuEvent(QContextMenuEvent* event) override;
private slots:
void deleteSelectedRows();
private:
QMenu* contexMenu_;
QAction* delAction_;
}; };
#endif // CP_TABLEWIDET_H #endif // CP_TABLEWIDET_H

View File

@@ -53,6 +53,7 @@ void frelayGUI::InitControl()
connect(localFile_, &FileManager::sigSendTasks, this, &frelayGUI::HandleTask); connect(localFile_, &FileManager::sigSendTasks, this, &frelayGUI::HandleTask);
connect(remoteFile_, &FileManager::sigSendTasks, this, &frelayGUI::HandleTask); connect(remoteFile_, &FileManager::sigSendTasks, this, &frelayGUI::HandleTask);
connect(compare_, &Compare::sigTasks, this, &frelayGUI::HandleTask);
} }
void frelayGUI::ControlSignal() void frelayGUI::ControlSignal()

View File

@@ -138,13 +138,25 @@ GlobalData* GlobalData::Ins()
void GlobalData::SetLocalRoot(const QString& root) void GlobalData::SetLocalRoot(const QString& root)
{ {
QMutexLocker locker(&mutex_); QMutexLocker locker(&mutex_);
LocalRoot_ = root; LocalRoot_ = root;
}
void GlobalData::SetLocalID(const QString& id)
{
QMutexLocker locker(&mutex_);
LocalID_ = id;
}
void GlobalData::SetRemoteID(const QString& id)
{
QMutexLocker locker(&mutex_);
RemoteID_ = id;
} }
void GlobalData::SetRemoteRoot(const QString& root) void GlobalData::SetRemoteRoot(const QString& root)
{ {
QMutexLocker locker(&mutex_); QMutexLocker locker(&mutex_);
RemoteRoot_ = root; RemoteRoot_ = root;
} }
QString GlobalData::GetLocalRoot() const QString GlobalData::GetLocalRoot() const
@@ -152,7 +164,17 @@ QString GlobalData::GetLocalRoot() const
return LocalRoot_; return LocalRoot_;
} }
QString GlobalData::GetLocalID() const
{
return LocalID_;
}
QString GlobalData::GetRemoteRoot() const QString GlobalData::GetRemoteRoot() const
{ {
return RemoteRoot_; return RemoteRoot_;
} }
QString GlobalData::GetRemoteID() const
{
return RemoteID_;
}

View File

@@ -13,9 +13,13 @@ public:
public: public:
void SetLocalRoot(const QString& root); void SetLocalRoot(const QString& root);
void SetLocalID(const QString& id);
void SetRemoteRoot(const QString& root); void SetRemoteRoot(const QString& root);
void SetRemoteID(const QString& id);
QString GetLocalRoot() const; QString GetLocalRoot() const;
QString GetLocalID() const;
QString GetRemoteRoot() const; QString GetRemoteRoot() const;
QString GetRemoteID() const;
private: private:
GlobalData() = default; GlobalData() = default;
@@ -24,6 +28,8 @@ public:
QMutex mutex_; QMutex mutex_;
QString LocalRoot_; QString LocalRoot_;
QString RemoteRoot_; QString RemoteRoot_;
QString LocalID_;
QString RemoteID_;
}; };
class Util : public QObject class Util : public QObject