diff --git a/ClientCore/ClientCore.cpp b/ClientCore/ClientCore.cpp index fc7058f..3bfa32d 100644 --- a/ClientCore/ClientCore.cpp +++ b/ClientCore/ClientCore.cpp @@ -8,7 +8,7 @@ ClientCore::ClientCore(QObject* parent) : QObject(parent) void ClientCore::Instance() { - //qDebug() << "Instance() thread:" << QThread::currentThread(); + // qDebug() << "Instance() thread:" << QThread::currentThread(); socket_ = new QTcpSocket(this); connect(socket_, &QTcpSocket::readyRead, this, &ClientCore::onReadyRead); connect(socket_, &QTcpSocket::disconnected, this, &ClientCore::onDisconnected); @@ -20,7 +20,7 @@ ClientCore::~ClientCore() void ClientCore::DoConnect(const QString& ip, quint16 port) { - //qDebug() << "doConnect thread:" << QThread::currentThread(); + // qDebug() << "doConnect thread:" << QThread::currentThread(); emit connecting(); if (!Connect(ip, port)) { emit conFailed(); @@ -88,6 +88,7 @@ void ClientCore::UseFrame(QSharedPointer frame) } case FrameBufferType::FBT_SER_MSG_YOURID: { ownID_ = frame->data; + GlobalData::Ins()->SetLocalID(ownID_); qInfo() << QString(tr("own id: %1")).arg(ownID_); break; } @@ -210,6 +211,7 @@ bool ClientCore::Send(const char* data, qint64 len) void ClientCore::SetRemoteID(const QString& id) { + GlobalData::Ins()->SetRemoteID(id); remoteID_ = id; } @@ -225,9 +227,9 @@ QString ClientCore::GetOwnID() SocketWorker::SocketWorker(ClientCore* core, QObject* parent) : QThread(parent), core_(core) { - //connect(core_, &ClientCore::sigDisconnect, this, [this]() { - // thread()->quit(); - //}); + // connect(core_, &ClientCore::sigDisconnect, this, [this]() { + // thread()->quit(); + // }); } SocketWorker::~SocketWorker() @@ -236,7 +238,7 @@ SocketWorker::~SocketWorker() void SocketWorker::run() { - //qDebug() << "SocketWorker thread:" << QThread::currentThread(); + // qDebug() << "SocketWorker thread:" << QThread::currentThread(); core_->Instance(); exec(); } diff --git a/Gui/Control/CompareControl.cpp b/Gui/Control/CompareControl.cpp index a339a54..b55d9ae 100644 --- a/Gui/Control/CompareControl.cpp +++ b/Gui/Control/CompareControl.cpp @@ -1,5 +1,10 @@ #include "CompareControl.h" +#include +#include +#include + +#include "GuiUtil/Public.h" #include "ui_CompareControl.h" Compare::Compare(QWidget* parent) : QWidget(parent), ui(new Ui::Compare) @@ -16,30 +21,248 @@ Compare::~Compare() void Compare::InitControl() { 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() { - QStringList headers; - headers << tr("") << tr("LocalPath") << tr("RemotePath"); - ui->tableWidget->setColumnCount(headers.size()); - ui->tableWidget->setHorizontalHeaderLabels(headers); - ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + QStringList headers; + headers << tr("") << tr("LocalPath") << tr("RemotePath"); + ui->tableWidget->setColumnCount(headers.size()); + ui->tableWidget->setHorizontalHeaderLabels(headers); + ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->comboBox->setEditable(true); + ui->comboBox->setEditable(true); // ui->tableWidget->setColumnWidth(0, 50); - ui->tableWidget->setColumnWidth(1, 500); - ui->tableWidget->setColumnWidth(2, 500); + ui->tableWidget->setColumnWidth(1, 500); + ui->tableWidget->setColumnWidth(2, 500); - 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->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); + 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->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); ui->tableWidget->setDragEnabled(false); ui->tableWidget->viewport()->setAcceptDrops(true); ui->tableWidget->setDropIndicatorShown(true); ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); 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 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 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 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); } diff --git a/Gui/Control/CompareControl.h b/Gui/Control/CompareControl.h index 76c8904..05447da 100644 --- a/Gui/Control/CompareControl.h +++ b/Gui/Control/CompareControl.h @@ -1,6 +1,8 @@ #ifndef COMPARECONTROL_H #define COMPARECONTROL_H +#include +#include #include namespace Ui { @@ -15,10 +17,21 @@ public: explicit Compare(QWidget* parent = nullptr); ~Compare(); +signals: + void sigTasks(const QVector& tasks); + private: void InitControl(); void InitTabWidget(); +private: + void Save(); + void Load(); + void LoadTitles(); + + void TransToLeft(); + void TransToRight(); + private: Ui::Compare* ui; }; diff --git a/Gui/Control/cpTableWidget.cpp b/Gui/Control/cpTableWidget.cpp index b09d616..f8cd150 100644 --- a/Gui/Control/cpTableWidget.cpp +++ b/Gui/Control/cpTableWidget.cpp @@ -6,14 +6,27 @@ #include #include +#include "GuiUtil/Public.h" + 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() { } +void CpTableWidget::contextMenuEvent(QContextMenuEvent* event) +{ + if (selectedItems().count() > 0) { + contexMenu_->exec(event->globalPos()); + } +} + void CpTableWidget::dropEvent(QDropEvent* event) { if (!event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) { @@ -78,3 +91,22 @@ void CpTableWidget::dragEnterEvent(QDragEnterEvent* event) event->ignore(); } } + +void CpTableWidget::deleteSelectedRows() +{ + auto r = FTCommon::affirm(this, tr("confirm"), tr("delete selected rows?")); + if (!r) { + return; + } + QList rowsToDelete; + for (QTableWidgetItem* item : selectedItems()) { + int row = item->row(); + if (!rowsToDelete.contains(row)) { + rowsToDelete.append(row); + } + } + std::sort(rowsToDelete.begin(), rowsToDelete.end(), std::greater()); + for (int row : rowsToDelete) { + removeRow(row); + } +} \ No newline at end of file diff --git a/Gui/Control/cpTableWidget.h b/Gui/Control/cpTableWidget.h index b1b36da..b33e94d 100644 --- a/Gui/Control/cpTableWidget.h +++ b/Gui/Control/cpTableWidget.h @@ -1,8 +1,10 @@ #ifndef CP_TABLEWIDET_H #define CP_TABLEWIDET_H -#include +#include #include +#include +#include class CpTableWidget : public QTableWidget { @@ -14,6 +16,14 @@ public: protected: void dropEvent(QDropEvent* event) override; 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 diff --git a/Gui/frelayGUI.cpp b/Gui/frelayGUI.cpp index 6c52b9e..aca9a10 100644 --- a/Gui/frelayGUI.cpp +++ b/Gui/frelayGUI.cpp @@ -53,6 +53,7 @@ void frelayGUI::InitControl() connect(localFile_, &FileManager::sigSendTasks, this, &frelayGUI::HandleTask); connect(remoteFile_, &FileManager::sigSendTasks, this, &frelayGUI::HandleTask); + connect(compare_, &Compare::sigTasks, this, &frelayGUI::HandleTask); } void frelayGUI::ControlSignal() diff --git a/Util/Util.cpp b/Util/Util.cpp index 7327500..cbf6a50 100644 --- a/Util/Util.cpp +++ b/Util/Util.cpp @@ -138,13 +138,25 @@ GlobalData* GlobalData::Ins() void GlobalData::SetLocalRoot(const QString& root) { 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) { QMutexLocker locker(&mutex_); - RemoteRoot_ = root; + RemoteRoot_ = root; } QString GlobalData::GetLocalRoot() const @@ -152,7 +164,17 @@ QString GlobalData::GetLocalRoot() const return LocalRoot_; } +QString GlobalData::GetLocalID() const +{ + return LocalID_; +} + QString GlobalData::GetRemoteRoot() const { return RemoteRoot_; +} + +QString GlobalData::GetRemoteID() const +{ + return RemoteID_; } \ No newline at end of file diff --git a/Util/Util.h b/Util/Util.h index 1b31492..cf9b59a 100644 --- a/Util/Util.h +++ b/Util/Util.h @@ -13,9 +13,13 @@ public: public: void SetLocalRoot(const QString& root); + void SetLocalID(const QString& id); void SetRemoteRoot(const QString& root); + void SetRemoteID(const QString& id); QString GetLocalRoot() const; + QString GetLocalID() const; QString GetRemoteRoot() const; + QString GetRemoteID() const; private: GlobalData() = default; @@ -24,6 +28,8 @@ public: QMutex mutex_; QString LocalRoot_; QString RemoteRoot_; + QString LocalID_; + QString RemoteID_; }; class Util : public QObject