debug:初步显示远端文件。

This commit is contained in:
taynpg 2025-05-12 22:07:06 +08:00
parent 7bf936fa8f
commit de46e40e0c
13 changed files with 358 additions and 9 deletions

View File

@ -4,11 +4,17 @@ project(ClientCore LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (MSVC)
add_compile_options(/utf-8)
endif()
find_package(wxWidgets CONFIG REQUIRED) find_package(wxWidgets CONFIG REQUIRED)
set(MSOURCES set(MSOURCES
ClientCore.h ClientCore.h
ClientCore.cxx ClientCore.cxx
ClientFile.h
ClientFile.cxx
) )
add_library(ClientCore STATIC ${MSOURCES}) add_library(ClientCore STATIC ${MSOURCES})

View File

@ -52,6 +52,11 @@ wxString ClientCore::GetErr() const
return err_; return err_;
} }
wxString ClientCore::GetOwnId() const
{
return id_;
}
bool ClientCore::IsOk() bool ClientCore::IsOk()
{ {
return socket_->IsConnected(); return socket_->IsConnected();
@ -76,6 +81,16 @@ void ClientCore::ReqOnlineCallback(const std::function<void(const InfoClientVec&
onlineCallback_ = callback; onlineCallback_ = callback;
} }
void ClientCore::SetHomeCallback(const std::function<void(const wxString&)>& callback)
{
homeCall_ = callback;
}
void ClientCore::SetDirFileCallback(const std::function<void(const DirFileInfoVec&)>& callback)
{
dirFileCall_ = callback;
}
bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec) bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec)
{ {
return false; return false;
@ -121,6 +136,42 @@ void ClientCore::UseFrame(FrameBuffer* buf)
InfoCommunicate info; InfoCommunicate info;
break; break;
} }
case FBT_CLI_ASK_HOME: {
InfoCommunicate info;
wxString home = wxGetHomeDir();
info.data = home.ToStdString();
Send<InfoCommunicate>(info, FBT_CLI_ANS_HOME, buf->fid);
break;
}
case FBT_CLI_ANS_HOME: {
InfoCommunicate info;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> info;
if (homeCall_) {
homeCall_(info.data);
}
break;
}
case FBT_CLI_ASK_DIRFILE: {
InfoCommunicate info;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> info;
DirFileInfoVec vec;
if (!cf_.GetDirFiles(info.data, vec)) {
break;
}
Send<DirFileInfoVec>(vec, FBT_CLI_ANS_DIRFILE, buf->fid);
break;
}
case FBT_CLI_ANS_DIRFILE: {
DirFileInfoVec vec;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> vec;
if (dirFileCall_) {
dirFileCall_(vec);
}
break;
}
default: default:
break; break;
} }

View File

@ -1,15 +1,16 @@
#ifndef CLIENTCORE_H #ifndef CLIENTCORE_H
#define CLIENTCORE_H #define CLIENTCORE_H
#include "ClientFile.h"
#include <InfoClient.hpp> #include <InfoClient.hpp>
#include <InfoCommunicate.hpp> #include <InfoCommunicate.hpp>
#include <InfoDirFile.hpp> #include <InfoDirFile.hpp>
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <memory>
#include <vector>
#include <thread>
#include <functional> #include <functional>
#include <memory>
#include <thread>
#include <vector>
#include <wx/socket.h> #include <wx/socket.h>
#include <Communicate.h> #include <Communicate.h>
@ -27,12 +28,17 @@ public:
public: public:
wxString GetErr() const; wxString GetErr() const;
wxString GetOwnId() const;
bool IsOk(); bool IsOk();
void SetLogCallback(const std::function<void(const wxString&)>& callback); void SetLogCallback(const std::function<void(const wxString&)>& callback);
bool ReqOnline(); bool ReqOnline();
void ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback);
bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec); bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec);
public:
void ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback);
void SetHomeCallback(const std::function<void(const wxString&)>& callback);
void SetDirFileCallback(const std::function<void(const DirFileInfoVec&)>& callback);
private: private:
void UseFrame(FrameBuffer* buf); void UseFrame(FrameBuffer* buf);
@ -42,7 +48,9 @@ private:
private: private:
void HeartBeat(); void HeartBeat();
void Recv(); void Recv();
template <typename T> bool Send(const T& info, FrameBufferType type)
public:
template <typename T> bool Send(const T& info, FrameBufferType type, const wxString& remoteId = wxEmptyString)
{ {
std::stringstream ss; std::stringstream ss;
cereal::BinaryOutputArchive archive(ss); cereal::BinaryOutputArchive archive(ss);
@ -52,6 +60,7 @@ private:
buf->dataConst = ss.view().data(); buf->dataConst = ss.view().data();
buf->len = ss.str().size(); buf->len = ss.str().size();
buf->dataType = type; buf->dataType = type;
buf->tid = remoteId.ToStdString();
return Send(buf.get()); return Send(buf.get());
} }
@ -62,13 +71,16 @@ private:
bool thRun_; bool thRun_;
MutBuffer buffer_; MutBuffer buffer_;
wxString err_; wxString err_;
ClientFile cf_;
std::thread recvThread_; std::thread recvThread_;
std::array<char, GBUFFER_SIZE> buf_; std::array<char, GBUFFER_SIZE> buf_;
wxSocketClient* socket_; wxSocketClient* socket_;
private: private:
std::function<void(const DirFileInfoVec&)> dirFileCall_;
std::function<void(const InfoClientVec&)> onlineCallback_; std::function<void(const InfoClientVec&)> onlineCallback_;
std::function<void(const wxString&)> logCall_; std::function<void(const wxString&)> logCall_;
std::function<void(const wxString&)> homeCall_;
}; };
#endif // CLIENTCORE_H #endif // CLIENTCORE_H

65
ClientCore/ClientFile.cxx Normal file
View File

@ -0,0 +1,65 @@
#include "ClientFile.h"
#include <wx/dir.h>
ClientFile::ClientFile()
{
}
bool ClientFile::GetDirFiles(const std::string& path, DirFileInfoVec& vec)
{
if (!fs::exists(path)) {
lastErr_ = wxString::Format(_("Path does not exist: %s"), path);
return false;
}
if (!fs::is_directory(path)) {
lastErr_ = wxString::Format(_("Not a directory: %s"), path);
return false;
}
vec.vec.clear();
try {
// 遍历目录
for (const auto& entry : fs::directory_iterator(path)) {
DirFileInfo info;
const auto& path = entry.path();
// 设置基本信息
info.fullPath = path.string();
info.name = path.filename().string();
// 设置类型
if (entry.is_directory()) {
info.type = Dir;
info.size = 0;
} else if (entry.is_regular_file()) {
info.type = File;
info.size = entry.file_size();
} else {
// 跳过符号链接、设备文件等
continue;
}
// 获取最后修改时间
auto ftime = entry.last_write_time();
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
info.lastModifyTime = std::chrono::system_clock::to_time_t(sctp);
vec.vec.push_back(info);
}
} catch (const fs::filesystem_error& e) {
lastErr_ = wxString::FromUTF8(e.what());
return false;
} catch (const std::exception& e) {
lastErr_ = wxString::FromUTF8(e.what());
return false;
}
return true;
}
wxString ClientFile::GetLastErr() const
{
return lastErr_;
}

21
ClientCore/ClientFile.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef CLIENTFILE_H
#define CLIENTFILE_H
#include <InfoDirFile.hpp>
#include <filesystem>
namespace fs = std::filesystem;
class ClientFile
{
public:
ClientFile();
public:
bool GetDirFiles(const std::string& path, DirFileInfoVec& vec);
wxString GetLastErr() const;
private:
wxString lastErr_;
};
#endif // CLIENTFILE_H

View File

@ -17,6 +17,47 @@ enum FileType : uint32_t {
}; };
struct DirFileInfo { struct DirFileInfo {
static wxString GetFileSize(uint64_t size)
{
const uint64_t KB = 1024;
const uint64_t MB = KB * 1024;
const uint64_t GB = MB * 1024;
if (size >= GB) {
return wxString::Format("%.2f GB", static_cast<double>(size) / GB);
} else if (size >= MB) {
return wxString::Format("%.2f MB", static_cast<double>(size) / MB);
} else if (size >= KB) {
return wxString::Format("%.2f KB", static_cast<double>(size) / KB);
} else {
return wxString::Format("%llu B", size);
}
}
static wxString GetStrTime(uint64_t time)
{
wxDateTime dt(static_cast<time_t>(time));
wxString dateStr = dt.Format("%Y/%m/%d %H:%M:%S");
return dateStr;
}
static wxString GetFileTypeName(FileType type)
{
switch (type) {
case None:
return _("None");
case File:
return _("File");
case Dir:
return _("Dir");
case Link:
return _("Link");
default:
return _("Unknown");
}
}
std::string name; std::string name;
uint64_t size = 0; uint64_t size = 0;
FileType type = None; FileType type = None;

View File

@ -12,7 +12,10 @@ enum FrameBufferType : uint16_t {
FBT_SER_MSG_RESPONSE, FBT_SER_MSG_RESPONSE,
FBT_CLI_BIN_FILEDATA = 31, FBT_CLI_BIN_FILEDATA = 31,
FBT_CLI_MSG_COMMUNICATE, FBT_CLI_MSG_COMMUNICATE,
FBT_CLI_INFO_DIRFILE FBT_CLI_ASK_DIRFILE,
FBT_CLI_ANS_DIRFILE,
FBT_CLI_ASK_HOME,
FBT_CLI_ANS_HOME
}; };
struct FrameBuffer { struct FrameBuffer {

View File

@ -10,13 +10,15 @@ void ControlManager::Init(std::shared_ptr<ClientCore>& clientCore)
log_ = new LogControl(parent_); log_ = new LogControl(parent_);
header_ = new HeaderControl(parent_, clientCore); header_ = new HeaderControl(parent_, clientCore);
local_ = new LocalControl(parent_); local_ = new LocalControl(parent_);
remote_ = new RemoteControl(parent_); remote_ = new RemoteControl(parent_, clientCore);
task_ = new TaskControl(parent_); task_ = new TaskControl(parent_);
online_ = new OnlineControl(parent_, clientCore); online_ = new OnlineControl(parent_, clientCore);
header_->SetLogControl(log_); header_->SetLogControl(log_);
online_->SetLogControl(log_); online_->SetLogControl(log_);
header_->SetOnlineControl(online_); header_->SetOnlineControl(online_);
online_->SetRemoteControl(remote_);
remote_->SetLogControl(log_);
clientCore->SetLogCallback([this](const wxString& msg) { log_->AddLog(msg); }); clientCore->SetLogCallback([this](const wxString& msg) { log_->AddLog(msg); });
} }

View File

@ -7,6 +7,7 @@
class LogControl; class LogControl;
class ClientCore; class ClientCore;
class OnlineControl; class OnlineControl;
class RemoteControl;
class HeaderControl : public wxPanel class HeaderControl : public wxPanel
{ {
public: public:
@ -16,6 +17,7 @@ public:
public: public:
void SetLogControl(LogControl* logControl); void SetLogControl(LogControl* logControl);
void SetOnlineControl(OnlineControl* onlineControl); void SetOnlineControl(OnlineControl* onlineControl);
void SetRemoteControl(RemoteControl* remoteControl);
private: private:
void Init(); void Init();

View File

@ -1,12 +1,14 @@
#include "OnLineControl.h" #include "OnLineControl.h"
#include "HeaderControl.h" #include "HeaderControl.h"
#include "LogControl.h" #include "LogControl.h"
#include "RemoteControl.h"
#include <ClientCore.h> #include <ClientCore.h>
OnlineControl::OnlineControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore) OnlineControl::OnlineControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore)
{ {
Init(); Init();
InitCall(); InitCall();
BindEvent();
} }
OnlineControl::~OnlineControl() OnlineControl::~OnlineControl()
@ -23,6 +25,11 @@ void OnlineControl::SetLogControl(LogControl* logControl)
logControl_ = logControl; logControl_ = logControl;
} }
void OnlineControl::SetRemoteControl(RemoteControl* remoteControl)
{
remoteControl_ = remoteControl;
}
void OnlineControl::Init() void OnlineControl::Init()
{ {
btnFresh_ = new wxButton(this, wxID_ANY, _("Refresh")); btnFresh_ = new wxButton(this, wxID_ANY, _("Refresh"));
@ -30,6 +37,8 @@ void OnlineControl::Init()
elbCurState_ = new wxStaticText(this, wxID_ANY, _("Disconnected")); elbCurState_ = new wxStaticText(this, wxID_ANY, _("Disconnected"));
elbCurState_->SetForegroundColour(*wxBLUE); elbCurState_->SetForegroundColour(*wxBLUE);
onLineList_ = new wxListBox(this, wxID_ANY); onLineList_ = new wxListBox(this, wxID_ANY);
// 设置 onLineList_ 只能单选
onLineList_->SetWindowStyle(wxLB_SINGLE);
lbCurPoint_ = new wxStaticText(this, wxID_ANY, _("Commnunicate Point => ")); lbCurPoint_ = new wxStaticText(this, wxID_ANY, _("Commnunicate Point => "));
elbCurPoint_ = new wxStaticText(this, wxID_ANY, _("None")); elbCurPoint_ = new wxStaticText(this, wxID_ANY, _("None"));
@ -51,7 +60,20 @@ void OnlineControl::Init()
SetSizer(topSizer); SetSizer(topSizer);
Layout(); Layout();
menu_ = new wxMenu;
useId_ = wxNewId();
menu_->Append(useId_, _("Use this client"));
}
void OnlineControl::BindEvent()
{
Bind(wxEVT_BUTTON, &OnlineControl::OnFreshClients, this, btnFresh_->GetId()); Bind(wxEVT_BUTTON, &OnlineControl::OnFreshClients, this, btnFresh_->GetId());
onLineList_->Bind(wxEVT_CONTEXT_MENU, [&](wxContextMenuEvent& event) {
auto p = event.GetPosition();
p = onLineList_->ScreenToClient(p);
onLineList_->PopupMenu(menu_, p);
});
Bind(wxEVT_MENU, &OnlineControl::UseThisClient, this, useId_);
} }
void OnlineControl::SetConnectState(const wxString& state) void OnlineControl::SetConnectState(const wxString& state)
@ -98,3 +120,20 @@ void OnlineControl::OnFreshClientsCall(const InfoClientVec& infoClientVec)
} }
logControl_->AddLog(_("Get online list success.")); logControl_->AddLog(_("Get online list success."));
} }
void OnlineControl::UseThisClient(wxCommandEvent& event)
{
int selection = onLineList_->GetSelection();
if (selection != wxNOT_FOUND) {
wxString selectedText = onLineList_->GetString(selection);
if (clientCore_->GetOwnId() == selectedText) {
wxMessageDialog dialog(this, _("You selected yourself, do you want to use yourself?"), _("Confirm"),
wxYES_NO | wxICON_QUESTION);
if (dialog.ShowModal() == wxID_YES) {
remoteControl_->setRemoteID(selectedText);
}
return;
}
remoteControl_->setRemoteID(selectedText);
}
}

View File

@ -8,6 +8,7 @@
class HeaderControl; class HeaderControl;
class LogControl; class LogControl;
class ClientCore; class ClientCore;
class RemoteControl;
class OnlineControl : public wxPanel class OnlineControl : public wxPanel
{ {
public: public:
@ -16,6 +17,7 @@ public:
public: public:
void SetHeaderControl(HeaderControl* headerControl); void SetHeaderControl(HeaderControl* headerControl);
void SetRemoteControl(RemoteControl* remoteControl);
void SetLogControl(LogControl* logControl); void SetLogControl(LogControl* logControl);
void SetConnectState(const wxString& state); void SetConnectState(const wxString& state);
void SetConnectServer(const wxString& server); void SetConnectServer(const wxString& server);
@ -24,10 +26,12 @@ public:
private: private:
void Init(); void Init();
void InitCall(); void InitCall();
void BindEvent();
void OnFreshClients(wxCommandEvent& event); void OnFreshClients(wxCommandEvent& event);
private: private:
void OnFreshClientsCall(const InfoClientVec& infoClientVec); void OnFreshClientsCall(const InfoClientVec& infoClientVec);
void UseThisClient(wxCommandEvent& event);
public: public:
wxButton* btnFresh_; wxButton* btnFresh_;
@ -39,7 +43,12 @@ public:
wxListBox* onLineList_; wxListBox* onLineList_;
HeaderControl* headerControl_; HeaderControl* headerControl_;
LogControl* logControl_; LogControl* logControl_;
wxMenu* menu_;
RemoteControl* remoteControl_;
std::shared_ptr<ClientCore> clientCore_; std::shared_ptr<ClientCore> clientCore_;
private:
wxWindowID useId_;
}; };
#endif // ONLINECONTROL_H #endif // ONLINECONTROL_H

View File

@ -1,9 +1,13 @@
#include "RemoteControl.h" #include "RemoteControl.h"
#include "LogControl.h"
#include <ClientCore.h>
#include <InfoCommunicate.hpp>
RemoteControl::RemoteControl(wxWindow* parent) : wxPanel(parent) RemoteControl::RemoteControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore)
{ {
Init(); Init();
SetGrid(); SetGrid();
BindEvent();
} }
RemoteControl::~RemoteControl() RemoteControl::~RemoteControl()
@ -19,6 +23,11 @@ void RemoteControl::Init()
textCtrl_ = new wxTextCtrl(this, wxID_ANY); textCtrl_ = new wxTextCtrl(this, wxID_ANY);
dirSizer->Add(textCtrl_, 1, wxALL | wxEXPAND, gBorder); dirSizer->Add(textCtrl_, 1, wxALL | wxEXPAND, gBorder);
edRemoteId_ = new wxTextCtrl(this, wxID_ANY);
edRemoteId_->SetMinSize(wxSize(200, -1));
edRemoteId_->SetEditable(false);
dirSizer->Add(edRemoteId_, 0, wxALL | wxCENTER, gBorder);
btnHome_ = new wxButton(this, wxID_ANY, _("Home")); btnHome_ = new wxButton(this, wxID_ANY, _("Home"));
dirSizer->Add(btnHome_, 0, wxALL | wxCENTER, gBorder); dirSizer->Add(btnHome_, 0, wxALL | wxCENTER, gBorder);
@ -40,6 +49,66 @@ void RemoteControl::Init()
Layout(); Layout();
} }
void RemoteControl::BindEvent()
{
Bind(wxEVT_BUTTON, &RemoteControl::AskHome, this, btnHome_->GetId());
clientCore_->SetHomeCallback([this](const wxString& home) {
textCtrl_->SetValue(home);
logControl_->AddLog(_("Remote Home: %s"), home);
});
Bind(wxEVT_BUTTON, &RemoteControl::GetDirContent, this, btnGet_->GetId());
clientCore_->SetDirFileCallback([this](const DirFileInfoVec& dirInfoVec) {
if (grid_->GetNumberRows() > 0) {
grid_->DeleteRows(0, grid_->GetNumberRows());
}
for (auto& dirInfo : dirInfoVec.vec) {
grid_->AppendRows();
auto wxPath = wxString::FromUTF8(dirInfo.fullPath);
grid_->SetCellValue(grid_->GetNumberRows() - 1, 0, wxPath);
grid_->SetCellValue(grid_->GetNumberRows() - 1, 1, DirFileInfo::GetFileSize(dirInfo.size));
grid_->SetCellValue(grid_->GetNumberRows() - 1, 2, DirFileInfo::GetFileTypeName(dirInfo.type));
grid_->SetCellValue(grid_->GetNumberRows() - 1, 3, DirFileInfo::GetStrTime(dirInfo.lastModifyTime));
grid_->SetCellValue(grid_->GetNumberRows() - 1, 4, wxString::Format("%o", dirInfo.permission));
}
});
}
void RemoteControl::AskHome(wxCommandEvent& event)
{
auto remoteId = edRemoteId_->GetValue();
if (remoteId.empty()) {
logControl_->AddLog(_("Remote ID is Empty."));
return;
}
InfoCommunicate infoCommunicate;
if (!clientCore_->Send<InfoCommunicate>(infoCommunicate, FBT_CLI_ASK_HOME, remoteId)) {
logControl_->AddLog(_("Request ask %s's Home Failed"), remoteId);
} else {
logControl_->AddLog(_("Request ask %s's Home Success"), remoteId);
}
}
void RemoteControl::GetDirContent(wxCommandEvent& event)
{
auto remoteId = edRemoteId_->GetValue();
if (remoteId.empty()) {
logControl_->AddLog(_("Remote ID is Empty."));
return;
}
auto home = textCtrl_->GetValue();
if (home.empty()) {
logControl_->AddLog(_("Remote Home is Empty."));
return;
}
InfoCommunicate info;
info.data = home.ToStdString();
if (!clientCore_->Send<InfoCommunicate>(info, FBT_CLI_ASK_DIRFILE, remoteId)) {
logControl_->AddLog(_("Request get %s's DirFile Failed"), home);
} else {
logControl_->AddLog(_("Request get %s's DirFile Success"), home);
}
}
void RemoteControl::SetGrid() void RemoteControl::SetGrid()
{ {
grid_->CreateGrid(10, 5); grid_->CreateGrid(10, 5);
@ -55,3 +124,14 @@ void RemoteControl::SetGrid()
grid_->SetColSize(3, 150); grid_->SetColSize(3, 150);
grid_->SetColSize(4, 100); grid_->SetColSize(4, 100);
} }
void RemoteControl::setRemoteID(const wxString& id)
{
logControl_->AddLog(_("You Selected Remote ID: ") + id);
edRemoteId_->SetValue(id);
}
void RemoteControl::SetLogControl(LogControl* logControl)
{
logControl_ = logControl;
}

View File

@ -4,23 +4,41 @@
#include "InterfaceDefine.hpp" #include "InterfaceDefine.hpp"
#include <wx/grid.h> #include <wx/grid.h>
class LogControl;
class ClientCore;
class RemoteControl : public wxPanel class RemoteControl : public wxPanel
{ {
public: public:
RemoteControl(wxWindow* parent); RemoteControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore);
~RemoteControl() override; ~RemoteControl() override;
public:
void setRemoteID(const wxString& id);
public:
void SetLogControl(LogControl* logControl);
private: private:
void Init(); void Init();
void SetGrid(); void SetGrid();
void BindEvent();
private:
void AskHome(wxCommandEvent& event);
void GetDirContent(wxCommandEvent& event);
public: public:
wxGrid* grid_; wxGrid* grid_;
wxTextCtrl* textCtrl_; wxTextCtrl* textCtrl_;
wxTextCtrl* edRemoteId_;
wxButton* btnHome_; wxButton* btnHome_;
wxButton* btnGet_; wxButton* btnGet_;
wxButton* btnUpLevel_; wxButton* btnUpLevel_;
wxButton* btnRefresh_; wxButton* btnRefresh_;
private:
LogControl* logControl_;
std::shared_ptr<ClientCore> clientCore_;
}; };
#endif // REMOTECONTROL_H #endif // REMOTECONTROL_H