Files
frelay/Gui/Control/ConnectControl.cpp

225 lines
6.4 KiB
C++

#include "ConnectControl.h"
#include <InfoMsg.h>
#include <InfoPack.hpp>
#include <QRegularExpression>
#include <future>
#include "GuiUtil/Public.h"
#include "ui_ConnectControl.h"
Connecter::Connecter(QWidget* parent) : QWidget(parent), ui(new Ui::Connecter)
{
ui->setupUi(this);
InitControl();
}
Connecter::~Connecter()
{
delete ui;
}
void Connecter::RunWorker(ClientCore* clientCore)
{
clientCore_ = clientCore;
connect(clientCore_, &ClientCore::sigClients, this, &Connecter::HandleClients);
sockWorker_ = new SocketWorker(clientCore_, nullptr);
heatBeat_ = new HeatBeat(clientCore_);
clientCore_->moveToThread(sockWorker_);
connect(clientCore_, &ClientCore::conSuccess, this, [this]() {
setState(ConnectState::CS_CONNECTED);
qInfo() << QString(tr("Connected."));
});
connect(clientCore_, &ClientCore::conFailed, this, [this]() {
setState(ConnectState::CS_DISCONNECT);
qInfo() << QString(tr("Connect failed."));
});
connect(clientCore_, &ClientCore::connecting, this, [this]() {
setState(ConnectState::CS_CONNECTING);
qInfo() << QString(tr("Connecting..."));
});
connect(clientCore_, &ClientCore::sigDisconnect, this, [this]() {
setState(ConnectState::CS_DISCONNECT);
QStandardItemModel* model = qobject_cast<QStandardItemModel*>(ui->listView->model());
if (model) {
model->clear();
}
ui->elbClient->clear();
clientCore_->SetRemoteID("");
qInfo() << QString(tr("Disconnected."));
});
connect(this, &Connecter::sigDoConnect, clientCore_, &ClientCore::DoConnect);
connect(this, &Connecter::sigDisConnect, this,
[this]() { QMetaObject::invokeMethod(clientCore_, "Disconnect", Qt::QueuedConnection); });
connect(sockWorker_, &QThread::finished, sockWorker_, &QObject::deleteLater);
heatBeat_->start();
sockWorker_->start();
}
void Connecter::SetRemoteCall(const std::function<void(const QString& id)>& call)
{
remoteCall_ = call;
}
void Connecter::HandleClients(const InfoClientVec& clients)
{
model_->removeRows(0, ui->listView->model()->rowCount());
for (const auto& client : clients.vec) {
auto* item = new QStandardItem(client.id);
model_->appendRow(item);
}
}
void Connecter::SetConfigPtr(std::shared_ptr<FrelayConfig> config)
{
config_ = config;
auto ipPorts = config_->GetIpPort();
for (const auto& ipPort : ipPorts) {
ui->comboBox->addItem(ipPort);
}
if (ui->comboBox->count() > 0) {
ui->comboBox->setCurrentIndex(0);
}
}
void Connecter::Connect()
{
QString ip;
QString port;
if (!parseIpPort(ui->comboBox->currentText(), ip, port)) {
FTCommon::msg(this, QString(tr("IP or port is invalid.")));
return;
}
emit sigDoConnect(ip, port.toInt());
}
void Connecter::setState(ConnectState cs)
{
config_->SaveIpPort(ui->comboBox->currentText());
switch (cs) {
case CS_CONNECTING:
ui->btnConnect->setEnabled(false);
ui->btnDisconnect->setEnabled(false);
break;
case CS_CONNECTED:
ui->btnConnect->setEnabled(false);
ui->btnDisconnect->setEnabled(true);
RefreshClient();
connect(heatBeat_, &HeatBeat::finished, heatBeat_, &QObject::deleteLater);
break;
case CS_DISCONNECT:
ui->btnConnect->setEnabled(true);
ui->btnDisconnect->setEnabled(false);
break;
default:
break;
}
}
void Connecter::Disconnect()
{
qWarning() << QString(tr("Disconnected requeset..."));
emit sigDisConnect();
}
void Connecter::RefreshClient()
{
InfoMsg info;
auto frame = QSharedPointer<FrameBuffer>::create();
frame->data = infoPack(info);
frame->type = FBT_SER_MSG_ASKCLIENTS;
auto sendRet = ClientCore::syncInvoke(clientCore_, frame);
if (!sendRet) {
qCritical() << QString(tr("send ask client list failed."));
return;
}
qInfo() << QString(tr("ask client list..."));
}
void Connecter::ShowContextMenu(const QPoint& pos)
{
auto index = ui->listView->indexAt(pos);
if (!index.isValid()) {
return;
}
menu_->exec(QCursor::pos());
}
std::string Connecter::getCurClient()
{
return ui->elbClient->text().toStdString();
}
void Connecter::InitControl()
{
ui->btnDisconnect->setEnabled(false);
ui->comboBox->setEditable(true);
connect(ui->btnConnect, &QPushButton::clicked, this, &Connecter::Connect);
connect(ui->btnRefresh, &QPushButton::clicked, this, &Connecter::RefreshClient);
connect(this, &Connecter::sendConnect, this, &Connecter::setState);
model_ = new QStandardItemModel(this);
ui->listView->setModel(model_);
ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->listView, &QListView::customContextMenuRequested, this, &Connecter::ShowContextMenu);
connect(ui->btnDisconnect, &QPushButton::clicked, this, &Connecter::Disconnect);
menu_ = new QMenu(this);
QAction* acUseThis = menu_->addAction(tr("UseThis"));
connect(acUseThis, &QAction::triggered, this, [this]() {
auto index = ui->listView->currentIndex();
if (!index.isValid()) {
return;
}
auto* item = model_->itemFromIndex(index);
if (!item) {
return;
}
auto name = item->text();
ui->elbClient->setText(name);
ui->elbClient->setStyleSheet("color: green;");
remoteCall_(name);
emit sigConfirmUse();
});
setMaximumWidth(300);
}
bool Connecter::parseIpPort(const QString& ipPort, QString& outIp, QString& outPort)
{
QRegularExpression regex("^\\s*"
"("
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
")"
"\\s*:\\s*"
"("
"\\d{1,5}"
")"
"\\s*$");
QRegularExpressionMatch match = regex.match(ipPort);
if (!match.hasMatch()) {
return false;
}
outIp = match.captured(1);
outPort = match.captured(2);
bool portOk;
int portNum = outPort.toInt(&portOk);
return portOk && portNum > 0 && portNum <= 65535;
}